From 5dd9ead820615b64aa15f911e5fa41dae79f1aa6 Mon Sep 17 00:00:00 2001 From: Eduard Vlad Date: Thu, 22 May 2025 15:10:40 +0200 Subject: [PATCH 001/964] 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 002/964] 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 003/964] 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 004/964] 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 005/964] 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 006/964] 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 007/964] 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 008/964] 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 009/964] 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 010/964] 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 011/964] 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 012/964] 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 013/964] 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 014/964] 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 015/964] 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 016/964] 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 017/964] 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 018/964] 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 019/964] 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 020/964] 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 021/964] 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 022/964] 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 023/964] 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 024/964] 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 025/964] 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 026/964] 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 027/964] 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 028/964] 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 029/964] 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 030/964] 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 031/964] 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 6677277b6de4d5654969e9e0e9416be3ea577419 Mon Sep 17 00:00:00 2001 From: Reem Bahsoun Date: Tue, 17 Jun 2025 14:56:40 +0200 Subject: [PATCH 032/964] Update cuBB version to 25-1 --- ci-scripts/yaml_files/sa_gnb_aerial/docker-compose.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci-scripts/yaml_files/sa_gnb_aerial/docker-compose.yaml b/ci-scripts/yaml_files/sa_gnb_aerial/docker-compose.yaml index d5677ac239..ee57c430a8 100644 --- a/ci-scripts/yaml_files/sa_gnb_aerial/docker-compose.yaml +++ b/ci-scripts/yaml_files/sa_gnb_aerial/docker-compose.yaml @@ -23,7 +23,7 @@ services: - ../../../cmake_targets/share:/opt/cuBB/share userns_mode: host ipc: "shareable" - image: cubb-build:24-3 + image: cubb-build:25-1 environment: - cuBB_SDK=/opt/nvidia/cuBB command: bash -c "sudo rm -rf /tmp/phy.log && sudo chmod +x /opt/nvidia/cuBB/aerial_l1_entrypoint.sh && /opt/nvidia/cuBB/aerial_l1_entrypoint.sh" From a18a4888ec903aeb73e9dd34990a8c986851fab6 Mon Sep 17 00:00:00 2001 From: Reem Bahsoun Date: Tue, 17 Jun 2025 14:57:27 +0200 Subject: [PATCH 033/964] Change number of cores used for OAI gNB from 8 to 2 - After testing we found that we do not need 8 cores --- ci-scripts/yaml_files/sa_gnb_aerial/docker-compose.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci-scripts/yaml_files/sa_gnb_aerial/docker-compose.yaml b/ci-scripts/yaml_files/sa_gnb_aerial/docker-compose.yaml index ee57c430a8..d11a97c186 100644 --- a/ci-scripts/yaml_files/sa_gnb_aerial/docker-compose.yaml +++ b/ci-scripts/yaml_files/sa_gnb_aerial/docker-compose.yaml @@ -33,7 +33,7 @@ services: timeout: 5s retries: 5 oai-gnb-aerial: - cpuset: "13-20" + cpuset: "13-14" image: ${REGISTRY:-oaisoftwarealliance}/oai-gnb-aerial:${TAG:-develop} depends_on: nv-cubb: From 97d0b6534aff42e1ce4466523c29f1771553e885 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 16 Jun 2025 19:01:53 +0200 Subject: [PATCH 034/964] 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 035/964] 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 036/964] 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 037/964] 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) From a8f8244b09ad0949dbd66706091746882c1bd9bc Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Mon, 28 Apr 2025 17:37:08 +0200 Subject: [PATCH 038/964] Fix mutation of input iterators in seq_arr_erase_it The seq_arr_erase_it function was modifying start_it during the free_func loop, which led to incorrectly apply the free_func on the whole array. This commit makes sure the elements "freed" are only those in the range and not the whole seq_arr. * Fixes the logic by introducing a temporary iterator for the free loop, preserving start_it and end_it for correct offset calculations. * Adds a regression test in test_seq_arr to verify that only the selected subrange is erased and that free_func is called exactly on that range. --- common/utils/ds/seq_arr.c | 9 ++++----- common/utils/ds/tests/test_seq_array.c | 20 ++++++++++++++++++++ 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/common/utils/ds/seq_arr.c b/common/utils/ds/seq_arr.c index 708552a24e..50a332a16b 100644 --- a/common/utils/ds/seq_arr.c +++ b/common/utils/ds/seq_arr.c @@ -123,11 +123,10 @@ void seq_arr_erase_it(seq_arr_t* arr, void* start_it, void* end_it, void (*free_ return; if (free_func != NULL) { - void* start_it = seq_arr_front(arr); - void* end_it = seq_arr_end(arr); - while (start_it != end_it) { - free_func(start_it); - start_it = seq_arr_next(arr, start_it); + void* it = start_it; + while (it != end_it) { + free_func(it); + it = seq_arr_next(arr, it); } } diff --git a/common/utils/ds/tests/test_seq_array.c b/common/utils/ds/tests/test_seq_array.c index 28a7c98b1e..e06f72c881 100644 --- a/common/utils/ds/tests/test_seq_array.c +++ b/common/utils/ds/tests/test_seq_array.c @@ -36,6 +36,13 @@ static int compar(const void* m0, const void* m1) return 1; } +static int free_func_call_count = 0; + +static void dummy_free_func(void* it) +{ + ++free_func_call_count; +} + int main() { seq_arr_t arr = {0}; @@ -83,6 +90,19 @@ int main() void* it = bsearch(&key, base, nmemb, size, compar); assert(seq_arr_dist(&arr, seq_arr_front(&arr), it) == 4); + // Regression test: erase a partial range only + // Erase 92, 93, 94 (i.e., indices 1 to 3) + int* start = seq_arr_at(&arr, 1); + int* end = seq_arr_at(&arr, 4); + seq_arr_erase_it(&arr, start, end, dummy_free_func); + + // Now values should be: [91, 95, 96, 97, 98, 99] + assert(free_func_call_count == 3); + assert(seq_arr_size(&arr) == 6); + assert(*(int*)seq_arr_at(&arr, 0) == 91); + assert(*(int*)seq_arr_at(&arr, 1) == 95); + assert(*(int*)seq_arr_at(&arr, 5) == 99); + // Free data structure seq_arr_free(&arr, NULL); From 786fada6e659eb6c3dc0d476a996a403c1ef2d11 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Tue, 22 Apr 2025 17:34:06 +0200 Subject: [PATCH 039/964] Change pdusession_id_t type to int and remove redundant definition for an ID type --- common/platform_types.h | 1 - openair2/COMMON/gtpv1_u_messages_types.h | 8 ++++---- openair3/ocp-gtpu/gtp_itf.cpp | 3 ++- openair3/ocp-gtpu/gtp_itf.h | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/common/platform_types.h b/common/platform_types.h index 8cbd502fda..db692902df 100644 --- a/common/platform_types.h +++ b/common/platform_types.h @@ -226,7 +226,6 @@ typedef struct transport_layer_addr_s { //----------------------------------------------------------------------------- typedef uint32_t teid_t; // tunnel endpoint identifier typedef uint8_t ebi_t; // eps bearer id -typedef uint8_t pdusessionid_t; //----------------------------------------------------------------------------- // diff --git a/openair2/COMMON/gtpv1_u_messages_types.h b/openair2/COMMON/gtpv1_u_messages_types.h index 5f12d1e9a2..30471c9c4f 100644 --- a/openair2/COMMON/gtpv1_u_messages_types.h +++ b/openair2/COMMON/gtpv1_u_messages_types.h @@ -163,7 +163,7 @@ typedef struct gtpv1u_gnb_create_tunnel_req_s { int num_tunnels; teid_t outgoing_teid[NR_GTPV1U_MAX_BEARERS_PER_UE]; int outgoing_qfi[NR_GTPV1U_MAX_BEARERS_PER_UE]; - pdusessionid_t pdusession_id[NR_GTPV1U_MAX_BEARERS_PER_UE]; + int pdusession_id[NR_GTPV1U_MAX_BEARERS_PER_UE]; ebi_t incoming_rb_id[NR_GTPV1U_MAX_BEARERS_PER_UE]; transport_layer_addr_t dst_addr[NR_GTPV1U_MAX_BEARERS_PER_UE]; } gtpv1u_gnb_create_tunnel_req_t; @@ -173,13 +173,13 @@ typedef struct gtpv1u_gnb_create_tunnel_resp_s { ue_id_t ue_id; int num_tunnels; teid_t gnb_NGu_teid[NR_GTPV1U_MAX_BEARERS_PER_UE]; ///< Tunnel Endpoint Identifier - pdusessionid_t pdusession_id[NR_GTPV1U_MAX_BEARERS_PER_UE]; + int pdusession_id[NR_GTPV1U_MAX_BEARERS_PER_UE]; transport_layer_addr_t gnb_addr; } gtpv1u_gnb_create_tunnel_resp_t; typedef struct gtpv1u_gnb_delete_tunnel_req_s { ue_id_t ue_id; uint8_t num_pdusession; - pdusessionid_t pdusession_id[NR_GTPV1U_MAX_BEARERS_PER_UE]; + int pdusession_id[NR_GTPV1U_MAX_BEARERS_PER_UE]; } gtpv1u_gnb_delete_tunnel_req_t; typedef struct gtpv1u_gnb_delete_tunnel_resp_s { @@ -192,7 +192,7 @@ typedef struct gtpv1u_gnb_delete_tunnel_resp_s { typedef struct gtpv1u_DU_buffer_report_req_s { uint32_t buffer_availability; ue_id_t ue_id; - pdusessionid_t pdusession_id; + int pdusession_id; } gtpv1u_DU_buffer_report_req_t; #endif /* GTPV1_U_MESSAGES_TYPES_H_ */ diff --git a/openair3/ocp-gtpu/gtp_itf.cpp b/openair3/ocp-gtpu/gtp_itf.cpp index fd571e8d0e..58be5ed638 100644 --- a/openair3/ocp-gtpu/gtp_itf.cpp +++ b/openair3/ocp-gtpu/gtp_itf.cpp @@ -897,7 +897,8 @@ int gtpv1u_delete_all_s1u_tunnel(const instance_t instance, const rnti_t rnti) return newGtpuDeleteAllTunnels(instance, rnti); } -int newGtpuDeleteTunnels(instance_t instance, ue_id_t ue_id, int nbTunnels, pdusessionid_t *pdusession_id) { +int newGtpuDeleteTunnels(instance_t instance, ue_id_t ue_id, int nbTunnels, int *pdusession_id) +{ LOG_D(GTPU, "[%ld] Start delete tunnels for ue id %lu\n", instance, ue_id); pthread_mutex_lock(&globGtp.gtp_lock); diff --git a/openair3/ocp-gtpu/gtp_itf.h b/openair3/ocp-gtpu/gtp_itf.h index d5226bb972..7a8c4da627 100644 --- a/openair3/ocp-gtpu/gtp_itf.h +++ b/openair3/ocp-gtpu/gtp_itf.h @@ -103,7 +103,7 @@ extern "C" { int newGtpuDeleteOneTunnel(instance_t instance, ue_id_t ue_id, int rb_id); int newGtpuDeleteAllTunnels(instance_t instance, ue_id_t ue_id); - int newGtpuDeleteTunnels(instance_t instance, ue_id_t ue_id, int nbTunnels, pdusessionid_t *pdusession_id); + int newGtpuDeleteTunnels(instance_t instance, ue_id_t ue_id, int nbTunnels, int *pdusession_id); void gtpv1uSendDirect(instance_t instance, ue_id_t ue_id, int bearer_id, uint8_t *buf, size_t len, bool seqNumFlag, bool npduNumFlag); From 00b18f2990f8c969b1e4cb877b9ea4e26876eee7 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Tue, 13 May 2025 15:16:07 +0200 Subject: [PATCH 040/964] Cleanup unused and/or long time commented out code in RRC/NGAP * Remove drb_is_active: function is unused and the logic will be later added to another function to add DRBs if necessary * Remove unused NGAP structs and empty TODO functions * Remove unused pdusession_setup_req_t struct definition --- openair2/COMMON/ngap_messages_def.h | 3 - openair2/COMMON/ngap_messages_types.h | 91 ------------------------- openair2/RRC/NR/rrc_gNB_NGAP.c | 14 ---- openair2/RRC/NR/rrc_gNB_radio_bearers.c | 8 --- openair2/RRC/NR/rrc_gNB_radio_bearers.h | 3 - openair3/NGAP/ngap_gNB.c | 8 --- openair3/NGAP/ngap_gNB_nas_procedures.c | 14 ---- openair3/NGAP/ngap_gNB_nas_procedures.h | 6 -- 8 files changed, 147 deletions(-) diff --git a/openair2/COMMON/ngap_messages_def.h b/openair2/COMMON/ngap_messages_def.h index 62498698f2..4f05a564c4 100644 --- a/openair2/COMMON/ngap_messages_def.h +++ b/openair2/COMMON/ngap_messages_def.h @@ -71,9 +71,6 @@ MESSAGE_DEF(NGAP_UE_CTXT_MODIFICATION_FAIL , MESSAGE_PRIORITY_MED, ngap_ue_ctxt_ MESSAGE_DEF(NGAP_PDUSESSION_SETUP_RESP , MESSAGE_PRIORITY_MED, ngap_pdusession_setup_resp_t , ngap_pdusession_setup_resp) MESSAGE_DEF(NGAP_PDUSESSION_MODIFY_RESP , MESSAGE_PRIORITY_MED, ngap_pdusession_modify_resp_t , ngap_pdusession_modify_resp) MESSAGE_DEF(NGAP_PDUSESSION_RELEASE_RESPONSE , MESSAGE_PRIORITY_MED, ngap_pdusession_release_resp_t , ngap_pdusession_release_resp) -MESSAGE_DEF(NGAP_PATH_SWITCH_REQ , MESSAGE_PRIORITY_MED, ngap_path_switch_req_t , ngap_path_switch_req) -MESSAGE_DEF(NGAP_PATH_SWITCH_REQ_ACK , MESSAGE_PRIORITY_MED, ngap_path_switch_req_ack_t , ngap_path_switch_req_ack) -MESSAGE_DEF(NGAP_PDUSESSION_MODIFICATION_IND , MESSAGE_PRIORITY_MED, ngap_pdusession_modification_ind_t , ngap_pdusession_modification_ind) /* NGAP -> RRC messages */ MESSAGE_DEF(NGAP_DOWNLINK_NAS , MESSAGE_PRIORITY_MED, ngap_downlink_nas_t , ngap_downlink_nas ) diff --git a/openair2/COMMON/ngap_messages_types.h b/openair2/COMMON/ngap_messages_types.h index b899bb33e2..c2ba04d53a 100644 --- a/openair2/COMMON/ngap_messages_types.h +++ b/openair2/COMMON/ngap_messages_types.h @@ -290,18 +290,6 @@ typedef struct pdusession_setup_s { pdusession_associate_qosflow_t associated_qos_flows[QOSFLOW_MAX_VALUE]; } pdusession_setup_t; -typedef struct pdusession_tobeswitched_s { - /* Unique pdusession_id for the UE. */ - uint8_t pdusession_id; - - /* The transport layer address for the IP packets */ - uint8_t pdu_session_type; - transport_layer_addr_t upf_addr; - - /* S-GW Tunnel endpoint identifier */ - uint32_t gtp_teid; -} pdusession_tobeswitched_t; - typedef struct qos_flow_tobe_modified_s { uint8_t qfi; // 0~63 } qos_flow_tobe_modified_t; @@ -640,13 +628,6 @@ typedef struct ngap_paging_ind_s { ngap_paging_priority_t paging_priority; } ngap_paging_ind_t; -typedef struct { - /* Unique pdusession_id for the UE. */ - int pdusession_id; - byte_array_t nas_pdu; - byte_array_t pdusessionTransfer; -} pdusession_setup_req_t; - typedef struct ngap_pdusession_setup_req_s { /* UE id for initial connection to NGAP */ uint32_t gNB_ue_ngap_id; @@ -682,78 +663,6 @@ typedef struct ngap_pdusession_setup_resp_s { pdusession_failed_t pdusessions_failed[NGAP_MAX_PDU_SESSION]; } ngap_pdusession_setup_resp_t; -typedef struct ngap_path_switch_req_s { - uint32_t gNB_ue_ngap_id; - - /* Number of pdusession setup-ed in the list */ - uint8_t nb_of_pdusessions; - - /* list of pdusession setup-ed by RRC layers */ - pdusession_setup_t pdusessions_tobeswitched[NGAP_MAX_PDU_SESSION]; - - /* AMF UE id */ - uint64_t amf_ue_ngap_id; - - nr_guami_t ue_guami; - - uint16_t ue_initial_id; - /* Security algorithms */ - ngap_security_capabilities_t security_capabilities; - -} ngap_path_switch_req_t; - -typedef struct ngap_path_switch_req_ack_s { - - /* UE id for initial connection to NGAP */ - uint16_t ue_initial_id; - - uint32_t gNB_ue_ngap_id; - - /* AMF UE id */ - uint64_t amf_ue_ngap_id; - - /* UE aggregate maximum bitrate */ - ngap_ambr_t ue_ambr; - - /* Number of pdusession setup-ed in the list */ - uint8_t nb_pdusessions_tobeswitched; - - /* list of pdusession to be switched by RRC layers */ - pdusession_tobeswitched_t pdusessions_tobeswitched[NGAP_MAX_PDU_SESSION]; - - /* Number of pdusessions to be released by RRC */ - uint8_t nb_pdusessions_tobereleased; - - /* list of pdusessions to be released */ - pdusession_failed_t pdusessions_tobereleased[NGAP_MAX_PDU_SESSION]; - - /* Security key */ - int next_hop_chain_count; - uint8_t next_security_key[SECURITY_KEY_LENGTH]; - -} ngap_path_switch_req_ack_t; - -typedef struct ngap_pdusession_modification_ind_s { - - uint32_t gNB_ue_ngap_id; - - /* AMF UE id */ - uint64_t amf_ue_ngap_id; - - /* Number of pdusession setup-ed in the list */ - uint8_t nb_of_pdusessions_tobemodified; - - uint8_t nb_of_pdusessions_nottobemodified; - - /* list of pdusession setup-ed by RRC layers */ - pdusession_setup_t pdusessions_tobemodified[NGAP_MAX_PDU_SESSION]; - - pdusession_setup_t pdusessions_nottobemodified[NGAP_MAX_PDU_SESSION]; - - uint16_t ue_initial_id; - -} ngap_pdusession_modification_ind_t; - // NGAP --> RRC messages typedef struct ngap_ue_release_command_s { diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index 9fd4306962..7b0261832c 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -807,10 +807,6 @@ void rrc_gNB_send_NGAP_PDUSESSION_SETUP_RESP(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE } resp->nb_of_pdusessions = pdu_sessions_done; resp->nb_of_pdusessions_failed = pdu_sessions_failed; - // } else { - // LOG_D(NR_RRC,"xid does not corresponds (context pdu_sessions index %d, status %d, xid %d/%d) \n ", - // pdusession, UE->pdusession[pdusession].status, xid, UE->pdusession[pdusession].xid); - // } } if ((pdu_sessions_done > 0 || pdu_sessions_failed)) { @@ -1457,16 +1453,6 @@ int rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND(MessageDef *msg_p, instance_ return 0; } -void nr_rrc_rx_tx(void) { - // check timers - - // check if UEs are lost, to remove them from upper layers - - // - -} - -/*------------------------------------------------------------------------------*/ int rrc_gNB_process_PAGING_IND(MessageDef *msg_p, instance_t instance) { for (uint16_t tai_size = 0; tai_size < NGAP_PAGING_IND(msg_p).tai_size; tai_size++) { diff --git a/openair2/RRC/NR/rrc_gNB_radio_bearers.c b/openair2/RRC/NR/rrc_gNB_radio_bearers.c index e22ee7ffd6..fa504b9dc4 100644 --- a/openair2/RRC/NR/rrc_gNB_radio_bearers.c +++ b/openair2/RRC/NR/rrc_gNB_radio_bearers.c @@ -208,11 +208,3 @@ int get_number_active_drbs(gNB_RRC_UE_t *ue) n++; return n; } - -bool drb_is_active(gNB_RRC_UE_t *ue, uint8_t drb_id) -{ - drb_t *drb = get_drb(ue, drb_id); - if (drb == NULL) - return DRB_INACTIVE; - return drb->status != DRB_INACTIVE; -} diff --git a/openair2/RRC/NR/rrc_gNB_radio_bearers.h b/openair2/RRC/NR/rrc_gNB_radio_bearers.h index 4a249496ff..248b6f8082 100644 --- a/openair2/RRC/NR/rrc_gNB_radio_bearers.h +++ b/openair2/RRC/NR/rrc_gNB_radio_bearers.h @@ -65,9 +65,6 @@ uint8_t get_next_available_drb_id(gNB_RRC_UE_t *ue); /// @brief returns the number of active DRBs for this UE int get_number_active_drbs(gNB_RRC_UE_t *ue); -/// @brief check if DRB with ID drb_id of UE ue is active -bool drb_is_active(gNB_RRC_UE_t *ue, uint8_t drb_id); - /// @brief retrieve PDU session of UE ue with ID id, optionally creating it if /// create is true rrc_pdu_session_param_t *find_pduSession(gNB_RRC_UE_t *ue, int id, bool create); diff --git a/openair3/NGAP/ngap_gNB.c b/openair3/NGAP/ngap_gNB.c index ae8d806e18..8edb5c3aa3 100644 --- a/openair3/NGAP/ngap_gNB.c +++ b/openair3/NGAP/ngap_gNB.c @@ -344,14 +344,6 @@ void *ngap_gNB_process_itti_msg(void *notUsed) { ngap_gNB_nas_non_delivery_ind(instance, &NGAP_NAS_NON_DELIVERY_IND(received_msg)); break; - case NGAP_PATH_SWITCH_REQ: - ngap_gNB_path_switch_req(instance, &NGAP_PATH_SWITCH_REQ(received_msg)); - break; - - case NGAP_PDUSESSION_MODIFICATION_IND: - ngap_gNB_generate_PDUSESSION_Modification_Indication(instance, &NGAP_PDUSESSION_MODIFICATION_IND(received_msg)); - break; - case NGAP_UE_CONTEXT_RELEASE_COMPLETE: ngap_ue_context_release_complete(instance, &NGAP_UE_CONTEXT_RELEASE_COMPLETE(received_msg)); break; diff --git a/openair3/NGAP/ngap_gNB_nas_procedures.c b/openair3/NGAP/ngap_gNB_nas_procedures.c index b00ce13f32..5ae65f1c42 100644 --- a/openair3/NGAP/ngap_gNB_nas_procedures.c +++ b/openair3/NGAP/ngap_gNB_nas_procedures.c @@ -1225,17 +1225,3 @@ int ngap_gNB_pdusession_release_resp(instance_t instance, ngap_pdusession_releas return 0; } -int ngap_gNB_path_switch_req(instance_t instance, ngap_path_switch_req_t *path_switch_req_p) -//------------------------------------------------------------------------------ -{ - //TODO - - return 0; -} - -int ngap_gNB_generate_PDUSESSION_Modification_Indication(instance_t instance, ngap_pdusession_modification_ind_t *pdusession_modification_ind) -//----------------------------------------------------------------------------- -{ - //TODO - return 0; -} diff --git a/openair3/NGAP/ngap_gNB_nas_procedures.h b/openair3/NGAP/ngap_gNB_nas_procedures.h index 3cd03838b4..5189e6b311 100644 --- a/openair3/NGAP/ngap_gNB_nas_procedures.h +++ b/openair3/NGAP/ngap_gNB_nas_procedures.h @@ -63,10 +63,4 @@ int ngap_gNB_pdusession_modify_resp(instance_t instance, int ngap_gNB_pdusession_release_resp(instance_t instance, ngap_pdusession_release_resp_t *pdusession_release_resp_p); -int ngap_gNB_path_switch_req(instance_t instance, - ngap_path_switch_req_t *path_switch_req_p); - -int ngap_gNB_generate_PDUSESSION_Modification_Indication( - instance_t instance, ngap_pdusession_modification_ind_t *pdusession_modification_ind); - #endif /* NGAP_GNB_NAS_PROCEDURES_H_ */ From 78feea10bb1022fb70fa13d5550a456c1979d2aa Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Tue, 22 Apr 2025 15:44:06 +0200 Subject: [PATCH 041/964] Add function to deep copy pdusession_t struct --- openair2/RRC/NR/rrc_gNB_radio_bearers.c | 9 +++++++++ openair2/RRC/NR/rrc_gNB_radio_bearers.h | 3 +++ 2 files changed, 12 insertions(+) diff --git a/openair2/RRC/NR/rrc_gNB_radio_bearers.c b/openair2/RRC/NR/rrc_gNB_radio_bearers.c index fa504b9dc4..7bed45ee64 100644 --- a/openair2/RRC/NR/rrc_gNB_radio_bearers.c +++ b/openair2/RRC/NR/rrc_gNB_radio_bearers.c @@ -32,6 +32,15 @@ #include "oai_asn1.h" #include "openair2/LAYER2/nr_pdcp/nr_pdcp_asn1_utils.h" +/** @brief Deep copy pdusession_t */ +void cp_pdusession(pdusession_t *dst, const pdusession_t *src) +{ + // Shallow copy + *dst = *src; + // nas_pdu + dst->nas_pdu = copy_byte_array(src->nas_pdu); +} + rrc_pdu_session_param_t *find_pduSession(gNB_RRC_UE_t *ue, int id, bool create) { int j; diff --git a/openair2/RRC/NR/rrc_gNB_radio_bearers.h b/openair2/RRC/NR/rrc_gNB_radio_bearers.h index 248b6f8082..1eac60a609 100644 --- a/openair2/RRC/NR/rrc_gNB_radio_bearers.h +++ b/openair2/RRC/NR/rrc_gNB_radio_bearers.h @@ -78,4 +78,7 @@ void get_pduSession_array(gNB_RRC_UE_t *ue, uint32_t pdu_sessions[NGAP_MAX_PDU_S /// @brief set PDCP configuration in a bearer context management message void set_bearer_context_pdcp_config(bearer_context_pdcp_config_t *pdcp_config, drb_t *rrc_drb, bool um_on_default_drb); +/// @brief Deep copy an instance of struct pdusession_t +void cp_pdusession(pdusession_t *dst, const pdusession_t *src); + #endif From 93936ffd9b189d973d5c3caf35d1e0237bbe5f6f Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Tue, 13 May 2025 21:31:43 +0200 Subject: [PATCH 042/964] Fix comment in transport_layer_addr_t --- common/platform_types.h | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/common/platform_types.h b/common/platform_types.h index db692902df..8a8868226a 100644 --- a/common/platform_types.h +++ b/common/platform_types.h @@ -208,14 +208,9 @@ typedef struct nsa_msg_t { } nsa_msg_t; typedef struct transport_layer_addr_s { - /** - * Transport Layer Address as a bitstring: - * - 32 bits for IPv4 (RFC 791), - * - 128 bits for IPv6 (RFC 2460), - * - 160 bits for both IPv4 and IPv6, with IPv4 in the first 32 bits. - * The S1AP/NGAP layer forwards this address (bitstring<1..160>) - * to S1-U/NG-U without interpreting it. - */ + /** Transport Layer Address in bytes: + * - 4 bytes for IPv4 (RFC 791), 16 bytes for IPv6 (RFC 2460), + * - 20 bytes for both IPv4 and IPv6, with IPv4 in the first 4 bytes. */ uint8_t length; /// Buffer: address in network byte order uint8_t buffer[20]; From 32e5f972e95368b7d6f96c6e06ff5ac9ad38382d Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Tue, 13 May 2025 21:57:25 +0200 Subject: [PATCH 043/964] Refactor f1u_tunnel_t into gtpu_tunnel_t This struct is used in different layers, e.g. RRC, NGAP: therefore it has been moved to platform_types.h. Also, the struct holds the tunnel endpoint configuration for any GTP-U tunnel, therefore the f1u prefix is not accurate and was updated to a more generic gtpu. --- common/platform_types.h | 8 ++++++++ openair2/RRC/NR/nr_rrc_defs.h | 14 ++------------ openair2/RRC/NR/rrc_gNB.c | 4 ++-- 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/common/platform_types.h b/common/platform_types.h index 8a8868226a..b31474d475 100644 --- a/common/platform_types.h +++ b/common/platform_types.h @@ -216,6 +216,14 @@ typedef struct transport_layer_addr_s { uint8_t buffer[20]; } transport_layer_addr_t; +/** @brief GTP tunnel configuration */ +typedef struct { + // Tunnel endpoint identifier + uint32_t teid; + // Transport layer address + transport_layer_addr_t addr; +} gtpu_tunnel_t; + //----------------------------------------------------------------------------- // GTPV1U TYPES //----------------------------------------------------------------------------- diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index f2434eceaf..9998562b61 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -106,16 +106,6 @@ typedef struct pdu_session_param_s { ngap_cause_t cause; } rrc_pdu_session_param_t; -/** - * @brief F1-U tunnel configuration -*/ -typedef struct f1u_tunnel_s { - /* F1-U Tunnel Endpoint Identifier (on DU side) */ - uint32_t teid; - /* Downlink F1-U Transport Layer (on DU side) */ - transport_layer_addr_t addr; -} f1u_tunnel_t; - typedef struct drb_s { int status; int drb_id; @@ -145,9 +135,9 @@ typedef struct drb_s { } ext1; } pdcp_config; // F1-U Downlink Tunnel Config (on DU side) - f1u_tunnel_t du_tunnel_config; + gtpu_tunnel_t du_tunnel_config; // F1-U Uplink Tunnel Config (on CU-UP side) - f1u_tunnel_t cuup_tunnel_config; + gtpu_tunnel_t cuup_tunnel_config; } drb_t; typedef enum { diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index f69e03b810..f47700ae9a 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -2007,7 +2007,7 @@ static void fill_e1_bearer_modif(DRB_nGRAN_to_mod_t *drb_e1, const f1ap_drb_to_b /** * @brief Store F1-U DL TL and TEID in RRC */ -static void f1u_dl_gtp_update(f1u_tunnel_t *f1u, const f1ap_up_tnl_t *p) +static void f1u_dl_gtp_update(gtpu_tunnel_t *f1u, const f1ap_up_tnl_t *p) { f1u->teid = p->teid; memcpy(&f1u->addr.buffer, &p->tl_address, sizeof(uint8_t) * 4); @@ -2031,7 +2031,7 @@ static void store_du_f1u_tunnel(const f1ap_drb_to_be_setup_t *drbs, int n, gNB_R /* * @brief Store F1-U UL TEID and address in RRC */ -static void f1u_ul_gtp_update(f1u_tunnel_t *f1u, const up_params_t *p) +static void f1u_ul_gtp_update(gtpu_tunnel_t *f1u, const up_params_t *p) { f1u->teid = p->tl_info.teId; memcpy(&f1u->addr.buffer, &p->tl_info.tlAddress, sizeof(uint8_t) * 4); From b86ae96c66933d0415501b6f0805aed01c8f4667 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Tue, 13 May 2025 22:54:00 +0200 Subject: [PATCH 044/964] Merge f1u_dl_gtp_update and f1u_ul_gtp_update in f1u_gtp_update * The 2 functions do the same thing, the only difference is the direction (DL/UL) --- openair2/RRC/NR/rrc_gNB.c | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index f47700ae9a..d71be33fcb 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -2004,14 +2004,13 @@ static void fill_e1_bearer_modif(DRB_nGRAN_to_mod_t *drb_e1, const f1ap_drb_to_b drb_e1->DlUpParamList[0].tl_info.teId = drb_f1->up_dl_tnl[0].teid; } -/** - * @brief Store F1-U DL TL and TEID in RRC -*/ -static void f1u_dl_gtp_update(gtpu_tunnel_t *f1u, const f1ap_up_tnl_t *p) +static gtpu_tunnel_t f1u_gtp_update(uint32_t teid, const in_addr_t addr) { - f1u->teid = p->teid; - memcpy(&f1u->addr.buffer, &p->tl_address, sizeof(uint8_t) * 4); - f1u->addr.length = sizeof(in_addr_t); + gtpu_tunnel_t out = {0}; + out.teid = teid; + memcpy(&out.addr.buffer, &addr, 4); + out.addr.length = sizeof(addr); + return out; } /** @@ -2024,20 +2023,10 @@ static void store_du_f1u_tunnel(const f1ap_drb_to_be_setup_t *drbs, int n, gNB_R AssertFatal(drb_f1->up_dl_tnl_length == 1, "can handle only one UP param\n"); AssertFatal(drb_f1->drb_id < MAX_DRBS_PER_UE, "illegal DRB ID %ld\n", drb_f1->drb_id); drb_t *drb = get_drb(ue, drb_f1->drb_id); - f1u_dl_gtp_update(&drb->du_tunnel_config, &drb_f1->up_dl_tnl[0]); + drb->du_tunnel_config = f1u_gtp_update(drb_f1->up_dl_tnl[0].teid, drb_f1->up_dl_tnl[0].tl_address); } } -/* - * @brief Store F1-U UL TEID and address in RRC - */ -static void f1u_ul_gtp_update(gtpu_tunnel_t *f1u, const up_params_t *p) -{ - f1u->teid = p->tl_info.teId; - memcpy(&f1u->addr.buffer, &p->tl_info.tlAddress, sizeof(uint8_t) * 4); - f1u->addr.length = sizeof(in_addr_t); -} - /* \brief use list of DRBs and send the corresponding bearer update message via * E1 to the CU of this UE. Also updates TEID info internally */ static void e1_send_bearer_updates(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, f1ap_drb_to_be_setup_t *drbs) @@ -2470,7 +2459,8 @@ void rrc_gNB_process_e1_bearer_context_setup_resp(e1ap_bearer_setup_resp_t *resp // numUpParam only relevant in F1, but not monolithic AssertFatal(drb_config->numUpParam <= 1, "can only up to one UP param\n"); drb_t *drb = get_drb(UE, drb_config->id); - f1u_ul_gtp_update(&drb->cuup_tunnel_config, &drb_config->UpParamList[0]); + UP_TL_information_t *tl_info = &drb_config->UpParamList[0].tl_info; + drb->cuup_tunnel_config = f1u_gtp_update(tl_info->teId, tl_info->tlAddress); } } From 4ec498c9960b0b3d2213b91893b913c3fbbf694d Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 4 Jun 2025 15:17:29 +0200 Subject: [PATCH 045/964] Refactor tunnel endpoint struct members in pdu_session_t Motivation: Clarify the role of GTP tunnel endpoint IDs in PDU session handling. Previously, the struct members (gNB_teid_N3, UPF_teid_N3, etc.) were confusingly named and duplicated with separate transport-layer address fields. This refactoring replaces these with explicit n3_incoming and n3_outgoing members using gtpu_tunnel_t. This aligns with GTP conventions: "incoming TEID" refers to the TEID received from the remote peer (UPF on N3), while "outgoing TEID" is the TEID sent by the local entity (NG-RAN on N3) to the remote peer. Benefits: * Improves readability and clarity of the code * Reduces redundant struct members, i.e. remove UPF_teid_N3, UPF_addr_N3 * Aligns naming with 3GPP conventions for transport layer tunnels Changes: * Replace gtp_addr_N3, gNB_teid_N3, gtp_teid, upf_addr with n3_incoming and n3_outgoing * Update all related code to use the new struct members * Aligns naming with 3GPP conventions for transport layer tunnels --- openair2/COMMON/ngap_messages_types.h | 13 ++++------- .../RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.c | 4 ++-- openair2/RRC/NR/rrc_gNB.c | 6 ++--- openair2/RRC/NR/rrc_gNB_NGAP.c | 23 ++++++++----------- 4 files changed, 19 insertions(+), 27 deletions(-) diff --git a/openair2/COMMON/ngap_messages_types.h b/openair2/COMMON/ngap_messages_types.h index c2ba04d53a..e30c0bab79 100644 --- a/openair2/COMMON/ngap_messages_types.h +++ b/openair2/COMMON/ngap_messages_types.h @@ -249,15 +249,10 @@ typedef struct pdusession_s { pdusession_level_qos_parameter_t qos[QOSFLOW_MAX_VALUE]; /* The transport layer address for the IP packets */ pdu_session_type_t pdu_session_type; - transport_layer_addr_t upf_addr; - /* Outgoing (UL) NG-U Tunnel Endpoint Identifier (S-GW/UPF) */ - uint32_t gtp_teid; - /* Incoming (DL) NG-U Tunnel Endpoint Identifier (S-GW/UPF) */ - uint32_t gNB_teid_N3; - transport_layer_addr_t gNB_addr_N3; - /* Incoming (DL) NG-U Tunnel Endpoint Identifier (S-GW/UPF) */ - uint32_t UPF_teid_N3; - transport_layer_addr_t UPF_addr_N3; + // NG-RAN endpoint of the NG-U (N3) transport bearer + gtpu_tunnel_t n3_outgoing; + // UPF endpoint of the NG-U (N3) transport bearer + gtpu_tunnel_t n3_incoming; nssai_t nssai; } pdusession_t; diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.c b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.c index 31d96433c1..158c126c39 100644 --- a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.c +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.c @@ -65,8 +65,8 @@ bool read_gtp_sm(void * data) int nb_pdu_session = ue_context_p->ue_context.nb_of_pdusessions; if (nb_pdu_session > 0) { int nb_pdu_idx = nb_pdu_session - 1; - gtp->msg.ngut[i].teidgnb = ue_context_p->ue_context.pduSession[nb_pdu_idx].param.gNB_teid_N3; - gtp->msg.ngut[i].teidupf = ue_context_p->ue_context.pduSession[nb_pdu_idx].param.UPF_teid_N3; + gtp->msg.ngut[i].teidgnb = ue_context_p->ue_context.pduSession[nb_pdu_idx].param.n3_outgoing.teid; + gtp->msg.ngut[i].teidupf = ue_context_p->ue_context.pduSession[nb_pdu_idx].param.n3_incoming.teid; // TODO: one PDU session has multiple QoS Flow int nb_qos_flow = ue_context_p->ue_context.pduSession[nb_pdu_idx].param.nb_qos; if (nb_qos_flow > 0) { diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index d71be33fcb..cda981ee34 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -2449,9 +2449,9 @@ void rrc_gNB_process_e1_bearer_context_setup_resp(e1ap_bearer_setup_resp_t *resp LOG_W(RRC, "E1: received setup for PDU session %ld, but has not been requested\n", e1_pdu->id); continue; } - rrc_pdu->param.gNB_teid_N3 = e1_pdu->tl_info.teId; - memcpy(&rrc_pdu->param.gNB_addr_N3.buffer, &e1_pdu->tl_info.tlAddress, sizeof(uint8_t) * 4); - rrc_pdu->param.gNB_addr_N3.length = sizeof(in_addr_t); + rrc_pdu->param.n3_outgoing.teid = e1_pdu->tl_info.teId; + memcpy(&rrc_pdu->param.n3_outgoing.addr.buffer, &e1_pdu->tl_info.tlAddress, sizeof(uint8_t) * 4); + rrc_pdu->param.n3_outgoing.addr.length = sizeof(in_addr_t); // save the tunnel address for the DRBs for (int i = 0; i < e1_pdu->numDRBSetup; i++) { diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index 7b0261832c..e1e5e046d9 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -283,12 +283,11 @@ static int decodePDUSessionResourceSetup(pdusession_t *session) NGAP_GTPTunnel_t *gTPTunnel_p = pdusessionTransfer_ies->value.choice.UPTransportLayerInformation.choice.gTPTunnel; /* Set the transport layer address */ - memcpy(session->upf_addr.buffer, gTPTunnel_p->transportLayerAddress.buf, gTPTunnel_p->transportLayerAddress.size); - - session->upf_addr.length = gTPTunnel_p->transportLayerAddress.size * 8 - gTPTunnel_p->transportLayerAddress.bits_unused; + memcpy(session->n3_incoming.addr.buffer, gTPTunnel_p->transportLayerAddress.buf, gTPTunnel_p->transportLayerAddress.size); + session->n3_incoming.addr.length = gTPTunnel_p->transportLayerAddress.size * 8 - gTPTunnel_p->transportLayerAddress.bits_unused; /* GTP tunnel endpoint ID */ - OCTET_STRING_TO_INT32(&gTPTunnel_p->gTP_TEID, session->gtp_teid); + OCTET_STRING_TO_INT32(&gTPTunnel_p->gTP_TEID, session->n3_incoming.teid); } break; @@ -386,8 +385,8 @@ bool trigger_bearer_setup(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, pdusession : SECURITY_NOT_NEEDED; sec->confidentialityProtectionIndication = rrc->security.do_drb_ciphering ? SECURITY_REQUIRED : SECURITY_NOT_NEEDED; - pdu->UP_TL_information.teId = session->gtp_teid; - memcpy(&pdu->UP_TL_information.tlAddress, session->upf_addr.buffer, sizeof(in_addr_t)); + pdu->UP_TL_information.teId = session->n3_incoming.teid; + memcpy(&pdu->UP_TL_information.tlAddress, session->n3_incoming.addr.buffer, sizeof(in_addr_t)); /* we assume for the moment one DRB per PDU session. Activate the bearer, * and configure in RRC. */ @@ -582,9 +581,9 @@ void rrc_gNB_send_NGAP_INITIAL_CONTEXT_SETUP_RESP(gNB_RRC_INST *rrc, gNB_RRC_UE_ if (session->status == PDU_SESSION_STATUS_DONE) { pdu_sessions_done++; resp->pdusessions[pdusession].pdusession_id = session->param.pdusession_id; - resp->pdusessions[pdusession].gtp_teid = session->param.gNB_teid_N3; + resp->pdusessions[pdusession].gtp_teid = session->param.n3_outgoing.teid; memcpy(resp->pdusessions[pdusession].gNB_addr.buffer, - session->param.gNB_addr_N3.buffer, + session->param.n3_outgoing.addr.buffer, sizeof(resp->pdusessions[pdusession].gNB_addr.buffer)); resp->pdusessions[pdusession].gNB_addr.length = 4; // Fixme: IPv4 hard coded here resp->pdusessions[pdusession].nb_of_qos_flow = session->param.nb_qos; @@ -777,10 +776,10 @@ void rrc_gNB_send_NGAP_PDUSESSION_SETUP_RESP(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE pdusession_setup_t *tmp = &resp->pdusessions[pdu_sessions_done]; tmp->pdusession_id = session->param.pdusession_id; tmp->nb_of_qos_flow = session->param.nb_qos; - tmp->gtp_teid = session->param.gNB_teid_N3; + tmp->gtp_teid = session->param.n3_outgoing.teid; tmp->pdu_session_type = session->param.pdu_session_type; - tmp->gNB_addr.length = session->param.gNB_addr_N3.length; - memcpy(tmp->gNB_addr.buffer, session->param.gNB_addr_N3.buffer, tmp->gNB_addr.length); + tmp->gNB_addr.length = session->param.n3_outgoing.addr.length; + memcpy(tmp->gNB_addr.buffer, session->param.n3_outgoing.addr.buffer, tmp->gNB_addr.length); for (int qos_flow_index = 0; qos_flow_index < tmp->nb_of_qos_flow; qos_flow_index++) { tmp->associated_qos_flows[qos_flow_index].qfi = session->param.qos[qos_flow_index].qfi; tmp->associated_qos_flows[qos_flow_index].qos_flow_mapping_ind = QOSFLOW_MAPPING_INDICATION_DL; @@ -1091,8 +1090,6 @@ int rrc_gNB_process_NGAP_PDUSESSION_MODIFY_REQ(MessageDef *msg_p, instance_t ins } // Save new pdu session parameters, qos, upf addr, teid decodePDUSessionResourceModify(&sess->param, UE->pduSession[i].param.pdusessionTransfer); - sess->param.UPF_addr_N3 = sessMod->upf_addr; - sess->param.UPF_teid_N3 = sessMod->gtp_teid; } } From a36de80e6f35f68c9b3f55bd29055aade59cc55e Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 4 Jun 2025 15:44:13 +0200 Subject: [PATCH 046/964] Simplify pdu session structs members naming to pdusession Rename the struct members: `pdusession_param` to `pdusession` in NGAP Initial Context Setup Request `pdusession_setup_params` in `ngap_pdusession_setup_req_t` `pdusession_modify_params` and `ngap_pdusession_modify_req_t` --- openair2/COMMON/ngap_messages_types.h | 6 +++--- openair2/RRC/NR/rrc_gNB_NGAP.c | 14 ++++++-------- openair3/NGAP/ngap_gNB_handlers.c | 22 +++++++++++----------- 3 files changed, 20 insertions(+), 22 deletions(-) diff --git a/openair2/COMMON/ngap_messages_types.h b/openair2/COMMON/ngap_messages_types.h index e30c0bab79..6bd2ed5a5f 100644 --- a/openair2/COMMON/ngap_messages_types.h +++ b/openair2/COMMON/ngap_messages_types.h @@ -589,7 +589,7 @@ typedef struct ngap_initial_context_setup_req_s { /* Number of pdusession to be setup in the list */ uint8_t nb_of_pdusessions; /* list of pdusession to be setup by RRC layers */ - pdusession_t pdusession_param[NGAP_MAX_PDU_SESSION]; + pdusession_t pdusession[NGAP_MAX_PDU_SESSION]; /* Mobility Restriction List */ uint8_t mobility_restriction_flag; @@ -638,7 +638,7 @@ typedef struct ngap_pdusession_setup_req_s { uint8_t nb_pdusessions_tosetup; /* E RAB setup request */ - pdusession_t pdusession_setup_params[NGAP_MAX_PDU_SESSION]; + pdusession_t pdusession[NGAP_MAX_PDU_SESSION]; /* UE Aggregated Max Bitrates */ ngap_ambr_t ueAggMaxBitRate; @@ -694,7 +694,7 @@ typedef struct ngap_pdusession_modify_req_s { uint8_t nb_pdusessions_tomodify; /* pdu session modify request */ - pdusession_t pdusession_modify_params[NGAP_MAX_PDU_SESSION]; + pdusession_t pdusession[NGAP_MAX_PDU_SESSION]; } ngap_pdusession_modify_req_t; typedef struct ngap_pdusession_modify_resp_s { diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index e1e5e046d9..42fe17fec9 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -479,7 +479,7 @@ static void send_ngap_initial_context_setup_resp_fail(instance_t instance, resp->gNB_ue_ngap_id = msg->gNB_ue_ngap_id; for (int i = 0; i < msg->nb_of_pdusessions; i++) { - fill_pdu_session_resource_failed_to_setup_item(&resp->pdusessions_failed[i], msg->pdusession_param[i].pdusession_id, cause); + fill_pdu_session_resource_failed_to_setup_item(&resp->pdusessions_failed[i], msg->pdusession[i].pdusession_id, cause); } resp->nb_of_pdusessions = 0; resp->nb_of_pdusessions_failed = msg->nb_of_pdusessions; @@ -521,7 +521,7 @@ int rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, instance_t UE->initial_pdus = calloc(UE->n_initial_pdu, sizeof(*UE->initial_pdus)); AssertFatal(UE->initial_pdus != NULL, "out of memory\n"); for (int i = 0; i < UE->n_initial_pdu; ++i) - UE->initial_pdus[i] = req->pdusession_param[i]; + UE->initial_pdus[i] = req->pdusession[i]; } /* security */ @@ -855,9 +855,7 @@ static void send_ngap_pdu_session_setup_resp_fail(instance_t instance, ngap_pdus resp->nb_of_pdusessions_failed = msg->nb_pdusessions_tosetup; resp->nb_of_pdusessions = 0; for (int i = 0; i < resp->nb_of_pdusessions_failed; ++i) { - fill_pdu_session_resource_failed_to_setup_item(&resp->pdusessions_failed[i], - msg->pdusession_setup_params[i].pdusession_id, - cause); + fill_pdu_session_resource_failed_to_setup_item(&resp->pdusessions_failed[i], msg->pdusession[i].pdusession_id, cause); } itti_send_msg_to_task(TASK_NGAP, instance, msg_resp); } @@ -903,7 +901,7 @@ void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(MessageDef *msg_p, instance_t ins // At least one because marking one as existing, and setting up another, that // might be more work than is worth it. See 8.2.1.4 in 38.413 for (int i = 0; i < msg->nb_pdusessions_tosetup; ++i) { - const pdusession_t *p = &msg->pdusession_setup_params[i]; + const pdusession_t *p = &msg->pdusession[i]; rrc_pdu_session_param_t *exist = find_pduSession(UE, p->pdusession_id, false /* don't create */); if (exist) { LOG_E(NR_RRC, "UE %d: already has existing PDU session %d rejecting PDU Session Resource Setup Request\n", UE->rrc_ue_id, p->pdusession_id); @@ -936,7 +934,7 @@ void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(MessageDef *msg_p, instance_t ins return; } - if (!trigger_bearer_setup(rrc, UE, msg->nb_pdusessions_tosetup, msg->pdusession_setup_params, msg->ueAggMaxBitRate.br_dl)) { + if (!trigger_bearer_setup(rrc, UE, msg->nb_pdusessions_tosetup, msg->pdusession, msg->ueAggMaxBitRate.br_dl)) { // Reject PDU Session Resource setup if there's no CU-UP associated LOG_W(NR_RRC, "UE %d: reject PDU Session Setup in PDU Session Resource Setup Response\n", UE->rrc_ue_id); ngap_cause_t cause = {.type = NGAP_CAUSE_RADIO_NETWORK, .value = NGAP_CAUSE_RADIO_NETWORK_RESOURCES_NOT_AVAILABLE_FOR_THE_SLICE}; @@ -1064,7 +1062,7 @@ int rrc_gNB_process_NGAP_PDUSESSION_MODIFY_REQ(MessageDef *msg_p, instance_t ins bool all_failed = true; for (int i = 0; i < req->nb_pdusessions_tomodify; i++) { rrc_pdu_session_param_t *sess; - const pdusession_t *sessMod = req->pdusession_modify_params + i; + const pdusession_t *sessMod = req->pdusession + i; for (sess = UE->pduSession; sess < UE->pduSession + UE->nb_of_pdusessions; sess++) if (sess->param.pdusession_id == sessMod->pdusession_id) break; diff --git a/openair3/NGAP/ngap_gNB_handlers.c b/openair3/NGAP/ngap_gNB_handlers.c index 3f6b718861..6737879e7f 100644 --- a/openair3/NGAP/ngap_gNB_handlers.c +++ b/openair3/NGAP/ngap_gNB_handlers.c @@ -762,13 +762,13 @@ static int ngap_gNB_handle_initial_context_request(sctp_assoc_t assoc_id, uint32 for (i = 0; i < ie->value.choice.PDUSessionResourceSetupListCxtReq.list.count; i++) { NGAP_PDUSessionResourceSetupItemCxtReq_t *item_p = ie->value.choice.PDUSessionResourceSetupListCxtReq.list.array[i]; - msg->pdusession_param[i].pdusession_id = item_p->pDUSessionID; - msg->pdusession_param[i].nssai = decode_ngap_nssai(&item_p->s_NSSAI); + msg->pdusession[i].pdusession_id = item_p->pDUSessionID; + msg->pdusession[i].nssai = decode_ngap_nssai(&item_p->s_NSSAI); if (item_p->nAS_PDU) { - msg->pdusession_param[i].nas_pdu = create_byte_array(item_p->nAS_PDU->size, item_p->nAS_PDU->buf); + msg->pdusession[i].nas_pdu = create_byte_array(item_p->nAS_PDU->size, item_p->nAS_PDU->buf); } OCTET_STRING_t *transfer = &item_p->pDUSessionResourceSetupRequestTransfer; - msg->pdusession_param[i].pdusessionTransfer = create_byte_array(transfer->size, transfer->buf); + msg->pdusession[i].pdusessionTransfer = create_byte_array(transfer->size, transfer->buf); } } @@ -936,14 +936,14 @@ static int ngap_gNB_handle_pdusession_setup_request(sctp_assoc_t assoc_id, uint3 for (int i = 0; i < ie->value.choice.PDUSessionResourceSetupListSUReq.list.count; i++) { NGAP_PDUSessionResourceSetupItemSUReq_t *item_p = ie->value.choice.PDUSessionResourceSetupListSUReq.list.array[i]; - msg->pdusession_setup_params[i].pdusession_id = item_p->pDUSessionID; + msg->pdusession[i].pdusession_id = item_p->pDUSessionID; // S-NSSAI - msg->pdusession_setup_params[i].nssai = decode_ngap_nssai(&item_p->s_NSSAI); + msg->pdusession[i].nssai = decode_ngap_nssai(&item_p->s_NSSAI); OCTET_STRING_t *transfer = &item_p->pDUSessionResourceSetupRequestTransfer; - msg->pdusession_setup_params[i].nas_pdu = create_byte_array(item_p->pDUSessionNAS_PDU->size, item_p->pDUSessionNAS_PDU->buf); - msg->pdusession_setup_params[i].pdusessionTransfer = create_byte_array(transfer->size, transfer->buf); + msg->pdusession[i].nas_pdu = create_byte_array(item_p->pDUSessionNAS_PDU->size, item_p->pDUSessionNAS_PDU->buf); + msg->pdusession[i].pdusessionTransfer = create_byte_array(transfer->size, transfer->buf); } itti_send_msg_to_task(TASK_RRC_GNB, ue_desc_p->gNB_instance->instance, message_p); @@ -1116,13 +1116,13 @@ static int ngap_gNB_handle_pdusession_modify_request(sctp_assoc_t assoc_id, uint for (int i = 0; i < ie->value.choice.PDUSessionResourceModifyListModReq.list.count; i++) { NGAP_PDUSessionResourceModifyItemModReq_t *item_p = ie->value.choice.PDUSessionResourceModifyListModReq.list.array[i]; - msg->pdusession_modify_params[i].pdusession_id = item_p->pDUSessionID; + msg->pdusession[i].pdusession_id = item_p->pDUSessionID; // check for the NAS PDU if (item_p->nAS_PDU != NULL && item_p->nAS_PDU->size > 0) { - msg->pdusession_modify_params[i].nas_pdu = create_byte_array(item_p->nAS_PDU->size, item_p->nAS_PDU->buf); + msg->pdusession[i].nas_pdu = create_byte_array(item_p->nAS_PDU->size, item_p->nAS_PDU->buf); OCTET_STRING_t *transfer = &item_p->pDUSessionResourceModifyRequestTransfer; - msg->pdusession_modify_params[i].pdusessionTransfer = create_byte_array(transfer->size, transfer->buf); + msg->pdusession[i].pdusessionTransfer = create_byte_array(transfer->size, transfer->buf); } else { LOG_W(NGAP, "received pdu session modify with void content for UE %u, pdu session %lu\n", msg->gNB_ue_ngap_id, item_p->pDUSessionID); continue; From 5ff24cce71e23ecad2e0799507ce529af2270452 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 4 Jun 2025 16:19:15 +0200 Subject: [PATCH 047/964] Refactor pdusession_t Definitions Motivation: The previous code had overlapping and partially inconsiste definitions of `pdusession_t` and related structures across NGAP and RRC. This struct type was used for either the data stored in the UE context and the NGAP message IEs holding the PDU session to setup/modify information. This patch aims to separte the `pdusession_t` in RRC, where it logically belongs, since RRC owns the state of the PDU sessions. NGAP should only deal with protocol messages, i.e. enc/dec and transfer structures to RRC. This clarifies module ownership. This also makes the code easier to maintain. Changes: * Moved `pdusession_t` definition from NGAP (`ngap_messages_types.h`) to RRC (`nr_rrc_defs.h`) * Added a simpler `pdusession_resource_item_t` structure to NGAP for use in protocol messages * Adjusted NGAP structures accordingly (Initial Context Setup, PDU Session Setup Request, and PDU Session Modify Request). * do decodePDUSessionResourceSetup to decode the NGAP IEs holding PDU session information and store what necessary in the UE context PDU Session IE: NOTE this changes were necessary since previously this function was acting on the common NGAP/RRC pdu_session_t struct --- openair2/COMMON/ngap_messages_types.h | 44 ++++++++------------------- openair2/RRC/NR/nr_rrc_defs.h | 25 +++++++++++++++ openair2/RRC/NR/rrc_gNB_NGAP.c | 28 +++++++++-------- 3 files changed, 54 insertions(+), 43 deletions(-) diff --git a/openair2/COMMON/ngap_messages_types.h b/openair2/COMMON/ngap_messages_types.h index 6bd2ed5a5f..db7529b797 100644 --- a/openair2/COMMON/ngap_messages_types.h +++ b/openair2/COMMON/ngap_messages_types.h @@ -231,31 +231,6 @@ typedef struct ngap_mobility_restriction_s{ ngap_plmn_identity_t serving_plmn; }ngap_mobility_restriction_t; -typedef enum pdu_session_type_e { - PDUSessionType_ipv4 = 0, - PDUSessionType_ipv6 = 1, - PDUSessionType_ipv4v6 = 2, - PDUSessionType_ethernet = 3, - PDUSessionType_unstructured = 4 -}pdu_session_type_t; - -typedef struct pdusession_s { - /* Unique pdusession_id for the UE. */ - int pdusession_id; - byte_array_t nas_pdu; - byte_array_t pdusessionTransfer; - uint8_t nb_qos; - /* Quality of service for this pdusession */ - pdusession_level_qos_parameter_t qos[QOSFLOW_MAX_VALUE]; - /* The transport layer address for the IP packets */ - pdu_session_type_t pdu_session_type; - // NG-RAN endpoint of the NG-U (N3) transport bearer - gtpu_tunnel_t n3_outgoing; - // UPF endpoint of the NG-U (N3) transport bearer - gtpu_tunnel_t n3_incoming; - nssai_t nssai; -} pdusession_t; - typedef enum pdusession_qosflow_mapping_ind_e{ QOSFLOW_MAPPING_INDICATION_UL = 0, QOSFLOW_MAPPING_INDICATION_DL = 1, @@ -563,6 +538,13 @@ typedef struct ngap_downlink_nas_s { byte_array_t nas_pdu; } ngap_downlink_nas_t; +/* PDU Session Resource Setup/Modify Request Item */ +typedef struct { + int pdusession_id; + byte_array_t nas_pdu; + nssai_t nssai; + byte_array_t pdusessionTransfer; +} pdusession_resource_item_t; typedef struct ngap_initial_context_setup_req_s { /* UE id for initial connection to NGAP */ @@ -588,8 +570,8 @@ typedef struct ngap_initial_context_setup_req_s { /* Number of pdusession to be setup in the list */ uint8_t nb_of_pdusessions; - /* list of pdusession to be setup by RRC layers */ - pdusession_t pdusession[NGAP_MAX_PDU_SESSION]; + // PDU Session Resource Setup Request List + pdusession_resource_item_t pdusession[NGAP_MAX_PDU_SESSION]; /* Mobility Restriction List */ uint8_t mobility_restriction_flag; @@ -637,8 +619,8 @@ typedef struct ngap_pdusession_setup_req_s { /* Number of pdusession to be setup in the list */ uint8_t nb_pdusessions_tosetup; - /* E RAB setup request */ - pdusession_t pdusession[NGAP_MAX_PDU_SESSION]; + // PDU Session Resource Setup Request List + pdusession_resource_item_t pdusession[NGAP_MAX_PDU_SESSION]; /* UE Aggregated Max Bitrates */ ngap_ambr_t ueAggMaxBitRate; @@ -693,8 +675,8 @@ typedef struct ngap_pdusession_modify_req_s { /* Number of pdusession to be modify in the list */ uint8_t nb_pdusessions_tomodify; - /* pdu session modify request */ - pdusession_t pdusession[NGAP_MAX_PDU_SESSION]; + // PDU Session Resource Modify Request List + pdusession_resource_item_t pdusession[NGAP_MAX_PDU_SESSION]; } ngap_pdusession_modify_req_t; typedef struct ngap_pdusession_modify_resp_s { diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index 9998562b61..89fcfe7561 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -99,6 +99,31 @@ typedef enum pdu_session_satus_e { PDU_SESSION_STATUS_RELEASED } pdu_session_status_t; +typedef enum pdu_session_type_e { + PDUSessionType_ipv4 = 0, + PDUSessionType_ipv6 = 1, + PDUSessionType_ipv4v6 = 2, + PDUSessionType_ethernet = 3, + PDUSessionType_unstructured = 4 +}pdu_session_type_t; + +typedef struct pdusession_s { + /* Unique pdusession_id for the UE. */ + int pdusession_id; + byte_array_t nas_pdu; + byte_array_t pdusessionTransfer; + uint8_t nb_qos; + /* Quality of service for this pdusession */ + pdusession_level_qos_parameter_t qos[QOSFLOW_MAX_VALUE]; + /* The transport layer address for the IP packets */ + pdu_session_type_t pdu_session_type; + // NG-RAN endpoint of the NG-U (N3) transport bearer + gtpu_tunnel_t n3_outgoing; + // UPF endpoint of the NG-U (N3) transport bearer + gtpu_tunnel_t n3_incoming; + nssai_t nssai; +} pdusession_t; + typedef struct pdu_session_param_s { pdusession_t param; pdu_session_status_t status; diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index 42fe17fec9..1bb60df9bc 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -254,7 +254,7 @@ static void fill_qos(NGAP_QosFlowSetupRequestList_t *qos, pdusession_t *session) session->nb_qos = qos->list.count; } -static int decodePDUSessionResourceSetup(pdusession_t *session) +static int decodePDUSessionResourceSetup(pdusession_t *out, const pdusession_resource_item_t *session) { NGAP_PDUSessionResourceSetupRequestTransfer_t *pdusessionTransfer = NULL; asn_codec_ctx_t st = {.max_stack_size = 100 * 1000}; @@ -283,11 +283,11 @@ static int decodePDUSessionResourceSetup(pdusession_t *session) NGAP_GTPTunnel_t *gTPTunnel_p = pdusessionTransfer_ies->value.choice.UPTransportLayerInformation.choice.gTPTunnel; /* Set the transport layer address */ - memcpy(session->n3_incoming.addr.buffer, gTPTunnel_p->transportLayerAddress.buf, gTPTunnel_p->transportLayerAddress.size); - session->n3_incoming.addr.length = gTPTunnel_p->transportLayerAddress.size * 8 - gTPTunnel_p->transportLayerAddress.bits_unused; + memcpy(out->n3_incoming.addr.buffer, gTPTunnel_p->transportLayerAddress.buf, gTPTunnel_p->transportLayerAddress.size); + out->n3_incoming.addr.length = gTPTunnel_p->transportLayerAddress.size * 8 - gTPTunnel_p->transportLayerAddress.bits_unused; /* GTP tunnel endpoint ID */ - OCTET_STRING_TO_INT32(&gTPTunnel_p->gTP_TEID, session->n3_incoming.teid); + OCTET_STRING_TO_INT32(&gTPTunnel_p->gTP_TEID, out->n3_incoming.teid); } break; @@ -302,7 +302,7 @@ static int decodePDUSessionResourceSetup(pdusession_t *session) /* mandatory PDUSessionType */ case NGAP_ProtocolIE_ID_id_PDUSessionType: - session->pdu_session_type = (uint8_t)pdusessionTransfer_ies->value.choice.PDUSessionType; + out->pdu_session_type = (uint8_t)pdusessionTransfer_ies->value.choice.PDUSessionType; break; /* optional SecurityIndication */ @@ -315,7 +315,7 @@ static int decodePDUSessionResourceSetup(pdusession_t *session) /* mandatory QosFlowSetupRequestList */ case NGAP_ProtocolIE_ID_id_QosFlowSetupRequestList: - fill_qos(&pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList, session); + fill_qos(&pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList, out); break; /* optional CommonNetworkInstance */ @@ -365,7 +365,6 @@ bool trigger_bearer_setup(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, pdusession session->nas_pdu = sessions[i].nas_pdu; session->pdusessionTransfer = sessions[i].pdusessionTransfer; session->nssai = sessions[i].nssai; - decodePDUSessionResourceSetup(session); bearer_req.gNB_cu_cp_ue_id = UE->rrc_ue_id; security_information_t *secInfo = &bearer_req.secInfo; secInfo->cipheringAlgorithm = rrc->security.do_drb_ciphering ? UE->ciphering_algorithm : 0; @@ -520,8 +519,9 @@ int rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, instance_t UE->n_initial_pdu = req->nb_of_pdusessions; UE->initial_pdus = calloc(UE->n_initial_pdu, sizeof(*UE->initial_pdus)); AssertFatal(UE->initial_pdus != NULL, "out of memory\n"); - for (int i = 0; i < UE->n_initial_pdu; ++i) - UE->initial_pdus[i] = req->pdusession[i]; + for (int i = 0; i < UE->n_initial_pdu; ++i) { + decodePDUSessionResourceSetup(&UE->initial_pdus[i], &req->pdusession[i]); + } } /* security */ @@ -901,7 +901,7 @@ void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(MessageDef *msg_p, instance_t ins // At least one because marking one as existing, and setting up another, that // might be more work than is worth it. See 8.2.1.4 in 38.413 for (int i = 0; i < msg->nb_pdusessions_tosetup; ++i) { - const pdusession_t *p = &msg->pdusession[i]; + const pdusession_resource_item_t *p = &msg->pdusession[i]; rrc_pdu_session_param_t *exist = find_pduSession(UE, p->pdusession_id, false /* don't create */); if (exist) { LOG_E(NR_RRC, "UE %d: already has existing PDU session %d rejecting PDU Session Resource Setup Request\n", UE->rrc_ue_id, p->pdusession_id); @@ -934,7 +934,11 @@ void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(MessageDef *msg_p, instance_t ins return; } - if (!trigger_bearer_setup(rrc, UE, msg->nb_pdusessions_tosetup, msg->pdusession, msg->ueAggMaxBitRate.br_dl)) { + pdusession_t to_setup[NGAP_MAX_PDU_SESSION] = {0}; + for (int i = 0; i < msg->nb_pdusessions_tosetup; ++i) { + decodePDUSessionResourceSetup(&to_setup[i], &msg->pdusession[i]); + } + if (!trigger_bearer_setup(rrc, UE, msg->nb_pdusessions_tosetup, to_setup, msg->ueAggMaxBitRate.br_dl)) { // Reject PDU Session Resource setup if there's no CU-UP associated LOG_W(NR_RRC, "UE %d: reject PDU Session Setup in PDU Session Resource Setup Response\n", UE->rrc_ue_id); ngap_cause_t cause = {.type = NGAP_CAUSE_RADIO_NETWORK, .value = NGAP_CAUSE_RADIO_NETWORK_RESOURCES_NOT_AVAILABLE_FOR_THE_SLICE}; @@ -1062,7 +1066,7 @@ int rrc_gNB_process_NGAP_PDUSESSION_MODIFY_REQ(MessageDef *msg_p, instance_t ins bool all_failed = true; for (int i = 0; i < req->nb_pdusessions_tomodify; i++) { rrc_pdu_session_param_t *sess; - const pdusession_t *sessMod = req->pdusession + i; + const pdusession_resource_item_t *sessMod = req->pdusession + i; for (sess = UE->pduSession; sess < UE->pduSession + UE->nb_of_pdusessions; sess++) if (sess->param.pdusession_id == sessMod->pdusession_id) break; From 48a4c2b0ab5f59e8075ed31f92bf6704b849bc4a Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 4 Jun 2025 16:50:22 +0200 Subject: [PATCH 048/964] Move pdu_session_type_t to platform constants * It is used by both NGAP and RRC --- common/5g_platform_types.h | 8 ++++++++ openair2/RRC/NR/nr_rrc_defs.h | 8 -------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/common/5g_platform_types.h b/common/5g_platform_types.h index a5b7b7a1fc..b46490a2e8 100644 --- a/common/5g_platform_types.h +++ b/common/5g_platform_types.h @@ -45,6 +45,14 @@ typedef struct nr_guami_s { uint8_t amf_pointer; } nr_guami_t; +typedef enum { + PDUSessionType_ipv4 = 0, + PDUSessionType_ipv6 = 1, + PDUSessionType_ipv4v6 = 2, + PDUSessionType_ethernet = 3, + PDUSessionType_unstructured = 4 +} pdu_session_type_t; + typedef enum { NON_DYNAMIC, DYNAMIC } fiveQI_t; #endif diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index 89fcfe7561..4f6b941144 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -99,14 +99,6 @@ typedef enum pdu_session_satus_e { PDU_SESSION_STATUS_RELEASED } pdu_session_status_t; -typedef enum pdu_session_type_e { - PDUSessionType_ipv4 = 0, - PDUSessionType_ipv6 = 1, - PDUSessionType_ipv4v6 = 2, - PDUSessionType_ethernet = 3, - PDUSessionType_unstructured = 4 -}pdu_session_type_t; - typedef struct pdusession_s { /* Unique pdusession_id for the UE. */ int pdusession_id; From 0c408875a310803386c7e2d326d9ce7db536a279 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 4 Jun 2025 16:46:27 +0200 Subject: [PATCH 049/964] Refactor NGAP decodePDUSessionResourceSetup/Modify to improve RRC/NGAP separation Motivation of the commit: Previously, the RRC module on the NGAP interface directly handled ASN.1 decoding of NGAP PDU Session Resource items, that was directly stored in pdusession_t, i.e. in the UE context. Decode logic between Setup and Modify was also duplicated., e.g. fill_qos/fill_qos2. The idea behind this change is to achieve this flow: (1) NGAP handler: decoding (2) ITTI to RRC: transfer decoded message (3) RRC handler: process decoded message, e.g. store in UE context, etc.. The goal of this commit is to: * improve the NGAP decoding library by adding decoding functions * let RRC handle the already decoded data * enhance error handling, with decode failures now consistently detected and rejected early * have a cleaner, more maintainable code with fewer duplications and a clearer separation of modules Changes: * Moved all ASN.1 decode logic for PDU Session Resource items into the NGAP library * Introduced decode functions for NGAP IEs whenever necessary, e.g. decode_TNLInformation decode_pdusession_transfer * Removed duplicate fill_qos functions and centralized QoS handling in NGAP * Added function to copy from NGAP PDU Session Resource item to RRC pdusession_t: this actually replaces decodePDUSessionResourceSetup in RRC, copying from the decoded NGAP struct to the UE context pdusession_t --- openair2/COMMON/ngap_messages_types.h | 11 +- openair2/RRC/NR/nr_rrc_defs.h | 1 - openair2/RRC/NR/rrc_gNB_NGAP.c | 235 +++----------------------- openair3/NGAP/ngap_gNB_handlers.c | 146 +++++++++++++++- openair3/NGAP/ngap_msg_includes.h | 7 + 5 files changed, 177 insertions(+), 223 deletions(-) diff --git a/openair2/COMMON/ngap_messages_types.h b/openair2/COMMON/ngap_messages_types.h index db7529b797..b5fb021305 100644 --- a/openair2/COMMON/ngap_messages_types.h +++ b/openair2/COMMON/ngap_messages_types.h @@ -538,12 +538,21 @@ typedef struct ngap_downlink_nas_s { byte_array_t nas_pdu; } ngap_downlink_nas_t; +/* PDU Session Resource Setup Request Transfer (9.3.4.1 3GPP TS 38.413) */ +typedef struct { + uint8_t nb_qos; + pdusession_level_qos_parameter_t qos[QOSFLOW_MAX_VALUE]; + pdu_session_type_t pdu_session_type; + // UPF endpoint of the NG-U (N3) transport bearer + gtpu_tunnel_t n3_incoming; +} pdusession_transfer_t; + /* PDU Session Resource Setup/Modify Request Item */ typedef struct { int pdusession_id; byte_array_t nas_pdu; nssai_t nssai; - byte_array_t pdusessionTransfer; + pdusession_transfer_t pdusessionTransfer; } pdusession_resource_item_t; typedef struct ngap_initial_context_setup_req_s { diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index 4f6b941144..804657e8ce 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -103,7 +103,6 @@ typedef struct pdusession_s { /* Unique pdusession_id for the UE. */ int pdusession_id; byte_array_t nas_pdu; - byte_array_t pdusessionTransfer; uint8_t nb_qos; /* Quality of service for this pdusession */ pdusession_level_qos_parameter_t qos[QOSFLOW_MAX_VALUE]; diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index 1bb60df9bc..16df2eac02 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -161,6 +161,20 @@ static nr_guami_t get_guami(const uint32_t amf_Id, const plmn_id_t plmn) return guami; } +/** @brief Copy NGAP PDU Session Resource item to RRC pdusession_t struct */ +static void cp_pdusession_resource_item_to_pdusession(pdusession_t *dst, const pdusession_resource_item_t *src) +{ + dst->pdusession_id = src->pdusession_id; + dst->nas_pdu = src->nas_pdu; + dst->nb_qos = src->pdusessionTransfer.nb_qos; + for (uint8_t i = 0; i < src->pdusessionTransfer.nb_qos && i < QOSFLOW_MAX_VALUE; ++i) { + dst->qos[i] = src->pdusessionTransfer.qos[i]; + } + dst->pdu_session_type = src->pdusessionTransfer.pdu_session_type; + dst->n3_incoming = src->pdusessionTransfer.n3_incoming; + dst->nssai = src->nssai; +} + /** * @brief Prepare the Initial UE Message (Uplink NAS) to be forwarded to the AMF over N2 * extracts NAS PDU, Selected PLMN and Registered AMF from the RRCSetupComplete @@ -225,113 +239,6 @@ void rrc_gNB_send_NGAP_NAS_FIRST_REQ(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, NR_RRC itti_send_msg_to_task(TASK_NGAP, rrc->module_id, message_p); } -static void fill_qos(NGAP_QosFlowSetupRequestList_t *qos, pdusession_t *session) -{ - DevAssert(qos->list.count > 0); - DevAssert(qos->list.count <= NGAP_maxnoofQosFlows); - for (int qosIdx = 0; qosIdx < qos->list.count; qosIdx++) { - NGAP_QosFlowSetupRequestItem_t *qosFlowItem_p = qos->list.array[qosIdx]; - // Set the QOS informations - session->qos[qosIdx].qfi = (uint8_t)qosFlowItem_p->qosFlowIdentifier; - NGAP_QosCharacteristics_t *qosChar = &qosFlowItem_p->qosFlowLevelQosParameters.qosCharacteristics; - AssertFatal(qosChar, "Qos characteristics are not available for qos flow index %d\n", qosIdx); - if (qosChar->present == NGAP_QosCharacteristics_PR_nonDynamic5QI) { - AssertFatal(qosChar->choice.dynamic5QI, "Non-Dynamic 5QI is NULL\n"); - session->qos[qosIdx].fiveQI_type = NON_DYNAMIC; - session->qos[qosIdx].fiveQI = (uint64_t)qosChar->choice.nonDynamic5QI->fiveQI; - } else { - AssertFatal(qosChar->choice.dynamic5QI, "Dynamic 5QI is NULL\n"); - session->qos[qosIdx].fiveQI_type = DYNAMIC; - session->qos[qosIdx].fiveQI = (uint64_t)(*qosChar->choice.dynamic5QI->fiveQI); - } - - ngap_allocation_retention_priority_t *tmp = &session->qos[qosIdx].allocation_retention_priority; - NGAP_AllocationAndRetentionPriority_t *tmp2 = &qosFlowItem_p->qosFlowLevelQosParameters.allocationAndRetentionPriority; - tmp->priority_level = tmp2->priorityLevelARP; - tmp->pre_emp_capability = tmp2->pre_emptionCapability; - tmp->pre_emp_vulnerability = tmp2->pre_emptionVulnerability; - } - session->nb_qos = qos->list.count; -} - -static int decodePDUSessionResourceSetup(pdusession_t *out, const pdusession_resource_item_t *session) -{ - NGAP_PDUSessionResourceSetupRequestTransfer_t *pdusessionTransfer = NULL; - asn_codec_ctx_t st = {.max_stack_size = 100 * 1000}; - asn_dec_rval_t dec_rval = aper_decode(&st, - &asn_DEF_NGAP_PDUSessionResourceSetupRequestTransfer, - (void **)&pdusessionTransfer, - session->pdusessionTransfer.buf, - session->pdusessionTransfer.len, - 0, - 0); - - if (dec_rval.code != RC_OK) { - LOG_E(NR_RRC, "can not decode PDUSessionResourceSetupRequestTransfer\n"); - return -1; - } - - for (int i = 0; i < pdusessionTransfer->protocolIEs.list.count; i++) { - NGAP_PDUSessionResourceSetupRequestTransferIEs_t *pdusessionTransfer_ies = pdusessionTransfer->protocolIEs.list.array[i]; - switch (pdusessionTransfer_ies->id) { - /* optional PDUSessionAggregateMaximumBitRate */ - case NGAP_ProtocolIE_ID_id_PDUSessionAggregateMaximumBitRate: - break; - - /* mandatory UL-NGU-UP-TNLInformation */ - case NGAP_ProtocolIE_ID_id_UL_NGU_UP_TNLInformation: { - NGAP_GTPTunnel_t *gTPTunnel_p = pdusessionTransfer_ies->value.choice.UPTransportLayerInformation.choice.gTPTunnel; - - /* Set the transport layer address */ - memcpy(out->n3_incoming.addr.buffer, gTPTunnel_p->transportLayerAddress.buf, gTPTunnel_p->transportLayerAddress.size); - out->n3_incoming.addr.length = gTPTunnel_p->transportLayerAddress.size * 8 - gTPTunnel_p->transportLayerAddress.bits_unused; - - /* GTP tunnel endpoint ID */ - OCTET_STRING_TO_INT32(&gTPTunnel_p->gTP_TEID, out->n3_incoming.teid); - } - - break; - - /* optional AdditionalUL-NGU-UP-TNLInformation */ - case NGAP_ProtocolIE_ID_id_AdditionalUL_NGU_UP_TNLInformation: - break; - - /* optional DataForwardingNotPossible */ - case NGAP_ProtocolIE_ID_id_DataForwardingNotPossible: - break; - - /* mandatory PDUSessionType */ - case NGAP_ProtocolIE_ID_id_PDUSessionType: - out->pdu_session_type = (uint8_t)pdusessionTransfer_ies->value.choice.PDUSessionType; - break; - - /* optional SecurityIndication */ - case NGAP_ProtocolIE_ID_id_SecurityIndication: - break; - - /* optional NetworkInstance */ - case NGAP_ProtocolIE_ID_id_NetworkInstance: - break; - - /* mandatory QosFlowSetupRequestList */ - case NGAP_ProtocolIE_ID_id_QosFlowSetupRequestList: - fill_qos(&pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList, out); - break; - - /* optional CommonNetworkInstance */ - case NGAP_ProtocolIE_ID_id_CommonNetworkInstance: - break; - - default: - LOG_E(NR_RRC, "could not found protocolIEs id %ld\n", pdusessionTransfer_ies->id); - return -1; - } - } - ASN_STRUCT_FREE(asn_DEF_NGAP_PDUSessionResourceSetupRequestTransfer, pdusessionTransfer); - - return 0; -} - /** * @brief Triggers bearer setup for the specified UE. * @@ -363,7 +270,6 @@ bool trigger_bearer_setup(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, pdusession LOG_I(NR_RRC, "Adding pdusession %d, total nb of sessions %d\n", session->pdusession_id, UE->nb_of_pdusessions); session->pdu_session_type = sessions[i].pdu_session_type; session->nas_pdu = sessions[i].nas_pdu; - session->pdusessionTransfer = sessions[i].pdusessionTransfer; session->nssai = sessions[i].nssai; bearer_req.gNB_cu_cp_ue_id = UE->rrc_ue_id; security_information_t *secInfo = &bearer_req.secInfo; @@ -519,9 +425,8 @@ int rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, instance_t UE->n_initial_pdu = req->nb_of_pdusessions; UE->initial_pdus = calloc(UE->n_initial_pdu, sizeof(*UE->initial_pdus)); AssertFatal(UE->initial_pdus != NULL, "out of memory\n"); - for (int i = 0; i < UE->n_initial_pdu; ++i) { - decodePDUSessionResourceSetup(&UE->initial_pdus[i], &req->pdusession[i]); - } + for (int i = 0; i < UE->n_initial_pdu; ++i) + cp_pdusession_resource_item_to_pdusession(&UE->initial_pdus[i], &req->pdusession[i]); } /* security */ @@ -935,9 +840,9 @@ void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(MessageDef *msg_p, instance_t ins } pdusession_t to_setup[NGAP_MAX_PDU_SESSION] = {0}; - for (int i = 0; i < msg->nb_pdusessions_tosetup; ++i) { - decodePDUSessionResourceSetup(&to_setup[i], &msg->pdusession[i]); - } + for (int i = 0; i < msg->nb_pdusessions_tosetup; ++i) + cp_pdusession_resource_item_to_pdusession(&to_setup[i], &msg->pdusession[i]); + if (!trigger_bearer_setup(rrc, UE, msg->nb_pdusessions_tosetup, to_setup, msg->ueAggMaxBitRate.br_dl)) { // Reject PDU Session Resource setup if there's no CU-UP associated LOG_W(NR_RRC, "UE %d: reject PDU Session Setup in PDU Session Resource Setup Response\n", UE->rrc_ue_id); @@ -949,104 +854,6 @@ void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(MessageDef *msg_p, instance_t ins } } -static void fill_qos2(NGAP_QosFlowAddOrModifyRequestList_t *qos, pdusession_t *session) -{ - // we need to duplicate the function fill_qos because all data types are slightly different - DevAssert(qos->list.count > 0); - DevAssert(qos->list.count <= NGAP_maxnoofQosFlows); - for (int qosIdx = 0; qosIdx < qos->list.count; qosIdx++) { - NGAP_QosFlowAddOrModifyRequestItem_t *qosFlowItem_p = qos->list.array[qosIdx]; - // Set the QOS informations - session->qos[qosIdx].qfi = (uint8_t)qosFlowItem_p->qosFlowIdentifier; - NGAP_QosCharacteristics_t *qosChar = &qosFlowItem_p->qosFlowLevelQosParameters->qosCharacteristics; - AssertFatal(qosChar, "Qos characteristics are not available for qos flow index %d\n", qosIdx); - if (qosChar->present == NGAP_QosCharacteristics_PR_nonDynamic5QI) { - AssertFatal(qosChar->choice.dynamic5QI, "Non-Dynamic 5QI is NULL\n"); - session->qos[qosIdx].fiveQI_type = NON_DYNAMIC; - session->qos[qosIdx].fiveQI = (uint64_t)qosChar->choice.nonDynamic5QI->fiveQI; - } else { - AssertFatal(qosChar->choice.dynamic5QI, "Dynamic 5QI is NULL\n"); - session->qos[qosIdx].fiveQI_type = DYNAMIC; - session->qos[qosIdx].fiveQI = (uint64_t)(*qosChar->choice.dynamic5QI->fiveQI); - } - - ngap_allocation_retention_priority_t *tmp = &session->qos[qosIdx].allocation_retention_priority; - NGAP_AllocationAndRetentionPriority_t *tmp2 = &qosFlowItem_p->qosFlowLevelQosParameters->allocationAndRetentionPriority; - tmp->priority_level = tmp2->priorityLevelARP; - tmp->pre_emp_capability = tmp2->pre_emptionCapability; - tmp->pre_emp_vulnerability = tmp2->pre_emptionVulnerability; - } - session->nb_qos = qos->list.count; -} - -static void decodePDUSessionResourceModify(pdusession_t *param, const byte_array_t pdu) -{ - NGAP_PDUSessionResourceModifyRequestTransfer_t *pdusessionTransfer = NULL; - asn_dec_rval_t dec_rval = aper_decode(NULL, - &asn_DEF_NGAP_PDUSessionResourceModifyRequestTransfer, - (void **)&pdusessionTransfer, - pdu.buf, - pdu.len, - 0, - 0); - - if (dec_rval.code != RC_OK) { - LOG_E(NR_RRC, "could not decode PDUSessionResourceModifyRequestTransfer\n"); - return; - } - - for (int j = 0; j < pdusessionTransfer->protocolIEs.list.count; j++) { - NGAP_PDUSessionResourceModifyRequestTransferIEs_t *pdusessionTransfer_ies = pdusessionTransfer->protocolIEs.list.array[j]; - switch (pdusessionTransfer_ies->id) { - /* optional PDUSessionAggregateMaximumBitRate */ - case NGAP_ProtocolIE_ID_id_PDUSessionAggregateMaximumBitRate: - // TODO - LOG_E(NR_RRC, "Cant' handle NGAP_ProtocolIE_ID_id_PDUSessionAggregateMaximumBitRate\n"); - break; - - /* optional UL-NGU-UP-TNLModifyList */ - case NGAP_ProtocolIE_ID_id_UL_NGU_UP_TNLModifyList: - // TODO - LOG_E(NR_RRC, "Cant' handle NGAP_ProtocolIE_ID_id_UL_NGU_UP_TNLModifyList\n"); - break; - - /* optional NetworkInstance */ - case NGAP_ProtocolIE_ID_id_NetworkInstance: - // TODO - LOG_E(NR_RRC, "Cant' handle NGAP_ProtocolIE_ID_id_NetworkInstance\n"); - break; - - /* optional QosFlowAddOrModifyRequestList */ - case NGAP_ProtocolIE_ID_id_QosFlowAddOrModifyRequestList: - fill_qos2(&pdusessionTransfer_ies->value.choice.QosFlowAddOrModifyRequestList, param); - break; - - /* optional QosFlowToReleaseList */ - case NGAP_ProtocolIE_ID_id_QosFlowToReleaseList: - // TODO - LOG_E(NR_RRC, "Can't handle NGAP_ProtocolIE_ID_id_QosFlowToReleaseList\n"); - break; - - /* optional AdditionalUL-NGU-UP-TNLInformation */ - case NGAP_ProtocolIE_ID_id_AdditionalUL_NGU_UP_TNLInformation: - // TODO - LOG_E(NR_RRC, "Cant' handle NGAP_ProtocolIE_ID_id_AdditionalUL_NGU_UP_TNLInformation\n"); - break; - - /* optional CommonNetworkInstance */ - case NGAP_ProtocolIE_ID_id_CommonNetworkInstance: - // TODO - LOG_E(NR_RRC, "Cant' handle NGAP_ProtocolIE_ID_id_CommonNetworkInstance\n"); - break; - - default: - LOG_E(NR_RRC, "could not found protocolIEs id %ld\n", pdusessionTransfer_ies->id); - return; - } - } - ASN_STRUCT_FREE(asn_DEF_NGAP_PDUSessionResourceModifyRequestTransfer,pdusessionTransfer ); -} - //------------------------------------------------------------------------------ int rrc_gNB_process_NGAP_PDUSESSION_MODIFY_REQ(MessageDef *msg_p, instance_t instance) //------------------------------------------------------------------------------ @@ -1090,8 +897,8 @@ int rrc_gNB_process_NGAP_PDUSESSION_MODIFY_REQ(MessageDef *msg_p, instance_t ins if (sessMod->nas_pdu.buf != NULL) { UE->pduSession[i].param.nas_pdu = sessMod->nas_pdu; } - // Save new pdu session parameters, qos, upf addr, teid - decodePDUSessionResourceModify(&sess->param, UE->pduSession[i].param.pdusessionTransfer); + for (int i = 0; i < req->nb_pdusessions_tomodify; ++i) + cp_pdusession_resource_item_to_pdusession(&UE->pduSession[i].param, &req->pdusession[i]); } } diff --git a/openair3/NGAP/ngap_gNB_handlers.c b/openair3/NGAP/ngap_gNB_handlers.c index 6737879e7f..f4c4ebb20f 100644 --- a/openair3/NGAP/ngap_gNB_handlers.c +++ b/openair3/NGAP/ngap_gNB_handlers.c @@ -694,6 +694,99 @@ static int ngap_gNB_handle_error_indication(sctp_assoc_t assoc_id, uint32_t stre return 0; } +static void *decode_pdusession_transfer(const asn_TYPE_descriptor_t *td, const OCTET_STRING_t buf) +{ + void *decoded = NULL; + asn_codec_ctx_t ctx = {.max_stack_size = 100 * 1000}; + asn_dec_rval_t rval = aper_decode(&ctx, td, &decoded, buf.buf, buf.size, 0, 0); + if (rval.code != RC_OK) { + NGAP_ERROR("Decoding failed for %s\n", td->name); + return NULL; + } + return decoded; +} + +static pdusession_level_qos_parameter_t fill_qos(uint8_t qfi, const NGAP_QosFlowLevelQosParameters_t *params) +{ + pdusession_level_qos_parameter_t out = {0}; + // QFI + out.qfi = qfi; + AssertFatal(params != NULL, "QoS parameters are NULL\n"); + // QosCharacteristics + const NGAP_QosCharacteristics_t *qosChar = ¶ms->qosCharacteristics; + AssertFatal(qosChar != NULL, "QoS characteristics are NULL\n"); + if (qosChar->present == NGAP_QosCharacteristics_PR_nonDynamic5QI) { + AssertFatal(qosChar->choice.nonDynamic5QI != NULL, "nonDynamic5QI is NULL\n"); + out.fiveQI_type = NON_DYNAMIC; + out.fiveQI = qosChar->choice.nonDynamic5QI->fiveQI; + } else if (qosChar->present == NGAP_QosCharacteristics_PR_dynamic5QI) { + AssertFatal(qosChar->choice.dynamic5QI != NULL, "dynamic5QI is NULL\n"); + out.fiveQI_type = DYNAMIC; + out.fiveQI = *qosChar->choice.dynamic5QI->fiveQI; + } else { + AssertFatal(0, "Unsupported QoS Characteristics present value: %d\n", qosChar->present); + } + // Allocation and Retention Priority + const NGAP_AllocationAndRetentionPriority_t *arp = ¶ms->allocationAndRetentionPriority; + out.allocation_retention_priority.priority_level = arp->priorityLevelARP; + out.allocation_retention_priority.pre_emp_capability = arp->pre_emptionCapability; + out.allocation_retention_priority.pre_emp_vulnerability = arp->pre_emptionVulnerability; + + return out; +} + +static gtpu_tunnel_t decode_TNLInformation(const NGAP_GTPTunnel_t *gTPTunnel_p) +{ + gtpu_tunnel_t out = {0}; + // Transport layer address + memcpy(out.addr.buffer, gTPTunnel_p->transportLayerAddress.buf, gTPTunnel_p->transportLayerAddress.size); + out.addr.length = gTPTunnel_p->transportLayerAddress.size - gTPTunnel_p->transportLayerAddress.bits_unused; + // GTP tunnel endpoint ID + OCTET_STRING_TO_INT32(&gTPTunnel_p->gTP_TEID, out.teid); + return out; +} + +/** @brief Decode PDU Session Resource Setup Request Transfer (9.3.4.1 3GPP TS 38.413) */ +static bool decodePDUSessionResourceSetup(pdusession_transfer_t *out, const OCTET_STRING_t in) +{ + void *decoded = decode_pdusession_transfer(&asn_DEF_NGAP_PDUSessionResourceSetupRequestTransfer, in); + if (!decoded) { + LOG_E(NR_RRC, "Failed to decode PDUSessionResourceSetupRequestTransfer\n"); + return false; + } + + NGAP_PDUSessionResourceSetupRequestTransfer_t *pdusessionTransfer = (NGAP_PDUSessionResourceSetupRequestTransfer_t *)decoded; + for (int i = 0; i < pdusessionTransfer->protocolIEs.list.count; i++) { + NGAP_PDUSessionResourceSetupRequestTransferIEs_t *pdusessionTransfer_ies = pdusessionTransfer->protocolIEs.list.array[i]; + switch (pdusessionTransfer_ies->id) { + // UL NG-U UP TNL Information (Mandatory) + case NGAP_ProtocolIE_ID_id_UL_NGU_UP_TNLInformation: + out->n3_incoming = decode_TNLInformation(pdusessionTransfer_ies->value.choice.UPTransportLayerInformation.choice.gTPTunnel); + break; + + // PDU Session Type (Mandatory) + case NGAP_ProtocolIE_ID_id_PDUSessionType: + out->pdu_session_type = pdusessionTransfer_ies->value.choice.PDUSessionType; + break; + + // QoS Flow Setup Request List (Mandatory) + case NGAP_ProtocolIE_ID_id_QosFlowSetupRequestList: + out->nb_qos = pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.count; + for (int i = 0; i < out->nb_qos; i++) { + NGAP_QosFlowSetupRequestItem_t *item = pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.array[i]; + out->qos[i] = fill_qos(item->qosFlowIdentifier, &item->qosFlowLevelQosParameters); + } + break; + + default: + LOG_D(NR_RRC, "Unhandled optional IE %ld\n", pdusessionTransfer_ies->id); + } + } + ASN_STRUCT_FREE(asn_DEF_NGAP_PDUSessionResourceSetupRequestTransfer, pdusessionTransfer); + + return true; +} + static int ngap_gNB_handle_initial_context_request(sctp_assoc_t assoc_id, uint32_t stream, NGAP_NGAP_PDU_t *pdu) { int i; @@ -767,8 +860,11 @@ static int ngap_gNB_handle_initial_context_request(sctp_assoc_t assoc_id, uint32 if (item_p->nAS_PDU) { msg->pdusession[i].nas_pdu = create_byte_array(item_p->nAS_PDU->size, item_p->nAS_PDU->buf); } - OCTET_STRING_t *transfer = &item_p->pDUSessionResourceSetupRequestTransfer; - msg->pdusession[i].pdusessionTransfer = create_byte_array(transfer->size, transfer->buf); + bool ret = decodePDUSessionResourceSetup(&msg->pdusession[i].pdusessionTransfer, item_p->pDUSessionResourceSetupRequestTransfer); + if (!ret) { + NGAP_ERROR("Failed to decode pDUSessionResourceSetupRequestTransfer in NG Initial Context Setup Request\n"); + return -1; + } } } @@ -941,11 +1037,14 @@ static int ngap_gNB_handle_pdusession_setup_request(sctp_assoc_t assoc_id, uint3 // S-NSSAI msg->pdusession[i].nssai = decode_ngap_nssai(&item_p->s_NSSAI); - OCTET_STRING_t *transfer = &item_p->pDUSessionResourceSetupRequestTransfer; msg->pdusession[i].nas_pdu = create_byte_array(item_p->pDUSessionNAS_PDU->size, item_p->pDUSessionNAS_PDU->buf); - msg->pdusession[i].pdusessionTransfer = create_byte_array(transfer->size, transfer->buf); + bool ret = decodePDUSessionResourceSetup(&msg->pdusession[i].pdusessionTransfer, item_p->pDUSessionResourceSetupRequestTransfer); + if (!ret) { + NGAP_ERROR("Failed to decode pDUSessionResourceSetupRequestTransfer in NG Setup Request\n"); + return -1; + } } - itti_send_msg_to_task(TASK_RRC_GNB, ue_desc_p->gNB_instance->instance, message_p); + itti_send_msg_to_task(TASK_RRC_GNB, ue_desc_p->gNB_instance->instance, message_p); return 0; } @@ -1039,6 +1138,37 @@ static int ngap_gNB_handle_paging(sctp_assoc_t assoc_id, uint32_t stream, NGAP_N return 0; } +static bool decodePDUSessionResourceModify(pdusession_transfer_t *out, const OCTET_STRING_t in) +{ + void *decoded = decode_pdusession_transfer(&asn_DEF_NGAP_PDUSessionResourceModifyRequestTransfer, in); + if (!decoded) { + LOG_E(NR_RRC, "Failed to decode PDUSessionResourceModifyRequestTransfer\n"); + return false; + } + + NGAP_PDUSessionResourceModifyRequestTransfer_t *pdusessionTransfer = (NGAP_PDUSessionResourceModifyRequestTransfer_t *)decoded; + for (int j = 0; j < pdusessionTransfer->protocolIEs.list.count; j++) { + NGAP_PDUSessionResourceModifyRequestTransferIEs_t *pdusessionTransfer_ies = pdusessionTransfer->protocolIEs.list.array[j]; + switch (pdusessionTransfer_ies->id) { + /* optional QosFlowAddOrModifyRequestList */ + case NGAP_ProtocolIE_ID_id_QosFlowAddOrModifyRequestList: + out->nb_qos = pdusessionTransfer_ies->value.choice.QosFlowAddOrModifyRequestList.list.count; + for (int i = 0; i < out->nb_qos; i++) { + NGAP_QosFlowAddOrModifyRequestItem_t *item = + pdusessionTransfer_ies->value.choice.QosFlowAddOrModifyRequestList.list.array[i]; + out->qos[i] = fill_qos(item->qosFlowIdentifier, item->qosFlowLevelQosParameters); + } + break; + + default: + LOG_E(NR_RRC, "Unhandled optional IE %ld\n", pdusessionTransfer_ies->id); + return false; + } + } + ASN_STRUCT_FREE(asn_DEF_NGAP_PDUSessionResourceModifyRequestTransfer, pdusessionTransfer); + return true; +} + static int ngap_gNB_handle_pdusession_modify_request(sctp_assoc_t assoc_id, uint32_t stream, NGAP_NGAP_PDU_t *pdu) { ngap_gNB_amf_data_t *amf_desc_p = NULL; @@ -1121,8 +1251,10 @@ static int ngap_gNB_handle_pdusession_modify_request(sctp_assoc_t assoc_id, uint // check for the NAS PDU if (item_p->nAS_PDU != NULL && item_p->nAS_PDU->size > 0) { msg->pdusession[i].nas_pdu = create_byte_array(item_p->nAS_PDU->size, item_p->nAS_PDU->buf); - OCTET_STRING_t *transfer = &item_p->pDUSessionResourceModifyRequestTransfer; - msg->pdusession[i].pdusessionTransfer = create_byte_array(transfer->size, transfer->buf); + if (!decodePDUSessionResourceModify(&msg->pdusession[i].pdusessionTransfer, item_p->pDUSessionResourceModifyRequestTransfer)) { + NGAP_ERROR("Failed to decode pDUSessionResourceModifyRequestTransfer\n"); + return -1; + } } else { LOG_W(NGAP, "received pdu session modify with void content for UE %u, pdu session %lu\n", msg->gNB_ue_ngap_id, item_p->pDUSessionID); continue; diff --git a/openair3/NGAP/ngap_msg_includes.h b/openair3/NGAP/ngap_msg_includes.h index c7ef77be6a..1debc2e9f1 100644 --- a/openair3/NGAP/ngap_msg_includes.h +++ b/openair3/NGAP/ngap_msg_includes.h @@ -71,5 +71,12 @@ #include "NGAP_UnsuccessfulOutcome.h" #include "NGAP_UserLocationInformationNR.h" #include "NGAP_asn_constant.h" +#include "NGAP_PDUSessionResourceSetupRequestTransfer.h" +#include "NGAP_QosFlowSetupRequestItem.h" +#include "NGAP_QosCharacteristics.h" +#include "NGAP_NonDynamic5QIDescriptor.h" +#include "NGAP_Dynamic5QIDescriptor.h" +#include "NGAP_PDUSessionResourceModifyRequestTransfer.h" +#include "NGAP_QosFlowAddOrModifyRequestItem.h" #endif // NGAP_MSG_INCLUDES_H From 389b40b121bdaa00df1911ca3a481e714a1164d5 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 4 Jun 2025 16:54:27 +0200 Subject: [PATCH 050/964] Use calloc_or_fail to initiate UE->initial_pdus --- openair2/RRC/NR/rrc_gNB_NGAP.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index 16df2eac02..07b969b7f1 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -423,8 +423,7 @@ int rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, instance_t /* if there are PDU sessions to setup, store them to be created once * security (and UE capabilities) are received */ UE->n_initial_pdu = req->nb_of_pdusessions; - UE->initial_pdus = calloc(UE->n_initial_pdu, sizeof(*UE->initial_pdus)); - AssertFatal(UE->initial_pdus != NULL, "out of memory\n"); + UE->initial_pdus = calloc_or_fail(UE->n_initial_pdu, sizeof(*UE->initial_pdus)); for (int i = 0; i < UE->n_initial_pdu; ++i) cp_pdusession_resource_item_to_pdusession(&UE->initial_pdus[i], &req->pdusession[i]); } From e1fc1c38dbbac3bf2a0945db83fb5445f7697690 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Tue, 13 May 2025 22:35:18 +0200 Subject: [PATCH 051/964] Use cp_pdusession in trigger_bearer_setup --- openair2/RRC/NR/rrc_gNB_NGAP.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index 07b969b7f1..351392de95 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -266,11 +266,8 @@ bool trigger_bearer_setup(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, pdusession for (int i = 0; i < n; i++) { rrc_pdu_session_param_t *pduSession = find_pduSession(UE, sessions[i].pdusession_id, true); pdusession_t *session = &pduSession->param; - session->pdusession_id = sessions[i].pdusession_id; LOG_I(NR_RRC, "Adding pdusession %d, total nb of sessions %d\n", session->pdusession_id, UE->nb_of_pdusessions); - session->pdu_session_type = sessions[i].pdu_session_type; - session->nas_pdu = sessions[i].nas_pdu; - session->nssai = sessions[i].nssai; + cp_pdusession(session, &sessions[i]); bearer_req.gNB_cu_cp_ue_id = UE->rrc_ue_id; security_information_t *secInfo = &bearer_req.secInfo; secInfo->cipheringAlgorithm = rrc->security.do_drb_ciphering ? UE->ciphering_algorithm : 0; From 248cf7f1553e47c9316d338986ded83351f2d2b3 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 14 May 2025 11:29:02 +0200 Subject: [PATCH 052/964] Use gtpu_tunnel_t in pdusession_setup_t --- openair2/COMMON/ngap_messages_types.h | 5 ++--- openair2/RRC/NR/rrc_gNB_NGAP.c | 22 +++++++++++++--------- openair3/NGAP/ngap_gNB_nas_procedures.c | 12 ++++++------ 3 files changed, 21 insertions(+), 18 deletions(-) diff --git a/openair2/COMMON/ngap_messages_types.h b/openair2/COMMON/ngap_messages_types.h index b5fb021305..2ad2db97bd 100644 --- a/openair2/COMMON/ngap_messages_types.h +++ b/openair2/COMMON/ngap_messages_types.h @@ -248,10 +248,9 @@ typedef struct pdusession_setup_s { /* The transport layer address for the IP packets */ uint8_t pdu_session_type; - transport_layer_addr_t gNB_addr; - /* Incoming NG-U Tunnel Endpoint Identifier (S-GW/UPF) */ - uint32_t gtp_teid; + // NG-U (N3) Tunnel Endpoint on the RAN side + gtpu_tunnel_t n3_outgoing; /* qos flow list number */ uint8_t nb_of_qos_flow; diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index 351392de95..9f9a307423 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -467,6 +467,15 @@ int rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, instance_t return 0; } +static gtpu_tunnel_t cp_gtp_tunnel(const gtpu_tunnel_t in) +{ + gtpu_tunnel_t out = {0}; + out.teid = in.teid; + out.addr.length = in.addr.length; + memcpy(out.addr.buffer, in.addr.buffer, out.addr.length); + return out; +} + void rrc_gNB_send_NGAP_INITIAL_CONTEXT_SETUP_RESP(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE) { MessageDef *msg_p = NULL; @@ -482,11 +491,7 @@ void rrc_gNB_send_NGAP_INITIAL_CONTEXT_SETUP_RESP(gNB_RRC_INST *rrc, gNB_RRC_UE_ if (session->status == PDU_SESSION_STATUS_DONE) { pdu_sessions_done++; resp->pdusessions[pdusession].pdusession_id = session->param.pdusession_id; - resp->pdusessions[pdusession].gtp_teid = session->param.n3_outgoing.teid; - memcpy(resp->pdusessions[pdusession].gNB_addr.buffer, - session->param.n3_outgoing.addr.buffer, - sizeof(resp->pdusessions[pdusession].gNB_addr.buffer)); - resp->pdusessions[pdusession].gNB_addr.length = 4; // Fixme: IPv4 hard coded here + resp->pdusessions[pdusession].n3_outgoing = cp_gtp_tunnel(session->param.n3_outgoing); resp->pdusessions[pdusession].nb_of_qos_flow = session->param.nb_qos; for (int qos_flow_index = 0; qos_flow_index < session->param.nb_qos; qos_flow_index++) { resp->pdusessions[pdusession].associated_qos_flows[qos_flow_index].qfi = session->param.qos[qos_flow_index].qfi; @@ -677,10 +682,9 @@ void rrc_gNB_send_NGAP_PDUSESSION_SETUP_RESP(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE pdusession_setup_t *tmp = &resp->pdusessions[pdu_sessions_done]; tmp->pdusession_id = session->param.pdusession_id; tmp->nb_of_qos_flow = session->param.nb_qos; - tmp->gtp_teid = session->param.n3_outgoing.teid; + tmp->n3_outgoing = cp_gtp_tunnel(session->param.n3_outgoing); tmp->pdu_session_type = session->param.pdu_session_type; - tmp->gNB_addr.length = session->param.n3_outgoing.addr.length; - memcpy(tmp->gNB_addr.buffer, session->param.n3_outgoing.addr.buffer, tmp->gNB_addr.length); + for (int qos_flow_index = 0; qos_flow_index < tmp->nb_of_qos_flow; qos_flow_index++) { tmp->associated_qos_flows[qos_flow_index].qfi = session->param.qos[qos_flow_index].qfi; tmp->associated_qos_flows[qos_flow_index].qos_flow_mapping_ind = QOSFLOW_MAPPING_INDICATION_DL; @@ -695,7 +699,7 @@ void rrc_gNB_send_NGAP_PDUSESSION_SETUP_RESP(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE xid, UE->nb_of_pdusessions, tmp->pdusession_id, - tmp->gtp_teid); + tmp->n3_outgoing.teid); pdu_sessions_done++; } else if (session->status != PDU_SESSION_STATUS_ESTABLISHED) { session->status = PDU_SESSION_STATUS_FAILED; diff --git a/openair3/NGAP/ngap_gNB_nas_procedures.c b/openair3/NGAP/ngap_gNB_nas_procedures.c index 5ae65f1c42..7889d8487c 100644 --- a/openair3/NGAP/ngap_gNB_nas_procedures.c +++ b/openair3/NGAP/ngap_gNB_nas_procedures.c @@ -613,8 +613,8 @@ int ngap_gNB_initial_ctxt_resp(instance_t instance, ngap_initial_context_setup_r pdusessionTransfer.dLQosFlowPerTNLInformation.uPTransportLayerInformation.present = NGAP_UPTransportLayerInformation_PR_gTPTunnel; asn1cCalloc(pdusessionTransfer.dLQosFlowPerTNLInformation.uPTransportLayerInformation.choice.gTPTunnel, tmp); - GTP_TEID_TO_ASN1(initial_ctxt_resp_p->pdusessions[i].gtp_teid, &tmp->gTP_TEID); - tnl_to_bitstring(&tmp->transportLayerAddress, initial_ctxt_resp_p->pdusessions[i].gNB_addr); + GTP_TEID_TO_ASN1(initial_ctxt_resp_p->pdusessions[i].n3_outgoing.teid, &tmp->gTP_TEID); + tnl_to_bitstring(&tmp->transportLayerAddress, initial_ctxt_resp_p->pdusessions[i].n3_outgoing.addr); NGAP_DEBUG("initial_ctxt_resp_p: pdusession ID %ld, gnb_addr %d.%d.%d.%d, SIZE %ld, TEID %u\n", item->pDUSessionID, @@ -623,7 +623,7 @@ int ngap_gNB_initial_ctxt_resp(instance_t instance, ngap_initial_context_setup_r tmp->transportLayerAddress.buf[2], tmp->transportLayerAddress.buf[3], tmp->transportLayerAddress.size, - initial_ctxt_resp_p->pdusessions[i].gtp_teid); + initial_ctxt_resp_p->pdusessions[i].n3_outgoing.teid); /* associatedQosFlowList. number of 1? */ for(int j=0; j < initial_ctxt_resp_p->pdusessions[i].nb_of_qos_flow; j++) { @@ -928,8 +928,8 @@ int ngap_gNB_pdusession_setup_resp(instance_t instance, ngap_pdusession_setup_re NGAP_PDUSessionResourceSetupResponseTransfer_t pdusessionTransfer = {0}; pdusessionTransfer.dLQosFlowPerTNLInformation.uPTransportLayerInformation.present = NGAP_UPTransportLayerInformation_PR_gTPTunnel; asn1cCalloc(pdusessionTransfer.dLQosFlowPerTNLInformation.uPTransportLayerInformation.choice.gTPTunnel, tmp); - GTP_TEID_TO_ASN1(pdusession->gtp_teid, &tmp->gTP_TEID); - tnl_to_bitstring(&tmp->transportLayerAddress, pdusession->gNB_addr); + GTP_TEID_TO_ASN1(pdusession->n3_outgoing.teid, &tmp->gTP_TEID); + tnl_to_bitstring(&tmp->transportLayerAddress, pdusession->n3_outgoing.addr); NGAP_DEBUG("pdusession_setup_resp_p: pdusession ID %ld, gnb_addr %d.%d.%d.%d, SIZE %ld, TEID %u\n", item->pDUSessionID, tmp->transportLayerAddress.buf[0], @@ -937,7 +937,7 @@ int ngap_gNB_pdusession_setup_resp(instance_t instance, ngap_pdusession_setup_re tmp->transportLayerAddress.buf[2], tmp->transportLayerAddress.buf[3], tmp->transportLayerAddress.size, - pdusession->gtp_teid); + pdusession->n3_outgoing.teid); /* associatedQosFlowList. number of 1? */ for(int j=0; j < pdusession_setup_resp_p->pdusessions[i].nb_of_qos_flow; j++) { asn1cSequenceAdd(pdusessionTransfer.dLQosFlowPerTNLInformation.associatedQosFlowList.list, NGAP_AssociatedQosFlowItem_t, ass_qos_item_p); From b5a717cc995b9a4dce9f46d4317e9aae3468386e Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 14 May 2025 13:49:18 +0200 Subject: [PATCH 053/964] Add encoder for PDU Session Resource Setup Response Transfer IE in NGAP (Initial Context/PDU Session) Setup Response --- openair3/NGAP/ngap_gNB_nas_procedures.c | 117 ++++++++++-------------- 1 file changed, 50 insertions(+), 67 deletions(-) diff --git a/openair3/NGAP/ngap_gNB_nas_procedures.c b/openair3/NGAP/ngap_gNB_nas_procedures.c index 7889d8487c..1aafeca8c9 100644 --- a/openair3/NGAP/ngap_gNB_nas_procedures.c +++ b/openair3/NGAP/ngap_gNB_nas_procedures.c @@ -35,6 +35,7 @@ #include #include #include +#include #include "BIT_STRING.h" #include "INTEGER.h" #include "ngap_msg_includes.h" @@ -57,6 +58,7 @@ #include "oai_asn1.h" #include "s1ap_messages_types.h" #include "xer_encoder.h" +#include "ds/byte_array.h" /** @brief Selects the AMF instance for a given UE based on identity information. * It attempts to select an AMF using the following prioritized criteria: @@ -537,6 +539,46 @@ int ngap_gNB_nas_non_delivery_ind(instance_t instance, return 0; } +/** @brief PDU Session Resource Setup Response Transfer encoding (9.3.4.2 3GPP TS 38.413) */ +static byte_array_t encode_ngap_pdusession_setup_response_transfer(const pdusession_setup_t *pdusession) +{ + NGAP_PDUSessionResourceSetupResponseTransfer_t pdusessionTransfer = {0}; + byte_array_t out = {0}; + + // DL QoS Flow per TNL Information (Mandatory) + NGAP_QosFlowPerTNLInformation_t *dLQosFlowPerTNLInformation = &pdusessionTransfer.dLQosFlowPerTNLInformation; + + // UP Transport Layer Information (Mandatory) + dLQosFlowPerTNLInformation->uPTransportLayerInformation.present = NGAP_UPTransportLayerInformation_PR_gTPTunnel; + asn1cCalloc(dLQosFlowPerTNLInformation->uPTransportLayerInformation.choice.gTPTunnel, gtp); + GTP_TEID_TO_ASN1(pdusession->n3_outgoing.teid, >p->gTP_TEID); + tnl_to_bitstring(>p->transportLayerAddress, pdusession->n3_outgoing.addr); + char ip_str[INET_ADDRSTRLEN] = {0}; + inet_ntop(AF_INET, gtp->transportLayerAddress.buf, ip_str, sizeof(ip_str)); + NGAP_DEBUG("Encoded PDU Session Transfer (%d): TEID=0x%08x, Addr=%s\n", + pdusession->pdusession_id, + pdusession->n3_outgoing.teid, + ip_str); + + // Associated QoS Flow List (Mandatory) + for (int j = 0; j < pdusession->nb_of_qos_flow; j++) { + asn1cSequenceAdd(dLQosFlowPerTNLInformation->associatedQosFlowList.list, NGAP_AssociatedQosFlowItem_t, qos_item); + // QoS Flow Identifier (Mandatory) + qos_item->qosFlowIdentifier = pdusession->associated_qos_flows[j].qfi; + } + + // Encode + asn_encode_to_new_buffer_result_t res = asn_encode_to_new_buffer(NULL, + ATS_ALIGNED_CANONICAL_PER, + &asn_DEF_NGAP_PDUSessionResourceSetupResponseTransfer, + &pdusessionTransfer); + AssertFatal(res.buffer, "ASN1 message encoding failed (%s, %lu)!\n", res.result.failed_type->name, res.result.encoded); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_PDUSessionResourceSetupResponseTransfer, &pdusessionTransfer); + out.buf = res.buffer; + out.len = res.result.encoded; + return out; +} + //------------------------------------------------------------------------------ int ngap_gNB_initial_ctxt_resp(instance_t instance, ngap_initial_context_setup_resp_t *initial_ctxt_resp_p) //------------------------------------------------------------------------------ @@ -606,39 +648,10 @@ int ngap_gNB_initial_ctxt_resp(instance_t instance, ngap_initial_context_setup_r asn1cSequenceAdd(ie->value.choice.PDUSessionResourceSetupListCxtRes.list, NGAP_PDUSessionResourceSetupItemCxtRes_t, item); /* pDUSessionID */ item->pDUSessionID = initial_ctxt_resp_p->pdusessions[i].pdusession_id; - - /* dLQosFlowPerTNLInformation */ - NGAP_PDUSessionResourceSetupResponseTransfer_t pdusessionTransfer = {0}; - - pdusessionTransfer.dLQosFlowPerTNLInformation.uPTransportLayerInformation.present = NGAP_UPTransportLayerInformation_PR_gTPTunnel; - - asn1cCalloc(pdusessionTransfer.dLQosFlowPerTNLInformation.uPTransportLayerInformation.choice.gTPTunnel, tmp); - GTP_TEID_TO_ASN1(initial_ctxt_resp_p->pdusessions[i].n3_outgoing.teid, &tmp->gTP_TEID); - tnl_to_bitstring(&tmp->transportLayerAddress, initial_ctxt_resp_p->pdusessions[i].n3_outgoing.addr); - - NGAP_DEBUG("initial_ctxt_resp_p: pdusession ID %ld, gnb_addr %d.%d.%d.%d, SIZE %ld, TEID %u\n", - item->pDUSessionID, - tmp->transportLayerAddress.buf[0], - tmp->transportLayerAddress.buf[1], - tmp->transportLayerAddress.buf[2], - tmp->transportLayerAddress.buf[3], - tmp->transportLayerAddress.size, - initial_ctxt_resp_p->pdusessions[i].n3_outgoing.teid); - - /* associatedQosFlowList. number of 1? */ - for(int j=0; j < initial_ctxt_resp_p->pdusessions[i].nb_of_qos_flow; j++) { - asn1cSequenceAdd(pdusessionTransfer.dLQosFlowPerTNLInformation.associatedQosFlowList.list, NGAP_AssociatedQosFlowItem_t, ass_qos_item_p); - /* qosFlowIdentifier */ - ass_qos_item_p->qosFlowIdentifier = initial_ctxt_resp_p->pdusessions[i].associated_qos_flows[j].qfi; - } - - void *pdusessionTransfer_buffer; - ssize_t encoded = aper_encode_to_new_buffer(&asn_DEF_NGAP_PDUSessionResourceSetupResponseTransfer, NULL, &pdusessionTransfer, &pdusessionTransfer_buffer); - AssertFatal(encoded > 0, "ASN1 message encoding failed !\n"); - item->pDUSessionResourceSetupResponseTransfer.buf = pdusessionTransfer_buffer; - item->pDUSessionResourceSetupResponseTransfer.size = encoded; - - ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_PDUSessionResourceSetupResponseTransfer, &pdusessionTransfer); + // PDU Session Resource Setup Response Transfer (Mandatory) + byte_array_t ba = encode_ngap_pdusession_setup_response_transfer(&initial_ctxt_resp_p->pdusessions[i]); + item->pDUSessionResourceSetupResponseTransfer.buf = ba.buf; + item->pDUSessionResourceSetupResponseTransfer.size = ba.len; } } /* optional */ @@ -924,40 +937,10 @@ int ngap_gNB_pdusession_setup_resp(instance_t instance, ngap_pdusession_setup_re /* pDUSessionID */ item->pDUSessionID = pdusession->pdusession_id; - /* dLQosFlowPerTNLInformation */ - NGAP_PDUSessionResourceSetupResponseTransfer_t pdusessionTransfer = {0}; - pdusessionTransfer.dLQosFlowPerTNLInformation.uPTransportLayerInformation.present = NGAP_UPTransportLayerInformation_PR_gTPTunnel; - asn1cCalloc(pdusessionTransfer.dLQosFlowPerTNLInformation.uPTransportLayerInformation.choice.gTPTunnel, tmp); - GTP_TEID_TO_ASN1(pdusession->n3_outgoing.teid, &tmp->gTP_TEID); - tnl_to_bitstring(&tmp->transportLayerAddress, pdusession->n3_outgoing.addr); - NGAP_DEBUG("pdusession_setup_resp_p: pdusession ID %ld, gnb_addr %d.%d.%d.%d, SIZE %ld, TEID %u\n", - item->pDUSessionID, - tmp->transportLayerAddress.buf[0], - tmp->transportLayerAddress.buf[1], - tmp->transportLayerAddress.buf[2], - tmp->transportLayerAddress.buf[3], - tmp->transportLayerAddress.size, - pdusession->n3_outgoing.teid); - /* associatedQosFlowList. number of 1? */ - for(int j=0; j < pdusession_setup_resp_p->pdusessions[i].nb_of_qos_flow; j++) { - asn1cSequenceAdd(pdusessionTransfer.dLQosFlowPerTNLInformation.associatedQosFlowList.list, NGAP_AssociatedQosFlowItem_t, ass_qos_item_p); - - /* qosFlowIdentifier */ - ass_qos_item_p->qosFlowIdentifier = pdusession_setup_resp_p->pdusessions[i].associated_qos_flows[j].qfi; - - /* qosFlowMappingIndication */ - // if(pdusession_setup_resp_p->pdusessions[i].associated_qos_flows[j].qos_flow_mapping_ind != QOSFLOW_MAPPING_INDICATION_NON) { - // ass_qos_item_p->qosFlowMappingIndication = malloc(sizeof(*ass_qos_item_p->qosFlowMappingIndication)); - // *ass_qos_item_p->qosFlowMappingIndication = pdusession_setup_resp_p->pdusessions[i].associated_qos_flows[j].qos_flow_mapping_ind; - // } - } - - asn_encode_to_new_buffer_result_t res = asn_encode_to_new_buffer(NULL, ATS_ALIGNED_CANONICAL_PER, &asn_DEF_NGAP_PDUSessionResourceSetupResponseTransfer, &pdusessionTransfer); - AssertFatal (res.buffer, "ASN1 message encoding failed (%s, %lu)!\n", res.result.failed_type->name, res.result.encoded); - item->pDUSessionResourceSetupResponseTransfer.buf = res.buffer; - item->pDUSessionResourceSetupResponseTransfer.size = res.result.encoded; - - ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_PDUSessionResourceSetupResponseTransfer, &pdusessionTransfer); + // PDU Session Resource Setup Response Transfer (Mandatory) + byte_array_t ba = encode_ngap_pdusession_setup_response_transfer(pdusession); + item->pDUSessionResourceSetupResponseTransfer.buf = ba.buf; + item->pDUSessionResourceSetupResponseTransfer.size = ba.len; } } From 7d0640ebcb391bee034737d8d204cfbfa5a9e026 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 14 May 2025 16:52:43 +0200 Subject: [PATCH 054/964] Improve PDU Session GTP tunnels logging --- openair2/RRC/NR/rrc_gNB_NGAP.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index 9f9a307423..72aad97750 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -36,6 +36,7 @@ #include #include #include +#include #include "E1AP_ConfidentialityProtectionIndication.h" #include "E1AP_IntegrityProtectionIndication.h" #include "NGAP_CauseRadioNetwork.h" @@ -266,7 +267,6 @@ bool trigger_bearer_setup(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, pdusession for (int i = 0; i < n; i++) { rrc_pdu_session_param_t *pduSession = find_pduSession(UE, sessions[i].pdusession_id, true); pdusession_t *session = &pduSession->param; - LOG_I(NR_RRC, "Adding pdusession %d, total nb of sessions %d\n", session->pdusession_id, UE->nb_of_pdusessions); cp_pdusession(session, &sessions[i]); bearer_req.gNB_cu_cp_ue_id = UE->rrc_ue_id; security_information_t *secInfo = &bearer_req.secInfo; @@ -287,8 +287,12 @@ bool trigger_bearer_setup(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, pdusession : SECURITY_NOT_NEEDED; sec->confidentialityProtectionIndication = rrc->security.do_drb_ciphering ? SECURITY_REQUIRED : SECURITY_NOT_NEEDED; - pdu->UP_TL_information.teId = session->n3_incoming.teid; - memcpy(&pdu->UP_TL_information.tlAddress, session->n3_incoming.addr.buffer, sizeof(in_addr_t)); + gtpu_tunnel_t *n3_incoming = &session->n3_incoming; + pdu->UP_TL_information.teId = n3_incoming->teid; + memcpy(&pdu->UP_TL_information.tlAddress, n3_incoming->addr.buffer, sizeof(in_addr_t)); + char ip_str[INET_ADDRSTRLEN] = {0}; + inet_ntop(AF_INET, n3_incoming->addr.buffer, ip_str, sizeof(ip_str)); + LOG_I(NR_RRC, "Bearer Context Setup: PDU Session ID=%d, incoming TEID=0x%08x, Addr=%s\n", session->pdusession_id, n3_incoming->teid, ip_str); /* we assume for the moment one DRB per PDU session. Activate the bearer, * and configure in RRC. */ @@ -691,15 +695,9 @@ void rrc_gNB_send_NGAP_PDUSESSION_SETUP_RESP(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE } session->status = PDU_SESSION_STATUS_ESTABLISHED; - LOG_I(NR_RRC, - "msg index %d, pdu_sessions index %d, status %d, xid %d): nb_of_pdusessions %d, pdusession_id %d, teid: %u \n ", - pdu_sessions_done, - pdusession, - session->status, - xid, - UE->nb_of_pdusessions, - tmp->pdusession_id, - tmp->n3_outgoing.teid); + char ip_str[INET_ADDRSTRLEN] = {0}; + inet_ntop(AF_INET, tmp->n3_outgoing.addr.buffer, ip_str, sizeof(ip_str)); + LOG_I(NR_RRC, "PDU Session Setup Response: ID=%d, outgoing TEID=0x%08x, Addr=%s\n", tmp->pdusession_id, tmp->n3_outgoing.teid, ip_str); pdu_sessions_done++; } else if (session->status != PDU_SESSION_STATUS_ESTABLISHED) { session->status = PDU_SESSION_STATUS_FAILED; From 122ff99b49fcac20a6eb4ecafbca9ece61e7d2d1 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 4 Jun 2025 13:12:26 +0200 Subject: [PATCH 055/964] Use f1u_gtp_update in rrc_gNB_process_e1_bearer_context_setup_resp --- openair2/RRC/NR/rrc_gNB.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index cda981ee34..e5513fdbdc 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -2449,9 +2449,7 @@ void rrc_gNB_process_e1_bearer_context_setup_resp(e1ap_bearer_setup_resp_t *resp LOG_W(RRC, "E1: received setup for PDU session %ld, but has not been requested\n", e1_pdu->id); continue; } - rrc_pdu->param.n3_outgoing.teid = e1_pdu->tl_info.teId; - memcpy(&rrc_pdu->param.n3_outgoing.addr.buffer, &e1_pdu->tl_info.tlAddress, sizeof(uint8_t) * 4); - rrc_pdu->param.n3_outgoing.addr.length = sizeof(in_addr_t); + rrc_pdu->param.n3_outgoing = f1u_gtp_update(e1_pdu->tl_info.teId, e1_pdu->tl_info.tlAddress); // save the tunnel address for the DRBs for (int i = 0; i < e1_pdu->numDRBSetup; i++) { From 833edb3b25077947aa4e9c0eff78fcdef933b64b Mon Sep 17 00:00:00 2001 From: Reem Bahsoun Date: Wed, 18 Jun 2025 09:57:33 +0200 Subject: [PATCH 056/964] Hard code the name of nvIPC file when called in the cls_containerize.py script - This is to avoid the Docker image builder from being confused in case we have multiple nvIPC files in `/opt/nvidia-ipc` - This occurs when we have an MR to upgrade the cuBB image --- ci-scripts/cls_containerize.py | 4 ++-- docker/Dockerfile.gNB.aerial.ubuntu22 | 2 +- docker/Dockerfile.gNB.aerial.ubuntu22.sanitize-address | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index f3d30d6170..817555554d 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -498,10 +498,10 @@ class Containerize(): elif image != 'ran-build': cmd.run(f'sed -i -e "s#ran-build:latest#ran-build:{imageTag}#" docker/Dockerfile.{pattern}{self.dockerfileprefix}') if image == 'oai-gnb-aerial': - cmd.run('cp -f /opt/nvidia-ipc/nvipc_src.*.tar.gz .') + cmd.run('cp -f /opt/nvidia-ipc/nvipc.src.2025.05.20.tar.gz .') ret = cmd.run(f'{self.cli} build {self.cliBuildOptions} --target {image} --tag {name}:{imageTag} --file docker/Dockerfile.{pattern}{self.dockerfileprefix} {option} . > cmake_targets/log/{name}.log 2>&1', timeout=1200) if image == 'oai-gnb-aerial': - cmd.run('rm -f nvipc_src.*.tar.gz') + cmd.run('rm -f nvipc.src.2025.05.20.tar.gz') if image == 'ran-build' and ret.returncode == 0: cmd.run(f"docker run --name test-log -d {name}:{imageTag} /bin/true") cmd.run(f"docker cp test-log:/oai-ran/cmake_targets/log/ cmake_targets/log/{name}/") diff --git a/docker/Dockerfile.gNB.aerial.ubuntu22 b/docker/Dockerfile.gNB.aerial.ubuntu22 index c5b090f551..07bc569586 100644 --- a/docker/Dockerfile.gNB.aerial.ubuntu22 +++ b/docker/Dockerfile.gNB.aerial.ubuntu22 @@ -45,7 +45,7 @@ WORKDIR /oai-ran COPY . . RUN /bin/sh oaienv && \ - tar -xvzf nvipc_src.*.tar.gz && \ + tar -xvzf nvipc* && \ cd nvipc_src.* && \ rm -rf build && mkdir build && cd build && \ cmake .. -DNVIPC_DPDK_ENABLE=OFF -DNVIPC_DOCA_ENABLE=OFF -DNVIPC_CUDA_ENABLE=OFF -DENABLE_SLT_RSP=ON && \ diff --git a/docker/Dockerfile.gNB.aerial.ubuntu22.sanitize-address b/docker/Dockerfile.gNB.aerial.ubuntu22.sanitize-address index 4d613718b4..c8d35aee55 100644 --- a/docker/Dockerfile.gNB.aerial.ubuntu22.sanitize-address +++ b/docker/Dockerfile.gNB.aerial.ubuntu22.sanitize-address @@ -45,7 +45,7 @@ WORKDIR /oai-ran COPY . . RUN /bin/sh oaienv && \ - tar -xvzf nvipc_src.*.tar.gz && \ + tar -xvzf nvipc* && \ cd nvipc_src.* && \ rm -rf build && mkdir build && cd build && \ cmake .. -DNVIPC_DPDK_ENABLE=OFF -DNVIPC_DOCA_ENABLE=OFF -DNVIPC_CUDA_ENABLE=OFF -DENABLE_SLT_RSP=ON && \ From 5445b12c32474e458d722af737ad23cb407e2697 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Thu, 10 Apr 2025 17:21:37 +0200 Subject: [PATCH 057/964] Add enc/dec function for EAP Message Also, add EAP message (optional) enc-dec to Service Reject lib --- openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_lib.c | 74 +++++++++++++++++-- openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_lib.h | 3 +- .../NR_UE/5GS/5GMM/MSG/fgmm_service_accept.c | 2 +- .../NR_UE/5GS/5GMM/MSG/fgmm_service_accept.h | 3 + .../NR_UE/5GS/5GMM/MSG/fgmm_service_reject.c | 7 +- .../NR_UE/5GS/5GMM/MSG/fgmm_service_reject.h | 2 + 6 files changed, 83 insertions(+), 8 deletions(-) diff --git a/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_lib.c b/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_lib.c index 1b607589d9..e53e3a2993 100644 --- a/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_lib.c +++ b/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_lib.c @@ -25,8 +25,12 @@ #include // For malloc and free #include "common/utils/ds/byte_array.h" +#define IEI_LEN 1 #define GPRS_TIMER_LENGTH 3 // octets #define FGS_NAS_CAUSE_LENGTH 1 +#define MIN_EAP_MSG_LEN 7 +#define MIN_EAP_CONTENTS_LEN 4 +#define MAX_EAP_CONTENTS_LEN 1500 /** * Encode PDU Session Status and PDU session reactivation result (optional IEs) @@ -152,12 +156,72 @@ bool eq_gprs_timer(const gprs_timer_t *a, const gprs_timer_t *b) return true; } -/* Decode EAP Message (todo) */ -int decode_eap_msg_ie(const byte_array_t *buffer) +/** @brief Encode EAP message IE (3GPP TS 24.501 9.11.2.2) */ +int encode_eap_msg_ie(byte_array_t *buffer, const byte_array_t *msg) { - int eap_msg_len = (buffer->buf[0] << 8) | buffer->buf[1]; - PRINT_NAS_ERROR("EAP message IE in NAS Service Reject is not handled\n"); - return eap_msg_len + 2; // content length + 2 octets for the length IE + int encoded = 0; + + // Sanity check on buffer length + if (buffer->len < MIN_EAP_MSG_LEN) { + PRINT_NAS_ERROR("Invalid buffer length %ld", buffer->len); + return -1; + } + + // Sanity check on input length + if (msg->len < MIN_EAP_CONTENTS_LEN || msg->len > MAX_EAP_CONTENTS_LEN) { + PRINT_NAS_ERROR("Invalid EAP message length %ld", msg->len); + return -1; + } + + // Encode IEI + buffer->buf[encoded++] = IEI_EAPMSG; + + // Encode length of EAP message content + uint16_t len = htons(msg->len); + memcpy(&buffer->buf[encoded], &len, sizeof(len)); + encoded += sizeof(len); + + // Encode EAP message content + memcpy(&buffer->buf[encoded], msg->buf, msg->len); + encoded += msg->len; + + return encoded; +} + +/** @brief Decode EAP message IE (3GPP TS 24.501 9.11.2.2): + length of contents and message payload */ +int decode_eap_msg_ie(byte_array_t *eap_msg, const byte_array_t *buffer) +{ + int decoded = 0; + int min_len_to_decode = MIN_EAP_MSG_LEN - IEI_LEN; + + // Check buffer length validity + if (buffer->len < min_len_to_decode) { + PRINT_NAS_ERROR("Invalid buffer for decoding EAP message IE"); + return -1; + } + + // Decode length IE + eap_msg->len = (buffer->buf[decoded] << 8) | buffer->buf[decoded + 1]; + decoded += 2; + + // Check payload length validity + if (eap_msg->len < MIN_EAP_CONTENTS_LEN || eap_msg->len > MAX_EAP_CONTENTS_LEN) { + PRINT_NAS_ERROR("Invalid EAP message length %ld", eap_msg->len); + return -1; + } + + // Check for buffer overflow + if (buffer->len < decoded + eap_msg->len) { + PRINT_NAS_ERROR("Buffer too short for EAP message: %ld < %ld", buffer->len, decoded + eap_msg->len); + return -1; + } + + // Copy EAP payload + memcpy(eap_msg->buf, &buffer->buf[decoded], eap_msg->len); + decoded += eap_msg->len; + + return decoded; } int encode_fgs_nas_cause(byte_array_t *buffer, const cause_id_t *cause) diff --git a/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_lib.h b/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_lib.h index 25118f2742..7a4e1da857 100644 --- a/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_lib.h +++ b/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_lib.h @@ -164,7 +164,8 @@ int decode_pdu_session_ie(uint8_t *psi, const byte_array_t *buffer); int encode_gprs_timer_ie(byte_array_t *buffer, nas_service_IEI_t iei, const gprs_timer_t *timer); int decode_gprs_timer_ie(gprs_timer_t *timer, const byte_array_t *buffer); bool eq_gprs_timer(const gprs_timer_t *a, const gprs_timer_t *b); -int decode_eap_msg_ie(const byte_array_t *buffer); +int decode_eap_msg_ie(byte_array_t *eap_msg, const byte_array_t *buffer); +int encode_eap_msg_ie(byte_array_t *buffer, const byte_array_t *msg); int encode_fgs_nas_cause(byte_array_t *buffer, const cause_id_t *cause); int decode_fgs_nas_cause(cause_id_t *cause, const byte_array_t *buffer); diff --git a/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_service_accept.c b/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_service_accept.c index 797deede84..63e2901f61 100644 --- a/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_service_accept.c +++ b/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_service_accept.c @@ -133,7 +133,7 @@ int decode_fgs_service_accept(fgs_service_accept_msg_t *msg, const byte_array_t break; case IEI_EAPMSG: - DECODE_NAS_IE(ba, decode_eap_msg_ie(&ba), decoded); + DECODE_NAS_IE(ba, decode_eap_msg_ie(&msg->eap_msg, &ba), decoded); break; default: diff --git a/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_service_accept.h b/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_service_accept.h index 9f82f47eb1..c5d042b674 100644 --- a/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_service_accept.h +++ b/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_service_accept.h @@ -47,6 +47,9 @@ typedef struct { // T3448 Value (Optional) gprs_timer_t *t3448; + + // EAP Message (Optional) + byte_array_t eap_msg; } fgs_service_accept_msg_t; int decode_fgs_service_accept(fgs_service_accept_msg_t *msg, const byte_array_t *buffer); diff --git a/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_service_reject.c b/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_service_reject.c index 74175fda36..14078637a3 100644 --- a/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_service_reject.c +++ b/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_service_reject.c @@ -59,6 +59,11 @@ int encode_fgs_service_reject(byte_array_t *buffer, const fgs_service_reject_msg ENCODE_NAS_IE(ba, encode_gprs_timer_ie(&ba, IEI_T3448_VALUE, msg->t3448), encoded); } + // EAP message (Optional) + if (msg->eap_msg) { + ENCODE_NAS_IE(ba, encode_eap_msg_ie(&ba, msg->eap_msg), encoded); + } + return encoded; } @@ -99,7 +104,7 @@ int decode_fgs_service_reject(fgs_service_reject_msg_t *msg, const byte_array_t break; case IEI_EAPMSG: - DECODE_NAS_IE(ba, decode_eap_msg_ie((const byte_array_t *)&ba), decoded); + DECODE_NAS_IE(ba, decode_eap_msg_ie(msg->eap_msg, &ba), decoded); break; case IEI_CAG_INFO_LIST: { diff --git a/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_service_reject.h b/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_service_reject.h index 61337d8525..29c8ab9b72 100644 --- a/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_service_reject.h +++ b/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_service_reject.h @@ -35,6 +35,8 @@ typedef struct { bool has_psi_status; // T3448 Value (Optional) gprs_timer_t *t3448; + // EAP message (optional) + byte_array_t *eap_msg; } fgs_service_reject_msg_t; int decode_fgs_service_reject(fgs_service_reject_msg_t *msg, const byte_array_t *buffer); From 299ce4a9bd247984df5fe578eaa92d264bb86002 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Fri, 15 Nov 2024 22:44:56 +0100 Subject: [PATCH 058/964] Add enc/dec lib for NAS Authentication Reject and unit test --- .../NAS/NR_UE/5GS/5GMM/MSG/CMakeLists.txt | 1 + .../5GS/5GMM/MSG/fgmm_authentication_reject.c | 69 +++++++++++++++++++ .../5GS/5GMM/MSG/fgmm_authentication_reject.h | 38 ++++++++++ openair3/NAS/NR_UE/5GS/tests/nas_lib_test.c | 40 +++++++++++ 4 files changed, 148 insertions(+) create mode 100644 openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_authentication_reject.c create mode 100644 openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_authentication_reject.h diff --git a/openair3/NAS/NR_UE/5GS/5GMM/MSG/CMakeLists.txt b/openair3/NAS/NR_UE/5GS/5GMM/MSG/CMakeLists.txt index 0f4445c353..7aafc588e2 100644 --- a/openair3/NAS/NR_UE/5GS/5GMM/MSG/CMakeLists.txt +++ b/openair3/NAS/NR_UE/5GS/5GMM/MSG/CMakeLists.txt @@ -14,6 +14,7 @@ add_library(fgs_5gmm_lib OBJECT FGSUplinkNasTransport.c FGSDeregistrationRequestUEOriginating.c fgmm_authentication_failure.c + fgmm_authentication_reject.c ) target_link_libraries(fgs_5gmm_lib PUBLIC fgs_5gmm_ies_lib) diff --git a/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_authentication_reject.c b/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_authentication_reject.c new file mode 100644 index 0000000000..193df8f7dd --- /dev/null +++ b/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_authentication_reject.c @@ -0,0 +1,69 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include "fgmm_authentication_reject.h" +#include +#include // For htons and ntohs +#include // For malloc and free +#include "fgmm_lib.h" + +#define MIN_AUTH_REJECT_LEN 3 + +/** @brief Encode Authentication Reject (8.2.5 of 3GPP TS 24.501) */ +int encode_fgmm_auth_reject(byte_array_t *buffer, const fgmm_auth_reject_msg_t *msg) +{ + uint32_t encoded = 0; + + const byte_array_t *eap_msg = &msg->eap_msg; + if (eap_msg->len > 0) { + return encode_eap_msg_ie(buffer, eap_msg); + } + return encoded; +} + +/** @brief Decode Authentication Reject (8.2.5 of 3GPP TS 24.501) + * the message contains only optional IEIs (EAP MSG) */ +int decode_fgmm_auth_reject(fgmm_auth_reject_msg_t *msg, const byte_array_t *buffer) +{ + if (buffer->len < MIN_AUTH_REJECT_LEN) { + // No optional IEIs present + return 0; + } + byte_array_t ba = *buffer; // Local copy of buffer + uint32_t decoded = 0; + // Decode the IEI + uint8_t iei = buffer->buf[decoded++]; + UPDATE_BYTE_ARRAY(ba, decoded); + if (iei == IEI_EAPMSG) { + return (decoded + decode_eap_msg_ie(&msg->eap_msg, &ba)); + } + PRINT_NAS_ERROR("Expected EAP MSG but it is not present"); + return -1; +} + +bool eq_auth_reject(fgmm_auth_reject_msg_t *a, fgmm_auth_reject_msg_t *b) +{ + _NAS_EQ_CHECK_LONG(a->eap_msg.len, b->eap_msg.len); + if (a->eap_msg.len > 0) { + return !memcmp(a->eap_msg.buf, b->eap_msg.buf, a->eap_msg.len); + } + return true; +} diff --git a/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_authentication_reject.h b/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_authentication_reject.h new file mode 100644 index 0000000000..33ae7a5181 --- /dev/null +++ b/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_authentication_reject.h @@ -0,0 +1,38 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef FGMM_AUTH_REJECT_H +#define FGMM_AUTH_REJECT_H + +#include +#include "fgmm_lib.h" +#include "common/utils/ds/byte_array.h" + +typedef struct { + // EAP Message (Optional) + byte_array_t eap_msg; +} fgmm_auth_reject_msg_t; + +int decode_fgmm_auth_reject(fgmm_auth_reject_msg_t *msg, const byte_array_t *buffer); +int encode_fgmm_auth_reject(byte_array_t *buffer, const fgmm_auth_reject_msg_t *msg); +bool eq_auth_reject(fgmm_auth_reject_msg_t *a, fgmm_auth_reject_msg_t *b); + +#endif /* FGMM_AUTH_REJECT_H */ diff --git a/openair3/NAS/NR_UE/5GS/tests/nas_lib_test.c b/openair3/NAS/NR_UE/5GS/tests/nas_lib_test.c index f733bdd3a5..d9f837d6b0 100644 --- a/openair3/NAS/NR_UE/5GS/tests/nas_lib_test.c +++ b/openair3/NAS/NR_UE/5GS/tests/nas_lib_test.c @@ -9,6 +9,7 @@ #include "fgmm_service_reject.h" #include "fgmm_authentication_failure.h" #include "FGSNASSecurityModeReject.h" +#include "fgmm_authentication_reject.h" #include "nr_nas_msg.h" void exit_function(const char *file, const char *function, const int line, const char *s, const int assert) @@ -298,6 +299,44 @@ static void test_security_mode_reject(void) AssertFatal(eq_sec_mode_reject(&orig, &dec), "test_sec_mode_reject() failed: original and decoded messages do not match\n"); } +/** + * @brief Test NAS Authentication Reject enc/dec + */ +static void test_auth_reject(void) +{ + // Dummy NAS Authentication Reject message + uint8_t dummy_eap_msg[] = {0x12, 0x34, 0x56, 0x78, 0x91, 0x01, 0x23}; // Example EAP message + fgmm_auth_reject_msg_t orig = { + .eap_msg.len = sizeof(dummy_eap_msg), + }; + orig.eap_msg.buf = dummy_eap_msg; + + // Expected encoded data + uint8_t expected_enc[] = {0x78, 0x00, 0x07, 0x12, 0x34, 0x56, 0x78, 0x91, 0x01, 0x23}; + + // Buffer + uint8_t buf[10] = {0}; + byte_array_t buffer = {.buf = buf, .len = sizeof(buf)}; + + // Encode + int encoded_length = encode_fgmm_auth_reject(&buffer, &orig); + AssertFatal(encoded_length >= 0, "encode_fgmm_auth_reject() failed\n"); + + // Compare the raw encoded buffer with expected encoded data + AssertFatal(encoded_length == sizeof(expected_enc), "Encoded length mismatch %d != %ld \n", encoded_length, sizeof(expected_enc)); + AssertFatal(memcmp(buffer.buf, expected_enc, encoded_length) == 0, "Encoding mismatch!\n"); + + // Decode + fgmm_auth_reject_msg_t dec = {0}; + uint8_t eap_msg[1500] = {0}; + dec.eap_msg.buf = eap_msg; + int decoded_length = decode_fgmm_auth_reject(&dec, &buffer); + AssertFatal(decoded_length >= 0, "decode_fgmm_auth_reject() failed\n"); + + // Compare original and decoded messages + AssertFatal(eq_auth_reject(&orig, &dec), "test_auth_reject() failed: original and decoded messages do not match\n"); +} + int main() { test_regression_registration_accept(); @@ -305,6 +344,7 @@ int main() test_service_accept(); test_service_reject(); test_auth_failure(); + test_auth_reject(); test_security_mode_reject(); return 0; } From 88f294bed10cbd3b7ef925622207f38ea09ddd72 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Thu, 10 Apr 2025 16:04:50 +0200 Subject: [PATCH 059/964] Handle NAS Authentication Reject in stack Handle authentication not accepted by the network. The handler assumes the message is not integrity protected, processes the received NAS message and logs whether a EAP-failure is enclosed. The UE enters state: 5GMM-DEREGISTERED. Not done in this commit: the UE shall performs actions as per 5.4.1.3.5 of 3GPP TS 24.501, including (1) Abort any ongoing 5GMM procedure (2) Stop all active timers: T3510, T3516, T3517, T3519, T3520, T3521 (3) Delete stored SUCI. (4) handle EAP-failure message. --- openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_lib.c | 1 - openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_lib.h | 1 + openair3/NAS/NR_UE/nr_nas_msg.c | 31 ++++++++++++++++++++++ openair3/SECU/key_nas_deriver.c | 2 +- openair3/SECU/key_nas_deriver.h | 2 ++ 5 files changed, 35 insertions(+), 2 deletions(-) diff --git a/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_lib.c b/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_lib.c index e53e3a2993..63c6ec0d32 100644 --- a/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_lib.c +++ b/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_lib.c @@ -30,7 +30,6 @@ #define FGS_NAS_CAUSE_LENGTH 1 #define MIN_EAP_MSG_LEN 7 #define MIN_EAP_CONTENTS_LEN 4 -#define MAX_EAP_CONTENTS_LEN 1500 /** * Encode PDU Session Status and PDU session reactivation result (optional IEs) diff --git a/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_lib.h b/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_lib.h index 7a4e1da857..8d833e74aa 100644 --- a/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_lib.h +++ b/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_lib.h @@ -39,6 +39,7 @@ both PDU Session Status and PDU session Reactivation Result IEs */ #define MAX_PDU_SESSION_CONTENTS_LEN 32 #define MAX_NUM_PSI 16 #define MAX_NUM_PDU_ERRORS 256 +#define MAX_EAP_CONTENTS_LEN 1500 /* This macro updates the local copy of a byte_array_t pointer used for enc/dec */ diff --git a/openair3/NAS/NR_UE/nr_nas_msg.c b/openair3/NAS/NR_UE/nr_nas_msg.c index 5709d482c6..6e4a9b55a4 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg.c +++ b/openair3/NAS/NR_UE/nr_nas_msg.c @@ -70,6 +70,7 @@ #include "fgs_nas_utils.h" #include "fgmm_service_accept.h" #include "fgmm_service_reject.h" +#include "fgmm_authentication_reject.h" #include "ds/byte_array.h" #include "key_nas_deriver.h" @@ -1062,6 +1063,33 @@ static void handle_fgmm_authentication_request(nr_ue_nas_t *nas, as_nas_info_t * generateAuthenticationResp(nas, initialNasMsg, buffer->buf); } +/** @brief Handle authentication not accepted by the network + * This function assumes the message is not integrity protected, processes the received + * NAS message and logs whether a EAP-failure is enclosed. The UE enters state: 5GMM-DEREGISTERED. + * @todo The UE shall performs actions as per 5.4.1.3.5 of 3GPP TS 24.501, including + * (1) Abort any ongoing 5GMM procedure (2) Stop all active timers: T3510, T3516, T3517, + * T3519, T3520, T3521 (3) Delete stored SUCI. (4) handle EAP-failure message. */ +static void handle_authentication_reject(nr_ue_nas_t *nas, as_nas_info_t *initialNasMsg, uint8_t *pdu, int pdu_length) +{ + LOG_E(NAS, "Received Authentication Reject message from the network\n"); + uint8_t eap_msg[MAX_EAP_CONTENTS_LEN] = {0}; + fgmm_auth_reject_msg_t msg = {.eap_msg.buf = eap_msg}; + + byte_array_t ba = {.buf = pdu + 3 /* skip header */, .len = pdu_length}; + if (decode_fgmm_auth_reject(&msg, &ba) < 0) { + LOG_E(NAS, "Could not decode Authentication Reject\n"); + return; + } + + if (msg.eap_msg.len > 0) { + /** @todo UE handling EAP-failure message (5.4.1.2.2.11 of 3GPP TS 24.501) */ + LOG_W(NAS, "NAS Authentication Reject contains an EAP message: handling is not implemented\n"); + log_hex_buffer("EAP-Failure", msg.eap_msg.buf, msg.eap_msg.len); + } + + nas->fiveGMM_state = FGS_DEREGISTERED; +} + int nas_itti_kgnb_refresh_req(instance_t instance, const uint8_t kgnb[32]) { MessageDef *message_p; @@ -2059,6 +2087,9 @@ void *nas_nrue(void *args_p) case FGS_AUTHENTICATION_REQUEST: handle_fgmm_authentication_request(nas, &initialNasMsg, &buffer); break; + case FGS_AUTHENTICATION_REJECT: + handle_authentication_reject(nas, &initialNasMsg, pdu_buffer, pdu_length); + break; case FGS_SECURITY_MODE_COMMAND: handle_security_mode_command(nas, &initialNasMsg, pdu_buffer, pdu_length); break; diff --git a/openair3/SECU/key_nas_deriver.c b/openair3/SECU/key_nas_deriver.c index a7cf27a1ff..3fb35adee2 100644 --- a/openair3/SECU/key_nas_deriver.c +++ b/openair3/SECU/key_nas_deriver.c @@ -57,7 +57,7 @@ #define NR_FC_ALG_KEY_DER (0x69) #define NR_FC_ALG_KEY_NG_RAN_STAR_DER (0x70) -static void log_hex_buffer(const char *label, const uint8_t *buf, const int len) +void log_hex_buffer(const char *label, const uint8_t *buf, const int len) { char hex_str[len * 2 + 1]; for (int i = 0; i < len; i++) { diff --git a/openair3/SECU/key_nas_deriver.h b/openair3/SECU/key_nas_deriver.h index 0ab14ad51a..eff72c68bb 100644 --- a/openair3/SECU/key_nas_deriver.h +++ b/openair3/SECU/key_nas_deriver.h @@ -36,4 +36,6 @@ void nr_derive_key_ng_ran_star(uint16_t pci, uint64_t nr_arfcn_dl, const uint8_t void nr_derive_nh(const uint8_t k_amf[SECURITY_KEY_LEN], const uint8_t *sync_input, uint8_t *nh); +void log_hex_buffer(const char *label, const uint8_t *buf, const int len); + #endif From 44618f45d2359b4385c3d63a3585ad52ac3662c4 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 18 Jun 2025 18:28:16 +0200 Subject: [PATCH 060/964] Remove unused ul_handle --- openair2/LAYER2/NR_MAC_gNB/main.c | 2 -- openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 4 ---- 2 files changed, 6 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/main.c b/openair2/LAYER2/NR_MAC_gNB/main.c index 0acc6fe0d2..e7c43ed204 100644 --- a/openair2/LAYER2/NR_MAC_gNB/main.c +++ b/openair2/LAYER2/NR_MAC_gNB/main.c @@ -269,8 +269,6 @@ void mac_top_init_gNB(ngran_node_t node_type, RC.nrmac[i]->tag = (NR_TAG_t*)malloc(sizeof(NR_TAG_t)); memset((void*)RC.nrmac[i]->tag,0,sizeof(NR_TAG_t)); - RC.nrmac[i]->ul_handle = 0; - RC.nrmac[i]->common_channels[0].ServingCellConfigCommon = scc; RC.nrmac[i]->radio_config = *config; RC.nrmac[i]->rlc_config = *default_rlc_config; diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 3918e0215c..49a18d3eac 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -848,10 +848,6 @@ typedef struct gNB_MAC_INST_s { NR_UEs_t UE_info; - /// UL handle - uint32_t ul_handle; - //UE_info_t UE_info; - // MAC function execution peformance profiler /// processing time of eNB scheduler time_stats_t eNB_scheduler; From 400926115e79ad900c1d1e6d1868989ef376e2e7 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Thu, 3 Apr 2025 13:30:28 +0000 Subject: [PATCH 061/964] NR UE: fix reestablishment for NTN During reestablishment the UE goes back to not synchronized state. While the synchronizatin is running, we trash frames using the function readFrame(). And when we successfully synchronize, we skip samples to align with the start of the frame using syncInFrame(). In rfsimulator mode, both of these functions send dummy data using the function dummyWrite(). Unfortunately, the writeTimestamp provided to that function was always assuming a duration from RX to TX of NR_UE_CAPABILITY_SLOT_RX_TO_TX. But in NTN mode, this value is changed when receiving SIB19. Therefore we have to consider this changed value instead of the static one. --- executables/nr-ue.c | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/executables/nr-ue.c b/executables/nr-ue.c index d0a8f27a0f..345a12d99a 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -825,7 +825,8 @@ void dummyWrite(PHY_VARS_NR_UE *UE,openair0_timestamp timestamp, int writeBlockS AssertFatal(writeBlockSize == tmp, ""); } -void readFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, bool toTrash) { +void readFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, int duration_rx_to_tx, bool toTrash) +{ NR_DL_FRAME_PARMS *fp = &UE->frame_parms; // two frames for initial sync int num_frames = 2; @@ -853,7 +854,8 @@ void readFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, bool toTrash) AssertFatal(read_block_size == tmp, ""); if (IS_SOFTMODEM_RFSIM) { - const openair0_timestamp writeTimestamp = *timestamp + fp->get_samples_slot_timestamp(slot, fp, NR_UE_CAPABILITY_SLOT_RX_TO_TX) - UE->N_TA_offset; + const openair0_timestamp writeTimestamp = + *timestamp + fp->get_samples_slot_timestamp(slot, fp, duration_rx_to_tx) - UE->N_TA_offset - UE->timing_advance; dummyWrite(UE, writeTimestamp, fp->get_samples_per_slot(slot, fp)); } } @@ -864,7 +866,7 @@ void readFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, bool toTrash) free(rxp[i]); } -static void syncInFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, openair0_timestamp rx_offset) +static void syncInFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, int duration_rx_to_tx, openair0_timestamp rx_offset) { NR_DL_FRAME_PARMS *fp = &UE->frame_parms; if (UE->sl_mode == 2) @@ -879,7 +881,8 @@ static void syncInFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, opena const int res = UE->rfdevice.trx_read_func(&UE->rfdevice, timestamp, (void **)UE->common_vars.rxdata, unitTransfer, fp->nb_antennas_rx); DevAssert(unitTransfer == res); if (IS_SOFTMODEM_RFSIM) { - const openair0_timestamp writeTimestamp = *timestamp + fp->get_samples_slot_timestamp(slot, fp, NR_UE_CAPABILITY_SLOT_RX_TO_TX) - UE->N_TA_offset; + const openair0_timestamp writeTimestamp = + *timestamp + fp->get_samples_slot_timestamp(slot, fp, duration_rx_to_tx) - UE->N_TA_offset - UE->timing_advance; dummyWrite(UE, writeTimestamp, unitTransfer); } slot = (slot + 1) % fp->slots_per_subframe; @@ -965,6 +968,10 @@ void *UE_thread(void *arg) notifiedFIFO_t freeBlocks; initNotifiedFIFO_nothreadSafe(&freeBlocks); + double ntn_init_time_drift = get_nrUE_params()->ntn_init_time_drift; + int ntn_koffset = 0; + + int duration_rx_to_tx = NR_UE_CAPABILITY_SLOT_RX_TO_TX; int timing_advance = UE->timing_advance; UE->N_TA_offset = determine_N_TA_offset(UE); NR_UE_MAC_INST_t *mac = get_mac_inst(UE->Mod_id); @@ -988,13 +995,9 @@ void *UE_thread(void *arg) //warm up the RF board int64_t tmp; for (int i = 0; i < 50; i++) - readFrame(UE, &tmp, true); + readFrame(UE, &tmp, duration_rx_to_tx, true); } - double ntn_init_time_drift = get_nrUE_params()->ntn_init_time_drift; - int ntn_koffset = 0; - int duration_rx_to_tx = NR_UE_CAPABILITY_SLOT_RX_TO_TX; - while (!oai_exit) { if (syncRunning) { notifiedFIFO_elt_t *res = pollNotifiedFIFO(&nf); @@ -1034,11 +1037,11 @@ void *UE_thread(void *arg) */ const unsigned int sync_in_frames = UE->rfdevice.openair0_cfg->recplay_conf->u_f_sync; while (trashed_frames != sync_in_frames) { - readFrame(UE, &sync_timestamp, true); + readFrame(UE, &sync_timestamp, duration_rx_to_tx, true); trashed_frames += 2; } } else { - readFrame(UE, &sync_timestamp, true); + readFrame(UE, &sync_timestamp, duration_rx_to_tx, true); trashed_frames += ((UE->sl_mode == 2) ? SL_NR_PSBCH_REPETITION_IN_FRAMES : 2); } continue; @@ -1048,7 +1051,7 @@ void *UE_thread(void *arg) AssertFatal(!syncRunning, "At this point synchronization can't be running\n"); if (!UE->is_synchronized) { - readFrame(UE, &sync_timestamp, false); + readFrame(UE, &sync_timestamp, duration_rx_to_tx, false); notifiedFIFO_elt_t *Msg = newNotifiedFIFO_elt(sizeof(syncData_t), 0, &nf, UE_synch); syncData_t *syncMsg = (syncData_t *)NotifiedFifoData(Msg); *syncMsg = (syncData_t){0}; @@ -1065,8 +1068,10 @@ void *UE_thread(void *arg) syncMsg->UE = UE; memset(&syncMsg->proc, 0, sizeof(syncMsg->proc)); pushNotifiedFIFO(&UE->sync_actor.fifo, Msg); - timing_advance = 0; - UE->timing_advance = 0; + if (ntn_koffset == 0) { // reset timing_advance for TN + timing_advance = 0; + UE->timing_advance = 0; + } trashed_frames = 0; syncRunning = true; continue; @@ -1074,7 +1079,7 @@ void *UE_thread(void *arg) if (stream_status == STREAM_STATUS_UNSYNC) { stream_status = STREAM_STATUS_SYNCING; - syncInFrame(UE, &sync_timestamp, intialSyncOffset); + syncInFrame(UE, &sync_timestamp, duration_rx_to_tx, intialSyncOffset); openair0_write_reorder_clear_context(&UE->rfdevice); if (get_nrUE_params()->time_sync_I) // ntn_init_time_drift is in µs/s, max_pos_acc * time_sync_I is in samples/frame @@ -1200,7 +1205,7 @@ void *UE_thread(void *arg) int writeBlockSize = fp->get_samples_per_slot((slot_nr + duration_rx_to_tx) % nb_slot_frame, fp) - iq_shift_to_apply; int new_timing_advance = UE->timing_advance; if (new_timing_advance != timing_advance) { - writeBlockSize -= new_timing_advance- timing_advance; + writeBlockSize -= new_timing_advance - timing_advance; timing_advance = new_timing_advance; } int new_N_TA_offset = determine_N_TA_offset(UE); From ffc0cd43a2d3ac0e6c0fc34b0982944f17ae0220 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Tue, 17 Jun 2025 14:11:57 +0000 Subject: [PATCH 062/964] for NTN GEO scenario increase ul_AM_RLC.t_PollRetransmit timer to 2 seconds --- .../conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn.conf | 9 +++++++++ 1 file changed, 9 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 fa1bcc20c8..7fbaac5f5b 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 @@ -195,6 +195,15 @@ gNBs = } ); +rlc = { + srb = { + t_poll_retransmit = "ms2000" + } + drb_am = { + t_poll_retransmit = "ms2000" + } +} + MACRLCs = ( { num_cc = 1; From 0ddba908748d83d62451d8ef9599bb96acd2d72e Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Tue, 17 Jun 2025 14:59:12 +0000 Subject: [PATCH 063/964] ci: test reestablishment for NTN GEO --- .../xml_files/container_5g_rfsim_ntn_geo.xml | 32 +++++++++++++++++++ .../docker-compose.yaml | 4 ++- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/ci-scripts/xml_files/container_5g_rfsim_ntn_geo.xml b/ci-scripts/xml_files/container_5g_rfsim_ntn_geo.xml index 72a6836882..32cc3b1f58 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_ntn_geo.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_ntn_geo.xml @@ -33,6 +33,11 @@ 000003 020001 020002 + 040001 + 020022 + 040002 + 020001 + 020002 100001 222222 @@ -98,6 +103,33 @@ 5 + + Custom_Command + Trigger Reestablishment + cacofonix + echo ci force_reestab | nc 192.168.71.140 9090 | grep -E 'Reset RLC counters of UE RNTI [0-9a-f]{4} to trigger reestablishment' + yes + + + + Ping + Ping ext-dn from NR-UE + rfsim5g_ue + cacofonix + rfsim5g_ext_dn + cacofonix + -c 20 -i0.5 -w25 + 80 + + + + Custom_Command + Verify Reestablishment + cacofonix + echo ci get_reestab_count | nc 192.168.71.140 9090 | grep -E 'UE RNTI [0-9a-f]{4} reestab 1' + yes + + Undeploy_Object true diff --git a/ci-scripts/yaml_files/5g_rfsimulator_ntn_geo/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_ntn_geo/docker-compose.yaml index 31390cde9c..eefcb37ba1 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_ntn_geo/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_ntn_geo/docker-compose.yaml @@ -87,7 +87,9 @@ services: - ALL environment: USE_ADDITIONAL_OPTIONS: --rfsim --log_config.global_log_options level,nocolor,time - ASAN_OPTIONS: detect_leaks=0 + --telnetsrv --telnetsrv.listenaddr 192.168.71.140 + --telnetsrv.shrmod ci + ASAN_OPTIONS: detect_leaks=0:detect_odr_violation=0 depends_on: - oai-ext-dn networks: From 99f36285692b3906165107f39285b7c1f817ef7d Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Mon, 7 Apr 2025 12:57:28 +0000 Subject: [PATCH 064/964] gNB: add function nr_update_sib19() allowing to update SIB19 information --- openair2/COMMON/mac_messages_def.h | 2 + openair2/COMMON/mac_messages_types.h | 3 + openair2/GNB_APP/gnb_app.c | 5 ++ openair2/LAYER2/NR_MAC_gNB/config.c | 90 +++++++++++++++++++++++++ openair2/LAYER2/NR_MAC_gNB/mac_config.h | 46 +++++++++++++ openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 1 + 6 files changed, 147 insertions(+) create mode 100644 openair2/LAYER2/NR_MAC_gNB/mac_config.h diff --git a/openair2/COMMON/mac_messages_def.h b/openair2/COMMON/mac_messages_def.h index e3ef328017..f342444c65 100644 --- a/openair2/COMMON/mac_messages_def.h +++ b/openair2/COMMON/mac_messages_def.h @@ -60,3 +60,5 @@ MESSAGE_DEF(NR_RRC_MAC_CCCH_DATA_IND, MESSAGE_PRIORITY_MED_PLUS, NRRrcMacCcch MESSAGE_DEF(NR_RRC_MAC_BCCH_DATA_IND, MESSAGE_PRIORITY_MED_PLUS, NRRrcMacBcchDataInd, nr_rrc_mac_bcch_data_ind) MESSAGE_DEF(NR_RRC_MAC_SBCCH_DATA_IND, MESSAGE_PRIORITY_MED_PLUS, NRRrcMacSBcchDataInd, nr_rrc_mac_sbcch_data_ind) +// Message to GNB_APP to update SIB19 satellite position information +MESSAGE_DEF(GNB_SAT_POSITION_UPDATE, MESSAGE_PRIORITY_MED, gnb_sat_position_update_t, gnb_sat_position_update) diff --git a/openair2/COMMON/mac_messages_types.h b/openair2/COMMON/mac_messages_types.h index ebbda2fc26..f5712b115a 100644 --- a/openair2/COMMON/mac_messages_types.h +++ b/openair2/COMMON/mac_messages_types.h @@ -31,6 +31,7 @@ #include #include "OCTET_STRING.h" +#include "NR_MAC_gNB/mac_config.h" //-------------------------------------------------------------------------------------------// // Defines to access message fields. @@ -61,6 +62,8 @@ #define RRC_MAC_DRX_CONFIG_REQ(mSGpTR) (mSGpTR)->ittiMsg.rrc_mac_drx_config_req +#define GNB_SAT_POSITION_UPDATE(mSGpTR) (mSGpTR)->ittiMsg.gnb_sat_position_update + // Some constants from "LAYER2/MAC/defs.h" #define BCCH_SDU_SIZE (512) #define BCCH_SDU_MBMS_SIZE (512) diff --git a/openair2/GNB_APP/gnb_app.c b/openair2/GNB_APP/gnb_app.c index e90a83d3bc..3b97dfe515 100644 --- a/openair2/GNB_APP/gnb_app.c +++ b/openair2/GNB_APP/gnb_app.c @@ -212,6 +212,11 @@ void *gNB_app_task(void *args_p) LOG_I(GNB_APP, " Received %s: timer_id %ld\n", msg_name, TIMER_HAS_EXPIRED(msg_p).timer_id); break; + case GNB_SAT_POSITION_UPDATE: + LOG_I(GNB_APP, " Received GNB_SAT_POSITION_UPDATE message\n"); + nr_update_sib19(&GNB_SAT_POSITION_UPDATE(msg_p)); + break; + default: LOG_E(GNB_APP, "Received unexpected message %s\n", msg_name); break; diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c index f87b4024b9..8224170271 100644 --- a/openair2/LAYER2/NR_MAC_gNB/config.c +++ b/openair2/LAYER2/NR_MAC_gNB/config.c @@ -927,6 +927,96 @@ bool nr_mac_configure_other_sib(gNB_MAC_INST *nrmac, int num_cu_sib, const f1ap_ return true; } +bool nr_update_sib19(const gnb_sat_position_update_t *sat_position) +{ + gNB_MAC_INST *nrmac = RC.nrmac[0]; + NR_COMMON_channels_t *cc = &nrmac->common_channels[0]; + NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; + + if (!scc || !scc->ext2 || !scc->ext2->ntn_Config_r17) + return false; + + const vector_t *pos = &sat_position->position; + const vector_t *vel = &sat_position->velocity; + + LOG_D(NR_MAC, "SFN = %d, SubFrame = %d\n", sat_position->sfn, sat_position->subframe); + LOG_D(NR_MAC, "TA_Common: value %d, %f msec\n", sat_position->delay, sat_position->delay * 4.072e-6); + LOG_D(NR_MAC, "TA_CommonDrift: value %d, = %f µsec/sec\n", sat_position->drift, sat_position->drift * 0.2e-3); + LOG_D(NR_MAC, "TA_CommonDriftVariant: value %d, %f µsec/sec^2\n", sat_position->accel, sat_position->accel * 0.2e-4); + LOG_D(NR_MAC, "SAT Position: values %d/%d/%d, %.3f/%3f/%3f metres in X/Y/Z\n", pos->X, pos->Y, pos->Z, pos->X * 1.3, pos->Y * 1.3, pos->Z * 1.3); + LOG_D(NR_MAC, "SAT Velocity: values %d/%d/%d, %.3f/%3f/%3f m/s in X/Y/Z\n", vel->X, vel->Y, vel->Z, vel->X * 0.06, vel->Y * 0.06, vel->Z * 0.06); + + NR_SCHED_LOCK(&nrmac->sched_lock); + + if (!scc->ext2->ntn_Config_r17->epochTime_r17) + scc->ext2->ntn_Config_r17->epochTime_r17 = calloc (1, sizeof(*scc->ext2->ntn_Config_r17->epochTime_r17)); + + NR_EpochTime_r17_t *epoch_time_r17 = scc->ext2->ntn_Config_r17->epochTime_r17; + epoch_time_r17->sfn_r17 = sat_position->sfn; + epoch_time_r17->subFrameNR_r17 = sat_position->subframe; + + if (!scc->ext2->ntn_Config_r17->ta_Info_r17) + scc->ext2->ntn_Config_r17->ta_Info_r17 = calloc(1, sizeof(*scc->ext2->ntn_Config_r17->ta_Info_r17)); + + NR_TA_Info_r17_t *sib19_ta_info = scc->ext2->ntn_Config_r17->ta_Info_r17; + + // SIB19 provides Round trip delay on feeder link (between gNB and SAT). + sib19_ta_info->ta_Common_r17 = sat_position->delay; + + if (sat_position->drift) { + if (!sib19_ta_info->ta_CommonDrift_r17) + sib19_ta_info->ta_CommonDrift_r17 = calloc(1, sizeof(*sib19_ta_info->ta_CommonDrift_r17)); + *sib19_ta_info->ta_CommonDrift_r17 = sat_position->drift; + } else + free_and_zero(sib19_ta_info->ta_CommonDrift_r17); + + if (sat_position->accel) { + if (!sib19_ta_info->ta_CommonDriftVariant_r17) + sib19_ta_info->ta_CommonDriftVariant_r17 = calloc(1, sizeof(*sib19_ta_info->ta_CommonDriftVariant_r17)); + *sib19_ta_info->ta_CommonDriftVariant_r17 = sat_position->accel; + } else + free_and_zero(sib19_ta_info->ta_CommonDriftVariant_r17); + + // Currently PositionVelocity is supported and not yet the OrbitalParams + if (!scc->ext2->ntn_Config_r17->ephemerisInfo_r17) { + scc->ext2->ntn_Config_r17->ephemerisInfo_r17 = calloc(1, sizeof(*scc->ext2->ntn_Config_r17->ephemerisInfo_r17)); + scc->ext2->ntn_Config_r17->ephemerisInfo_r17->present = NR_EphemerisInfo_r17_PR_NOTHING; + } + if (scc->ext2->ntn_Config_r17->ephemerisInfo_r17->present == NR_EphemerisInfo_r17_PR_orbital_r17) { + ASN_STRUCT_FREE(asn_DEF_NR_Orbital_r17, scc->ext2->ntn_Config_r17->ephemerisInfo_r17->choice.orbital_r17); + scc->ext2->ntn_Config_r17->ephemerisInfo_r17->choice.orbital_r17 = NULL; + scc->ext2->ntn_Config_r17->ephemerisInfo_r17->present = NR_EphemerisInfo_r17_PR_NOTHING; + } + if (!scc->ext2->ntn_Config_r17->ephemerisInfo_r17->choice.positionVelocity_r17) + scc->ext2->ntn_Config_r17->ephemerisInfo_r17->choice.positionVelocity_r17 = + calloc(1, sizeof(*scc->ext2->ntn_Config_r17->ephemerisInfo_r17->choice.positionVelocity_r17)); + + scc->ext2->ntn_Config_r17->ephemerisInfo_r17->present = NR_EphemerisInfo_r17_PR_positionVelocity_r17; + NR_PositionVelocity_r17_t *sib19_PosVel = scc->ext2->ntn_Config_r17->ephemerisInfo_r17->choice.positionVelocity_r17; + + sib19_PosVel->positionX_r17 = pos->X; + sib19_PosVel->positionY_r17 = pos->Y; + sib19_PosVel->positionZ_r17 = pos->Z; + sib19_PosVel->velocityVX_r17 = vel->X; + sib19_PosVel->velocityVY_r17 = vel->Y; + sib19_PosVel->velocityVZ_r17 = vel->Z; + + NR_SystemInformation_IEs_t *sysInfov17 = calloc(1, sizeof(*sysInfov17)); // for othersibs + struct NR_SystemInformation_IEs__sib_TypeAndInfo__Member *type_du = calloc(1, sizeof(*type_du)); + type_du->present = NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib19_v1700; + NR_SIB19_r17_t *sib19 = get_SIB19_NR(cc->ServingCellConfigCommon); + type_du->choice.sib19_v1700 = sib19; + add_sib_to_systeminformation(sysInfov17, type_du); + + cc->other_sib_bcch_length[1] = encode_sysinfo_ie(sysInfov17, cc->other_sib_bcch_pdu[1], sizeof(cc->other_sib_bcch_pdu[1])); + AssertFatal(cc->other_sib_bcch_length[1] > 0, "could not encode SIB19\n"); + ASN_STRUCT_FREE(asn_DEF_NR_SystemInformation_IEs, sysInfov17); + + NR_SCHED_UNLOCK(&nrmac->sched_lock); + + return true; +} + void prepare_du_configuration_update(gNB_MAC_INST *mac, f1ap_served_cell_info_t *info, NR_BCCH_BCH_Message_t *mib, diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_config.h b/openair2/LAYER2/NR_MAC_gNB/mac_config.h new file mode 100644 index 0000000000..1fdbe62115 --- /dev/null +++ b/openair2/LAYER2/NR_MAC_gNB/mac_config.h @@ -0,0 +1,46 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef __LAYER2_NR_MAC_CONFIG_H__ +#define __LAYER2_NR_MAC_CONFIG_H__ + +#include + +typedef struct vector_s { + int X; + int Y; + int Z; +} vector_t; + +// Format similar to values sent in SIB19 +typedef struct gnb_sat_position_update_s { + int sfn; + int subframe; + uint32_t delay; + int drift; + uint32_t accel; + vector_t position; + vector_t velocity; +} gnb_sat_position_update_t; + +bool nr_update_sib19(const gnb_sat_position_update_t *sat_position); + +#endif /*__LAYER2_NR_MAC_CONFIG_H__*/ diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 3918e0215c..64bdb86980 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -88,6 +88,7 @@ /* MAC */ #include "LAYER2/NR_MAC_COMMON/nr_mac_common.h" +#include "LAYER2/NR_MAC_gNB/mac_config.h" #include "NR_TAG.h" /* Defs */ From 42bc0d4eb37ec0f95440f4f4187afc84c8942f85 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Wed, 23 Apr 2025 12:38:13 +0000 Subject: [PATCH 065/964] rfsimulator: update SIB19 contents every second for LEO channel simulations --- radio/rfsimulator/apply_channelmod.c | 32 ++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/radio/rfsimulator/apply_channelmod.c b/radio/rfsimulator/apply_channelmod.c index efeb03b25c..2771706f55 100644 --- a/radio/rfsimulator/apply_channelmod.c +++ b/radio/rfsimulator/apply_channelmod.c @@ -25,6 +25,7 @@ #include #include #include +#include "openair2/LAYER2/NR_MAC_gNB/mac_config.h" #include "rfsimulator.h" /* @@ -95,6 +96,7 @@ void rxAddInput(const c16_t *input_sig, const double vel_ue_sat = (vel_sat_x * dir_ue_sat_x + vel_sat_y * dir_ue_sat_y + vel_sat_z * dir_ue_sat_z) / dist_ue_sat; double dist_sat_gnb = 0; + double vel_sat_gnb = 0; if (channelDesc->modelid == SAT_LEO_TRANS) { const double pos_gnb_x = 0; const double pos_gnb_y = 0; @@ -105,6 +107,7 @@ void rxAddInput(const c16_t *input_sig, const double dir_sat_gnb_z = pos_gnb_z - pos_sat_z; dist_sat_gnb = sqrt(dir_sat_gnb_x * dir_sat_gnb_x + dir_sat_gnb_y * dir_sat_gnb_y + dir_sat_gnb_z * dir_sat_gnb_z); + vel_sat_gnb = (vel_sat_x * dir_sat_gnb_x + vel_sat_y * dir_sat_gnb_y + vel_sat_z * dir_sat_gnb_z) / dist_sat_gnb; } const double prop_delay = (dist_ue_sat + dist_sat_gnb) / c; @@ -117,8 +120,29 @@ void rxAddInput(const c16_t *input_sig, if(TS - last_TS >= channelDesc->sampling_rate) { last_TS = TS; - LOG_D(HW, "Satellite orbit: time %f s, Position = (%f, %f, %f), Velocity = (%f, %f, %f)\n", t, pos_sat_x, pos_sat_y, pos_sat_z, vel_sat_x, vel_sat_y, vel_sat_z); - LOG_D(HW, "Uplink delay %f ms, Doppler shift UE->SAT %f kHz\n", prop_delay * 1000, f_Doppler_shift_ue_sat / 1000); + LOG_I(HW, "Satellite orbit: time %f s, Position = (%f, %f, %f), Velocity = (%f, %f, %f)\n", t, pos_sat_x, pos_sat_y, pos_sat_z, vel_sat_x, vel_sat_y, vel_sat_z); + LOG_I(HW, "Uplink delay %f ms, Doppler shift UE->SAT %f kHz\n", prop_delay * 1000, f_Doppler_shift_ue_sat / 1000); + + const int samples_per_subframe = channelDesc->sampling_rate / 1000; + const int abs_subframe = TS / samples_per_subframe; + gnb_sat_position_update_t sat_position = { + .sfn = (abs_subframe / 10) % 1024, + .subframe = abs_subframe % 10, + .delay = 2 * dist_sat_gnb / (c * 4.072e-9), + .drift = 2 * -vel_sat_gnb / (c * 0.2e-9), + .position.X = pos_sat_x / 1.3, + .position.Y = pos_sat_y / 1.3, + .position.Z = pos_sat_z / 1.3, + .velocity.X = vel_sat_x / 0.06, + .velocity.Y = vel_sat_y / 0.06, + .velocity.Z = vel_sat_z / 0.06, + }; + // Here we update the SIB19 information directly in the gNB MAC layer. + // Without rf-simulaor, in a real system or with an external channel emulator, the SIB19 updates would + // be provided via an external interface (e.g. O-RAN E2 interface) to the MAC layer (in the O-DU). + // We do it directly here, because we can, and an E2 Interface implementation (e.g using FlexRIC) + // would pull too many dependencies into rf-simulator, just for updating SIB19. + nr_update_sib19(&sat_position); } } else { const double dir_sat_ue_x = pos_ue_x - pos_sat_x; @@ -151,8 +175,8 @@ void rxAddInput(const c16_t *input_sig, if(TS - last_TS >= channelDesc->sampling_rate) { last_TS = TS; - LOG_D(HW, "Satellite orbit: time %f s, Position = (%f, %f, %f), Velocity = (%f, %f, %f)\n", t, pos_sat_x, pos_sat_y, pos_sat_z, vel_sat_x, vel_sat_y, vel_sat_z); - LOG_D(HW, "Downlink delay %f ms, Doppler shift SAT->UE %f kHz\n", prop_delay * 1000, f_Doppler_shift_sat_ue / 1000); + LOG_I(HW, "Satellite orbit: time %f s, Position = (%f, %f, %f), Velocity = (%f, %f, %f)\n", t, pos_sat_x, pos_sat_y, pos_sat_z, vel_sat_x, vel_sat_y, vel_sat_z); + LOG_I(HW, "Downlink delay %f ms, Doppler shift SAT->UE %f kHz\n", prop_delay * 1000, f_Doppler_shift_sat_ue / 1000); } } } From f1d612c01bbfd3fb1ce2c6de42cf726fedf944ed Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Wed, 23 Apr 2025 12:49:16 +0000 Subject: [PATCH 066/964] NR UE: improve initial timing advance calculation from SIB19 Before, we only considered ta_Common_r17 and the SAT position from SIB19 to compute the initial timing advance value. This is good enough if the satellite does not move too fast (e.g. GEO satellite). Now we also consider ta_CommonDrift_r17 and the SAT velocity together with the epoch time from SIB19. This improves the accuracy of the initial TA computation, esp. for LEO satellite scenarios. --- executables/nr-ue.c | 36 ++++--- .../nfapi/public_inc/fapi_nr_ue_interface.h | 10 +- openair1/SCHED_NR_UE/fapi_nr_ue_l1.c | 7 +- openair2/LAYER2/NR_MAC_UE/config_ue.c | 97 +++++++++++++------ openair2/LAYER2/NR_MAC_UE/mac_defs.h | 24 +++-- openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c | 4 +- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 12 ++- 7 files changed, 135 insertions(+), 55 deletions(-) diff --git a/executables/nr-ue.c b/executables/nr-ue.c index d0a8f27a0f..ff3b5c2110 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -905,7 +905,8 @@ static inline int get_readBlockSize(uint16_t slot, NR_DL_FRAME_PARMS *fp) { static inline void apply_ntn_config(PHY_VARS_NR_UE *UE, NR_DL_FRAME_PARMS *fp, - int slot_nr, + int frame_rx, + int slot_rx, int *duration_rx_to_tx, int *timing_advance, int *ntn_koffset) @@ -913,22 +914,33 @@ static inline void apply_ntn_config(PHY_VARS_NR_UE *UE, if (UE->ntn_config_message->update) { UE->ntn_config_message->update = false; - double total_ta_ms = UE->ntn_config_message->ntn_config_params.ntn_total_time_advance_ms; - UE->timing_advance = fp->samples_per_subframe * total_ta_ms; + const int mu = fp->numerology_index; + const int koffset = UE->ntn_config_message->ntn_config_params.cell_specific_k_offset; - int mu = fp->numerology_index; - int koffset = UE->ntn_config_message->ntn_config_params.cell_specific_k_offset; - if (*ntn_koffset != koffset) { - *duration_rx_to_tx = NR_UE_CAPABILITY_SLOT_RX_TO_TX + (koffset << mu); - *timing_advance += fp->get_samples_slot_timestamp(slot_nr, fp, (koffset - *ntn_koffset) << mu); - *ntn_koffset = koffset; - } + *duration_rx_to_tx = NR_UE_CAPABILITY_SLOT_RX_TO_TX + (koffset << mu); + if (koffset > *ntn_koffset) + *timing_advance += fp->get_samples_slot_timestamp(slot_rx, fp, (koffset - *ntn_koffset) << mu); + else if (koffset < *ntn_koffset) + *timing_advance -= fp->get_samples_slot_timestamp(slot_rx, fp, (*ntn_koffset - koffset) << mu); + *ntn_koffset = koffset; + + const int abs_subframe_tx = 10 * frame_rx + ((slot_rx + *duration_rx_to_tx) >> mu); + const int abs_subframe_epoch = + 10 * UE->ntn_config_message->ntn_config_params.epoch_sfn + UE->ntn_config_message->ntn_config_params.epoch_subframe; + const int ms_since_epoch = (abs_subframe_tx - abs_subframe_epoch + 10240) % 10240; + + const double total_ta_ms = UE->ntn_config_message->ntn_config_params.ntn_total_time_advance_ms; + const double total_ta_drift = UE->ntn_config_message->ntn_config_params.ntn_total_time_advance_drift; // µs/s + UE->timing_advance = fp->samples_per_subframe * (total_ta_ms + (total_ta_drift / 1000.0) * (ms_since_epoch / 1000.0)); LOG_I(PHY, - "k_offset = %d ms (%d slots), ntn_total_time_advance_ms = %f ms (%d samples)\n", + "k_offset = %d ms (%d slots), total_ta_ms = %f ms, total_ta_drift = %f µs/s, ms_since_epoch = %d ms, computed " + "timing_advance = %d samples\n", *ntn_koffset, *ntn_koffset << mu, total_ta_ms, + total_ta_drift, + ms_since_epoch, UE->timing_advance); } } @@ -1227,7 +1239,7 @@ void *UE_thread(void *arg) } // apply new NTN timing information - apply_ntn_config(UE, fp, slot_nr, &duration_rx_to_tx, &timing_advance, &ntn_koffset); + apply_ntn_config(UE, fp, curMsg.proc.frame_rx, curMsg.proc.nr_slot_rx, &duration_rx_to_tx, &timing_advance, &ntn_koffset); // Start TX slot processing here. It runs in parallel with RX slot processing // in current code, DURATION_RX_TO_TX constant is the limit to get UL data to encode from a RX slot diff --git a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h index 140ed130a4..b40c062f03 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h @@ -557,16 +557,22 @@ typedef struct { } fapi_nr_ta_command_pdu; typedef struct { + int epoch_sfn; + int epoch_subframe; + // N_common_ta_adj represents common round-trip-time between gNB and SAT received in SIB19 (ms) double N_common_ta_adj; - // N_UE_TA_adj calculated round-trip-time between UE and SAT (ms) - double N_UE_TA_adj; // drift rate of common ta in µs/s double ntn_ta_commondrift; + // N_UE_TA_adj calculated round-trip-time between UE and SAT (ms) + double N_UE_TA_adj; + // drift rate of N_UE_TA in µs/s + double N_UE_TA_drift; // cell scheduling offset expressed in terms of 15kHz SCS long cell_specific_k_offset; double ntn_total_time_advance_ms; + double ntn_total_time_advance_drift; } fapi_nr_dl_ntn_config_command_pdu; typedef struct { diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c index 6bb7ed3e4c..c7235e807b 100644 --- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c +++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c @@ -352,10 +352,15 @@ static void configure_ntn_params(PHY_VARS_NR_UE *ue, fapi_nr_dl_ntn_config_comma ue->ntn_config_message = CALLOC(1, sizeof(*ue->ntn_config_message)); } - ue->ntn_config_message->ntn_config_params.cell_specific_k_offset = ntn_params_message->cell_specific_k_offset; + ue->ntn_config_message->ntn_config_params.epoch_sfn = ntn_params_message->epoch_sfn; + ue->ntn_config_message->ntn_config_params.epoch_subframe = ntn_params_message->epoch_subframe; ue->ntn_config_message->ntn_config_params.N_common_ta_adj = ntn_params_message->N_common_ta_adj; ue->ntn_config_message->ntn_config_params.ntn_ta_commondrift = ntn_params_message->ntn_ta_commondrift; + ue->ntn_config_message->ntn_config_params.N_UE_TA_adj = ntn_params_message->N_UE_TA_adj; + ue->ntn_config_message->ntn_config_params.N_UE_TA_drift = ntn_params_message->N_UE_TA_drift; + ue->ntn_config_message->ntn_config_params.cell_specific_k_offset = ntn_params_message->cell_specific_k_offset; ue->ntn_config_message->ntn_config_params.ntn_total_time_advance_ms = ntn_params_message->ntn_total_time_advance_ms; + ue->ntn_config_message->ntn_config_params.ntn_total_time_advance_drift = ntn_params_message->ntn_total_time_advance_drift; ue->ntn_config_message->update = true; } diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index bfea78d540..8bf20428c2 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -267,59 +267,102 @@ static void config_common_ue_sa(NR_UE_MAC_INST_t *mac, NR_ServingCellConfigCommo } // computes round-trip-time between ue and sat based on SIB19 ephemeris data -static double calculate_ue_sat_ta(const position_t *position_params, NR_PositionVelocity_r17_t *sat_pos) +static void calculate_ue_sat_ta(const position_t *position_params, + const NR_PositionVelocity_r17_t *sat_pos, + ntn_timing_advance_componets_t *ntn_ta) { // get UE position coordinates - double posx = position_params->positionX; - double posy = position_params->positionY; - double posz = position_params->positionZ; + double pos_ue_x = position_params->positionX; + double pos_ue_y = position_params->positionY; + double pos_ue_z = position_params->positionZ; // get sat position coordinates - double posx_0 = (double)sat_pos->positionX_r17 * 1.3; - double posy_0 = (double)sat_pos->positionY_r17 * 1.3; - double posz_0 = (double)sat_pos->positionZ_r17 * 1.3; + double pos_sat_x = (double)sat_pos->positionX_r17 * 1.3; + double pos_sat_y = (double)sat_pos->positionY_r17 * 1.3; + double pos_sat_z = (double)sat_pos->positionZ_r17 * 1.3; - double distance = 2 * sqrt(pow(posx - posx_0, 2) + pow(posy - posy_0, 2) + pow(posz - posz_0, 2)); - double ta_ms = (distance / SPEED_OF_LIGHT) * 1000; + // calculate directional vector from SAT to UE + double dir_sat_ue_x = pos_ue_x - pos_sat_x; + double dir_sat_ue_y = pos_ue_y - pos_sat_y; + double dir_sat_ue_z = pos_ue_z - pos_sat_z; - return ta_ms; + // calculate distance between SAT and UE + double distance = sqrt(dir_sat_ue_x * dir_sat_ue_x + dir_sat_ue_y * dir_sat_ue_y + dir_sat_ue_z * dir_sat_ue_z); + + // get sat velocity vector + double vel_sat_x = (double)sat_pos->velocityVX_r17 * 0.06; + double vel_sat_y = (double)sat_pos->velocityVY_r17 * 0.06; + double vel_sat_z = (double)sat_pos->velocityVZ_r17 * 0.06; + + // calculate SAT velocity towards UE + double velocity = (vel_sat_x * dir_sat_ue_x + vel_sat_y * dir_sat_ue_y + vel_sat_z * dir_sat_ue_z) / distance; + + ntn_ta->N_UE_TA_adj = (2 * distance / SPEED_OF_LIGHT) * 1e3; // in ms + ntn_ta->N_UE_TA_drift = (2 * -velocity / SPEED_OF_LIGHT) * 1e6; // in µs/s } // populate ntn_ta structure from mac -void configure_ntn_ta(module_id_t module_id, ntn_timing_advance_componets_t *ntn_ta, NR_NTN_Config_r17_t *ntn_Config_r17) +static void configure_ntn_ta(module_id_t module_id, + ntn_timing_advance_componets_t *ntn_ta, + const NR_NTN_Config_r17_t *ntn_Config_r17) { position_t position_params = {0}; get_position_coordinates(module_id, &position_params); - // if ephemerisInfo_r17 present in SIB19 - NR_EphemerisInfo_r17_t *ephemeris_info = ntn_Config_r17->ephemerisInfo_r17; + // epochTime_r17 must be present (this is assured by function `eval_epoch_time()`) + const NR_EpochTime_r17_t *epoch_time_r17 = ntn_Config_r17->epochTime_r17; + AssertFatal(epoch_time_r17, "epoch_time_r17 should not be NULL here\n"); + ntn_ta->epoch_sfn = epoch_time_r17->sfn_r17; + ntn_ta->epoch_subframe = epoch_time_r17->subFrameNR_r17; + + // handle ephemerisInfo_r17 + const NR_EphemerisInfo_r17_t *ephemeris_info = ntn_Config_r17->ephemerisInfo_r17; if (ephemeris_info) { - NR_PositionVelocity_r17_t *position_velocity = ephemeris_info->choice.positionVelocity_r17; - if (position_velocity - && (position_velocity->positionX_r17 != 0 || position_velocity->positionY_r17 != 0 - || position_velocity->positionZ_r17 != 0)) { - ntn_ta->N_UE_TA_adj = calculate_ue_sat_ta(&position_params, position_velocity); + if (ephemeris_info->present == NR_EphemerisInfo_r17_PR_positionVelocity_r17) { + const NR_PositionVelocity_r17_t *position_velocity = ephemeris_info->choice.positionVelocity_r17; + AssertFatal(position_velocity, "position_velocity should not be NULL here\n"); + calculate_ue_sat_ta(&position_params, position_velocity, ntn_ta); + } else { + LOG_W(NR_MAC, "NR UE currently supports only ephemerisInfo_r17 of type positionVelocity_r17\n"); + ntn_ta->N_UE_TA_adj = 0; + ntn_ta->N_UE_TA_drift = 0; } + } else { // Need R - Release if not present + ntn_ta->N_UE_TA_adj = 0; + ntn_ta->N_UE_TA_drift = 0; } - // if cellSpecificKoffset_r17 is present - if (ntn_Config_r17->cellSpecificKoffset_r17) { + + // handle cellSpecificKoffset_r17 + if (ntn_Config_r17->cellSpecificKoffset_r17) ntn_ta->cell_specific_k_offset = *ntn_Config_r17->cellSpecificKoffset_r17; - } - // Check if ta_Info_r17 is present and convert directly ta_Common_r17 (is in units of 4.072e-3 µs) + else // Need R - Release if not present + ntn_ta->cell_specific_k_offset = 0; + + // Check if ta_Info_r17 is present and convert the time units if (ntn_Config_r17->ta_Info_r17) { + // ta_Common_r17 (is in units of 4.072e-3 µs) ntn_ta->N_common_ta_adj = ntn_Config_r17->ta_Info_r17->ta_Common_r17 * 4.072e-6; // ta_CommonDrift_r17 (is in units of 0.2e-3 µs/s) if (ntn_Config_r17->ta_Info_r17->ta_CommonDrift_r17) ntn_ta->ntn_ta_commondrift = *ntn_Config_r17->ta_Info_r17->ta_CommonDrift_r17 * 0.2e-3; + else // Need R - Release if not present + ntn_ta->ntn_ta_commondrift = 0; + } else { // Need R - Release if not present + ntn_ta->N_common_ta_adj = 0; + ntn_ta->ntn_ta_commondrift = 0; } + ntn_ta->ntn_params_changed = true; LOG_D(NR_MAC, - "SIB19 Rxd. k_offset:%ld, N_Common_Ta:%f,drift:%f,N_UE_TA:%f \n", + "SIB19 Rxd. Epoch SFN: %d, Epoch Subframe: %d, k_offset: %ldms, N_Common_Ta: %fms, drift: %fµs/s, N_UE_TA: %fms, drift: %fµs/s\n", + ntn_ta->epoch_sfn, + ntn_ta->epoch_subframe, ntn_ta->cell_specific_k_offset, ntn_ta->N_common_ta_adj, ntn_ta->ntn_ta_commondrift, - ntn_ta->N_UE_TA_adj); + ntn_ta->N_UE_TA_adj, + ntn_ta->N_UE_TA_drift); } static void config_common_ue(NR_UE_MAC_INST_t *mac, NR_ServingCellConfigCommon_t *scc, int cc_idP) @@ -1863,10 +1906,8 @@ void nr_rrc_mac_config_other_sib(module_id_t module_id, NR_SIB19_r17_t *sib19, b if (sib19) { // update ntn_Config_r17 with received values - NR_NTN_Config_r17_t *ntn_Config_r17 = mac->sc_info.ntn_Config_r17; - UPDATE_IE(ntn_Config_r17, sib19->ntn_Config_r17, NR_NTN_Config_r17_t); - - configure_ntn_ta(mac->ue_id, &mac->ntn_ta, ntn_Config_r17); + UPDATE_IE(mac->sc_info.ntn_Config_r17, sib19->ntn_Config_r17, NR_NTN_Config_r17_t); + configure_ntn_ta(mac->ue_id, &mac->ntn_ta, mac->sc_info.ntn_Config_r17); } if (mac->state == UE_RECEIVING_SIB && can_start_ra) mac->state = UE_PERFORMING_RA; diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index dee2a30c08..13f42ca9e3 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -526,12 +526,17 @@ typedef struct { } si_schedInfo_t; typedef struct ntn_timing_advance_components { + int epoch_sfn; + int epoch_subframe; + // N_common_ta_adj represents common round-trip-time between gNB and SAT received in SIB19 (ms) double N_common_ta_adj; - // N_UE_TA_adj calculated round-trip-time between UE and SAT (ms) - double N_UE_TA_adj; // drift rate of common ta in µs/s double ntn_ta_commondrift; + // N_UE_TA_adj calculated round-trip-time between UE and SAT (ms) + double N_UE_TA_adj; + // drift rate of N_UE_TA in µs/s + double N_UE_TA_drift; // cell scheduling offset expressed in terms of 15kHz SCS long cell_specific_k_offset; @@ -650,15 +655,20 @@ static inline int GET_NTN_UE_K_OFFSET(const ntn_timing_advance_componets_t *ntn_ return (int)ntn_ta->cell_specific_k_offset << scs; } -static inline double GET_COMPLETE_TIME_ADVANCE_MS(const ntn_timing_advance_componets_t *ntn_ta) -{ - return ntn_ta->N_common_ta_adj + ntn_ta->N_UE_TA_adj; -} - static inline long GET_DURATION_RX_TO_TX(const ntn_timing_advance_componets_t *ntn_ta, int scs) { return NR_UE_CAPABILITY_SLOT_RX_TO_TX + (ntn_ta->cell_specific_k_offset << scs); } +static inline double get_total_TA_ms(const ntn_timing_advance_componets_t *ntn_ta) +{ + return ntn_ta->N_common_ta_adj + ntn_ta->N_UE_TA_adj; +} + +static inline double get_total_TA_drift(const ntn_timing_advance_componets_t *ntn_ta) +{ + return ntn_ta->ntn_ta_commondrift + ntn_ta->N_UE_TA_drift; +} + /*@}*/ #endif /*__LAYER2_MAC_DEFS_H__ */ diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index 2f717a7466..58269f769a 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -818,7 +818,7 @@ static void setup_ra_response_window(RA_config_t *ra, int ta_Common_slots = 0; if (ntn_Config_r17) { - const double ta_Common_ms = GET_COMPLETE_TIME_ADVANCE_MS(ntn_ta); + const double ta_Common_ms = get_total_TA_ms(ntn_ta); ta_Common_slots = (int)ceil(ta_Common_ms * slots_per_frame / 10); } @@ -1066,7 +1066,7 @@ void nr_Msg3_transmitted(NR_UE_MAC_INST_t *mac, uint8_t CC_id, frame_t frameP, s { RA_config_t *ra = &mac->ra; NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon = mac->current_UL_BWP->rach_ConfigCommon; - const double ta_Common_ms = GET_COMPLETE_TIME_ADVANCE_MS(&mac->ntn_ta); + const double ta_Common_ms = get_total_TA_ms(&mac->ntn_ta); const int slots_per_ms = mac->frame_structure.numb_slots_frame / 10; // start contention resolution timer diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 2c37b21f5b..a818096a6f 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -2843,11 +2843,17 @@ static uint8_t nr_ue_get_sdu(NR_UE_MAC_INST_t *mac, static void schedule_ntn_config_command(fapi_nr_dl_config_request_t *dl_config, NR_UE_MAC_INST_t *mac) { fapi_nr_dl_ntn_config_command_pdu *ntn_config_command_pdu = &dl_config->dl_config_list[dl_config->number_pdus].ntn_config_command_pdu; - ntn_config_command_pdu->cell_specific_k_offset = mac->ntn_ta.cell_specific_k_offset; - ntn_config_command_pdu->ntn_ta_commondrift = mac->ntn_ta.ntn_ta_commondrift; + + ntn_config_command_pdu->epoch_sfn = mac->ntn_ta.epoch_sfn; + ntn_config_command_pdu->epoch_subframe = mac->ntn_ta.epoch_subframe; ntn_config_command_pdu->N_common_ta_adj = mac->ntn_ta.N_common_ta_adj; + ntn_config_command_pdu->ntn_ta_commondrift = mac->ntn_ta.ntn_ta_commondrift; ntn_config_command_pdu->N_UE_TA_adj = mac->ntn_ta.N_UE_TA_adj; - ntn_config_command_pdu->ntn_total_time_advance_ms = mac->ntn_ta.N_common_ta_adj + mac->ntn_ta.N_UE_TA_adj; + ntn_config_command_pdu->N_UE_TA_drift = mac->ntn_ta.N_UE_TA_drift; + ntn_config_command_pdu->cell_specific_k_offset = mac->ntn_ta.cell_specific_k_offset; + ntn_config_command_pdu->ntn_total_time_advance_ms = get_total_TA_ms(&mac->ntn_ta); + ntn_config_command_pdu->ntn_total_time_advance_drift = get_total_TA_drift(&mac->ntn_ta); + dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_NTN_CONFIG_PARAMS; dl_config->number_pdus += 1; } From ece430b6c3e8088da125f87e31f0cf3557f2ae25 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Fri, 16 May 2025 13:48:34 +0000 Subject: [PATCH 067/964] NR UE: use shorter member names for position_t structure --- executables/position_interface.h | 12 ++++++------ openair2/LAYER2/NR_MAC_UE/config_ue.c | 20 ++++++-------------- 2 files changed, 12 insertions(+), 20 deletions(-) diff --git a/executables/position_interface.h b/executables/position_interface.h index 0324bceb15..8ef0b3144b 100644 --- a/executables/position_interface.h +++ b/executables/position_interface.h @@ -41,16 +41,16 @@ /*----------------------------------------------------------------------------------------------------------------------------------------------------*/ // clang-format off #define POSITION_CONFIG_PARAMS_DEF { \ - {CONFIG_STRING_POSITION_X, HELP_STRING_POSITION, 0, .dblptr=&(position->positionX), .defuintval=0, TYPE_DOUBLE, 0}, \ - {CONFIG_STRING_POSITION_Y, HELP_STRING_POSITION, 0, .dblptr=&(position->positionY), .defuintval=0, TYPE_DOUBLE, 0}, \ - {CONFIG_STRING_POSITION_Z, HELP_STRING_POSITION, 0, .dblptr=&(position->positionZ), .defuintval=0, TYPE_DOUBLE, 0} \ + {CONFIG_STRING_POSITION_X, HELP_STRING_POSITION, 0, .dblptr=&(position->X), .defuintval=0, TYPE_DOUBLE, 0}, \ + {CONFIG_STRING_POSITION_Y, HELP_STRING_POSITION, 0, .dblptr=&(position->Y), .defuintval=0, TYPE_DOUBLE, 0}, \ + {CONFIG_STRING_POSITION_Z, HELP_STRING_POSITION, 0, .dblptr=&(position->Z), .defuintval=0, TYPE_DOUBLE, 0} \ } // clang-format on typedef struct position { - double positionX; - double positionY; - double positionZ; + double X; + double Y; + double Z; } position_t; void get_position_coordinates(int Mod_id, position_t *position); diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index 8bf20428c2..2381bdb3e3 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -272,30 +272,22 @@ static void calculate_ue_sat_ta(const position_t *position_params, ntn_timing_advance_componets_t *ntn_ta) { // get UE position coordinates - double pos_ue_x = position_params->positionX; - double pos_ue_y = position_params->positionY; - double pos_ue_z = position_params->positionZ; + const position_t pos_ue = *position_params; // get sat position coordinates - double pos_sat_x = (double)sat_pos->positionX_r17 * 1.3; - double pos_sat_y = (double)sat_pos->positionY_r17 * 1.3; - double pos_sat_z = (double)sat_pos->positionZ_r17 * 1.3; + const position_t pos_sat = {sat_pos->positionX_r17 * 1.3, sat_pos->positionY_r17 * 1.3, sat_pos->positionZ_r17 * 1.3}; // calculate directional vector from SAT to UE - double dir_sat_ue_x = pos_ue_x - pos_sat_x; - double dir_sat_ue_y = pos_ue_y - pos_sat_y; - double dir_sat_ue_z = pos_ue_z - pos_sat_z; + const position_t dir_sat_ue = {pos_ue.X - pos_sat.X, pos_ue.Y - pos_sat.Y, pos_ue.Z - pos_sat.Z}; // calculate distance between SAT and UE - double distance = sqrt(dir_sat_ue_x * dir_sat_ue_x + dir_sat_ue_y * dir_sat_ue_y + dir_sat_ue_z * dir_sat_ue_z); + double distance = sqrt(dir_sat_ue.X * dir_sat_ue.X + dir_sat_ue.Y * dir_sat_ue.Y + dir_sat_ue.Z * dir_sat_ue.Z); // get sat velocity vector - double vel_sat_x = (double)sat_pos->velocityVX_r17 * 0.06; - double vel_sat_y = (double)sat_pos->velocityVY_r17 * 0.06; - double vel_sat_z = (double)sat_pos->velocityVZ_r17 * 0.06; + const position_t vel_sat = {sat_pos->velocityVX_r17 * 0.06, sat_pos->velocityVY_r17 * 0.06, sat_pos->velocityVZ_r17 * 0.06}; // calculate SAT velocity towards UE - double velocity = (vel_sat_x * dir_sat_ue_x + vel_sat_y * dir_sat_ue_y + vel_sat_z * dir_sat_ue_z) / distance; + double velocity = (vel_sat.X * dir_sat_ue.X + vel_sat.Y * dir_sat_ue.Y + vel_sat.Z * dir_sat_ue.Z) / distance; ntn_ta->N_UE_TA_adj = (2 * distance / SPEED_OF_LIGHT) * 1e3; // in ms ntn_ta->N_UE_TA_drift = (2 * -velocity / SPEED_OF_LIGHT) * 1e6; // in µs/s From 7ba63a20522e0fccb62e830c921bc8ad19edbd5a Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Thu, 24 Apr 2025 09:48:35 +0000 Subject: [PATCH 068/964] rfsimulator: for LEO NTN, calculate SAT acceleration towards gNB to determine ta-CommonDriftVariant-r17 --- radio/rfsimulator/apply_channelmod.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/radio/rfsimulator/apply_channelmod.c b/radio/rfsimulator/apply_channelmod.c index 2771706f55..1e873b8a2e 100644 --- a/radio/rfsimulator/apply_channelmod.c +++ b/radio/rfsimulator/apply_channelmod.c @@ -97,7 +97,12 @@ void rxAddInput(const c16_t *input_sig, double dist_sat_gnb = 0; double vel_sat_gnb = 0; + double acc_sat_gnb = 0; if (channelDesc->modelid == SAT_LEO_TRANS) { + const double acc_sat_x = 0; + const double acc_sat_y = -w_sat * w_sat * radius_sat * sin(w_sat * t); + const double acc_sat_z = -w_sat * w_sat * radius_sat * cos(w_sat * t); + const double pos_gnb_x = 0; const double pos_gnb_y = 0; const double pos_gnb_z = radius_earth; @@ -108,6 +113,7 @@ void rxAddInput(const c16_t *input_sig, dist_sat_gnb = sqrt(dir_sat_gnb_x * dir_sat_gnb_x + dir_sat_gnb_y * dir_sat_gnb_y + dir_sat_gnb_z * dir_sat_gnb_z); vel_sat_gnb = (vel_sat_x * dir_sat_gnb_x + vel_sat_y * dir_sat_gnb_y + vel_sat_z * dir_sat_gnb_z) / dist_sat_gnb; + acc_sat_gnb = (acc_sat_x * dir_sat_gnb_x + acc_sat_y * dir_sat_gnb_y + acc_sat_z * dir_sat_gnb_z) / dist_sat_gnb; } const double prop_delay = (dist_ue_sat + dist_sat_gnb) / c; @@ -122,6 +128,7 @@ void rxAddInput(const c16_t *input_sig, last_TS = TS; LOG_I(HW, "Satellite orbit: time %f s, Position = (%f, %f, %f), Velocity = (%f, %f, %f)\n", t, pos_sat_x, pos_sat_y, pos_sat_z, vel_sat_x, vel_sat_y, vel_sat_z); LOG_I(HW, "Uplink delay %f ms, Doppler shift UE->SAT %f kHz\n", prop_delay * 1000, f_Doppler_shift_ue_sat / 1000); + LOG_I(HW, "Satellite velocity towards gNB: %f m/s, acceleration towards gNB: %f m/s²\n", vel_sat_gnb, acc_sat_gnb); const int samples_per_subframe = channelDesc->sampling_rate / 1000; const int abs_subframe = TS / samples_per_subframe; @@ -130,6 +137,7 @@ void rxAddInput(const c16_t *input_sig, .subframe = abs_subframe % 10, .delay = 2 * dist_sat_gnb / (c * 4.072e-9), .drift = 2 * -vel_sat_gnb / (c * 0.2e-9), + .accel = 2 * acc_sat_gnb / (c * 0.2e-10), .position.X = pos_sat_x / 1.3, .position.Y = pos_sat_y / 1.3, .position.Z = pos_sat_z / 1.3, From f7ab814a3cf978aa3049a9ff11155627ddebb850 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Thu, 24 Apr 2025 10:22:45 +0000 Subject: [PATCH 069/964] NR UE: remove unused elements from struc fapi_nr_dl_ntn_config_command_pdu --- nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h | 8 -------- openair1/SCHED_NR_UE/fapi_nr_ue_l1.c | 4 ---- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 4 ---- 3 files changed, 16 deletions(-) diff --git a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h index b40c062f03..024c0b4220 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h @@ -560,14 +560,6 @@ typedef struct { int epoch_sfn; int epoch_subframe; - // N_common_ta_adj represents common round-trip-time between gNB and SAT received in SIB19 (ms) - double N_common_ta_adj; - // drift rate of common ta in µs/s - double ntn_ta_commondrift; - // N_UE_TA_adj calculated round-trip-time between UE and SAT (ms) - double N_UE_TA_adj; - // drift rate of N_UE_TA in µs/s - double N_UE_TA_drift; // cell scheduling offset expressed in terms of 15kHz SCS long cell_specific_k_offset; diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c index c7235e807b..fa8043966c 100644 --- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c +++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c @@ -354,10 +354,6 @@ static void configure_ntn_params(PHY_VARS_NR_UE *ue, fapi_nr_dl_ntn_config_comma ue->ntn_config_message->ntn_config_params.epoch_sfn = ntn_params_message->epoch_sfn; ue->ntn_config_message->ntn_config_params.epoch_subframe = ntn_params_message->epoch_subframe; - ue->ntn_config_message->ntn_config_params.N_common_ta_adj = ntn_params_message->N_common_ta_adj; - ue->ntn_config_message->ntn_config_params.ntn_ta_commondrift = ntn_params_message->ntn_ta_commondrift; - ue->ntn_config_message->ntn_config_params.N_UE_TA_adj = ntn_params_message->N_UE_TA_adj; - ue->ntn_config_message->ntn_config_params.N_UE_TA_drift = ntn_params_message->N_UE_TA_drift; ue->ntn_config_message->ntn_config_params.cell_specific_k_offset = ntn_params_message->cell_specific_k_offset; ue->ntn_config_message->ntn_config_params.ntn_total_time_advance_ms = ntn_params_message->ntn_total_time_advance_ms; ue->ntn_config_message->ntn_config_params.ntn_total_time_advance_drift = ntn_params_message->ntn_total_time_advance_drift; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index a818096a6f..58ccbac7b4 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -2846,10 +2846,6 @@ static void schedule_ntn_config_command(fapi_nr_dl_config_request_t *dl_config, ntn_config_command_pdu->epoch_sfn = mac->ntn_ta.epoch_sfn; ntn_config_command_pdu->epoch_subframe = mac->ntn_ta.epoch_subframe; - ntn_config_command_pdu->N_common_ta_adj = mac->ntn_ta.N_common_ta_adj; - ntn_config_command_pdu->ntn_ta_commondrift = mac->ntn_ta.ntn_ta_commondrift; - ntn_config_command_pdu->N_UE_TA_adj = mac->ntn_ta.N_UE_TA_adj; - ntn_config_command_pdu->N_UE_TA_drift = mac->ntn_ta.N_UE_TA_drift; ntn_config_command_pdu->cell_specific_k_offset = mac->ntn_ta.cell_specific_k_offset; ntn_config_command_pdu->ntn_total_time_advance_ms = get_total_TA_ms(&mac->ntn_ta); ntn_config_command_pdu->ntn_total_time_advance_drift = get_total_TA_drift(&mac->ntn_ta); From 22866c3c1e32087e438310f8e85ae8e3ffefc500 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Thu, 24 Apr 2025 09:51:05 +0000 Subject: [PATCH 070/964] NR UE: for consistency, rename ntn_ta_commondrift to N_common_ta_drift --- openair2/LAYER2/NR_MAC_UE/config_ue.c | 8 ++++---- openair2/LAYER2/NR_MAC_UE/mac_defs.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index 2381bdb3e3..921e3da6d1 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -336,12 +336,12 @@ static void configure_ntn_ta(module_id_t module_id, ntn_ta->N_common_ta_adj = ntn_Config_r17->ta_Info_r17->ta_Common_r17 * 4.072e-6; // ta_CommonDrift_r17 (is in units of 0.2e-3 µs/s) if (ntn_Config_r17->ta_Info_r17->ta_CommonDrift_r17) - ntn_ta->ntn_ta_commondrift = *ntn_Config_r17->ta_Info_r17->ta_CommonDrift_r17 * 0.2e-3; + ntn_ta->N_common_ta_drift = *ntn_Config_r17->ta_Info_r17->ta_CommonDrift_r17 * 0.2e-3; else // Need R - Release if not present - ntn_ta->ntn_ta_commondrift = 0; + ntn_ta->N_common_ta_drift = 0; } else { // Need R - Release if not present ntn_ta->N_common_ta_adj = 0; - ntn_ta->ntn_ta_commondrift = 0; + ntn_ta->N_common_ta_drift = 0; } ntn_ta->ntn_params_changed = true; @@ -352,7 +352,7 @@ static void configure_ntn_ta(module_id_t module_id, ntn_ta->epoch_subframe, ntn_ta->cell_specific_k_offset, ntn_ta->N_common_ta_adj, - ntn_ta->ntn_ta_commondrift, + ntn_ta->N_common_ta_drift, ntn_ta->N_UE_TA_adj, ntn_ta->N_UE_TA_drift); } diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index 13f42ca9e3..aeecf2ecaf 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -532,7 +532,7 @@ typedef struct ntn_timing_advance_components { // N_common_ta_adj represents common round-trip-time between gNB and SAT received in SIB19 (ms) double N_common_ta_adj; // drift rate of common ta in µs/s - double ntn_ta_commondrift; + double N_common_ta_drift; // N_UE_TA_adj calculated round-trip-time between UE and SAT (ms) double N_UE_TA_adj; // drift rate of N_UE_TA in µs/s @@ -667,7 +667,7 @@ static inline double get_total_TA_ms(const ntn_timing_advance_componets_t *ntn_t static inline double get_total_TA_drift(const ntn_timing_advance_componets_t *ntn_ta) { - return ntn_ta->ntn_ta_commondrift + ntn_ta->N_UE_TA_drift; + return ntn_ta->N_common_ta_drift + ntn_ta->N_UE_TA_drift; } /*@}*/ From e91fb33da3fd01d4815799e1011052c79aa5cd8e Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Thu, 24 Apr 2025 10:25:47 +0000 Subject: [PATCH 071/964] NR UE: also use ta_CommonDriftVariant_r17 to calculate the initial timing advance --- executables/nr-ue.c | 6 ++++-- nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h | 4 ++++ openair1/SCHED_NR_UE/fapi_nr_ue_l1.c | 1 + openair2/LAYER2/NR_MAC_UE/config_ue.c | 9 ++++++++- openair2/LAYER2/NR_MAC_UE/mac_defs.h | 2 ++ openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 1 + 6 files changed, 20 insertions(+), 3 deletions(-) diff --git a/executables/nr-ue.c b/executables/nr-ue.c index ff3b5c2110..c4237cb914 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -931,15 +931,17 @@ static inline void apply_ntn_config(PHY_VARS_NR_UE *UE, const double total_ta_ms = UE->ntn_config_message->ntn_config_params.ntn_total_time_advance_ms; const double total_ta_drift = UE->ntn_config_message->ntn_config_params.ntn_total_time_advance_drift; // µs/s - UE->timing_advance = fp->samples_per_subframe * (total_ta_ms + (total_ta_drift / 1000.0) * (ms_since_epoch / 1000.0)); + const double total_ta_drift_variant = UE->ntn_config_message->ntn_config_params.ntn_total_time_advance_drift_variant; // µs/s² + UE->timing_advance = fp->samples_per_subframe * (total_ta_ms + (total_ta_drift / 1000.0) * (ms_since_epoch / 1000.0) + (total_ta_drift_variant / 1000.0) * (ms_since_epoch / 1000.0) * (ms_since_epoch / 1000.0)); LOG_I(PHY, - "k_offset = %d ms (%d slots), total_ta_ms = %f ms, total_ta_drift = %f µs/s, ms_since_epoch = %d ms, computed " + "k_offset = %d ms (%d slots), total_ta_ms = %f ms, total_ta_drift = %f µs/s, total_ta_drift_variant = %f µs/s², ms_since_epoch = %d ms, computed " "timing_advance = %d samples\n", *ntn_koffset, *ntn_koffset << mu, total_ta_ms, total_ta_drift, + total_ta_drift_variant, ms_since_epoch, UE->timing_advance); } diff --git a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h index 024c0b4220..64c8dab07e 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h @@ -563,8 +563,12 @@ typedef struct { // cell scheduling offset expressed in terms of 15kHz SCS long cell_specific_k_offset; + // ntn_total_time_advance_ms represents the complete round-trip-time between gNB and UE via SAT double ntn_total_time_advance_ms; + // drift rate of ntn_total_time_advance_ms in µs/s double ntn_total_time_advance_drift; + // change rate of ntn_total_time_advance_ms drift in µs/s² + double ntn_total_time_advance_drift_variant; } fapi_nr_dl_ntn_config_command_pdu; typedef struct { diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c index fa8043966c..52d5033457 100644 --- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c +++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c @@ -357,6 +357,7 @@ static void configure_ntn_params(PHY_VARS_NR_UE *ue, fapi_nr_dl_ntn_config_comma ue->ntn_config_message->ntn_config_params.cell_specific_k_offset = ntn_params_message->cell_specific_k_offset; ue->ntn_config_message->ntn_config_params.ntn_total_time_advance_ms = ntn_params_message->ntn_total_time_advance_ms; ue->ntn_config_message->ntn_config_params.ntn_total_time_advance_drift = ntn_params_message->ntn_total_time_advance_drift; + ue->ntn_config_message->ntn_config_params.ntn_total_time_advance_drift_variant = ntn_params_message->ntn_total_time_advance_drift_variant; ue->ntn_config_message->update = true; } diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index 921e3da6d1..ad7ae1a338 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -339,20 +339,27 @@ static void configure_ntn_ta(module_id_t module_id, ntn_ta->N_common_ta_drift = *ntn_Config_r17->ta_Info_r17->ta_CommonDrift_r17 * 0.2e-3; else // Need R - Release if not present ntn_ta->N_common_ta_drift = 0; + // ta_CommonDriftVariant_r17 (is in units of 0.2e-4 µs/s²) + if (ntn_Config_r17->ta_Info_r17->ta_CommonDriftVariant_r17) + ntn_ta->N_common_ta_drift_variant = *ntn_Config_r17->ta_Info_r17->ta_CommonDriftVariant_r17 * 0.2e-4; + else // Need R - Release if not present + ntn_ta->N_common_ta_drift_variant = 0; } else { // Need R - Release if not present ntn_ta->N_common_ta_adj = 0; ntn_ta->N_common_ta_drift = 0; + ntn_ta->N_common_ta_drift_variant = 0; } ntn_ta->ntn_params_changed = true; LOG_D(NR_MAC, - "SIB19 Rxd. Epoch SFN: %d, Epoch Subframe: %d, k_offset: %ldms, N_Common_Ta: %fms, drift: %fµs/s, N_UE_TA: %fms, drift: %fµs/s\n", + "SIB19 Rxd. Epoch SFN: %d, Epoch Subframe: %d, k_offset: %ldms, N_Common_Ta: %fms, drift: %fµs/s, variant %fµs/s², N_UE_TA: %fms, drift: %fµs/s\n", ntn_ta->epoch_sfn, ntn_ta->epoch_subframe, ntn_ta->cell_specific_k_offset, ntn_ta->N_common_ta_adj, ntn_ta->N_common_ta_drift, + ntn_ta->N_common_ta_drift_variant, ntn_ta->N_UE_TA_adj, ntn_ta->N_UE_TA_drift); } diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index aeecf2ecaf..9e4fc64e63 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -533,6 +533,8 @@ typedef struct ntn_timing_advance_components { double N_common_ta_adj; // drift rate of common ta in µs/s double N_common_ta_drift; + // change rate of common ta drift in µs/s² + double N_common_ta_drift_variant; // N_UE_TA_adj calculated round-trip-time between UE and SAT (ms) double N_UE_TA_adj; // drift rate of N_UE_TA in µs/s diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 58ccbac7b4..6f6e6746cf 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -2849,6 +2849,7 @@ static void schedule_ntn_config_command(fapi_nr_dl_config_request_t *dl_config, ntn_config_command_pdu->cell_specific_k_offset = mac->ntn_ta.cell_specific_k_offset; ntn_config_command_pdu->ntn_total_time_advance_ms = get_total_TA_ms(&mac->ntn_ta); ntn_config_command_pdu->ntn_total_time_advance_drift = get_total_TA_drift(&mac->ntn_ta); + ntn_config_command_pdu->ntn_total_time_advance_drift_variant = mac->ntn_ta.N_common_ta_drift_variant; dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_NTN_CONFIG_PARAMS; dl_config->number_pdus += 1; From 786f4877bcd39d1235eaaee8dd39270afa885963 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Thu, 24 Apr 2025 11:15:28 +0000 Subject: [PATCH 072/964] rfsimulator: for LEO NTN, update SIB19 information once for each frame --- radio/rfsimulator/apply_channelmod.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/radio/rfsimulator/apply_channelmod.c b/radio/rfsimulator/apply_channelmod.c index 1e873b8a2e..a976c63264 100644 --- a/radio/rfsimulator/apply_channelmod.c +++ b/radio/rfsimulator/apply_channelmod.c @@ -129,12 +129,14 @@ void rxAddInput(const c16_t *input_sig, LOG_I(HW, "Satellite orbit: time %f s, Position = (%f, %f, %f), Velocity = (%f, %f, %f)\n", t, pos_sat_x, pos_sat_y, pos_sat_z, vel_sat_x, vel_sat_y, vel_sat_z); LOG_I(HW, "Uplink delay %f ms, Doppler shift UE->SAT %f kHz\n", prop_delay * 1000, f_Doppler_shift_ue_sat / 1000); LOG_I(HW, "Satellite velocity towards gNB: %f m/s, acceleration towards gNB: %f m/s²\n", vel_sat_gnb, acc_sat_gnb); + } - const int samples_per_subframe = channelDesc->sampling_rate / 1000; - const int abs_subframe = TS / samples_per_subframe; + const int samples_per_subframe = channelDesc->sampling_rate / 1000; + const int abs_subframe = TS / samples_per_subframe; + if (abs_subframe % 10 == 0) { // update SIB19 information for the next frame gnb_sat_position_update_t sat_position = { - .sfn = (abs_subframe / 10) % 1024, - .subframe = abs_subframe % 10, + .sfn = (abs_subframe / 10 + 1) % 1024, + .subframe = 0, .delay = 2 * dist_sat_gnb / (c * 4.072e-9), .drift = 2 * -vel_sat_gnb / (c * 0.2e-9), .accel = 2 * acc_sat_gnb / (c * 0.2e-10), From a9a6ab367b6bc8adcba3901bb4760d6054b62eb7 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Thu, 22 May 2025 09:58:22 +0000 Subject: [PATCH 073/964] NR UE: fix autonomous_ta to be applied only when we also adjust the DL sync --- executables/nr-ue.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/executables/nr-ue.c b/executables/nr-ue.c index c4237cb914..e7b305c7d2 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -1097,9 +1097,6 @@ void *UE_thread(void *arg) UE->max_pos_acc = 0; shiftForNextFrame = -(UE->init_sync_frame + trashed_frames + 2) * UE->max_pos_acc * get_nrUE_params()->time_sync_I; // compensate for the time drift that happened during initial sync LOG_D(PHY, "max_pos_acc = %d, shiftForNextFrame = %d\n", UE->max_pos_acc, shiftForNextFrame); - // TODO: remove this autonomous TA and use up-to-date values of ta-Common, ta-CommonDrift and ta-CommonDriftVariant from received SIB19 instead - if (get_nrUE_params()->autonomous_ta) - UE->timing_advance -= 2 * shiftForNextFrame; // read in first symbol AssertFatal(fp->ofdm_symbol_size + fp->nb_prefix_samples0 == UE->rfdevice.trx_read_func(&UE->rfdevice, From 960f2e710122e92b2271645b48ec4f49843aff88 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Thu, 22 May 2025 09:59:57 +0000 Subject: [PATCH 074/964] NR UE: allow the epochTime-r17 in NTN-Config-r17 to be in the future The implementation is limited to epoch times that are not more than 5.12 seconds in the future (allowed are up to 10.24 seconds) and ntn-UlSyncValidityDuration < 5.12 seconds (allowed are up to 90 seconds). To fix this limitation, the hyper frame number HFN has to be introduced at the OAI UE! --- executables/nr-ue.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/executables/nr-ue.c b/executables/nr-ue.c index e7b305c7d2..1774000b8f 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -927,7 +927,15 @@ static inline void apply_ntn_config(PHY_VARS_NR_UE *UE, const int abs_subframe_tx = 10 * frame_rx + ((slot_rx + *duration_rx_to_tx) >> mu); const int abs_subframe_epoch = 10 * UE->ntn_config_message->ntn_config_params.epoch_sfn + UE->ntn_config_message->ntn_config_params.epoch_subframe; - const int ms_since_epoch = (abs_subframe_tx - abs_subframe_epoch + 10240) % 10240; + int ms_since_epoch = abs_subframe_tx - abs_subframe_epoch; + // cope with sfn wrap-around + // this currently limits us to epoch times that are not more than 5.12 seconds in the future (allowed are up to 10.24 seconds) + // and ntn-UlSyncValidityDuration < 5.12 seconds (allowed are up to 900 seconds) + // TODO: fix this limitation by introducing the hyper frame number HFN + if (ms_since_epoch < -5120) + ms_since_epoch += 10240; + else if (ms_since_epoch > 5120) + ms_since_epoch -= 10240; const double total_ta_ms = UE->ntn_config_message->ntn_config_params.ntn_total_time_advance_ms; const double total_ta_drift = UE->ntn_config_message->ntn_config_params.ntn_total_time_advance_drift; // µs/s From 1bb781b08cf72227e1d9d95197e847100115ad2e Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Fri, 20 Jun 2025 11:13:08 +0000 Subject: [PATCH 075/964] NR UE: trigger RRC timers based on RX frame and slot For NTN Epoch time calculations, we need to know the RX frame number. --- executables/nr-ue.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/executables/nr-ue.c b/executables/nr-ue.c index 1774000b8f..21048c8d52 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -1229,8 +1229,8 @@ void *UE_thread(void *arg) UE->N_TA_offset = new_N_TA_offset; } - if (curMsg.proc.nr_slot_tx == 0) - nr_ue_rrc_timer_trigger(UE->Mod_id, curMsg.proc.frame_tx, curMsg.proc.gNB_id); + if (curMsg.proc.nr_slot_rx == 0) + nr_ue_rrc_timer_trigger(UE->Mod_id, curMsg.proc.frame_rx, curMsg.proc.gNB_id); // RX slot processing. We launch and forget. notifiedFIFO_elt_t *newRx = newNotifiedFIFO_elt(sizeof(nr_rxtx_thread_data_t), curMsg.proc.nr_slot_tx, NULL, UE_dl_processing); From ef416234d9472eb672447e5ba59ed883478af909 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Fri, 20 Jun 2025 11:43:59 +0000 Subject: [PATCH 076/964] NR UE: enable logging of NTN RRC timer information To verify the NTN epoch time and NTN timer calculations, enable the logging by default. This only affects NTN configurations. --- openair2/RRC/NR_UE/rrc_UE.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 90713ff50c..3ff510c7f2 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -195,7 +195,7 @@ static void get_epochtime_from_sib19scheduling(NR_UE_RRC_SI_INFO *SI_info, int * int slot = slot_end_sib19_window % N; *subframe = ceil(slot / slots_per_subframe); - LOG_D(NR_RRC, + LOG_I(NR_RRC, "Get EPOCHTIME: x:%d, N:%d, slot_endw:%d, frame:%d, subframe:%d , slot:%d\n", x, N, @@ -228,7 +228,7 @@ static int eval_epoch_time(NR_UE_RRC_SI_INFO *SI_info, NR_NTN_Config_r17_t *ntnc // 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); + LOG_I(NR_RRC, "Epoch frame %d, ahead by %d frames\n", epoch_frame, diff_frames); return diff_frames; } @@ -248,7 +248,7 @@ static int get_ntn_timervalues(NR_UE_RRC_SI_INFO *SI_info, NR_NTN_Config_r17_t * 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); + LOG_I(NR_RRC, "val430:%d s, T430:%d ms, sib19_timer:%d ms\n", val430, *val430_ms, sib19_timer_ms); return sib19_timer_ms; } From a3bb97b6b7f1fe69422c89e8403ba09ea1105978 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Fri, 20 Jun 2025 13:55:45 +0000 Subject: [PATCH 077/964] gNB: set invalid NTN parameters in prepare_scc(), so fix_scc() will free them when not used --- openair2/GNB_APP/gnb_config.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 36ac8b6b1f..044dc56351 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -221,11 +221,18 @@ void prepare_scc(NR_ServingCellConfigCommon_t *scc) scc->ext2->ntn_Config_r17->ephemerisInfo_r17 = calloc_or_fail(1, sizeof(*scc->ext2->ntn_Config_r17->ephemerisInfo_r17)); scc->ext2->ntn_Config_r17->ta_Info_r17 = calloc_or_fail(1, sizeof(*scc->ext2->ntn_Config_r17->ta_Info_r17)); + scc->ext2->ntn_Config_r17->ta_Info_r17->ta_Common_r17 = -1; scc->ext2->ntn_Config_r17->ta_Info_r17->ta_CommonDrift_r17 = calloc_or_fail(1, sizeof(*scc->ext2->ntn_Config_r17->ta_Info_r17->ta_CommonDrift_r17)); scc->ext2->ntn_Config_r17->ephemerisInfo_r17->present = NR_EphemerisInfo_r17_PR_positionVelocity_r17; scc->ext2->ntn_Config_r17->ephemerisInfo_r17->choice.positionVelocity_r17 = calloc_or_fail(1, sizeof(*scc->ext2->ntn_Config_r17->ephemerisInfo_r17->choice.positionVelocity_r17)); + scc->ext2->ntn_Config_r17->ephemerisInfo_r17->choice.positionVelocity_r17->positionX_r17 = LONG_MAX; + scc->ext2->ntn_Config_r17->ephemerisInfo_r17->choice.positionVelocity_r17->positionY_r17 = LONG_MAX; + scc->ext2->ntn_Config_r17->ephemerisInfo_r17->choice.positionVelocity_r17->positionZ_r17 = LONG_MAX; + scc->ext2->ntn_Config_r17->ephemerisInfo_r17->choice.positionVelocity_r17->velocityVX_r17 = LONG_MAX; + scc->ext2->ntn_Config_r17->ephemerisInfo_r17->choice.positionVelocity_r17->velocityVY_r17 = LONG_MAX; + scc->ext2->ntn_Config_r17->ephemerisInfo_r17->choice.positionVelocity_r17->velocityVZ_r17 = LONG_MAX; } void prepare_msgA_scc(NR_ServingCellConfigCommon_t *scc) { NR_BWP_UplinkCommon_t *initialUplinkBWP = scc->uplinkConfigCommon->initialUplinkBWP; From 7b991c4dbfae15bf3022a6198d4256e4fca250db Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Fri, 20 Jun 2025 13:58:55 +0000 Subject: [PATCH 078/964] NR UE: exit from configure_ntn_ta() if ntn_Config_r17 is not provided --- openair2/LAYER2/NR_MAC_UE/config_ue.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index ad7ae1a338..e3535843fe 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -298,6 +298,9 @@ static void configure_ntn_ta(module_id_t module_id, ntn_timing_advance_componets_t *ntn_ta, const NR_NTN_Config_r17_t *ntn_Config_r17) { + if (!ntn_Config_r17) + return; + position_t position_params = {0}; get_position_coordinates(module_id, &position_params); From a0974f7c730ea1878b4f317669fd9b3017f99882 Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Mon, 23 Jun 2025 10:02:21 +0200 Subject: [PATCH 079/964] nr pdcp security: add a 'decipher' API function --- openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c | 10 ++++++---- openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h | 3 +++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c index f3402bcf81..41d41cf922 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c @@ -136,10 +136,10 @@ static void nr_pdcp_entity_recv_pdu(nr_pdcp_entity_t *entity, } if (entity->has_ciphering) - entity->cipher(entity->security_context, - buffer + header_size + sdap_header_size, - size - (header_size + sdap_header_size), - entity->rb_id, rcvd_count, entity->is_gnb ? 0 : 1); + entity->decipher(entity->security_context, + buffer + header_size + sdap_header_size, + size - (header_size + sdap_header_size), + entity->rb_id, rcvd_count, entity->is_gnb ? 0 : 1); if (entity->has_integrity) { unsigned char integrity[PDCP_INTEGRITY_SIZE] = {0}; @@ -380,10 +380,12 @@ static void nr_pdcp_entity_set_security(struct nr_pdcp_entity_t *entity, if (parameters->ciphering_algorithm == 2) { entity->security_context = nr_pdcp_security_nea2_init(entity->security_keys_and_algos.ciphering_key); entity->cipher = nr_pdcp_security_nea2_cipher; + entity->decipher = nr_pdcp_security_nea2_cipher; entity->free_security = nr_pdcp_security_nea2_free_security; } else if (parameters->ciphering_algorithm == 1) { entity->security_context = nr_pdcp_security_nea1_init(entity->security_keys_and_algos.ciphering_key); entity->cipher = nr_pdcp_security_nea1_cipher; + entity->decipher = nr_pdcp_security_nea1_cipher; entity->free_security = nr_pdcp_security_nea1_free_security; } else { LOG_E(PDCP, "FATAL: only nea1 and nea2 supported for the moment\n"); diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h index f05ba07b02..7f1297ac3e 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h @@ -156,6 +156,9 @@ typedef struct nr_pdcp_entity_t { void (*cipher)(stream_security_context_t *security_context, unsigned char *buffer, int length, int bearer, uint32_t count, int direction); + void (*decipher)(stream_security_context_t *security_context, + unsigned char *buffer, int length, + int bearer, uint32_t count, int direction); void (*free_security)(stream_security_context_t *security_context); stream_security_context_t *integrity_context; void (*integrity)(stream_security_context_t *integrity_context, From 260135a35b3c04372a62cdf5a7277ae650621512 Mon Sep 17 00:00:00 2001 From: luis_pereira87 Date: Mon, 23 Jun 2025 11:00:51 +0100 Subject: [PATCH 080/964] Fix Msg3 with MAC CE for C-RNTI and RRCReestablishmentComplete Only trigger RRCReconfiguration if UE is not performing RRCReestablishment The RRCReconfiguration will be triggered by the RRCReestablishmentComplete --- .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 37 +++++++++++-------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 3fa16f6a51..534b955f7b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -269,7 +269,7 @@ static rnti_t lcid_crnti_lookahead(uint8_t *pdu, uint32_t pdu_len) if (lcid == UL_SCH_LCID_C_RNTI) { // Extract C-RNTI value rnti_t crnti = ((pdu[1] & 0xFF) << 8) | (pdu[2] & 0xFF); - LOG_D(NR_MAC, "Received a MAC CE for C-RNTI with %04x\n", crnti); + LOG_A(NR_MAC, "Received a MAC CE for C-RNTI with %04x\n", crnti); return crnti; } else if (lcid == UL_SCH_LCID_PADDING) { // End of MAC PDU, can ignore the remaining bytes @@ -783,26 +783,33 @@ static void nr_rx_ra_sdu(const module_id_t mod_id, // Reset HARQ processes reset_dl_harq_list(&old_UE->UE_sched_ctrl); reset_ul_harq_list(&old_UE->UE_sched_ctrl); - // Trigger RRC Reconfiguration - LOG_I(NR_MAC, "Received UL_SCH_LCID_C_RNTI with C-RNTI 0x%04x, triggering RRC Reconfiguration\n", crnti); - nr_mac_trigger_reconfiguration(mac, old_UE); + + // Only trigger RRCReconfiguration if UE is not performing RRCReestablishment + // The RRCReconfiguration will be triggered by the RRCReestablishmentComplete + if (!old_UE->reconfigSpCellConfig) { + LOG_I(NR_MAC, "Received UL_SCH_LCID_C_RNTI with C-RNTI 0x%04x, triggering RRC Reconfiguration\n", crnti); + // Trigger RRCReconfiguration + nr_mac_trigger_reconfiguration(mac, old_UE); + // we configure the UE using common search space with DCIX0 while waiting for a reconfiguration + configure_UE_BWP(mac, scc, old_UE, false, NR_SearchSpace__searchSpaceType_PR_common, -1, -1); + } nr_release_ra_UE(mac, rnti); - LOG_A(NR_MAC, "%4d.%2d UE %04x: RA with C-RNTI complete\n", frame, slot, crnti); - // we configure the UE using common search space with DCIX0 while waiting for a reconfiguration - configure_UE_BWP(mac, scc, old_UE, false, NR_SearchSpace__searchSpaceType_PR_common, -1, -1); - // TODO do we actually need to still process the PDU? + LOG_A(NR_MAC, "%4d.%2d RA with C-RNTI %04x complete\n", frame, slot, crnti); + + // Decode the entire MAC PDU + // It may have multiple MAC subPDUs, for example, a MAC subPDU with LCID 1 caring a RRCReestablishmentComplete nr_process_mac_pdu(mod_id, old_UE, CC_id, frame, slot, sdu, sdu_len, -1); return; - } else { - // UE Contention Resolution Identity - // Store the first 48 bits belonging to the uplink CCCH SDU within Msg3 to fill in Msg4 - // First byte corresponds to R/LCID MAC sub-header - memcpy(ra->cont_res_id, &sdu[1], sizeof(uint8_t) * 6); } - // Decode MAC PDU for the correct UE, after checking for MAC CE for C-RNTI - // harq_pid set a non valid value because it is not used in this call + // UE Contention Resolution Identity + // Store the first 48 bits belonging to the uplink CCCH SDU within Msg3 to fill in Msg4 + // First byte corresponds to R/LCID MAC sub-header + memcpy(ra->cont_res_id, &sdu[1], sizeof(uint8_t) * 6); + + // Decode MAC PDU // the function is only called to decode the contention resolution sub-header + // harq_pid set a non-valid value because it is not used in this call nr_process_mac_pdu(mod_id, UE, CC_id, frame, slot, sdu, sdu_len, -1); LOG_I(NR_MAC, From 319f5961a142b40e4a02745503452ca1181c9de1 Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Tue, 24 Jun 2025 12:44:21 +0200 Subject: [PATCH 081/964] bugfix: read msg_type only after deciphering --- openair3/NAS/NR_UE/nr_nas_msg.c | 88 +++++++++++++++++---------------- 1 file changed, 45 insertions(+), 43 deletions(-) diff --git a/openair3/NAS/NR_UE/nr_nas_msg.c b/openair3/NAS/NR_UE/nr_nas_msg.c index d7fb313fa8..4e645c28b2 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg.c +++ b/openair3/NAS/NR_UE/nr_nas_msg.c @@ -300,7 +300,44 @@ static void nas_security_decrypt_payload(nr_ue_nas_t *nas, byte_array_t buffer, free(decrypted); } -static security_state_t nas_security_rx_process(nr_ue_nas_t *nas, byte_array_t buffer, fgs_nas_msg_t msg_type) +static fgs_nas_msg_t get_msg_type(uint8_t *pdu_buffer, uint32_t length) +{ + if (pdu_buffer == NULL) + goto error; + + /* get security header type */ + if (length < 2) + goto error; + + int security_header_type = pdu_buffer[1]; + + if (security_header_type == 0) { + /* plain NAS message */ + if (length < 3) + goto error; + return pdu_buffer[2]; + } + + if (length < 10) + goto error; + + int msg_type = pdu_buffer[9]; + + if (msg_type == FGS_DOWNLINK_NAS_TRANSPORT) { + if (length < 17) + goto error; + + msg_type = pdu_buffer[16]; + } + + return msg_type; + +error: + LOG_E(NAS, "[UE] Received invalid downlink message\n"); + return 0; +} + +static security_state_t nas_security_rx_process(nr_ue_nas_t *nas, byte_array_t buffer) { if (nas->security_container == NULL) return NAS_SECURITY_NO_SECURITY_CONTEXT; @@ -313,9 +350,11 @@ static security_state_t nas_security_rx_process(nr_ue_nas_t *nas, byte_array_t b LOG_D(NAS, "Security type is: %s\n", print_info(security_type, security_header_type_s, sizeofArray(security_header_type_s))); switch (security_type) { - case PLAIN_5GS_MSG: + case PLAIN_5GS_MSG: { + fgs_nas_msg_t msg_type = get_msg_type(buffer.buf, buffer.len); return unprotected_allowed(buffer, msg_type) ? NAS_SECURITY_UNPROTECTED : NAS_SECURITY_BAD_INPUT; break; + } case INTEGRITY_PROTECTED_WITH_NEW_SECU_CTX: stream_security_container_delete(nas->security_container); nas->security_container = NULL; @@ -1679,43 +1718,6 @@ static void generatePduSessionEstablishRequest(nr_ue_nas_t *nas, as_nas_info_t * } } -static fgs_nas_msg_t get_msg_type(uint8_t *pdu_buffer, uint32_t length) -{ - if (pdu_buffer == NULL) - goto error; - - /* get security header type */ - if (length < 2) - goto error; - - int security_header_type = pdu_buffer[1]; - - if (security_header_type == 0) { - /* plain NAS message */ - if (length < 3) - goto error; - return pdu_buffer[2]; - } - - if (length < 10) - goto error; - - int msg_type = pdu_buffer[9]; - - if (msg_type == FGS_DOWNLINK_NAS_TRANSPORT) { - if (length < 17) - goto error; - - msg_type = pdu_buffer[16]; - } - - return msg_type; - -error: - LOG_E(NAS, "[UE] Received invalid downlink message\n"); - return 0; -} - static void send_nas_uplink_data_req(nr_ue_nas_t *nas, const as_nas_info_t *initial_nas_msg) { MessageDef *msg = itti_alloc_new_message(TASK_NAS_NRUE, nas->UE_id, NAS_UPLINK_DATA_REQ); @@ -1975,13 +1977,13 @@ void *nas_nrue(void *args_p) NAS_CONN_ESTABLI_CNF(msg_p).nasMsg.length); byte_array_t ba = {.buf = NAS_CONN_ESTABLI_CNF(msg_p).nasMsg.nas_data, .len = NAS_CONN_ESTABLI_CNF(msg_p).nasMsg.length}; - fgs_nas_msg_t msg_type = get_msg_type(ba.buf, ba.len); - security_state_t security_state = nas_security_rx_process(nas, ba, msg_type); + security_state_t security_state = nas_security_rx_process(nas, ba); if (security_state > NAS_SECURITY_INTEGRITY_PASSED) { LOG_E(NAS, "NAS integrity failed, discard incoming message: security state is %s\n", security_state_info[security_state].text); break; } + fgs_nas_msg_t msg_type = get_msg_type(ba.buf, ba.len); if (msg_type == FGS_REGISTRATION_ACCEPT) { handle_registration_accept(nas, ba.buf, ba.len); } else if (msg_type == FGS_PDU_SESSION_ESTABLISHMENT_ACC) { @@ -2043,13 +2045,13 @@ void *nas_nrue(void *args_p) uint8_t *pdu_buffer = NAS_DOWNLINK_DATA_IND(msg_p).nasMsg.nas_data; int pdu_length = NAS_DOWNLINK_DATA_IND(msg_p).nasMsg.length; byte_array_t buffer = {.buf = pdu_buffer, .len = pdu_length}; - fgs_nas_msg_t msg_type = get_msg_type(pdu_buffer, pdu_length); - security_state_t security_state = nas_security_rx_process(nas, buffer, msg_type); + security_state_t security_state = nas_security_rx_process(nas, buffer); if (security_state > NAS_SECURITY_INTEGRITY_PASSED) { LOG_E(NAS, "NAS integrity failed, discard incoming message\n"); break; } + fgs_nas_msg_t msg_type = get_msg_type(pdu_buffer, pdu_length); LOG_I(NAS, "[UE %ld] Received %s type %s with length %u\n", nas->UE_id, From c3a11c4717fccbf943ef02e6058b07b72e7fc34b Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Tue, 24 Jun 2025 14:28:09 +0000 Subject: [PATCH 082/964] NR UE: fix condition when to print the error message in write_reorder_clear_context() We should print the error message when the mutex cannot be locked because it is already locked. Unfortunately, the if() condition was inverted... --- radio/COMMON/common_lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radio/COMMON/common_lib.c b/radio/COMMON/common_lib.c index 14b66d7060..670a9cc852 100644 --- a/radio/COMMON/common_lib.c +++ b/radio/COMMON/common_lib.c @@ -276,7 +276,7 @@ void openair0_write_reorder_clear_context(openair0_device *device) re_order_t *ctx = &device->reOrder; if (!ctx->initDone) return; - if (pthread_mutex_trylock(&ctx->mutex_write) == 0) + if (pthread_mutex_trylock(&ctx->mutex_write) != 0) LOG_E(HW, "write_reorder_clear_context call while still writing on the device\n"); pthread_mutex_destroy(&ctx->mutex_write); pthread_mutex_lock(&ctx->mutex_store); From 5856c897412261606ffab015ac5298bbbbbc8563 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Tue, 24 Jun 2025 14:33:35 +0000 Subject: [PATCH 083/964] NR UE: do not select a suspended LCID for scheduling This fixes a lifelock in nr_ue_get_sdu(), because select_logical_channels() would select a suspended LCID for scheduling, but fill_mac_sdu() would not provide data for it. --- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 2c37b21f5b..23e9cb04e8 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -2539,10 +2539,13 @@ static uint select_logical_channels(NR_UE_MAC_INST_t *mac, nr_lcordered_info_t * int nb = 0; // selection of logical channels with Bj > 0 for (int i = 0; i < mac->lc_ordered_list.count; i++) { - int lcid = mac->lc_ordered_list.array[i]->lcid; + 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 *sched_info = get_scheduling_info_from_lcid(mac, lcid); if (sched_info->Bj > 0) { - active_lcids[nb++] = *mac->lc_ordered_list.array[i]; + active_lcids[nb++] = *lc_info; LOG_D(NR_MAC, "The available lcid is %d with total active channels count = %d\n", lcid, nb); } } From c7cb7896a0db94112f4c659c047b030014c7db41 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Tue, 24 Jun 2025 16:43:26 +0200 Subject: [PATCH 084/964] CI: add a test with AS ciphering + integrity --- ci-scripts/conf_files/gnb.sa.band77.273prb.usrpn310.2x2.conf | 4 ++-- ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ci-scripts/conf_files/gnb.sa.band77.273prb.usrpn310.2x2.conf b/ci-scripts/conf_files/gnb.sa.band77.273prb.usrpn310.2x2.conf index d14493376f..5567d233d4 100644 --- a/ci-scripts/conf_files/gnb.sa.band77.273prb.usrpn310.2x2.conf +++ b/ci-scripts/conf_files/gnb.sa.band77.273prb.usrpn310.2x2.conf @@ -213,7 +213,7 @@ security = { # preferred ciphering algorithms # the first one of the list that an UE supports in chosen # valid values: nea0, nea1, nea2, nea3 - ciphering_algorithms = ( "nea0" ); + ciphering_algorithms = ( "nea2", "nea0" ); # preferred integrity algorithms # the first one of the list that an UE supports in chosen @@ -223,7 +223,7 @@ security = { # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' drb_ciphering = "yes"; - drb_integrity = "no"; + drb_integrity = "yes"; }; log_config : diff --git a/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf b/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf index d92f096f24..62a7830541 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf @@ -212,7 +212,7 @@ security = { # preferred ciphering algorithms # the first one of the list that an UE supports in chosen # valid values: nea0, nea1, nea2, nea3 - ciphering_algorithms = ( "nea0" ); + ciphering_algorithms = ( "nea2", "nea0" ); # preferred integrity algorithms # the first one of the list that an UE supports in chosen @@ -222,7 +222,7 @@ security = { # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' drb_ciphering = "yes"; - drb_integrity = "no"; + drb_integrity = "yes"; }; log_config : From ed54e0bbd120e8abf2084577f9c0926cb6aa6676 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Tue, 24 Jun 2025 14:38:27 +0000 Subject: [PATCH 085/964] NR_UE: make lcids_bj_pos an array of nr_lcordered_info_t pointers instead of structure elements This makes the array itself smaller and allows to store just a pointer in select_logical_channels() instead of copying the complete structure element. --- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 23e9cb04e8..5539ce08ef 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -2466,13 +2466,13 @@ static void nr_ue_get_sdu_mac_ce_post(NR_UE_MAC_INST_t *mac, mac_ce_p->cur_ptr += size; } -uint32_t get_count_lcids_same_priority(uint8_t start, uint8_t total_active_lcids, nr_lcordered_info_t *lcid_ordered_array) +static uint32_t get_count_lcids_same_priority(uint8_t start, uint8_t total_active_lcids, nr_lcordered_info_t *lcid_ordered_array[]) { // count number of logical channels with same priority as curr_lcid uint8_t same_priority_count = 0; - uint8_t curr_lcid = lcid_ordered_array[start].lcid; + uint8_t curr_lcid = lcid_ordered_array[start]->lcid; for (uint8_t index = start; index < total_active_lcids; index++) { - if (lcid_ordered_array[start].priority == lcid_ordered_array[index].priority) { + if (lcid_ordered_array[start]->priority == lcid_ordered_array[index]->priority) { same_priority_count++; } } @@ -2520,11 +2520,13 @@ static long get_num_bytes_to_reqlc(NR_UE_MAC_INST_t *mac, return num_bytes_requested; } -bool get_dataavailability_buffers(uint8_t total_active_lcids, nr_lcordered_info_t *lcid_ordered_array, bool *data_status_lcbuffers) +static bool get_dataavailability_buffers(uint8_t total_active_lcids, + nr_lcordered_info_t *lcid_ordered_array[], + bool *data_status_lcbuffers) { // check whether there is any data in the rlc buffer corresponding to active lcs for (uint8_t id = 0; id < total_active_lcids; id++) { - int lcid = lcid_ordered_array[id].lcid; + int lcid = lcid_ordered_array[id]->lcid; if (data_status_lcbuffers[lcid_buffer_index(lcid)]) { return true; } @@ -2532,7 +2534,7 @@ bool get_dataavailability_buffers(uint8_t total_active_lcids, nr_lcordered_info_ return false; } -static uint select_logical_channels(NR_UE_MAC_INST_t *mac, nr_lcordered_info_t *active_lcids) +static uint select_logical_channels(NR_UE_MAC_INST_t *mac, nr_lcordered_info_t *active_lcids[]) { // (TODO: selection of logical channels for logical channel prioritization procedure as per 5.4.3.1.2 Selection of logical // channels, TS38.321) @@ -2545,7 +2547,7 @@ static uint select_logical_channels(NR_UE_MAC_INST_t *mac, nr_lcordered_info_t * int lcid = lc_info->lcid; NR_LC_SCHEDULING_INFO *sched_info = get_scheduling_info_from_lcid(mac, lcid); if (sched_info->Bj > 0) { - active_lcids[nb++] = *lc_info; + active_lcids[nb++] = lc_info; LOG_D(NR_MAC, "The available lcid is %d with total active channels count = %d\n", lcid, nb); } } @@ -2734,7 +2736,7 @@ static uint8_t nr_ue_get_sdu(NR_UE_MAC_INST_t *mac, LOG_E(NR_MAC, "Failed to init lcids_bj_pos: mac->lc_ordered_list.count = 0\n"); return 0; } - nr_lcordered_info_t lcids_bj_pos[mac->lc_ordered_list.count]; + nr_lcordered_info_t *lcids_bj_pos[mac->lc_ordered_list.count]; int avail_lcids_count = select_logical_channels(mac, lcids_bj_pos); // multiplex in the order of highest priority @@ -2755,7 +2757,7 @@ static uint8_t nr_ue_get_sdu(NR_UE_MAC_INST_t *mac, still space availble in the MAC PDU, then from the next run all the remaining data from the higher priority logical channel is placed in the MAC PDU before going on to next high priority logical channel */ - int lcid = lcids_bj_pos[id].lcid; + int lcid = lcids_bj_pos[id]->lcid; int idx = lcid_buffer_index(lcid); // skip the logical channel if no data in the buffer initially or the data in the buffer was zero because it was written in to // MAC PDU From 528e42c357cdb892006ee976cc487e29472bffc5 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 19 Jun 2025 13:31:58 +0200 Subject: [PATCH 086/964] Update/refine MAC stats Print a number of statistics, e.g., rx_ulsch_sdu to track UL MAC stats timing. Remove unused time_meas_t definitions, and fix the name for the total gNB scheduler time. --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c | 6 +++-- .../LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 2 -- .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 2 ++ openair2/LAYER2/NR_MAC_gNB/main.c | 6 +++-- openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 26 +++++-------------- 5 files changed, 17 insertions(+), 25 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c index dfe4cfeea2..b4bfaa7a05 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c @@ -174,7 +174,7 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frame, slot_t slo clear_beam_information(&gNB->beam_info, frame, slot, slots_frame); gNB->frame = frame; - start_meas(&gNB->eNB_scheduler); + start_meas(&gNB->gNB_scheduler); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_DLSCH_ULSCH_SCHEDULER,VCD_FUNCTION_IN); for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { @@ -244,7 +244,9 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frame, slot_t slo } // This schedules the DCI for Uplink and subsequently PUSCH + start_meas(&gNB->schedule_ulsch); nr_schedule_ulsch(module_idP, frame, slot, &sched_info->UL_dci_req); + stop_meas(&gNB->schedule_ulsch); // This schedules the DCI for Downlink and PDSCH start_meas(&gNB->schedule_dlsch); @@ -262,7 +264,7 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frame, slot_t slo const int current_index = ul_buffer_index(frame, slot, slots_frame, gNB->UL_tti_req_ahead_size); copy_ul_tti_req(&sched_info->UL_tti_req, &gNB->UL_tti_req_ahead[0][current_index]); - stop_meas(&gNB->eNB_scheduler); + stop_meas(&gNB->gNB_scheduler); NR_SCHED_UNLOCK(&gNB->sched_lock); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_DLSCH_ULSCH_SCHEDULER,VCD_FUNCTION_OUT); } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index cb3c1bf801..c47b54d268 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -340,9 +340,7 @@ static void nr_store_dlsch_buffer(module_id_t module_id, frame_t frame, slot_t s continue; if (lcid == DL_SCH_LCID_DTCH && nr_timer_is_active(&sched_ctrl->transm_interrupt)) continue; - start_meas(&RC.nrmac[module_id]->rlc_status_ind); sched_ctrl->rlc_status[lcid] = nr_mac_rlc_status_ind(rnti, frame, lcid); - stop_meas(&RC.nrmac[module_id]->rlc_status_ind); if (sched_ctrl->rlc_status[lcid].bytes_in_buffer == 0) continue; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 3fa16f6a51..3b6fe62d8a 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -954,7 +954,9 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP, { gNB_MAC_INST *gNB_mac = RC.nrmac[gnb_mod_idP]; NR_SCHED_LOCK(&gNB_mac->sched_lock); + start_meas(&gNB_mac->rx_ulsch_sdu); _nr_rx_sdu(gnb_mod_idP, CC_idP, frameP, slotP, rntiP, sduP, sdu_lenP, harq_pid, timing_advance, ul_cqi, rssi); + stop_meas(&gNB_mac->rx_ulsch_sdu); NR_SCHED_UNLOCK(&gNB_mac->sched_lock); } diff --git a/openair2/LAYER2/NR_MAC_gNB/main.c b/openair2/LAYER2/NR_MAC_gNB/main.c index e7c43ed204..d547cd52c9 100644 --- a/openair2/LAYER2/NR_MAC_gNB/main.c +++ b/openair2/LAYER2/NR_MAC_gNB/main.c @@ -88,10 +88,12 @@ void *nrmac_stats_thread(void *arg) { p += dump_mac_stats(gNB, p, end - p, false); NR_SCHED_UNLOCK(&gNB->sched_lock); p += snprintf(p, end - p, "\n"); - p += print_meas_log(&gNB->eNB_scheduler, "DL & UL scheduling timing", NULL, NULL, p, end - p); + p += print_meas_log(&gNB->gNB_scheduler, "gNB_scheduler", NULL, NULL, p, end - p); + p += print_meas_log(&gNB->rx_ulsch_sdu, "rx_ulsch_sdu", NULL, NULL, p, end - p); p += print_meas_log(&gNB->schedule_dlsch, "dlsch scheduler", NULL, NULL, p, end - p); + p += print_meas_log(&gNB->schedule_ulsch, "ulsch scheduler", NULL, NULL, p, end - p); + p += print_meas_log(&gNB->schedule_ra, "RA scheduler", NULL, NULL, p, end - p); p += print_meas_log(&gNB->rlc_data_req, "rlc_data_req", NULL, NULL, p, end - p); - p += print_meas_log(&gNB->rlc_status_ind, "rlc_status_ind", NULL, NULL, p, end - p); p += print_meas_log(&gNB->nr_srs_ri_computation_timer, "UL-RI computation time", NULL, NULL, p, end - p); p += print_meas_log(&gNB->nr_srs_tpmi_computation_timer, "UL-TPMI computation time", NULL, NULL, p, end - p); fwrite(output, p - output, 1, file); diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 49a18d3eac..3d37259762 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -849,34 +849,22 @@ typedef struct gNB_MAC_INST_s { NR_UEs_t UE_info; // MAC function execution peformance profiler - /// processing time of eNB scheduler - time_stats_t eNB_scheduler; - /// processing time of eNB scheduler for SI - time_stats_t schedule_si; - /// processing time of eNB scheduler for Random access + /// processing time of gNB scheduler + time_stats_t gNB_scheduler; + /// processing time of gNB scheduler for Random access time_stats_t schedule_ra; - /// processing time of eNB ULSCH scheduler - time_stats_t schedule_ulsch; - /// processing time of eNB DCI generation - time_stats_t fill_DLSCH_dci; - /// processing time of eNB MAC preprocessor - time_stats_t schedule_dlsch_preprocessor; - /// processing time of eNB DLSCH scheduler + /// processing time of gNB DLSCH scheduler + time_stats_t schedule_ulsch; // include preprocessor + /// processing time of gNB DLSCH scheduler time_stats_t schedule_dlsch; // include rlc_data_req + MAC header + preprocessor /// processing time of rlc_data_req time_stats_t rlc_data_req; - /// processing time of rlc_status_ind - time_stats_t rlc_status_ind; /// processing time of nr_srs_ri_computation time_stats_t nr_srs_ri_computation_timer; /// processing time of nr_srs_tpmi_estimation time_stats_t nr_srs_tpmi_computation_timer; - /// processing time of eNB MCH scheduler - time_stats_t schedule_mch; - /// processing time of eNB ULSCH reception + /// processing time of gNB ULSCH reception time_stats_t rx_ulsch_sdu; // include rlc_data_ind - /// processing time of eNB PCH scheduler - time_stats_t schedule_pch; NR_beam_info_t beam_info; From d66986a23fa83aa2aba0b0692cbf21d0b9ed99d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Soares=20Silva?= Date: Mon, 9 Sep 2024 09:36:52 +0100 Subject: [PATCH 087/964] Use P5 copy function for config.request instead of memcpy --- CMakeLists.txt | 2 +- openair1/PHY/INIT/nr_init.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 38168ae460..cc30b7a5bd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1047,7 +1047,7 @@ add_library(PHY_NR_COMMON ${PHY_NR_SRC_COMMON}) target_link_libraries(PHY_NR_COMMON PUBLIC UTIL) add_library(PHY_NR ${PHY_NR_SRC}) -target_link_libraries(PHY_NR nr_phy_common nr_common) +target_link_libraries(PHY_NR nr_phy_common nr_common nr_fapi_p5) add_library(PHY_NR_NO_AVX_256 ${PHY_NR_SRC}) target_link_libraries(PHY_NR_NO_AVX_256 nr_phy_common nr_common) diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c index ca453b6e65..7a706f61bf 100644 --- a/openair1/PHY/INIT/nr_init.c +++ b/openair1/PHY/INIT/nr_init.c @@ -42,6 +42,7 @@ #include "SCHED_NR/fapi_nr_l1.h" #include "PHY/NR_REFSIG/ul_ref_seq_nr.h" #include +#include "nfapi/open-nFAPI/fapi/inc/nr_fapi_p5_utils.h" int l1_north_init_gNB() { @@ -363,7 +364,7 @@ void nr_phy_config_request(NR_PHY_Config_t *phy_config) NR_DL_FRAME_PARMS *fp = &RC.gNB[Mod_id]->frame_parms; nfapi_nr_config_request_scf_t *gNB_config = &RC.gNB[Mod_id]->gNB_config; - memcpy((void*)gNB_config,phy_config->cfg,sizeof(*phy_config->cfg)); + copy_config_request(phy_config->cfg, gNB_config); uint64_t dl_bw_khz = (12*gNB_config->carrier_config.dl_grid_size[gNB_config->ssb_config.scs_common.value].value)*(15<ssb_config.scs_common.value); fp->dl_CarrierFreq = ((dl_bw_khz>>1) + gNB_config->carrier_config.dl_frequency.value)*1000 ; From 1ea164468ff1d27b03696d9b6bf0deb3e129c6eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Soares=20Silva?= Date: Mon, 2 Dec 2024 09:29:12 +0000 Subject: [PATCH 088/964] Refactor fapi_nr_p5_message_unpack to have the same signature as nfapi_nr_p5_message_header_unpack. This change is done in preparation to add the header unpack functions to the VNF and PNF structures as function pointers, used to peek the message headers prior to processing. Add a faux fapi_nr_p7_message_header_unpack with the same signature as nfapi_nr_p7_message_header_unpack, to be used for the P7 header unpack function pointer. --- nfapi/open-nFAPI/fapi/inc/nr_fapi.h | 7 +++++- nfapi/open-nFAPI/fapi/src/nr_fapi.c | 23 +++++++++++++++---- nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c | 7 +++--- nfapi/open-nFAPI/fapi/src/nr_fapi_p7.c | 9 ++++---- nfapi/tests/p5/nr_fapi_config_request_test.c | 2 +- nfapi/tests/p5/nr_fapi_config_response_test.c | 2 +- .../tests/p5/nr_fapi_error_indication_test.c | 2 +- nfapi/tests/p5/nr_fapi_param_request_test.c | 2 +- nfapi/tests/p5/nr_fapi_param_response_test.c | 2 +- nfapi/tests/p5/nr_fapi_start_request_test.c | 2 +- nfapi/tests/p5/nr_fapi_start_response_test.c | 2 +- nfapi/tests/p5/nr_fapi_stop_indication_test.c | 2 +- nfapi/tests/p5/nr_fapi_stop_request_test.c | 2 +- nfapi/tests/p7/nr_fapi_crc_indication_test.c | 2 +- nfapi/tests/p7/nr_fapi_dl_tti_request_test.c | 2 +- nfapi/tests/p7/nr_fapi_rach_indication_test.c | 2 +- .../p7/nr_fapi_rx_data_indication_test.c | 2 +- nfapi/tests/p7/nr_fapi_slot_indication_test.c | 2 +- nfapi/tests/p7/nr_fapi_srs_indication_test.c | 2 +- nfapi/tests/p7/nr_fapi_tx_data_request_test.c | 2 +- nfapi/tests/p7/nr_fapi_uci_indication_test.c | 2 +- nfapi/tests/p7/nr_fapi_ul_dci_request_test.c | 2 +- nfapi/tests/p7/nr_fapi_ul_tti_request_test.c | 2 +- 23 files changed, 50 insertions(+), 34 deletions(-) diff --git a/nfapi/open-nFAPI/fapi/inc/nr_fapi.h b/nfapi/open-nFAPI/fapi/inc/nr_fapi.h index ee405792d2..fcf4b97973 100644 --- a/nfapi/open-nFAPI/fapi/inc/nr_fapi.h +++ b/nfapi/open-nFAPI/fapi/inc/nr_fapi.h @@ -77,10 +77,15 @@ bool isFAPIMessageIDValid(uint16_t id); int check_nr_fapi_unpack_length(nfapi_nr_phy_msg_type_e msgId, uint32_t unpackedBufLen); -int fapi_nr_message_header_unpack(uint8_t **pMessageBuf, +int fapi_nr_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t *config); +int fapi_nr_p7_message_header_unpack(void *pMessageBuf, + uint32_t messageBufLen, + void *pUnpackedBuf, + uint32_t unpackedBufLen, + nfapi_p7_codec_config_t *config); #endif // OPENAIRINTERFACE_NR_FAPI_H diff --git a/nfapi/open-nFAPI/fapi/src/nr_fapi.c b/nfapi/open-nFAPI/fapi/src/nr_fapi.c index c36fff4b34..475b6c07dd 100644 --- a/nfapi/open-nFAPI/fapi/src/nr_fapi.c +++ b/nfapi/open-nFAPI/fapi/src/nr_fapi.c @@ -165,13 +165,26 @@ int check_nr_fapi_unpack_length(nfapi_nr_phy_msg_type_e msgId, uint32_t unpacked return retLen; } -int fapi_nr_message_header_unpack(uint8_t **pMessageBuf, +int fapi_nr_p7_message_header_unpack(void *pMessageBuf, + uint32_t messageBufLen, + void *pUnpackedBuf, + uint32_t unpackedBufLen, + nfapi_p7_codec_config_t *config) +{ + return fapi_nr_message_header_unpack(pMessageBuf, + messageBufLen, + pUnpackedBuf, + unpackedBufLen, + NULL); +} + +int fapi_nr_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t *config) { - uint8_t **pReadPackedMessage = pMessageBuf; + uint8_t *pReadPackedMessage = pMessageBuf; nfapi_nr_p4_p5_message_header_t *header = pUnpackedBuf; fapi_message_header_t fapi_msg = {0}; @@ -179,10 +192,10 @@ int fapi_nr_message_header_unpack(uint8_t **pMessageBuf, || unpackedBufLen < sizeof(fapi_message_header_t)) { return -1; } - uint8_t *end = *pMessageBuf + messageBufLen; + uint8_t *end = pMessageBuf + messageBufLen; // process the header int result = - (pull8(pReadPackedMessage, &fapi_msg.num_msg, end) && pull8(pReadPackedMessage, &fapi_msg.opaque_handle, end) - && pull16(pReadPackedMessage, &header->message_id, end) && pull32(pReadPackedMessage, &header->message_length, end)); + (pull8(&pReadPackedMessage, &fapi_msg.num_msg, end) && pull8(&pReadPackedMessage, &fapi_msg.opaque_handle, end) + && pull16(&pReadPackedMessage, &header->message_id, end) && pull32(&pReadPackedMessage, &header->message_length, end)); return (result); } diff --git a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c index 6bf2ff37ea..554898cbd4 100644 --- a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c +++ b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c @@ -135,22 +135,21 @@ int fapi_nr_p5_message_unpack(void *pMessageBuf, nfapi_p4_p5_codec_config_t *config) { fapi_message_header_t *pMessageHeader = pUnpackedBuf; - uint8_t *pReadPackedMessage = pMessageBuf; AssertFatal(pMessageBuf != NULL && pUnpackedBuf != NULL, "P5 unpack supplied pointers are null"); - uint8_t *end = (uint8_t *)pMessageBuf + messageBufLen; AssertFatal(messageBufLen >= NFAPI_HEADER_LENGTH && unpackedBufLen >= sizeof(fapi_message_header_t), "P5 unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen); // clean the supplied buffer for - tag value blanking (void)memset(pUnpackedBuf, 0, unpackedBufLen); - if (fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, pMessageHeader, sizeof(fapi_message_header_t), 0) + if (fapi_nr_message_header_unpack(pMessageBuf, NFAPI_HEADER_LENGTH, pMessageHeader, sizeof(fapi_message_header_t), 0) < 0) { // failed to read the header return -1; } - + uint8_t *pReadPackedMessage = pMessageBuf + NFAPI_HEADER_LENGTH; + uint8_t *end = (uint8_t *)pMessageBuf + messageBufLen; int result = -1; if (check_nr_fapi_unpack_length(pMessageHeader->message_id, unpackedBufLen) == 0) { diff --git a/nfapi/open-nFAPI/fapi/src/nr_fapi_p7.c b/nfapi/open-nFAPI/fapi/src/nr_fapi_p7.c index 7b840fc126..4f73e4596c 100644 --- a/nfapi/open-nFAPI/fapi/src/nr_fapi_p7.c +++ b/nfapi/open-nFAPI/fapi/src/nr_fapi_p7.c @@ -143,20 +143,19 @@ int fapi_nr_p7_message_unpack(void *pMessageBuf, int result = 0; nfapi_nr_p7_message_header_t *pMessageHeader = (nfapi_nr_p7_message_header_t *)pUnpackedBuf; fapi_message_header_t fapi_hdr; - uint8_t *pReadPackedMessage = pMessageBuf; - AssertFatal(pMessageBuf != NULL && pUnpackedBuf != NULL, "P7 unpack supplied pointers are null"); - uint8_t *end = (uint8_t *)pMessageBuf + messageBufLen; + AssertFatal(messageBufLen >= NFAPI_HEADER_LENGTH && unpackedBufLen >= sizeof(fapi_message_header_t), "P5 unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen); - - if (fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &fapi_hdr, sizeof(fapi_message_header_t), 0) < 0) { + if (fapi_nr_message_header_unpack(pMessageBuf, NFAPI_HEADER_LENGTH, &fapi_hdr, sizeof(fapi_message_header_t), 0) < 0) { // failed to read the header return -1; } + uint8_t *pReadPackedMessage = pMessageBuf + NFAPI_HEADER_LENGTH; + uint8_t *end = (uint8_t *)pMessageBuf + messageBufLen; pMessageHeader->message_length = fapi_hdr.message_length; pMessageHeader->message_id = fapi_hdr.message_id; if ((uint8_t *)(pMessageBuf + pMessageHeader->message_length) > end) { diff --git a/nfapi/tests/p5/nr_fapi_config_request_test.c b/nfapi/tests/p5/nr_fapi_config_request_test.c index 82ce60ca3b..bfb3f7fa21 100644 --- a/nfapi/tests/p5/nr_fapi_config_request_test.c +++ b/nfapi/tests/p5/nr_fapi_config_request_test.c @@ -334,7 +334,7 @@ static void test_pack_unpack(nfapi_nr_config_request_scf_t *req) header_buffer[idx] = msg_buf[idx]; } uint8_t *pReadPackedMessage = header_buffer; - int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + int unpack_header_result = fapi_nr_message_header_unpack(pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); DevAssert(unpack_header_result >= 0); DevAssert(header.message_id == req->header.message_id); DevAssert(header.message_length == req->header.message_length); diff --git a/nfapi/tests/p5/nr_fapi_config_response_test.c b/nfapi/tests/p5/nr_fapi_config_response_test.c index bc44b4b6fd..36a6389c0c 100644 --- a/nfapi/tests/p5/nr_fapi_config_response_test.c +++ b/nfapi/tests/p5/nr_fapi_config_response_test.c @@ -92,7 +92,7 @@ void test_pack_unpack(nfapi_nr_config_response_scf_t *req) header_buffer[idx] = msg_buf[idx]; } uint8_t *pReadPackedMessage = header_buffer; - int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + int unpack_header_result = fapi_nr_message_header_unpack(pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); DevAssert(unpack_header_result >= 0); DevAssert(header.message_id == req->header.message_id); DevAssert(header.message_length == req->header.message_length); diff --git a/nfapi/tests/p5/nr_fapi_error_indication_test.c b/nfapi/tests/p5/nr_fapi_error_indication_test.c index 85ef17b536..772b9bccea 100644 --- a/nfapi/tests/p5/nr_fapi_error_indication_test.c +++ b/nfapi/tests/p5/nr_fapi_error_indication_test.c @@ -40,7 +40,7 @@ void test_pack_unpack(nfapi_nr_error_indication_scf_t *req) header_buffer[idx] = msg_buf[idx]; } uint8_t *pReadPackedMessage = header_buffer; - int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + int unpack_header_result = fapi_nr_message_header_unpack(pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); DevAssert(unpack_header_result >= 0); DevAssert(header.message_id == req->header.message_id); DevAssert(header.message_length == req->header.message_length); diff --git a/nfapi/tests/p5/nr_fapi_param_request_test.c b/nfapi/tests/p5/nr_fapi_param_request_test.c index d42717eaeb..0af3fd9633 100644 --- a/nfapi/tests/p5/nr_fapi_param_request_test.c +++ b/nfapi/tests/p5/nr_fapi_param_request_test.c @@ -41,7 +41,7 @@ void test_pack_unpack(nfapi_nr_param_request_scf_t *req) header_buffer[idx] = msg_buf[idx]; } uint8_t *pReadPackedMessage = header_buffer; - int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + int unpack_header_result = fapi_nr_message_header_unpack(pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); DevAssert(unpack_header_result >= 0); DevAssert(header.message_id == req->header.message_id); DevAssert(header.message_length == req->header.message_length); diff --git a/nfapi/tests/p5/nr_fapi_param_response_test.c b/nfapi/tests/p5/nr_fapi_param_response_test.c index 1ba14c1655..e94e805bcb 100644 --- a/nfapi/tests/p5/nr_fapi_param_response_test.c +++ b/nfapi/tests/p5/nr_fapi_param_response_test.c @@ -233,7 +233,7 @@ void test_pack_unpack(nfapi_nr_param_response_scf_t *req) header_buffer[idx] = msg_buf[idx]; } uint8_t *pReadPackedMessage = header_buffer; - int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + int unpack_header_result = fapi_nr_message_header_unpack(pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); DevAssert(unpack_header_result >= 0); DevAssert(header.message_id == req->header.message_id); DevAssert(header.message_length == req->header.message_length); diff --git a/nfapi/tests/p5/nr_fapi_start_request_test.c b/nfapi/tests/p5/nr_fapi_start_request_test.c index 9a36528db6..d908fbe023 100644 --- a/nfapi/tests/p5/nr_fapi_start_request_test.c +++ b/nfapi/tests/p5/nr_fapi_start_request_test.c @@ -41,7 +41,7 @@ void test_pack_unpack(nfapi_nr_start_request_scf_t *req) header_buffer[idx] = msg_buf[idx]; } uint8_t *pReadPackedMessage = header_buffer; - int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + int unpack_header_result = fapi_nr_message_header_unpack(pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); DevAssert(unpack_header_result >= 0); DevAssert(header.message_id == req->header.message_id); DevAssert(header.message_length == req->header.message_length); diff --git a/nfapi/tests/p5/nr_fapi_start_response_test.c b/nfapi/tests/p5/nr_fapi_start_response_test.c index bb3a096734..9d9423de83 100644 --- a/nfapi/tests/p5/nr_fapi_start_response_test.c +++ b/nfapi/tests/p5/nr_fapi_start_response_test.c @@ -41,7 +41,7 @@ void test_pack_unpack(nfapi_nr_start_response_scf_t *req) header_buffer[idx] = msg_buf[idx]; } uint8_t *pReadPackedMessage = header_buffer; - int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + int unpack_header_result = fapi_nr_message_header_unpack(pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); DevAssert(unpack_header_result >= 0); DevAssert(header.message_id == req->header.message_id); DevAssert(header.message_length == req->header.message_length); diff --git a/nfapi/tests/p5/nr_fapi_stop_indication_test.c b/nfapi/tests/p5/nr_fapi_stop_indication_test.c index 4b5d9d4319..e4205d982c 100644 --- a/nfapi/tests/p5/nr_fapi_stop_indication_test.c +++ b/nfapi/tests/p5/nr_fapi_stop_indication_test.c @@ -41,7 +41,7 @@ void test_pack_unpack(nfapi_nr_stop_indication_scf_t *req) header_buffer[idx] = msg_buf[idx]; } uint8_t *pReadPackedMessage = header_buffer; - int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + int unpack_header_result = fapi_nr_message_header_unpack(pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); DevAssert(unpack_header_result >= 0); DevAssert(header.message_id == req->header.message_id); DevAssert(header.message_length == req->header.message_length); diff --git a/nfapi/tests/p5/nr_fapi_stop_request_test.c b/nfapi/tests/p5/nr_fapi_stop_request_test.c index 74e5ea31ff..3536ad2272 100644 --- a/nfapi/tests/p5/nr_fapi_stop_request_test.c +++ b/nfapi/tests/p5/nr_fapi_stop_request_test.c @@ -41,7 +41,7 @@ void test_pack_unpack(nfapi_nr_stop_request_scf_t *req) header_buffer[idx] = msg_buf[idx]; } uint8_t *pReadPackedMessage = header_buffer; - int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + int unpack_header_result = fapi_nr_message_header_unpack(pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); DevAssert(unpack_header_result >= 0); DevAssert(header.message_id == req->header.message_id); DevAssert(header.message_length == req->header.message_length); diff --git a/nfapi/tests/p7/nr_fapi_crc_indication_test.c b/nfapi/tests/p7/nr_fapi_crc_indication_test.c index 472959b0d6..71bb8eca1b 100644 --- a/nfapi/tests/p7/nr_fapi_crc_indication_test.c +++ b/nfapi/tests/p7/nr_fapi_crc_indication_test.c @@ -72,7 +72,7 @@ static void test_pack_unpack(nfapi_nr_crc_indication_t *req) header_buffer[idx] = msg_buf[idx]; } uint8_t *pReadPackedMessage = header_buffer; - int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + int unpack_header_result = fapi_nr_p7_message_header_unpack(pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); DevAssert(unpack_header_result >= 0); DevAssert(header.message_id == req->header.message_id); DevAssert(header.message_length == req->header.message_length); diff --git a/nfapi/tests/p7/nr_fapi_dl_tti_request_test.c b/nfapi/tests/p7/nr_fapi_dl_tti_request_test.c index 2cc95260f0..599a3b85a5 100644 --- a/nfapi/tests/p7/nr_fapi_dl_tti_request_test.c +++ b/nfapi/tests/p7/nr_fapi_dl_tti_request_test.c @@ -241,7 +241,7 @@ static void test_pack_unpack(nfapi_nr_dl_tti_request_t *req) header_buffer[idx] = msg_buf[idx]; } uint8_t *pReadPackedMessage = header_buffer; - int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + int unpack_header_result = fapi_nr_p7_message_header_unpack(pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); DevAssert(unpack_header_result >= 0); DevAssert(header.message_id == req->header.message_id); DevAssert(header.message_length == req->header.message_length); diff --git a/nfapi/tests/p7/nr_fapi_rach_indication_test.c b/nfapi/tests/p7/nr_fapi_rach_indication_test.c index fd4a0fac32..83f569a7d1 100644 --- a/nfapi/tests/p7/nr_fapi_rach_indication_test.c +++ b/nfapi/tests/p7/nr_fapi_rach_indication_test.c @@ -71,7 +71,7 @@ static void test_pack_unpack(nfapi_nr_rach_indication_t *req) header_buffer[idx] = msg_buf[idx]; } uint8_t *pReadPackedMessage = header_buffer; - int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + int unpack_header_result = fapi_nr_p7_message_header_unpack(pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); DevAssert(unpack_header_result >= 0); DevAssert(header.message_id == req->header.message_id); DevAssert(header.message_length == req->header.message_length); diff --git a/nfapi/tests/p7/nr_fapi_rx_data_indication_test.c b/nfapi/tests/p7/nr_fapi_rx_data_indication_test.c index 2f382cf797..18445a0ee2 100644 --- a/nfapi/tests/p7/nr_fapi_rx_data_indication_test.c +++ b/nfapi/tests/p7/nr_fapi_rx_data_indication_test.c @@ -69,7 +69,7 @@ static void test_pack_unpack(nfapi_nr_rx_data_indication_t *req) header_buffer[idx] = msg_buf[idx]; } uint8_t *pReadPackedMessage = header_buffer; - int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + int unpack_header_result = fapi_nr_p7_message_header_unpack(pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); DevAssert(unpack_header_result >= 0); DevAssert(header.message_id == req->header.message_id); DevAssert(header.message_length == req->header.message_length); diff --git a/nfapi/tests/p7/nr_fapi_slot_indication_test.c b/nfapi/tests/p7/nr_fapi_slot_indication_test.c index 96c030479c..414b52332f 100644 --- a/nfapi/tests/p7/nr_fapi_slot_indication_test.c +++ b/nfapi/tests/p7/nr_fapi_slot_indication_test.c @@ -47,7 +47,7 @@ static void test_pack_unpack(nfapi_nr_slot_indication_scf_t *req) header_buffer[idx] = msg_buf[idx]; } uint8_t *pReadPackedMessage = header_buffer; - int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + int unpack_header_result = fapi_nr_message_header_unpack(pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); DevAssert(unpack_header_result >= 0); DevAssert(header.message_id == req->header.message_id); DevAssert(header.message_length == req->header.message_length); diff --git a/nfapi/tests/p7/nr_fapi_srs_indication_test.c b/nfapi/tests/p7/nr_fapi_srs_indication_test.c index 1271606b77..363aa43962 100644 --- a/nfapi/tests/p7/nr_fapi_srs_indication_test.c +++ b/nfapi/tests/p7/nr_fapi_srs_indication_test.c @@ -78,7 +78,7 @@ static void test_pack_unpack(nfapi_nr_srs_indication_t *req) header_buffer[idx] = msg_buf[idx]; } uint8_t *pReadPackedMessage = header_buffer; - int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + int unpack_header_result = fapi_nr_p7_message_header_unpack(pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); DevAssert(unpack_header_result >= 0); DevAssert(header.message_id == req->header.message_id); DevAssert(header.message_length == req->header.message_length); diff --git a/nfapi/tests/p7/nr_fapi_tx_data_request_test.c b/nfapi/tests/p7/nr_fapi_tx_data_request_test.c index e67b5bf3ca..660c514b9c 100644 --- a/nfapi/tests/p7/nr_fapi_tx_data_request_test.c +++ b/nfapi/tests/p7/nr_fapi_tx_data_request_test.c @@ -132,7 +132,7 @@ static void test_pack_unpack(nfapi_nr_tx_data_request_t *req) header_buffer[idx] = msg_buf[idx]; } uint8_t *pReadPackedMessage = header_buffer; - int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + int unpack_header_result = fapi_nr_p7_message_header_unpack(pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); DevAssert(unpack_header_result >= 0); DevAssert(header.message_id == req->header.message_id); DevAssert(header.message_length == req->header.message_length); diff --git a/nfapi/tests/p7/nr_fapi_uci_indication_test.c b/nfapi/tests/p7/nr_fapi_uci_indication_test.c index 9e2dcda6be..53f8469325 100644 --- a/nfapi/tests/p7/nr_fapi_uci_indication_test.c +++ b/nfapi/tests/p7/nr_fapi_uci_indication_test.c @@ -199,7 +199,7 @@ static void test_pack_unpack(nfapi_nr_uci_indication_t *req) header_buffer[idx] = msg_buf[idx]; } uint8_t *pReadPackedMessage = header_buffer; - int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + int unpack_header_result = fapi_nr_p7_message_header_unpack(pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); DevAssert(unpack_header_result >= 0); DevAssert(header.message_id == req->header.message_id); DevAssert(header.message_length == req->header.message_length); diff --git a/nfapi/tests/p7/nr_fapi_ul_dci_request_test.c b/nfapi/tests/p7/nr_fapi_ul_dci_request_test.c index b1bc910da8..709c1c9db9 100644 --- a/nfapi/tests/p7/nr_fapi_ul_dci_request_test.c +++ b/nfapi/tests/p7/nr_fapi_ul_dci_request_test.c @@ -103,7 +103,7 @@ static void test_pack_unpack(nfapi_nr_ul_dci_request_t *req) header_buffer[idx] = msg_buf[idx]; } uint8_t *pReadPackedMessage = header_buffer; - int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + int unpack_header_result = fapi_nr_p7_message_header_unpack(pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); DevAssert(unpack_header_result >= 0); DevAssert(header.message_id == req->header.message_id); DevAssert(header.message_length == req->header.message_length); diff --git a/nfapi/tests/p7/nr_fapi_ul_tti_request_test.c b/nfapi/tests/p7/nr_fapi_ul_tti_request_test.c index 4f65cbfc9e..f7087c92ef 100644 --- a/nfapi/tests/p7/nr_fapi_ul_tti_request_test.c +++ b/nfapi/tests/p7/nr_fapi_ul_tti_request_test.c @@ -422,7 +422,7 @@ static void test_pack_unpack(nfapi_nr_ul_tti_request_t *req) header_buffer[idx] = msg_buf[idx]; } uint8_t *pReadPackedMessage = header_buffer; - int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + int unpack_header_result = fapi_nr_p7_message_header_unpack(pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); DevAssert(unpack_header_result >= 0); DevAssert(header.message_id == req->header.message_id); DevAssert(header.message_length == req->header.message_length); From 00b5eba19266365bc96d7daedffa0c301314648a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Soares=20Silva?= Date: Fri, 31 Jan 2025 14:31:46 +0000 Subject: [PATCH 089/964] Change PNF to use functions pointers to pack/unpack messages. Adds 3 new function pointers to the P5 and P7 PNF structures, allowing to configure which function to use to pack/unpack the messages, as well as unpack the message header, being then used seamlessly regardless of using the FAPI or nFAPI functions. Changes the header unpack and message unpack functions to return true on success and false on failure, instead of an int --- nfapi/oai_integration/nfapi_pnf.c | 6 ++ .../nfapi/public_inc/nfapi_nr_interface.h | 16 ++-- nfapi/open-nFAPI/nfapi/src/nfapi_p5.c | 22 +++--- nfapi/open-nFAPI/nfapi/src/nfapi_p7.c | 24 +++--- .../pnf/public_inc/nfapi_pnf_interface.h | 75 +++++++++++++++++++ nfapi/open-nFAPI/pnf/src/pnf.c | 41 +++++----- nfapi/open-nFAPI/pnf/src/pnf_p7.c | 35 +++++---- .../SIMULATION/NR_PHY/nr_unitary_common.c | 4 +- openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c | 44 +++++------ openair2/RRC/LTE/rrc_UE.c | 14 ++-- 10 files changed, 178 insertions(+), 103 deletions(-) diff --git a/nfapi/oai_integration/nfapi_pnf.c b/nfapi/oai_integration/nfapi_pnf.c index 21b3e1e90e..b58463a7de 100644 --- a/nfapi/oai_integration/nfapi_pnf.c +++ b/nfapi/oai_integration/nfapi_pnf.c @@ -1747,6 +1747,9 @@ int nr_start_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nf p7_config->codec_config.pack_p7_vendor_extension = &pnf_nr_phy_pack_p7_vendor_extension; p7_config->codec_config.unpack_vendor_extension_tlv = &pnf_nr_phy_unpack_vendor_extension_tlv; p7_config->codec_config.pack_vendor_extension_tlv = &pnf_nr_phy_pack_vendor_extention_tlv; + p7_config->unpack_func = &nfapi_nr_p7_message_unpack; + p7_config->hdr_unpack_func = &nfapi_nr_p7_message_header_unpack; + p7_config->pack_func = &nfapi_nr_p7_message_pack; NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] Creating P7 thread %s\n", __FUNCTION__); pthread_t p7_thread; threadCreate(&p7_thread, &pnf_nr_p7_thread_start, p7_config, "pnf_p7_thread", -1, OAI_PRIORITY_RT); @@ -2188,6 +2191,9 @@ void configure_nr_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_add config->deallocate_p4_p5_vendor_ext = &pnf_nr_sim_deallocate_p4_p5_vendor_ext; config->codec_config.unpack_p4_p5_vendor_extension = &pnf_nr_sim_unpack_p4_p5_vendor_extension; config->codec_config.pack_p4_p5_vendor_extension = &pnf_nr_sim_pack_p4_p5_vendor_extension; + config->unpack_func = &nfapi_nr_p5_message_unpack; + config->hdr_unpack_func = &nfapi_nr_p5_message_header_unpack; + config->pack_func = &nfapi_nr_p5_message_pack; NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] Creating PNF NFAPI start thread %s\n", __FUNCTION__); pthread_create(&pnf_start_pthread, NULL, &pnf_nr_start_thread, config); pthread_setname_np(pnf_start_pthread, "NFAPI_PNF"); 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 eb668f3e73..683de59c59 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h @@ -110,11 +110,11 @@ uint8_t pack_nr_p5_message_body(nfapi_nr_p4_p5_message_header_t *header, * \param pUnpackedBuf A pointer to the nfapi_message_header * \param unpackedBufLen The size of nfapi_message_header structure. * \param config A pointer to the nfapi configuration structure - * \return 10 ( size of the unpacked header ) on success, -1 on failure. + * \return true on success, false on failure. * * The function will decode a byte stream pointed to by pMessageBuf into a nfapi p5 header structure pointed to by pUnpackedBuf */ -int nfapi_nr_p5_message_header_unpack(void *pMessageBuf, +bool nfapi_nr_p5_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, @@ -126,11 +126,11 @@ int nfapi_nr_p5_message_header_unpack(void *pMessageBuf, * \param pUnpackedBuf A pointer to the nfapi_message_header * \param unpackedBufLen The size of nfapi_message_header structure. * \param config A pointer to the nfapi configuration structure - * \return != -1 means success, -1 means failure. + * \return true on success, false on failure. * * The function will decode a byte stream pointed to by pMessageBuf into a nfapi p5 message structure pointer to by pUnpackedBuf */ -int nfapi_nr_p5_message_unpack(void *pMessageBuf, +bool nfapi_nr_p5_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, @@ -154,13 +154,13 @@ int nfapi_nr_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packe * \param pUnpackedBuf A pointer to the nfapi_message_header * \param unpackedBufLen The size of nfapi_message_header structure. * \param config A pointer to the nfapi configuration structure - * \return 0 means success, -1 means failure. + * \return true on success, false on failure. * * The function will decode a byte stream pointed to by pMessageBuf into a nfapi_p7_message_header structure pointer to by pUnpackedBuf */ -int nfapi_nr_p7_message_header_unpack(void *pMessageBuf, +bool nfapi_nr_p7_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, @@ -172,11 +172,11 @@ int nfapi_nr_p7_message_header_unpack(void *pMessageBuf, * \param pUnpackedBuf A pointer to the nfapi_message_header * \param unpackedBufLen The size of nfapi_message_header structure. * \param config A pointer to the nfapi configuration structure - * \return 0 means success, -1 means failure. + * \return true on success, false failure. * * The function will decode a byte stream pointed to by pMessageBuf into a nfapi p7 message structure pointer to by pUnpackedBuf */ -int nfapi_nr_p7_message_unpack(void *pMessageBuf, +bool nfapi_nr_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c index 1aeef4b766..4516302e48 100644 --- a/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c @@ -2325,7 +2325,7 @@ int nfapi_p5_message_header_unpack(void *pMessageBuf, return 8; } -int nfapi_nr_p5_message_header_unpack(void *pMessageBuf, +bool nfapi_nr_p5_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, @@ -2336,25 +2336,25 @@ int nfapi_nr_p5_message_header_unpack(void *pMessageBuf, if (pMessageBuf == NULL || pUnpackedBuf == NULL) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "P5 header unpack supplied pointers are null\n"); - return -1; + return false; } uint8_t *end = pMessageBuf + messageBufLen; if (messageBufLen < NFAPI_NR_P5_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_nr_p4_p5_message_header_t)) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "P5 header unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen); - return -1; + return false; } // process the header if (!(pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) && pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) && pull32(&pReadPackedMessage, &pMessageHeader->message_length, end) && pull16(&pReadPackedMessage, &pMessageHeader->spare, end))) { - return -1; + return false; } - return NFAPI_NR_P5_HEADER_LENGTH; + return true; } -int nfapi_nr_p5_message_unpack(void *pMessageBuf, +bool nfapi_nr_p5_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, @@ -2362,11 +2362,11 @@ int nfapi_nr_p5_message_unpack(void *pMessageBuf, { if (pMessageBuf == NULL || pUnpackedBuf == NULL) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "P5 unpack supplied pointers are null\n"); - return -1; + return false; } if (messageBufLen < NFAPI_NR_P5_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_nr_p4_p5_message_header_t)) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "P5 unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen); - return -1; + return false; } nfapi_nr_p4_p5_message_header_t *pMessageHeader = pUnpackedBuf; @@ -2374,7 +2374,7 @@ int nfapi_nr_p5_message_unpack(void *pMessageBuf, (void)memset(pUnpackedBuf, 0, unpackedBufLen); // process the header if (!nfapi_nr_p5_message_header_unpack(pMessageBuf, messageBufLen, pMessageHeader, unpackedBufLen, config)) { - return -1; + return false; } uint8_t *pReadPackedMessage = pMessageBuf + NFAPI_NR_P5_HEADER_LENGTH; uint8_t *end = (uint8_t *)pMessageBuf + messageBufLen; @@ -2382,7 +2382,7 @@ int nfapi_nr_p5_message_unpack(void *pMessageBuf, if (check_nr_unpack_length(pMessageHeader->message_id, unpackedBufLen) == 0) { // the unpack buffer is not big enough for the struct - return -1; + return false; } // look for the specific message @@ -2476,7 +2476,7 @@ int nfapi_nr_p5_message_unpack(void *pMessageBuf, break; } - return result; + return result == 1; } int nfapi_p5_message_unpack(void *pMessageBuf, diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c index b6e15e294b..c60ed27d07 100644 --- a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c @@ -5930,7 +5930,7 @@ int nfapi_p7_message_header_unpack(void *pMessageBuf, return 0; } -int nfapi_nr_p7_message_header_unpack(void *pMessageBuf, +bool nfapi_nr_p7_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, @@ -5941,14 +5941,14 @@ int nfapi_nr_p7_message_header_unpack(void *pMessageBuf, if (pMessageBuf == NULL || pUnpackedBuf == NULL) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 header unpack supplied pointers are null\n"); - return -1; + return false; } uint8_t *end = (uint8_t *)pMessageBuf + messageBufLen; if (messageBufLen < NFAPI_NR_P7_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_nr_p7_message_header_t)) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 header unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen); - return -1; + return false; } // process the header if (!(pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) && pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) @@ -5956,9 +5956,9 @@ int nfapi_nr_p7_message_header_unpack(void *pMessageBuf, && pull16(&pReadPackedMessage, &pMessageHeader->m_segment_sequence, end) && pull32(&pReadPackedMessage, &pMessageHeader->checksum, end) && pull32(&pReadPackedMessage, &pMessageHeader->transmit_timestamp, end))) - return -1; + return false; - return 0; + return true; } int nfapi_p7_message_unpack(void *pMessageBuf, @@ -6213,7 +6213,7 @@ bool peek_nr_nfapi_p7_sfn_slot(void *pMessageBuf, uint32_t messageBufLen, uint16 return true; } -int nfapi_nr_p7_message_unpack(void *pMessageBuf, +bool nfapi_nr_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, @@ -6225,14 +6225,14 @@ int nfapi_nr_p7_message_unpack(void *pMessageBuf, if (pMessageBuf == NULL || pUnpackedBuf == NULL) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack supplied pointers are null\n"); - return -1; + return false; } uint8_t *end = (uint8_t *)pMessageBuf + messageBufLen; if (messageBufLen < NFAPI_NR_P7_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_nr_p7_message_header_t)) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen); - return -1; + return false; } // process the header @@ -6242,11 +6242,11 @@ int nfapi_nr_p7_message_unpack(void *pMessageBuf, && pull32(&pReadPackedMessage, &pMessageHeader->checksum, end) && pull32(&pReadPackedMessage, &pMessageHeader->transmit_timestamp, end))) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack header failed\n"); - return -1; + return false; } if ((uint8_t *)(pMessageBuf + pMessageHeader->message_length) > end) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack message length is greater than the message buffer \n"); - return -1; + return false; } /* @@ -6356,7 +6356,7 @@ int nfapi_nr_p7_message_unpack(void *pMessageBuf, if (result == 0) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack failed to pack message\n"); - return -1; + return false; } - return 0; + return true; } diff --git a/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h b/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h index 7403bd7169..2e4cb8812c 100644 --- a/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h +++ b/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h @@ -319,7 +319,47 @@ typedef struct nfapi_pnf_config */ void (*deallocate_p4_p5_vendor_ext)(void* header); + /*! \brief Encodes an (n)FAPI P5 message to a buffer + * \param pMessageBuf A pointer to a nfapi p5 message structure + * \param messageBufLen The size of the p5 message structure + * \param pPackedBuf A pointer to the buffer that the p5 message will be packed into + * \param packedBufLen The size of the buffer + * \param config A pointer to the nfapi configuration structure + * \return != 0 means success, -1 means failure. + */ + int (*pack_func)(void* pMessageBuf, + uint32_t messageBufLen, + void* pPackedBuf, + uint32_t packedBufLen, + nfapi_p4_p5_codec_config_t* config); + /*! \brief Decodes a (n)FAPI P5 message + * \param pMessageBuf A pointer to an encoded P5 message + * \param messageBufLen The size of the encoded P5 message + * \param pUnpackedBuf A pointer to the nfapi_message_header + * \param unpackedBufLen The size of nfapi_message_header structure. + * \param config A pointer to the nfapi configuration structure + * \return true on success, false on failure. + */ + bool (*unpack_func)(void* pMessageBuf, + uint32_t messageBufLen, + void* pUnpackedBuf, + uint32_t unpackedBufLen, + nfapi_p4_p5_codec_config_t* config); + + /*! \brief Decodes an (n)FAPI P5 message header + * \param pMessageBuf A pointer to an encoded P5 message header + * \param messageBufLen The size of the encoded P5 message header + * \param pUnpackedBuf A pointer to the nfapi_message_header + * \param unpackedBufLen The size of nfapi_message_header structure. + * \param config A pointer to the nfapi configuration structure + * \return true on success, false on failure. + */ + bool (*hdr_unpack_func)(void* pMessageBuf, + uint32_t messageBufLen, + void* pUnpackedBuf, + uint32_t unpackedBufLen, + nfapi_p4_p5_codec_config_t* config); } nfapi_pnf_config_t; @@ -726,7 +766,42 @@ typedef struct nfapi_pnf_p7_config */ void (*deallocate_p7_vendor_ext)(void* header); + /*! A callback to pack a P7 message + * \param pMessageBuf A pointer to a nfapi p7 message structure + * \param pPackedBuf A pointer to the buffer that the p7 message will be packed into + * \param packedBufLen The size of the buffer + * \param config A pointer to the nfapi configuration structure + * \return != -1 means success, -1 means failure. + */ + int (*pack_func)(void* pMessageBuf, void* pPackedBuf, uint32_t packedBufLen, nfapi_p7_codec_config_t* config); + /*! A callback to unpack a P7 message + * \param pMessageBuf A pointer to an encoded P7 message header + * \param messageBufLen The size of the encoded P7 message header + * \param pUnpackedBuf A pointer to the nfapi_message_header + * \param unpackedBufLen The size of nfapi_message_header structure. + * \param config A pointer to the nfapi configuration structure + * \return true success, false on failure. + */ + bool (*unpack_func)(void* pMessageBuf, + uint32_t messageBufLen, + void* pUnpackedBuf, + uint32_t unpackedBufLen, + nfapi_p7_codec_config_t* config); + + /*! \brief Decodes a NFAPI P7 message header + * \param pMessageBuf A pointer to an encoded P5 message header + * \param messageBufLen The size of the encoded P5 message header + * \param pUnpackedBuf A pointer to the nfapi_message_header + * \param unpackedBufLen The size of nfapi_message_header structure. + * \param config A pointer to the nfapi configuration structure + * \return true on success, false on failure. + */ + bool (*hdr_unpack_func)(void* pMessageBuf, + uint32_t messageBufLen, + void* pUnpackedBuf, + uint32_t unpackedBufLen, + nfapi_p7_codec_config_t* config); } nfapi_pnf_p7_config_t; diff --git a/nfapi/open-nFAPI/pnf/src/pnf.c b/nfapi/open-nFAPI/pnf/src/pnf.c index 4cef8e6412..e4438eded7 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf.c +++ b/nfapi/open-nFAPI/pnf/src/pnf.c @@ -95,8 +95,9 @@ void pnf_nr_handle_pnf_param_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF_PARAM.request received\n"); - // unpack the message - if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(nfapi_nr_pnf_param_request_t), &pnf->_public.codec_config) >= 0) + /// The unpack() function pointer is not called here due to the only possibility of entering being on a nFAPI message + const bool result = nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(nfapi_nr_pnf_param_request_t), &pnf->_public.codec_config); + if (result) { if(pnf->_public.state == NFAPI_PNF_IDLE) { @@ -251,8 +252,9 @@ void pnf_nr_handle_pnf_config_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF_CONFIG.request received\n"); - // unpack the message - if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &pnf->_public.codec_config) >= 0) + /// The unpack() function pointer is not called here due to the only possibility of entering being on a nFAPI message + const bool result = nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &pnf->_public.codec_config); + if (result) { // ensure correct state if(pnf->_public.state != NFAPI_PNF_RUNNING) @@ -357,8 +359,9 @@ void pnf_nr_handle_pnf_start_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF_START.request Received\n"); - // unpack the message - if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &pnf->_public.codec_config) >= 0) + /// The unpack() function pointer is not called here due to the only possibility of entering being on a nFAPI message + const bool result = nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &pnf->_public.codec_config); + if (result) { if(pnf->_public.state == NFAPI_PNF_CONFIGURED) { @@ -517,7 +520,8 @@ void pnf_nr_handle_param_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) NFAPI_TRACE(NFAPI_TRACE_INFO, "PARAM.request received\n"); // unpack the message - if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &config->codec_config) >= 0) + const bool result = pnf->_public.unpack_func(pRecvMsg, recvMsgLen, &req, sizeof(req), &config->codec_config); + if (result) { if(config->state == NFAPI_PNF_RUNNING) { @@ -662,7 +666,8 @@ void pnf_nr_handle_config_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) nfapi_pnf_config_t* config = &(pnf->_public); // unpack the message - if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &config->codec_config) >= 0) + const bool result = pnf->_public.unpack_func(pRecvMsg, recvMsgLen, &req, sizeof(req), &config->codec_config); + if (result) { if(config->state == NFAPI_PNF_RUNNING) { @@ -806,7 +811,8 @@ void pnf_nr_handle_start_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() START.request received state:%d\n", __FUNCTION__, config->state); // unpack the message - if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &config->codec_config) >= 0) + const bool result = pnf->_public.unpack_func(pRecvMsg, recvMsgLen, &req, sizeof(req), &config->codec_config); + if (result) { if(config->state == NFAPI_PNF_RUNNING) { @@ -945,7 +951,8 @@ void pnf_nr_handle_stop_request(pnf_t* pnf, void* pRecvMsg, int recvMsgLen) nfapi_pnf_config_t* config = &(pnf->_public); // unpack the message - if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &config->codec_config) >= 0) { + const bool result = pnf->_public.unpack_func(pRecvMsg, recvMsgLen, &req, sizeof(req), &config->codec_config); + if (result) { if (config->state == NFAPI_PNF_RUNNING) { nfapi_pnf_phy_config_t* phy = nfapi_pnf_phy_config_find(config, req.header.phy_id); if (phy) { @@ -1525,12 +1532,8 @@ void pnf_nr_handle_p5_message(pnf_t* pnf, void* pRecvMsg, int recvMsgLen) } // unpack the message header - if (nfapi_nr_p5_message_header_unpack(pRecvMsg, - recvMsgLen, - &messageHeader, - sizeof(nfapi_nr_p4_p5_message_header_t), - &pnf->_public.codec_config) - < 0) { + const bool result = pnf->_public.hdr_unpack_func(pRecvMsg, recvMsgLen, &messageHeader, sizeof(messageHeader), &pnf->_public.codec_config); + if (!result) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n"); return; } @@ -1705,7 +1708,7 @@ void pnf_handle_p5_message(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) int pnf_nr_pack_and_send_p5_message(pnf_t* pnf, nfapi_nr_p4_p5_message_header_t* msg, uint32_t msg_len) { int packed_len = - nfapi_nr_p5_message_pack(msg, msg_len, pnf->tx_message_buffer, sizeof(pnf->tx_message_buffer), &pnf->_public.codec_config); + pnf->_public.pack_func(msg, msg_len, pnf->tx_message_buffer, sizeof(pnf->tx_message_buffer), &pnf->_public.codec_config); if (packed_len < 0) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi_nr_p5_message_pack failed (%d)\n", packed_len); @@ -2143,8 +2146,8 @@ int pnf_nr_read_dispatch_message(pnf_t* pnf) } nfapi_nr_p4_p5_message_header_t header; - int unpack_result = nfapi_nr_p5_message_header_unpack(header_buffer, header_buffer_size, &header, sizeof(header), 0); - if (unpack_result < 0) { + const bool result = pnf->_public.hdr_unpack_func(header_buffer, header_buffer_size, &header, sizeof(header), 0); + if (!result) { NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF Failed to unpack p5 message header\n"); return 0; } diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7.c b/nfapi/open-nFAPI/pnf/src/pnf_p7.c index bdc1634ef5..2235a7c153 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7.c @@ -580,7 +580,7 @@ int pnf_nr_p7_pack_and_send_p7_message(pnf_p7_t* pnf_p7, nfapi_nr_p7_message_hea } uint8_t tx_buf[131072]; // four times NFAPI_MAX_PACKED_MESSAGE_SIZE as of this commit - int len = nfapi_nr_p7_message_pack(header, tx_buf, sizeof(tx_buf), &pnf_p7->_public.codec_config); + int len = pnf_p7->_public.pack_func(header, tx_buf, sizeof(tx_buf), &pnf_p7->_public.codec_config); if (len < 0) { if (pthread_mutex_unlock(&(pnf_p7->pack_mutex)) != 0) { @@ -1299,8 +1299,8 @@ void pnf_handle_dl_tti_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7) frame, slot, buffer_index); - - if (nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, req, sizeof(*req), &(pnf_p7->_public.codec_config)) != 0) + const bool result = pnf_p7->_public.unpack_func(pRecvMsg, recvMsgLen, req, sizeof(*req), &(pnf_p7->_public.codec_config)); + if (!result) NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to unpack request\n"); } else { if (pnf_p7->_public.timing_info_mode_aperiodic) @@ -1432,8 +1432,8 @@ void pnf_handle_ul_tti_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7) frame, slot, buffer_index); - - if (nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, req, sizeof(*req), &(pnf_p7->_public.codec_config)) != 0) + const bool result = pnf_p7->_public.unpack_func(pRecvMsg, recvMsgLen, req, sizeof(*req), &(pnf_p7->_public.codec_config)); + if (!result) NFAPI_TRACE(NFAPI_TRACE_ERROR, "failed to unpack UL_TTI.request\n"); } else { NFAPI_TRACE(NFAPI_TRACE_NOTE, @@ -1551,8 +1551,8 @@ void pnf_handle_ul_dci_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7) frame, slot, buffer_index); - - if (nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, req, sizeof(*req), &pnf_p7->_public.codec_config) != 0) + const bool result = pnf_p7->_public.unpack_func(pRecvMsg, recvMsgLen, req, sizeof(*req), &(pnf_p7->_public.codec_config)); + if (!result) NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to unpack request\n"); } else { if (pnf_p7->_public.timing_info_mode_aperiodic) { @@ -1664,8 +1664,8 @@ void pnf_handle_tx_data_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7 frame, slot, buffer_index); - - if (nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, req, sizeof(*req), &pnf_p7->_public.codec_config) == 0) { + const bool result = pnf_p7->_public.unpack_func(pRecvMsg, recvMsgLen, req, sizeof(*req), &(pnf_p7->_public.codec_config)); + if (result) { for (int i = 0; i < req->Number_of_PDUs; ++i) pnf_p7->nr_stats.dl.bytes += req->pdu_list[i].PDU_length; } else { @@ -2063,7 +2063,8 @@ void pnf_nr_handle_dl_node_sync(void *pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7 } // unpack the message - if (nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &dl_node_sync, sizeof(dl_node_sync), &pnf_p7->_public.codec_config) < 0) + const bool result = pnf_p7->_public.unpack_func(pRecvMsg, recvMsgLen, &dl_node_sync, sizeof(dl_node_sync), &pnf_p7->_public.codec_config); + if (!result) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__); return; @@ -2182,7 +2183,8 @@ void pnf_nr_dispatch_p7_message(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7 } // unpack the message header - if (nfapi_nr_p7_message_header_unpack(pRecvMsg, recvMsgLen, &header, sizeof(header), &pnf_p7->_public.codec_config) < 0) { + const bool result = pnf_p7->_public.hdr_unpack_func(pRecvMsg, recvMsgLen, &header, sizeof(header), &pnf_p7->_public.codec_config); + if (!result) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n"); return; } @@ -2336,12 +2338,9 @@ void pnf_nr_handle_p7_message(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7, } // unpack the message header - if (nfapi_nr_p7_message_header_unpack(pRecvMsg, - recvMsgLen, - &messageHeader, - sizeof(nfapi_nr_p7_message_header_t), - &pnf_p7->_public.codec_config) - < 0) { + const bool result = + pnf_p7->_public.hdr_unpack_func(pRecvMsg, recvMsgLen, &messageHeader, sizeof(messageHeader), &pnf_p7->_public.codec_config); + if (!result) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n"); return; } @@ -2519,7 +2518,7 @@ void pnf_nr_nfapi_p7_read_dispatch_message(pnf_p7_t* pnf_p7, uint32_t now_hr_tim if (recvfrom_result > 0) { // get the segment size nfapi_nr_p7_message_header_t header; - nfapi_nr_p7_message_header_unpack(header_buffer, NFAPI_NR_P7_HEADER_LENGTH, &header, 34, 0); + pnf_p7->_public.hdr_unpack_func(header_buffer, NFAPI_NR_P7_HEADER_LENGTH, &header, 34, 0); // resize the buffer if we have a large segment if (header.message_length > pnf_p7->rx_message_buffer_size) { diff --git a/openair1/SIMULATION/NR_PHY/nr_unitary_common.c b/openair1/SIMULATION/NR_PHY/nr_unitary_common.c index 734a62d994..8a682b02f1 100644 --- a/openair1/SIMULATION/NR_PHY/nr_unitary_common.c +++ b/openair1/SIMULATION/NR_PHY/nr_unitary_common.c @@ -119,13 +119,13 @@ int nfapi_nr_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packe { return 0; } -int nfapi_nr_p7_message_unpack(void *pMessageBuf, +bool nfapi_nr_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p7_codec_config_t *config) { - return 0; + return false; } int nfapi_p7_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c index e13ddac506..de5ae571ca 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c @@ -853,12 +853,11 @@ static void enqueue_nr_nfapi_msg(void *buffer, ssize_t len, nfapi_p7_message_hea case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: { nfapi_nr_dl_tti_request_t *dl_tti_request = malloc16(sizeof(*dl_tti_request)); - if (nfapi_nr_p7_message_unpack(buffer, len, dl_tti_request, - sizeof(*dl_tti_request), NULL) < 0) - { - LOG_E(NR_PHY, "Message dl_tti_request failed to unpack\n"); - break; - } + const bool result = nfapi_nr_p7_message_unpack(buffer, len, dl_tti_request, sizeof(*dl_tti_request), NULL); + if (!result) { + LOG_E(NR_PHY, "Message dl_tti_request failed to unpack\n"); + break; + } LOG_D(NR_PHY, "Received an NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST message in sfn/slot %d %d. \n", dl_tti_request->SFN, dl_tti_request->Slot); @@ -877,12 +876,11 @@ static void enqueue_nr_nfapi_msg(void *buffer, ssize_t len, nfapi_p7_message_hea case NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST: { nfapi_nr_tx_data_request_t *tx_data_request = malloc16(sizeof(*tx_data_request)); - if (nfapi_nr_p7_message_unpack(buffer, len, tx_data_request, - sizeof(*tx_data_request), NULL) < 0) - { - LOG_E(NR_PHY, "Message tx_data_request failed to unpack\n"); - break; - } + const bool result = nfapi_nr_p7_message_unpack(buffer, len, tx_data_request, sizeof(*tx_data_request), NULL); + if (!result) { + LOG_E(NR_PHY, "Message tx_data_request failed to unpack\n"); + break; + } LOG_D(NR_PHY, "Received an NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST message in SFN/slot %d %d. \n", tx_data_request->SFN, tx_data_request->Slot); if (!put_queue(&nr_tx_req_queue, tx_data_request)) @@ -897,12 +895,11 @@ static void enqueue_nr_nfapi_msg(void *buffer, ssize_t len, nfapi_p7_message_hea case NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST: { nfapi_nr_ul_dci_request_t *ul_dci_request = malloc16(sizeof(*ul_dci_request)); - if (nfapi_nr_p7_message_unpack(buffer, len, ul_dci_request, - sizeof(*ul_dci_request), NULL) < 0) - { - LOG_E(NR_PHY, "Message ul_dci_request failed to unpack\n"); - break; - } + const bool result = nfapi_nr_p7_message_unpack(buffer, len, ul_dci_request, sizeof(*ul_dci_request), NULL); + if (!result) { + LOG_E(NR_PHY, "Message ul_dci_request failed to unpack\n"); + break; + } LOG_D(NR_PHY, "Received an NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST message in SFN/slot %d %d. \n", ul_dci_request->SFN, ul_dci_request->Slot); if (!put_queue(&nr_ul_dci_req_queue, ul_dci_request)) @@ -917,12 +914,11 @@ static void enqueue_nr_nfapi_msg(void *buffer, ssize_t len, nfapi_p7_message_hea case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: { nfapi_nr_ul_tti_request_t *ul_tti_request = malloc16(sizeof(*ul_tti_request)); - if (nfapi_nr_p7_message_unpack(buffer, len, ul_tti_request, - sizeof(*ul_tti_request), NULL) < 0) - { - LOG_E(NR_PHY, "Message ul_tti_request failed to unpack\n"); - break; - } + const bool result = nfapi_nr_p7_message_unpack(buffer, len, ul_tti_request, sizeof(*ul_tti_request), NULL); + if (!result) { + LOG_E(NR_PHY, "Message ul_tti_request failed to unpack\n"); + break; + } /* We are filtering UL_TTI_REQs below. We only care about UL_TTI_REQs that will trigger sending a ul_harq (CRC/RX pair). This UL_TTI_REQ will have NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE. If we have not yet completed the CBRA/ diff --git a/openair2/RRC/LTE/rrc_UE.c b/openair2/RRC/LTE/rrc_UE.c index 2216fb5a75..39b8f426ce 100644 --- a/openair2/RRC/LTE/rrc_UE.c +++ b/openair2/RRC/LTE/rrc_UE.c @@ -6582,15 +6582,11 @@ void process_nr_nsa_msg(nsa_msg_t *msg, int msg_len) } nfapi_nr_dl_tti_request_t dl_tti_request; - int unpack_len = nfapi_nr_p7_message_unpack((void *)msg_buffer, - msg_len, - &dl_tti_request, - sizeof(nfapi_nr_dl_tti_request_t), - NULL); - if (unpack_len < 0) - { - LOG_E(RRC, "%s: SSB PDU unpack failed \n", __FUNCTION__); - break; + const bool result = + nfapi_nr_p7_message_unpack((void *)msg_buffer, msg_len, &dl_tti_request, sizeof(nfapi_nr_dl_tti_request_t), NULL); + if (!result) { + LOG_E(RRC, "%s: SSB PDU unpack failed \n", __FUNCTION__); + break; } int num_pdus = dl_tti_request.dl_tti_request_body.nPDUs; if (num_pdus <= 0) From 2089655a97938b58041370f5d6ec14c5fde79553 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Soares=20Silva?= Date: Mon, 2 Dec 2024 11:28:07 +0000 Subject: [PATCH 090/964] Change VNF to use functions pointers to pack/unpack messages. Adds 3 new function pointers to the P5 and P7 VNF structures, allowing to configure which function to use to pack/unpack the messages, as well as unpack the message header, being then used seamlessly regardless of using the FAPI or nFAPI functions. --- nfapi/oai_integration/nfapi_vnf.c | 6 ++ .../vnf/public_inc/nfapi_vnf_interface.h | 75 +++++++++++++++++++ nfapi/open-nFAPI/vnf/src/vnf.c | 27 ++++--- nfapi/open-nFAPI/vnf/src/vnf_p7.c | 45 +++++------ 4 files changed, 122 insertions(+), 31 deletions(-) diff --git a/nfapi/oai_integration/nfapi_vnf.c b/nfapi/oai_integration/nfapi_vnf.c index e30c939c83..f7b5575084 100644 --- a/nfapi/oai_integration/nfapi_vnf.c +++ b/nfapi/oai_integration/nfapi_vnf.c @@ -1445,6 +1445,9 @@ void *vnf_nr_p7_thread_start(void *ptr) p7_vnf->config->codec_config.deallocate = &vnf_deallocate; p7_vnf->config->allocate_p7_vendor_ext = &phy_nr_allocate_p7_vendor_ext; p7_vnf->config->deallocate_p7_vendor_ext = &phy_nr_deallocate_p7_vendor_ext; + p7_vnf->config->unpack_func = &nfapi_nr_p7_message_unpack; + p7_vnf->config->hdr_unpack_func = &nfapi_nr_p7_message_header_unpack; + p7_vnf->config->pack_func = &nfapi_nr_p7_message_pack; NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Creating VNF NFAPI P7 start thread %s\n", __FUNCTION__); pthread_create(&vnf_p7_start_pthread, NULL, &vnf_nr_p7_start_thread, p7_vnf->config); return 0; @@ -1862,6 +1865,9 @@ void configure_nr_nfapi_vnf(char *vnf_addr, int vnf_p5_port, char *pnf_ip_addr, config->codec_config.allocate = &vnf_nr_allocate; config->codec_config.deallocate = &vnf_nr_deallocate; memset(&UL_RCC_INFO, 0, sizeof(UL_RCC_IND_t)); + config->unpack_func = &nfapi_nr_p5_message_unpack; + config->hdr_unpack_func = &nfapi_nr_p5_message_header_unpack; + config->pack_func = &nfapi_nr_p5_message_pack; NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Creating VNF NFAPI start thread %s\n", __FUNCTION__); pthread_create(&vnf_start_pthread, NULL, (void *)&vnf_nr_start_thread, config); NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Created VNF NFAPI start thread %s\n", __FUNCTION__); diff --git a/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h b/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h index 6fd7d733eb..ba01329b2d 100644 --- a/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h +++ b/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h @@ -449,7 +449,47 @@ typedef struct nfapi_vnf_config */ void (*deallocate_p4_p5_vendor_ext)(void* header); + /*! \brief Encodes a (n)FAPI P5 message to a buffer + * \param pMessageBuf A pointer to a (n)fapi p5 message structure + * \param messageBufLen The size of the p5 message structure + * \param pPackedBuf A pointer to the buffer that the p5 message will be packed into + * \param packedBufLen The size of the buffer + * \param config A pointer to the nfapi configuration structure + * \return != 0 means success, -1 means failure. + */ + int (*pack_func)(void* pMessageBuf, + uint32_t messageBufLen, + void* pPackedBuf, + uint32_t packedBufLen, + nfapi_p4_p5_codec_config_t* config); + /*! \brief Decodes an (n)FAPI P5 message + * \param pMessageBuf A pointer to an encoded P5 message + * \param messageBufLen The size of the encoded P5 message + * \param pUnpackedBuf A pointer to the nfapi_message_header + * \param unpackedBufLen The size of nfapi_message_header structure. + * \param config A pointer to the nfapi configuration structure + * \return true on success, false on failure + */ + bool (*unpack_func)(void* pMessageBuf, + uint32_t messageBufLen, + void* pUnpackedBuf, + uint32_t unpackedBufLen, + nfapi_p4_p5_codec_config_t* config); + + /*! \brief Decodes an (n)FAPI P5 message header + * \param pMessageBuf A pointer to an encoded P5 message header + * \param messageBufLen The size of the encoded P5 message header + * \param pUnpackedBuf A pointer to the nfapi_message_header + * \param unpackedBufLen The size of nfapi_message_header structure. + * \param config A pointer to the nfapi configuration structure + * \return true on success, false on failure + */ + bool (*hdr_unpack_func)(void* pMessageBuf, + uint32_t messageBufLen, + void* pUnpackedBuf, + uint32_t unpackedBufLen, + nfapi_p4_p5_codec_config_t* config); @@ -878,7 +918,42 @@ typedef struct nfapi_vnf_p7_config */ void (*deallocate_p7_vendor_ext)(void* header); + /*! A callback to pack a P7 message +* \param pMessageBuf A pointer to a nfapi p7 message structure +* \param pPackedBuf A pointer to the buffer that the p7 message will be packed into +* \param packedBufLen The size of the buffer +* \param config A pointer to the nfapi configuration structure +* \return != -1 means success, -1 means failure. +*/ + int (*pack_func)(void* pMessageBuf, void* pPackedBuf, uint32_t packedBufLen, nfapi_p7_codec_config_t* config); + /*! A callback to unpack a P7 message + * \param pMessageBuf A pointer to an encoded P7 message header + * \param messageBufLen The size of the encoded P7 message header + * \param pUnpackedBuf A pointer to the nfapi_message_header + * \param unpackedBufLen The size of nfapi_message_header structure. + * \param config A pointer to the nfapi configuration structure + * \return true on success, false on failure + */ + bool (*unpack_func)(void* pMessageBuf, + uint32_t messageBufLen, + void* pUnpackedBuf, + uint32_t unpackedBufLen, + nfapi_p7_codec_config_t* config); + + /*! \brief Decodes an NFAPI P7 message header + * \param pMessageBuf A pointer to an encoded P5 message header + * \param messageBufLen The size of the encoded P5 message header + * \param pUnpackedBuf A pointer to the nfapi_message_header + * \param unpackedBufLen The size of nfapi_message_header structure. + * \param config A pointer to the nfapi configuration structure + * \return true on success, false on failure + */ + bool (*hdr_unpack_func)(void* pMessageBuf, + uint32_t messageBufLen, + void* pUnpackedBuf, + uint32_t unpackedBufLen, + nfapi_p7_codec_config_t* config); } nfapi_vnf_p7_config_t; /*! Creates and initializes the nfapi_vnf_p7_config structure before use diff --git a/nfapi/open-nFAPI/vnf/src/vnf.c b/nfapi/open-nFAPI/vnf/src/vnf.c index 390c4b15d9..900521f85d 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf.c +++ b/nfapi/open-nFAPI/vnf/src/vnf.c @@ -117,7 +117,8 @@ void vnf_nr_handle_pnf_param_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_ nfapi_nr_pnf_param_response_t msg; // unpack the message - if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0) + const bool result = config->unpack_func(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config); + if (result) { // Invoke the call back if(config->pnf_nr_param_resp) @@ -188,7 +189,8 @@ void vnf_nr_handle_pnf_config_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf nfapi_nr_pnf_config_response_t msg; // unpack the message - if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0) + const bool result = config->unpack_func(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config); + if (result) { // Invoke the call back if(config->pnf_nr_config_resp) @@ -258,7 +260,8 @@ void vnf_nr_handle_pnf_start_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_ nfapi_nr_pnf_start_response_t msg; // unpack the message - if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0) + const bool result = config->unpack_func(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config); + if (result) { if(config->pnf_nr_start_resp) { @@ -428,7 +431,8 @@ void vnf_nr_handle_param_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_conf nfapi_nr_param_response_scf_t msg; // unpack the message - if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0) + const bool result = config->unpack_func(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config); + if (result) { if (msg.error_code == NFAPI_NR_PARAM_MSG_OK) @@ -495,7 +499,8 @@ void vnf_nr_handle_config_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_con nfapi_nr_config_response_scf_t msg; // unpack the message - if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >=0 ) + const bool result = config->unpack_func(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config); + if (result) { // check the error code: @@ -602,7 +607,8 @@ void vnf_nr_handle_start_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_conf nfapi_nr_start_response_scf_t msg; // unpack the message - if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0) + const bool result = config->unpack_func(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config); + if (result) { // check the error code if (msg.error_code == NFAPI_NR_START_MSG_OK){ if(config->nr_start_resp) @@ -1085,7 +1091,8 @@ void vnf_nr_handle_p4_p5_message(void *pRecvMsg, int recvMsgLen, int p5_idx, nfa } // unpack the message header - if (nfapi_nr_p5_message_header_unpack(pRecvMsg, recvMsgLen, &messageHeader, sizeof(nfapi_nr_p4_p5_message_header_t), &config->codec_config) < 0) + const bool result = config->hdr_unpack_func(pRecvMsg, recvMsgLen, &messageHeader, sizeof(nfapi_nr_p4_p5_message_header_t), &config->codec_config); + if (!result) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n"); return; @@ -1295,9 +1302,9 @@ int vnf_nr_read_dispatch_message(nfapi_vnf_config_t* config, nfapi_vnf_pnf_info_ } nfapi_nr_p4_p5_message_header_t header; - int unpack_result = nfapi_nr_p5_message_header_unpack(header_buffer, header_buffer_size, &header, sizeof(header), 0); - if (unpack_result < 0) { - NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Failed to decode message header %d\n", unpack_result); + const bool result = config->hdr_unpack_func(header_buffer, header_buffer_size, &header, sizeof(header), 0); + if (!result) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Failed to decode message header\n"); return 0; } message_size = header.message_length + header_buffer_size; diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7.c b/nfapi/open-nFAPI/vnf/src/vnf_p7.c index 3d2975d03c..6c37339d7d 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7.c @@ -1098,10 +1098,8 @@ void vnf_nr_handle_p7_vendor_extension(void *pRecvMsg, int recvMsgLen, vnf_p7_t* NFAPI_TRACE(NFAPI_TRACE_INFO, "%s failed to allocate vendor extention structure\n", __FUNCTION__); return; } - - int unpack_result = nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, msg, msg_size, &vnf_p7->_public.codec_config); - - if(unpack_result == 0) + const bool result = vnf_p7->_public.unpack_func(pRecvMsg, recvMsgLen, msg, msg_size, &vnf_p7->_public.codec_config); + if(!result) { if(vnf_p7->_public.vendor_ext) vnf_p7->_public.vendor_ext(&(vnf_p7->_public), msg); @@ -1497,8 +1495,8 @@ void vnf_handle_nr_slot_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf else { nfapi_nr_slot_indication_scf_t ind = {0}; - - if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0) + const bool result = vnf_p7->_public.unpack_func(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config); + if(!result) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); } @@ -1524,8 +1522,8 @@ void vnf_handle_nr_rx_data_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* else { nfapi_nr_rx_data_indication_t ind; - - if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0) + const bool result = vnf_p7->_public.unpack_func(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config); + if(!result) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); } @@ -1551,8 +1549,8 @@ void vnf_handle_nr_crc_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_ else { nfapi_nr_crc_indication_t ind; - - if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0) + const bool result = vnf_p7->_public.unpack_func(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config); + if(!result) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); } @@ -1578,8 +1576,8 @@ void vnf_handle_nr_srs_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_ else { nfapi_nr_srs_indication_t ind; - - if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0) + const bool result = vnf_p7->_public.unpack_func(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config); + if(!result) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); } @@ -1604,8 +1602,8 @@ void vnf_handle_nr_uci_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_ else { nfapi_nr_uci_indication_t ind; - - if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0) + const bool result = vnf_p7->_public.unpack_func(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config); + if(!result) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); } @@ -1631,8 +1629,8 @@ void vnf_handle_nr_rach_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf else { nfapi_nr_rach_indication_t ind; - - if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0) + const bool result = vnf_p7->_public.unpack_func(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config); + if(!result) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); } @@ -1661,7 +1659,8 @@ void vnf_nr_handle_ul_node_sync(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7 } nfapi_nr_ul_node_sync_t ind; - if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(nfapi_nr_ul_node_sync_t), &vnf_p7->_public.codec_config) < 0) + const bool result = vnf_p7->_public.unpack_func(pRecvMsg, recvMsgLen, &ind, sizeof(nfapi_nr_ul_node_sync_t), &vnf_p7->_public.codec_config); + if(!result) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failed to unpack ul_node_sync\n"); return; @@ -2096,7 +2095,8 @@ void vnf_nr_handle_timing_info(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) } nfapi_nr_timing_info_t ind; - if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(nfapi_timing_info_t), &vnf_p7->_public.codec_config) < 0) + const bool result = vnf_p7->_public.unpack_func(pRecvMsg, recvMsgLen, &ind, sizeof(nfapi_timing_info_t), &vnf_p7->_public.codec_config); + if(!result) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failed to unpack timing_info\n"); return; @@ -2232,7 +2232,8 @@ void vnf_nr_dispatch_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7 } // unpack the message header - if (nfapi_nr_p7_message_header_unpack(pRecvMsg, recvMsgLen, &header, sizeof(header), &vnf_p7->_public.codec_config) < 0) + const bool result = vnf_p7->_public.hdr_unpack_func(pRecvMsg, recvMsgLen, &header, sizeof(header), &vnf_p7->_public.codec_config); + if (!result) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n"); return; @@ -2429,7 +2430,8 @@ void vnf_nr_handle_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) } // unpack the message header - if (nfapi_nr_p7_message_header_unpack(pRecvMsg, recvMsgLen, &messageHeader, sizeof(nfapi_nr_p7_message_header_t), &vnf_p7->_public.codec_config) < 0) + const bool result = vnf_p7->_public.hdr_unpack_func(pRecvMsg, recvMsgLen, &messageHeader, sizeof(nfapi_nr_p7_message_header_t), &vnf_p7->_public.codec_config); + if (!result) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n"); return; @@ -2552,7 +2554,8 @@ int vnf_nr_p7_read_dispatch_message(vnf_p7_t* vnf_p7) { // get the segment size nfapi_nr_p7_message_header_t header; - if(nfapi_nr_p7_message_header_unpack(header_buffer, NFAPI_NR_P7_HEADER_LENGTH, &header, sizeof(header), 0) < 0) + const bool result = vnf_p7->_public.hdr_unpack_func(header_buffer, NFAPI_NR_P7_HEADER_LENGTH, &header, sizeof(header), 0); + if(!result) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n"); return -1; From 52a0ceac0444101af460926ef08ed0ab8cdace93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Soares=20Silva?= Date: Wed, 2 Apr 2025 17:46:21 +0100 Subject: [PATCH 091/964] Add send function pointers to VNF --- nfapi/oai_integration/nfapi_vnf.c | 20 ++++++----- nfapi/open-nFAPI/vnf/inc/vnf.h | 6 ++-- nfapi/open-nFAPI/vnf/inc/vnf_p7.h | 6 ++-- .../vnf/public_inc/nfapi_vnf_interface.h | 33 ++++++++++++++++--- nfapi/open-nFAPI/vnf/src/vnf.c | 10 +++--- nfapi/open-nFAPI/vnf/src/vnf_interface.c | 31 ++++++++--------- nfapi/open-nFAPI/vnf/src/vnf_p7.c | 14 ++++---- nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c | 20 ++++++----- 8 files changed, 86 insertions(+), 54 deletions(-) diff --git a/nfapi/oai_integration/nfapi_vnf.c b/nfapi/oai_integration/nfapi_vnf.c index f7b5575084..32c0e61ee7 100644 --- a/nfapi/oai_integration/nfapi_vnf.c +++ b/nfapi/oai_integration/nfapi_vnf.c @@ -34,6 +34,8 @@ #include "nfapi_nr_interface_scf.h" #include "nfapi_vnf_interface.h" #include "nfapi_vnf.h" +#include +#include #include "nfapi.h" #include "vendor_ext.h" @@ -1448,6 +1450,7 @@ void *vnf_nr_p7_thread_start(void *ptr) p7_vnf->config->unpack_func = &nfapi_nr_p7_message_unpack; p7_vnf->config->hdr_unpack_func = &nfapi_nr_p7_message_header_unpack; p7_vnf->config->pack_func = &nfapi_nr_p7_message_pack; + p7_vnf->config->send_p7_msg = &vnf_nr_send_p7_msg; NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Creating VNF NFAPI P7 start thread %s\n", __FUNCTION__); pthread_create(&vnf_p7_start_pthread, NULL, &vnf_nr_p7_start_thread, p7_vnf->config); return 0; @@ -1868,6 +1871,7 @@ void configure_nr_nfapi_vnf(char *vnf_addr, int vnf_p5_port, char *pnf_ip_addr, config->unpack_func = &nfapi_nr_p5_message_unpack; config->hdr_unpack_func = &nfapi_nr_p5_message_header_unpack; config->pack_func = &nfapi_nr_p5_message_pack; + config->send_p5_msg = &vnf_nr_send_p5_message; NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Creating VNF NFAPI start thread %s\n", __FUNCTION__); pthread_create(&vnf_start_pthread, NULL, (void *)&vnf_nr_start_thread, config); NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Created VNF NFAPI start thread %s\n", __FUNCTION__); @@ -1963,13 +1967,13 @@ int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req) dl_config_req->header.message_id= NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST; dl_config_req->header.phy_id = 1; // HACK TODO FIXME - need to pass this around!!!! - int retval = nfapi_vnf_p7_nr_dl_config_req(p7_config, dl_config_req); + bool retval = nfapi_vnf_p7_nr_dl_config_req(p7_config, dl_config_req); dl_config_req->dl_tti_request_body.nPDUs = 0; dl_config_req->dl_tti_request_body.nGroup = 0; - if (retval!=0) { + if (!retval) { LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval); } return retval; @@ -1982,9 +1986,9 @@ int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req) tx_data_req->header.phy_id = 1; // HACK TODO FIXME - need to pass this around!!!! tx_data_req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST; //LOG_D(PHY, "[VNF] %s() TX_REQ sfn_sf:%d number_of_pdus:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(tx_req->sfn_sf), tx_req->tx_request_body.number_of_pdus); - int retval = nfapi_vnf_p7_tx_data_req(p7_config, tx_data_req); + bool retval = nfapi_vnf_p7_tx_data_req(p7_config, tx_data_req); - if (retval!=0) { + if (!retval) { LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval); } else { tx_data_req->Number_of_PDUs = 0; @@ -2015,9 +2019,9 @@ int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req) { ul_dci_req->header.phy_id = 1; // HACK TODO FIXME - need to pass this around!!!! ul_dci_req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST; //LOG_D(PHY, "[VNF] %s() HI_DCI0_REQ sfn_sf:%d dci:%d hi:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(hi_dci0_req->sfn_sf), hi_dci0_req->hi_dci0_request_body.number_of_dci, hi_dci0_req->hi_dci0_request_body.number_of_hi); - int retval = nfapi_vnf_p7_ul_dci_req(p7_config, ul_dci_req); + bool retval = nfapi_vnf_p7_ul_dci_req(p7_config, ul_dci_req); - if (retval!=0) { + if (!retval) { LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval); } else { ul_dci_req->numPdus = 0; @@ -2068,9 +2072,9 @@ int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req) { ul_tti_req->header.phy_id = 1; // HACK TODO FIXME - need to pass this around!!!! ul_tti_req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST; - int retval = nfapi_vnf_p7_ul_tti_req(p7_config, ul_tti_req); + bool retval = nfapi_vnf_p7_ul_tti_req(p7_config, ul_tti_req); - if (retval!=0) { + if (!retval) { LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval); } else { // Reset number of PDUs so that it is not resent diff --git a/nfapi/open-nFAPI/vnf/inc/vnf.h b/nfapi/open-nFAPI/vnf/inc/vnf.h index 26870f5523..006bb2014c 100644 --- a/nfapi/open-nFAPI/vnf/inc/vnf.h +++ b/nfapi/open-nFAPI/vnf/inc/vnf.h @@ -20,7 +20,7 @@ #include "nfapi_vnf_interface.h" -typedef struct +struct vnf_t { nfapi_vnf_config_t _public; @@ -31,11 +31,11 @@ typedef struct uint8_t tx_message_buffer[NFAPI_MAX_PACKED_MESSAGE_SIZE]; uint16_t next_phy_id; -} vnf_t; +}; int vnf_pack_and_send_p5_message(vnf_t* vnf, uint16_t p5_idx, nfapi_p4_p5_message_header_t* msg, uint16_t msg_len); -int vnf_nr_pack_and_send_p5_message(vnf_t* vnf, uint16_t p5_idx, nfapi_nr_p4_p5_message_header_t* msg, uint16_t msg_len); +bool vnf_nr_send_p5_message(vnf_t* vnf, uint16_t p5_idx, nfapi_nr_p4_p5_message_header_t* msg, uint32_t msg_len); int vnf_pack_and_send_p4_message(vnf_t* vnf, uint16_t p5_idx, nfapi_p4_p5_message_header_t* msg, uint16_t msg_len); diff --git a/nfapi/open-nFAPI/vnf/inc/vnf_p7.h b/nfapi/open-nFAPI/vnf/inc/vnf_p7.h index 92623b41b8..d368c0fa83 100644 --- a/nfapi/open-nFAPI/vnf/inc/vnf_p7.h +++ b/nfapi/open-nFAPI/vnf/inc/vnf_p7.h @@ -108,7 +108,7 @@ typedef struct nfapi_vnf_p7_connection_info { } nfapi_vnf_p7_connection_info_t; -typedef struct { +struct vnf_p7_t{ nfapi_vnf_p7_config_t _public; @@ -121,7 +121,7 @@ typedef struct { uint8_t* rx_message_buffer; // would this be better put in the p7 conenction info? uint16_t rx_message_buffer_size; -} vnf_p7_t; +}; uint32_t vnf_get_current_time_hr(void); @@ -139,7 +139,7 @@ nfapi_vnf_p7_connection_info_t* vnf_p7_connection_info_list_find(vnf_p7_t* vnf_p nfapi_vnf_p7_connection_info_t* vnf_p7_connection_info_list_delete(vnf_p7_t* vnf_p7, uint16_t phy_id); int vnf_p7_pack_and_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_p7_message_header_t* header); -int vnf_nr_p7_pack_and_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_nr_p7_message_header_t* header); +bool vnf_nr_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_nr_p7_message_header_t* header); void vnf_p7_release_msg(vnf_p7_t* vnf_p7, nfapi_p7_message_header_t* header); void vnf_p7_release_pdu(vnf_p7_t* vnf_p7, void* pdu); diff --git a/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h b/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h index ba01329b2d..c791ff7028 100644 --- a/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h +++ b/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h @@ -30,6 +30,9 @@ extern "C" { #endif +typedef struct vnf_t vnf_t; +typedef struct vnf_p7_t vnf_p7_t; + #define NFAPI_MAX_PACKED_MESSAGE_SIZE 32768 /*! The nfapi VNF phy configuration information @@ -491,9 +494,19 @@ typedef struct nfapi_vnf_config uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t* config); + /*! \brief Sends a (n)FAPI P5 message + * + * This function internally packs the given message into a buffer by calling the previously defined pack_func() function pointer + * Then, having the message buffer populated, sends it to the PNF + * \param vnf A pointer to a vnf_t* + * \param p5_idx The index of the P5 PNF intended to receive the message + * \param msg A pointer to the P5 message + * \param msg_len The size of the encoded P5 message header + * \return true on success, false on failure + */ + bool (*send_p5_msg)(vnf_t* vnf, uint16_t p5_idx, nfapi_nr_p4_p5_message_header_t* msg, uint32_t msg_len); - } nfapi_vnf_config_t; /*! Creates and initialise the vnf config structure before use @@ -954,6 +967,16 @@ typedef struct nfapi_vnf_p7_config void* pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p7_codec_config_t* config); + + /*! \brief Sends a (n)FAPI P7 message + * + * This function internally packs the given message into a buffer by calling the previously defined pack_func() function pointer + * Then, having the message buffer populated, sends it to the PNF + * \param vnf_p7 A pointer to a vnf_p7_t struct + * \param header A pointer to the P7 message to pack & send + * \return true on success, false on failure + */ + bool (*send_p7_msg)(vnf_p7_t* vnf_p7, nfapi_nr_p7_message_header_t* header); } nfapi_vnf_p7_config_t; /*! Creates and initializes the nfapi_vnf_p7_config structure before use @@ -1034,7 +1057,7 @@ int nfapi_vnf_p7_del_pnf(nfapi_vnf_p7_config_t* config, int phy_id); * may be released after this function call has returned or at a later pointer */ int nfapi_vnf_p7_dl_config_req(nfapi_vnf_p7_config_t* config, nfapi_dl_config_request_t* req); -int nfapi_vnf_p7_nr_dl_config_req(nfapi_vnf_p7_config_t* config, nfapi_nr_dl_tti_request_t* req); +bool nfapi_vnf_p7_nr_dl_config_req(nfapi_vnf_p7_config_t* config, nfapi_nr_dl_tti_request_t* req); /*! Send the UL_CONFIG.request * \param config A pointer to the vnf p7 configuration @@ -1045,7 +1068,7 @@ int nfapi_vnf_p7_nr_dl_config_req(nfapi_vnf_p7_config_t* config, nfapi_nr_dl_tti * may be released after this function call has returned or at a later pointer */ int nfapi_vnf_p7_ul_config_req(nfapi_vnf_p7_config_t* config, nfapi_ul_config_request_t* req); -int nfapi_vnf_p7_ul_tti_req(nfapi_vnf_p7_config_t* config, nfapi_nr_ul_tti_request_t* req); +bool nfapi_vnf_p7_ul_tti_req(nfapi_vnf_p7_config_t* config, nfapi_nr_ul_tti_request_t* req); /*! Send the HI_DCI0.request * \param config A pointer to the vnf p7 configuration * \param req A data structure for the decoded HI_DCI0.request. @@ -1055,7 +1078,7 @@ int nfapi_vnf_p7_ul_tti_req(nfapi_vnf_p7_config_t* config, nfapi_nr_ul_tti_reque * may be released after this function call has returned or at a later pointer */ int nfapi_vnf_p7_hi_dci0_req(nfapi_vnf_p7_config_t* config, nfapi_hi_dci0_request_t* req); -int nfapi_vnf_p7_ul_dci_req(nfapi_vnf_p7_config_t* config, nfapi_nr_ul_dci_request_t* req); +bool nfapi_vnf_p7_ul_dci_req(nfapi_vnf_p7_config_t* config, nfapi_nr_ul_dci_request_t* req); /*! Send the TX.req * \param config A pointer to the vnf p7 configuration * \param req A data structure for the decoded HI_DCI0.request. @@ -1065,7 +1088,7 @@ int nfapi_vnf_p7_ul_dci_req(nfapi_vnf_p7_config_t* config, nfapi_nr_ul_dci_reque * may be released after this function call has returned or at a later pointer */ int nfapi_vnf_p7_tx_req(nfapi_vnf_p7_config_t* config, nfapi_tx_request_t* req); -int nfapi_vnf_p7_tx_data_req(nfapi_vnf_p7_config_t* config, nfapi_nr_tx_data_request_t* req); +bool nfapi_vnf_p7_tx_data_req(nfapi_vnf_p7_config_t* config, nfapi_nr_tx_data_request_t* req); /*! Send the LBT_DL_CONFIG.requst * \param config A pointer to the vnf p7 configuration * \param req A data structure for the decoded LBT_DL_CONFIG.request. diff --git a/nfapi/open-nFAPI/vnf/src/vnf.c b/nfapi/open-nFAPI/vnf/src/vnf.c index 900521f85d..baac137512 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf.c +++ b/nfapi/open-nFAPI/vnf/src/vnf.c @@ -1537,7 +1537,7 @@ static int vnf_send_p5_msg(nfapi_vnf_pnf_info_t* pnf, const void *msg, int len, return 0; } -int vnf_nr_pack_and_send_p5_message(vnf_t* vnf, uint16_t p5_idx, nfapi_nr_p4_p5_message_header_t* msg, uint16_t msg_len) +bool vnf_nr_send_p5_message(vnf_t* vnf, uint16_t p5_idx, nfapi_nr_p4_p5_message_header_t* msg, uint32_t msg_len) { nfapi_vnf_pnf_info_t* pnf = nfapi_vnf_pnf_list_find(&(vnf->_public), p5_idx); @@ -1554,9 +1554,9 @@ int vnf_nr_pack_and_send_p5_message(vnf_t* vnf, uint16_t p5_idx, nfapi_nr_p4_p5_ int packedMessageLengthFAPI = -1; packedMessageLengthFAPI = fapi_nr_p5_message_pack(msg, msg_len, tx_messagebufferFAPI, sizeof(tx_messagebufferFAPI), &vnf->_public.codec_config); - return aerial_send_P5_msg(tx_messagebufferFAPI, packedMessageLengthFAPI, msg); + return aerial_send_P5_msg(tx_messagebufferFAPI, packedMessageLengthFAPI, msg) == 0; #else - return 0; + return true; #endif } else { packedMessageLength = nfapi_nr_p5_message_pack(msg, @@ -1567,7 +1567,7 @@ int vnf_nr_pack_and_send_p5_message(vnf_t* vnf, uint16_t p5_idx, nfapi_nr_p4_p5_ if (packedMessageLength < 0) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi_nr_p5_message_pack failed with return %d\n", packedMessageLength); - return -1; + return false; } // printf("msg id = 0x%02x, entire message length: %d\n", msg->message_id, packedMessageLength); // for (int i = 0; i < packedMessageLength; i++) { @@ -1578,7 +1578,7 @@ int vnf_nr_pack_and_send_p5_message(vnf_t* vnf, uint16_t p5_idx, nfapi_nr_p4_p5_ } } else { NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() cannot find pnf info for p5_idx:%d\n", __FUNCTION__, p5_idx); - return -1; + return false; } } diff --git a/nfapi/open-nFAPI/vnf/src/vnf_interface.c b/nfapi/open-nFAPI/vnf/src/vnf_interface.c index 633dd18f24..d964e5b9dc 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_interface.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_interface.c @@ -1,12 +1,12 @@ /* * Copyright 2017 Cisco Systems, Inc. - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -14,6 +14,7 @@ * limitations under the License. */ +#include "assertions.h" #include #include @@ -894,8 +895,8 @@ int nfapi_nr_vnf_pnf_param_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_ return -1; vnf_t* _this = (vnf_t*)(config); - - return vnf_nr_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_nr_pnf_param_request_t)); + AssertFatal(config->send_p5_msg, "Function pointer must be configured\n"); + return config->send_p5_msg(_this, p5_idx, &req->header, sizeof(nfapi_nr_pnf_param_request_t)); } int nfapi_vnf_pnf_param_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_param_request_t* req) @@ -914,8 +915,8 @@ int nfapi_nr_vnf_pnf_config_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr return -1; vnf_t* _this = (vnf_t*)(config); - - return vnf_nr_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_nr_pnf_config_request_t)); + AssertFatal(config->send_p5_msg, "Function pointer must be configured\n"); + return config->send_p5_msg(_this, p5_idx, &req->header, sizeof(nfapi_nr_pnf_config_request_t)); } @@ -945,8 +946,8 @@ int nfapi_nr_vnf_pnf_start_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_ return -1; vnf_t* _this = (vnf_t*)(config); - - return vnf_nr_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_nr_pnf_start_request_t)); + AssertFatal(config->send_p5_msg, "Function pointer must be configured\n"); + return config->send_p5_msg(_this, p5_idx, &req->header, sizeof(nfapi_nr_pnf_start_request_t)); } int nfapi_vnf_pnf_stop_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_stop_request_t* req) @@ -965,8 +966,8 @@ int nfapi_nr_vnf_param_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_para return -1; vnf_t* _this = (vnf_t*)(config); - - return vnf_nr_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_nr_param_request_scf_t)); + AssertFatal(config->send_p5_msg, "Function pointer must be configured\n"); + return config->send_p5_msg(_this, p5_idx, &req->header, sizeof(nfapi_nr_param_request_scf_t)); } int nfapi_vnf_param_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_param_request_t* req) @@ -983,7 +984,7 @@ int nfapi_nr_vnf_config_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_con { if(config == 0 || req == 0) return -1; - + AssertFatal(config->send_p5_msg, "Function pointer must be configured\n"); vnf_t* _this = (vnf_t*)(config); nfapi_vnf_phy_info_t* phy = nfapi_vnf_phy_info_list_find(config, req->header.phy_id); @@ -1007,7 +1008,7 @@ int nfapi_nr_vnf_config_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_con req->nfapi_config.timing_info_period.value = phy->timing_info_period; req->num_tlv++; - return vnf_nr_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_nr_config_request_scf_t)); + return config->send_p5_msg(_this, p5_idx, &req->header, sizeof(nfapi_nr_config_request_scf_t)); } int nfapi_vnf_config_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_config_request_t* req) @@ -1057,8 +1058,8 @@ int nfapi_nr_vnf_start_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_star return -1; vnf_t* _this = (vnf_t*)(config); - - return vnf_nr_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_nr_start_request_scf_t)); + AssertFatal(config->send_p5_msg, "Function pointer must be configured\n"); + return config->send_p5_msg(_this, p5_idx, &req->header, sizeof(nfapi_nr_start_request_scf_t)); } diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7.c b/nfapi/open-nFAPI/vnf/src/vnf_p7.c index 6c37339d7d..d1c4105997 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7.c @@ -473,9 +473,8 @@ int vnf_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t* p7_info, u return 0; } -int vnf_nr_p7_pack_and_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_nr_p7_message_header_t* header) +bool vnf_nr_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_nr_p7_message_header_t* header) { - nfapi_vnf_p7_connection_info_t* p7_connection = vnf_p7_connection_info_list_find(vnf_p7, header->phy_id); if(p7_connection) { @@ -491,7 +490,7 @@ int vnf_nr_p7_pack_and_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_nr_p7_message_header_ if(len < 0) { NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() failed to pack p7 message phy_id:%d\n", __FUNCTION__, header->phy_id); - return -1; + return false; } if(len > vnf_p7->_public.segment_size) @@ -560,12 +559,12 @@ int vnf_nr_p7_pack_and_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_nr_p7_message_header_ } p7_connection->sequence_number++; - return send_result; + return send_result == 0; } else { NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() cannot find p7 connection info for phy_id:%d\n", __FUNCTION__, header->phy_id); - return -1; + return false; } } @@ -676,7 +675,8 @@ int vnf_build_send_dl_node_sync(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t } int vnf_nr_build_send_dl_node_sync(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t* p7_info) -{ +{ + nfapi_vnf_p7_config_t* config = (nfapi_vnf_p7_config_t*)vnf_p7; nfapi_nr_dl_node_sync_t dl_node_sync; memset(&dl_node_sync, 0, sizeof(dl_node_sync)); @@ -686,7 +686,7 @@ int vnf_nr_build_send_dl_node_sync(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_inf dl_node_sync.t1 = calculate_nr_t1(p7_info->mu, p7_info->sfn,p7_info->slot, vnf_p7->slot_start_time_hr); dl_node_sync.delta_sfn_slot = 0; - return vnf_nr_p7_pack_and_send_p7_msg(vnf_p7, &dl_node_sync.header); + return config->send_p7_msg(vnf_p7, &dl_node_sync.header); } int vnf_nr_sync(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t* p7_info) diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c index d3160f4e30..c536995e91 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c @@ -600,7 +600,7 @@ int nfapi_vnf_p7_dl_config_req(nfapi_vnf_p7_config_t* config, nfapi_dl_config_re return vnf_p7_pack_and_send_p7_msg(vnf_p7, &req->header); } -int nfapi_vnf_p7_nr_dl_config_req(nfapi_vnf_p7_config_t* config, nfapi_nr_dl_tti_request_t* req) +bool nfapi_vnf_p7_nr_dl_config_req(nfapi_vnf_p7_config_t* config, nfapi_nr_dl_tti_request_t* req) { //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s(config:%p req:%p)\n", __FUNCTION__, config, req); @@ -608,15 +608,17 @@ int nfapi_vnf_p7_nr_dl_config_req(nfapi_vnf_p7_config_t* config, nfapi_nr_dl_tti return -1; vnf_p7_t* vnf_p7 = (vnf_p7_t*)config; - return vnf_nr_p7_pack_and_send_p7_msg(vnf_p7, &req->header); + AssertFatal(config->send_p7_msg, "Function pointer must be configured|"); + return config->send_p7_msg(vnf_p7, &req->header); } -int nfapi_vnf_p7_ul_tti_req(nfapi_vnf_p7_config_t* config, nfapi_nr_ul_tti_request_t* req) +bool nfapi_vnf_p7_ul_tti_req(nfapi_vnf_p7_config_t* config, nfapi_nr_ul_tti_request_t* req) { if(config == 0 || req == 0) return -1; vnf_p7_t* vnf_p7 = (vnf_p7_t*)config; - return vnf_nr_p7_pack_and_send_p7_msg(vnf_p7, &req->header); + AssertFatal(config->send_p7_msg, "Function pointer must be configured|"); + return config->send_p7_msg(vnf_p7, &req->header); } int nfapi_vnf_p7_ul_config_req(nfapi_vnf_p7_config_t* config, nfapi_ul_config_request_t* req) @@ -627,13 +629,14 @@ int nfapi_vnf_p7_ul_config_req(nfapi_vnf_p7_config_t* config, nfapi_ul_config_re vnf_p7_t* vnf_p7 = (vnf_p7_t*)config; return vnf_p7_pack_and_send_p7_msg(vnf_p7, &req->header); } -int nfapi_vnf_p7_ul_dci_req(nfapi_vnf_p7_config_t* config, nfapi_nr_ul_dci_request_t* req) +bool nfapi_vnf_p7_ul_dci_req(nfapi_vnf_p7_config_t* config, nfapi_nr_ul_dci_request_t* req) { if(config == 0 || req == 0) return -1; vnf_p7_t* vnf_p7 = (vnf_p7_t*)config; - return vnf_nr_p7_pack_and_send_p7_msg(vnf_p7, &req->header); + AssertFatal(config->send_p7_msg, "Function pointer must be configured|"); + return config->send_p7_msg(vnf_p7, &req->header); } int nfapi_vnf_p7_hi_dci0_req(nfapi_vnf_p7_config_t* config, nfapi_hi_dci0_request_t* req) { @@ -643,13 +646,14 @@ int nfapi_vnf_p7_hi_dci0_req(nfapi_vnf_p7_config_t* config, nfapi_hi_dci0_reques vnf_p7_t* vnf_p7 = (vnf_p7_t*)config; return vnf_p7_pack_and_send_p7_msg(vnf_p7, &req->header); } -int nfapi_vnf_p7_tx_data_req(nfapi_vnf_p7_config_t* config, nfapi_nr_tx_data_request_t* req) +bool nfapi_vnf_p7_tx_data_req(nfapi_vnf_p7_config_t* config, nfapi_nr_tx_data_request_t* req) { if(config == 0 || req == 0) return -1; vnf_p7_t* vnf_p7 = (vnf_p7_t*)config; - return vnf_nr_p7_pack_and_send_p7_msg(vnf_p7, &req->header); + AssertFatal(config->send_p7_msg, "Function pointer must be configured|"); + return config->send_p7_msg(vnf_p7, &req->header); } int nfapi_vnf_p7_tx_req(nfapi_vnf_p7_config_t* config, nfapi_tx_request_t* req) { From 471b563ac7511d9ce9bb25e823a1055e5cdb43fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Soares=20Silva?= Date: Wed, 2 Apr 2025 17:50:58 +0100 Subject: [PATCH 092/964] Add send function pointers to PNF --- nfapi/oai_integration/nfapi_pnf.c | 3 ++ nfapi/open-nFAPI/pnf/inc/pnf.h | 6 ++-- nfapi/open-nFAPI/pnf/inc/pnf_p7.h | 8 ++---- .../pnf/public_inc/nfapi_pnf_interface.h | 28 +++++++++++++++++-- nfapi/open-nFAPI/pnf/src/pnf.c | 6 ++-- nfapi/open-nFAPI/pnf/src/pnf_interface.c | 24 ++++++++-------- nfapi/open-nFAPI/pnf/src/pnf_p7.c | 21 +++++++------- nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c | 19 ++++++++----- 8 files changed, 72 insertions(+), 43 deletions(-) diff --git a/nfapi/oai_integration/nfapi_pnf.c b/nfapi/oai_integration/nfapi_pnf.c index b58463a7de..f1010bde1a 100644 --- a/nfapi/oai_integration/nfapi_pnf.c +++ b/nfapi/oai_integration/nfapi_pnf.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include "fapi_stub.h" @@ -1750,6 +1751,7 @@ int nr_start_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nf p7_config->unpack_func = &nfapi_nr_p7_message_unpack; p7_config->hdr_unpack_func = &nfapi_nr_p7_message_header_unpack; p7_config->pack_func = &nfapi_nr_p7_message_pack; + p7_config->send_p7_msg = &pnf_nr_send_p7_message; NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] Creating P7 thread %s\n", __FUNCTION__); pthread_t p7_thread; threadCreate(&p7_thread, &pnf_nr_p7_thread_start, p7_config, "pnf_p7_thread", -1, OAI_PRIORITY_RT); @@ -2194,6 +2196,7 @@ void configure_nr_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_add config->unpack_func = &nfapi_nr_p5_message_unpack; config->hdr_unpack_func = &nfapi_nr_p5_message_header_unpack; config->pack_func = &nfapi_nr_p5_message_pack; + config->send_p5_msg = &pnf_nr_send_p5_message; NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] Creating PNF NFAPI start thread %s\n", __FUNCTION__); pthread_create(&pnf_start_pthread, NULL, &pnf_nr_start_thread, config); pthread_setname_np(pnf_start_pthread, "NFAPI_PNF"); diff --git a/nfapi/open-nFAPI/pnf/inc/pnf.h b/nfapi/open-nFAPI/pnf/inc/pnf.h index 7275db76e1..386cb3cf6a 100644 --- a/nfapi/open-nFAPI/pnf/inc/pnf.h +++ b/nfapi/open-nFAPI/pnf/inc/pnf.h @@ -22,7 +22,7 @@ #define NFAPI_MAX_PACKED_MESSAGE_SIZE 32768 -typedef struct { +struct pnf_t { nfapi_pnf_config_t _public; @@ -33,14 +33,14 @@ typedef struct { uint8_t terminate; -} pnf_t; +}; int pnf_connect(pnf_t *pnf); int pnf_message_pump(pnf_t *pnf); int pnf_nr_message_pump(pnf_t *pnf); -int pnf_nr_pack_and_send_p5_message(pnf_t* pnf, nfapi_nr_p4_p5_message_header_t* msg, uint32_t msg_len); +bool pnf_nr_send_p5_message(pnf_t* pnf, nfapi_nr_p4_p5_message_header_t* msg, uint32_t msg_len); int pnf_pack_and_send_p5_message(pnf_t* pnf, nfapi_p4_p5_message_header_t* msg, uint32_t msg_len); int pnf_pack_and_send_p4_message(pnf_t* pnf, nfapi_p4_p5_message_header_t* msg, uint32_t msg_len); int pnf_send_message(pnf_t* pnf, uint8_t* msg, uint32_t msg_len, uint16_t stream_id); diff --git a/nfapi/open-nFAPI/pnf/inc/pnf_p7.h b/nfapi/open-nFAPI/pnf/inc/pnf_p7.h index 0325c8c242..8a603ecdb3 100644 --- a/nfapi/open-nFAPI/pnf/inc/pnf_p7.h +++ b/nfapi/open-nFAPI/pnf/inc/pnf_p7.h @@ -82,7 +82,7 @@ typedef struct { } pnf_p7_rx_reassembly_queue_t; -typedef struct { +struct pnf_p7_t { nfapi_pnf_p7_config_t _public; @@ -139,12 +139,12 @@ typedef struct { pnf_p7_stats_t stats; pnf_p7_nr_stats_t nr_stats; -} pnf_p7_t; +}; int pnf_p7_message_pump(pnf_p7_t* pnf_p7); int pnf_nr_p7_message_pump(pnf_p7_t* pnf_p7); int pnf_p7_pack_and_send_p7_message(pnf_p7_t* pnf_p7, nfapi_p7_message_header_t* msg, uint32_t msg_len); -int pnf_nr_p7_pack_and_send_p7_message(pnf_p7_t* pnf_p7, nfapi_nr_p7_message_header_t* header, uint32_t msg_len); +bool pnf_nr_send_p7_message(pnf_p7_t* pnf_p7, nfapi_nr_p7_message_header_t* header, uint32_t msg_len); int pnf_p7_send_message(pnf_p7_t* pnf_p7, uint8_t* msg, uint32_t msg_len); @@ -160,7 +160,5 @@ pnf_p7_rx_message_t* pnf_p7_rx_reassembly_queue_add_segment(pnf_p7_t* pnf_p7, pn void pnf_p7_rx_reassembly_queue_remove_msg(pnf_p7_t* pnf_p7, pnf_p7_rx_reassembly_queue_t* queue, pnf_p7_rx_message_t* msg); void pnf_p7_rx_reassembly_queue_remove_old_msgs(pnf_p7_t* pnf_p7, pnf_p7_rx_reassembly_queue_t* queue, uint32_t rx_hr_time, uint32_t delta); -int pnf_nr_p7_pack_and_send_p7_message(pnf_p7_t* pnf_p7, nfapi_nr_p7_message_header_t* header, uint32_t msg_len); - #endif /* _PNF_P7_H_ */ diff --git a/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h b/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h index 2e4cb8812c..04abf6309d 100644 --- a/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h +++ b/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h @@ -31,8 +31,8 @@ extern "C" { #include #include "openair1/PHY/defs_gNB.h" - - +typedef struct pnf_t pnf_t; +typedef struct pnf_p7_t pnf_p7_t; /*! This enum is used to describe the states of the pnf */ @@ -320,6 +320,8 @@ typedef struct nfapi_pnf_config void (*deallocate_p4_p5_vendor_ext)(void* header); /*! \brief Encodes an (n)FAPI P5 message to a buffer + * + * This function is called internally in send_p5_msg() * \param pMessageBuf A pointer to a nfapi p5 message structure * \param messageBufLen The size of the p5 message structure * \param pPackedBuf A pointer to the buffer that the p5 message will be packed into @@ -361,6 +363,16 @@ typedef struct nfapi_pnf_config uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t* config); + /*! \brief Sends a (N)FAPI P5 message + * + * This function internally packs the given message into a buffer by calling the previously defined pack_func() function pointer + * Then, having the message buffer populated, sends it to the VNF + * \param pnf A pointer to a pnf_t* + * \param msg A pointer to the P5 message + * \param msg_len The size of the encoded P5 message + * \return true on success, false on failure. + */ + bool (*send_p5_msg)(pnf_t* pnf, nfapi_nr_p4_p5_message_header_t* msg, uint32_t msg_len); } nfapi_pnf_config_t; /*! Create a pnf configuration @@ -767,6 +779,8 @@ typedef struct nfapi_pnf_p7_config void (*deallocate_p7_vendor_ext)(void* header); /*! A callback to pack a P7 message + * + * This function is called internally in send_p7_msg() * \param pMessageBuf A pointer to a nfapi p7 message structure * \param pPackedBuf A pointer to the buffer that the p7 message will be packed into * \param packedBufLen The size of the buffer @@ -803,6 +817,16 @@ typedef struct nfapi_pnf_p7_config uint32_t unpackedBufLen, nfapi_p7_codec_config_t* config); + /*! \brief Sends a (N)FAPI P7 message + * + * This function internally packs the given message into a buffer by calling the previously defined pack_func() function pointer + * Then, having the message buffer populated, sends it to the VNF + * \param pnf_p7 A pointer to a pnf_p7_t struct + * \param header A pointer to the P7 message to pack & send + * \param msg_len The P7 message length + * \return true on success, false on failure. + */ + bool (*send_p7_msg)(pnf_p7_t* pnf_p7, nfapi_nr_p7_message_header_t* header, uint32_t msg_len); } nfapi_pnf_p7_config_t; /*! Create and initialise a nfapi_pnf_p7_config structure diff --git a/nfapi/open-nFAPI/pnf/src/pnf.c b/nfapi/open-nFAPI/pnf/src/pnf.c index e4438eded7..7ed881f7e3 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf.c +++ b/nfapi/open-nFAPI/pnf/src/pnf.c @@ -1705,17 +1705,17 @@ void pnf_handle_p5_message(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) } } -int pnf_nr_pack_and_send_p5_message(pnf_t* pnf, nfapi_nr_p4_p5_message_header_t* msg, uint32_t msg_len) +bool pnf_nr_send_p5_message(pnf_t* pnf, nfapi_nr_p4_p5_message_header_t* msg, uint32_t msg_len) { int packed_len = pnf->_public.pack_func(msg, msg_len, pnf->tx_message_buffer, sizeof(pnf->tx_message_buffer), &pnf->_public.codec_config); if (packed_len < 0) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi_nr_p5_message_pack failed (%d)\n", packed_len); - return -1; + return false; } - return pnf_send_message(pnf, pnf->tx_message_buffer, packed_len, 0 /*msg->stream_id*/); + return pnf_send_message(pnf, pnf->tx_message_buffer, packed_len, 0 /*msg->stream_id*/) == 0; } diff --git a/nfapi/open-nFAPI/pnf/src/pnf_interface.c b/nfapi/open-nFAPI/pnf/src/pnf_interface.c index a53604640c..78ea46bbf6 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_interface.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_interface.c @@ -135,8 +135,8 @@ int nfapi_nr_pnf_pnf_param_resp(nfapi_pnf_config_t* config, nfapi_nr_pnf_param_r } pnf_t* _this = (pnf_t*)(config); - - return pnf_nr_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_nr_pnf_param_response_t)); + AssertFatal(config->send_p5_msg, "Function pointer must be configured!"); + return config->send_p5_msg(_this, &(resp->header), sizeof(nfapi_nr_pnf_param_response_t)); } int nfapi_pnf_pnf_param_resp(nfapi_pnf_config_t* config, nfapi_pnf_param_response_t* resp) @@ -188,8 +188,8 @@ int nfapi_nr_pnf_pnf_config_resp(nfapi_pnf_config_t* config, nfapi_nr_pnf_config } pnf_t* _this = (pnf_t*)(config); - - return pnf_nr_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_nr_pnf_config_response_t)); + AssertFatal(config->send_p5_msg, "Function pointer must be configured|"); + return config->send_p5_msg(_this, &(resp->header), sizeof(nfapi_nr_pnf_config_response_t)); } @@ -227,8 +227,8 @@ int nfapi_nr_pnf_pnf_start_resp(nfapi_pnf_config_t* config, nfapi_nr_pnf_start_r } pnf_t* _this = (pnf_t*)(config); - - return pnf_nr_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_nr_pnf_start_response_t)); + AssertFatal(config->send_p5_msg, "Function pointer must be configured|"); + return config->send_p5_msg(_this, &(resp->header), sizeof(nfapi_nr_pnf_start_response_t)); } @@ -273,8 +273,8 @@ int nfapi_nr_pnf_param_resp(nfapi_pnf_config_t* config, nfapi_nr_param_response_ } pnf_t* _this = (pnf_t*)(config); - - return pnf_nr_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_nr_param_response_scf_t)); + AssertFatal(config->send_p5_msg, "Function pointer must be configured|"); + return config->send_p5_msg(_this, &(resp->header), sizeof(nfapi_nr_param_response_scf_t)); } int nfapi_pnf_config_resp(nfapi_pnf_config_t* config, nfapi_config_response_t* resp) @@ -329,8 +329,8 @@ int nfapi_nr_pnf_config_resp(nfapi_pnf_config_t* config, nfapi_nr_config_respons NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: unknow phy id %d\n", __FUNCTION__, resp->header.phy_id); return -1; } - - return pnf_nr_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_nr_config_response_scf_t)); + AssertFatal(config->send_p5_msg, "Function pointer must be configured|"); + return config->send_p5_msg(_this, &(resp->header), sizeof(nfapi_nr_config_response_scf_t)); } @@ -384,8 +384,8 @@ int nfapi_nr_pnf_start_resp(nfapi_pnf_config_t* config, nfapi_nr_start_response_ NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: unknown phy id %d\n", __FUNCTION__, resp->header.phy_id); return -1; } - - return pnf_nr_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_nr_start_response_scf_t)); + AssertFatal(config->send_p5_msg, "Function pointer must be configured|"); + return config->send_p5_msg(_this, &(resp->header), sizeof(nfapi_nr_start_response_scf_t)); } diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7.c b/nfapi/open-nFAPI/pnf/src/pnf_p7.c index 2235a7c153..95fff37bc9 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7.c @@ -569,14 +569,14 @@ int pnf_p7_pack_and_send_p7_message(pnf_p7_t* pnf_p7, nfapi_p7_message_header_t* return 0; } -int pnf_nr_p7_pack_and_send_p7_message(pnf_p7_t* pnf_p7, nfapi_nr_p7_message_header_t* header, uint32_t msg_len) +bool pnf_nr_send_p7_message(pnf_p7_t* pnf_p7, nfapi_nr_p7_message_header_t* header, uint32_t msg_len) { header->m_segment_sequence = NFAPI_P7_SET_MSS(0, 0, pnf_p7->sequence_number); // Need to guard against different threads calling the encode function at the same time if (pthread_mutex_lock(&(pnf_p7->pack_mutex)) != 0) { NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to lock mutex\n"); - return -1; + return false; } uint8_t tx_buf[131072]; // four times NFAPI_MAX_PACKED_MESSAGE_SIZE as of this commit @@ -585,11 +585,11 @@ int pnf_nr_p7_pack_and_send_p7_message(pnf_p7_t* pnf_p7, nfapi_nr_p7_message_hea if (len < 0) { if (pthread_mutex_unlock(&(pnf_p7->pack_mutex)) != 0) { NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to unlock mutex\n"); - return -1; + return false; } NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi_p7_message_pack failed with return %d\n", len); - return -1; + return false; } if (len > pnf_p7->_public.segment_size) { @@ -644,10 +644,10 @@ int pnf_nr_p7_pack_and_send_p7_message(pnf_p7_t* pnf_p7, nfapi_nr_p7_message_hea if (pthread_mutex_unlock(&(pnf_p7->pack_mutex)) != 0) { NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to unlock mutex\n"); - return -1; + return false; } - return 0; + return true; } void pnf_pack_and_send_timing_info(pnf_p7_t* pnf_p7) @@ -707,9 +707,8 @@ void pnf_nr_pack_and_send_timing_info(pnf_p7_t* pnf_p7) timing_info.tx_data_request_earliest_arrival = 0; timing_info.ul_tti_earliest_arrival = 0; timing_info.ul_dci_earliest_arrival = 0; - - - pnf_nr_p7_pack_and_send_p7_message(pnf_p7, &(timing_info.header), sizeof(timing_info)); + AssertFatal(pnf_p7->_public.send_p7_msg, "The function pointer to pack and send P7 messages must be set"); + pnf_p7->_public.send_p7_msg(pnf_p7, &(timing_info.header), sizeof(timing_info)); pnf_p7->timing_info_ms_counter = 0; } @@ -2097,8 +2096,8 @@ void pnf_nr_handle_dl_node_sync(void *pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7 NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to unlock mutex\n"); return; } - - pnf_nr_p7_pack_and_send_p7_message(pnf_p7, &(ul_node_sync.header), sizeof(ul_node_sync)); + AssertFatal(pnf_p7->_public.send_p7_msg, "Function pointer must be configured|"); + pnf_p7->_public.send_p7_msg(pnf_p7, &(ul_node_sync.header), sizeof(ul_node_sync)); //printf("\nSSent UL Node Sync sfn:%d,slot:%d\n",pnf_p7->sfn,pnf_p7->slot); } diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c b/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c index 6e5569d972..06d268a875 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c @@ -260,7 +260,8 @@ int nfapi_pnf_p7_nr_slot_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_slot_indica } pnf_p7_t* _this = (pnf_p7_t*)(config); - return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_nr_p7_message_header_t*)ind, sizeof(nfapi_nr_slot_indication_scf_t)); + AssertFatal(_this->_public.send_p7_msg, "Function pointer must be configured|"); + return _this->_public.send_p7_msg(_this, (nfapi_nr_p7_message_header_t*)ind, sizeof(nfapi_nr_slot_indication_scf_t)); } int nfapi_pnf_p7_nr_rx_data_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_rx_data_indication_t* ind) @@ -272,8 +273,8 @@ int nfapi_pnf_p7_nr_rx_data_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_rx_data_ } pnf_p7_t* _this = (pnf_p7_t*)(config); - - int ret = pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_nr_p7_message_header_t*)ind, sizeof(nfapi_nr_rx_data_indication_t)); + AssertFatal(_this->_public.send_p7_msg, "Function pointer must be configured|"); + int ret = _this->_public.send_p7_msg(_this, (nfapi_nr_p7_message_header_t*)ind, sizeof(nfapi_nr_rx_data_indication_t)); if (ret == 0) { for (int i = 0; i < ind->number_of_pdus; ++i) _this->nr_stats.ul.bytes += ind->pdu_list[i].pdu_length; @@ -290,7 +291,8 @@ int nfapi_pnf_p7_nr_crc_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_crc_indicati } pnf_p7_t* _this = (pnf_p7_t*)(config); - return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_nr_p7_message_header_t*)ind, sizeof(nfapi_nr_crc_indication_t)); + AssertFatal(_this->_public.send_p7_msg, "Function pointer must be configured|"); + return _this->_public.send_p7_msg(_this, (nfapi_nr_p7_message_header_t*)ind, sizeof(nfapi_nr_crc_indication_t)); } int nfapi_pnf_p7_nr_srs_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_srs_indication_t* ind) @@ -302,7 +304,8 @@ int nfapi_pnf_p7_nr_srs_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_srs_indicati } pnf_p7_t* _this = (pnf_p7_t*)(config); - return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_nr_p7_message_header_t*)ind, sizeof(nfapi_nr_srs_indication_t)); + AssertFatal(_this->_public.send_p7_msg, "Function pointer must be configured|"); + return _this->_public.send_p7_msg(_this, (nfapi_nr_p7_message_header_t*)ind, sizeof(nfapi_nr_srs_indication_t)); } int nfapi_pnf_p7_nr_uci_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_uci_indication_t* ind) @@ -314,7 +317,8 @@ int nfapi_pnf_p7_nr_uci_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_uci_indicati } pnf_p7_t* _this = (pnf_p7_t*)(config); - return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_nr_p7_message_header_t*)ind, sizeof(nfapi_nr_uci_indication_t)); + AssertFatal(_this->_public.send_p7_msg, "Function pointer must be configured|"); + return _this->_public.send_p7_msg(_this, (nfapi_nr_p7_message_header_t*)ind, sizeof(nfapi_nr_uci_indication_t)); } int nfapi_pnf_p7_nr_rach_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_rach_indication_t* ind) @@ -326,5 +330,6 @@ int nfapi_pnf_p7_nr_rach_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_rach_indica } pnf_p7_t* _this = (pnf_p7_t*)(config); - return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_nr_p7_message_header_t*)ind, sizeof(nfapi_nr_rach_indication_t)); + AssertFatal(_this->_public.send_p7_msg, "Function pointer must be configured|"); + return _this->_public.send_p7_msg(_this, (nfapi_nr_p7_message_header_t*)ind, sizeof(nfapi_nr_rach_indication_t)); } From ca940e62f9607fce664e97d2c78dab9a31a81f41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Soares=20Silva?= Date: Mon, 10 Feb 2025 21:57:12 +0000 Subject: [PATCH 093/964] Add default PNF timing_info value for when the TLV is not sent Intended to allow FAPI PNF to work without this nFAPI TLV being sent --- nfapi/oai_integration/nfapi_pnf.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/nfapi/oai_integration/nfapi_pnf.c b/nfapi/oai_integration/nfapi_pnf.c index f1010bde1a..e17690da2d 100644 --- a/nfapi/oai_integration/nfapi_pnf.c +++ b/nfapi/oai_integration/nfapi_pnf.c @@ -992,6 +992,10 @@ int nr_config_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, n phy_info->timing_window, req->nfapi_config.timing_window.value); num_tlv++; + }else { + // This is a nFAPI TLV, thus not sent when working with FAPI. + // When not sent, we still need a default value, otherwise every message from the L2 is treated as late and not processed + phy_info->timing_window = 30; } if (req->nfapi_config.timing_info_mode.tl.tag == NFAPI_NR_NFAPI_TIMING_INFO_MODE_TAG) { From f986f6843a519db394bbbbff45557f7e8596004f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Soares=20Silva?= Date: Fri, 21 Feb 2025 16:23:57 +0000 Subject: [PATCH 094/964] Fix non-SCTP socket communication for P5 messages between PNF and VNF. Switches the used socket type in pnf_interface.c and vnf_interface.c. These values must always be the same in both components so the same socket type is used in both --- nfapi/open-nFAPI/pnf/src/pnf.c | 57 +++++++--- nfapi/open-nFAPI/vnf/src/vnf.c | 128 +++++++++++++++-------- nfapi/open-nFAPI/vnf/src/vnf_interface.c | 9 ++ 3 files changed, 140 insertions(+), 54 deletions(-) diff --git a/nfapi/open-nFAPI/pnf/src/pnf.c b/nfapi/open-nFAPI/pnf/src/pnf.c index 7ed881f7e3..e6fb69bd71 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf.c +++ b/nfapi/open-nFAPI/pnf/src/pnf.c @@ -1935,7 +1935,20 @@ int pnf_connect(pnf_t* pnf) socketConnected = 1; } - } + } else { + int error; + socklen_t len = sizeof(error); + + if (getsockopt(pnf->p5_sock, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After getsockopt errno: %d\n", errno); + return -1; + } else { + // If error is zero, the socket is connected + if (error == 0) { + socketConnected = 1; + } + } + } NFAPI_TRACE(NFAPI_TRACE_NOTE, "Socket %s\n", socketConnected ? "CONNECTED" : "NOT_CONNECTED"); return socketConnected; @@ -2132,15 +2145,23 @@ int pnf_nr_read_dispatch_message(pnf_t* pnf) { int flags = MSG_PEEK; - message_size = sctp_recvmsg(pnf->p5_sock, - header_buffer, - header_buffer_size, - /*(struct sockaddr*)&addr, &addr_len*/ 0, - 0, - &sndrcvinfo, - &flags); + if (pnf->sctp) { + message_size = sctp_recvmsg(pnf->p5_sock, + header_buffer, + header_buffer_size, + /*(struct sockaddr*)&addr, &addr_len*/ + 0, + 0, + &sndrcvinfo, + &flags); + } else { + message_size = recv(pnf->p5_sock, + header_buffer, + header_buffer_size, + flags); + } - if (message_size == -1) { + if (message_size < NFAPI_NR_P5_HEADER_LENGTH) { NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF Failed to peek sctp message size errno:%d\n", errno); return 0; } @@ -2172,8 +2193,20 @@ int pnf_nr_read_dispatch_message(pnf_t* pnf) int flags = 0; (void)memset(&sndrcvinfo, 0, sizeof(struct sctp_sndrcvinfo)); - int recvmsg_result = - sctp_recvmsg(pnf->p5_sock, read_buffer, message_size, (struct sockaddr*)&addr, &addr_len, &sndrcvinfo, &flags); + ssize_t recvmsg_result = 0; + if (pnf->sctp) { + recvmsg_result = sctp_recvmsg(pnf->p5_sock, + read_buffer, + message_size, + (struct sockaddr *)&addr, + &addr_len, + &sndrcvinfo, + &flags); + } else { + if ((recvmsg_result = recv(pnf->p5_sock, read_buffer, message_size, flags))<=0) { + recvmsg_result = -1; + } + } if (recvmsg_result == -1) { NFAPI_TRACE(NFAPI_TRACE_INFO, "Failed to read sctp message size errno:%d\n", errno); } else { @@ -2204,7 +2237,7 @@ int pnf_nr_read_dispatch_message(pnf_t* pnf) */ // handle now if complete message in one or more segments - if ((flags & 0x80) == 0x80) { + if ((flags & 0x80) == 0x80 || !pnf->sctp) { pnf_nr_handle_p5_message(pnf, read_buffer, message_size); } else { NFAPI_TRACE(NFAPI_TRACE_WARN, "sctp_recvmsg: unhandled mode with flags 0x%x\n", flags); diff --git a/nfapi/open-nFAPI/vnf/src/vnf.c b/nfapi/open-nFAPI/vnf/src/vnf.c index baac137512..757a4e7d68 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf.c +++ b/nfapi/open-nFAPI/vnf/src/vnf.c @@ -32,6 +32,9 @@ #include "nfapi/oai_integration/aerial/fapi_vnf_p5.h" #include "nr_fapi_p5.h" #endif + +#include + #include "nfapi/oai_integration/vendor_ext.h" void* vnf_malloc(nfapi_vnf_config_t* config, size_t size) @@ -434,22 +437,22 @@ void vnf_nr_handle_param_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_conf const bool result = config->unpack_func(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config); if (result) { - + if (msg.error_code == NFAPI_NR_PARAM_MSG_OK) { nfapi_vnf_phy_info_t* phy_info = nfapi_vnf_phy_info_list_find(config, msg.header.phy_id); - + if(msg.nfapi_config.p7_pnf_address_ipv4.tl.tag) { struct sockaddr_in sockAddr; - + (void)memcpy(&sockAddr.sin_addr.s_addr, msg.nfapi_config.p7_pnf_address_ipv4.address, NFAPI_IPV4_ADDRESS_LENGTH); NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF P7 IPv4 address: %s\n", inet_ntoa(sockAddr.sin_addr)); - + // store address phy_info->p7_pnf_address.sin_addr = sockAddr.sin_addr; } - + if(msg.nfapi_config.p7_pnf_address_ipv6.tl.tag) { struct sockaddr_in6 sockAddr6; @@ -457,11 +460,11 @@ void vnf_nr_handle_param_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_conf (void)memcpy(&sockAddr6.sin6_addr, msg.nfapi_config.p7_pnf_address_ipv6.address, NFAPI_IPV6_ADDRESS_LENGTH); NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF P7 IPv6 address: %s\n", inet_ntop(AF_INET6, &sockAddr6.sin6_addr, addr6, sizeof(addr6))); } - + if (msg.nfapi_config.p7_pnf_port.tl.tag) { NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF P7 Port: %d\n", msg.nfapi_config.p7_pnf_port.value); - + // store port phy_info->p7_pnf_address.sin_port = htons(msg.nfapi_config.p7_pnf_port.value); } @@ -1268,7 +1271,7 @@ int vnf_nr_read_dispatch_message(nfapi_vnf_config_t* config, nfapi_vnf_pnf_info_ { if (1) { int socket_connected = 1; - + vnf_t *vnf = (vnf_t *)(config); // 1. Peek the message header // 2. If the message is larger than the stack buffer then create a dynamic buffer // 3. Read the buffer @@ -1293,8 +1296,21 @@ int vnf_nr_read_dispatch_message(nfapi_vnf_config_t* config, nfapi_vnf_pnf_info_ { int flags = MSG_PEEK; - message_size = - sctp_recvmsg(pnf->p5_sock, header_buffer, header_buffer_size, (struct sockaddr*)&addr, &addr_len, &sndrcvinfo, &flags); + if (vnf->sctp) { + message_size = + sctp_recvmsg(pnf->p5_sock, + header_buffer, + header_buffer_size, + (struct sockaddr *)&addr, + &addr_len, + &sndrcvinfo, + &flags); + } else { + message_size = recv(pnf->p5_sock, + header_buffer, + header_buffer_size, + flags); + } if (message_size == -1) { NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Failed to peek sctp message size errno:%d\n", errno); @@ -1328,8 +1344,22 @@ int vnf_nr_read_dispatch_message(nfapi_vnf_config_t* config, nfapi_vnf_pnf_info_ int flags = 0; (void)memset(&sndrcvinfo, 0, sizeof(struct sctp_sndrcvinfo)); - int recvmsg_result = - sctp_recvmsg(pnf->p5_sock, read_buffer, message_size, (struct sockaddr*)&addr, &addr_len, &sndrcvinfo, &flags); + ssize_t recvmsg_result = 0; + if (vnf->sctp) { + recvmsg_result = sctp_recvmsg(pnf->p5_sock, + read_buffer, + message_size, + (struct sockaddr *)&addr, + &addr_len, + &sndrcvinfo, + &flags); + } else { + recvmsg_result = recv(pnf->p5_sock, + read_buffer, + message_size, + 0); + } + if (recvmsg_result == -1) { NFAPI_TRACE(NFAPI_TRACE_INFO, "Failed to read sctp message size errno:%d\n", errno); } else { @@ -1338,34 +1368,34 @@ int vnf_nr_read_dispatch_message(nfapi_vnf_config_t* config, nfapi_vnf_pnf_info_ // todo - handle the events } else { - /* - NFAPI_TRACE(NFAPI_TRACE_INFO, "Received message fd:%d from %s:%u assoc:%d on stream %d, PPID %d, length %d, flags 0x%x\n", - pnf->p5_sock, - inet_ntoa(addr.sin_addr), - ntohs(addr.sin_port), - sndrcvinfo.sinfo_assoc_id, - sndrcvinfo.sinfo_stream, - ntohl(sndrcvinfo.sinfo_ppid), - message_size, - flags); - */ + /* + NFAPI_TRACE(NFAPI_TRACE_INFO, "Received message fd:%d from %s:%u assoc:%d on stream %d, PPID %d, length %d, flags 0x%x\n", + pnf->p5_sock, + inet_ntoa(addr.sin_addr), + ntohs(addr.sin_port), + sndrcvinfo.sinfo_assoc_id, + sndrcvinfo.sinfo_stream, + ntohl(sndrcvinfo.sinfo_ppid), + message_size, + flags); + */ - // handle now if complete message in one or more segments - if ((flags & 0x80) == 0x80) { - // printf("\nVNF RECEIVES:\n"); - // for(int i=0; isctp) { + // printf("\nVNF RECEIVES:\n"); + // for(int i=0; ip5_idx, config); - } else { - NFAPI_TRACE(NFAPI_TRACE_WARN, "sctp_recvmsg: unhandled mode with flags 0x%x\n", flags); + vnf_nr_handle_p4_p5_message(read_buffer, message_size, pnf->p5_idx, config); + } else { + NFAPI_TRACE(NFAPI_TRACE_WARN, "sctp_recvmsg: unhandled mode with flags 0x%x\n", flags); - // assume socket disconnected - NFAPI_TRACE(NFAPI_TRACE_WARN, "Disconnected socket\n"); - socket_connected = 0; - } + // assume socket disconnected + NFAPI_TRACE(NFAPI_TRACE_WARN, "Disconnected socket\n"); + socket_connected = 0; + } } } } @@ -1509,7 +1539,7 @@ int vnf_read_dispatch_message(nfapi_vnf_config_t* config, nfapi_vnf_pnf_info_t* } } -static int vnf_send_p5_msg(nfapi_vnf_pnf_info_t* pnf, const void *msg, int len, uint8_t stream) +static int vnf_send_p5_msg(vnf_t *vnf, nfapi_vnf_pnf_info_t *pnf, const void *msg, int len, uint8_t stream) { // printf("\n MESSAGE SENT: \n"); // for(int i=0; ip5_sock, msg, len, (struct sockaddr*)&pnf->p5_pnf_sockaddr, sizeof(pnf->p5_pnf_sockaddr),1, 0, stream, 0, 4); + ssize_t result = -1; + if (vnf->sctp) { + result = sctp_sendmsg(pnf->p5_sock, + msg, + len, + (struct sockaddr *)&pnf->p5_pnf_sockaddr, + sizeof(pnf->p5_pnf_sockaddr), + 1, + 0, + stream, + 0, + 4); + } else { + result = send(pnf->p5_sock, msg, len,0); + } if(result != len) { @@ -1574,7 +1618,7 @@ bool vnf_nr_send_p5_message(vnf_t* vnf, uint16_t p5_idx, nfapi_nr_p4_p5_message_ // printf(" msg->msg_buf[%d] = 0x%02x\n", i, ((uint8_t *) vnf->tx_message_buffer)[i]); // } - return vnf_send_p5_msg(pnf, vnf->tx_message_buffer, packedMessageLength, 0); + return vnf_send_p5_msg(vnf, pnf, vnf->tx_message_buffer, packedMessageLength, 0); } } else { NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() cannot find pnf info for p5_idx:%d\n", __FUNCTION__, p5_idx); @@ -1599,7 +1643,7 @@ int vnf_pack_and_send_p5_message(vnf_t* vnf, uint16_t p5_idx, nfapi_p4_p5_messag return -1; } - return vnf_send_p5_msg(pnf, vnf->tx_message_buffer, packedMessageLength, 0/*msg->phy_id*/); + return vnf_send_p5_msg(vnf, pnf, vnf->tx_message_buffer, packedMessageLength, 0/*msg->phy_id*/); } else { @@ -1624,7 +1668,7 @@ int vnf_pack_and_send_p4_message(vnf_t* vnf, uint16_t p5_idx, nfapi_p4_p5_messag return -1; } - return vnf_send_p5_msg(pnf, vnf->tx_message_buffer, packedMessageLength, 0/*msg->phy_id*/); + return vnf_send_p5_msg(vnf, pnf, vnf->tx_message_buffer, packedMessageLength, 0/*msg->phy_id*/); } else { diff --git a/nfapi/open-nFAPI/vnf/src/vnf_interface.c b/nfapi/open-nFAPI/vnf/src/vnf_interface.c index d964e5b9dc..9eccb45acb 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_interface.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_interface.c @@ -237,7 +237,15 @@ int nfapi_nr_vnf_start(nfapi_vnf_config_t* config) close(p5ListenSock); return -1; } + } else { + int error; + socklen_t len = sizeof(error); + if (getsockopt(p5ListenSock, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After getsockopt errno: %d\n", errno); + close(p5ListenSock); + return -1; + } } @@ -359,6 +367,7 @@ int nfapi_nr_vnf_start(nfapi_vnf_config_t* config) // check the connection status + if (vnf->sctp) { struct sctp_status status; (void)memset(&status, 0, sizeof(struct sctp_status)); From 35d0314be5a5a2714351ac94e97e2c3ea9ece660 Mon Sep 17 00:00:00 2001 From: alexjiao Date: Fri, 27 Jun 2025 10:45:51 +0800 Subject: [PATCH 095/964] NR UE: enable CSI report for SISO case Correct precoded_sinr_dB wrongly set to 0 for SISO case. Also correct ri_restriction is 0 when calculating CQI bit length for SISO. --- openair1/PHY/NR_UE_TRANSPORT/csi_rx.c | 28 ++++++++++++++++++- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 2 +- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c b/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c index 33ba3e0829..764fbbabc6 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c +++ b/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c @@ -592,7 +592,33 @@ int nr_csi_rs_pmi_estimation(const PHY_VARS_NR_UE *ue, // The first column is applicable if the UE is reporting a Rank = 1, whereas the second column is applicable if the // UE is reporting a Rank = 2. - if(N_ports == 1 || interference_plus_noise_power == 0) { + if (interference_plus_noise_power == 0) { + return 0; + } + + if (N_ports == 1) { + // SISO case: SINR = E[|h|^2] / noise_power. No PMI to estimate. + int64_t signal_power = 0; + int count = 0; + + for (int rb = csirs_config_pdu->start_rb; rb < (csirs_config_pdu->start_rb + csirs_config_pdu->nr_of_rbs); rb++) { + if (csirs_config_pdu->freq_density <= 1 && csirs_config_pdu->freq_density != (rb % 2)) { + continue; + } + uint16_t k = (frame_parms->first_carrier_offset + rb * NR_NB_SC_PER_RB) % frame_parms->ofdm_symbol_size; + uint16_t k_offset = k + mem_offset; + + const c16_t h = csi_rs_estimated_channel_freq[0][0][k_offset]; + signal_power += (int64_t)h.r * h.r + (int64_t)h.i * h.i; + count++; + } + + if (count > 0) { + const int64_t avg_signal_power = signal_power / count; + const uint32_t sinr = avg_signal_power / interference_plus_noise_power; + *precoded_sinr_dB = dB_fixed(sinr); + } + return 0; } diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index b435e9e265..cd51f6a48f 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -4480,7 +4480,7 @@ static uint8_t compute_ri_bitlen(const NR_CSI_ReportConfig_t *csi_reportconfig, if (codebookConfig == NULL) { csi_report->csi_meas_bitlen.ri_bitlen = 0; - return 0; + return 1; } struct NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel *type1single = NULL; From bfaec58ca50e770c2c3bc0b780bbcd30e8459db7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Soares=20Silva?= Date: Mon, 17 Mar 2025 12:58:40 +0000 Subject: [PATCH 096/964] Separate PNF socket send functions into separate socket library --- CMakeLists.txt | 4 + nfapi/CMakeLists.txt | 1 + nfapi/oai_integration/nfapi_pnf.c | 39 +- nfapi/oai_integration/socket/CMakeLists.txt | 13 + .../socket/include/socket_common.h | 39 + .../socket/include/socket_pnf.h | 39 + nfapi/oai_integration/socket/socket_common.c | 58 ++ nfapi/oai_integration/socket/socket_pnf.c | 867 ++++++++++++++++++ nfapi/open-nFAPI/fapi/CMakeLists.txt | 2 + .../nfapi/public_inc/nfapi_interface.h | 3 +- nfapi/open-nFAPI/nfapi/src/nfapi_p7.c | 3 + nfapi/open-nFAPI/pnf/inc/pnf.h | 3 +- nfapi/open-nFAPI/pnf/inc/pnf_p7.h | 8 +- .../pnf/public_inc/nfapi_pnf_interface.h | 3 +- nfapi/open-nFAPI/pnf/src/pnf.c | 263 +----- nfapi/open-nFAPI/pnf/src/pnf_interface.c | 30 - nfapi/open-nFAPI/pnf/src/pnf_p7.c | 448 +-------- nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c | 13 - 18 files changed, 1089 insertions(+), 747 deletions(-) create mode 100644 nfapi/oai_integration/socket/CMakeLists.txt create mode 100644 nfapi/oai_integration/socket/include/socket_common.h create mode 100644 nfapi/oai_integration/socket/include/socket_pnf.h create mode 100644 nfapi/oai_integration/socket/socket_common.c create mode 100644 nfapi/oai_integration/socket/socket_pnf.c diff --git a/CMakeLists.txt b/CMakeLists.txt index cc30b7a5bd..4dc8c9ce7a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -715,6 +715,7 @@ add_library(NFAPI_LIB ${NFAPI_SRC}) target_link_libraries(NFAPI_LIB PUBLIC nfapi_common) target_link_libraries(NFAPI_LIB PUBLIC nr_fapi_p5 nr_fapi_p7) +target_compile_definitions(NFAPI_LIB PRIVATE ENABLE_SOCKET) include_directories(${NFAPI_DIR}/nfapi/public_inc) include_directories(${NFAPI_DIR}/nfapi/inc) @@ -755,6 +756,7 @@ set(NFAPI_USER_SRC ${NFAPI_USER_DIR}/gnb_ind_vars.c ) add_library(NFAPI_USER_LIB ${NFAPI_USER_SRC}) +target_compile_definitions(NFAPI_USER_LIB PRIVATE ENABLE_SOCKET) target_link_libraries(NFAPI_USER_LIB PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs UTIL) target_link_libraries(NFAPI_USER_LIB PRIVATE nr_fapi_p7) if(OAI_AERIAL) @@ -1839,6 +1841,8 @@ target_link_libraries(nr-softmodem PRIVATE pthread m CONFIG_LIB rt sctp) target_link_libraries(nr-softmodem PRIVATE ${T_LIB}) target_link_libraries(nr-softmodem PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) target_link_libraries(nr-softmodem PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) + +target_link_libraries(nr-softmodem PUBLIC nfapi_socket_lib) add_boolean_option(OAI_AERIAL OFF "Activate OAI's AERIAL driver" OFF) if (OAI_AERIAL) target_compile_definitions(nr-softmodem PUBLIC ENABLE_AERIAL) diff --git a/nfapi/CMakeLists.txt b/nfapi/CMakeLists.txt index d6c5b0e92a..e79905b07c 100644 --- a/nfapi/CMakeLists.txt +++ b/nfapi/CMakeLists.txt @@ -1,3 +1,4 @@ add_subdirectory(oai_integration/aerial) +add_subdirectory(oai_integration/socket) add_subdirectory(open-nFAPI) add_subdirectory(tests) diff --git a/nfapi/oai_integration/nfapi_pnf.c b/nfapi/oai_integration/nfapi_pnf.c index e17690da2d..88b82ad480 100644 --- a/nfapi/oai_integration/nfapi_pnf.c +++ b/nfapi/oai_integration/nfapi_pnf.c @@ -63,6 +63,10 @@ #include "executables/lte-softmodem.h" #include "nfapi/open-nFAPI/pnf/inc/pnf_p7.h" +#ifdef ENABLE_SOCKET +#include +#endif + #define NUM_P5_PHY 2 #define _GNU_SOURCE @@ -186,7 +190,7 @@ typedef struct { } pnf_phy_user_data_t; static pnf_info pnf; -static pthread_t pnf_start_pthread; +static pthread_t pnf_p5_init_and_receive_pthread; int nfapitooai_level(int nfapi_level) { switch(nfapi_level) { @@ -220,12 +224,7 @@ void *pnf_p7_thread_start(void *ptr) { return 0; } -void *pnf_nr_p7_thread_start(void *ptr) { - NFAPI_TRACE(NFAPI_TRACE_INFO, "[NR_PNF] NR P7 THREAD %s\n", __FUNCTION__); - nfapi_pnf_p7_config_t *config = (nfapi_pnf_p7_config_t *)ptr; - nfapi_nr_pnf_p7_start(config); - return 0; -} + int pnf_nr_param_request(nfapi_pnf_config_t *config, nfapi_nr_pnf_param_request_t *req) { @@ -1752,6 +1751,8 @@ int nr_start_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nf p7_config->codec_config.pack_p7_vendor_extension = &pnf_nr_phy_pack_p7_vendor_extension; p7_config->codec_config.unpack_vendor_extension_tlv = &pnf_nr_phy_unpack_vendor_extension_tlv; p7_config->codec_config.pack_vendor_extension_tlv = &pnf_nr_phy_pack_vendor_extention_tlv; + +#ifdef ENABLE_SOCKET p7_config->unpack_func = &nfapi_nr_p7_message_unpack; p7_config->hdr_unpack_func = &nfapi_nr_p7_message_header_unpack; p7_config->pack_func = &nfapi_nr_p7_message_pack; @@ -1759,6 +1760,8 @@ int nr_start_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nf NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] Creating P7 thread %s\n", __FUNCTION__); pthread_t p7_thread; threadCreate(&p7_thread, &pnf_nr_p7_thread_start, p7_config, "pnf_p7_thread", -1, OAI_PRIORITY_RT); +#endif + NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] Calling l1_north_init_eNB() %s\n", __FUNCTION__); l1_north_init_gNB(); NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] HACK - Set p7_config global ready for subframe ind%s\n", __FUNCTION__); @@ -2141,15 +2144,6 @@ void *pnf_start_thread(void *ptr) { return (void *)0; } -void *pnf_nr_start_thread(void *ptr) { - NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] IN PNF NFAPI start thread %s\n", __FUNCTION__); - nfapi_pnf_config_t *config = (nfapi_pnf_config_t *)ptr; - struct sched_param sp; - sp.sched_priority = 20; - pthread_setschedparam(pthread_self(),SCHED_FIFO,&sp); - nfapi_nr_pnf_start(config); - return (void *)0; -} void configure_nr_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port) { @@ -2197,13 +2191,18 @@ void configure_nr_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_add config->deallocate_p4_p5_vendor_ext = &pnf_nr_sim_deallocate_p4_p5_vendor_ext; config->codec_config.unpack_p4_p5_vendor_extension = &pnf_nr_sim_unpack_p4_p5_vendor_extension; config->codec_config.pack_p4_p5_vendor_extension = &pnf_nr_sim_pack_p4_p5_vendor_extension; + + +#ifdef ENABLE_SOCKET + NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] Creating PNF NFAPI start thread %s\n", __FUNCTION__); config->unpack_func = &nfapi_nr_p5_message_unpack; config->hdr_unpack_func = &nfapi_nr_p5_message_header_unpack; config->pack_func = &nfapi_nr_p5_message_pack; config->send_p5_msg = &pnf_nr_send_p5_message; NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] Creating PNF NFAPI start thread %s\n", __FUNCTION__); - pthread_create(&pnf_start_pthread, NULL, &pnf_nr_start_thread, config); - pthread_setname_np(pnf_start_pthread, "NFAPI_PNF"); + pthread_create(&pnf_p5_init_and_receive_pthread, NULL, &pnf_start_p5_thread, config); + pthread_setname_np(pnf_p5_init_and_receive_pthread, "NFAPI_PNF"); +#endif } void configure_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port) { @@ -2253,8 +2252,8 @@ void configure_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr, config->codec_config.unpack_p4_p5_vendor_extension = &pnf_sim_unpack_p4_p5_vendor_extension; config->codec_config.pack_p4_p5_vendor_extension = &pnf_sim_pack_p4_p5_vendor_extension; NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] Creating PNF NFAPI start thread %s\n", __FUNCTION__); - pthread_create(&pnf_start_pthread, NULL, &pnf_start_thread, config); - pthread_setname_np(pnf_start_pthread, "NFAPI_PNF"); + pthread_create(&pnf_p5_init_and_receive_pthread, NULL, &pnf_start_thread, config); + pthread_setname_np(pnf_p5_init_and_receive_pthread, "NFAPI_PNF"); } void oai_subframe_ind(uint16_t sfn, uint16_t sf) { diff --git a/nfapi/oai_integration/socket/CMakeLists.txt b/nfapi/oai_integration/socket/CMakeLists.txt new file mode 100644 index 0000000000..edf5457cea --- /dev/null +++ b/nfapi/oai_integration/socket/CMakeLists.txt @@ -0,0 +1,13 @@ +add_library(nfapi_socket_lib + socket_pnf.c + socket_common.c +) + +target_include_directories(nfapi_socket_lib PRIVATE include/) + +target_compile_definitions(nfapi_socket_lib PUBLIC ENABLE_SOCKET) +target_link_libraries(nfapi_socket_lib PRIVATE NFAPI_LIB NFAPI_USER_LIB) +target_link_libraries(nfapi_socket_lib PRIVATE LOG) +add_dependencies(nfapi_socket_lib generate_T) +target_link_libraries(nfapi_socket_lib PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs) +target_link_libraries(nfapi_socket_lib PRIVATE nr_fapi_p5 nr_fapi_p7) diff --git a/nfapi/oai_integration/socket/include/socket_common.h b/nfapi/oai_integration/socket/include/socket_common.h new file mode 100644 index 0000000000..2456740ec4 --- /dev/null +++ b/nfapi/oai_integration/socket/include/socket_common.h @@ -0,0 +1,39 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ +#ifndef SOCKET_COMMON_H +#define SOCKET_COMMON_H + +#include +#include +#include +#include +#include +#include + +int socket_send_p5_msg(const int sctp, + const int socket, + const void* remote_addr, + const void* msg, + const uint32_t len, + const uint16_t stream); +int socket_send_p7_msg(const int socket, const void* remote_addr, const void* msg, const uint32_t len); + +#endif // SOCKET_COMMON_H diff --git a/nfapi/oai_integration/socket/include/socket_pnf.h b/nfapi/oai_integration/socket/include/socket_pnf.h new file mode 100644 index 0000000000..ccb3eaea3a --- /dev/null +++ b/nfapi/oai_integration/socket/include/socket_pnf.h @@ -0,0 +1,39 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef SOCKET_PNF_H +#define SOCKET_PNF_H +#include "socket_common.h" +#include +#include +#include +#include "pnf.h" +#include "pnf_p7.h" +#include "nr_fapi_p5.h" +#include "nr_nfapi_p7.h" + +int pnf_connect_socket(pnf_t *pnf); +int pnf_nr_message_pump(pnf_t *pnf); +bool pnf_nr_send_p5_message(pnf_t *pnf, nfapi_nr_p4_p5_message_header_t *msg, uint32_t msg_len); +bool pnf_nr_send_p7_message(pnf_p7_t* pnf_p7, nfapi_nr_p7_message_header_t* header, uint32_t msg_len); +void *pnf_start_p5_thread(void *ptr); +void *pnf_nr_p7_thread_start(void *ptr); +#endif // SOCKET_PNF_H diff --git a/nfapi/oai_integration/socket/socket_common.c b/nfapi/oai_integration/socket/socket_common.c new file mode 100644 index 0000000000..5ec9a13ac6 --- /dev/null +++ b/nfapi/oai_integration/socket/socket_common.c @@ -0,0 +1,58 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ +#include "socket_common.h" +#include "LOG/log.h" + +int socket_send_p5_msg(const int sctp, + const int socket, + const void* remote_addr, + const void* msg, + const uint32_t len, + const uint16_t stream) +{ + if (sctp == 1) { + struct sockaddr* to = (struct sockaddr*)remote_addr; + const int retval = sctp_sendmsg(socket, msg, len, to, 0, 42, 0, stream, 0, 0); + if (retval < 0) { + LOG_E(NR_PHY, "sctp_sendmsg failed errno: %d\n", errno); + return -1; + } + } else { + if (send(socket, msg, len, 0) != len) { + LOG_E(NR_PHY, "write failed errno: %d\n", errno); + return -1; + } + } + + return len; +} + +int socket_send_p7_msg(const int socket, const void* remote_addr, const void* msg, const uint32_t len) +{ + const struct sockaddr* to = (struct sockaddr*)remote_addr; + const long sendto_result = sendto(socket, msg, len, 0, to, sizeof(struct sockaddr_in)); + if (sendto_result != len) { + LOG_E(NR_PHY, "%s() sendto_result %ld %d\n", __FUNCTION__, sendto_result, errno); + return -1; + } + + return 0; +} diff --git a/nfapi/oai_integration/socket/socket_pnf.c b/nfapi/oai_integration/socket/socket_pnf.c new file mode 100644 index 0000000000..fe4999c998 --- /dev/null +++ b/nfapi/oai_integration/socket/socket_pnf.c @@ -0,0 +1,867 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ +#include "socket_pnf.h" +#include "nfapi.h" + +bool pnf_nr_send_p5_message(pnf_t *pnf, nfapi_nr_p4_p5_message_header_t *msg, uint32_t msg_len) +{ + int packed_len = + pnf->_public.pack_func(msg, msg_len, pnf->tx_message_buffer, sizeof(pnf->tx_message_buffer), &pnf->_public.codec_config); + + if (packed_len < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "p5_message_pack failed (%d)\n", packed_len); + return false; + } + + return socket_send_p5_msg(pnf->sctp, pnf->p5_sock, NULL, pnf->tx_message_buffer, packed_len, 0) == packed_len; +} + +static int send_p7_msg(pnf_p7_t *pnf_p7, uint8_t *msg, uint32_t len) +{ + // todo : consider how to do this only once + struct sockaddr_in remote_addr = {.sin_family = AF_INET, .sin_port = htons(pnf_p7->_public.remote_p7_port)}; + + if (inet_aton(pnf_p7->_public.remote_p7_addr, &remote_addr.sin_addr) == -1) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "inet_aton failed %d\n", errno); + return -1; + } + + socklen_t remote_addr_len = sizeof(struct sockaddr_in); + + int sendto_result = socket_send_p7_msg((int)pnf_p7->p7_sock, &remote_addr, msg, len); + if (sendto_result < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, + "%s %s:%d sendto(%d, %p, %d) %d failed errno: %d\n", + __FUNCTION__, + pnf_p7->_public.remote_p7_addr, + pnf_p7->_public.remote_p7_port, + (int)pnf_p7->p7_sock, + (const char *)msg, + len, + remote_addr_len, + errno); + return -1; + } + + if (sendto_result != 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s sendto failed to send the entire message %d %d\n", __FUNCTION__, sendto_result, len); + } + return 0; +} + +bool pnf_nr_send_p7_message(pnf_p7_t *pnf_p7, nfapi_nr_p7_message_header_t *header, uint32_t msg_len) +{ + header->m_segment_sequence = NFAPI_NR_P7_SET_MSS(0, 0, pnf_p7->sequence_number); + + // Need to guard against different threads calling the encode function at the same time + if (pthread_mutex_lock(&(pnf_p7->pack_mutex)) != 0) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to lock mutex\n"); + return false; + } + + uint8_t tx_buf[131072]; // four times NFAPI_MAX_PACKED_MESSAGE_SIZE as of this commit + int len = pnf_p7->_public.pack_func(header, tx_buf, sizeof(tx_buf), &pnf_p7->_public.codec_config); + + if (len < 0) { + if (pthread_mutex_unlock(&(pnf_p7->pack_mutex)) != 0) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to unlock mutex\n"); + return false; + } + + NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi_p7_message_pack failed with return %d\n", len); + return false; + } + + if (len > pnf_p7->_public.segment_size) { + int msg_body_len = len - NFAPI_NR_P7_HEADER_LENGTH; + int seg_body_len = pnf_p7->_public.segment_size - NFAPI_NR_P7_HEADER_LENGTH; + int segment_count = (msg_body_len / (seg_body_len)) + ((msg_body_len % seg_body_len) ? 1 : 0); + + int segment = 0; + int offset = NFAPI_NR_P7_HEADER_LENGTH; + uint8_t buffer[pnf_p7->_public.segment_size]; + for (segment = 0; segment < segment_count; ++segment) { + uint8_t last = 0; + uint32_t size = pnf_p7->_public.segment_size - NFAPI_NR_P7_HEADER_LENGTH; + if (segment + 1 == segment_count) { + last = 1; + size = (msg_body_len) - (seg_body_len * segment); + } + + uint32_t segment_size = size + NFAPI_NR_P7_HEADER_LENGTH; + + // Update the header with the m and segement + memcpy(&buffer[0], tx_buf, NFAPI_NR_P7_HEADER_LENGTH); + + // set the segment length , update and push m_segment_sequence + uint8_t *buf_ptr = &buffer[4]; + uint8_t *buf_ptr_end = &buffer[10]; + push32(segment_size, (&buf_ptr), buf_ptr_end); + header->m_segment_sequence = NFAPI_NR_P7_SET_MSS((!last), segment, pnf_p7->sequence_number); + push16(header->m_segment_sequence, (&buf_ptr), buf_ptr_end); + memcpy(&buffer[NFAPI_NR_P7_HEADER_LENGTH], tx_buf + offset, size); + offset += size; + + if (pnf_p7->_public.checksum_enabled) { + nfapi_nr_p7_update_checksum(buffer, segment_size); + } + + send_p7_msg(pnf_p7, &buffer[0], segment_size); + } + } else { + if (pnf_p7->_public.checksum_enabled) { + nfapi_nr_p7_update_checksum(tx_buf, len); + } + + // simple case that the message fits in a single segment + send_p7_msg(pnf_p7, tx_buf, len); + } + + pnf_p7->sequence_number++; + + if (pthread_mutex_unlock(&(pnf_p7->pack_mutex)) != 0) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to unlock mutex\n"); + return false; + } + + return true; +} + +void *pnf_start_p5_thread(void *ptr) +{ + NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] IN PNF NFAPI start thread %s\n", __FUNCTION__); + nfapi_pnf_config_t *config = (nfapi_pnf_config_t *)ptr; + struct sched_param sp; + sp.sched_priority = 20; + pthread_setschedparam(pthread_self(), SCHED_FIFO, &sp); + + // Verify that config is not null + if (config == 0) + return (void *)-1; + + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__); + + pnf_t *_this = (pnf_t *)(config); + + while (_this->terminate == 0) { + int connect_result = pnf_connect_socket(_this); + + if (connect_result > 0) { + pnf_nr_message_pump(_this); + } else if (connect_result < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() Error connecting to P5 socket\n", __FUNCTION__); + return 0; + } + + sleep(1); + } + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() terminate=1 - EXITTING............\n", __FUNCTION__); + + return 0; +} + +int pnf_connect_socket(pnf_t *pnf) +{ + uint8_t socketConnected = 0; + + if (pnf->_public.vnf_ip_addr == 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "vnfIpAddress is null\n"); + return -1; + } + + NFAPI_TRACE(NFAPI_TRACE_INFO, "Starting P5 PNF connection to VNF at %s:%u\n", pnf->_public.vnf_ip_addr, pnf->_public.vnf_p5_port); + + // todo split the vnf address list. currently only supporting 1 + + struct addrinfo hints = {0}, *servinfo; + + hints.ai_socktype = SOCK_STREAM; // For SCTP we are only interested in SOCK_STREAM + // todo : allow the client to restrict IPV4 or IPV6 + // todo : randomize which address to connect to? + + char port_str[8]; + snprintf(port_str, sizeof(port_str), "%d", pnf->_public.vnf_p5_port); + if (getaddrinfo(pnf->_public.vnf_ip_addr, port_str, &hints, &servinfo) != 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failed to get host (%s) addr info h_errno:%d \n", pnf->_public.vnf_ip_addr, h_errno); + return -1; + } + + struct addrinfo *p = servinfo; + int connected = 0; + + while (p != NULL && connected == 0) { +#ifdef NFAPI_TRACE_ENABLED + char *family = "Unknown"; + char *address = "Unknown"; + char _addr[128]; + + if (p->ai_family == AF_INET6) { + family = "IPV6"; + struct sockaddr_in6 *addr = (struct sockaddr_in6 *)p->ai_addr; + inet_ntop(AF_INET6, &addr->sin6_addr, _addr, sizeof(_addr)); + address = &_addr[0]; + } else if (p->ai_family == AF_INET) { + family = "IPV4"; + struct sockaddr_in *addr = (struct sockaddr_in *)p->ai_addr; + address = inet_ntoa(addr->sin_addr); + } + + NFAPI_TRACE(NFAPI_TRACE_NOTE, "Host address info %d Family:%s Address:%s\n", i++, family, address); +#endif + + if (pnf->sctp) { + // open the SCTP socket + if ((pnf->p5_sock = socket(p->ai_family, SOCK_STREAM, IPPROTO_SCTP)) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After P5 socket errno: %d\n", errno); + freeaddrinfo(servinfo); + return -1; + } + int noDelay; + struct sctp_initmsg initMsg = {0}; + + // configure the socket options + NFAPI_TRACE(NFAPI_TRACE_NOTE, "PNF Setting the SCTP_INITMSG\n"); + initMsg.sinit_num_ostreams = 5; // MAX_SCTP_STREAMS; // number of output streams can be greater + initMsg.sinit_max_instreams = 5; // MAX_SCTP_STREAMS; // number of output streams can be greater + if (setsockopt(pnf->p5_sock, IPPROTO_SCTP, SCTP_INITMSG, &initMsg, sizeof(initMsg)) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt errno: %d\n", errno); + freeaddrinfo(servinfo); + return -1; + } + noDelay = 1; + if (setsockopt(pnf->p5_sock, IPPROTO_SCTP, SCTP_NODELAY, &noDelay, sizeof(noDelay)) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt errno: %d\n", errno); + freeaddrinfo(servinfo); + return -1; + } + + struct sctp_event_subscribe events = {0}; + events.sctp_data_io_event = 1; + + if (setsockopt(pnf->p5_sock, SOL_SCTP, SCTP_EVENTS, (const void *)&events, sizeof(events)) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt errno: %d\n", errno); + freeaddrinfo(servinfo); + return -1; + } + } else { + // Create an IP socket point + if ((pnf->p5_sock = socket(p->ai_family, SOCK_STREAM, IPPROTO_IP)) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After P5 socket errno: %d\n", errno); + freeaddrinfo(servinfo); + return -1; + } + } + + NFAPI_TRACE(NFAPI_TRACE_INFO, "P5 socket created...\n"); + + if (connect(pnf->p5_sock, p->ai_addr, p->ai_addrlen) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, + "After connect (address:%s port:%d) errno: %d\n", + pnf->_public.vnf_ip_addr, + pnf->_public.vnf_p5_port, + errno); + + if (errno == EINVAL) { + freeaddrinfo(servinfo); + return -1; + } + if (pnf->terminate != 0) { + freeaddrinfo(servinfo); + return 0; + } + close(pnf->p5_sock); + sleep(1); + } else { + NFAPI_TRACE(NFAPI_TRACE_INFO, "connect succeeded...\n"); + + connected = 1; + } + + p = p->ai_next; + } + + freeaddrinfo(servinfo); + + // If we have failed to connect return 0 and it is retry + if (connected == 0) + return 0; + + NFAPI_TRACE(NFAPI_TRACE_NOTE, "After connect loop\n"); + if (pnf->sctp) { + socklen_t optLen; + struct sctp_status status = {0}; + + // check the connection status + optLen = (socklen_t)sizeof(struct sctp_status); + if (getsockopt(pnf->p5_sock, IPPROTO_SCTP, SCTP_STATUS, &status, &optLen) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After getsockopt errno: %d\n", errno); + return -1; + } else { + NFAPI_TRACE(NFAPI_TRACE_INFO, "Association ID = %d\n", status.sstat_assoc_id); + NFAPI_TRACE(NFAPI_TRACE_INFO, "Receiver window size = %d\n", status.sstat_rwnd); + NFAPI_TRACE(NFAPI_TRACE_INFO, "In Streams = %d\n", status.sstat_instrms); + NFAPI_TRACE(NFAPI_TRACE_INFO, "Out Streams = %d\n", status.sstat_outstrms); + + socketConnected = 1; + } + } else { + int error; + socklen_t len = sizeof(error); + + if (getsockopt(pnf->p5_sock, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After getsockopt errno: %d\n", errno); + return -1; + } else { + // If error is zero, the socket is connected + if (error == 0) { + socketConnected = 1; + } + } + } + + NFAPI_TRACE(NFAPI_TRACE_NOTE, "Socket %s\n", socketConnected ? "CONNECTED" : "NOT_CONNECTED"); + return socketConnected; +} + +static int pnf_nr_read_dispatch_message(pnf_t *pnf) +{ + int socket_connected = 1; + + // 1. Peek the message header + // 2. If the message is larger than the stack buffer, then create a dynamic buffer + // 3. Read the buffer + // 4. Handle the p5 message + + uint32_t header_buffer_size = NFAPI_NR_P5_HEADER_LENGTH; + uint8_t header_buffer[header_buffer_size]; + + uint32_t stack_buffer_size = 32; // should it be the size of then sctp_notificatoin structure + uint8_t stack_buffer[stack_buffer_size]; + + uint8_t *dynamic_buffer = 0; + + uint8_t *read_buffer = &stack_buffer[0]; + uint32_t message_size = 0; + + struct sockaddr_in addr; + socklen_t addr_len = sizeof(addr); + + struct sctp_sndrcvinfo sndrcvinfo = {0}; + + { + int flags = MSG_PEEK; + if (pnf->sctp) { + message_size = sctp_recvmsg(pnf->p5_sock, + header_buffer, + header_buffer_size, + /*(struct sockaddr*)&addr, &addr_len*/ + 0, + 0, + &sndrcvinfo, + &flags); + } else { + message_size = recv(pnf->p5_sock, header_buffer, header_buffer_size, flags); + } + + if (message_size < NFAPI_NR_P5_HEADER_LENGTH) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF Failed to peek sctp message size errno:%d\n", errno); + return 0; + } + + nfapi_nr_p4_p5_message_header_t header; + const bool result = pnf->_public.hdr_unpack_func(header_buffer, header_buffer_size, &header, sizeof(header), 0); + if (!result) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF Failed to unpack p5 message header\n"); + return 0; + } + message_size = header.message_length + header_buffer_size; + + // now have the size of the mesage + } + + if (message_size > stack_buffer_size) { + dynamic_buffer = (uint8_t *)malloc(message_size); + + if (dynamic_buffer == NULL) { + // todo : add error mesage + NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF Failed to allocate dynamic buffer for sctp_recvmsg size:%d\n", message_size); + return -1; + } + + read_buffer = dynamic_buffer; + } + + { + int flags = 0; + + ssize_t recvmsg_result = 0; + if (pnf->sctp) { + recvmsg_result = + sctp_recvmsg(pnf->p5_sock, read_buffer, message_size, (struct sockaddr *)&addr, &addr_len, &sndrcvinfo, &flags); + } else { + if ((recvmsg_result = recv(pnf->p5_sock, read_buffer, message_size, flags)) <= 0) { + recvmsg_result = -1; + } + } + if (recvmsg_result == -1) { + int tmp = errno; + NFAPI_TRACE(NFAPI_TRACE_INFO, "Failed to read sctp message size error %s errno:%d\n", strerror(tmp), tmp); + } else { +#if 0 + // print the received message + printf("\n MESSAGE RECEIVED: \n"); + for(int i=0; ip5_sock, + inet_ntoa(addr.sin_addr), + ntohs(addr.sin_port), + sndrcvinfo.sinfo_assoc_id, + sndrcvinfo.sinfo_stream, + ntohl(sndrcvinfo.sinfo_ppid), + message_size, + flags); + */ + + // handle now if complete message in one or more segments + if ((flags & 0x80) == 0x80 || !pnf->sctp) { + pnf_nr_handle_p5_message(pnf, read_buffer, message_size); + } else { + int tmp = errno; + NFAPI_TRACE(NFAPI_TRACE_WARN, + "sctp_recvmsg: unhandled mode with flags 0x%x and error %s errno:%d\n", + flags, + strerror(tmp), + tmp); + // assume socket disconnected + NFAPI_TRACE(NFAPI_TRACE_WARN, "Disconnected socket\n"); + socket_connected = 0; + } + } + } + } + + if (dynamic_buffer) { + free(dynamic_buffer); + } + + return socket_connected; +} + +int pnf_nr_message_pump(pnf_t *pnf) +{ + uint8_t socketConnected = 1; + + while (socketConnected && pnf->terminate == 0) { + fd_set rfds; + int selectRetval = 0; + + // select on a timeout and then get the message + FD_ZERO(&rfds); + FD_SET(pnf->p5_sock, &rfds); + + struct timeval timeout; + timeout.tv_sec = 1; + timeout.tv_usec = 0; + + selectRetval = select(pnf->p5_sock + 1, &rfds, NULL, NULL, &timeout); + + if (selectRetval == 0) { + // timeout + continue; + } else if (selectRetval == -1 && (errno == EINTR)) { + // interrupted by signal + NFAPI_TRACE(NFAPI_TRACE_WARN, "P5 Signal Interrupt %d\n", errno); + continue; + } else if (selectRetval == -1) { + NFAPI_TRACE(NFAPI_TRACE_WARN, "P5 select() failed\n"); + sleep(1); + continue; + } + + if (FD_ISSET(pnf->p5_sock, &rfds)) { + socketConnected = pnf_nr_read_dispatch_message(pnf); + } else { + NFAPI_TRACE(NFAPI_TRACE_WARN, "Why are we here\n"); + } + } + + // Drop back to idle if we have lost connection + pnf->_public.state = NFAPI_PNF_IDLE; + + // close the connection and socket + if (close(pnf->p5_sock) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "close(sctpSock) failed errno: %d\n", errno); + } + + return 0; +} + +static void pnf_nr_reassemble_nfapi_p7_message(void *pRecvMsg, int recvMsgLen, pnf_p7_t *pnf_p7, uint32_t rx_hr_time) +{ + nfapi_nr_p7_message_header_t messageHeader; + + // validate the input params + if (pRecvMsg == NULL || recvMsgLen < 4 || pnf_p7 == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "pnf_handle_p7_message: invalid input params (%p %d %p)\n", pRecvMsg, recvMsgLen, pnf_p7); + return; + } + + // unpack the message header + const bool result = + pnf_p7->_public.hdr_unpack_func(pRecvMsg, recvMsgLen, &messageHeader, sizeof(messageHeader), &pnf_p7->_public.codec_config); + if (!result) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n"); + return; + } + + uint8_t m = NFAPI_P7_GET_MORE(messageHeader.m_segment_sequence); + uint8_t sequence_num = NFAPI_P7_GET_SEQUENCE(messageHeader.m_segment_sequence); + uint8_t segment_num = NFAPI_P7_GET_SEGMENT(messageHeader.m_segment_sequence); + + if (pnf_p7->_public.checksum_enabled) { + uint32_t checksum = nfapi_nr_p7_calculate_checksum(pRecvMsg, recvMsgLen); + if (checksum != messageHeader.checksum) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Checksum verification failed %d %d\n", checksum, messageHeader.checksum); + return; + } + } + + if (m == 0 && segment_num == 0) { + // we have a complete message + // ensure the message is sensible + if (recvMsgLen < 8 || pRecvMsg == NULL) { + NFAPI_TRACE(NFAPI_TRACE_WARN, "Invalid message size: %d, ignoring\n", recvMsgLen); + return; + } + + pnf_nr_handle_p7_message(pRecvMsg, recvMsgLen, pnf_p7, rx_hr_time); + } else { + pnf_p7_rx_message_t *rx_msg = pnf_p7_rx_reassembly_queue_add_segment(pnf_p7, + &(pnf_p7->reassembly_queue), + rx_hr_time, + sequence_num, + segment_num, + m, + pRecvMsg, + recvMsgLen); + + if (rx_msg->num_segments_received == rx_msg->num_segments_expected) { + // send the buffer on + uint16_t i = 0; + uint32_t length = 0; + for (i = 0; i < rx_msg->num_segments_expected; ++i) { + length += rx_msg->segments[i].length - (i > 0 ? NFAPI_NR_P7_HEADER_LENGTH : 0); + } + + if (pnf_p7->reassemby_buffer_size < length) { + pnf_p7_free(pnf_p7, pnf_p7->reassemby_buffer); + pnf_p7->reassemby_buffer = 0; + } + + if (pnf_p7->reassemby_buffer == 0) { + NFAPI_TRACE(NFAPI_TRACE_NOTE, "Resizing PNF_P7 Reassembly buffer %d->%d\n", pnf_p7->reassemby_buffer_size, length); + pnf_p7->reassemby_buffer = (uint8_t *)pnf_p7_malloc(pnf_p7, length); + + if (pnf_p7->reassemby_buffer == 0) { + NFAPI_TRACE(NFAPI_TRACE_NOTE, "Failed to allocate PNF_P7 reassemby buffer len:%d\n", length); + return; + } + memset(pnf_p7->reassemby_buffer, 0, length); + pnf_p7->reassemby_buffer_size = length; + } + + uint32_t offset = 0; + for (i = 0; i < rx_msg->num_segments_expected; ++i) { + if (i == 0) { + memcpy(pnf_p7->reassemby_buffer, rx_msg->segments[i].buffer, rx_msg->segments[i].length); + offset += rx_msg->segments[i].length; + } else { + memcpy(pnf_p7->reassemby_buffer + offset, + rx_msg->segments[i].buffer + NFAPI_NR_P7_HEADER_LENGTH, + rx_msg->segments[i].length - NFAPI_NR_P7_HEADER_LENGTH); + offset += rx_msg->segments[i].length - NFAPI_NR_P7_HEADER_LENGTH; + } + } + + pnf_nr_handle_p7_message(pnf_p7->reassemby_buffer, length, pnf_p7, rx_msg->rx_hr_time); + + // delete the structure + pnf_p7_rx_reassembly_queue_remove_msg(pnf_p7, &(pnf_p7->reassembly_queue), rx_msg); + } + } + + // The timeout used to be 1000, i.e., 1ms, which is too short. The below 10ms + // is selected to be able to encompass any "reasonable" slot ahead time for the VNF. + // Ideally, we would remove old msg (segments) if we detect packet loss + // (e.g., if the sequence numbers advances sufficiently); in the branch of + // this commit, our goal is to make the PNF work, so we content ourselves to + // just remove very old messages. + pnf_p7_rx_reassembly_queue_remove_old_msgs(pnf_p7, &(pnf_p7->reassembly_queue), rx_hr_time, 10000); +} + +static void pnf_nr_nfapi_p7_read_dispatch_message(pnf_p7_t *pnf_p7, uint32_t now_hr_time) +{ + int recvfrom_result = 0; + struct sockaddr_in remote_addr; + socklen_t remote_addr_size = sizeof(remote_addr); + remote_addr.sin_family = 2; // hardcoded + do { + // peek the header + uint8_t header_buffer[NFAPI_NR_P7_HEADER_LENGTH]; + recvfrom_result = recvfrom(pnf_p7->p7_sock, + header_buffer, + NFAPI_NR_P7_HEADER_LENGTH, + MSG_DONTWAIT | MSG_PEEK, + (struct sockaddr *)&remote_addr, + &remote_addr_size); + if (recvfrom_result > 0) { + // get the segment size + nfapi_nr_p7_message_header_t header; + pnf_p7->_public.hdr_unpack_func(header_buffer, NFAPI_NR_P7_HEADER_LENGTH, &header, 34, 0); + + // resize the buffer if we have a large segment + if (header.message_length > pnf_p7->rx_message_buffer_size) { + NFAPI_TRACE(NFAPI_TRACE_NOTE, "reallocing rx buffer %d\n", header.message_length); + pnf_p7->rx_message_buffer = realloc(pnf_p7->rx_message_buffer, header.message_length); + pnf_p7->rx_message_buffer_size = header.message_length; + } + + // read the segment + recvfrom_result = recvfrom(pnf_p7->p7_sock, + pnf_p7->rx_message_buffer, + header.message_length, + MSG_DONTWAIT, + (struct sockaddr *)&remote_addr, + &remote_addr_size); + + now_hr_time = pnf_get_current_time_hr(); // moved to here - get closer timestamp??? + + if (recvfrom_result > 0) { + pnf_nr_reassemble_nfapi_p7_message(pnf_p7->rx_message_buffer, recvfrom_result, pnf_p7, now_hr_time); + // printf("\npnf_handle_p7_message sfn=%d,slot=%d\n",pnf_p7->sfn,pnf_p7->slot); + } + } else if (recvfrom_result == 0) { + // recv zero length message + recvfrom_result = + recvfrom(pnf_p7->p7_sock, header_buffer, 0, MSG_DONTWAIT, (struct sockaddr *)&remote_addr, &remote_addr_size); + } + + if (recvfrom_result == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) { + // return to the select + // NFAPI_TRACE(NFAPI_TRACE_WARN, "%s recvfrom would block :%d\n", __FUNCTION__, errno); + } else { + NFAPI_TRACE(NFAPI_TRACE_WARN, "%s recvfrom failed errno:%d\n", __FUNCTION__, errno); + } + } + + // need to update the time as we would only use the value from the + // select + } while (recvfrom_result > 0); +} + +int pnf_nr_p7_message_pump(pnf_p7_t *pnf_p7) +{ + // initialize the mutex lock + if (pthread_mutex_init(&(pnf_p7->mutex), NULL) != 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After P7 mutex init: %d\n", errno); + return -1; + } + + if (pthread_mutex_init(&(pnf_p7->pack_mutex), NULL) != 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After P7 mutex init: %d\n", errno); + return -1; + } + + // create the pnf p7 socket + if ((pnf_p7->p7_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After P7 socket errno: %d\n", errno); + return -1; + } + NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF P7 socket created (%d)...\n", pnf_p7->p7_sock); + + // configure the UDP socket options + int reuseaddr_enable = 1; + if (setsockopt(pnf_p7->p7_sock, SOL_SOCKET, SO_REUSEADDR, &reuseaddr_enable, sizeof(int)) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "PNF P7 setsockopt (SOL_SOCKET, SO_REUSEADDR) failed errno: %d\n", errno); + return -1; + } + + /* + int reuseport_enable = 1; + if (setsockopt(pnf_p7->p7_sock, SOL_SOCKET, SO_REUSEPORT, &reuseport_enable, sizeof(int)) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "PNF P7 setsockopt (SOL_SOCKET, SO_REUSEPORT) failed errno: %d\n", errno); + return -1; + } + */ + + int iptos_value = 0; + if (setsockopt(pnf_p7->p7_sock, IPPROTO_IP, IP_TOS, &iptos_value, sizeof(iptos_value)) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "PNF P7 setsockopt (IPPROTO_IP, IP_TOS) failed errno: %d\n", errno); + return -1; + } + + struct sockaddr_in addr = {0}; + addr.sin_family = AF_INET; + addr.sin_port = htons(pnf_p7->_public.local_p7_port); + + if (pnf_p7->_public.local_p7_addr == 0) { + addr.sin_addr.s_addr = INADDR_ANY; + } else { + // addr.sin_addr.s_addr = inet_addr(pnf_p7->_public.local_p7_addr); + if (inet_aton(pnf_p7->_public.local_p7_addr, &addr.sin_addr) == -1) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "inet_aton failed\n"); + } + } + + NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF P7 binding %d too %s:%d\n", pnf_p7->p7_sock, inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); + if (bind(pnf_p7->p7_sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "PNF_P7 bind error fd:%d errno: %d\n", pnf_p7->p7_sock, errno); + return -1; + } + NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF P7 bind succeeded...\n"); + + // Initializaing timing structures needed for slot ticking + + struct timespec slot_start; + clock_gettime(CLOCK_MONOTONIC, &slot_start); + + struct timespec pselect_start; + + struct timespec slot_duration; + slot_duration.tv_sec = 0; + slot_duration.tv_nsec = 0.5e6; + + // Infinite loop + + while (pnf_p7->terminate == 0) { + fd_set rfds; + int selectRetval = 0; + + // select on a timeout and then get the message + FD_ZERO(&rfds); + FD_SET(pnf_p7->p7_sock, &rfds); + + struct timespec timeout; + timeout.tv_sec = 100; + timeout.tv_nsec = 0; + clock_gettime(CLOCK_MONOTONIC, &pselect_start); + + // setting the timeout + + if ((pselect_start.tv_sec > slot_start.tv_sec) + || ((pselect_start.tv_sec == slot_start.tv_sec) && (pselect_start.tv_nsec > slot_start.tv_nsec))) { + // overran the end of the subframe we do not want to wait + timeout.tv_sec = 0; + timeout.tv_nsec = 0; + + // struct timespec overrun = pnf_timespec_sub(pselect_start, sf_start); + // NFAPI_TRACE(NFAPI_TRACE_INFO, "Subframe overrun detected of %d.%d running to catchup\n", overrun.tv_sec, overrun.tv_nsec); + } else { + // still time before the end of the subframe wait + timeout = pnf_timespec_sub(slot_start, pselect_start); + } + + selectRetval = pselect(pnf_p7->p7_sock + 1, &rfds, NULL, NULL, &timeout, NULL); + + uint32_t now_hr_time = pnf_get_current_time_hr(); + + if (selectRetval == 0) { + // timeout + + // update slot start timing + slot_start = pnf_timespec_add(slot_start, slot_duration); + + // increment sfn/slot + if (++pnf_p7->slot == 20) { + pnf_p7->slot = 0; + pnf_p7->sfn = (pnf_p7->sfn + 1) % 1024; + } + + continue; + } else if (selectRetval == -1 && (errno == EINTR)) { + // interrupted by signal + NFAPI_TRACE(NFAPI_TRACE_WARN, "PNF P7 Signal Interrupt %d\n", errno); + continue; + } else if (selectRetval == -1) { + NFAPI_TRACE(NFAPI_TRACE_WARN, "PNF P7 select() failed\n"); + sleep(1); + continue; + } + + if (FD_ISSET(pnf_p7->p7_sock, &rfds)) + + { + pnf_nr_nfapi_p7_read_dispatch_message(pnf_p7, now_hr_time); + } + } + NFAPI_TRACE(NFAPI_TRACE_ERROR, "PNF_P7 Terminating..\n"); + + // close the connection and socket + if (close(pnf_p7->p7_sock) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "close failed errno: %d\n", errno); + } + + if (pthread_mutex_destroy(&(pnf_p7->pack_mutex)) != 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "mutex destroy failed errno: %d\n", errno); + } + + if (pthread_mutex_destroy(&(pnf_p7->mutex)) != 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "mutex destroy failed errno: %d\n", errno); + } + + return 0; +} + +static int nfapi_nr_pnf_p7_start(nfapi_pnf_p7_config_t *config) +{ + // Verify that config is not null + if (config == 0) + return -1; + + pnf_p7_t *_this = (pnf_p7_t *)(config); + + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__); + + pnf_nr_p7_message_pump(_this); + + return 0; +} + +void *pnf_nr_p7_thread_start(void *ptr) +{ + NFAPI_TRACE(NFAPI_TRACE_INFO, "[NR_PNF] NR P7 THREAD %s\n", __FUNCTION__); + nfapi_pnf_p7_config_t *config = (nfapi_pnf_p7_config_t *)ptr; + nfapi_nr_pnf_p7_start(config); + return 0; +} diff --git a/nfapi/open-nFAPI/fapi/CMakeLists.txt b/nfapi/open-nFAPI/fapi/CMakeLists.txt index b332ef6a8e..a97f5f6e6f 100644 --- a/nfapi/open-nFAPI/fapi/CMakeLists.txt +++ b/nfapi/open-nFAPI/fapi/CMakeLists.txt @@ -22,3 +22,5 @@ if (OAI_AERIAL) target_compile_definitions(nr_fapi_p5 PRIVATE ENABLE_AERIAL) target_compile_definitions(nr_fapi_p7 PRIVATE ENABLE_AERIAL) endif () + +target_compile_definitions(nr_fapi_common PRIVATE ENABLE_SOCKET) diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h index f830e904e2..3cfd0591fc 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h @@ -115,7 +115,8 @@ typedef struct { #define NFAPI_P7_GET_MORE(_mss) ( ((_mss) & 0x8000) >> 15 ) #define NFAPI_P7_GET_SEGMENT(_mss) ( ((_mss) & 0x7F00) >> 8 ) #define NFAPI_P7_GET_SEQUENCE(_mss) ( (_mss) & 0x00FF ) -#define NFAPI_P7_SET_MSS(_more, _segm, _sequ) ( (((_more) & 0x1) << 7) | (((_segm) & 0x7) << 4) | ((_sequ) & 0xF) ) +#define NFAPI_NR_P7_SET_MSS(_more, _segm, _sequ) ( (((_more) & 0x1) << 15) | (((_segm) & 0x7F) << 8) | ((_sequ) & 0xFF) ) +#define NFAPI_P7_SET_MSS(_more, _segm, _sequ) ( (((_more) & 0x1) << 7) | (((_segm) & 0x7F) << 4) | ((_sequ) & 0xF) ) #define NFAPI_TAG_LENGTH_PACKED_LEN 4 diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c index c60ed27d07..f7c55cd2e0 100644 --- a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c @@ -6203,7 +6203,10 @@ int nfapi_p7_message_unpack(void *pMessageBuf, bool peek_nr_nfapi_p7_sfn_slot(void *pMessageBuf, uint32_t messageBufLen, uint16_t *SFN, uint16_t *Slot) { +#ifdef ENABLE_SOCKET + // Socket transport will always use nFAPI encoding uint8_t *pReadPackedMessage = &((uint8_t *)pMessageBuf)[NFAPI_NR_P7_HEADER_LENGTH]; +#endif uint8_t *end = (uint8_t*)pMessageBuf + messageBufLen; if(!(pull16(&pReadPackedMessage, SFN, end) && pull16(&pReadPackedMessage, Slot, end))) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failed to peek SFN.Slot\n"); diff --git a/nfapi/open-nFAPI/pnf/inc/pnf.h b/nfapi/open-nFAPI/pnf/inc/pnf.h index 386cb3cf6a..968359dfee 100644 --- a/nfapi/open-nFAPI/pnf/inc/pnf.h +++ b/nfapi/open-nFAPI/pnf/inc/pnf.h @@ -38,9 +38,8 @@ struct pnf_t { int pnf_connect(pnf_t *pnf); int pnf_message_pump(pnf_t *pnf); -int pnf_nr_message_pump(pnf_t *pnf); -bool pnf_nr_send_p5_message(pnf_t* pnf, nfapi_nr_p4_p5_message_header_t* msg, uint32_t msg_len); +void pnf_nr_handle_p5_message(pnf_t* pnf, void* pRecvMsg, int recvMsgLen); int pnf_pack_and_send_p5_message(pnf_t* pnf, nfapi_p4_p5_message_header_t* msg, uint32_t msg_len); int pnf_pack_and_send_p4_message(pnf_t* pnf, nfapi_p4_p5_message_header_t* msg, uint32_t msg_len); int pnf_send_message(pnf_t* pnf, uint8_t* msg, uint32_t msg_len, uint16_t stream_id); diff --git a/nfapi/open-nFAPI/pnf/inc/pnf_p7.h b/nfapi/open-nFAPI/pnf/inc/pnf_p7.h index 8a603ecdb3..49868bde8d 100644 --- a/nfapi/open-nFAPI/pnf/inc/pnf_p7.h +++ b/nfapi/open-nFAPI/pnf/inc/pnf_p7.h @@ -144,7 +144,6 @@ struct pnf_p7_t { int pnf_p7_message_pump(pnf_p7_t* pnf_p7); int pnf_nr_p7_message_pump(pnf_p7_t* pnf_p7); int pnf_p7_pack_and_send_p7_message(pnf_p7_t* pnf_p7, nfapi_p7_message_header_t* msg, uint32_t msg_len); -bool pnf_nr_send_p7_message(pnf_p7_t* pnf_p7, nfapi_nr_p7_message_header_t* header, uint32_t msg_len); int pnf_p7_send_message(pnf_p7_t* pnf_p7, uint8_t* msg, uint32_t msg_len); @@ -159,6 +158,11 @@ int nfapi_pnf_p7_nr_rach_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_rach_indica pnf_p7_rx_message_t* pnf_p7_rx_reassembly_queue_add_segment(pnf_p7_t* pnf_p7, pnf_p7_rx_reassembly_queue_t* queue, uint32_t rx_hr_time, uint16_t sequence_number, uint16_t segment_number, uint8_t m, uint8_t* data, uint16_t data_len); void pnf_p7_rx_reassembly_queue_remove_msg(pnf_p7_t* pnf_p7, pnf_p7_rx_reassembly_queue_t* queue, pnf_p7_rx_message_t* msg); void pnf_p7_rx_reassembly_queue_remove_old_msgs(pnf_p7_t* pnf_p7, pnf_p7_rx_reassembly_queue_t* queue, uint32_t rx_hr_time, uint32_t delta); - +void pnf_nr_handle_p7_message(void *pRecvMsg, int recvMsgLen, pnf_p7_t *pnf_p7, uint32_t rx_hr_time); +struct timespec pnf_timespec_sub(struct timespec lhs, struct timespec rhs); +uint32_t pnf_get_current_time_hr(void); +struct timespec pnf_timespec_add(struct timespec lhs, struct timespec rhs); +void pnf_p7_free(pnf_p7_t* pnf_p7, void* ptr); +void* pnf_p7_malloc(pnf_p7_t* pnf_p7, size_t size); #endif /* _PNF_P7_H_ */ diff --git a/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h b/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h index 04abf6309d..957e032f69 100644 --- a/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h +++ b/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h @@ -419,7 +419,6 @@ int nfapi_pnf_config_destroy(nfapi_pnf_config_t* config); * \endcode */ int nfapi_pnf_start(nfapi_pnf_config_t* config); -int nfapi_nr_pnf_start(nfapi_pnf_config_t* config); /*! Stop the PNF library. * \param config A pointer to the pnf configuration @@ -847,7 +846,7 @@ int nfapi_pnf_p7_config_destroy(nfapi_pnf_p7_config_t* config); * This function will not return until nfapi_pnf_p7_stop is called. */ int nfapi_pnf_p7_start(nfapi_pnf_p7_config_t* config); -int nfapi_nr_pnf_p7_start(nfapi_pnf_p7_config_t* config); + /*! Stop the PNF P7 library. * \param config A pointer to a PNF P7 config diff --git a/nfapi/open-nFAPI/pnf/src/pnf.c b/nfapi/open-nFAPI/pnf/src/pnf.c index e6fb69bd71..fd572cf77f 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf.c +++ b/nfapi/open-nFAPI/pnf/src/pnf.c @@ -30,6 +30,10 @@ #include "nfapi_nr_interface_scf.h" #include "pnf.h" +#include + +#include "nfapi/open-nFAPI/fapi/inc/nr_fapi.h" + # if 1 // for hard-code (remove later) #include "common/platform_types.h" #include "common/platform_constants.h" @@ -1705,20 +1709,6 @@ void pnf_handle_p5_message(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) } } -bool pnf_nr_send_p5_message(pnf_t* pnf, nfapi_nr_p4_p5_message_header_t* msg, uint32_t msg_len) -{ - int packed_len = - pnf->_public.pack_func(msg, msg_len, pnf->tx_message_buffer, sizeof(pnf->tx_message_buffer), &pnf->_public.codec_config); - - if (packed_len < 0) { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi_nr_p5_message_pack failed (%d)\n", packed_len); - return false; - } - - return pnf_send_message(pnf, pnf->tx_message_buffer, packed_len, 0 /*msg->stream_id*/) == 0; -} - - int pnf_pack_and_send_p5_message(pnf_t* pnf, nfapi_p4_p5_message_header_t* msg, uint32_t msg_len) { int packed_len = nfapi_p5_message_pack(msg, msg_len, @@ -1751,8 +1741,6 @@ int pnf_pack_and_send_p4_message(pnf_t* pnf, nfapi_p4_p5_message_header_t* msg, return pnf_send_message(pnf, pnf->tx_message_buffer, packed_len, 0/*msg->stream_id*/); } - - int pnf_connect(pnf_t* pnf) { struct sockaddr_in servaddr; @@ -1957,30 +1945,30 @@ int pnf_connect(pnf_t* pnf) int pnf_send_message(pnf_t* pnf, uint8_t *msg, uint32_t len, uint16_t stream) { - if (pnf->sctp) - { + if (pnf->sctp) + { #if 0 - printf("\nPNF SENDS: \n"); - for(int i=0; ip5_sock, msg, len, NULL, 0, 42/*config->sctp_stream_number*/, 0, stream/*P5_STREAM_ID*/, 0, 0) < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "sctp_sendmsg failed errno: %d\n", errno); - return -1; - } - } - else - { - if (write(pnf->p5_sock, msg, len) != len) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "read failed errno: %d\n", errno); - return -1; - } - } + if (sctp_sendmsg(pnf->p5_sock, msg, len, NULL, 0, 42/*config->sctp_stream_number*/, 0, stream/*P5_STREAM_ID*/, 0, 0) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "sctp_sendmsg failed errno: %d\n", errno); + return -1; + } + } + else + { + if (write(pnf->p5_sock, msg, len) != len) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "read failed errno: %d\n", errno); + return -1; + } + } return 0; } @@ -2117,146 +2105,6 @@ int pnf_read_dispatch_message(pnf_t* pnf) } -int pnf_nr_read_dispatch_message(pnf_t* pnf) -{ - int socket_connected = 1; - - // 1. Peek the message header - // 2. If the message is larger than the stack buffer then create a dynamic buffer - // 3. Read the buffer - // 4. Handle the p5 message - - uint32_t header_buffer_size = NFAPI_NR_P5_HEADER_LENGTH; - uint8_t header_buffer[header_buffer_size]; - - uint32_t stack_buffer_size = 32; // should it be the size of then sctp_notificatoin structure - uint8_t stack_buffer[stack_buffer_size]; - - uint8_t* dynamic_buffer = 0; - - uint8_t* read_buffer = &stack_buffer[0]; - uint32_t message_size = 0; - - struct sockaddr_in addr; - socklen_t addr_len = sizeof(addr); - - struct sctp_sndrcvinfo sndrcvinfo; - (void)memset(&sndrcvinfo, 0, sizeof(struct sctp_sndrcvinfo)); - - { - int flags = MSG_PEEK; - if (pnf->sctp) { - message_size = sctp_recvmsg(pnf->p5_sock, - header_buffer, - header_buffer_size, - /*(struct sockaddr*)&addr, &addr_len*/ - 0, - 0, - &sndrcvinfo, - &flags); - } else { - message_size = recv(pnf->p5_sock, - header_buffer, - header_buffer_size, - flags); - } - - if (message_size < NFAPI_NR_P5_HEADER_LENGTH) { - NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF Failed to peek sctp message size errno:%d\n", errno); - return 0; - } - - nfapi_nr_p4_p5_message_header_t header; - const bool result = pnf->_public.hdr_unpack_func(header_buffer, header_buffer_size, &header, sizeof(header), 0); - if (!result) { - NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF Failed to unpack p5 message header\n"); - return 0; - } - message_size = header.message_length + header_buffer_size; - - // now have the size of the mesage - } - - if (message_size > stack_buffer_size) { - dynamic_buffer = (uint8_t*)malloc(message_size); - - if (dynamic_buffer == NULL) { - // todo : add error mesage - NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF Failed to allocate dynamic buffer for sctp_recvmsg size:%d\n", message_size); - return -1; - } - - read_buffer = dynamic_buffer; - } - - { - int flags = 0; - (void)memset(&sndrcvinfo, 0, sizeof(struct sctp_sndrcvinfo)); - - ssize_t recvmsg_result = 0; - if (pnf->sctp) { - recvmsg_result = sctp_recvmsg(pnf->p5_sock, - read_buffer, - message_size, - (struct sockaddr *)&addr, - &addr_len, - &sndrcvinfo, - &flags); - } else { - if ((recvmsg_result = recv(pnf->p5_sock, read_buffer, message_size, flags))<=0) { - recvmsg_result = -1; - } - } - if (recvmsg_result == -1) { - NFAPI_TRACE(NFAPI_TRACE_INFO, "Failed to read sctp message size errno:%d\n", errno); - } else { -#if 0 - // print the received message - printf("\n MESSAGE RECEIVED: \n"); - for(int i=0; ip5_sock, - inet_ntoa(addr.sin_addr), - ntohs(addr.sin_port), - sndrcvinfo.sinfo_assoc_id, - sndrcvinfo.sinfo_stream, - ntohl(sndrcvinfo.sinfo_ppid), - message_size, - flags); - */ - - // handle now if complete message in one or more segments - if ((flags & 0x80) == 0x80 || !pnf->sctp) { - pnf_nr_handle_p5_message(pnf, read_buffer, message_size); - } else { - NFAPI_TRACE(NFAPI_TRACE_WARN, "sctp_recvmsg: unhandled mode with flags 0x%x\n", flags); - - // assume socket disconnected - NFAPI_TRACE(NFAPI_TRACE_WARN, "Disconnected socket\n"); - socket_connected = 0; - } - } - } - } - - if (dynamic_buffer) { - free(dynamic_buffer); - } - - return socket_connected; -} - int pnf_message_pump(pnf_t* pnf) { uint8_t socketConnected = 1; @@ -2308,67 +2156,6 @@ int pnf_message_pump(pnf_t* pnf) pnf->_public.state = NFAPI_PNF_IDLE; - // close the connection and socket - if (close(pnf->p5_sock) < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "close(sctpSock) failed errno: %d\n", errno); - } - - return 0; - -} - -int pnf_nr_message_pump(pnf_t* pnf) -{ - uint8_t socketConnected = 1; - - while(socketConnected && pnf->terminate == 0) - { - fd_set rfds; - int selectRetval = 0; - - // select on a timeout and then get the message - FD_ZERO(&rfds); - FD_SET(pnf->p5_sock, &rfds); - - struct timeval timeout; - timeout.tv_sec = 1; - timeout.tv_usec = 0; - - selectRetval = select(pnf->p5_sock+1, &rfds, NULL, NULL, &timeout); - - if(selectRetval == 0) - { - // timeout - continue; - } - else if (selectRetval == -1 && (errno == EINTR)) - { - // interrupted by signal - NFAPI_TRACE(NFAPI_TRACE_WARN, "P5 Signal Interrupt %d\n", errno); - continue; - } - else if (selectRetval == -1) - { - NFAPI_TRACE(NFAPI_TRACE_WARN, "P5 select() failed\n"); - sleep(1); - continue; - } - - if(FD_ISSET(pnf->p5_sock, &rfds)) - { - socketConnected = pnf_nr_read_dispatch_message(pnf); - } - else - { - NFAPI_TRACE(NFAPI_TRACE_WARN, "Why are we here\n"); - } - } - - // Drop back to idle if we have lost connection - pnf->_public.state = NFAPI_PNF_IDLE; - - // close the connection and socket if (close(pnf->p5_sock) < 0) { diff --git a/nfapi/open-nFAPI/pnf/src/pnf_interface.c b/nfapi/open-nFAPI/pnf/src/pnf_interface.c index 78ea46bbf6..d80ab168fa 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_interface.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_interface.c @@ -79,36 +79,6 @@ int nfapi_pnf_start(nfapi_pnf_config_t* config) return 0; } -int nfapi_nr_pnf_start(nfapi_pnf_config_t* config) -{ - // Verify that config is not null - if(config == 0) - return -1; - - NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__); - - pnf_t* _this = (pnf_t*)(config); - - while (_this->terminate == 0) - { - int connect_result = pnf_connect(_this); - - if(connect_result > 0) - { - pnf_nr_message_pump(_this); - } - else if(connect_result < 0) - { - return connect_result; - } - - sleep(1); - } - NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() terminate=1 - EXITTING............\n", __FUNCTION__); - - return 0; -} - int nfapi_pnf_stop(nfapi_pnf_config_t* config) { // Verify that config is not null diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7.c b/nfapi/open-nFAPI/pnf/src/pnf_p7.c index 95fff37bc9..e2b6d253d2 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7.c @@ -32,7 +32,6 @@ #include "common/ran_context.h" #include -#define FAPI2_IP_DSCP 0 extern int sf_ahead; @@ -464,10 +463,10 @@ int pnf_p7_send_message(pnf_p7_t* pnf_p7, uint8_t* msg, uint32_t len) socklen_t remote_addr_len = sizeof(struct sockaddr_in); int sendto_result; - - if ((sendto_result = sendto((int)pnf_p7->p7_sock, (const char*)msg, len, 0, (const struct sockaddr*)&remote_addr, remote_addr_len)) < 0) -//if ((sendto_result = sendto((int)pnf_p7->p7_sock,"hello", 6, 0, (const struct sockaddr*)&remote_addr, remote_addr_len)) < 0) - { + + if ((sendto_result = sendto((int)pnf_p7->p7_sock, (const char*)msg, len, 0, (const struct sockaddr*)&remote_addr, remote_addr_len)) < 0) + //if ((sendto_result = sendto((int)pnf_p7->p7_sock,"hello", 6, 0, (const struct sockaddr*)&remote_addr, remote_addr_len)) < 0) + { NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s %s:%d sendto(%d, %p, %d) %d failed errno: %d\n", __FUNCTION__, pnf_p7->_public.remote_p7_addr, pnf_p7->_public.remote_p7_port, (int)pnf_p7->p7_sock, (const char*)msg, len, remote_addr_len, errno); return -1; } @@ -569,87 +568,6 @@ int pnf_p7_pack_and_send_p7_message(pnf_p7_t* pnf_p7, nfapi_p7_message_header_t* return 0; } -bool pnf_nr_send_p7_message(pnf_p7_t* pnf_p7, nfapi_nr_p7_message_header_t* header, uint32_t msg_len) -{ - header->m_segment_sequence = NFAPI_P7_SET_MSS(0, 0, pnf_p7->sequence_number); - - // Need to guard against different threads calling the encode function at the same time - if (pthread_mutex_lock(&(pnf_p7->pack_mutex)) != 0) { - NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to lock mutex\n"); - return false; - } - - uint8_t tx_buf[131072]; // four times NFAPI_MAX_PACKED_MESSAGE_SIZE as of this commit - int len = pnf_p7->_public.pack_func(header, tx_buf, sizeof(tx_buf), &pnf_p7->_public.codec_config); - - if (len < 0) { - if (pthread_mutex_unlock(&(pnf_p7->pack_mutex)) != 0) { - NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to unlock mutex\n"); - return false; - } - - NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi_p7_message_pack failed with return %d\n", len); - return false; - } - - if (len > pnf_p7->_public.segment_size) { - int msg_body_len = len - NFAPI_NR_P7_HEADER_LENGTH; - int seg_body_len = pnf_p7->_public.segment_size - NFAPI_NR_P7_HEADER_LENGTH; - int segment_count = (msg_body_len / (seg_body_len)) + ((msg_body_len % seg_body_len) ? 1 : 0); - - int segment = 0; - int offset = NFAPI_NR_P7_HEADER_LENGTH; - uint8_t buffer[pnf_p7->_public.segment_size]; - for (segment = 0; segment < segment_count; ++segment) { - uint8_t last = 0; - uint32_t size = pnf_p7->_public.segment_size - NFAPI_NR_P7_HEADER_LENGTH; - if (segment + 1 == segment_count) { - last = 1; - size = (msg_body_len) - (seg_body_len * segment); - } - - uint32_t segment_size = size + NFAPI_NR_P7_HEADER_LENGTH; - - // Update the header with the m and segement - memcpy(&buffer[0], tx_buf, NFAPI_NR_P7_HEADER_LENGTH); - - // set the segment length - buffer[4] = (segment_size & 0xFF000000) >> 24; - buffer[5] = (segment_size & 0xFF0000) >> 16; - buffer[6] = (segment_size & 0xFF00) >> 8; - buffer[7] = (segment_size & 0xFF); - - // set the m & segment number - buffer[8] = ((!last) << 7) + segment; - - memcpy(&buffer[NFAPI_NR_P7_HEADER_LENGTH], tx_buf + offset, size); - offset += size; - - if (pnf_p7->_public.checksum_enabled) { - nfapi_nr_p7_update_checksum(buffer, segment_size); - } - - pnf_p7_send_message(pnf_p7, &buffer[0], segment_size); - } - } else { - if (pnf_p7->_public.checksum_enabled) { - nfapi_nr_p7_update_checksum(tx_buf, len); - } - - // simple case that the message fits in a single segment - pnf_p7_send_message(pnf_p7, tx_buf, len); - } - - pnf_p7->sequence_number++; - - if (pthread_mutex_unlock(&(pnf_p7->pack_mutex)) != 0) { - NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to unlock mutex\n"); - return false; - } - - return true; -} - void pnf_pack_and_send_timing_info(pnf_p7_t* pnf_p7) { nfapi_timing_info_t timing_info; @@ -2171,7 +2089,7 @@ void pnf_dispatch_p7_message(void *pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7, } } -void pnf_nr_dispatch_p7_message(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7, uint32_t rx_hr_time) +void pnf_nr_handle_p7_message(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7, uint32_t rx_hr_time) { nfapi_nr_p7_message_header_t header; @@ -2326,110 +2244,6 @@ void pnf_handle_p7_message(void *pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7, ui } -void pnf_nr_handle_p7_message(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7, uint32_t rx_hr_time) -{ - nfapi_nr_p7_message_header_t messageHeader; - - // validate the input params - if (pRecvMsg == NULL || recvMsgLen < 4 || pnf_p7 == NULL) { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "pnf_handle_p7_message: invalid input params (%p %d %p)\n", pRecvMsg, recvMsgLen, pnf_p7); - return; - } - - // unpack the message header - const bool result = - pnf_p7->_public.hdr_unpack_func(pRecvMsg, recvMsgLen, &messageHeader, sizeof(messageHeader), &pnf_p7->_public.codec_config); - if (!result) { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n"); - return; - } - - uint8_t m = NFAPI_P7_GET_MORE(messageHeader.m_segment_sequence); - uint8_t sequence_num = NFAPI_P7_GET_SEQUENCE(messageHeader.m_segment_sequence); - uint8_t segment_num = NFAPI_P7_GET_SEGMENT(messageHeader.m_segment_sequence); - - if (pnf_p7->_public.checksum_enabled) { - uint32_t checksum = nfapi_nr_p7_calculate_checksum(pRecvMsg, recvMsgLen); - if (checksum != messageHeader.checksum) { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Checksum verification failed %d %d\n", checksum, messageHeader.checksum); - return; - } - } - - if (m == 0 && segment_num == 0) { - // we have a complete message - // ensure the message is sensible - if (recvMsgLen < 8 || pRecvMsg == NULL) { - NFAPI_TRACE(NFAPI_TRACE_WARN, "Invalid message size: %d, ignoring\n", recvMsgLen); - return; - } - - pnf_nr_dispatch_p7_message(pRecvMsg, recvMsgLen, pnf_p7, rx_hr_time); - } else { - pnf_p7_rx_message_t* rx_msg = pnf_p7_rx_reassembly_queue_add_segment(pnf_p7, - &(pnf_p7->reassembly_queue), - rx_hr_time, - sequence_num, - segment_num, - m, - pRecvMsg, - recvMsgLen); - - if (rx_msg->num_segments_received == rx_msg->num_segments_expected) { - // send the buffer on - uint16_t i = 0; - uint32_t length = 0; - for (i = 0; i < rx_msg->num_segments_expected; ++i) { - length += rx_msg->segments[i].length - (i > 0 ? NFAPI_NR_P7_HEADER_LENGTH : 0); - } - - if (pnf_p7->reassemby_buffer_size < length) { - pnf_p7_free(pnf_p7, pnf_p7->reassemby_buffer); - pnf_p7->reassemby_buffer = 0; - } - - if (pnf_p7->reassemby_buffer == 0) { - NFAPI_TRACE(NFAPI_TRACE_NOTE, "Resizing PNF_P7 Reassembly buffer %d->%d\n", pnf_p7->reassemby_buffer_size, length); - pnf_p7->reassemby_buffer = (uint8_t*)pnf_p7_malloc(pnf_p7, length); - - if (pnf_p7->reassemby_buffer == 0) { - NFAPI_TRACE(NFAPI_TRACE_NOTE, "Failed to allocate PNF_P7 reassemby buffer len:%d\n", length); - return; - } - memset(pnf_p7->reassemby_buffer, 0, length); - pnf_p7->reassemby_buffer_size = length; - } - - uint32_t offset = 0; - for (i = 0; i < rx_msg->num_segments_expected; ++i) { - if (i == 0) { - memcpy(pnf_p7->reassemby_buffer, rx_msg->segments[i].buffer, rx_msg->segments[i].length); - offset += rx_msg->segments[i].length; - } else { - memcpy(pnf_p7->reassemby_buffer + offset, - rx_msg->segments[i].buffer + NFAPI_NR_P7_HEADER_LENGTH, - rx_msg->segments[i].length - NFAPI_NR_P7_HEADER_LENGTH); - offset += rx_msg->segments[i].length - NFAPI_NR_P7_HEADER_LENGTH; - } - } - - pnf_nr_dispatch_p7_message(pnf_p7->reassemby_buffer, length, pnf_p7, rx_msg->rx_hr_time); - - // delete the structure - pnf_p7_rx_reassembly_queue_remove_msg(pnf_p7, &(pnf_p7->reassembly_queue), rx_msg); - } - } - - // The timeout used to be 1000, i.e., 1ms, which is too short. The below 10ms - // is selected to be able to encompass any "reasonable" slot ahead time for the VNF. - // Ideally, we would remove old msg (segments) if we detect packet loss - // (e.g., if the sequence numbers advances sufficiently); in the branch of - // this commit, our goal is to make the PNF work, so we content ourselves to - // just remove very old messages. - pnf_p7_rx_reassembly_queue_remove_old_msgs(pnf_p7, &(pnf_p7->reassembly_queue), rx_hr_time, 10000); -} - - void pnf_nfapi_p7_read_dispatch_message(pnf_p7_t* pnf_p7, uint32_t now_hr_time) { int recvfrom_result = 0; @@ -2499,68 +2313,6 @@ void pnf_nfapi_p7_read_dispatch_message(pnf_p7_t* pnf_p7, uint32_t now_hr_time) while(recvfrom_result > 0); } -void pnf_nr_nfapi_p7_read_dispatch_message(pnf_p7_t* pnf_p7, uint32_t now_hr_time) -{ - int recvfrom_result = 0; - struct sockaddr_in remote_addr; - socklen_t remote_addr_size = sizeof(remote_addr); - remote_addr.sin_family = 2; // hardcoded - do { - // peek the header - uint8_t header_buffer[NFAPI_NR_P7_HEADER_LENGTH]; - recvfrom_result = recvfrom(pnf_p7->p7_sock, - header_buffer, - NFAPI_NR_P7_HEADER_LENGTH, - MSG_DONTWAIT | MSG_PEEK, - (struct sockaddr*)&remote_addr, - &remote_addr_size); - if (recvfrom_result > 0) { - // get the segment size - nfapi_nr_p7_message_header_t header; - pnf_p7->_public.hdr_unpack_func(header_buffer, NFAPI_NR_P7_HEADER_LENGTH, &header, 34, 0); - - // resize the buffer if we have a large segment - if (header.message_length > pnf_p7->rx_message_buffer_size) { - NFAPI_TRACE(NFAPI_TRACE_NOTE, "reallocing rx buffer %d\n", header.message_length); - pnf_p7->rx_message_buffer = realloc(pnf_p7->rx_message_buffer, header.message_length); - pnf_p7->rx_message_buffer_size = header.message_length; - } - - // read the segment - recvfrom_result = recvfrom(pnf_p7->p7_sock, - pnf_p7->rx_message_buffer, - header.message_length, - MSG_DONTWAIT, - (struct sockaddr*)&remote_addr, - &remote_addr_size); - - now_hr_time = pnf_get_current_time_hr(); // moved to here - get closer timestamp??? - - if (recvfrom_result > 0) { - pnf_nr_handle_p7_message(pnf_p7->rx_message_buffer, recvfrom_result, pnf_p7, now_hr_time); - // printf("\npnf_handle_p7_message sfn=%d,slot=%d\n",pnf_p7->sfn,pnf_p7->slot); - } - } else if (recvfrom_result == 0) { - // recv zero length message - recvfrom_result = - recvfrom(pnf_p7->p7_sock, header_buffer, 0, MSG_DONTWAIT, (struct sockaddr*)&remote_addr, &remote_addr_size); - } - - if (recvfrom_result == -1) { - if (errno == EAGAIN || errno == EWOULDBLOCK) { - // return to the select - // NFAPI_TRACE(NFAPI_TRACE_WARN, "%s recvfrom would block :%d\n", __FUNCTION__, errno); - } else { - NFAPI_TRACE(NFAPI_TRACE_WARN, "%s recvfrom failed errno:%d\n", __FUNCTION__, errno); - } - } - - // need to update the time as we would only use the value from the - // select - } while (recvfrom_result > 0); -} - - int pnf_p7_message_pump(pnf_p7_t* pnf_p7) { @@ -2602,7 +2354,7 @@ int pnf_p7_message_pump(pnf_p7_t* pnf_p7) } */ - int iptos_value = FAPI2_IP_DSCP << 2; + int iptos_value = 0; if (setsockopt(pnf_p7->p7_sock, IPPROTO_IP, IP_TOS, &iptos_value, sizeof(iptos_value)) < 0) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "PNF P7 setsockopt (IPPROTO_IP, IP_TOS) failed errno: %d\n", errno); @@ -2720,197 +2472,15 @@ struct timespec pnf_timespec_add(struct timespec lhs, struct timespec rhs) struct timespec pnf_timespec_sub(struct timespec lhs, struct timespec rhs) { struct timespec result; - if ((lhs.tv_nsec-rhs.tv_nsec)<0) + if ((lhs.tv_nsec-rhs.tv_nsec)<0) { result.tv_sec = lhs.tv_sec-rhs.tv_sec-1; result.tv_nsec = 1000000000+lhs.tv_nsec-rhs.tv_nsec; - } - else + } + else { result.tv_sec = lhs.tv_sec-rhs.tv_sec; result.tv_nsec = lhs.tv_nsec-rhs.tv_nsec; } return result; } - -int pnf_nr_p7_message_pump(pnf_p7_t* pnf_p7) -{ - - // initialize the mutex lock - if(pthread_mutex_init(&(pnf_p7->mutex), NULL) != 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "After P7 mutex init: %d\n", errno); - return -1; - } - - if(pthread_mutex_init(&(pnf_p7->pack_mutex), NULL) != 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "After P7 mutex init: %d\n", errno); - return -1; - } - - // create the pnf p7 socket - if ((pnf_p7->p7_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "After P7 socket errno: %d\n", errno); - return -1; - } - NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF P7 socket created (%d)...\n", pnf_p7->p7_sock); - - // configure the UDP socket options - int reuseaddr_enable = 1; - if (setsockopt(pnf_p7->p7_sock, SOL_SOCKET, SO_REUSEADDR, &reuseaddr_enable, sizeof(int)) < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "PNF P7 setsockopt (SOL_SOCKET, SO_REUSEADDR) failed errno: %d\n", errno); - return -1; - } - -/* - int reuseport_enable = 1; - if (setsockopt(pnf_p7->p7_sock, SOL_SOCKET, SO_REUSEPORT, &reuseport_enable, sizeof(int)) < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "PNF P7 setsockopt (SOL_SOCKET, SO_REUSEPORT) failed errno: %d\n", errno); - return -1; - } -*/ - - int iptos_value = FAPI2_IP_DSCP << 2; - if (setsockopt(pnf_p7->p7_sock, IPPROTO_IP, IP_TOS, &iptos_value, sizeof(iptos_value)) < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "PNF P7 setsockopt (IPPROTO_IP, IP_TOS) failed errno: %d\n", errno); - return -1; - } - - struct sockaddr_in addr; - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_port = htons(pnf_p7->_public.local_p7_port); - - if(pnf_p7->_public.local_p7_addr == 0) - { - addr.sin_addr.s_addr = INADDR_ANY; - } - else - { - //addr.sin_addr.s_addr = inet_addr(pnf_p7->_public.local_p7_addr); - if(inet_aton(pnf_p7->_public.local_p7_addr, &addr.sin_addr) == -1) - { - NFAPI_TRACE(NFAPI_TRACE_INFO, "inet_aton failed\n"); - } - } - - - NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF P7 binding %d too %s:%d\n", pnf_p7->p7_sock, inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); - if (bind(pnf_p7->p7_sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "PNF_P7 bind error fd:%d errno: %d\n", pnf_p7->p7_sock, errno); - return -1; - } - NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF P7 bind succeeded...\n"); - - //Initializaing timing structures needed for slot ticking - - struct timespec slot_start; - clock_gettime(CLOCK_MONOTONIC, &slot_start); - - struct timespec pselect_start; - - struct timespec slot_duration; - slot_duration.tv_sec = 0; - slot_duration.tv_nsec = 0.5e6; - - //Infinite loop - - while(pnf_p7->terminate == 0) - { - fd_set rfds; - int selectRetval = 0; - - // select on a timeout and then get the message - FD_ZERO(&rfds); - FD_SET(pnf_p7->p7_sock, &rfds); - - struct timespec timeout; - timeout.tv_sec = 100; - timeout.tv_nsec = 0; - clock_gettime(CLOCK_MONOTONIC, &pselect_start); - - //setting the timeout - - if((pselect_start.tv_sec > slot_start.tv_sec) || ((pselect_start.tv_sec == slot_start.tv_sec) && (pselect_start.tv_nsec > slot_start.tv_nsec))) - { - // overran the end of the subframe we do not want to wait - timeout.tv_sec = 0; - timeout.tv_nsec = 0; - - //struct timespec overrun = pnf_timespec_sub(pselect_start, sf_start); - //NFAPI_TRACE(NFAPI_TRACE_INFO, "Subframe overrun detected of %d.%d running to catchup\n", overrun.tv_sec, overrun.tv_nsec); - } - else - { - // still time before the end of the subframe wait - timeout = pnf_timespec_sub(slot_start, pselect_start); - } - - selectRetval = pselect(pnf_p7->p7_sock+1, &rfds, NULL, NULL, &timeout, NULL); - - uint32_t now_hr_time = pnf_get_current_time_hr(); - - - - - if(selectRetval == 0) - { - // timeout - - //update slot start timing - slot_start = pnf_timespec_add(slot_start, slot_duration); - - //increment sfn/slot - if (++pnf_p7->slot == 20) - { - pnf_p7->slot = 0; - pnf_p7->sfn = (pnf_p7->sfn + 1) % 1024; - } - - continue; - } - else if (selectRetval == -1 && (errno == EINTR)) - { - // interrupted by signal - NFAPI_TRACE(NFAPI_TRACE_WARN, "PNF P7 Signal Interrupt %d\n", errno); - continue; - } - else if (selectRetval == -1) - { - NFAPI_TRACE(NFAPI_TRACE_WARN, "PNF P7 select() failed\n"); - sleep(1); - continue; - } - - if(FD_ISSET(pnf_p7->p7_sock, &rfds)) - - { - pnf_nr_nfapi_p7_read_dispatch_message(pnf_p7, now_hr_time); - } - } - NFAPI_TRACE(NFAPI_TRACE_ERROR, "PNF_P7 Terminating..\n"); - - // close the connection and socket - if (close(pnf_p7->p7_sock) < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "close failed errno: %d\n", errno); - } - - if(pthread_mutex_destroy(&(pnf_p7->pack_mutex)) != 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "mutex destroy failed errno: %d\n", errno); - } - - if(pthread_mutex_destroy(&(pnf_p7->mutex)) != 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "mutex destroy failed errno: %d\n", errno); - } - - return 0; -} diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c b/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c index 06d268a875..b021e67fc9 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c @@ -74,20 +74,7 @@ int nfapi_pnf_p7_start(nfapi_pnf_p7_config_t* config) return 0; } -int nfapi_nr_pnf_p7_start(nfapi_pnf_p7_config_t* config) -{ - // Verify that config is not null - if(config == 0) - return -1; - pnf_p7_t* _this = (pnf_p7_t*)(config); - - NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__); - - pnf_nr_p7_message_pump(_this); - - return 0; -} int nfapi_pnf_p7_stop(nfapi_pnf_p7_config_t* config) From 20f4951bfe7a141e1cde87ae3957b610eaf4a5ac Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Fri, 27 Jun 2025 11:04:37 +0200 Subject: [PATCH 097/964] CI: use CN with NAS ciphering + integrity in OAIUE and SA-2x2 pipelines --- ci-scripts/ci_infra.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ci-scripts/ci_infra.yaml b/ci-scripts/ci_infra.yaml index 1f040c33ff..cda6258244 100644 --- a/ci-scripts/ci_infra.yaml +++ b/ci-scripts/ci_infra.yaml @@ -65,9 +65,9 @@ oc-cn5g: Host: avra NetworkScript: echo "inet 172.21.6.102" RunIperf3Server: False - Deploy: "! scripts/oc-cn5g-deploy.sh /opt/oai-cn5g-fed-develop-2025-jan oaicicd-core-for-ci-ran" - Undeploy: "! scripts/oc-cn5g-undeploy.sh /opt/oai-cn5g-fed-develop-2025-jan oaicicd-core-for-ci-ran" - LogCollect: "! scripts/oc-cn5g-logcollect.sh /opt/oai-cn5g-fed-develop-2025-jan oaicicd-core-for-ci-ran %%log_dir%%" + Deploy: "! scripts/oc-cn5g-deploy.sh /opt/oai-cn5g-fed-develop-2025-jun oaicicd-core-for-ci-ran" + Undeploy: "! scripts/oc-cn5g-undeploy.sh /opt/oai-cn5g-fed-develop-2025-jun oaicicd-core-for-ci-ran" + LogCollect: "! scripts/oc-cn5g-logcollect.sh /opt/oai-cn5g-fed-develop-2025-jun oaicicd-core-for-ci-ran %%log_dir%%" oc-cn5g-20897: Host: cacofonix @@ -89,8 +89,8 @@ matix-cn5g: Host: matix NetworkScript: docker exec prod-trf-gen ip a show dev eth0 RunIperf3Server: False - Deploy: "cd /opt/oai-cn5g-fed-v2/docker-compose && python3 ./core-network.py --type start-basic" - Undeploy: "cd /opt/oai-cn5g-fed-v2/docker-compose && python3 ./core-network.py --type stop-basic" + Deploy: "cd /opt/oai-cn5g-fed-v2-jun-2025/docker-compose && python3 ./core-network.py --type start-basic" + Undeploy: "cd /opt/oai-cn5g-fed-v2-jun-2025/docker-compose && python3 ./core-network.py --type stop-basic" LogCollect: - "docker logs oai-smf > %%log_dir%%/oai-smf.log" - "docker logs oai-amf > %%log_dir%%/oai-amf.log" From b19dff31e17d40f0dfacf6228a9114ab93938d6f Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 20 Jun 2025 07:58:19 +0200 Subject: [PATCH 098/964] Print gNB MAC stats in phy-test mode as well There is no PRACH, so the condition to print stats would never be reached. Fixes: 0301b239a264 ("print stats only after scheduler started") --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c index dfe4cfeea2..09734d8215 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c @@ -195,7 +195,7 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frame, slot_t slo } bool wait_prach_completed = gNB->num_scheduled_prach_rx >= NUM_PRACH_RX_FOR_NOISE_ESTIMATE; - if (wait_prach_completed && (slot == 0) && (frame & 127) == 0) { + if ((wait_prach_completed || get_softmodem_params()->phy_test) && (slot == 0) && (frame & 127) == 0) { char stats_output[32656] = {0}; dump_mac_stats(gNB, stats_output, sizeof(stats_output), true); LOG_I(NR_MAC, "Frame.Slot %d.%d\n%s\n", frame, slot, stats_output); From d1541a83296bad22ab657d77ee9aefb1aab68aef Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 27 May 2025 19:24:25 +0200 Subject: [PATCH 099/964] Remove useless parameter for UE context setup response callback --- openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c | 2 +- openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h | 2 +- openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c | 5 +---- openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c | 5 +---- 4 files changed, 4 insertions(+), 10 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c index 5d7642c815..691a161c0a 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -712,7 +712,7 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req) DevAssert(resp.du_to_cu_rrc_information != NULL); DevAssert(resp.rrc_container == NULL && resp.rrc_container_length == 0); - mac->mac_rrc.ue_context_setup_response(req, &resp); + mac->mac_rrc.ue_context_setup_response(&resp); /* free the memory we allocated above */ free(resp.srbs_to_be_setup); diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h index 1e416f01f9..afce935185 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h @@ -31,7 +31,7 @@ typedef void (*f1_reset_acknowledge_cu_initiated_func_t)(const f1ap_reset_ack_t typedef void (*f1_setup_request_func_t)(const f1ap_setup_req_t* req); typedef void (*gnb_du_configuration_update_t)(const f1ap_gnb_du_configuration_update_t *upd); -typedef void (*ue_context_setup_response_func_t)(const f1ap_ue_context_setup_t* req, const f1ap_ue_context_setup_t *resp); +typedef void (*ue_context_setup_response_func_t)(const f1ap_ue_context_setup_t *resp); typedef void (*ue_context_modification_response_func_t)(const f1ap_ue_context_modif_req_t *req, const f1ap_ue_context_modif_resp_t *resp); typedef void (*ue_context_modification_required_func_t)(const f1ap_ue_context_modif_required_t *t); diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c index e687991a5e..ae672b5bfd 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c @@ -58,11 +58,8 @@ static void gnb_du_configuration_update_direct(const f1ap_gnb_du_configuration_u itti_send_msg_to_task(TASK_RRC_GNB, 0, msg); } -static void ue_context_setup_response_direct(const f1ap_ue_context_setup_t *req, const f1ap_ue_context_setup_t *resp) +static void ue_context_setup_response_direct(const f1ap_ue_context_setup_t *resp) { - DevAssert(req->drbs_to_be_setup_length == resp->drbs_to_be_setup_length); - - (void) req; /* we don't need the request -- it is to set up GTP in F1 case */ MessageDef *msg = itti_alloc_new_message (TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_SETUP_RESP); msg->ittiMsgHeader.originInstance = -1; // means monolithic f1ap_ue_context_setup_t *f1ap_msg = &F1AP_UE_CONTEXT_SETUP_RESP(msg); diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c index 81373e0bc9..85a790b852 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c @@ -85,11 +85,8 @@ static void gnb_du_configuration_update_f1ap(const f1ap_gnb_du_configuration_upd itti_send_msg_to_task(TASK_DU_F1, 0, msg); } -static void ue_context_setup_response_f1ap(const f1ap_ue_context_setup_t *req, const f1ap_ue_context_setup_t *resp) +static void ue_context_setup_response_f1ap(const f1ap_ue_context_setup_t *resp) { - DevAssert(req->drbs_to_be_setup_length == resp->drbs_to_be_setup_length); - - DevAssert(req->srbs_to_be_setup_length == resp->srbs_to_be_setup_length); MessageDef *msg = itti_alloc_new_message (TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_SETUP_RESP); f1ap_ue_context_setup_t *f1ap_msg = &F1AP_UE_CONTEXT_SETUP_RESP(msg); /* copy all fields, but reallocate rrc_containers! */ From 8a772d362f791ab617a3e064d701b02f8158e506 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 17 Jun 2025 19:13:30 +0200 Subject: [PATCH 100/964] Remove useless parameter for UE context modification response callback --- openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c | 2 +- openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h | 3 +-- openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c | 4 +--- openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c | 2 +- 4 files changed, 4 insertions(+), 7 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c index 691a161c0a..ed706d51f8 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -838,7 +838,7 @@ void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req) // resp.du_to_cu_rrc_information can be either NULL or not DevAssert(resp.rrc_container == NULL && resp.rrc_container_length == 0); - mac->mac_rrc.ue_context_modification_response(req, &resp); + mac->mac_rrc.ue_context_modification_response(&resp); /* free the memory we allocated above */ free(resp.srbs_to_be_setup); diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h index afce935185..6681b96032 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h @@ -32,8 +32,7 @@ typedef void (*f1_setup_request_func_t)(const f1ap_setup_req_t* req); typedef void (*gnb_du_configuration_update_t)(const f1ap_gnb_du_configuration_update_t *upd); typedef void (*ue_context_setup_response_func_t)(const f1ap_ue_context_setup_t *resp); -typedef void (*ue_context_modification_response_func_t)(const f1ap_ue_context_modif_req_t *req, - const f1ap_ue_context_modif_resp_t *resp); +typedef void (*ue_context_modification_response_func_t)(const f1ap_ue_context_modif_resp_t *resp); typedef void (*ue_context_modification_required_func_t)(const f1ap_ue_context_modif_required_t *t); typedef void (*ue_context_release_request_func_t)(const f1ap_ue_context_release_req_t* req); typedef void (*ue_context_release_complete_func_t)(const f1ap_ue_context_release_complete_t *complete); diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c index ae672b5bfd..65e56aee10 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c @@ -93,10 +93,8 @@ static void ue_context_setup_response_direct(const f1ap_ue_context_setup_t *resp itti_send_msg_to_task(TASK_RRC_GNB, 0, msg); } -static void ue_context_modification_response_direct(const f1ap_ue_context_modif_req_t *req, - const f1ap_ue_context_modif_resp_t *resp) +static void ue_context_modification_response_direct(const f1ap_ue_context_modif_resp_t *resp) { - (void)req; /* we don't need the request -- it is to set up GTP in F1 case */ MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_MODIFICATION_RESP); msg->ittiMsgHeader.originInstance = -1; // means monolithic f1ap_ue_context_modif_resp_t *f1ap_msg = &F1AP_UE_CONTEXT_MODIFICATION_RESP(msg); diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c index 85a790b852..deb160a1a6 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c @@ -123,7 +123,7 @@ static void ue_context_setup_response_f1ap(const f1ap_ue_context_setup_t *resp) itti_send_msg_to_task(TASK_DU_F1, 0, msg); } -static void ue_context_modification_response_f1ap(const f1ap_ue_context_modif_req_t *req, const f1ap_ue_context_modif_resp_t *resp) +static void ue_context_modification_response_f1ap(const f1ap_ue_context_modif_resp_t *resp) { MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_MODIFICATION_RESP); f1ap_ue_context_modif_resp_t *f1ap_msg = &F1AP_UE_CONTEXT_MODIFICATION_RESP(msg); From e4857991fc7f62097191bd3bfe8bf673825595fc Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 30 May 2025 18:14:52 +0200 Subject: [PATCH 101/964] F1 PRINT_ERROR(): show file/line no for debuggability Somewhat align with the E1 PRINT_ERROR(), but extend with information. --- openair2/F1AP/lib/f1ap_lib_common.h | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/openair2/F1AP/lib/f1ap_lib_common.h b/openair2/F1AP/lib/f1ap_lib_common.h index 8a3ddfba4a..162476a182 100644 --- a/openair2/F1AP/lib/f1ap_lib_common.h +++ b/openair2/F1AP/lib/f1ap_lib_common.h @@ -32,21 +32,17 @@ #include "f1ap_messages_types.h" #ifdef ENABLE_TESTS - #define PRINT_ERROR(...) fprintf(stderr, ##__VA_ARGS__) + #define PRINT_ERROR(fmt, ...) fprintf(stderr, "%s:%d: " fmt, __FILE__, __LINE__, ##__VA_ARGS__) #else #define PRINT_ERROR(...) // Do nothing #endif -#define _F1_EQ_CHECK_GENERIC(condition, fmt, ...) \ - do { \ - if (!(condition)) { \ - PRINT_ERROR("F1 Equality Check failure: %s:%d: Condition '%s' failed: " fmt " != " fmt "\n", \ - __FILE__, \ - __LINE__, \ - #condition, \ - ##__VA_ARGS__); \ - return false; \ - } \ +#define _F1_EQ_CHECK_GENERIC(condition, fmt, ...) \ + do { \ + if (!(condition)) { \ + PRINT_ERROR("Equality condition '%s' failed: " fmt " != " fmt "\n", #condition, ##__VA_ARGS__); \ + return false; \ + } \ } while (0) #define _F1_EQ_CHECK_LONG(A, B) _F1_EQ_CHECK_GENERIC(A == B, "%ld", A, B); From 9f0373e051c3283f6aa85dbdd5b4830019a6dc64 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 6 May 2025 11:00:05 +0200 Subject: [PATCH 102/964] F1AP lib: introduce macros to simplify implementation Introduce generic _F1_CHECK_EXP(), which is like the macros for checking values (_F1_EQ_CHECK_INT() etc). Reuse the same for introducing _F1_EQ_CHECK_OPTIONAL_IE that will be used to write the check for optional fields more concisely. CP_OPT_BYTE_ARRAY() FREE_OPT_BYTE_ARRAY() are macros to wrap handling of optional byte arrays. _F1_MALLOC() simplifies allocations and is similar to asn1cCallocOne(), but provided to avoid confusion (since more than ASN.1 structures will use it). All will be used in the following commits. --- openair2/F1AP/lib/f1ap_lib_common.h | 39 +++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/openair2/F1AP/lib/f1ap_lib_common.h b/openair2/F1AP/lib/f1ap_lib_common.h index 162476a182..358a2d5eaf 100644 --- a/openair2/F1AP/lib/f1ap_lib_common.h +++ b/openair2/F1AP/lib/f1ap_lib_common.h @@ -27,6 +27,7 @@ #include #include "openair3/UTILS/conversions.h" #include "common/5g_platform_types.h" +#include "common/utils/ds/byte_array.h" #include "F1AP_Cause.h" #include "f1ap_messages_types.h" @@ -49,6 +50,21 @@ #define _F1_EQ_CHECK_INT(A, B) _F1_EQ_CHECK_GENERIC(A == B, "%d", A, B); #define _F1_EQ_CHECK_STR(A, B) _F1_EQ_CHECK_GENERIC(strcmp(A, B) == 0, "'%s'", A, B); +#define _F1_CHECK_EXP(EXP) \ + do { \ + if (!(EXP)) { \ + PRINT_ERROR("Failed at " #EXP "\n"); \ + return false; \ + } \ + } while (0) + +#define _F1_EQ_CHECK_OPTIONAL_IE(A, B, FIELD, EQ_MACRO) \ + do { \ + _F1_CHECK_EXP(((A)->FIELD && (B)->FIELD) || (!(A)->FIELD && !(B)->FIELD)); \ + if ((A)->FIELD && (B)->FIELD) \ + EQ_MACRO(*(A)->FIELD, *(B)->FIELD); \ + } while (0) + /* macro to look up IE. If mandatory and not found, macro will print * descriptive debug message to stderr and force exit in calling function */ #define F1AP_LIB_FIND_IE(IE_TYPE, ie, container, IE_ID, mandatory) \ @@ -68,6 +84,29 @@ } \ } while (0) +#define CP_OPT_BYTE_ARRAY(dst, src) \ + do { \ + if (src) { \ + dst = calloc_or_fail(1, sizeof(*dst)); \ + *(dst) = copy_byte_array(*(src)); \ + } \ + } while (0) + +#define FREE_OPT_BYTE_ARRAY(a) \ + do { \ + if (a) { \ + free_byte_array(*(a)); \ + } \ + free(a); \ + } while (0) + +/* similar to asn1cCallocOne(), duplicated to not confuse with asn.1 types */ +#define _F1_MALLOC(VaR, VaLue) \ + do { \ + VaR = malloc_or_fail(sizeof(*VaR)); \ + *VaR = VaLue; \ + } while (0) + bool eq_f1ap_plmn(const plmn_id_t *a, const plmn_id_t *b); struct f1ap_served_cell_info_t; bool eq_f1ap_cell_info(const struct f1ap_served_cell_info_t *a, const struct f1ap_served_cell_info_t *b); From e991f26ff1575427b45edfb5487926efb492ea68 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sat, 24 May 2025 12:43:42 +0200 Subject: [PATCH 103/964] Factor out NSSAI, to be used in other messages lates --- openair2/F1AP/lib/f1ap_interface_management.c | 13 ++-------- openair2/F1AP/lib/f1ap_lib_common.c | 24 ++++++++++++++++++- openair2/F1AP/lib/f1ap_lib_common.h | 4 ++++ 3 files changed, 29 insertions(+), 12 deletions(-) diff --git a/openair2/F1AP/lib/f1ap_interface_management.c b/openair2/F1AP/lib/f1ap_interface_management.c index 0ac1f8d63a..e6d863f7a3 100644 --- a/openair2/F1AP/lib/f1ap_interface_management.c +++ b/openair2/F1AP/lib/f1ap_interface_management.c @@ -394,11 +394,7 @@ static int read_slice_info(const F1AP_ServedPLMNs_Item_t *plmn, nssai_t *nssai, AssertFatal(ssl->list.count <= max_nssai, "cannot handle more than 16 slices\n"); for (int s = 0; s < ssl->list.count; ++s) { const F1AP_SliceSupportItem_t *sl = ssl->list.array[s]; - nssai_t *n = &nssai[s]; - OCTET_STRING_TO_INT8(&sl->sNSSAI.sST, n->sst); - n->sd = 0xffffff; - if (sl->sNSSAI.sD != NULL) - OCTET_STRING_TO_INT24(sl->sNSSAI.sD, n->sd); + nssai[s] = decode_nssai(&sl->sNSSAI); } return ssl->list.count; @@ -418,12 +414,7 @@ static F1AP_ProtocolExtensionContainer_10696P34_t *write_slice_info(int num_ssi, for (int s = 0; s < num_ssi; s++) { asn1cSequenceAdd(slice_support_list->list, F1AP_SliceSupportItem_t, slice); - const nssai_t *n = &nssai[s]; - INT8_TO_OCTET_STRING(n->sst, &slice->sNSSAI.sST); - if (n->sd != 0xffffff) { - asn1cCalloc(slice->sNSSAI.sD, tmp); - INT24_TO_OCTET_STRING(n->sd, tmp); - } + slice->sNSSAI = encode_nssai(&nssai[s]); } return p; diff --git a/openair2/F1AP/lib/f1ap_lib_common.c b/openair2/F1AP/lib/f1ap_lib_common.c index e32f7e6779..0e1d07a71d 100644 --- a/openair2/F1AP/lib/f1ap_lib_common.c +++ b/openair2/F1AP/lib/f1ap_lib_common.c @@ -25,7 +25,7 @@ #include "OCTET_STRING.h" #include "common/utils/utils.h" #include "common/utils/assertions.h" -#include "common/utils/utils.h" +#include "common/utils/oai_asn1.h" bool eq_f1ap_plmn(const plmn_id_t *a, const plmn_id_t *b) { @@ -115,6 +115,28 @@ uint8_t *cp_octet_string(const OCTET_STRING_t *os, int *len) return buf; } +F1AP_SNSSAI_t encode_nssai(const nssai_t *nssai) +{ + F1AP_SNSSAI_t enc = {0}; + INT8_TO_OCTET_STRING(nssai->sst, &enc.sST); + // see 23.003 sec. 28.4.2: 0xffffff means "no SD" + if (nssai->sd != 0xffffff) { + asn1cCalloc(enc.sD, tmp); + INT24_TO_OCTET_STRING(nssai->sd, tmp); + } + return enc; +} + +nssai_t decode_nssai(const F1AP_SNSSAI_t *nssai) +{ + // see 23.003 sec. 28.4.2: 0xffffff means "no SD" + nssai_t dec = { .sd = 0xffffff, }; + OCTET_STRING_TO_INT8(&nssai->sST, dec.sst); + if (nssai->sD != NULL) + OCTET_STRING_TO_INT24(nssai->sD, dec.sd); + return dec; +} + F1AP_Cause_t encode_f1ap_cause(f1ap_Cause_t cause, long cause_value) { F1AP_Cause_t f1_cause = {0}; diff --git a/openair2/F1AP/lib/f1ap_lib_common.h b/openair2/F1AP/lib/f1ap_lib_common.h index 358a2d5eaf..6a50ba45b2 100644 --- a/openair2/F1AP/lib/f1ap_lib_common.h +++ b/openair2/F1AP/lib/f1ap_lib_common.h @@ -30,6 +30,7 @@ #include "common/utils/ds/byte_array.h" #include "F1AP_Cause.h" +#include "F1AP_SNSSAI.h" #include "f1ap_messages_types.h" #ifdef ENABLE_TESTS @@ -120,6 +121,9 @@ bool eq_f1ap_tx_bandwidth(const struct f1ap_transmission_bandwidth_t *a, const s struct OCTET_STRING; uint8_t *cp_octet_string(const struct OCTET_STRING *os, int *len); +F1AP_SNSSAI_t encode_nssai(const nssai_t *nssai); +nssai_t decode_nssai(const F1AP_SNSSAI_t *nssai); + F1AP_Cause_t encode_f1ap_cause(f1ap_Cause_t cause, long cause_value); bool decode_f1ap_cause(F1AP_Cause_t f1_cause, f1ap_Cause_t *cause, long *cause_value); From 3a4440a99cc3b79d2a505cd1c64e5148fb8f71b4 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 26 May 2025 11:10:52 +0200 Subject: [PATCH 104/964] Generalize F1AP_LIB_FIND_IE() to work with list container F1AP_LIB_FIND_IE() is used to look up elements in a list, but was hitherto hardcoded to use "protocolIEs" as an intermediate struct. A follow-up commit will use this macro where we don't have protocolIEs, but "iE_Extensions". Hence, modify to make it work for that case (and others) as well. --- openair2/F1AP/lib/f1ap_interface_management.c | 30 ++++++++-------- openair2/F1AP/lib/f1ap_lib_common.h | 6 ++-- openair2/F1AP/lib/f1ap_rrc_message_transfer.c | 35 ++++++++++--------- 3 files changed, 36 insertions(+), 35 deletions(-) diff --git a/openair2/F1AP/lib/f1ap_interface_management.c b/openair2/F1AP/lib/f1ap_interface_management.c index e6d863f7a3..cc2b5b3160 100644 --- a/openair2/F1AP/lib/f1ap_interface_management.c +++ b/openair2/F1AP/lib/f1ap_interface_management.c @@ -156,9 +156,9 @@ bool decode_f1ap_reset(const F1AP_F1AP_PDU_t *pdu, f1ap_reset_t *out) /* Check presence of mandatory IEs */ F1AP_Reset_t *in = &pdu->choice.initiatingMessage->value.choice.Reset; F1AP_ResetIEs_t *ie; - F1AP_LIB_FIND_IE(F1AP_ResetIEs_t, ie, in, F1AP_ProtocolIE_ID_id_TransactionID, true); - F1AP_LIB_FIND_IE(F1AP_ResetIEs_t, ie, in, F1AP_ProtocolIE_ID_id_Cause, true); - F1AP_LIB_FIND_IE(F1AP_ResetIEs_t, ie, in, F1AP_ProtocolIE_ID_id_ResetType, true); + F1AP_LIB_FIND_IE(F1AP_ResetIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_TransactionID, true); + F1AP_LIB_FIND_IE(F1AP_ResetIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_Cause, true); + F1AP_LIB_FIND_IE(F1AP_ResetIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_ResetType, true); /* Loop over all IEs */ for (int i = 0; i < in->protocolIEs.list.count; i++) { @@ -303,7 +303,7 @@ bool decode_f1ap_reset_ack(const struct F1AP_F1AP_PDU *pdu, f1ap_reset_ack_t *ou /* Check presence of mandatory IEs */ F1AP_ResetAcknowledge_t *in = &pdu->choice.successfulOutcome->value.choice.ResetAcknowledge; F1AP_ResetAcknowledgeIEs_t *ie; - F1AP_LIB_FIND_IE(F1AP_ResetAcknowledgeIEs_t, ie, in, F1AP_ProtocolIE_ID_id_TransactionID, true); + F1AP_LIB_FIND_IE(F1AP_ResetAcknowledgeIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_TransactionID, true); /* Loop over all IEs */ for (int i = 0; i < in->protocolIEs.list.count; i++) { @@ -813,9 +813,9 @@ bool decode_f1ap_setup_request(const F1AP_F1AP_PDU_t *pdu, f1ap_setup_req_t *out /* Check presence of mandatory IEs */ F1AP_F1SetupRequest_t *in = &pdu->choice.initiatingMessage->value.choice.F1SetupRequest; F1AP_F1SetupRequestIEs_t *ie; - F1AP_LIB_FIND_IE(F1AP_F1SetupRequestIEs_t, ie, in, F1AP_ProtocolIE_ID_id_TransactionID, true); - F1AP_LIB_FIND_IE(F1AP_F1SetupRequestIEs_t, ie, in, F1AP_ProtocolIE_ID_id_gNB_DU_ID, true); - F1AP_LIB_FIND_IE(F1AP_F1SetupRequestIEs_t, ie, in, F1AP_ProtocolIE_ID_id_GNB_DU_RRC_Version, true); + F1AP_LIB_FIND_IE(F1AP_F1SetupRequestIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_TransactionID, true); + F1AP_LIB_FIND_IE(F1AP_F1SetupRequestIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_DU_ID, true); + F1AP_LIB_FIND_IE(F1AP_F1SetupRequestIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_GNB_DU_RRC_Version, true); /* Loop over all IEs */ for (int i = 0; i < in->protocolIEs.list.count; i++) { AssertError(in->protocolIEs.list.array[i] != NULL, return false, "in->protocolIEs.list.array[i] is NULL"); @@ -1086,8 +1086,8 @@ bool decode_f1ap_setup_response(const F1AP_F1AP_PDU_t *pdu, f1ap_setup_resp_t *o /* Check presence of mandatory IEs */ F1AP_F1SetupResponse_t *in = &pdu->choice.successfulOutcome->value.choice.F1SetupResponse; F1AP_F1SetupResponseIEs_t *ie; - F1AP_LIB_FIND_IE(F1AP_F1SetupResponseIEs_t, ie, in, F1AP_ProtocolIE_ID_id_TransactionID, true); - F1AP_LIB_FIND_IE(F1AP_F1SetupResponseIEs_t, ie, in, F1AP_ProtocolIE_ID_id_GNB_CU_RRC_Version, true); + F1AP_LIB_FIND_IE(F1AP_F1SetupResponseIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_TransactionID, true); + F1AP_LIB_FIND_IE(F1AP_F1SetupResponseIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_GNB_CU_RRC_Version, true); /* Loop over all IEs */ for (int i = 0; i < in->protocolIEs.list.count; i++) { ie = in->protocolIEs.list.array[i]; @@ -1297,8 +1297,8 @@ bool decode_f1ap_setup_failure(const F1AP_F1AP_PDU_t *pdu, f1ap_setup_failure_t F1AP_F1SetupFailureIEs_t *ie; F1AP_F1SetupFailure_t *in = &pdu->choice.unsuccessfulOutcome->value.choice.F1SetupFailure; /* Check presence of mandatory IEs */ - F1AP_LIB_FIND_IE(F1AP_F1SetupFailureIEs_t, ie, in, F1AP_ProtocolIE_ID_id_TransactionID, true); - F1AP_LIB_FIND_IE(F1AP_F1SetupFailureIEs_t, ie, in, F1AP_ProtocolIE_ID_id_Cause, true); + F1AP_LIB_FIND_IE(F1AP_F1SetupFailureIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_TransactionID, true); + F1AP_LIB_FIND_IE(F1AP_F1SetupFailureIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_Cause, true); /* Loop over all IEs */ for (int i = 0; i < in->protocolIEs.list.count; i++) { ie = in->protocolIEs.list.array[i]; @@ -1494,7 +1494,7 @@ bool decode_f1ap_du_configuration_update(const F1AP_F1AP_PDU_t *pdu, f1ap_gnb_du F1AP_GNBDUConfigurationUpdate_t *in = &pdu->choice.initiatingMessage->value.choice.GNBDUConfigurationUpdate; F1AP_GNBDUConfigurationUpdateIEs_t *ie; /* Check mandatory IEs */ - F1AP_LIB_FIND_IE(F1AP_GNBDUConfigurationUpdateIEs_t, ie, in, F1AP_ProtocolIE_ID_id_TransactionID, true); + F1AP_LIB_FIND_IE(F1AP_GNBDUConfigurationUpdateIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_TransactionID, true); /* Loop over all IEs */ for (int i = 0; i < in->protocolIEs.list.count; i++) { AssertError(in->protocolIEs.list.array[i] != NULL, return false, "in->protocolIEs.list.array[i] is NULL"); @@ -1751,7 +1751,7 @@ bool decode_f1ap_cu_configuration_update(const F1AP_F1AP_PDU_t *pdu, f1ap_gnb_cu /* Check presence of mandatory IEs */ F1AP_GNBCUConfigurationUpdate_t *in = &pdu->choice.initiatingMessage->value.choice.GNBCUConfigurationUpdate; F1AP_GNBCUConfigurationUpdateIEs_t *ie; - F1AP_LIB_FIND_IE(F1AP_GNBCUConfigurationUpdateIEs_t, ie, in, F1AP_ProtocolIE_ID_id_TransactionID, true); + F1AP_LIB_FIND_IE(F1AP_GNBCUConfigurationUpdateIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_TransactionID, true); /* Loop over all IEs */ for (int i = 0; i < in->protocolIEs.list.count; i++) { ie = in->protocolIEs.list.array[i]; @@ -1903,7 +1903,7 @@ bool decode_f1ap_cu_configuration_update_acknowledge(const F1AP_F1AP_PDU_t *pdu, F1AP_GNBCUConfigurationUpdateAcknowledge_t *in = &pdu->choice.successfulOutcome->value.choice.GNBCUConfigurationUpdateAcknowledge; F1AP_GNBCUConfigurationUpdateAcknowledgeIEs_t *ie; /* Check mandatory IEs */ - F1AP_LIB_FIND_IE(F1AP_GNBCUConfigurationUpdateAcknowledgeIEs_t, ie, in, F1AP_ProtocolIE_ID_id_TransactionID, true); + F1AP_LIB_FIND_IE(F1AP_GNBCUConfigurationUpdateAcknowledgeIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_TransactionID, true); /* Loop over all IEs */ for (int i = 0; i < in->protocolIEs.list.count; i++) { ie = in->protocolIEs.list.array[i]; @@ -2079,7 +2079,7 @@ bool decode_f1ap_du_configuration_update_acknowledge(const F1AP_F1AP_PDU_t *pdu, F1AP_GNBDUConfigurationUpdateAcknowledge_t *in = &pdu->choice.successfulOutcome->value.choice.GNBDUConfigurationUpdateAcknowledge; F1AP_GNBDUConfigurationUpdateAcknowledgeIEs_t *ie; /* Check mandatory IEs */ - F1AP_LIB_FIND_IE(F1AP_GNBDUConfigurationUpdateAcknowledgeIEs_t, ie, in, F1AP_ProtocolIE_ID_id_TransactionID, true); + F1AP_LIB_FIND_IE(F1AP_GNBDUConfigurationUpdateAcknowledgeIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_TransactionID, true); /* Loop over all IEs */ for (int i = 0; i < in->protocolIEs.list.count; i++) { ie = in->protocolIEs.list.array[i]; diff --git a/openair2/F1AP/lib/f1ap_lib_common.h b/openair2/F1AP/lib/f1ap_lib_common.h index 6a50ba45b2..b49fad88c1 100644 --- a/openair2/F1AP/lib/f1ap_lib_common.h +++ b/openair2/F1AP/lib/f1ap_lib_common.h @@ -68,12 +68,10 @@ /* macro to look up IE. If mandatory and not found, macro will print * descriptive debug message to stderr and force exit in calling function */ -#define F1AP_LIB_FIND_IE(IE_TYPE, ie, container, IE_ID, mandatory) \ +#define F1AP_LIB_FIND_IE(IE_TYPE, ie, IE_LIST, IE_ID, mandatory) \ do { \ ie = NULL; \ - for (IE_TYPE **ptr = container->protocolIEs.list.array; \ - ptr < &container->protocolIEs.list.array[container->protocolIEs.list.count]; \ - ptr++) { \ + for (IE_TYPE **ptr = (IE_LIST)->array; ptr < &(IE_LIST)->array[(IE_LIST)->count]; ptr++) { \ if ((*ptr)->id == IE_ID) { \ ie = *ptr; \ break; \ diff --git a/openair2/F1AP/lib/f1ap_rrc_message_transfer.c b/openair2/F1AP/lib/f1ap_rrc_message_transfer.c index 5fc9e2d622..c2f6e780aa 100644 --- a/openair2/F1AP/lib/f1ap_rrc_message_transfer.c +++ b/openair2/F1AP/lib/f1ap_rrc_message_transfer.c @@ -114,26 +114,27 @@ bool decode_initial_ul_rrc_message_transfer(const F1AP_F1AP_PDU_t *pdu, f1ap_ini memset(out, 0, sizeof(*out)); F1AP_InitialULRRCMessageTransfer_t *container = &pdu->choice.initiatingMessage->value.choice.InitialULRRCMessageTransfer; + F1AP_ProtocolIE_Container_10659P31_t *pIEs = &container->protocolIEs; F1AP_InitialULRRCMessageTransferIEs_t *ie; - F1AP_LIB_FIND_IE(F1AP_InitialULRRCMessageTransferIEs_t, ie, container, F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); + F1AP_LIB_FIND_IE(F1AP_InitialULRRCMessageTransferIEs_t, ie, &pIEs->list, F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); out->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; - F1AP_LIB_FIND_IE(F1AP_InitialULRRCMessageTransferIEs_t, ie, container, F1AP_ProtocolIE_ID_id_NRCGI, true); + F1AP_LIB_FIND_IE(F1AP_InitialULRRCMessageTransferIEs_t, ie, &pIEs->list, F1AP_ProtocolIE_ID_id_NRCGI, true); PLMNID_TO_MCC_MNC(&ie->value.choice.NRCGI.pLMN_Identity, out->plmn.mcc, out->plmn.mnc, out->plmn.mnc_digit_length); BIT_STRING_TO_NR_CELL_IDENTITY(&ie->value.choice.NRCGI.nRCellIdentity, out->nr_cellid); - F1AP_LIB_FIND_IE(F1AP_InitialULRRCMessageTransferIEs_t, ie, container, F1AP_ProtocolIE_ID_id_C_RNTI, true); + F1AP_LIB_FIND_IE(F1AP_InitialULRRCMessageTransferIEs_t, ie, &pIEs->list, F1AP_ProtocolIE_ID_id_C_RNTI, true); out->crnti = ie->value.choice.C_RNTI; - F1AP_LIB_FIND_IE(F1AP_InitialULRRCMessageTransferIEs_t, ie, container, F1AP_ProtocolIE_ID_id_RRCContainer, true); + F1AP_LIB_FIND_IE(F1AP_InitialULRRCMessageTransferIEs_t, ie, &pIEs->list, F1AP_ProtocolIE_ID_id_RRCContainer, true); out->rrc_container = cp_octet_string(&ie->value.choice.RRCContainer, &out->rrc_container_length); - F1AP_LIB_FIND_IE(F1AP_InitialULRRCMessageTransferIEs_t, ie, container, F1AP_ProtocolIE_ID_id_DUtoCURRCContainer, false); + F1AP_LIB_FIND_IE(F1AP_InitialULRRCMessageTransferIEs_t, ie, &pIEs->list, F1AP_ProtocolIE_ID_id_DUtoCURRCContainer, false); if (ie != NULL) out->du2cu_rrc_container = cp_octet_string(&ie->value.choice.DUtoCURRCContainer, &out->du2cu_rrc_container_length); - F1AP_LIB_FIND_IE(F1AP_InitialULRRCMessageTransferIEs_t, ie, container, F1AP_ProtocolIE_ID_id_TransactionID, true); + F1AP_LIB_FIND_IE(F1AP_InitialULRRCMessageTransferIEs_t, ie, &pIEs->list, F1AP_ProtocolIE_ID_id_TransactionID, true); out->transaction_id = ie->value.choice.TransactionID; return true; @@ -258,19 +259,20 @@ bool decode_ul_rrc_message_transfer(const F1AP_F1AP_PDU_t *pdu, f1ap_ul_rrc_mess DevAssert(pdu != NULL); F1AP_ULRRCMessageTransfer_t *container = &pdu->choice.initiatingMessage->value.choice.ULRRCMessageTransfer; + F1AP_ProtocolIE_Container_10659P33_t *pIEs = &container->protocolIEs; F1AP_ULRRCMessageTransferIEs_t *ie; // gNB-CU UE F1AP ID (M) - F1AP_LIB_FIND_IE(F1AP_ULRRCMessageTransferIEs_t, ie, container, F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); + F1AP_LIB_FIND_IE(F1AP_ULRRCMessageTransferIEs_t, ie, &pIEs->list, F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); out->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID; // gNB-DU UE F1AP ID (M) - F1AP_LIB_FIND_IE(F1AP_ULRRCMessageTransferIEs_t, ie, container, F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); + F1AP_LIB_FIND_IE(F1AP_ULRRCMessageTransferIEs_t, ie, &pIEs->list, F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); out->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; // SRB ID (M) - F1AP_LIB_FIND_IE(F1AP_ULRRCMessageTransferIEs_t, ie, container, F1AP_ProtocolIE_ID_id_SRBID, true); + F1AP_LIB_FIND_IE(F1AP_ULRRCMessageTransferIEs_t, ie, &pIEs->list, F1AP_ProtocolIE_ID_id_SRBID, true); out->srb_id = ie->value.choice.SRBID; // RRC-Container (M) - F1AP_LIB_FIND_IE(F1AP_ULRRCMessageTransferIEs_t, ie, container, F1AP_ProtocolIE_ID_id_RRCContainer, true); + F1AP_LIB_FIND_IE(F1AP_ULRRCMessageTransferIEs_t, ie, &pIEs->list, F1AP_ProtocolIE_ID_id_RRCContainer, true); out->rrc_container = cp_octet_string(&ie->value.choice.RRCContainer, &out->rrc_container_length); return true; @@ -392,30 +394,31 @@ bool decode_dl_rrc_message_transfer(const F1AP_F1AP_PDU_t *pdu, f1ap_dl_rrc_mess DevAssert(pdu != NULL); F1AP_DLRRCMessageTransfer_t *container = &pdu->choice.initiatingMessage->value.choice.DLRRCMessageTransfer; + F1AP_ProtocolIE_Container_10659P32_t *pIEs = &container->protocolIEs; F1AP_DLRRCMessageTransferIEs_t *ie; // gNB-CU UE F1AP ID (M) - F1AP_LIB_FIND_IE(F1AP_DLRRCMessageTransferIEs_t, ie, container, F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); + F1AP_LIB_FIND_IE(F1AP_DLRRCMessageTransferIEs_t, ie, &pIEs->list, F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); out->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID; // gNB-DU UE F1AP ID (M) - F1AP_LIB_FIND_IE(F1AP_DLRRCMessageTransferIEs_t, ie, container, F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); + F1AP_LIB_FIND_IE(F1AP_DLRRCMessageTransferIEs_t, ie, &pIEs->list, F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); out->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; // old gNB-DU UE F1AP ID (O) out->old_gNB_DU_ue_id = NULL; - F1AP_LIB_FIND_IE(F1AP_DLRRCMessageTransferIEs_t, ie, container, F1AP_ProtocolIE_ID_id_oldgNB_DU_UE_F1AP_ID, false); + F1AP_LIB_FIND_IE(F1AP_DLRRCMessageTransferIEs_t, ie, &pIEs->list, F1AP_ProtocolIE_ID_id_oldgNB_DU_UE_F1AP_ID, false); if (ie) { out->old_gNB_DU_ue_id = malloc_or_fail(sizeof(*out->old_gNB_DU_ue_id)); *out->old_gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID_1; } // SRB ID (M) - F1AP_LIB_FIND_IE(F1AP_DLRRCMessageTransferIEs_t, ie, container, F1AP_ProtocolIE_ID_id_SRBID, true); + F1AP_LIB_FIND_IE(F1AP_DLRRCMessageTransferIEs_t, ie, &pIEs->list, F1AP_ProtocolIE_ID_id_SRBID, true); out->srb_id = ie->value.choice.SRBID; // Execute Duplication (O) - F1AP_LIB_FIND_IE(F1AP_DLRRCMessageTransferIEs_t, ie, container, F1AP_ProtocolIE_ID_id_ExecuteDuplication, false); + F1AP_LIB_FIND_IE(F1AP_DLRRCMessageTransferIEs_t, ie, &pIEs->list, F1AP_ProtocolIE_ID_id_ExecuteDuplication, false); if (ie) { out->execute_duplication = ie->value.choice.ExecuteDuplication; } // RRC-Container (M) - F1AP_LIB_FIND_IE(F1AP_DLRRCMessageTransferIEs_t, ie, container, F1AP_ProtocolIE_ID_id_RRCContainer, true); + F1AP_LIB_FIND_IE(F1AP_DLRRCMessageTransferIEs_t, ie, &pIEs->list, F1AP_ProtocolIE_ID_id_RRCContainer, true); out->rrc_container = cp_octet_string(&ie->value.choice.RRCContainer, &out->rrc_container_length); return true; From 8cee8ad6617776f600ae940a7b3956afd2828260 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 19 Jun 2025 19:18:13 +0200 Subject: [PATCH 105/964] Remove f1ap_lib_extern.h: use headers directly --- openair2/F1AP/lib/f1ap_interface_management.c | 2 +- openair2/F1AP/lib/f1ap_lib_extern.h | 27 ------------------- openair2/F1AP/tests/f1ap_lib_test.c | 2 +- .../LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c | 1 + .../LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c | 2 +- openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c | 2 +- openair2/RRC/NR/mac_rrc_dl_f1ap.c | 4 +-- openair2/RRC/NR/rrc_gNB.c | 4 +-- 8 files changed, 9 insertions(+), 35 deletions(-) delete mode 100644 openair2/F1AP/lib/f1ap_lib_extern.h diff --git a/openair2/F1AP/lib/f1ap_interface_management.c b/openair2/F1AP/lib/f1ap_interface_management.c index cc2b5b3160..acd6859ad7 100644 --- a/openair2/F1AP/lib/f1ap_interface_management.c +++ b/openair2/F1AP/lib/f1ap_interface_management.c @@ -30,7 +30,7 @@ #include "f1ap_lib_common.h" #include "f1ap_lib_includes.h" #include "f1ap_messages_types.h" -#include "f1ap_lib_extern.h" +#include "lib/f1ap_interface_management.h" F1AP_UE_associatedLogicalF1_ConnectionItem_t encode_f1ap_ue_to_reset(const f1ap_ue_to_reset_t *to_reset) { diff --git a/openair2/F1AP/lib/f1ap_lib_extern.h b/openair2/F1AP/lib/f1ap_lib_extern.h deleted file mode 100644 index f95b685540..0000000000 --- a/openair2/F1AP/lib/f1ap_lib_extern.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.openairinterface.org/?page_id=698 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#ifndef F1AP_LIB_EXTERN_H_ -#define F1AP_LIB_EXTERN_H_ - -#include "f1ap_rrc_message_transfer.h" - -#endif /* F1AP_LIB_EXTERN_H_ */ diff --git a/openair2/F1AP/tests/f1ap_lib_test.c b/openair2/F1AP/tests/f1ap_lib_test.c index cbb5955fe9..57a503d8ab 100644 --- a/openair2/F1AP/tests/f1ap_lib_test.c +++ b/openair2/F1AP/tests/f1ap_lib_test.c @@ -38,7 +38,7 @@ #include "f1ap_messages_types.h" #include "F1AP_F1AP-PDU.h" -#include "f1ap_lib_extern.h" +#include "lib/f1ap_rrc_message_transfer.h" #include "lib/f1ap_interface_management.h" void exit_function(const char *file, const char *function, const int line, const char *s, const int assert) diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c index ed706d51f8..ed03ba76a5 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -31,6 +31,7 @@ #include "NR_CG-ConfigInfo.h" #include "openair3/ocp-gtpu/gtp_itf.h" #include "openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h" +#include "lib/f1ap_rrc_message_transfer.h" #include "lib/f1ap_interface_management.h" #include "executables/softmodem-common.h" diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c index 65e56aee10..d1c9efbdfb 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c @@ -23,7 +23,7 @@ #include "intertask_interface.h" #include "mac_rrc_ul.h" -#include "f1ap_lib_extern.h" +#include "lib/f1ap_rrc_message_transfer.h" #include "lib/f1ap_interface_management.h" static void f1_reset_du_initiated_direct(const f1ap_reset_t *reset) diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c index deb160a1a6..10b6206204 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c @@ -29,7 +29,7 @@ #include "mac_rrc_ul.h" -#include "f1ap_lib_extern.h" +#include "lib/f1ap_rrc_message_transfer.h" #include "lib/f1ap_interface_management.h" static f1ap_net_config_t read_DU_IP_config(const eth_params_t* f1_params, const char *f1u_ip_addr) diff --git a/openair2/RRC/NR/mac_rrc_dl_f1ap.c b/openair2/RRC/NR/mac_rrc_dl_f1ap.c index 9fef2dea58..30c4f910ee 100644 --- a/openair2/RRC/NR/mac_rrc_dl_f1ap.c +++ b/openair2/RRC/NR/mac_rrc_dl_f1ap.c @@ -30,8 +30,8 @@ #include "intertask_interface.h" #include "mac_rrc_dl.h" #include "nr_rrc_defs.h" -#include "openair2/F1AP/lib/f1ap_rrc_message_transfer.h" -#include "openair2/F1AP/lib/f1ap_interface_management.h" +#include "lib/f1ap_rrc_message_transfer.h" +#include "lib/f1ap_interface_management.h" static void f1_reset_cu_initiated_f1ap(sctp_assoc_t assoc_id, const f1ap_reset_t *reset) { diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 520dc469d0..e08a0a4d9e 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -78,8 +78,8 @@ #include "oai_asn1.h" #include "openair2/F1AP/f1ap_common.h" #include "openair2/F1AP/f1ap_ids.h" -#include "openair2/F1AP/lib/f1ap_lib_extern.h" -#include "lib/f1ap_interface_management.h" +#include "openair2/F1AP/lib/f1ap_rrc_message_transfer.h" +#include "openair2/F1AP/lib/f1ap_interface_management.h" #include "rrc_gNB_NGAP.h" #include "rrc_gNB_du.h" #include "rrc_gNB_mobility.h" From 10ff80815f43f30f11693e3558cd3c4d9e4056ca Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Fri, 27 Jun 2025 15:21:13 +0200 Subject: [PATCH 106/964] when we try to detect a specific PCI, and it fails, the SSS detection return successful detection, with wrong frequency offset --- openair1/PHY/NR_UE_TRANSPORT/sss_nr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/sss_nr.c b/openair1/PHY/NR_UE_TRANSPORT/sss_nr.c index 0a13462d8c..da27ca8603 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/sss_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/sss_nr.c @@ -499,7 +499,7 @@ bool rx_sss_nr(const NR_DL_FRAME_PARMS *frame_parms, int re = 0; int im = 0; - if (Nid1 == N_ID_1_NUMBER) { + if (Nid1 == Nid1_end) { LOG_D(PHY, "Failed to detect SSS after PSS, metric of SSS %d, threshold to consider SSS valid %d, detected PCI: %d\n", *tot_metric, From fb85a8cda309bbd94cd4b4b1eccddb098dc4492e Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Fri, 27 Jun 2025 15:21:47 +0200 Subject: [PATCH 107/964] clarify and indent correctly the function initial sync --- .../PHY/NR_UE_TRANSPORT/nr_initial_sync.c | 130 +++++++++--------- 1 file changed, 66 insertions(+), 64 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c index 422e8d6484..d5c2514634 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c @@ -311,7 +311,7 @@ nr_initial_sync_t nr_initial_sync(UE_nr_rxtx_proc_t *proc, fp->dl_CarrierFreq, fp->N_RB_DL, numGscn); - + DevAssert(numGscn); task_ans_t ans; init_task_ans(&ans, numGscn); nr_ue_ssb_scan_t ssb_info[numGscn]; @@ -342,39 +342,38 @@ nr_initial_sync_t nr_initial_sync(UE_nr_rxtx_proc_t *proc, } // Collect the scan results - nr_ue_ssb_scan_t res = {0}; - if (numGscn > 0) { - join_task_ans(&ans); - for (int i = 0; i < numGscn; i++) { - nr_ue_ssb_scan_t *ssbInfo = &ssb_info[i]; - if (ssbInfo->syncRes.cell_detected) { - LOG_I(NR_PHY, - "Cell Detected with GSCN: %d, SSB SC offset: %d, SSB Ref: %lf, PSS Corr peak: %d dB, PSS Corr Average: %d\n", - ssbInfo->gscnInfo.gscn, - ssbInfo->gscnInfo.ssbFirstSC, - ssbInfo->gscnInfo.ssRef, - ssbInfo->pssCorrPeakPower, - ssbInfo->pssCorrAvgPower); - if (!res.syncRes.cell_detected) { // take the first cell detected - res = *ssbInfo; - } - } - for (int ant = 0; ant < fp->nb_antennas_rx; ant++) { - free(ssbInfo->rxdata[ant]); - } - free(ssbInfo->rxdata); + nr_ue_ssb_scan_t *res = NULL; + join_task_ans(&ans); + for (int i = 0; i < numGscn; i++) { + nr_ue_ssb_scan_t *ssbInfo = &ssb_info[i]; + if (ssbInfo->syncRes.cell_detected) { + LOG_I(NR_PHY, + "Cell Detected with GSCN: %d, SSB SC offset: %d, SSB Ref: %lf, PSS Corr peak: %d dB, PSS Corr Average: %d\n", + ssbInfo->gscnInfo.gscn, + ssbInfo->gscnInfo.ssbFirstSC, + ssbInfo->gscnInfo.ssRef, + ssbInfo->pssCorrPeakPower, + ssbInfo->pssCorrAvgPower); + // take the first cell detected + if (!res) + res = ssbInfo; } + for (int ant = 0; ant < fp->nb_antennas_rx; ant++) { + free(ssbInfo->rxdata[ant]); + } + free(ssbInfo->rxdata); + ssbInfo->rxdata = NULL; } // Set globals based on detected cell - if (res.syncRes.cell_detected) { - fp->Nid_cell = res.nidCell; - fp->ssb_start_subcarrier = res.gscnInfo.ssbFirstSC; - fp->half_frame_bit = res.halfFrameBit; - fp->ssb_index = res.ssbIndex; - ue->symbol_offset = res.symbolOffset; - ue->common_vars.freq_offset = res.freqOffset; - ue->adjust_rxgain = res.adjust_rxgain; + if (res) { + fp->Nid_cell = res->nidCell; + fp->ssb_start_subcarrier = res->gscnInfo.ssbFirstSC; + fp->half_frame_bit = res->halfFrameBit; + fp->ssb_index = res->ssbIndex; + ue->symbol_offset = res->symbolOffset; + ue->common_vars.freq_offset = res->freqOffset; + ue->adjust_rxgain = res->adjust_rxgain; } // In initial sync, we indicate PBCH to MAC after the scan is complete. @@ -389,7 +388,7 @@ nr_initial_sync_t nr_initial_sync(UE_nr_rxtx_proc_t *proc, NULL, number_pdus, proc, - res.syncRes.cell_detected ? (void *)&res.pbchResult : NULL, + res ? (void *)&res->pbchResult : NULL, NULL); if (ue->if_inst && ue->if_inst->dl_indication) @@ -398,73 +397,76 @@ nr_initial_sync_t nr_initial_sync(UE_nr_rxtx_proc_t *proc, LOG_D(PHY, "nr_initial sync ue RB_DL %d\n", fp->N_RB_DL); - if (res.syncRes.cell_detected) { + if (res) { // digital compensation of FFO for SSB symbols - if (res.freqOffset && ue->UE_fo_compensation) { + if (res->freqOffset && ue->UE_fo_compensation) { // In SA we need to perform frequency offset correction until the end of buffer because we need to decode SIB1 // and we do not know yet in which slot it goes. - compensate_freq_offset(ue->common_vars.rxdata, fp, res.freqOffset, res.syncRes.frame_id); + compensate_freq_offset(ue->common_vars.rxdata, fp, res->freqOffset, res->syncRes.frame_id); } // sync at symbol ue->symbol_offset // computing the offset wrt the beginning of the frame int mu = fp->numerology_index; // number of symbols with different prefix length // every 7*(1<symbolOffset / (7 * (1 << mu))) + 1; const int sync_pos_frame = n_symb_prefix0 * (fp->ofdm_symbol_size + fp->nb_prefix_samples0) - + (res.symbolOffset - n_symb_prefix0) * (fp->ofdm_symbol_size + fp->nb_prefix_samples); + + (res->symbolOffset - n_symb_prefix0) * (fp->ofdm_symbol_size + fp->nb_prefix_samples); // for a correct computation of frame number to sync with the one decoded at MIB we need to take into account in which of // the n_frames we got sync - ue->init_sync_frame = n_frames - 1 - res.syncRes.frame_id; + ue->init_sync_frame = n_frames - 1 - res->syncRes.frame_id; // we also need to take into account the shift by samples_per_frame in case the if is true - if (res.ssbOffset < sync_pos_frame) { - res.syncRes.rx_offset = fp->samples_per_frame - sync_pos_frame + res.ssbOffset; + if (res->ssbOffset < sync_pos_frame) { + res->syncRes.rx_offset = fp->samples_per_frame - sync_pos_frame + res->ssbOffset; ue->init_sync_frame += 1; } else - res.syncRes.rx_offset = res.ssbOffset - sync_pos_frame; + res->syncRes.rx_offset = res->ssbOffset - sync_pos_frame; } - if (res.syncRes.cell_detected) { - LOG_I(PHY, "[UE%d] In synch, rx_offset %d samples\n", ue->Mod_id, res.syncRes.rx_offset); - LOG_I(PHY, "[UE %d] Measured Carrier Frequency offset %d Hz\n", ue->Mod_id, res.freqOffset); - } else { + if (res) { + LOG_I(PHY, "[UE%d] In synch, rx_offset %d samples\n", ue->Mod_id, res->syncRes.rx_offset); + LOG_I(PHY, "[UE %d] Measured Carrier Frequency offset %d Hz\n", ue->Mod_id, res->freqOffset); + } else { #ifdef DEBUG_INITIAL_SYNC LOG_I(PHY,"[UE%d] Initial sync : PBCH not ok\n",ue->Mod_id); LOG_I(PHY, "[UE%d] Initial sync : Estimated PSS position %d, Nid2 %d\n", ue->Mod_id, sync_pos, ue->common_vars.nid2); LOG_I(PHY,"[UE%d] Initial sync : Estimated Nid_cell %d, Frame_type %d\n",ue->Mod_id, fp->Nid_cell,fp->frame_type); #endif - } + } // gain control - if (!res.syncRes.cell_detected) { // we are not synched, so we cannot use rssi measurement (which is based on channel estimates) - int rx_power = 0; + if (!res) { // we are not synched, so we cannot use rssi measurement (which is based on channel estimates) + int rx_power = 0; - // do a measurement on the best guess of the PSS - // for (aarx=0; aarxnb_antennas_rx; aarx++) - // rx_power += signal_energy(&ue->common_vars.rxdata[aarx][sync_pos2], - // frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples); + // do a measurement on the best guess of the PSS + // for (aarx=0; aarxnb_antennas_rx; aarx++) + // rx_power += signal_energy(&ue->common_vars.rxdata[aarx][sync_pos2], + // frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples); - /* - // do a measurement on the full frame - for (aarx=0; aarxnb_antennas_rx; aarx++) - rx_power += signal_energy(&ue->common_vars.rxdata[aarx][0], - frame_parms->samples_per_subframe*10); - */ + /* + // do a measurement on the full frame + for (aarx=0; aarxnb_antennas_rx; aarx++) + rx_power += signal_energy(&ue->common_vars.rxdata[aarx][0], + frame_parms->samples_per_subframe*10); + */ - // we might add a low-pass filter here later - ue->measurements.rx_power_avg[0] = rx_power / fp->nb_antennas_rx; + // we might add a low-pass filter here later + ue->measurements.rx_power_avg[0] = rx_power / fp->nb_antennas_rx; - ue->measurements.rx_power_avg_dB[0] = dB_fixed(ue->measurements.rx_power_avg[0]); + ue->measurements.rx_power_avg_dB[0] = dB_fixed(ue->measurements.rx_power_avg[0]); #ifdef DEBUG_INITIAL_SYNCH LOG_I(PHY, "[UE%d] Initial sync failed : Estimated power: %d dB\n", ue->Mod_id, ue->measurements.rx_power_avg_dB[0]); #endif - } else { - LOG_A(PHY, "Initial sync successful, PCI: %d\n",fp->Nid_cell); - } + } else { + LOG_A(PHY, "Initial sync successful, PCI: %d\n", fp->Nid_cell); + } // exit_fun("debug exit"); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_INITIAL_UE_SYNC, VCD_FUNCTION_OUT); - return res.syncRes; + if (res) + return res->syncRes; + else + return (nr_initial_sync_t){.cell_detected = false}; } From 8e4b760c863f9298598304814ecaca3206826cc2 Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 27 Jun 2025 17:14:06 +0200 Subject: [PATCH 108/964] bugfix for UL TBSLBRM --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index a447d9f91c..e35865fc0d 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -2422,7 +2422,7 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac, NRRIV2PRBOFFSET(scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); sc_info->dl_bw_tbslbrm = get_dlbw_tbslbrm(sc_info->initial_dl_BWPSize, servingCellConfig); - sc_info->dl_bw_tbslbrm = get_ulbw_tbslbrm(sc_info->initial_ul_BWPSize, servingCellConfig); + sc_info->ul_bw_tbslbrm = get_ulbw_tbslbrm(sc_info->initial_ul_BWPSize, servingCellConfig); if (UL_BWP->bwp_id > 0) { UL_BWP->pucch_ConfigCommon = ul_bwp->bwp_Common->pucch_ConfigCommon ? ul_bwp->bwp_Common->pucch_ConfigCommon->choice.setup : NULL; From 33d011b2cb157cbcf60a94c88bf10da3323b3dd3 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Fri, 6 Jun 2025 12:33:18 +0200 Subject: [PATCH 109/964] CI: adjust YAML files to speedup deployment/undeployment in rfsim5g - `init: true` initializes the docker container with tini or alternative - it is used to collect all the processes and correctly pass the termination signal to them, this allows the docker container to be stopped without waiting 10 seconds to kill the container - speeding up the healthchecks by reducing the interval from 1-10s to 0.5s during start period Co-authored-by: Bartosz Podrygajlo --- .../5g_f1_rfsimulator/docker-compose.yaml | 15 ++++++++++ .../5g_fdd_rfsimulator/docker-compose.yaml | 11 +++++++ .../5g_rfsimulator/docker-compose.yaml | 29 +++++++++++++++++++ .../5g_rfsimulator_24prb/docker-compose.yaml | 11 +++++++ .../5g_rfsimulator_2x2/docker-compose.yaml | 11 +++++++ .../5g_rfsimulator_e1/docker-compose.yaml | 24 +++++++++++++++ .../docker-compose.yaml | 11 +++++++ .../docker-compose.yaml | 11 +++++++ .../docker-compose.yaml | 8 +++++ .../docker-compose.yaml | 4 +++ .../docker-compose.yaml | 13 +++++++++ 11 files changed, 148 insertions(+) diff --git a/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml b/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml index fb1d5a95ce..b4bec0e486 100644 --- a/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml @@ -2,6 +2,7 @@ services: mysql: container_name: "rfsim5g-mysql" image: mysql:8.0 + init: true volumes: - ../5g_rfsimulator/oai_db.sql:/docker-entrypoint-initdb.d/oai_db.sql - ../5g_rfsimulator/mysql-healthcheck.sh:/tmp/mysql-healthcheck.sh @@ -13,6 +14,8 @@ services: - MYSQL_ROOT_PASSWORD=linux healthcheck: test: /bin/bash -c "/tmp/mysql-healthcheck.sh" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 30 @@ -46,6 +49,7 @@ services: oai-upf: container_name: "rfsim5g-oai-upf" image: oaisoftwarealliance/oai-upf:v2.1.9 + init: true environment: - TZ=Europe/Paris volumes: @@ -68,6 +72,7 @@ services: privileged: true container_name: rfsim5g-oai-ext-dn image: oaisoftwarealliance/trf-gen-cn5g:focal + init: true entrypoint: /bin/bash -c \ "iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE;"\ "ip route add 12.1.1.0/24 via 192.168.72.134 dev eth0; sleep infinity" @@ -78,6 +83,8 @@ services: ipv4_address: 192.168.72.135 healthcheck: test: /bin/bash -c "ping -c 2 192.168.72.134" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 5 @@ -103,6 +110,8 @@ services: - ../../conf_files/gnb-cu.sa.band78.106prb.conf:/opt/oai-gnb/etc/gnb.conf healthcheck: test: /bin/bash -c "pgrep nr-softmodem" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 5 @@ -130,6 +139,8 @@ services: - ../../conf_files/gnb-du.sa.band78.106prb.rfsim.conf:/opt/oai-gnb/etc/gnb.conf healthcheck: test: /bin/bash -c "pgrep nr-softmodem" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 5 @@ -161,6 +172,8 @@ services: - ../../conf_files/gnb-du.sa.band78.106prb.rfsim.conf:/opt/oai-gnb/etc/gnb.conf healthcheck: test: /bin/bash -c "pgrep nr-softmodem" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 5 @@ -193,6 +206,8 @@ services: - ../../conf_files/nrue.uicc.conf:/opt/oai-nr-ue/etc/nr-ue.conf healthcheck: test: /bin/bash -c "pgrep nr-uesoftmodem" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 5 diff --git a/ci-scripts/yaml_files/5g_fdd_rfsimulator/docker-compose.yaml b/ci-scripts/yaml_files/5g_fdd_rfsimulator/docker-compose.yaml index a40033be7f..dd306c15f6 100644 --- a/ci-scripts/yaml_files/5g_fdd_rfsimulator/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_fdd_rfsimulator/docker-compose.yaml @@ -2,6 +2,7 @@ services: mysql: container_name: "rfsim5g-mysql" image: mysql:8.0 + init: true volumes: - ../5g_rfsimulator/oai_db.sql:/docker-entrypoint-initdb.d/oai_db.sql - ../5g_rfsimulator/mysql-healthcheck.sh:/tmp/mysql-healthcheck.sh @@ -15,6 +16,8 @@ services: test: /bin/bash -c "/tmp/mysql-healthcheck.sh" interval: 10s timeout: 5s + start_period: 10s + start_interval: 500ms retries: 30 networks: public_net: @@ -46,6 +49,7 @@ services: oai-upf: container_name: "rfsim5g-oai-upf" image: oaisoftwarealliance/oai-upf:v2.1.9 + init: true environment: - TZ=Europe/Paris volumes: @@ -67,6 +71,7 @@ services: privileged: true container_name: rfsim5g-oai-ext-dn image: oaisoftwarealliance/trf-gen-cn5g:focal + init: true entrypoint: /bin/bash -c \ "iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE;"\ "ip route add 12.1.1.0/24 via 192.168.72.134 dev eth0; sleep infinity" @@ -80,6 +85,8 @@ services: interval: 10s timeout: 5s retries: 5 + start_period: 10s + start_interval: 500ms oai-gnb: image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop} container_name: rfsim5g-oai-gnb @@ -99,6 +106,8 @@ services: test: /bin/bash -c "pgrep nr-softmodem" interval: 10s timeout: 5s + start_period: 10s + start_interval: 500ms retries: 5 ipc: host oai-nr-ue: @@ -126,6 +135,8 @@ services: interval: 10s timeout: 5s retries: 5 + start_period: 10s + start_interval: 500ms ipc: host networks: diff --git a/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml index 4733737b50..ac89f0d036 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml @@ -2,6 +2,7 @@ services: mysql: container_name: "rfsim5g-mysql" image: mysql:8.0 + init: true volumes: - ./oai_db.sql:/docker-entrypoint-initdb.d/oai_db.sql - ./mysql-healthcheck.sh:/tmp/mysql-healthcheck.sh @@ -13,6 +14,8 @@ services: - MYSQL_ROOT_PASSWORD=linux healthcheck: test: /bin/bash -c "/tmp/mysql-healthcheck.sh" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 30 @@ -46,6 +49,7 @@ services: oai-upf: container_name: "rfsim5g-oai-upf" image: oaisoftwarealliance/oai-upf:v2.1.9 + init: true environment: - TZ=Europe/Paris volumes: @@ -67,6 +71,7 @@ services: privileged: true container_name: rfsim5g-oai-ext-dn image: oaisoftwarealliance/trf-gen-cn5g:focal + init: true entrypoint: /bin/bash -c \ "iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE;"\ "ip route add 12.1.1.0/24 via 192.168.72.134 dev eth0; sleep infinity" @@ -77,6 +82,8 @@ services: ipv4_address: 192.168.72.135 healthcheck: test: /bin/bash -c "ping -c 2 192.168.72.134" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 5 @@ -97,6 +104,8 @@ services: - ../../conf_files/gnb.sa.band78.106prb.rfsim.yaml:/opt/oai-gnb/etc/gnb.yaml healthcheck: test: /bin/bash -c "pgrep nr-softmodem" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 5 @@ -121,6 +130,8 @@ services: - ../../conf_files/nrue.uicc.yaml:/opt/oai-nr-ue/etc/nr-ue.yaml healthcheck: test: /bin/bash -c "pgrep nr-uesoftmodem" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 5 @@ -145,6 +156,8 @@ services: - ../../conf_files/nrue.uicc.conf:/opt/oai-nr-ue/etc/nr-ue.conf healthcheck: test: /bin/bash -c "pgrep nr-uesoftmodem" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 5 @@ -169,6 +182,8 @@ services: - ../../conf_files/nrue.uicc.conf:/opt/oai-nr-ue/etc/nr-ue.conf healthcheck: test: /bin/bash -c "pgrep nr-uesoftmodem" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 5 @@ -193,6 +208,8 @@ services: - ../../conf_files/nrue.uicc.conf:/opt/oai-nr-ue/etc/nr-ue.conf healthcheck: test: /bin/bash -c "pgrep nr-uesoftmodem" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 5 @@ -217,6 +234,8 @@ services: - ../../conf_files/nrue.uicc.conf:/opt/oai-nr-ue/etc/nr-ue.conf healthcheck: test: /bin/bash -c "pgrep nr-uesoftmodem" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 5 @@ -241,6 +260,8 @@ services: - ../../conf_files/nrue.uicc.conf:/opt/oai-nr-ue/etc/nr-ue.conf healthcheck: test: /bin/bash -c "pgrep nr-uesoftmodem" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 5 @@ -265,6 +286,8 @@ services: - ../../conf_files/nrue.uicc.conf:/opt/oai-nr-ue/etc/nr-ue.conf healthcheck: test: /bin/bash -c "pgrep nr-uesoftmodem" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 5 @@ -289,6 +312,8 @@ services: - ../../conf_files/nrue.uicc.conf:/opt/oai-nr-ue/etc/nr-ue.conf healthcheck: test: /bin/bash -c "pgrep nr-uesoftmodem" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 5 @@ -313,6 +338,8 @@ services: - ../../conf_files/nrue.uicc.conf:/opt/oai-nr-ue/etc/nr-ue.conf healthcheck: test: /bin/bash -c "pgrep nr-uesoftmodem" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 5 @@ -337,6 +364,8 @@ services: - ../../conf_files/nrue.uicc.conf:/opt/oai-nr-ue/etc/nr-ue.conf healthcheck: test: /bin/bash -c "pgrep nr-uesoftmodem" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 5 diff --git a/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml index 165d2791e7..8dfe5a5980 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml @@ -2,6 +2,7 @@ services: mysql: container_name: "rfsim5g-mysql" image: mysql:8.0 + init: true volumes: - ../5g_rfsimulator/oai_db.sql:/docker-entrypoint-initdb.d/oai_db.sql - ../5g_rfsimulator/mysql-healthcheck.sh:/tmp/mysql-healthcheck.sh @@ -13,6 +14,8 @@ services: - MYSQL_ROOT_PASSWORD=linux healthcheck: test: /bin/bash -c "/tmp/mysql-healthcheck.sh" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 30 @@ -46,6 +49,7 @@ services: oai-upf: container_name: "rfsim5g-oai-upf" image: oaisoftwarealliance/oai-upf:v2.1.9 + init: true environment: - TZ=Europe/Paris volumes: @@ -67,6 +71,7 @@ services: privileged: true container_name: rfsim5g-oai-ext-dn image: oaisoftwarealliance/trf-gen-cn5g:focal + init: true entrypoint: /bin/bash -c \ "iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE;"\ "ip route add 12.1.1.0/24 via 192.168.72.134 dev eth0; sleep infinity" @@ -77,6 +82,8 @@ services: ipv4_address: 192.168.72.135 healthcheck: test: /bin/bash -c "ping -c 2 192.168.72.134" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 5 @@ -97,6 +104,8 @@ services: - ../../conf_files/gnb.sa.band78.24prb.rfsim.conf:/opt/oai-gnb/etc/gnb.conf healthcheck: test: /bin/bash -c "pgrep nr-softmodem" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 5 @@ -124,6 +133,8 @@ services: - ../../conf_files/nrue.uicc.conf:/opt/oai-nr-ue/etc/nr-ue.conf healthcheck: test: /bin/bash -c "pgrep nr-uesoftmodem" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 5 diff --git a/ci-scripts/yaml_files/5g_rfsimulator_2x2/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_2x2/docker-compose.yaml index b051712a4c..3231a2f76e 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_2x2/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_2x2/docker-compose.yaml @@ -2,6 +2,7 @@ services: mysql: container_name: "rfsim5g-mysql" image: mysql:8.0 + init: true volumes: - ../5g_rfsimulator/oai_db.sql:/docker-entrypoint-initdb.d/oai_db.sql - ../5g_rfsimulator/mysql-healthcheck.sh:/tmp/mysql-healthcheck.sh @@ -13,6 +14,8 @@ services: - MYSQL_ROOT_PASSWORD=linux healthcheck: test: /bin/bash -c "/tmp/mysql-healthcheck.sh" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 30 @@ -46,6 +49,7 @@ services: oai-upf: container_name: "rfsim5g-oai-upf" image: oaisoftwarealliance/oai-upf:v2.1.9 + init: true environment: - TZ=Europe/Paris volumes: @@ -67,6 +71,7 @@ services: privileged: true container_name: rfsim5g-oai-ext-dn image: oaisoftwarealliance/trf-gen-cn5g:focal + init: true entrypoint: /bin/bash -c \ "iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE;"\ "ip route add 12.1.1.0/24 via 192.168.72.134 dev eth0; sleep infinity" @@ -77,6 +82,8 @@ services: ipv4_address: 192.168.72.135 healthcheck: test: /bin/bash -c "ping -c 2 192.168.72.134" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 5 @@ -97,6 +104,8 @@ services: - ../../conf_files/gnb.sa.band78.273prb.rfsim.2x2.conf:/opt/oai-gnb/etc/gnb.conf healthcheck: test: /bin/bash -c "pgrep nr-softmodem" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 5 @@ -123,6 +132,8 @@ services: - ../../conf_files/nrue.uicc.conf:/opt/oai-nr-ue/etc/nr-ue.conf healthcheck: test: /bin/bash -c "pgrep nr-uesoftmodem" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 5 diff --git a/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml index 69d27de863..66b746b6f2 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml @@ -2,6 +2,7 @@ services: mysql: container_name: "rfsim5g-mysql" image: mysql:8.0 + init: true volumes: - ../5g_rfsimulator/oai_db.sql:/docker-entrypoint-initdb.d/oai_db.sql - ../5g_rfsimulator/mysql-healthcheck.sh:/tmp/mysql-healthcheck.sh @@ -13,6 +14,8 @@ services: - MYSQL_ROOT_PASSWORD=linux healthcheck: test: /bin/bash -c "/tmp/mysql-healthcheck.sh" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 30 @@ -46,6 +49,7 @@ services: oai-upf: container_name: "rfsim5g-oai-upf" image: oaisoftwarealliance/oai-upf:v2.1.9 + init: true environment: - TZ=Europe/Paris volumes: @@ -87,6 +91,8 @@ services: - ../../conf_files/gnb-cucp.sa.f1.conf:/opt/oai-gnb/etc/gnb.conf healthcheck: test: /bin/bash -c "pgrep nr-softmodem" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 5 @@ -116,6 +122,8 @@ services: - ../../conf_files/gnb-cuup.sa.f1.conf:/opt/oai-gnb/etc/gnb.conf healthcheck: test: /bin/bash -c "pgrep nr-cuup" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 5 @@ -148,6 +156,8 @@ services: - ../../conf_files/gnb-cuup.sa.f1.conf:/opt/oai-gnb/etc/gnb.conf healthcheck: test: /bin/bash -c "pgrep nr-cuup" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 5 @@ -180,6 +190,8 @@ services: - ../../conf_files/gnb-cuup.sa.f1.conf:/opt/oai-gnb/etc/gnb.conf healthcheck: test: /bin/bash -c "pgrep nr-cuup" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 5 @@ -209,6 +221,8 @@ services: - ../../conf_files/gnb-du.sa.band78.106prb.rfsim.conf:/opt/oai-gnb/etc/gnb.conf healthcheck: test: /bin/bash -c "pgrep nr-softmodem" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 5 @@ -241,6 +255,8 @@ services: - ../../conf_files/gnb-du.sa.band78.106prb.rfsim.conf:/opt/oai-gnb/etc/gnb.conf healthcheck: test: /bin/bash -c "pgrep nr-softmodem" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 5 @@ -273,6 +289,8 @@ services: - ../../conf_files/gnb-du.sa.band78.106prb.rfsim.conf:/opt/oai-gnb/etc/gnb.conf healthcheck: test: /bin/bash -c "pgrep nr-softmodem" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 5 @@ -301,6 +319,8 @@ services: - ../../conf_files/nrue.uicc.conf:/opt/oai-nr-ue/etc/nr-ue.conf healthcheck: test: /bin/bash -c "pgrep nr-uesoftmodem" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 5 @@ -329,6 +349,8 @@ services: - ../../conf_files/nrue.uicc.conf:/opt/oai-nr-ue/etc/nr-ue.conf healthcheck: test: /bin/bash -c "pgrep nr-uesoftmodem" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 5 @@ -358,6 +380,8 @@ services: - ../../conf_files/nrue.uicc.conf:/opt/oai-nr-ue/etc/nr-ue.conf healthcheck: test: /bin/bash -c "pgrep nr-uesoftmodem" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 5 diff --git a/ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb/docker-compose.yaml index 627fde5dce..413fdb1358 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb/docker-compose.yaml @@ -2,6 +2,7 @@ services: mysql: container_name: "rfsim5g-mysql" image: mysql:8.0 + init: true volumes: - ../5g_rfsimulator/oai_db.sql:/docker-entrypoint-initdb.d/oai_db.sql - ../5g_rfsimulator/mysql-healthcheck.sh:/tmp/mysql-healthcheck.sh @@ -13,6 +14,8 @@ services: - MYSQL_ROOT_PASSWORD=linux healthcheck: test: /bin/bash -c "/tmp/mysql-healthcheck.sh" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 30 @@ -46,6 +49,7 @@ services: oai-upf: container_name: "rfsim5g-oai-upf" image: oaisoftwarealliance/oai-upf:v2.1.9 + init: true environment: - TZ=Europe/Paris volumes: @@ -67,6 +71,7 @@ services: privileged: true container_name: rfsim5g-oai-ext-dn image: oaisoftwarealliance/trf-gen-cn5g:focal + init: true entrypoint: /bin/bash -c \ "iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE;"\ "ip route add 12.1.1.0/24 via 192.168.72.134 dev eth0; sleep infinity" @@ -77,6 +82,8 @@ services: ipv4_address: 192.168.72.135 healthcheck: test: /bin/bash -c "ping -c 2 192.168.72.134" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 5 @@ -96,6 +103,8 @@ services: - ../../conf_files/gnb.sa.band261.u3.32prb.rfsim.conf:/opt/oai-gnb/etc/gnb.conf healthcheck: test: /bin/bash -c "pgrep nr-softmodem" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 5 @@ -124,6 +133,8 @@ services: ipv4_address: 192.168.71.150 healthcheck: test: /bin/bash -c "pgrep nr-uesoftmodem" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 5 diff --git a/ci-scripts/yaml_files/5g_rfsimulator_ntn_geo/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_ntn_geo/docker-compose.yaml index 31390cde9c..79240aa876 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_ntn_geo/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_ntn_geo/docker-compose.yaml @@ -2,6 +2,7 @@ services: mysql: container_name: "rfsim5g-mysql" image: mysql:8.0 + init: true volumes: - ../5g_rfsimulator/oai_db.sql:/docker-entrypoint-initdb.d/oai_db.sql - ../5g_rfsimulator/mysql-healthcheck.sh:/tmp/mysql-healthcheck.sh @@ -13,6 +14,8 @@ services: - MYSQL_ROOT_PASSWORD=linux healthcheck: test: /bin/bash -c "/tmp/mysql-healthcheck.sh" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 30 @@ -46,6 +49,7 @@ services: oai-upf: container_name: "rfsim5g-oai-upf" image: oaisoftwarealliance/oai-upf:v2.1.9 + init: true environment: - TZ=Europe/Paris volumes: @@ -67,6 +71,7 @@ services: privileged: true container_name: rfsim5g-oai-ext-dn image: oaisoftwarealliance/trf-gen-cn5g:focal + init: true entrypoint: /bin/bash -c \ "iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE;"\ "ip route add 12.1.1.0/24 via 192.168.72.134 dev eth0; sleep infinity" @@ -77,6 +82,8 @@ services: ipv4_address: 192.168.72.135 healthcheck: test: /bin/bash -c "ping -c 2 192.168.72.134" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 5 @@ -97,6 +104,8 @@ services: - ../../conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn.conf:/opt/oai-gnb/etc/gnb.conf healthcheck: test: /bin/bash -c "pgrep nr-softmodem" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 5 @@ -122,6 +131,8 @@ services: - ../../conf_files/nrue.uicc.conf:/opt/oai-nr-ue/etc/nr-ue.conf healthcheck: test: /bin/bash -c "pgrep nr-uesoftmodem" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 5 diff --git a/ci-scripts/yaml_files/5g_rfsimulator_ntn_leo/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_ntn_leo/docker-compose.yaml index 29be9d6900..65de72fb51 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_ntn_leo/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_ntn_leo/docker-compose.yaml @@ -13,6 +13,8 @@ services: - MYSQL_ROOT_PASSWORD=linux healthcheck: test: /bin/bash -c "/tmp/mysql-healthcheck.sh" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 30 @@ -77,6 +79,8 @@ services: ipv4_address: 192.168.72.135 healthcheck: test: /bin/bash -c "ping -c 2 192.168.72.134" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 5 @@ -97,6 +101,8 @@ services: - ../../conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn-leo.conf:/opt/oai-gnb/etc/gnb.conf healthcheck: test: /bin/bash -c "pgrep nr-softmodem" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 5 @@ -129,6 +135,8 @@ services: - ../../conf_files/nrue.uicc.ntn-leo.conf:/opt/oai-nr-ue/etc/nr-ue.conf healthcheck: test: /bin/bash -c "pgrep nr-uesoftmodem" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 5 diff --git a/ci-scripts/yaml_files/5g_rfsimulator_sidelink/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_sidelink/docker-compose.yaml index 35e6a4eee9..cae436e001 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_sidelink/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_sidelink/docker-compose.yaml @@ -18,6 +18,8 @@ services: - ../../conf_files/nrue.uicc.conf:/opt/oai-nr-ue/etc/nr-ue.conf healthcheck: test: /bin/bash -c "pgrep nr-uesoftmodem" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 5 @@ -43,6 +45,8 @@ services: - ../../conf_files/nrue.uicc.conf:/opt/oai-nr-ue/etc/nr-ue.conf healthcheck: test: /bin/bash -c "pgrep nr-uesoftmodem" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 5 diff --git a/ci-scripts/yaml_files/5g_rfsimulator_u0_25prb/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_u0_25prb/docker-compose.yaml index cd0365b4ec..2dca6cc25f 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_u0_25prb/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_u0_25prb/docker-compose.yaml @@ -2,6 +2,7 @@ services: mysql: container_name: "rfsim5g-mysql" image: mysql:8.0 + init: true volumes: - ../5g_rfsimulator/oai_db.sql:/docker-entrypoint-initdb.d/oai_db.sql - ../5g_rfsimulator/mysql-healthcheck.sh:/tmp/mysql-healthcheck.sh @@ -13,6 +14,8 @@ services: - MYSQL_ROOT_PASSWORD=linux healthcheck: test: /bin/bash -c "/tmp/mysql-healthcheck.sh" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 30 @@ -46,6 +49,7 @@ services: oai-upf: container_name: "rfsim5g-oai-upf" image: oaisoftwarealliance/oai-upf:v2.1.9 + init: true environment: - TZ=Europe/Paris volumes: @@ -67,6 +71,7 @@ services: privileged: true container_name: rfsim5g-oai-ext-dn image: oaisoftwarealliance/trf-gen-cn5g:focal + init: true entrypoint: /bin/bash -c \ "iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE;"\ "ip route add 12.1.1.0/24 via 192.168.72.134 dev eth0; sleep infinity" @@ -77,6 +82,8 @@ services: ipv4_address: 192.168.72.135 healthcheck: test: /bin/bash -c "ping -c 2 192.168.72.134" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 5 @@ -99,6 +106,8 @@ services: - ../../conf_files/gnb-vnf.sa.band66.u0.25prb.nfapi.conf:/opt/oai-gnb/etc/gnb.conf healthcheck: test: /bin/bash -c "pgrep nr-softmodem" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 5 @@ -121,6 +130,8 @@ services: - ../../conf_files/gnb-pnf.band66.rfsim.conf:/opt/oai-gnb/etc/gnb.conf healthcheck: test: /bin/bash -c "pgrep nr-softmodem" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 5 @@ -146,6 +157,8 @@ services: - ../../conf_files/nrue.uicc.conf:/opt/oai-nr-ue/etc/nr-ue.conf healthcheck: test: /bin/bash -c "pgrep nr-uesoftmodem" + start_period: 10s + start_interval: 500ms interval: 10s timeout: 5s retries: 5 From 2d398519838411643ec05252f1c4b48484fe02cc Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Fri, 27 Jun 2025 20:15:09 +0200 Subject: [PATCH 110/964] CI: adjustment of DeployObject to speedup deployment - using docker compose up --wait instead of a custom healthcheck script Co-authored-by: Bartosz Podrygajlo --- ci-scripts/cls_containerize.py | 40 +++++++++------------------------- 1 file changed, 10 insertions(+), 30 deletions(-) diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index f3d30d6170..29b71628ed 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -152,19 +152,6 @@ def GetImageName(ssh, svcName, file): else: return ret.stdout.strip() -def GetServiceHealth(ssh, svcName, file): - if svcName is None: - return False, f"Service {svcName} not found in {file}" - image = GetImageName(ssh, svcName, file) - if 'db_init' in svcName or 'db-init' in svcName: # exits with 0, there cannot be healthy - return True, f"Service {svcName} healthy, image {image}" - for _ in range(8): - result = ssh.run(f"docker compose -f {file} ps --format json {svcName} | jq -r 'if type==\"array\" then .[0].Health else .Health end'", silent=True) - if result.stdout == 'healthy': - return True, f"Service {svcName} healthy, image {image}" - time.sleep(5) - return False, f"Failed to deploy: service {svcName}" - def ExistEnvFilePrint(ssh, wd, prompt='env vars in existing'): ret = ssh.run(f'cat {wd}/.env', silent=True, reportNonZero=False) if ret.returncode != 0: @@ -872,31 +859,24 @@ class Containerize(): if num_attempts <= 0: raise ValueError(f'Invalid value for num_attempts: {num_attempts}, must be greater than 0') for attempt in range(num_attempts): - imagesInfo = [] - healthInfo = [] logging.info(f'will start services {services}') - status = ssh.run(f'docker compose -f {wd_yaml} up -d -- {services}') - if status.returncode != 0: + status = ssh.run(f'docker compose -f {wd_yaml} up -d --wait --wait-timeout 60 -- {services}') + info = ssh.run(f"docker compose -f {wd_yaml} ps --all --format=\'table {{{{.Service}}}} [{{{{.Image}}}}] {{{{.Status}}}}\' -- {services} | column -t") + deployed = status.returncode == 0 + if not deployed: msg = f'cannot deploy services {services}: {status.stdout}' logging.error(msg) - HTML.CreateHtmlTestRowQueue('N/A', 'NOK', [msg]) - return False - for svc in services.split(): - health, msg = GetServiceHealth(ssh, svc, f'{wd_yaml}') - logging.info(msg) - imagesInfo.append(msg) - healthInfo.append(health) - deployed = all(healthInfo) - if deployed: + else: break - elif (attempt < num_attempts - 1): - warning_msg = f'Restart services {services}' + if (attempt < num_attempts - 1): + warning_msg = (f'Failed to deploy on attempt {attempt}, restart services {services}') logging.warning(warning_msg) - imagesInfo.append(warning_msg) - HTML.CreateHtmlTestRowQueue('N/A', 'NOK', ['\n'.join(imagesInfo)]) + HTML.CreateHtmlTestRowQueue('N/A', 'NOK', [warning_msg]) for svc in services.split(): CopyinServiceLog(ssh, lSourcePath, yaml_dir, svc, wd_yaml, f'{svc}-{HTML.testCase_id}-attempt{attempt}.log') ssh.run(f'docker compose -f {wd_yaml} down -- {services}') + imagesInfo = info.stdout.splitlines()[1:] + logging.debug(f'{info.stdout.splitlines()[1:]}') if deployed: HTML.CreateHtmlTestRowQueue('N/A', 'OK', ['\n'.join(imagesInfo)]) else: From f7b3e04cf9bc56a0909a4c8e24c4c35af03ddcf6 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Fri, 4 Apr 2025 15:45:44 +0200 Subject: [PATCH 111/964] CI: new healthcheck condition for OTA docker deployments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This modification aims to improve health status detection by using PRACH IO as an indicator of the gNB's status (container is marked as "healthy" when the PRACH IO value in gNB nrL1_stats.log exceeds 0.0 dB.). The new condition accounts for scenarios where the container may not exit or produce error codes (e.g., “sleep” logs or "error code overflow" messages). --- .../yaml_files/5g_sa_n310_2x2_100MHz/docker-compose.yml | 6 ++++-- .../yaml_files/5g_sa_n310_2x2_60MHz/docker-compose.yml | 6 ++++-- .../yaml_files/5g_sa_n310_4x4_60MHz/docker-compose.yml | 8 +++++--- ci-scripts/yaml_files/5g_sa_n310_gnb/docker-compose.yml | 8 +++++--- .../sa_fhi_7.2_benetel550_gnb/docker-compose.yml | 8 +++++--- .../sa_fhi_7.2_metanoia_2x2_gnb/docker-compose.yml | 8 +++++--- .../yaml_files/sa_fhi_7.2_vvdn_gnb/docker-compose.yml | 9 ++++++--- docker/Dockerfile.gNB.fhi72.rhel9 | 1 + docker/Dockerfile.gNB.fhi72.rocky | 1 + docker/Dockerfile.gNB.fhi72.ubuntu22 | 1 + docker/Dockerfile.gNB.rhel9 | 1 + docker/Dockerfile.gNB.rocky | 1 + docker/Dockerfile.gNB.ubuntu22 | 1 + docker/scripts/check-prach-io.sh | 5 +++++ 14 files changed, 45 insertions(+), 19 deletions(-) create mode 100755 docker/scripts/check-prach-io.sh diff --git a/ci-scripts/yaml_files/5g_sa_n310_2x2_100MHz/docker-compose.yml b/ci-scripts/yaml_files/5g_sa_n310_2x2_100MHz/docker-compose.yml index 6d597d3a86..11ecb20f08 100644 --- a/ci-scripts/yaml_files/5g_sa_n310_2x2_100MHz/docker-compose.yml +++ b/ci-scripts/yaml_files/5g_sa_n310_2x2_100MHz/docker-compose.yml @@ -14,7 +14,9 @@ services: volumes: - ../../conf_files/gnb.sa.band77.273prb.usrpn310.2x2.conf:/opt/oai-gnb/etc/gnb.conf healthcheck: - test: /bin/bash -c "pgrep nr-softmodem" - interval: 10s + test: /bin/bash -c "/opt/oai-gnb/bin/check-prach-io.sh" + start_period: 15s + start_interval: 500ms + interval: 5s timeout: 5s retries: 5 diff --git a/ci-scripts/yaml_files/5g_sa_n310_2x2_60MHz/docker-compose.yml b/ci-scripts/yaml_files/5g_sa_n310_2x2_60MHz/docker-compose.yml index 43211d7381..332fb23503 100644 --- a/ci-scripts/yaml_files/5g_sa_n310_2x2_60MHz/docker-compose.yml +++ b/ci-scripts/yaml_files/5g_sa_n310_2x2_60MHz/docker-compose.yml @@ -14,7 +14,9 @@ services: volumes: - ../../conf_files/gnb.sa.band77.162prb.usrpn310.2x2.conf:/opt/oai-gnb/etc/gnb.conf healthcheck: - test: /bin/bash -c "pgrep nr-softmodem" - interval: 10s + test: /bin/bash -c "/opt/oai-gnb/bin/check-prach-io.sh" + start_period: 15s + start_interval: 500ms + interval: 5s timeout: 5s retries: 5 diff --git a/ci-scripts/yaml_files/5g_sa_n310_4x4_60MHz/docker-compose.yml b/ci-scripts/yaml_files/5g_sa_n310_4x4_60MHz/docker-compose.yml index 0ecba5f39e..d3d2ddf582 100644 --- a/ci-scripts/yaml_files/5g_sa_n310_4x4_60MHz/docker-compose.yml +++ b/ci-scripts/yaml_files/5g_sa_n310_4x4_60MHz/docker-compose.yml @@ -16,7 +16,7 @@ services: - ../../conf_files/gnb-vnf.sa.band77.162prb.nfapi.4x4.conf:/opt/oai-gnb/etc/gnb.conf healthcheck: test: /bin/bash -c "pgrep nr-softmodem" - interval: 15s + interval: 5s timeout: 5s retries: 5 oai-pnf: @@ -35,7 +35,9 @@ services: volumes: - ../../conf_files/gnb-pnf.band77.usrpn310.4x4.conf:/opt/oai-gnb/etc/gnb.conf healthcheck: - test: /bin/bash -c "pgrep nr-softmodem" - interval: 15s + test: /bin/bash -c "/opt/oai-gnb/bin/check-prach-io.sh" + start_period: 15s + start_interval: 500ms + interval: 5s timeout: 5s retries: 5 diff --git a/ci-scripts/yaml_files/5g_sa_n310_gnb/docker-compose.yml b/ci-scripts/yaml_files/5g_sa_n310_gnb/docker-compose.yml index e93152bd37..562b72561a 100644 --- a/ci-scripts/yaml_files/5g_sa_n310_gnb/docker-compose.yml +++ b/ci-scripts/yaml_files/5g_sa_n310_gnb/docker-compose.yml @@ -16,7 +16,9 @@ services: volumes: - ../../conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf:/opt/oai-gnb/etc/gnb.conf healthcheck: - test: /bin/bash -c "pgrep nr-softmodem" - interval: 10s + test: /bin/bash -c "/opt/oai-gnb/bin/check-prach-io.sh" + start_period: 15s + start_interval: 500ms + interval: 5s timeout: 5s - retries: 5 + retries: 10 diff --git a/ci-scripts/yaml_files/sa_fhi_7.2_benetel550_gnb/docker-compose.yml b/ci-scripts/yaml_files/sa_fhi_7.2_benetel550_gnb/docker-compose.yml index a0bc415730..b70229ac94 100644 --- a/ci-scripts/yaml_files/sa_fhi_7.2_benetel550_gnb/docker-compose.yml +++ b/ci-scripts/yaml_files/sa_fhi_7.2_benetel550_gnb/docker-compose.yml @@ -22,10 +22,12 @@ services: oai-net: ipv4_address: 172.21.18.20 healthcheck: - test: /bin/bash -c "pgrep nr-softmodem" - interval: 10s + test: /bin/bash -c "/opt/oai-gnb/bin/check-prach-io.sh" + start_period: 15s + start_interval: 500ms + interval: 5s timeout: 5s - retries: 5 + retries: 10 networks: oai-net: driver: macvlan diff --git a/ci-scripts/yaml_files/sa_fhi_7.2_metanoia_2x2_gnb/docker-compose.yml b/ci-scripts/yaml_files/sa_fhi_7.2_metanoia_2x2_gnb/docker-compose.yml index 0dd0a6c99d..06273747bf 100644 --- a/ci-scripts/yaml_files/sa_fhi_7.2_metanoia_2x2_gnb/docker-compose.yml +++ b/ci-scripts/yaml_files/sa_fhi_7.2_metanoia_2x2_gnb/docker-compose.yml @@ -21,10 +21,12 @@ services: oai-net: ipv4_address: 172.21.18.20 healthcheck: - test: /bin/bash -c "pgrep nr-softmodem" - interval: 10s + test: /bin/bash -c "/opt/oai-gnb/bin/check-prach-io.sh" + start_period: 15s + start_interval: 500ms + interval: 5s timeout: 5s - retries: 5 + retries: 10 networks: oai-net: driver: macvlan diff --git a/ci-scripts/yaml_files/sa_fhi_7.2_vvdn_gnb/docker-compose.yml b/ci-scripts/yaml_files/sa_fhi_7.2_vvdn_gnb/docker-compose.yml index a74b583e2b..ff06893fa0 100644 --- a/ci-scripts/yaml_files/sa_fhi_7.2_vvdn_gnb/docker-compose.yml +++ b/ci-scripts/yaml_files/sa_fhi_7.2_vvdn_gnb/docker-compose.yml @@ -21,10 +21,13 @@ services: oai-net: ipv4_address: 172.21.18.20 healthcheck: - test: /bin/bash -c "pgrep nr-softmodem" - interval: 10s + test: /bin/bash -c "/opt/oai-gnb/bin/check-prach-io.sh" + start_period: 15s + start_interval: 500ms + interval: 5s timeout: 5s - retries: 5 + retries: 10 + networks: oai-net: driver: macvlan diff --git a/docker/Dockerfile.gNB.fhi72.rhel9 b/docker/Dockerfile.gNB.fhi72.rhel9 index 5f68599873..122b3b668d 100644 --- a/docker/Dockerfile.gNB.fhi72.rhel9 +++ b/docker/Dockerfile.gNB.fhi72.rhel9 @@ -71,6 +71,7 @@ WORKDIR /opt/oai-gnb/bin COPY --from=gnb-build \ /oai-ran/cmake_targets/ran_build/build/nr-softmodem ./ COPY ./docker/scripts/gnb_entrypoint.sh ./entrypoint.sh +COPY ./docker/scripts/check-prach-io.sh ./check-prach-io.sh COPY --from=gnb-build \ /oai-ran/cmake_targets/ran_build/build/librfsimulator.so \ diff --git a/docker/Dockerfile.gNB.fhi72.rocky b/docker/Dockerfile.gNB.fhi72.rocky index 3fdc2f97af..f95310059d 100644 --- a/docker/Dockerfile.gNB.fhi72.rocky +++ b/docker/Dockerfile.gNB.fhi72.rocky @@ -59,6 +59,7 @@ WORKDIR /opt/oai-gnb/bin COPY --from=gnb-build \ /oai-ran/cmake_targets/ran_build/build/nr-softmodem ./ COPY ./docker/scripts/gnb_entrypoint.sh ./entrypoint.sh +COPY ./docker/scripts/check-prach-io.sh ./check-prach-io.sh COPY --from=gnb-build \ /oai-ran/cmake_targets/ran_build/build/librfsimulator.so \ diff --git a/docker/Dockerfile.gNB.fhi72.ubuntu22 b/docker/Dockerfile.gNB.fhi72.ubuntu22 index 069055d63b..eb781281ec 100644 --- a/docker/Dockerfile.gNB.fhi72.ubuntu22 +++ b/docker/Dockerfile.gNB.fhi72.ubuntu22 @@ -71,6 +71,7 @@ WORKDIR /opt/oai-gnb/bin COPY --from=gnb-build \ /oai-ran/cmake_targets/ran_build/build/nr-softmodem ./ COPY ./docker/scripts/gnb_entrypoint.sh ./entrypoint.sh +COPY ./docker/scripts/check-prach-io.sh ./check-prach-io.sh COPY --from=gnb-build \ /oai-ran/cmake_targets/ran_build/build/librfsimulator.so \ diff --git a/docker/Dockerfile.gNB.rhel9 b/docker/Dockerfile.gNB.rhel9 index 824e3b3833..d02b6907d7 100644 --- a/docker/Dockerfile.gNB.rhel9 +++ b/docker/Dockerfile.gNB.rhel9 @@ -60,6 +60,7 @@ WORKDIR /opt/oai-gnb/bin COPY --from=gnb-build \ /oai-ran/cmake_targets/ran_build/build/nr-softmodem ./ COPY ./docker/scripts/gnb_entrypoint.sh ./entrypoint.sh +COPY ./docker/scripts/check-prach-io.sh ./check-prach-io.sh COPY --from=gnb-build \ /oai-ran/cmake_targets/ran_build/build/liboai_eth_transpro.so \ diff --git a/docker/Dockerfile.gNB.rocky b/docker/Dockerfile.gNB.rocky index 225432fdab..912de17ede 100644 --- a/docker/Dockerfile.gNB.rocky +++ b/docker/Dockerfile.gNB.rocky @@ -57,6 +57,7 @@ WORKDIR /opt/oai-gnb/bin COPY --from=gnb-build \ /oai-ran/cmake_targets/ran_build/build/nr-softmodem ./ COPY ./docker/scripts/gnb_entrypoint.sh ./entrypoint.sh +COPY ./docker/scripts/check-prach-io.sh ./check-prach-io.sh COPY --from=gnb-build \ /oai-ran/cmake_targets/ran_build/build/liboai_eth_transpro.so \ diff --git a/docker/Dockerfile.gNB.ubuntu22 b/docker/Dockerfile.gNB.ubuntu22 index 68c903450a..ea7b538c41 100644 --- a/docker/Dockerfile.gNB.ubuntu22 +++ b/docker/Dockerfile.gNB.ubuntu22 @@ -94,6 +94,7 @@ WORKDIR /opt/oai-gnb/bin COPY --from=gnb-build \ /oai-ran/cmake_targets/ran_build/build/nr-softmodem ./ COPY ./docker/scripts/gnb_entrypoint.sh ./entrypoint.sh +COPY ./docker/scripts/check-prach-io.sh ./check-prach-io.sh COPY --from=gnb-build \ /oai-ran/cmake_targets/ran_build/build/liboai_eth_transpro.so \ diff --git a/docker/scripts/check-prach-io.sh b/docker/scripts/check-prach-io.sh new file mode 100755 index 0000000000..1e1544dadf --- /dev/null +++ b/docker/scripts/check-prach-io.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +set -eo pipefail + +test -f /opt/oai-gnb/nrL1_stats.log && grep -oP 'PRACH I0 = \K[0-9.]*' /opt/oai-gnb/nrL1_stats.log | awk '{if ($1 > 0.0) exit 0; else exit 1}' From 63bdaaa1cb0a10e426ae10ebcebdfc7af68d862f Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Mon, 2 Jun 2025 13:43:31 +0200 Subject: [PATCH 112/964] CI: remove unused attributes in cls_containerize.py --- ci-scripts/cls_containerize.py | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index 29b71628ed..71e384c354 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -298,7 +298,6 @@ class Containerize(): self.yamlPath = ['', '', ''] self.services = ['', '', ''] self.deploymentTag = '' - self.eNB_logFile = ['', '', ''] self.testCase_id = '' @@ -307,17 +306,6 @@ class Containerize(): self.dockerfileprefix = '' self.host = '' - self.deployedContainers = [] - self.tsharkStarted = False - self.pingContName = '' - self.pingOptions = '' - self.pingLossThreshold = '' - self.svrContName = '' - self.svrOptions = '' - self.cliContName = '' - self.cliOptions = '' - - self.imageToCopy = '' #checkers from xml self.ran_checkers={} self.num_attempts = 1 From 136a59b42c0f58dd3ccb575abd2be099729aeaac Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Tue, 3 Jun 2025 23:38:50 +0200 Subject: [PATCH 113/964] CI: increase deployment interval for Cassandra database --- ci-scripts/yaml_files/4g_l2sim_fdd/docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci-scripts/yaml_files/4g_l2sim_fdd/docker-compose.yml b/ci-scripts/yaml_files/4g_l2sim_fdd/docker-compose.yml index 9f40fb856d..0d810a1d4b 100644 --- a/ci-scripts/yaml_files/4g_l2sim_fdd/docker-compose.yml +++ b/ci-scripts/yaml_files/4g_l2sim_fdd/docker-compose.yml @@ -10,7 +10,7 @@ services: CASSANDRA_ENDPOINT_SNITCH: GossipingPropertyFileSnitch healthcheck: test: /bin/bash -c "nodetool status" - interval: 10s + interval: 20s timeout: 5s retries: 5 From 1407784130264ac404826f0e1332b9d3fb867dfe Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Wed, 4 Jun 2025 12:45:44 +0200 Subject: [PATCH 114/964] =?UTF-8?q?CI:=20RFSim=205G=20=E2=80=93=20Wait=20f?= =?UTF-8?q?or=20IP=20address=20assignment=20before=20starting=20traffic=20?= =?UTF-8?q?test?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ci-scripts/xml_files/container_5g_rfsim_fr2_32prb.xml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ci-scripts/xml_files/container_5g_rfsim_fr2_32prb.xml b/ci-scripts/xml_files/container_5g_rfsim_fr2_32prb.xml index db10ff6478..1965f95aa0 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_fr2_32prb.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_fr2_32prb.xml @@ -29,6 +29,7 @@ 800813 000000 000001 + 000013 020001 020002 100001 @@ -68,6 +69,13 @@ 0 + + Attach_UE + Attach OAI UE (Wait for IP) + rfsim5g_ue + cacofonix + + Ping Ping ext-dn from NR-UE From 874d2b73a4c043acbd7fa9a60407b7241e9ae12a Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Wed, 4 Jun 2025 12:48:56 +0200 Subject: [PATCH 115/964] CI: reduce number of attach tries --- ci-scripts/cls_module.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci-scripts/cls_module.py b/ci-scripts/cls_module.py index 3ec6ffc9e5..4ef5c67ccd 100644 --- a/ci-scripts/cls_module.py +++ b/ci-scripts/cls_module.py @@ -107,7 +107,7 @@ class Module_UE: return self._logCollect() return None - def attach(self, attach_tries = 4, attach_timeout = 60): + def attach(self, attach_tries = 2, attach_timeout = 60): ip = None while attach_tries > 0: self._command(self.cmd_dict["attach"]) From cd1aaab014ea5835b36bfd4e564c1634b633117f Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 13 May 2025 18:09:20 +0200 Subject: [PATCH 116/964] Remove only UEs belonging to DU that disconnected The previous condition was wrong: if a UE did not have the assoc_id of the DU that connected (i.e., it was connected to another DU then the one disconnecting), it was marked for deletion. Instead, skip those UEs. --- openair2/RRC/NR/rrc_gNB_du.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openair2/RRC/NR/rrc_gNB_du.c b/openair2/RRC/NR/rrc_gNB_du.c index a650a03604..ad1ae30e03 100644 --- a/openair2/RRC/NR/rrc_gNB_du.c +++ b/openair2/RRC/NR/rrc_gNB_du.c @@ -457,7 +457,9 @@ static int invalidate_du_connections(gNB_RRC_INST *rrc, sctp_assoc_t assoc_id) nr_rrc_finalize_ho(UE); } f1_ue_data_t ue_data = cu_get_f1_ue_data(ue_id); - if (ue_data.du_assoc_id == assoc_id && IS_SA_MODE(get_softmodem_params())) { + if (ue_data.du_assoc_id != assoc_id) + continue; /* this UE is on another DU */ + if (IS_SA_MODE(get_softmodem_params())) { /* this UE belongs to the DU that disconnected, set du_assoc_id to 0, * meaning DU is offline, then trigger release request */ ue_data.du_assoc_id = 0; From a6c319e84ba5399eccc1c4cc830f78ffcd06c821 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 14 May 2025 09:47:28 +0200 Subject: [PATCH 117/964] Update handover documentation Point out that an error message is expected, after user feedback pointing out this somewhat confusing behavior. --- doc/handover-tutorial.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/doc/handover-tutorial.md b/doc/handover-tutorial.md index a367de868a..5381cd0cc8 100644 --- a/doc/handover-tutorial.md +++ b/doc/handover-tutorial.md @@ -54,7 +54,11 @@ Start DU0: sudo ./nr-softmodem --rfsim -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band78.106prb.rfsim.pci0.conf --rfsimulator.serveraddr 127.0.0.1 -Start the UE, and let it connect completely: +This will show an error `[HW] connect() to 127.0.0.1:4043 failed, +errno(111)`. _This is expected_, because the RFsim server is at the UE (to be +able to serve two RFsim clients, one DU each; see below for more info). Proceed +by starting the UE, and let it connect completely (this should make the error +go away): sudo ./nr-uesoftmodem -C 3450720000 -r 106 --numerology 1 --ssb 516 -O --rfsim --rfsimulator.serveraddr server From 249812e10dd013a212cb7a8565c6bce0fd0aa53f Mon Sep 17 00:00:00 2001 From: Reem Bahsoun Date: Tue, 27 May 2025 10:21:39 +0200 Subject: [PATCH 118/964] Clarify HO doc: describe where to put neighbour configuration --- doc/handover-tutorial.md | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/doc/handover-tutorial.md b/doc/handover-tutorial.md index 5381cd0cc8..5fe08be665 100644 --- a/doc/handover-tutorial.md +++ b/doc/handover-tutorial.md @@ -146,7 +146,7 @@ neighbour relation of the DUs at the CU. To do so, proceed as follows: ``` cat nrRRC_stats.log ``` -1. Fill in the `neighbour-config.conf` configuration file as shown below, and +1. Fill in the [`neighbour-config.conf`](../ci-scripts/conf_files/neighbour-config.conf) configuration file as shown below, and `@include` it in the CU file. 1. Start the CU and both DUs. 1. Bring the phone close to one cell, and leave flight mode. It should connect @@ -161,7 +161,7 @@ triggered: - Make sure that both DUs use the same hardware. - Make sure that the UE sees both cells. For instance, you can switch to flight mode, go closer to the other DU, and switch off flight mode -- the UE should - connect to that second UE. + connect to that second DU. - We did not manage handover with every phone yet -- make sure you use one of the list provided above. @@ -250,6 +250,15 @@ nr_measurement_configuration = { }) }; ``` +`@include` this configuration file inside the gNB section of CU file as shown below. + +``` + plmn_list = ({ mcc = 222; mnc = 01; mnc_length = 2; snssaiList = ({ sst = 1, sd = 0xffffff })}); + + + @include "neighbour-config.conf" + +``` # Handovers triggers and NTN From da915d21e04f8bf95a0776020348f8914d825eb7 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 2 Apr 2025 07:19:43 +0200 Subject: [PATCH 119/964] Add F1AP UE context setup request message enc/dec + test Reintroduce separate message types to simplify the encoding/decoding, including shorter names. The old types will be removed once everything has been migrated to the new encoder/decoder, which should ensure that everything is properly migrated to the unit-tested encoder/decoders. Also, for each type of F1 message (F1 UE context setup request, response, modification request, ...) introduce a separate type to avoid to mistakenly use wrong fields, which can lead to bugs. In this regard, the DL PDCP SN bit size in the DRB-ToBeSetup list of the UE context setup request is optional, as it will also be used in the UE context modification request DRB SetupMod list (which avoids quite some code duplication). The encoder checks that this IE is present, though. --- openair2/COMMON/f1ap_messages_types.h | 99 +++ openair2/F1AP/lib/CMakeLists.txt | 3 +- openair2/F1AP/lib/f1ap_lib_includes.h | 5 + openair2/F1AP/lib/f1ap_ue_context.c | 876 ++++++++++++++++++++++++++ openair2/F1AP/lib/f1ap_ue_context.h | 36 ++ openair2/F1AP/tests/CMakeLists.txt | 2 +- openair2/F1AP/tests/f1ap_lib_test.c | 170 +++++ 7 files changed, 1189 insertions(+), 2 deletions(-) create mode 100644 openair2/F1AP/lib/f1ap_ue_context.c create mode 100644 openair2/F1AP/lib/f1ap_ue_context.h diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h index 84d887f8f9..85f2def720 100644 --- a/openair2/COMMON/f1ap_messages_types.h +++ b/openair2/COMMON/f1ap_messages_types.h @@ -26,6 +26,7 @@ #include #include "common/5g_platform_types.h" #include "common/platform_constants.h" +#include "common/utils/ds/byte_array.h" //-------------------------------------------------------------------------------------------// // Defines to access message fields. @@ -452,6 +453,13 @@ typedef struct cu_to_du_rrc_information_s { uint32_t handoverPreparationInfo_length; }cu_to_du_rrc_information_t; +typedef struct f1ap_cu_to_du_rrc_info_s { + byte_array_t *cg_configinfo; + byte_array_t *ue_cap; + byte_array_t *meas_config; + byte_array_t *ho_prep_info; +} f1ap_cu_to_du_rrc_info_t; + typedef struct du_to_cu_rrc_information_s { uint8_t * cellGroupConfig; uint32_t cellGroupConfig_length; @@ -477,6 +485,97 @@ typedef enum TransmActionInd_e { TransmActionInd_RESTART, } TransmActionInd_t; +typedef struct f1ap_srb_to_setup_t { + int id; +} f1ap_srb_to_setup_t; + +/// 9.3.1.52 Packet Error Rate +typedef struct f1ap_per_t { + uint8_t scalar; + uint8_t exponent; +} f1ap_per_t; + +// 9.3.1.49 Non-Dynamic 5QI Descriptor +typedef struct f1ap_nondynamic_5qi_t { + int fiveQI; +} f1ap_nondynamic_5qi_t; + +// 9.3.1.47 Dynamic 5QI Descriptor +typedef struct f1ap_dynamic_5qi_t { + int prio; /// QoS Priority Level + int pdb; /// Packet Delay Budget + f1ap_per_t per; /// Packet Error Rate + bool *delay_critical; /// Delay Critical + int *avg_win; /// Averaging Window +} f1ap_dynamic_5qi_t; + +typedef struct f1ap_arp_t { + uint16_t prio; + preemption_capability_t preempt_cap; + preemption_vulnerability_t preempt_vuln; +} f1ap_arp_t; + +// 9.3.1.45 QoS Flow Level QoS Parameters +typedef struct f1ap_qos_flow_param_t { + fiveQI_t qos_type; + union { + f1ap_nondynamic_5qi_t nondyn; + f1ap_dynamic_5qi_t dyn; + }; + f1ap_arp_t arp; +} f1ap_qos_flow_param_t; + +// in 9.2.2.1 Flows Mapped to DRB Item +typedef struct f1ap_drb_flows_mapped_t { + int qfi; + f1ap_qos_flow_param_t param; +} f1ap_drb_flows_mapped_t; + +/// in 9.2.2.1 DRB Info in UE Context Setup Request +typedef struct f1ap_drb_info_nr_t { + f1ap_qos_flow_param_t drb_qos; + nssai_t nssai; + int flows_len; + f1ap_drb_flows_mapped_t *flows; +} f1ap_drb_info_nr_t; + +typedef enum { F1AP_PDCP_SN_12B, F1AP_PDCP_SN_18B } f1ap_pdcp_sn_len_t; +/// in 9.2.2.1 DRB to Be Setup Item IEs +typedef struct f1ap_drb_to_setup_t { + int id; + enum { F1AP_QOS_CHOICE_EUTRAN, F1AP_QOS_CHOICE_NR } qos_choice; + union { + // eutran not implemented + f1ap_drb_info_nr_t nr; + }; + int up_ul_tnl_len; + f1ap_up_tnl_t up_ul_tnl[2]; + f1ap_rlc_mode_t rlc_mode; + f1ap_pdcp_sn_len_t *dl_pdcp_sn_len; // in setup mandatory, in setupmod optional + f1ap_pdcp_sn_len_t *ul_pdcp_sn_len; +} f1ap_drb_to_setup_t; + +typedef struct f1ap_ue_context_setup_req_s { + uint32_t gNB_CU_ue_id; + uint32_t *gNB_DU_ue_id; + + plmn_id_t plmn; + uint64_t nr_cellid; + uint8_t servCellIndex; + + f1ap_cu_to_du_rrc_info_t cu_to_du_rrc_info; + + int srbs_len; + f1ap_srb_to_setup_t *srbs; + + int drbs_len; + f1ap_drb_to_setup_t *drbs; + + byte_array_t *rrc_container; + + uint64_t *gnb_du_ue_agg_mbr_ul; // C-ifDRBSetup +} f1ap_ue_context_setup_req_t; + typedef struct f1ap_ue_context_setup_s { uint32_t gNB_CU_ue_id; uint32_t gNB_DU_ue_id; diff --git a/openair2/F1AP/lib/CMakeLists.txt b/openair2/F1AP/lib/CMakeLists.txt index 0c6137dc30..978f69fb29 100644 --- a/openair2/F1AP/lib/CMakeLists.txt +++ b/openair2/F1AP/lib/CMakeLists.txt @@ -2,8 +2,9 @@ add_library(f1ap_lib OBJECT f1ap_lib_common.c f1ap_rrc_message_transfer.c f1ap_interface_management.c + f1ap_ue_context.c ) -target_link_libraries(f1ap_lib PRIVATE asn1_f1ap) +target_link_libraries(f1ap_lib PRIVATE asn1_f1ap ds) target_include_directories(f1ap_lib PUBLIC ${CMAKE_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR} diff --git a/openair2/F1AP/lib/f1ap_lib_includes.h b/openair2/F1AP/lib/f1ap_lib_includes.h index 267e7243e7..e34ec0598d 100644 --- a/openair2/F1AP/lib/f1ap_lib_includes.h +++ b/openair2/F1AP/lib/f1ap_lib_includes.h @@ -41,5 +41,10 @@ #include "F1AP_SibtypetobeupdatedListItem.h" #include "F1AP_UnsuccessfulOutcome.h" #include "F1AP_UE-associatedLogicalF1-ConnectionListRes.h" +#include "F1AP_ULUPTNLInformation-ToBeSetup-Item.h" +#include "F1AP_GTPTunnel.h" +#include "F1AP_Flows-Mapped-To-DRB-Item.h" +#include "F1AP_NonDynamic5QIDescriptor.h" +#include "F1AP_Dynamic5QIDescriptor.h" #endif /* F1AP_LIB_INCLUDES_H_ */ diff --git a/openair2/F1AP/lib/f1ap_ue_context.c b/openair2/F1AP/lib/f1ap_ue_context.c new file mode 100644 index 0000000000..572ad3ce6a --- /dev/null +++ b/openair2/F1AP/lib/f1ap_ue_context.c @@ -0,0 +1,876 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include "f1ap_ue_context.h" + +#include "f1ap_lib_common.h" +#include "f1ap_lib_includes.h" +#include "f1ap_messages_types.h" + +#include "common/utils/assertions.h" +#include "openair3/UTILS/conversions.h" +#include "common/utils/oai_asn1.h" +#include "common/utils/utils.h" +#include "common/utils/ds/byte_array.h" + +static F1AP_CUtoDURRCInformation_t encode_cu_to_du_rrc_info(const f1ap_cu_to_du_rrc_info_t *cu2du) +{ + F1AP_CUtoDURRCInformation_t enc = {0}; + + /* optional: cG_ConfigInfo */ + if (cu2du->cg_configinfo) { + asn1cCalloc(enc.cG_ConfigInfo, cG_ConfigInfo); + const byte_array_t *ba = cu2du->cg_configinfo; + OCTET_STRING_fromBuf(cG_ConfigInfo, (const char *)ba->buf, ba->len); + } + + /* optional: uE_CapabilityRAT_ContainerList */ + if (cu2du->ue_cap) { + asn1cCalloc(enc.uE_CapabilityRAT_ContainerList, uE_CapabilityRAT_ContainerList); + const byte_array_t *ba = cu2du->ue_cap; + OCTET_STRING_fromBuf(uE_CapabilityRAT_ContainerList, (const char *)ba->buf, ba->len); + } + + /* optional: measConfig */ + if (cu2du->meas_config) { + asn1cCalloc(enc.measConfig, measConfig); + const byte_array_t *ba = cu2du->meas_config; + OCTET_STRING_fromBuf(measConfig, (const char *)ba->buf, ba->len); + } + + /* optional: HandoverPreparationInformation */ + if (cu2du->ho_prep_info) { + F1AP_ProtocolExtensionContainer_10696P60_t *p = calloc_or_fail(1, sizeof(*p)); + enc.iE_Extensions = (struct F1AP_ProtocolExtensionContainer *)p; + asn1cSequenceAdd(p->list, F1AP_CUtoDURRCInformation_ExtIEs_t, ie_ext); + ie_ext->id = F1AP_ProtocolIE_ID_id_HandoverPreparationInformation; + ie_ext->criticality = F1AP_Criticality_ignore; + ie_ext->extensionValue.present = F1AP_CUtoDURRCInformation_ExtIEs__extensionValue_PR_HandoverPreparationInformation; + const byte_array_t *ba = cu2du->ho_prep_info; + F1AP_HandoverPreparationInformation_t *hpi = &ie_ext->extensionValue.choice.HandoverPreparationInformation; + OCTET_STRING_fromBuf(hpi, (const char *)ba->buf, ba->len); + } + return enc; +} + +static bool decode_cu_to_du_rrc_info(f1ap_cu_to_du_rrc_info_t *dec, const F1AP_CUtoDURRCInformation_t *cu2du) +{ + if (cu2du->cG_ConfigInfo) { + dec->cg_configinfo = calloc_or_fail(1, sizeof(*dec->cg_configinfo)); + const F1AP_CG_ConfigInfo_t *cgci = cu2du->cG_ConfigInfo; + *dec->cg_configinfo = create_byte_array(cgci->size, (uint8_t*)cgci->buf); + } + if (cu2du->uE_CapabilityRAT_ContainerList) { + dec->ue_cap = calloc_or_fail(1, sizeof(*dec->ue_cap)); + const F1AP_UE_CapabilityRAT_ContainerList_t *l = cu2du->uE_CapabilityRAT_ContainerList; + *dec->ue_cap = create_byte_array(l->size, (uint8_t*)l->buf); + } + if (cu2du->measConfig) { + dec->meas_config = calloc_or_fail(1, sizeof(*dec->meas_config)); + const F1AP_MeasConfig_t *mc = cu2du->measConfig; + *dec->meas_config = create_byte_array(mc->size, (uint8_t*)mc->buf); + } + if (cu2du->iE_Extensions) { + const F1AP_ProtocolExtensionContainer_10696P60_t *ext = (const F1AP_ProtocolExtensionContainer_10696P60_t *)cu2du->iE_Extensions; + for (int i = 0; i < ext->list.count; ++i) { + const F1AP_CUtoDURRCInformation_ExtIEs_t *cu2du_info_ext = ext->list.array[i]; + switch (cu2du_info_ext->id) { + case F1AP_ProtocolIE_ID_id_HandoverPreparationInformation: + dec->ho_prep_info = calloc_or_fail(1, sizeof(*dec->ho_prep_info)); + const F1AP_HandoverPreparationInformation_t *hopi = &cu2du_info_ext->extensionValue.choice.HandoverPreparationInformation; + *dec->ho_prep_info = create_byte_array(hopi->size, (uint8_t*) hopi->buf); + break; + default: + PRINT_ERROR("received unsupported F1AP CUtoDURRCInfo extension container %ld\n", cu2du_info_ext->id); + } + } + } + return true; +} + +static f1ap_cu_to_du_rrc_info_t cp_cu_to_du_rrc_info(const f1ap_cu_to_du_rrc_info_t *src) +{ + f1ap_cu_to_du_rrc_info_t dst = {0}; + CP_OPT_BYTE_ARRAY(dst.cg_configinfo, src->cg_configinfo); + CP_OPT_BYTE_ARRAY(dst.ue_cap, src->ue_cap); + CP_OPT_BYTE_ARRAY(dst.meas_config, src->meas_config); + CP_OPT_BYTE_ARRAY(dst.ho_prep_info, src->ho_prep_info); + return dst; +} + +static bool eq_ba(const byte_array_t a, const byte_array_t b) +{ + return eq_byte_array(&a, &b); +} + +static bool eq_cu_to_du_rrc_info(const f1ap_cu_to_du_rrc_info_t *a, const f1ap_cu_to_du_rrc_info_t *b) +{ + _F1_EQ_CHECK_OPTIONAL_IE(a, b, cg_configinfo, eq_ba); + _F1_EQ_CHECK_OPTIONAL_IE(a, b, ue_cap, eq_ba); + _F1_EQ_CHECK_OPTIONAL_IE(a, b, meas_config, eq_ba); + _F1_EQ_CHECK_OPTIONAL_IE(a, b, ho_prep_info, eq_ba); + return true; +} + +static void free_cu_to_du_rrc_info(f1ap_cu_to_du_rrc_info_t *cu2du) +{ + FREE_OPT_BYTE_ARRAY(cu2du->cg_configinfo); + FREE_OPT_BYTE_ARRAY(cu2du->ue_cap); + FREE_OPT_BYTE_ARRAY(cu2du->meas_config); + FREE_OPT_BYTE_ARRAY(cu2du->ho_prep_info); +} + +/* \brief Encode SRB-ToBeSetup List, for UE Context Setup Request, from + * f1ap_srb_to_setup_t. */ +static F1AP_SRBs_ToBeSetup_List_t encode_srbs_to_setup(int n, const f1ap_srb_to_setup_t *srbs) +{ + F1AP_SRBs_ToBeSetup_List_t list = {0}; + for (int i = 0; i < n; ++i) { + asn1cSequenceAdd(list, F1AP_SRBs_ToBeSetup_ItemIEs_t, itie); + itie->id = F1AP_ProtocolIE_ID_id_SRBs_ToBeSetup_Item; + itie->criticality = F1AP_Criticality_reject; + itie->value.present = F1AP_SRBs_ToBeSetup_ItemIEs__value_PR_SRBs_ToBeSetup_Item; + itie->value.choice.SRBs_ToBeSetup_Item.sRBID = srbs[i].id; + } + return list; +} + +/* \brief Decode SRB-ToBeSetup List, from UE Context Setup Request, into + * f1ap_srb_to_setup_t. */ +static bool decode_srbs_to_setup(const F1AP_SRBs_ToBeSetup_List_t *f1ap, int *n, f1ap_srb_to_setup_t **out) +{ + DevAssert(out != NULL); + *out = NULL; + int count = *n = f1ap->list.count; + if (count == 0) + return true; + + f1ap_srb_to_setup_t *srbs = *out = calloc_or_fail(count, sizeof(*srbs)); + for (int i = 0; i < count; ++i) { + const F1AP_SRBs_ToBeSetup_ItemIEs_t *itie = (F1AP_SRBs_ToBeSetup_ItemIEs_t *)f1ap->list.array[i]; + _F1_EQ_CHECK_LONG(itie->id, F1AP_ProtocolIE_ID_id_SRBs_ToBeSetup_Item); + _F1_EQ_CHECK_INT(itie->value.present, F1AP_SRBs_ToBeSetup_ItemIEs__value_PR_SRBs_ToBeSetup_Item); + srbs[i].id = itie->value.choice.SRBs_ToBeSetup_Item.sRBID; + } + + return true; +} + +static f1ap_srb_to_setup_t cp_srb_to_setup(const f1ap_srb_to_setup_t *orig) +{ + f1ap_srb_to_setup_t cp = { + .id = orig->id, + }; + return cp; +} + +static bool eq_srb_to_setup(const f1ap_srb_to_setup_t *a, const f1ap_srb_to_setup_t *b) +{ + _F1_EQ_CHECK_INT(a->id, b->id); + return true; +} + +static void free_srb_to_setup(f1ap_srb_to_setup_t *srbs) +{ + // nothing to free +} + +static F1AP_QoSFlowLevelQoSParameters_t encode_qos_flow_param(const f1ap_qos_flow_param_t *p) +{ + F1AP_QoSFlowLevelQoSParameters_t f1ap = {0}; + + if (p->qos_type == NON_DYNAMIC) { + f1ap.qoS_Characteristics.present = F1AP_QoS_Characteristics_PR_non_Dynamic_5QI; + asn1cCalloc(f1ap.qoS_Characteristics.choice.non_Dynamic_5QI, nd); + nd->fiveQI = p->nondyn.fiveQI; + } else { + DevAssert(p->qos_type == DYNAMIC); + f1ap.qoS_Characteristics.present = F1AP_QoS_Characteristics_PR_dynamic_5QI; + asn1cCalloc(f1ap.qoS_Characteristics.choice.dynamic_5QI, d); + + d->qoSPriorityLevel = p->dyn.prio; + d->packetDelayBudget = p->dyn.pdb; + d->packetErrorRate.pER_Scalar = p->dyn.per.scalar; + d->packetErrorRate.pER_Exponent = p->dyn.per.exponent; + + if (p->dyn.delay_critical) { + e_F1AP_Dynamic5QIDescriptor__delayCritical v = *p->dyn.delay_critical + ? F1AP_Dynamic5QIDescriptor__delayCritical_delay_critical + : F1AP_Dynamic5QIDescriptor__delayCritical_non_delay_critical; + asn1cCallocOne(d->delayCritical, v); + } + + if (p->dyn.avg_win) + asn1cCallocOne(d->averagingWindow, *p->dyn.avg_win); + } + + F1AP_NGRANAllocationAndRetentionPriority_t *arp = &f1ap.nGRANallocationRetentionPriority; + arp->priorityLevel = p->arp.prio; + arp->pre_emptionCapability = p->arp.preempt_cap; + arp->pre_emptionVulnerability = p->arp.preempt_vuln; + return f1ap; +} + +static bool decode_qos_flow_param(const F1AP_QoSFlowLevelQoSParameters_t *f1ap, f1ap_qos_flow_param_t *out) +{ + if (f1ap->qoS_Characteristics.present == F1AP_QoS_Characteristics_PR_non_Dynamic_5QI) { + out->qos_type = NON_DYNAMIC; + const F1AP_NonDynamic5QIDescriptor_t *nondyn = f1ap->qoS_Characteristics.choice.non_Dynamic_5QI; + out->nondyn.fiveQI = nondyn->fiveQI; + } else { + _F1_EQ_CHECK_INT(f1ap->qoS_Characteristics.present, F1AP_QoS_Characteristics_PR_dynamic_5QI); + const F1AP_Dynamic5QIDescriptor_t *d = f1ap->qoS_Characteristics.choice.dynamic_5QI; + out->qos_type = DYNAMIC; + out->dyn.prio = d->qoSPriorityLevel; + out->dyn.pdb = d->packetDelayBudget; + out->dyn.per.scalar = d->packetErrorRate.pER_Scalar; + out->dyn.per.exponent = d->packetErrorRate.pER_Exponent; + + if (d->delayCritical) { + bool v = *d->delayCritical == F1AP_Dynamic5QIDescriptor__delayCritical_delay_critical; + _F1_MALLOC(out->dyn.delay_critical, v); + } + + if (d->averagingWindow) + _F1_MALLOC(out->dyn.avg_win, *d->averagingWindow); + } + + const F1AP_NGRANAllocationAndRetentionPriority_t *arp = &f1ap->nGRANallocationRetentionPriority; + out->arp.prio = arp->priorityLevel; + out->arp.preempt_cap = arp->pre_emptionCapability; + out->arp.preempt_vuln = arp->pre_emptionVulnerability; + return true; +} + +static f1ap_qos_flow_param_t cp_qos_flow_param(const f1ap_qos_flow_param_t *orig) +{ + f1ap_qos_flow_param_t cp = { + .qos_type = orig->qos_type, + // dyn/nondyn below + .arp = orig->arp, + }; + if (cp.qos_type == NON_DYNAMIC) { + cp.nondyn.fiveQI = orig->nondyn.fiveQI; + } else { + DevAssert(cp.qos_type == DYNAMIC); + f1ap_dynamic_5qi_t *cpdyn = &cp.dyn; + const f1ap_dynamic_5qi_t *odyn = &orig->dyn; + cpdyn->prio = odyn->prio; + cpdyn->pdb = odyn->pdb; + cpdyn->per.scalar = odyn->per.scalar; + cpdyn->per.exponent = odyn->per.exponent; + if (odyn->delay_critical) + _F1_MALLOC(cpdyn->delay_critical, *odyn->delay_critical); + if (odyn->avg_win) + _F1_MALLOC(cpdyn->avg_win, *odyn->avg_win); + } + return cp; +} + +static bool eq_qos_flow_param(const f1ap_qos_flow_param_t *a, const f1ap_qos_flow_param_t *b) +{ + _F1_EQ_CHECK_INT(a->qos_type, b->qos_type); + if (a->qos_type == NON_DYNAMIC) { + _F1_EQ_CHECK_INT(a->nondyn.fiveQI, b->nondyn.fiveQI); + } else { + DevAssert(a->qos_type == DYNAMIC); + DevAssert(b->qos_type == DYNAMIC); + const f1ap_dynamic_5qi_t *adyn = &a->dyn, *bdyn = &b->dyn; + _F1_EQ_CHECK_INT(adyn->prio, bdyn->prio); + _F1_EQ_CHECK_INT(adyn->pdb, bdyn->pdb); + _F1_EQ_CHECK_INT(adyn->per.scalar, bdyn->per.scalar); + _F1_EQ_CHECK_INT(adyn->per.exponent, bdyn->per.exponent); + _F1_EQ_CHECK_OPTIONAL_IE(adyn, bdyn, delay_critical, _F1_EQ_CHECK_INT); + _F1_EQ_CHECK_OPTIONAL_IE(adyn, bdyn, avg_win, _F1_EQ_CHECK_INT); + } + _F1_EQ_CHECK_INT(a->arp.prio, b->arp.prio); + _F1_EQ_CHECK_INT(a->arp.preempt_cap, b->arp.preempt_cap); + _F1_EQ_CHECK_INT(a->arp.preempt_vuln, b->arp.preempt_vuln); + return true; +} + +static void free_qos_flow_param(f1ap_qos_flow_param_t *p) +{ + if (p->qos_type == NON_DYNAMIC) { + // nothing to free + } else { + DevAssert(p->qos_type == DYNAMIC); + free(p->dyn.delay_critical); + free(p->dyn.avg_win); + } + // arp: nothing to free +} + +static F1AP_DRB_Information_t encode_drb_info_nr(const f1ap_drb_info_nr_t *drb) +{ + F1AP_DRB_Information_t f1ap = {0}; + + f1ap.dRB_QoS = encode_qos_flow_param(&drb->drb_qos); + f1ap.sNSSAI = encode_nssai(&drb->nssai); + + for (int i = 0; i < drb->flows_len; ++i) { + asn1cSequenceAdd(f1ap.flows_Mapped_To_DRB_List.list, F1AP_Flows_Mapped_To_DRB_Item_t, it); + it->qoSFlowIdentifier = drb->flows[i].qfi; + it->qoSFlowLevelQoSParameters = encode_qos_flow_param(&drb->flows[i].param); + } + + return f1ap; +} + +static bool decode_drb_info_nr(const F1AP_DRB_Information_t *f1ap, f1ap_drb_info_nr_t *out) +{ + _F1_CHECK_EXP(decode_qos_flow_param(&f1ap->dRB_QoS, &out->drb_qos)); + out->nssai = decode_nssai(&f1ap->sNSSAI); + out->flows_len = f1ap->flows_Mapped_To_DRB_List.list.count; + out->flows = calloc_or_fail(out->flows_len, sizeof(*out->flows)); + for (int i = 0; i < out->flows_len; ++i) { + const F1AP_Flows_Mapped_To_DRB_Item_t *it = f1ap->flows_Mapped_To_DRB_List.list.array[i]; + out->flows[i].qfi = it->qoSFlowIdentifier; + _F1_CHECK_EXP(decode_qos_flow_param(&it->qoSFlowLevelQoSParameters, &out->flows[i].param)); + } + return true; +} + +static f1ap_drb_info_nr_t cp_drb_info_nr(const f1ap_drb_info_nr_t *orig) +{ + f1ap_drb_info_nr_t cp = { + .drb_qos = cp_qos_flow_param(&orig->drb_qos), + .nssai = orig->nssai, + .flows_len = orig->flows_len, + // flows below + }; + cp.flows = calloc_or_fail(cp.flows_len, sizeof(*cp.flows)); + for (int i = 0; i < cp.flows_len; ++i) { + cp.flows[i].qfi = orig->flows[i].qfi; + cp.flows[i].param = cp_qos_flow_param(&orig->flows[i].param); + } + return cp; +} + +static bool eq_drb_info_nr(const f1ap_drb_info_nr_t *a, const f1ap_drb_info_nr_t *b) +{ + _F1_CHECK_EXP(eq_qos_flow_param(&a->drb_qos, &b->drb_qos)); + _F1_EQ_CHECK_INT(a->nssai.sst, b->nssai.sst); + _F1_EQ_CHECK_INT(a->nssai.sd, b->nssai.sd); + _F1_EQ_CHECK_INT(a->flows_len, b->flows_len); + for (int i = 0; i < a->flows_len; ++i) { + _F1_EQ_CHECK_INT(a->flows[i].qfi, b->flows[i].qfi); + _F1_CHECK_EXP(eq_qos_flow_param(&a->flows[i].param, &b->flows[i].param)); + } + return true; +} + +static void free_drb_info_nr(f1ap_drb_info_nr_t *p) +{ + free_qos_flow_param(&p->drb_qos); + // nssai: nothing + for (int i = 0; i < p->flows_len; ++i) + free_qos_flow_param(&p->flows[i].param); + free(p->flows); +} + +static F1AP_RLCMode_t rlc_mode_to_asn1(f1ap_rlc_mode_t mode) +{ + switch (mode) { + case F1AP_RLC_MODE_AM: + return F1AP_RLCMode_rlc_am; + case F1AP_RLC_MODE_UM_BIDIR: + return F1AP_RLCMode_rlc_um_bidirectional; + default: + break; + } + AssertFatal(false, "unsupported RLC Mode %d received\n", mode); + return F1AP_RLCMode_rlc_am; // won't be reached +} + +static bool rlc_mode_from_asn1(F1AP_RLCMode_t mode, f1ap_rlc_mode_t *out) +{ + switch (mode) { + case F1AP_RLCMode_rlc_am: + *out = F1AP_RLC_MODE_AM; + return true; + case F1AP_RLCMode_rlc_um_bidirectional: + *out = F1AP_RLC_MODE_UM_BIDIR; + return true; + default: + PRINT_ERROR("unsupported RLC Mode %ld received: setting AM\n", mode); + break; + } + return false; +} + +static F1AP_UPTransportLayerInformation_t encode_up_tnl(const f1ap_up_tnl_t *tnl) +{ + F1AP_UPTransportLayerInformation_t tnl_info = { .present = F1AP_UPTransportLayerInformation_PR_gTPTunnel, }; + asn1cCalloc(tnl_info.choice.gTPTunnel, gtp_tnl); + TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(tnl->tl_address, >p_tnl->transportLayerAddress); + INT32_TO_OCTET_STRING(tnl->teid, >p_tnl->gTP_TEID); + return tnl_info; +} + +static bool decode_up_tnl(const F1AP_UPTransportLayerInformation_t *tnl_info, f1ap_up_tnl_t *out) +{ + _F1_EQ_CHECK_INT(tnl_info->present, F1AP_UPTransportLayerInformation_PR_gTPTunnel); + const F1AP_GTPTunnel_t *gtp_tnl = tnl_info->choice.gTPTunnel; + BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(>p_tnl->transportLayerAddress, out->tl_address); + OCTET_STRING_TO_UINT32(>p_tnl->gTP_TEID, out->teid); + return true; +} + +static f1ap_up_tnl_t cp_up_tnl(const f1ap_up_tnl_t *orig) +{ + f1ap_up_tnl_t cp = { .teid = orig->teid, }; + memcpy(&cp.tl_address, &orig->tl_address, sizeof(orig->tl_address)); + return cp; +} + +static bool eq_up_tnl(const f1ap_up_tnl_t *a, const f1ap_up_tnl_t *b) +{ + if (memcmp(&a->tl_address, &b->tl_address, sizeof(a->tl_address)) != 0) { + PRINT_ERROR("tl_address mismatch\n"); + return false; + } + _F1_EQ_CHECK_INT(a->teid, b->teid); + return true; +} + +static void free_up_tnl(const f1ap_up_tnl_t *tnl) +{ + // nothing to free +} + +/* Encode a DRBs_ToSetup list for UE Context Setup Request, from f1ap_drb_to_setup_t. */ +static F1AP_DRBs_ToBeSetup_List_t encode_drbs_to_setup(int n, const f1ap_drb_to_setup_t *drbs) +{ + F1AP_DRBs_ToBeSetup_List_t list = {0}; + for (int i = 0; i < n; ++i) { + const f1ap_drb_to_setup_t *drb = &drbs[i]; + asn1cSequenceAdd(list, F1AP_DRBs_ToBeSetup_ItemIEs_t, itie); + itie->id = F1AP_ProtocolIE_ID_id_DRBs_ToBeSetup_Item; + itie->criticality = F1AP_Criticality_reject; + itie->value.present = F1AP_DRBs_ToBeSetup_ItemIEs__value_PR_DRBs_ToBeSetup_Item; + + F1AP_DRBs_ToBeSetup_Item_t *it = &itie->value.choice.DRBs_ToBeSetup_Item; + it->dRBID = drb->id; + AssertFatal(drb->qos_choice == F1AP_QOS_CHOICE_NR, "only NR QoS choice implemented\n"); + it->qoSInformation.present = F1AP_QoSInformation_PR_choice_extension; + F1AP_QoSInformation_ExtIEs_t *qos_ext_ie = calloc_or_fail(1, sizeof(*qos_ext_ie)); + it->qoSInformation.choice.choice_extension = (struct F1AP_ProtocolIE_SingleContainer *)qos_ext_ie; + qos_ext_ie->id = F1AP_ProtocolIE_ID_id_DRB_Information; + qos_ext_ie->criticality = F1AP_Criticality_reject; + qos_ext_ie->value.present = F1AP_QoSInformation_ExtIEs__value_PR_DRB_Information; + qos_ext_ie->value.choice.DRB_Information = encode_drb_info_nr(&drb->nr); + + /* 12.1.3 uLUPTNLInformation_ToBeSetup_List */ + for (int j = 0; j < drb->up_ul_tnl_len; j++) { + DevAssert(drb->up_ul_tnl[j].teid > 0); + asn1cSequenceAdd(it->uLUPTNLInformation_ToBeSetup_List.list, F1AP_ULUPTNLInformation_ToBeSetup_Item_t, tnl_it); + tnl_it->uLUPTNLInformation = encode_up_tnl(&drb->up_ul_tnl[j]); + } + + it->rLCMode = rlc_mode_to_asn1(drb->rlc_mode); + + F1AP_ProtocolExtensionContainer_10696P82_t *ext = calloc_or_fail(1, sizeof(*ext)); + it->iE_Extensions = (struct F1AP_ProtocolExtensionContainer *)ext; + asn1cSequenceAdd(ext->list, F1AP_DRBs_ToBeSetup_ItemExtIEs_t, ext_ie); + ext_ie->id = F1AP_ProtocolIE_ID_id_DLPDCPSNLength; + ext_ie->criticality = F1AP_Criticality_ignore; + ext_ie->extensionValue.present = F1AP_DRBs_ToBeSetup_ItemExtIEs__extensionValue_PR_PDCPSNLength; + AssertFatal(drb->dl_pdcp_sn_len != NULL, "dl_pdcp_sn_len required for setup\n"); + ext_ie->extensionValue.choice.PDCPSNLength = *drb->dl_pdcp_sn_len; + + if (drb->ul_pdcp_sn_len) { + asn1cSequenceAdd(ext->list, F1AP_DRBs_ToBeSetup_ItemExtIEs_t, ext_ie); + ext_ie->id = F1AP_ProtocolIE_ID_id_ULPDCPSNLength; + ext_ie->criticality = F1AP_Criticality_ignore; + ext_ie->extensionValue.present = F1AP_DRBs_ToBeSetup_ItemExtIEs__extensionValue_PR_PDCPSNLength_1; + ext_ie->extensionValue.choice.PDCPSNLength_1 = *drb->ul_pdcp_sn_len; + } + } + return list; +} + +/* \brief Decode DRBS-ToBeSetup list from UE Context Setup request, into + * f1ap_drb_to_setup_t. */ +static bool decode_drbs_to_setup(const F1AP_DRBs_ToBeSetup_List_t *f1ap, int *n, f1ap_drb_to_setup_t **out) +{ + DevAssert(out != NULL); + *out = NULL; + int count = *n = f1ap->list.count; + if (count == 0) + return true; + + f1ap_drb_to_setup_t *drbs = *out = calloc_or_fail(count, sizeof(*drbs)); + for (int i = 0; i < count; ++i) { + const F1AP_DRBs_ToBeSetup_ItemIEs_t *itie = (const F1AP_DRBs_ToBeSetup_ItemIEs_t *)f1ap->list.array[i]; + _F1_EQ_CHECK_LONG(itie->id, F1AP_ProtocolIE_ID_id_DRBs_ToBeSetup_Item); + _F1_EQ_CHECK_INT(itie->value.present, F1AP_DRBs_ToBeSetup_ItemIEs__value_PR_DRBs_ToBeSetup_Item); + const F1AP_DRBs_ToBeSetup_Item_t *it = &itie->value.choice.DRBs_ToBeSetup_Item; + + f1ap_drb_to_setup_t *drb = &drbs[i]; + drb->id = it->dRBID; + + _F1_EQ_CHECK_INT(it->qoSInformation.present, F1AP_QoSInformation_PR_choice_extension); + const F1AP_QoSInformation_ExtIEs_t *qos_ext = (F1AP_QoSInformation_ExtIEs_t *)it->qoSInformation.choice.choice_extension; + _F1_EQ_CHECK_LONG(qos_ext->id, F1AP_ProtocolIE_ID_id_DRB_Information); + _F1_EQ_CHECK_INT(qos_ext->value.present, F1AP_QoSInformation_ExtIEs__value_PR_DRB_Information); + drb->qos_choice = F1AP_QOS_CHOICE_NR; + _F1_CHECK_EXP(decode_drb_info_nr(&qos_ext->value.choice.DRB_Information, &drb->nr)); + + drb->up_ul_tnl_len = it->uLUPTNLInformation_ToBeSetup_List.list.count; + _F1_EQ_CHECK_GENERIC(drb->up_ul_tnl_len > 0 && drb->up_ul_tnl_len <= 2, "%d", drb->up_ul_tnl_len, 1); + for (int j = 0; j < drb->up_ul_tnl_len; ++j) { + const F1AP_ULUPTNLInformation_ToBeSetup_Item_t *it_tnl = it->uLUPTNLInformation_ToBeSetup_List.list.array[j]; + _F1_CHECK_EXP(decode_up_tnl(&it_tnl->uLUPTNLInformation, &drb->up_ul_tnl[j])); + } + + _F1_CHECK_EXP(rlc_mode_from_asn1(it->rLCMode, &drb->rlc_mode)); + + _F1_CHECK_EXP(it->iE_Extensions); // PDCP SN length is under extension, is mandatory + const F1AP_ProtocolExtensionContainer_10696P82_t *ext = (const F1AP_ProtocolExtensionContainer_10696P82_t *)it->iE_Extensions; + const F1AP_DRBs_ToBeSetup_ItemExtIEs_t *ie; + F1AP_LIB_FIND_IE(F1AP_DRBs_ToBeSetup_ItemExtIEs_t, ie, &ext->list, F1AP_ProtocolIE_ID_id_DLPDCPSNLength, true); + + for (int j = 0; j < ext->list.count; ++j) { + ie = ext->list.array[j]; + AssertError(ie != NULL, return false, "ext->list.array[j] is NULL"); + switch (ie->id) { + case F1AP_ProtocolIE_ID_id_DLPDCPSNLength: + _F1_EQ_CHECK_INT(ie->extensionValue.present, F1AP_DRBs_ToBeSetup_ItemExtIEs__extensionValue_PR_PDCPSNLength); + _F1_MALLOC(drb->dl_pdcp_sn_len, ie->extensionValue.choice.PDCPSNLength); + break; + case F1AP_ProtocolIE_ID_id_ULPDCPSNLength: + _F1_EQ_CHECK_INT(ie->extensionValue.present, F1AP_DRBs_ToBeSetup_ItemExtIEs__extensionValue_PR_PDCPSNLength_1); + _F1_MALLOC(drb->ul_pdcp_sn_len, ie->extensionValue.choice.PDCPSNLength_1); + break; + default: + PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld unknown, skipping\n", ie->id); + break; + } + } + } + + return true; +} + +static f1ap_drb_to_setup_t cp_drb_to_setup(const f1ap_drb_to_setup_t *orig) +{ + f1ap_drb_to_setup_t cp = { + .id = orig->id, + .qos_choice = orig->qos_choice, + // nr below + .up_ul_tnl_len = orig->up_ul_tnl_len, + .up_ul_tnl[0] = cp_up_tnl(&orig->up_ul_tnl[0]), + .up_ul_tnl[1] = cp_up_tnl(&orig->up_ul_tnl[1]), + .rlc_mode = orig->rlc_mode, + // dl_pdcp_sn_len below + // ul_pdcp_sn_len below + }; + AssertFatal(cp.qos_choice == F1AP_QOS_CHOICE_NR, "only NR QoS choice implemented\n"); + if (orig->qos_choice == F1AP_QOS_CHOICE_NR) + cp.nr = cp_drb_info_nr(&orig->nr); + if (orig->dl_pdcp_sn_len) { + _F1_MALLOC(cp.dl_pdcp_sn_len, *orig->dl_pdcp_sn_len); + } + if (orig->ul_pdcp_sn_len) { + _F1_MALLOC(cp.ul_pdcp_sn_len, *orig->ul_pdcp_sn_len); + } + return cp; +} + +static bool eq_drb_to_setup(const f1ap_drb_to_setup_t *a, const f1ap_drb_to_setup_t *b) +{ + _F1_EQ_CHECK_INT(a->id, b->id); + _F1_EQ_CHECK_INT(a->qos_choice, b->qos_choice); + AssertFatal(a->qos_choice == F1AP_QOS_CHOICE_NR, "only NR QoS choice implemented\n"); + if (a->qos_choice == F1AP_QOS_CHOICE_NR) + eq_drb_info_nr(&a->nr, &b->nr); + _F1_EQ_CHECK_INT(a->up_ul_tnl_len, b->up_ul_tnl_len); + for (int i = 0; i < a->up_ul_tnl_len; ++i) { + _F1_CHECK_EXP(eq_up_tnl(&a->up_ul_tnl[i], &b->up_ul_tnl[i])); + } + _F1_EQ_CHECK_INT(a->rlc_mode, b->rlc_mode); + _F1_EQ_CHECK_OPTIONAL_IE(a, b, dl_pdcp_sn_len, _F1_EQ_CHECK_INT); + _F1_EQ_CHECK_OPTIONAL_IE(a, b, ul_pdcp_sn_len, _F1_EQ_CHECK_INT); + return true; +} + +static void free_drb_to_setup(f1ap_drb_to_setup_t *drb) +{ + if (drb->qos_choice == F1AP_QOS_CHOICE_NR) + free_drb_info_nr(&drb->nr); + for (int i = 0; i < drb->up_ul_tnl_len; ++i) + free_up_tnl(&drb->up_ul_tnl[i]); + free(drb->dl_pdcp_sn_len); + free(drb->ul_pdcp_sn_len); +} + +/** + * @brief Encode F1 UE context setup request to ASN.1 + */ +F1AP_F1AP_PDU_t *encode_ue_context_setup_req(const f1ap_ue_context_setup_req_t *req) +{ + F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); + + /* Message Type */ + pdu->present = F1AP_F1AP_PDU_PR_initiatingMessage; + asn1cCalloc(pdu->choice.initiatingMessage, tmp); + tmp->procedureCode = F1AP_ProcedureCode_id_UEContextSetup; + tmp->criticality = F1AP_Criticality_reject; + tmp->value.present = F1AP_InitiatingMessage__value_PR_UEContextSetupRequest; + F1AP_UEContextSetupRequest_t *out = &tmp->value.choice.UEContextSetupRequest; + + /* mandatory: GNB_CU_UE_F1AP_ID */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie1); + ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; + ie1->criticality = F1AP_Criticality_reject; + ie1->value.present = F1AP_UEContextSetupRequestIEs__value_PR_GNB_CU_UE_F1AP_ID; + ie1->value.choice.GNB_CU_UE_F1AP_ID = req->gNB_CU_ue_id; + + /* optional: GNB_DU_UE_F1AP_ID */ + if (req->gNB_DU_ue_id) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie); + ie->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; + ie->criticality = F1AP_Criticality_ignore; + ie->value.present = F1AP_UEContextSetupRequestIEs__value_PR_GNB_DU_UE_F1AP_ID; + ie->value.choice.GNB_DU_UE_F1AP_ID = *req->gNB_DU_ue_id; + } + + /* mandatory: SpCell ID/NRCGI */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie3); + ie3->id = F1AP_ProtocolIE_ID_id_SpCell_ID; + ie3->criticality = F1AP_Criticality_reject; + ie3->value.present = F1AP_UEContextSetupRequestIEs__value_PR_NRCGI; + F1AP_NRCGI_t *nrcgi = &ie3->value.choice.NRCGI; + const plmn_id_t *plmn = &req->plmn; + MCC_MNC_TO_PLMNID(plmn->mcc,plmn->mnc,plmn->mnc_digit_length, &nrcgi->pLMN_Identity); + NR_CELL_ID_TO_BIT_STRING(req->nr_cellid, &nrcgi->nRCellIdentity); + + /* mandatory: ServCellIndox */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie4); + ie4->id = F1AP_ProtocolIE_ID_id_ServCellIndex; + ie4->criticality = F1AP_Criticality_reject; + ie4->value.present = F1AP_UEContextSetupRequestIEs__value_PR_ServCellIndex; + ie4->value.choice.ServCellIndex = req->servCellIndex; + + /* mandatory: CUtoDURRCInformation */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie6); + ie6->id = F1AP_ProtocolIE_ID_id_CUtoDURRCInformation; + ie6->criticality = F1AP_Criticality_reject; + ie6->value.present = F1AP_UEContextSetupRequestIEs__value_PR_CUtoDURRCInformation; + ie6->value.choice.CUtoDURRCInformation = encode_cu_to_du_rrc_info(&req->cu_to_du_rrc_info); + + /* optional: SRB to be setup list */ + if (req->srbs_len > 0) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie); + ie->id = F1AP_ProtocolIE_ID_id_SRBs_ToBeSetup_List; + ie->criticality = F1AP_Criticality_reject; + ie->value.present = F1AP_UEContextSetupRequestIEs__value_PR_SRBs_ToBeSetup_List; + ie->value.choice.SRBs_ToBeSetup_List = encode_srbs_to_setup(req->srbs_len, req->srbs); + } + + /* optional: DRB to be setup list */ + if (req->drbs_len > 0) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie); + ie->id = F1AP_ProtocolIE_ID_id_DRBs_ToBeSetup_List; + ie->criticality = F1AP_Criticality_reject; + ie->value.present = F1AP_UEContextSetupRequestIEs__value_PR_DRBs_ToBeSetup_List; + ie->value.choice.DRBs_ToBeSetup_List = encode_drbs_to_setup(req->drbs_len, req->drbs); + } + + /* optional: RRC container */ + if (req->rrc_container) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie); + ie->id = F1AP_ProtocolIE_ID_id_RRCContainer; + ie->criticality = F1AP_Criticality_ignore; + ie->value.present = F1AP_UEContextSetupRequestIEs__value_PR_RRCContainer; + OCTET_STRING_fromBuf(&ie->value.choice.RRCContainer, (const char *)req->rrc_container->buf, req->rrc_container->len); + } + + /* conditional if DRB setup list: gNB-DU UE Aggregate Maximum Bit Rate Uplink */ + if (req->gnb_du_ue_agg_mbr_ul) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie); + ie->id = F1AP_ProtocolIE_ID_id_GNB_DU_UE_AMBR_UL; + ie->criticality = F1AP_Criticality_ignore; + ie->value.present = F1AP_UEContextSetupRequestIEs__value_PR_BitRate; + asn_long2INTEGER(&ie->value.choice.BitRate, *req->gnb_du_ue_agg_mbr_ul); + } + + return pdu; +} + +/** + * @brief Decode F1 UE Context Setup Request + */ +bool decode_ue_context_setup_req(const F1AP_F1AP_PDU_t *pdu, f1ap_ue_context_setup_req_t *out) +{ + DevAssert(out != NULL); + memset(out, 0, sizeof(*out)); + + F1AP_UEContextSetupRequest_t *in = &pdu->choice.initiatingMessage->value.choice.UEContextSetupRequest; + F1AP_UEContextSetupRequestIEs_t *ie; + + F1AP_LIB_FIND_IE(F1AP_UEContextSetupRequestIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); + F1AP_LIB_FIND_IE(F1AP_UEContextSetupRequestIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_SpCell_ID, true); + F1AP_LIB_FIND_IE(F1AP_UEContextSetupRequestIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_ServCellIndex, true); + F1AP_LIB_FIND_IE(F1AP_UEContextSetupRequestIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_CUtoDURRCInformation, true); + + for (int i = 0; i < in->protocolIEs.list.count; ++i) { + ie = in->protocolIEs.list.array[i]; + AssertError(ie != NULL, return false, "in->protocolIEs.list.array[i] is NULL"); + switch (ie->id) { + case F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupRequestIEs__value_PR_GNB_CU_UE_F1AP_ID); + out->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID; + break; + case F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupRequestIEs__value_PR_GNB_DU_UE_F1AP_ID); + _F1_MALLOC(out->gNB_DU_ue_id, ie->value.choice.GNB_DU_UE_F1AP_ID); + break; + case F1AP_ProtocolIE_ID_id_SpCell_ID: { + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupRequestIEs__value_PR_NRCGI); + const F1AP_NRCGI_t *nrcgi = &ie->value.choice.NRCGI; + PLMNID_TO_MCC_MNC(&nrcgi->pLMN_Identity, out->plmn.mcc, out->plmn.mnc, out->plmn.mnc_digit_length); + BIT_STRING_TO_NR_CELL_IDENTITY(&nrcgi->nRCellIdentity, out->nr_cellid); + } break; + case F1AP_ProtocolIE_ID_id_ServCellIndex: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupRequestIEs__value_PR_ServCellIndex); + out->servCellIndex = ie->value.choice.ServCellIndex; + break; + case F1AP_ProtocolIE_ID_id_CUtoDURRCInformation: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupRequestIEs__value_PR_CUtoDURRCInformation); + _F1_CHECK_EXP(decode_cu_to_du_rrc_info(&out->cu_to_du_rrc_info, &ie->value.choice.CUtoDURRCInformation)); + break; + case F1AP_ProtocolIE_ID_id_SRBs_ToBeSetup_List: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupRequestIEs__value_PR_SRBs_ToBeSetup_List); + _F1_CHECK_EXP(decode_srbs_to_setup(&ie->value.choice.SRBs_ToBeSetup_List, &out->srbs_len, &out->srbs)); + break; + case F1AP_ProtocolIE_ID_id_DRBs_ToBeSetup_List: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupRequestIEs__value_PR_DRBs_ToBeSetup_List); + { + // gNB-DU UE Aggregate Maximum Bit Rate Uplink is C-ifDRBSetup + // below, check that gNB-DU UE AMBR UL IE is present if we have DRB + // setup, as required by the spec, or return false otherwise (like in + // the beginning of the function) + F1AP_UEContextSetupRequestIEs_t *check_ie; + F1AP_LIB_FIND_IE(F1AP_UEContextSetupRequestIEs_t, check_ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_GNB_DU_UE_AMBR_UL, true); + } + _F1_CHECK_EXP(decode_drbs_to_setup(&ie->value.choice.DRBs_ToBeSetup_List, &out->drbs_len, &out->drbs)); + break; + case F1AP_ProtocolIE_ID_id_RRCContainer: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupRequestIEs__value_PR_RRCContainer); + out->rrc_container = malloc_or_fail(sizeof(*out->rrc_container)); + { + OCTET_STRING_t *os = &ie->value.choice.RRCContainer; + *out->rrc_container = create_byte_array(os->size, os->buf); + } + break; + case F1AP_ProtocolIE_ID_id_GNB_DU_UE_AMBR_UL: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupRequestIEs__value_PR_BitRate); + out->gnb_du_ue_agg_mbr_ul = malloc_or_fail(sizeof(*out->gnb_du_ue_agg_mbr_ul)); + asn_INTEGER2uint64(&ie->value.choice.BitRate, out->gnb_du_ue_agg_mbr_ul); + break; + default: + PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld unknown, skipping\n", ie->id); + break; + } + } + + return true; +} + +/** + * @brief F1 UE Context Setup Request deep copy + */ +f1ap_ue_context_setup_req_t cp_ue_context_setup_req(const f1ap_ue_context_setup_req_t *orig) +{ + /* copy all mandatory fields that are not dynamic memory */ + f1ap_ue_context_setup_req_t cp = { + .gNB_CU_ue_id = orig->gNB_CU_ue_id, + .plmn = orig->plmn, + .nr_cellid = orig->nr_cellid, + .servCellIndex = orig->servCellIndex, + .cu_to_du_rrc_info = cp_cu_to_du_rrc_info(&orig->cu_to_du_rrc_info), + }; + if (orig->gNB_DU_ue_id) + _F1_MALLOC(cp.gNB_DU_ue_id, *orig->gNB_DU_ue_id); + if (orig->srbs_len > 0 && orig->srbs) { + cp.srbs = calloc_or_fail(orig->srbs_len, sizeof(*cp.srbs)); + cp.srbs_len = orig->srbs_len; + for (int i = 0; i < cp.srbs_len; ++i) + cp.srbs[i] = cp_srb_to_setup(&orig->srbs[i]); + } + if (orig->drbs_len > 0 && orig->drbs) { + cp.drbs = calloc_or_fail(orig->drbs_len, sizeof(*cp.drbs)); + cp.drbs_len = orig->drbs_len; + for (int i = 0; i < cp.drbs_len; ++i) + cp.drbs[i] = cp_drb_to_setup(&orig->drbs[i]); + } + CP_OPT_BYTE_ARRAY(cp.rrc_container, orig->rrc_container); + if (orig->gnb_du_ue_agg_mbr_ul) + _F1_MALLOC(cp.gnb_du_ue_agg_mbr_ul, *orig->gnb_du_ue_agg_mbr_ul); + return cp; +} + +/** + * @brief F1 UE Context Setup Request equality check + */ +bool eq_ue_context_setup_req(const f1ap_ue_context_setup_req_t *a, const f1ap_ue_context_setup_req_t *b) +{ + _F1_EQ_CHECK_INT(a->gNB_CU_ue_id, b->gNB_CU_ue_id); + _F1_EQ_CHECK_OPTIONAL_IE(a, b, gNB_DU_ue_id, _F1_EQ_CHECK_INT); + _F1_CHECK_EXP(eq_f1ap_plmn(&a->plmn, &b->plmn)); + _F1_EQ_CHECK_LONG(a->nr_cellid, b->nr_cellid); + _F1_EQ_CHECK_INT(a->servCellIndex, b->servCellIndex); + _F1_CHECK_EXP(eq_cu_to_du_rrc_info(&a->cu_to_du_rrc_info, &b->cu_to_du_rrc_info)); + + _F1_EQ_CHECK_INT(a->srbs_len, b->srbs_len); + _F1_CHECK_EXP(a->srbs_len == 0 || (a->srbs && b->srbs)); + for (int i = 0; i < a->srbs_len; ++i) + _F1_CHECK_EXP(eq_srb_to_setup(&a->srbs[i], &b->srbs[i])); + + _F1_EQ_CHECK_INT(a->drbs_len, b->drbs_len); + _F1_CHECK_EXP(a->drbs_len == 0 || (a->drbs && b->drbs)); + for (int i = 0; i < a->drbs_len; ++i) + _F1_CHECK_EXP(eq_drb_to_setup(&a->drbs[i], &b->drbs[i])); + + _F1_EQ_CHECK_OPTIONAL_IE(a, b, rrc_container, eq_ba); + + _F1_EQ_CHECK_OPTIONAL_IE(a, b, gnb_du_ue_agg_mbr_ul, _F1_EQ_CHECK_LONG); + return true; +} + +/** + * @brief Free Allocated F1 UE Context Setup Request + */ +void free_ue_context_setup_req(f1ap_ue_context_setup_req_t *req) +{ + free(req->gNB_DU_ue_id); + free_cu_to_du_rrc_info(&req->cu_to_du_rrc_info); + for (int i = 0; i < req->srbs_len; ++i) + free_srb_to_setup(&req->srbs[i]); + free(req->srbs); + for (int i = 0; i < req->drbs_len; ++i) + free_drb_to_setup(&req->drbs[i]); + free(req->drbs); + FREE_OPT_BYTE_ARRAY(req->rrc_container); + free(req->gnb_du_ue_agg_mbr_ul); +} diff --git a/openair2/F1AP/lib/f1ap_ue_context.h b/openair2/F1AP/lib/f1ap_ue_context.h new file mode 100644 index 0000000000..947273b7a8 --- /dev/null +++ b/openair2/F1AP/lib/f1ap_ue_context.h @@ -0,0 +1,36 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef F1AP_UE_CONTEXT_SETUP_REQ_H_ +#define F1AP_UE_CONTEXT_SETUP_REQ_H_ + +#include +#include "f1ap_messages_types.h" + +struct F1AP_F1AP_PDU; + +struct F1AP_F1AP_PDU *encode_ue_context_setup_req(const f1ap_ue_context_setup_req_t *msg); +bool decode_ue_context_setup_req(const struct F1AP_F1AP_PDU *pdu, f1ap_ue_context_setup_req_t *out); +f1ap_ue_context_setup_req_t cp_ue_context_setup_req(const f1ap_ue_context_setup_req_t *orig); +bool eq_ue_context_setup_req(const f1ap_ue_context_setup_req_t *a, const f1ap_ue_context_setup_req_t *b); +void free_ue_context_setup_req(f1ap_ue_context_setup_req_t *req); + +#endif /* F1AP_UE_CONTEXT_SETUP_REQ_H_ */ diff --git a/openair2/F1AP/tests/CMakeLists.txt b/openair2/F1AP/tests/CMakeLists.txt index a73334051a..396e86d513 100644 --- a/openair2/F1AP/tests/CMakeLists.txt +++ b/openair2/F1AP/tests/CMakeLists.txt @@ -1,6 +1,6 @@ add_executable(f1ap_lib_test f1ap_lib_test.c) add_dependencies(tests f1ap_lib_test) add_test(NAME f1ap_lib_test COMMAND f1ap_lib_test) -target_link_libraries(f1ap_lib_test PRIVATE f1ap_lib) +target_link_libraries(f1ap_lib_test PRIVATE f1ap_lib ds) target_link_libraries(f1ap_lib_test PRIVATE asn1_f1ap) target_include_directories(f1ap_lib_test PRIVATE ${CMAKE_SOURCE_DIR}) diff --git a/openair2/F1AP/tests/f1ap_lib_test.c b/openair2/F1AP/tests/f1ap_lib_test.c index 57a503d8ab..a06bd28564 100644 --- a/openair2/F1AP/tests/f1ap_lib_test.c +++ b/openair2/F1AP/tests/f1ap_lib_test.c @@ -31,6 +31,7 @@ #include #include #include +#include #include "common/utils/assertions.h" #include "common/utils/utils.h" @@ -38,8 +39,10 @@ #include "f1ap_messages_types.h" #include "F1AP_F1AP-PDU.h" +#include "lib/f1ap_lib_common.h" #include "lib/f1ap_rrc_message_transfer.h" #include "lib/f1ap_interface_management.h" +#include "lib/f1ap_ue_context.h" void exit_function(const char *file, const char *function, const int line, const char *s, const int assert) { @@ -718,6 +721,171 @@ static void test_f1ap_cu_configuration_update_acknowledge(void) // No free needed } +static byte_array_t get_test_ba(const char *s) +{ + byte_array_t ba = { + .len = strlen(s) + 1, /* binary data: needs to include null-byte of strdup() */ + .buf = (uint8_t *) strdup(s), + }; + return ba; +} + +static byte_array_t *get_malloced_test_ba(const char *s) +{ + byte_array_t *ba = calloc_or_fail(1, sizeof(*ba)); + *ba = get_test_ba(s); + return ba; +} + +static void test_f1ap_ue_context_setup_request() +{ + plmn_id_t plmn = { .mcc = 001, .mnc = 01, .mnc_digit_length = 2 }; + f1ap_ue_context_setup_req_t orig = { + .gNB_CU_ue_id = 12, + //.gNB_DU_ue_id below + .plmn = plmn, + .nr_cellid = 132, + .servCellIndex = 1, + //.cu_to_du_rrc_info below + //.srbs below + //.drbs below + //gnb_du_ue_agg_mbr_ul below + }; + _F1_MALLOC(orig.gNB_DU_ue_id, 13); + orig.cu_to_du_rrc_info.cg_configinfo = get_malloced_test_ba("CG-CONFIGINFO"); + orig.cu_to_du_rrc_info.ue_cap = get_malloced_test_ba("UE CAP"); + orig.cu_to_du_rrc_info.meas_config = get_malloced_test_ba("UE MEASUREMENT CONFIGURATION"); + orig.cu_to_du_rrc_info.ho_prep_info = get_malloced_test_ba("PREPARATION DATA FOR HANDOVER"); + orig.srbs_len = 2; + orig.srbs = calloc_or_fail(orig.srbs_len, sizeof(*orig.srbs)); + for (int i = 0; i < orig.srbs_len; ++i) + orig.srbs[i].id = 1 + i; + + orig.drbs_len = 2; + orig.drbs = calloc_or_fail(orig.drbs_len, sizeof(*orig.drbs)); + f1ap_drb_to_setup_t *drb1 = &orig.drbs[0]; + drb1->id = 4; + drb1->qos_choice = F1AP_QOS_CHOICE_NR; + f1ap_arp_t arp = { 1, MAY_TRIGGER_PREEMPTION, PREEMPTABLE, }; + drb1->nr.drb_qos.qos_type = NON_DYNAMIC; + drb1->nr.drb_qos.nondyn.fiveQI = 3; + drb1->nr.drb_qos.arp = arp; + drb1->nr.nssai = (nssai_t) {.sst = 1, .sd = 123}; + drb1->nr.flows_len = 1; + f1ap_drb_flows_mapped_t *flow = drb1->nr.flows = calloc_or_fail(drb1->nr.flows_len, sizeof(*flow)); + flow->qfi = 2; + flow->param.qos_type = NON_DYNAMIC; + flow->param.nondyn.fiveQI = 3; + flow->param.arp = arp; + drb1->up_ul_tnl_len = 1; + inet_pton(AF_INET, "192.168.40.23", &drb1->up_ul_tnl[0].tl_address); + drb1->up_ul_tnl[0].teid = 0x11223344; + drb1->rlc_mode = F1AP_RLC_MODE_UM_BIDIR; + _F1_MALLOC(drb1->dl_pdcp_sn_len, F1AP_PDCP_SN_18B); + _F1_MALLOC(drb1->ul_pdcp_sn_len, F1AP_PDCP_SN_18B); + + f1ap_drb_to_setup_t *drb2 = &orig.drbs[1]; + drb2->id = 12; + drb2->qos_choice = F1AP_QOS_CHOICE_NR; + drb2->nr.drb_qos.qos_type = DYNAMIC; + f1ap_dynamic_5qi_t *dyn = &drb2->nr.drb_qos.dyn; + dyn->prio = 4; + dyn->pdb = 1000; + dyn->per.scalar = 4; + dyn->per.exponent = 8; + _F1_MALLOC(dyn->delay_critical, true); + _F1_MALLOC(dyn->avg_win, 3000); + f1ap_arp_t arp2 = { 13, SHALL_NOT_TRIGGER_PREEMPTION, NOT_PREEMPTABLE, }; + drb2->nr.drb_qos.arp = arp2; + drb2->nr.nssai = (nssai_t) {.sst = 2, .sd = 0xffffff}; + drb2->nr.flows_len = 2; + f1ap_drb_flows_mapped_t *flow2 = drb2->nr.flows = calloc_or_fail(drb2->nr.flows_len, sizeof(*flow2)); + flow2[0].qfi = 4; + flow2[0].param.qos_type = DYNAMIC; + flow2[0].param.dyn.prio = 4; + flow2[0].param.dyn.pdb = 999; + flow2[0].param.dyn.per.scalar = 4; + flow2[0].param.dyn.per.exponent = 8; + flow2[0].param.arp = arp2; + flow2[1].qfi = 5; + flow2[1].param.qos_type = NON_DYNAMIC; + flow2[1].param.nondyn.fiveQI = 3; + flow2[1].param.arp = arp; + drb2->up_ul_tnl_len = 2; + inet_pton(AF_INET, "10.0.0.2", &drb2->up_ul_tnl[0].tl_address); + drb2->up_ul_tnl[0].teid = 0x1234; + inet_pton(AF_INET, "10.0.0.2", &drb2->up_ul_tnl[1].tl_address); + drb2->up_ul_tnl[1].teid = 0x1235; + drb2->rlc_mode = F1AP_RLC_MODE_AM; + _F1_MALLOC(drb2->dl_pdcp_sn_len, F1AP_PDCP_SN_12B); + _F1_MALLOC(drb2->ul_pdcp_sn_len, F1AP_PDCP_SN_12B); + + orig.rrc_container = get_malloced_test_ba("RRC container"); + + _F1_MALLOC(orig.gnb_du_ue_agg_mbr_ul, 5LL * 1000 * 1000 * 1000); + + F1AP_F1AP_PDU_t *f1enc = encode_ue_context_setup_req(&orig); + F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + + f1ap_ue_context_setup_req_t decoded = {0}; + bool ret = decode_ue_context_setup_req(f1dec, &decoded); + AssertFatal(ret, "decode_ue_context_setup_req(): could not decode message\n"); + f1ap_msg_free(f1dec); + + ret = eq_ue_context_setup_req(&orig, &decoded); + AssertFatal(ret, "eq_ue_context_setup_req(): decoded message doesn't match\n"); + char ip_ret[100]; + inet_ntop(AF_INET, &decoded.drbs[0].up_ul_tnl[0].tl_address, ip_ret, sizeof(ip_ret)); + printf("%s\n", ip_ret); + inet_ntop(AF_INET, &decoded.drbs[1].up_ul_tnl[0].tl_address, ip_ret, sizeof(ip_ret)); + printf("%s\n", ip_ret); + free_ue_context_setup_req(&decoded); + + f1ap_ue_context_setup_req_t cp = cp_ue_context_setup_req(&orig); + ret = eq_ue_context_setup_req(&orig, &cp); + AssertFatal(ret, "eq_ue_context_setup_req(): copied message doesn't match\n"); + free_ue_context_setup_req(&orig); + free_ue_context_setup_req(&cp); + + printf("%s() successful\n", __func__); +} + +static void test_f1ap_ue_context_setup_request_simple() +{ + plmn_id_t plmn = { .mcc = 001, .mnc = 01, .mnc_digit_length = 2 }; + f1ap_ue_context_setup_req_t orig = { + .gNB_CU_ue_id = 12, + .plmn = plmn, + .nr_cellid = 132, + .servCellIndex = 1, + //.cu_to_du_rrc_info: all fields optional, intentionally left empty + // rest is optional and intentionally left empty + // .gnb_du_ue_agg_mbr_ul is C-ifDRBSetup => no DRB => no IE + }; + F1AP_F1AP_PDU_t *f1enc = encode_ue_context_setup_req(&orig); + F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + + f1ap_ue_context_setup_req_t decoded = {0}; + bool ret = decode_ue_context_setup_req(f1dec, &decoded); + AssertFatal(ret, "decode_ue_context_setup_req(): could not decode message\n"); + f1ap_msg_free(f1dec); + + ret = eq_ue_context_setup_req(&orig, &decoded); + AssertFatal(ret, "eq_ue_context_setup_req(): decoded message doesn't match\n"); + free_ue_context_setup_req(&decoded); + + f1ap_ue_context_setup_req_t cp = cp_ue_context_setup_req(&orig); + ret = eq_ue_context_setup_req(&orig, &cp); + AssertFatal(ret, "eq_ue_context_setup_req(): copied message doesn't match\n"); + free_ue_context_setup_req(&orig); + free_ue_context_setup_req(&cp); + + printf("%s() successful\n", __func__); +} + + int main() { test_initial_ul_rrc_message_transfer(); @@ -733,5 +901,7 @@ int main() test_f1ap_cu_configuration_update(); test_f1ap_cu_configuration_update_acknowledge(); test_f1ap_du_configuration_update_acknowledge(); + test_f1ap_ue_context_setup_request(); + test_f1ap_ue_context_setup_request_simple(); return 0; } From 807e44d6042721d7607b6999a7e1dd8547c70b18 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 4 Jun 2025 18:23:20 +0200 Subject: [PATCH 120/964] Add F1AP UE context modification request message enc/dec + test See commit "Add F1AP UE context setup request message enc/dec + test" for more details on the approach taken. --- openair2/COMMON/f1ap_messages_types.h | 37 ++ openair2/F1AP/lib/f1ap_ue_context.c | 565 ++++++++++++++++++++++++++ openair2/F1AP/lib/f1ap_ue_context.h | 6 + openair2/F1AP/tests/f1ap_lib_test.c | 111 +++++ 4 files changed, 719 insertions(+) diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h index 85f2def720..9992473c9e 100644 --- a/openair2/COMMON/f1ap_messages_types.h +++ b/openair2/COMMON/f1ap_messages_types.h @@ -485,6 +485,11 @@ typedef enum TransmActionInd_e { TransmActionInd_RESTART, } TransmActionInd_t; +typedef enum lower_layer_status_e { + LOWER_LAYERS_SUSPEND, + LOWER_LAYERS_RESUME, +} lower_layer_status_t; + typedef struct f1ap_srb_to_setup_t { int id; } f1ap_srb_to_setup_t; @@ -555,6 +560,10 @@ typedef struct f1ap_drb_to_setup_t { f1ap_pdcp_sn_len_t *ul_pdcp_sn_len; } f1ap_drb_to_setup_t; +typedef struct f1ap_drb_to_release_t { + int id; +} f1ap_drb_to_release_t; + typedef struct f1ap_ue_context_setup_req_s { uint32_t gNB_CU_ue_id; uint32_t *gNB_DU_ue_id; @@ -576,6 +585,34 @@ typedef struct f1ap_ue_context_setup_req_s { uint64_t *gnb_du_ue_agg_mbr_ul; // C-ifDRBSetup } f1ap_ue_context_setup_req_t; +typedef struct f1ap_ue_context_mod_req_t { + uint32_t gNB_CU_ue_id; + uint32_t gNB_DU_ue_id; + + plmn_id_t *plmn; + uint64_t *nr_cellid; + uint8_t *servCellIndex; + + f1ap_cu_to_du_rrc_info_t *cu_to_du_rrc_info; + + TransmActionInd_t *transm_action_ind; + ReconfigurationCompl_t *reconfig_compl; + + byte_array_t *rrc_container; + + int srbs_len; + f1ap_srb_to_setup_t *srbs; // reuse the same type as for setup; there is a + // list for SRB modification + + int drbs_len; + f1ap_drb_to_setup_t *drbs; // as for SRBs + + int drbs_rel_len; + f1ap_drb_to_release_t *drbs_rel; + + lower_layer_status_t *status; +} f1ap_ue_context_mod_req_t; + typedef struct f1ap_ue_context_setup_s { uint32_t gNB_CU_ue_id; uint32_t gNB_DU_ue_id; diff --git a/openair2/F1AP/lib/f1ap_ue_context.c b/openair2/F1AP/lib/f1ap_ue_context.c index 572ad3ce6a..332b0ad130 100644 --- a/openair2/F1AP/lib/f1ap_ue_context.c +++ b/openair2/F1AP/lib/f1ap_ue_context.c @@ -153,6 +153,22 @@ static F1AP_SRBs_ToBeSetup_List_t encode_srbs_to_setup(int n, const f1ap_srb_to_ return list; } +/* \brief Encode SRB-ToBeSetupMod List, for UE context Modification Request, + * from f1ap_srb_to_setup_t. The ToBeSetup/ToBeSetupMod lists are basically the + * same in both cases, but the asn1c types are different. */ +static F1AP_SRBs_ToBeSetupMod_List_t encode_srbs_to_setupmod(int n, const f1ap_srb_to_setup_t *srbs) +{ + F1AP_SRBs_ToBeSetupMod_List_t list = {0}; + for (int i = 0; i < n; ++i) { + asn1cSequenceAdd(list, F1AP_SRBs_ToBeSetupMod_ItemIEs_t, itie); + itie->id = F1AP_ProtocolIE_ID_id_SRBs_ToBeSetupMod_Item; + itie->criticality = F1AP_Criticality_reject; + itie->value.present = F1AP_SRBs_ToBeSetupMod_ItemIEs__value_PR_SRBs_ToBeSetupMod_Item; + itie->value.choice.SRBs_ToBeSetupMod_Item.sRBID = srbs[i].id; + } + return list; +} + /* \brief Decode SRB-ToBeSetup List, from UE Context Setup Request, into * f1ap_srb_to_setup_t. */ static bool decode_srbs_to_setup(const F1AP_SRBs_ToBeSetup_List_t *f1ap, int *n, f1ap_srb_to_setup_t **out) @@ -174,6 +190,28 @@ static bool decode_srbs_to_setup(const F1AP_SRBs_ToBeSetup_List_t *f1ap, int *n, return true; } +/* \brief Decode SRB-ToBeSetupMod List, from UE Context Modification Request, + * into f1ap_srb_to_setup_t. The ToBeSetup/ToBeSetupMod lists are basically the + * same, but the asn1c types are different. */ +static bool decode_srbs_to_setupmod(const F1AP_SRBs_ToBeSetupMod_List_t *f1ap, int *n, f1ap_srb_to_setup_t **out) +{ + DevAssert(out != NULL); + *out = NULL; + int count = *n = f1ap->list.count; + if (count == 0) + return true; + + f1ap_srb_to_setup_t *srbs = *out = calloc_or_fail(count, sizeof(*srbs)); + for (int i = 0; i < count; ++i) { + const F1AP_SRBs_ToBeSetupMod_ItemIEs_t *itie = (F1AP_SRBs_ToBeSetupMod_ItemIEs_t *)f1ap->list.array[i]; + _F1_EQ_CHECK_LONG(itie->id, F1AP_ProtocolIE_ID_id_SRBs_ToBeSetupMod_Item); + _F1_EQ_CHECK_INT(itie->value.present, F1AP_SRBs_ToBeSetupMod_ItemIEs__value_PR_SRBs_ToBeSetupMod_Item); + srbs[i].id = itie->value.choice.SRBs_ToBeSetupMod_Item.sRBID; + } + + return true; +} + static f1ap_srb_to_setup_t cp_srb_to_setup(const f1ap_srb_to_setup_t *orig) { f1ap_srb_to_setup_t cp = { @@ -508,6 +546,64 @@ static F1AP_DRBs_ToBeSetup_List_t encode_drbs_to_setup(int n, const f1ap_drb_to_ return list; } +/* Encode a DRBs_ToBeSetupMod list for UE Context Modification Request, from + * f1ap_drb_to_setup_t. The ToBeSetup/ToBeSetupMod lists are almost the same + * (with the exception that one field is optional in the latter), so that we + * can reuse the internal types, but the asn1c types are different. */ +static F1AP_DRBs_ToBeSetupMod_List_t encode_drbs_to_setupmod(int n, const f1ap_drb_to_setup_t *drbs) +{ + F1AP_DRBs_ToBeSetupMod_List_t list = {0}; + for (int i = 0; i < n; ++i) { + const f1ap_drb_to_setup_t *drb = &drbs[i]; + asn1cSequenceAdd(list, F1AP_DRBs_ToBeSetupMod_ItemIEs_t, itie); + itie->id = F1AP_ProtocolIE_ID_id_DRBs_ToBeSetupMod_Item; + itie->criticality = F1AP_Criticality_reject; + itie->value.present = F1AP_DRBs_ToBeSetupMod_ItemIEs__value_PR_DRBs_ToBeSetupMod_Item; + + F1AP_DRBs_ToBeSetupMod_Item_t *it = &itie->value.choice.DRBs_ToBeSetupMod_Item; + it->dRBID = drb->id; + AssertFatal(drb->qos_choice == F1AP_QOS_CHOICE_NR, "only NR QoS choice implemented\n"); + it->qoSInformation.present = F1AP_QoSInformation_PR_choice_extension; + F1AP_QoSInformation_ExtIEs_t *qos_ext_ie = calloc_or_fail(1, sizeof(*qos_ext_ie)); + it->qoSInformation.choice.choice_extension = (struct F1AP_ProtocolIE_SingleContainer *)qos_ext_ie; + qos_ext_ie->id = F1AP_ProtocolIE_ID_id_DRB_Information; + qos_ext_ie->criticality = F1AP_Criticality_reject; + qos_ext_ie->value.present = F1AP_QoSInformation_ExtIEs__value_PR_DRB_Information; + qos_ext_ie->value.choice.DRB_Information = encode_drb_info_nr(&drb->nr); + + /* 12.1.3 uLUPTNLInformation_ToBeSetupMod_List */ + for (int j = 0; j < drb->up_ul_tnl_len; j++) { + DevAssert(drb->up_ul_tnl[j].teid > 0); + asn1cSequenceAdd(it->uLUPTNLInformation_ToBeSetup_List.list, F1AP_ULUPTNLInformation_ToBeSetup_Item_t, tnl_it); + tnl_it->uLUPTNLInformation = encode_up_tnl(&drb->up_ul_tnl[j]); + } + + it->rLCMode = rlc_mode_to_asn1(drb->rlc_mode); + + if (!drb->dl_pdcp_sn_len && !drb->ul_pdcp_sn_len) + continue; + + F1AP_ProtocolExtensionContainer_10696P83_t *ext = calloc_or_fail(1, sizeof(*ext)); + it->iE_Extensions = (struct F1AP_ProtocolExtensionContainer *)ext; + if (drb->dl_pdcp_sn_len) { + asn1cSequenceAdd(ext->list, F1AP_DRBs_ToBeSetupMod_ItemExtIEs_t, ext_ie); + ext_ie->id = F1AP_ProtocolIE_ID_id_DLPDCPSNLength; + ext_ie->criticality = F1AP_Criticality_ignore; + ext_ie->extensionValue.present = F1AP_DRBs_ToBeSetupMod_ItemExtIEs__extensionValue_PR_PDCPSNLength; + ext_ie->extensionValue.choice.PDCPSNLength = *drb->dl_pdcp_sn_len; + } + + if (drb->ul_pdcp_sn_len) { + asn1cSequenceAdd(ext->list, F1AP_DRBs_ToBeSetupMod_ItemExtIEs_t, ext_ie); + ext_ie->id = F1AP_ProtocolIE_ID_id_ULPDCPSNLength; + ext_ie->criticality = F1AP_Criticality_ignore; + ext_ie->extensionValue.present = F1AP_DRBs_ToBeSetupMod_ItemExtIEs__extensionValue_PR_PDCPSNLength_1; + ext_ie->extensionValue.choice.PDCPSNLength_1 = *drb->ul_pdcp_sn_len; + } + } + return list; +} + /* \brief Decode DRBS-ToBeSetup list from UE Context Setup request, into * f1ap_drb_to_setup_t. */ static bool decode_drbs_to_setup(const F1AP_DRBs_ToBeSetup_List_t *f1ap, int *n, f1ap_drb_to_setup_t **out) @@ -571,6 +667,71 @@ static bool decode_drbs_to_setup(const F1AP_DRBs_ToBeSetup_List_t *f1ap, int *n, return true; } +/* \brief Decode DRBS-ToBeSetupMod list from UE Context Modification Request, into + * f1ap_drb_to_setup_t. The ToBeSetup/ToBeSetupMod lists are almost the same + * (except for some optional types in the latter), so we reuse the internal + * representation, but the asn1c types are different. */ +static bool decode_drbs_to_setupmod(const F1AP_DRBs_ToBeSetupMod_List_t *f1ap, int *n, f1ap_drb_to_setup_t **out) +{ + DevAssert(out != NULL); + *out = NULL; + int count = *n = f1ap->list.count; + if (count == 0) + return true; + + f1ap_drb_to_setup_t *drbs = *out = calloc_or_fail(count, sizeof(*drbs)); + for (int i = 0; i < count; ++i) { + const F1AP_DRBs_ToBeSetupMod_ItemIEs_t *itie = (const F1AP_DRBs_ToBeSetupMod_ItemIEs_t *)f1ap->list.array[i]; + _F1_EQ_CHECK_LONG(itie->id, F1AP_ProtocolIE_ID_id_DRBs_ToBeSetupMod_Item); + _F1_EQ_CHECK_INT(itie->value.present, F1AP_DRBs_ToBeSetupMod_ItemIEs__value_PR_DRBs_ToBeSetupMod_Item); + const F1AP_DRBs_ToBeSetupMod_Item_t *it = &itie->value.choice.DRBs_ToBeSetupMod_Item; + + f1ap_drb_to_setup_t *drb = &drbs[i]; + drb->id = it->dRBID; + + _F1_EQ_CHECK_INT(it->qoSInformation.present, F1AP_QoSInformation_PR_choice_extension); + const F1AP_QoSInformation_ExtIEs_t *qos_ext = (F1AP_QoSInformation_ExtIEs_t *)it->qoSInformation.choice.choice_extension; + _F1_EQ_CHECK_LONG(qos_ext->id, F1AP_ProtocolIE_ID_id_DRB_Information); + _F1_EQ_CHECK_INT(qos_ext->value.present, F1AP_QoSInformation_ExtIEs__value_PR_DRB_Information); + drb->qos_choice = F1AP_QOS_CHOICE_NR; + _F1_CHECK_EXP(decode_drb_info_nr(&qos_ext->value.choice.DRB_Information, &drb->nr)); + + drb->up_ul_tnl_len = it->uLUPTNLInformation_ToBeSetup_List.list.count; + _F1_EQ_CHECK_GENERIC(drb->up_ul_tnl_len > 0 && drb->up_ul_tnl_len <= 2, "%d", drb->up_ul_tnl_len, 1); + for (int j = 0; j < drb->up_ul_tnl_len; ++j) { + const F1AP_ULUPTNLInformation_ToBeSetup_Item_t *it_tnl = it->uLUPTNLInformation_ToBeSetup_List.list.array[j]; + _F1_CHECK_EXP(decode_up_tnl(&it_tnl->uLUPTNLInformation, &drb->up_ul_tnl[j])); + } + + _F1_CHECK_EXP(rlc_mode_from_asn1(it->rLCMode, &drb->rlc_mode)); + + if (!it->iE_Extensions) + continue; + const F1AP_ProtocolExtensionContainer_10696P83_t *ext = (const F1AP_ProtocolExtensionContainer_10696P83_t *)it->iE_Extensions; + const F1AP_DRBs_ToBeSetupMod_ItemExtIEs_t *ie; + + for (int j = 0; j < ext->list.count; ++j) { + ie = ext->list.array[j]; + AssertError(ie != NULL, return false, "ext->list.array[j] is NULL"); + switch (ie->id) { + case F1AP_ProtocolIE_ID_id_DLPDCPSNLength: + _F1_EQ_CHECK_INT(ie->extensionValue.present, F1AP_DRBs_ToBeSetupMod_ItemExtIEs__extensionValue_PR_PDCPSNLength); + _F1_MALLOC(drb->dl_pdcp_sn_len, ie->extensionValue.choice.PDCPSNLength); + break; + case F1AP_ProtocolIE_ID_id_ULPDCPSNLength: + _F1_EQ_CHECK_INT(ie->extensionValue.present, F1AP_DRBs_ToBeSetupMod_ItemExtIEs__extensionValue_PR_PDCPSNLength_1); + _F1_MALLOC(drb->ul_pdcp_sn_len, ie->extensionValue.choice.PDCPSNLength_1); + break; + default: + PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld unknown, skipping\n", ie->id); + break; + } + } + } + + return true; +} + static f1ap_drb_to_setup_t cp_drb_to_setup(const f1ap_drb_to_setup_t *orig) { f1ap_drb_to_setup_t cp = { @@ -623,6 +784,57 @@ static void free_drb_to_setup(f1ap_drb_to_setup_t *drb) free(drb->ul_pdcp_sn_len); } +static F1AP_DRBs_ToBeReleased_List_t encode_drbs_to_release(int n, const f1ap_drb_to_release_t *drbs) +{ + F1AP_DRBs_ToBeReleased_List_t list = {0}; + for (int i = 0; i < n; i++) { + asn1cSequenceAdd(list, F1AP_DRBs_ToBeReleased_ItemIEs_t, itie); + itie->id = F1AP_ProtocolIE_ID_id_DRBs_ToBeReleased_Item; + itie->criticality = F1AP_Criticality_reject; + itie->value.present = F1AP_DRBs_ToBeReleased_ItemIEs__value_PR_DRBs_ToBeReleased_Item; + itie->value.choice.DRBs_ToBeReleased_Item.dRBID = drbs[i].id; + } + return list; +} + +static bool decode_drbs_to_release(const F1AP_DRBs_ToBeReleased_List_t *f1ap, int *n, f1ap_drb_to_release_t **out) +{ + DevAssert(out != NULL); + *out = NULL; + int count = *n = f1ap->list.count; + if (count == 0) + return true; + + f1ap_drb_to_release_t *drbs = *out = calloc_or_fail(count, sizeof(*drbs)); + for (int i = 0; i < count; ++i) { + const F1AP_DRBs_ToBeReleased_ItemIEs_t *itie = (F1AP_DRBs_ToBeReleased_ItemIEs_t *)f1ap->list.array[i]; + _F1_EQ_CHECK_LONG(itie->id, F1AP_ProtocolIE_ID_id_DRBs_ToBeReleased_Item); + _F1_EQ_CHECK_INT(itie->value.present, F1AP_DRBs_ToBeReleased_ItemIEs__value_PR_DRBs_ToBeReleased_Item); + drbs[i].id = itie->value.choice.DRBs_ToBeReleased_Item.dRBID; + } + + return true; +} + +static f1ap_drb_to_release_t cp_drb_to_release(const f1ap_drb_to_release_t *orig) +{ + f1ap_drb_to_release_t cp = { + .id = orig->id, + }; + return cp; +} + +static bool eq_drb_to_release(const f1ap_drb_to_release_t *a, const f1ap_drb_to_release_t *b) +{ + _F1_EQ_CHECK_INT(a->id, b->id); + return true; +} + +static void free_drb_to_release(f1ap_drb_to_release_t *drb) +{ + // nothing to free +} + /** * @brief Encode F1 UE context setup request to ASN.1 */ @@ -874,3 +1086,356 @@ void free_ue_context_setup_req(f1ap_ue_context_setup_req_t *req) FREE_OPT_BYTE_ARRAY(req->rrc_container); free(req->gnb_du_ue_agg_mbr_ul); } + +/** + * @brief Encode F1 UE context modification request to ASN.1 + */ +F1AP_F1AP_PDU_t *encode_ue_context_mod_req(const f1ap_ue_context_mod_req_t *req) +{ + F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); + + /* Message Type */ + pdu->present = F1AP_F1AP_PDU_PR_initiatingMessage; + asn1cCalloc(pdu->choice.initiatingMessage, tmp); + tmp->procedureCode = F1AP_ProcedureCode_id_UEContextModification; + tmp->criticality = F1AP_Criticality_reject; + tmp->value.present = F1AP_InitiatingMessage__value_PR_UEContextModificationRequest; + F1AP_UEContextModificationRequest_t *out = &tmp->value.choice.UEContextModificationRequest; + + /* mandatory: GNB_CU_UE_F1AP_ID */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie1); + ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; + ie1->criticality = F1AP_Criticality_reject; + ie1->value.present = F1AP_UEContextModificationRequestIEs__value_PR_GNB_CU_UE_F1AP_ID; + ie1->value.choice.GNB_CU_UE_F1AP_ID = req->gNB_CU_ue_id; + + /* mandatory: GNB_DU_UE_F1AP_ID */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie2); + ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; + ie2->criticality = F1AP_Criticality_reject; + ie2->value.present = F1AP_UEContextModificationRequestIEs__value_PR_GNB_DU_UE_F1AP_ID; + ie2->value.choice.GNB_DU_UE_F1AP_ID = req->gNB_DU_ue_id; + + /* optional: SpCellID/NRCGI */ + if (req->plmn) { + DevAssert(req->nr_cellid); + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie3); + ie3->id = F1AP_ProtocolIE_ID_id_SpCell_ID; + ie3->criticality = F1AP_Criticality_ignore; + ie3->value.present = F1AP_UEContextModificationRequestIEs__value_PR_NRCGI; + F1AP_NRCGI_t *nrcgi = &ie3->value.choice.NRCGI; + const plmn_id_t *plmn = req->plmn; + MCC_MNC_TO_PLMNID(plmn->mcc, plmn->mnc, plmn->mnc_digit_length, &nrcgi->pLMN_Identity); + NR_CELL_ID_TO_BIT_STRING(*req->nr_cellid, &nrcgi->nRCellIdentity); + } + + /* optional: ServCellIndex */ + if (req->servCellIndex) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie4); + ie4->id = F1AP_ProtocolIE_ID_id_ServCellIndex; + ie4->criticality = F1AP_Criticality_reject; + ie4->value.present = F1AP_UEContextModificationRequestIEs__value_PR_ServCellIndex; + ie4->value.choice.ServCellIndex = *req->servCellIndex; + } + + /* optional: CUtoDURRCInformation */ + if (req->cu_to_du_rrc_info) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie6); + ie6->id = F1AP_ProtocolIE_ID_id_CUtoDURRCInformation; + ie6->criticality = F1AP_Criticality_reject; + ie6->value.present = F1AP_UEContextModificationRequestIEs__value_PR_CUtoDURRCInformation; + ie6->value.choice.CUtoDURRCInformation = encode_cu_to_du_rrc_info(req->cu_to_du_rrc_info); + } + + /* optional: TransmissionActionIndicator */ + if (req->transm_action_ind) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie7); + ie7->id = F1AP_ProtocolIE_ID_id_TransmissionActionIndicator; + ie7->criticality = F1AP_Criticality_ignore; + ie7->value.present = F1AP_UEContextModificationRequestIEs__value_PR_TransmissionActionIndicator; + ie7->value.choice.TransmissionActionIndicator = *req->transm_action_ind; + // Stop is guaranteed to be 0, by restart might be different from 1 + static_assert((int)F1AP_TransmissionActionIndicator_restart == (int)TransmActionInd_RESTART, + "mismatch of ASN.1 and internal representation\n"); + } + + /* optional: RRCRconfigurationCompleteIndicator */ + if (req->reconfig_compl) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie71); + ie71->id = F1AP_ProtocolIE_ID_id_RRCReconfigurationCompleteIndicator; + ie71->criticality = F1AP_Criticality_ignore; + ie71->value.present = F1AP_UEContextModificationRequestIEs__value_PR_RRCReconfigurationCompleteIndicator; + ie71->value.choice.RRCReconfigurationCompleteIndicator = *req->reconfig_compl == RRCreconf_success + ? F1AP_RRCReconfigurationCompleteIndicator_true + : F1AP_RRCReconfigurationCompleteIndicator_failure; + } + + /* optional: RRC container */ + if (req->rrc_container) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie81); + ie81->id = F1AP_ProtocolIE_ID_id_RRCContainer; + ie81->criticality = F1AP_Criticality_ignore; + ie81->value.present = F1AP_UEContextModificationRequestIEs__value_PR_RRCContainer; + OCTET_STRING_fromBuf(&ie81->value.choice.RRCContainer, (const char *)req->rrc_container->buf, req->rrc_container->len); + } + + /* optional: SRBs_ToBeSetupMod */ + if (req->srbs_len > 0) { + DevAssert(req->srbs); + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie11); + ie11->id = F1AP_ProtocolIE_ID_id_SRBs_ToBeSetupMod_List; + ie11->criticality = F1AP_Criticality_reject; + ie11->value.present = F1AP_UEContextModificationRequestIEs__value_PR_SRBs_ToBeSetupMod_List; + ie11->value.choice.SRBs_ToBeSetupMod_List = encode_srbs_to_setupmod(req->srbs_len, req->srbs); + } + + /* optional: DRBs_ToBeSetupMod */ + if (req->drbs_len > 0) { + DevAssert(req->drbs); + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie12); + ie12->id = F1AP_ProtocolIE_ID_id_DRBs_ToBeSetupMod_List; + ie12->criticality = F1AP_Criticality_reject; + ie12->value.present = F1AP_UEContextModificationRequestIEs__value_PR_DRBs_ToBeSetupMod_List; + ie12->value.choice.DRBs_ToBeSetupMod_List = encode_drbs_to_setupmod(req->drbs_len, req->drbs); + } + + /* optional: DRBs_ToBeReleased */ + if (req->drbs_rel_len > 0) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie15); + ie15->id = F1AP_ProtocolIE_ID_id_DRBs_ToBeReleased_List; + ie15->criticality = F1AP_Criticality_reject; + ie15->value.present = F1AP_UEContextModificationRequestIEs__value_PR_DRBs_ToBeReleased_List; + ie15->value.choice.DRBs_ToBeReleased_List = encode_drbs_to_release(req->drbs_rel_len, req->drbs_rel); + } + + /* optional: Lower Layer Presence Status Change */ + if (req->status) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie17); + ie17->id = F1AP_ProtocolIE_ID_id_LowerLayerPresenceStatusChange; + ie17->criticality = F1AP_Criticality_ignore; + ie17->value.present = F1AP_UEContextModificationRequestIEs__value_PR_LowerLayerPresenceStatusChange; + ie17->value.choice.LowerLayerPresenceStatusChange = *req->status == LOWER_LAYERS_SUSPEND + ? F1AP_LowerLayerPresenceStatusChange_suspend_lower_layers + : F1AP_LowerLayerPresenceStatusChange_resume_lower_layers; + } + return pdu; +} + +/** + * @brief Decode F1 UE Context Modification Request + */ +bool decode_ue_context_mod_req(const F1AP_F1AP_PDU_t *pdu, f1ap_ue_context_mod_req_t *out) +{ + DevAssert(out != NULL); + memset(out, 0, sizeof(*out)); + + F1AP_UEContextModificationRequest_t *in = &pdu->choice.initiatingMessage->value.choice.UEContextModificationRequest; + F1AP_UEContextModificationRequestIEs_t *ie; + F1AP_LIB_FIND_IE(F1AP_UEContextModificationRequestIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); + F1AP_LIB_FIND_IE(F1AP_UEContextModificationRequestIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); + + for (int i = 0; i < in->protocolIEs.list.count; ++i) { + ie = in->protocolIEs.list.array[i]; + AssertError(ie != NULL, return false, "in->protocolIEs.list.array[i] is NULL"); + switch (ie->id) { + case F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_GNB_CU_UE_F1AP_ID); + out->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID; + break; + case F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_GNB_DU_UE_F1AP_ID); + out->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; + break; + case F1AP_ProtocolIE_ID_id_SpCell_ID: { + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_NRCGI); + const F1AP_NRCGI_t *nrcgi = &ie->value.choice.NRCGI; + out->plmn = malloc_or_fail(sizeof(*out->plmn)); + PLMNID_TO_MCC_MNC(&nrcgi->pLMN_Identity, out->plmn->mcc, out->plmn->mnc, out->plmn->mnc_digit_length); + out->nr_cellid = malloc_or_fail(sizeof(*out->nr_cellid)); + BIT_STRING_TO_NR_CELL_IDENTITY(&nrcgi->nRCellIdentity, *out->nr_cellid); + } break; + case F1AP_ProtocolIE_ID_id_ServCellIndex: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_ServCellIndex); + _F1_MALLOC(out->servCellIndex, ie->value.choice.ServCellIndex); + break; + case F1AP_ProtocolIE_ID_id_CUtoDURRCInformation: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_CUtoDURRCInformation); + out->cu_to_du_rrc_info = calloc(1, sizeof(*out->cu_to_du_rrc_info)); + _F1_CHECK_EXP(decode_cu_to_du_rrc_info(out->cu_to_du_rrc_info, &ie->value.choice.CUtoDURRCInformation)); + break; + case F1AP_ProtocolIE_ID_id_TransmissionActionIndicator: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_TransmissionActionIndicator); + { + TransmActionInd_t v = ie->value.choice.TransmissionActionIndicator == F1AP_TransmissionActionIndicator_stop + ? TransmActionInd_STOP + : TransmActionInd_RESTART; + _F1_MALLOC(out->transm_action_ind, v); + } + break; + case F1AP_ProtocolIE_ID_id_RRCReconfigurationCompleteIndicator: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_RRCReconfigurationCompleteIndicator); + { + ReconfigurationCompl_t v = + ie->value.choice.RRCReconfigurationCompleteIndicator == F1AP_RRCReconfigurationCompleteIndicator_true + ? RRCreconf_success + : RRCreconf_failure; + _F1_MALLOC(out->reconfig_compl, v); + } + break; + case F1AP_ProtocolIE_ID_id_RRCContainer: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_RRCContainer); + out->rrc_container = malloc_or_fail(sizeof(*out->rrc_container)); + { + OCTET_STRING_t *os = &ie->value.choice.RRCContainer; + *out->rrc_container = create_byte_array(os->size, os->buf); + } + break; + case F1AP_ProtocolIE_ID_id_SRBs_ToBeSetupMod_List: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_SRBs_ToBeSetupMod_List); + _F1_CHECK_EXP(decode_srbs_to_setupmod(&ie->value.choice.SRBs_ToBeSetupMod_List, &out->srbs_len, &out->srbs)); + break; + case F1AP_ProtocolIE_ID_id_DRBs_ToBeSetupMod_List: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_DRBs_ToBeSetupMod_List); + _F1_CHECK_EXP(decode_drbs_to_setupmod(&ie->value.choice.DRBs_ToBeSetupMod_List, &out->drbs_len, &out->drbs)); + break; + case F1AP_ProtocolIE_ID_id_DRBs_ToBeReleased_List: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_DRBs_ToBeReleased_List); + _F1_CHECK_EXP(decode_drbs_to_release(&ie->value.choice.DRBs_ToBeReleased_List, &out->drbs_rel_len, &out->drbs_rel)); + break; + case F1AP_ProtocolIE_ID_id_LowerLayerPresenceStatusChange: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_LowerLayerPresenceStatusChange); + { + lower_layer_status_t v = ie->value.choice.LowerLayerPresenceStatusChange == F1AP_LowerLayerPresenceStatusChange_suspend_lower_layers + ? LOWER_LAYERS_SUSPEND : LOWER_LAYERS_RESUME; + _F1_MALLOC(out->status, v); + } + break; + default: + PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld unknown, skipping\n", ie->id); + break; + } + } + + return true; +} + +/** + * @brief F1 UE Context Modification Request deep copy + */ +f1ap_ue_context_mod_req_t cp_ue_context_mod_req(const f1ap_ue_context_mod_req_t *orig) +{ + f1ap_ue_context_mod_req_t cp = { + .gNB_CU_ue_id = orig->gNB_CU_ue_id, + .gNB_DU_ue_id = orig->gNB_DU_ue_id, + // .plmn, .nr_cellid, .servCellIndex below + // .cu_to_du_rrc_info below + // .transm_action_ind below + // .reconfig_compl below + // .rrc_container below + .srbs_len = orig->srbs_len, + // .srbs below + .drbs_len = orig->drbs_len, + // .drbs below + // .status below + }; + + if (orig->plmn) + _F1_MALLOC(cp.plmn, *orig->plmn); + if (orig->nr_cellid) + _F1_MALLOC(cp.nr_cellid, *orig->nr_cellid); + if (orig->servCellIndex) + _F1_MALLOC(cp.servCellIndex, *orig->servCellIndex); + if (orig->cu_to_du_rrc_info) + _F1_MALLOC(cp.cu_to_du_rrc_info, cp_cu_to_du_rrc_info(orig->cu_to_du_rrc_info)); + if (orig->transm_action_ind) + _F1_MALLOC(cp.transm_action_ind, *orig->transm_action_ind); + if (orig->reconfig_compl) + _F1_MALLOC(cp.reconfig_compl, *orig->reconfig_compl); + CP_OPT_BYTE_ARRAY(cp.rrc_container, orig->rrc_container); + if (orig->srbs_len > 0) { + DevAssert(orig->srbs); + cp.srbs = calloc_or_fail(orig->srbs_len, sizeof(*cp.srbs)); + cp.srbs_len = orig->srbs_len; + for (int i = 0; i < cp.srbs_len; ++i) + cp.srbs[i] = cp_srb_to_setup(&orig->srbs[i]); + } + if (orig->drbs_len > 0) { + DevAssert(orig->drbs); + cp.drbs = calloc_or_fail(orig->drbs_len, sizeof(*cp.drbs)); + cp.drbs_len = orig->drbs_len; + for (int i = 0; i < cp.drbs_len; ++i) + cp.drbs[i] = cp_drb_to_setup(&orig->drbs[i]); + } + if (orig->drbs_rel_len > 0) { + DevAssert(orig->drbs_rel); + cp.drbs_rel = calloc_or_fail(orig->drbs_rel_len, sizeof(*cp.drbs_rel)); + cp.drbs_rel_len = orig->drbs_rel_len; + for (int i = 0; i < cp.drbs_rel_len; ++i) + cp.drbs_rel[i] = cp_drb_to_release(&orig->drbs_rel[i]); + } + if (orig->status) + _F1_MALLOC(cp.status, *orig->status); + return cp; +} + +/** + * @brief F1 UE Context Modification Request equality check + */ +bool eq_ue_context_mod_req(const f1ap_ue_context_mod_req_t *a, const f1ap_ue_context_mod_req_t *b) +{ + _F1_EQ_CHECK_INT(a->gNB_CU_ue_id, b->gNB_CU_ue_id); + _F1_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id); + _F1_CHECK_EXP((a->plmn && b->plmn) || (!a->plmn && !b->plmn)); + _F1_CHECK_EXP(!a->plmn || eq_f1ap_plmn(a->plmn, b->plmn)); + _F1_EQ_CHECK_OPTIONAL_IE(a, b, nr_cellid, _F1_EQ_CHECK_LONG); + _F1_EQ_CHECK_OPTIONAL_IE(a, b, servCellIndex, _F1_EQ_CHECK_INT); + _F1_CHECK_EXP((a->cu_to_du_rrc_info && b->cu_to_du_rrc_info) || (!a->cu_to_du_rrc_info && !b->cu_to_du_rrc_info)); + _F1_CHECK_EXP(!a->cu_to_du_rrc_info || eq_cu_to_du_rrc_info(a->cu_to_du_rrc_info, b->cu_to_du_rrc_info)); + _F1_EQ_CHECK_OPTIONAL_IE(a, b, transm_action_ind, _F1_EQ_CHECK_INT); + _F1_EQ_CHECK_OPTIONAL_IE(a, b, reconfig_compl, _F1_EQ_CHECK_INT); + _F1_EQ_CHECK_OPTIONAL_IE(a, b, rrc_container, eq_ba); + + _F1_EQ_CHECK_INT(a->srbs_len, b->srbs_len); + _F1_CHECK_EXP(a->srbs_len == 0 || (a->srbs && b->srbs)); + for (int i = 0; i < a->srbs_len; ++i) + _F1_CHECK_EXP(eq_srb_to_setup(&a->srbs[i], &b->srbs[i])); + + _F1_EQ_CHECK_INT(a->drbs_len, b->drbs_len); + _F1_CHECK_EXP(a->drbs_len == 0 || (a->drbs && b->drbs)); + for (int i = 0; i < a->drbs_len; ++i) + _F1_CHECK_EXP(eq_drb_to_setup(&a->drbs[i], &b->drbs[i])); + + _F1_EQ_CHECK_INT(a->drbs_rel_len, b->drbs_rel_len); + _F1_CHECK_EXP(a->drbs_rel_len == 0 || (a->drbs_rel_len && b->drbs_rel_len)); + for (int i = 0; i < a->drbs_rel_len; ++i) + _F1_CHECK_EXP(eq_drb_to_release(&a->drbs_rel[i], &b->drbs_rel[i])); + + _F1_EQ_CHECK_OPTIONAL_IE(a, b, status, _F1_EQ_CHECK_INT); + return true; +} + +/** + * @brief Free Allocated F1 UE Context Modification Request + */ +void free_ue_context_mod_req(f1ap_ue_context_mod_req_t *req) +{ + free(req->plmn); + free(req->nr_cellid); + free(req->servCellIndex); + if (req->cu_to_du_rrc_info) + free_cu_to_du_rrc_info(req->cu_to_du_rrc_info); + free(req->cu_to_du_rrc_info); + free(req->transm_action_ind); + free(req->reconfig_compl); + FREE_OPT_BYTE_ARRAY(req->rrc_container); + for (int i = 0; i < req->srbs_len; ++i) + free_srb_to_setup(&req->srbs[i]); + free(req->srbs); + for (int i = 0; i < req->drbs_len; ++i) + free_drb_to_setup(&req->drbs[i]); + free(req->drbs); + for (int i = 0; i < req->drbs_rel_len; ++i) + free_drb_to_release(&req->drbs_rel[i]); + free(req->drbs_rel); + free(req->status); +} diff --git a/openair2/F1AP/lib/f1ap_ue_context.h b/openair2/F1AP/lib/f1ap_ue_context.h index 947273b7a8..6ac521085b 100644 --- a/openair2/F1AP/lib/f1ap_ue_context.h +++ b/openair2/F1AP/lib/f1ap_ue_context.h @@ -33,4 +33,10 @@ f1ap_ue_context_setup_req_t cp_ue_context_setup_req(const f1ap_ue_context_setup_ bool eq_ue_context_setup_req(const f1ap_ue_context_setup_req_t *a, const f1ap_ue_context_setup_req_t *b); void free_ue_context_setup_req(f1ap_ue_context_setup_req_t *req); +struct F1AP_F1AP_PDU *encode_ue_context_mod_req(const f1ap_ue_context_mod_req_t *msg); +bool decode_ue_context_mod_req(const struct F1AP_F1AP_PDU *pdu, f1ap_ue_context_mod_req_t *out); +f1ap_ue_context_mod_req_t cp_ue_context_mod_req(const f1ap_ue_context_mod_req_t *orig); +bool eq_ue_context_mod_req(const f1ap_ue_context_mod_req_t *a, const f1ap_ue_context_mod_req_t *b); +void free_ue_context_mod_req(f1ap_ue_context_mod_req_t *req); + #endif /* F1AP_UE_CONTEXT_SETUP_REQ_H_ */ diff --git a/openair2/F1AP/tests/f1ap_lib_test.c b/openair2/F1AP/tests/f1ap_lib_test.c index a06bd28564..159ea41470 100644 --- a/openair2/F1AP/tests/f1ap_lib_test.c +++ b/openair2/F1AP/tests/f1ap_lib_test.c @@ -886,6 +886,115 @@ static void test_f1ap_ue_context_setup_request_simple() } +static void test_f1ap_ue_context_modification_request() +{ + f1ap_ue_context_mod_req_t orig = { + .gNB_CU_ue_id = 1111, + .gNB_DU_ue_id = 2222, + // rest below + }; + plmn_id_t plmn = { .mcc = 999, .mnc = 101, .mnc_digit_length = 3 }; + _F1_MALLOC(orig.plmn, plmn); + _F1_MALLOC(orig.nr_cellid, 1532); + _F1_MALLOC(orig.servCellIndex, 3); + + f1ap_cu_to_du_rrc_info_t cu2du = { + .cg_configinfo = get_malloced_test_ba("Modified"), + .ue_cap = get_malloced_test_ba("UE forgot to send earlier"), + .meas_config = get_malloced_test_ba("with updates from another cell"), + .ho_prep_info = get_malloced_test_ba("prepare to ho soon!"), + }; + _F1_MALLOC(orig.cu_to_du_rrc_info, cu2du); + + orig.rrc_container = get_malloced_test_ba("important RRC message!!"); + + orig.srbs_len = 1; + orig.srbs = calloc_or_fail(orig.srbs_len, sizeof(*orig.srbs)); + orig.srbs[0].id = 1; + + orig.drbs_len = 1; + orig.drbs = calloc_or_fail(orig.drbs_len, sizeof(*orig.drbs)); + f1ap_drb_to_setup_t *drb1 = &orig.drbs[0]; + drb1->id = 4; + drb1->qos_choice = F1AP_QOS_CHOICE_NR; + f1ap_arp_t arp = { 2, SHALL_NOT_TRIGGER_PREEMPTION, NOT_PREEMPTABLE, }; + drb1->nr.drb_qos.qos_type = NON_DYNAMIC; + drb1->nr.drb_qos.nondyn.fiveQI = 8; + drb1->nr.drb_qos.arp = arp; + drb1->nr.nssai = (nssai_t) {.sst = 2, .sd = 0xffffff}; + drb1->nr.flows_len = 1; + f1ap_drb_flows_mapped_t *flow = drb1->nr.flows = calloc_or_fail(drb1->nr.flows_len, sizeof(*flow)); + flow->qfi = 2; + flow->param.qos_type = NON_DYNAMIC; + flow->param.nondyn.fiveQI = 9; + flow->param.arp = arp; + drb1->up_ul_tnl_len = 1; + inet_pton(AF_INET, "8.8.8.8", &drb1->up_ul_tnl[0].tl_address); + drb1->up_ul_tnl[0].teid = 0x9876541; + drb1->rlc_mode = F1AP_RLC_MODE_AM; + _F1_MALLOC(drb1->dl_pdcp_sn_len, F1AP_PDCP_SN_12B); + _F1_MALLOC(drb1->ul_pdcp_sn_len, F1AP_PDCP_SN_18B); + + orig.drbs_rel_len = 3; + orig.drbs_rel = calloc_or_fail(orig.drbs_rel_len, sizeof(*orig.drbs_rel)); + orig.drbs_rel[0].id = 13; + orig.drbs_rel[1].id = 4; + orig.drbs_rel[2].id = 19; + + _F1_MALLOC(orig.status, LOWER_LAYERS_RESUME); + + F1AP_F1AP_PDU_t *f1enc = encode_ue_context_mod_req(&orig); + F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + + f1ap_ue_context_mod_req_t decoded = {0}; + bool ret = decode_ue_context_mod_req(f1dec, &decoded); + AssertFatal(ret, "decode_ue_context_mod_req(): could not decode message\n"); + f1ap_msg_free(f1dec); + + ret = eq_ue_context_mod_req(&orig, &decoded); + AssertFatal(ret, "eq_ue_context_mod_req(): decoded message doesn't match\n"); + free_ue_context_mod_req(&decoded); + + f1ap_ue_context_mod_req_t cp = cp_ue_context_mod_req(&orig); + ret = eq_ue_context_mod_req(&orig, &cp); + AssertFatal(ret, "eq_ue_context_mod_req(): copied message doesn't match\n"); + free_ue_context_mod_req(&orig); + free_ue_context_mod_req(&cp); + + printf("%s() successful\n", __func__); +} + +static void test_f1ap_ue_context_modification_request_simple() +{ + f1ap_ue_context_mod_req_t orig = { + .gNB_CU_ue_id = 1111, + .gNB_DU_ue_id = 2222, + // rest is optional and intentionally left out + }; + + F1AP_F1AP_PDU_t *f1enc = encode_ue_context_mod_req(&orig); + F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + + f1ap_ue_context_mod_req_t decoded = {0}; + bool ret = decode_ue_context_mod_req(f1dec, &decoded); + AssertFatal(ret, "decode_ue_context_mod_req(): could not decode message\n"); + f1ap_msg_free(f1dec); + + ret = eq_ue_context_mod_req(&orig, &decoded); + AssertFatal(ret, "eq_ue_context_mod_req(): decoded message doesn't match\n"); + free_ue_context_mod_req(&decoded); + + f1ap_ue_context_mod_req_t cp = cp_ue_context_mod_req(&orig); + ret = eq_ue_context_mod_req(&orig, &cp); + AssertFatal(ret, "eq_ue_context_mod_req(): copied message doesn't match\n"); + free_ue_context_mod_req(&orig); + free_ue_context_mod_req(&cp); + + printf("%s() successful\n", __func__); +} + int main() { test_initial_ul_rrc_message_transfer(); @@ -903,5 +1012,7 @@ int main() test_f1ap_du_configuration_update_acknowledge(); test_f1ap_ue_context_setup_request(); test_f1ap_ue_context_setup_request_simple(); + test_f1ap_ue_context_modification_request(); + test_f1ap_ue_context_modification_request_simple(); return 0; } From 014e67fccd698120eb047ed8c2b94d3e335ddf28 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 19 Jun 2025 12:20:46 +0200 Subject: [PATCH 121/964] Use F1 UE context setup/modif Request in stack Use the new, tested F1 UE context setup request and modification requests in the stack. We have to do both at once, because there are some functions that are used by handlers for both messages, notably - handle_ue_context_drbs_setup() - handle_ue_context_srbs_setup() (+ and some functions called by those two). For instance, the first uses the (new/old) type f1ap_drb_to_be_setup_t/f1ap_drb_to_setup_t which is shared. The alternative would be to duplicate the functionality temporarily, and I want to avoid unnecessary code churn. --- openair2/COMMON/f1ap_messages_def.h | 4 +- openair2/COMMON/f1ap_messages_types.h | 4 +- openair2/F1AP/f1ap_cu_task.c | 9 +- openair2/F1AP/f1ap_cu_ue_context_management.c | 1020 +---------------- openair2/F1AP/f1ap_cu_ue_context_management.h | 5 +- openair2/F1AP/f1ap_du_task.c | 1 + openair2/F1AP/f1ap_du_ue_context_management.c | 499 +------- .../LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c | 155 ++- .../LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h | 4 +- openair2/RRC/NR/mac_rrc_dl.h | 4 +- openair2/RRC/NR/mac_rrc_dl_direct.c | 4 +- openair2/RRC/NR/mac_rrc_dl_f1ap.c | 106 +- openair2/RRC/NR/nr_rrc_proto.h | 8 +- openair2/RRC/NR/rrc_gNB.c | 144 ++- openair2/RRC/NR/rrc_gNB_mobility.c | 94 +- openair2/RRC/NR/rrc_gNB_nsa.c | 65 +- 16 files changed, 304 insertions(+), 1822 deletions(-) diff --git a/openair2/COMMON/f1ap_messages_def.h b/openair2/COMMON/f1ap_messages_def.h index 405ecae3d5..c713361aa5 100644 --- a/openair2/COMMON/f1ap_messages_def.h +++ b/openair2/COMMON/f1ap_messages_def.h @@ -56,9 +56,9 @@ MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_REQUIRED, MESSAGE_PRIORITY_MED, f1ap_ue /* RRC -> F1AP messages */ MESSAGE_DEF(F1AP_DL_RRC_MESSAGE , MESSAGE_PRIORITY_MED, f1ap_dl_rrc_message_t , f1ap_dl_rrc_message ) //MESSAGE_DEF(F1AP_INITIAL_CONTEXT_SETUP_REQ , MESSAGE_PRIORITY_MED, f1ap_initial_context_setup_req_t , f1ap_initial_context_setup_req ) -MESSAGE_DEF(F1AP_UE_CONTEXT_SETUP_REQ, MESSAGE_PRIORITY_MED, f1ap_ue_context_setup_t, f1ap_ue_context_setup_req) +MESSAGE_DEF(F1AP_UE_CONTEXT_SETUP_REQ, MESSAGE_PRIORITY_MED, f1ap_ue_context_setup_req_t, f1ap_ue_context_setup_req) MESSAGE_DEF(F1AP_UE_CONTEXT_SETUP_RESP, MESSAGE_PRIORITY_MED, f1ap_ue_context_setup_t, f1ap_ue_context_setup_resp) -MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_REQ, MESSAGE_PRIORITY_MED, f1ap_ue_context_modif_req_t, f1ap_ue_context_modification_req) +MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_REQ, MESSAGE_PRIORITY_MED, f1ap_ue_context_mod_req_t, f1ap_ue_context_mod_req) MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_RESP, MESSAGE_PRIORITY_MED, f1ap_ue_context_modif_resp_t, f1ap_ue_context_modification_resp) MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_CONFIRM, MESSAGE_PRIORITY_MED, f1ap_ue_context_modif_confirm_t, f1ap_ue_context_modification_confirm) MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_REFUSE, MESSAGE_PRIORITY_MED, f1ap_ue_context_modif_refuse_t, f1ap_ue_context_modification_refuse) diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h index 9992473c9e..73b8162eb4 100644 --- a/openair2/COMMON/f1ap_messages_types.h +++ b/openair2/COMMON/f1ap_messages_types.h @@ -55,7 +55,7 @@ #define F1AP_UL_RRC_MESSAGE(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ul_rrc_message #define F1AP_UE_CONTEXT_SETUP_REQ(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_setup_req #define F1AP_UE_CONTEXT_SETUP_RESP(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_setup_resp -#define F1AP_UE_CONTEXT_MODIFICATION_REQ(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_modification_req +#define F1AP_UE_CONTEXT_MODIFICATION_REQ(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_mod_req #define F1AP_UE_CONTEXT_MODIFICATION_RESP(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_modification_resp #define F1AP_UE_CONTEXT_MODIFICATION_FAIL(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_modification_fail #define F1AP_UE_CONTEXT_MODIFICATION_REQUIRED(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_modification_required @@ -645,7 +645,7 @@ typedef struct f1ap_ue_context_setup_s { uint8_t *rrc_container; int rrc_container_length; TransmActionInd_t *transm_action_ind; -} f1ap_ue_context_setup_t, f1ap_ue_context_modif_req_t, f1ap_ue_context_modif_resp_t; +} f1ap_ue_context_setup_t, f1ap_ue_context_modif_resp_t; typedef enum F1ap_Cause_e { F1AP_CAUSE_NOTHING, /* No components present */ diff --git a/openair2/F1AP/f1ap_cu_task.c b/openair2/F1AP/f1ap_cu_task.c index 4528a7766f..85375e4109 100644 --- a/openair2/F1AP/f1ap_cu_task.c +++ b/openair2/F1AP/f1ap_cu_task.c @@ -36,6 +36,7 @@ #include "f1ap_cu_ue_context_management.h" #include "lib/f1ap_rrc_message_transfer.h" #include "lib/f1ap_interface_management.h" +#include "lib/f1ap_ue_context.h" #include "f1ap_cu_paging.h" #include "f1ap_cu_task.h" #include "openair2/RRC/NR/nr_rrc_defs.h" @@ -186,13 +187,13 @@ void *F1AP_CU_task(void *arg) { break; case F1AP_UE_CONTEXT_SETUP_REQ: // from rrc - CU_send_UE_CONTEXT_SETUP_REQUEST(assoc_id, - &F1AP_UE_CONTEXT_SETUP_REQ(received_msg)); + CU_send_UE_CONTEXT_SETUP_REQUEST(assoc_id, &F1AP_UE_CONTEXT_SETUP_REQ(received_msg)); + free_ue_context_setup_req(&F1AP_UE_CONTEXT_SETUP_REQ(received_msg)); break; case F1AP_UE_CONTEXT_MODIFICATION_REQ: - CU_send_UE_CONTEXT_MODIFICATION_REQUEST(assoc_id, - &F1AP_UE_CONTEXT_MODIFICATION_REQ(received_msg)); + CU_send_UE_CONTEXT_MODIFICATION_REQUEST(assoc_id, &F1AP_UE_CONTEXT_MODIFICATION_REQ(received_msg)); + free_ue_context_mod_req(&F1AP_UE_CONTEXT_MODIFICATION_REQ(received_msg)); break; case F1AP_UE_CONTEXT_RELEASE_CMD: // from rrc diff --git a/openair2/F1AP/f1ap_cu_ue_context_management.c b/openair2/F1AP/f1ap_cu_ue_context_management.c index f4bffe6144..9dc9e8c086 100644 --- a/openair2/F1AP/f1ap_cu_ue_context_management.c +++ b/openair2/F1AP/f1ap_cu_ue_context_management.c @@ -34,6 +34,7 @@ #include "f1ap_encoder.h" #include "f1ap_itti_messaging.h" #include "f1ap_cu_ue_context_management.h" +#include "lib/f1ap_ue_context.h" #include #include "rrc_extern.h" @@ -44,572 +45,25 @@ #include "openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc_extern.h" #endif -static void f1ap_write_drb_qos_param(const f1ap_qos_flow_level_qos_parameters_t *drb_qos_in, F1AP_QoSFlowLevelQoSParameters_t *asn1_qosparam) +int CU_send_UE_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, const f1ap_ue_context_setup_req_t *req) { - int type = drb_qos_in->qos_characteristics.qos_type; + F1AP_F1AP_PDU_t *pdu = encode_ue_context_setup_req(req); - const f1ap_qos_characteristics_t *drb_qos_char_in = &drb_qos_in->qos_characteristics; - if (type == NON_DYNAMIC) { - asn1_qosparam->qoS_Characteristics.present = F1AP_QoS_Characteristics_PR_non_Dynamic_5QI; - asn1cCalloc(asn1_qosparam->qoS_Characteristics.choice.non_Dynamic_5QI, tmp); - - /* 5QI */ - tmp->fiveQI = drb_qos_char_in->non_dynamic.fiveqi; - } else { - asn1_qosparam->qoS_Characteristics.present = F1AP_QoS_Characteristics_PR_dynamic_5QI; - asn1cCalloc(asn1_qosparam->qoS_Characteristics.choice.dynamic_5QI, tmp); - /* qoSPriorityLevel */ - tmp->qoSPriorityLevel = drb_qos_char_in->dynamic.qos_priority_level; - /* packetDelayBudget */ - tmp->packetDelayBudget = drb_qos_char_in->dynamic.packet_delay_budget; - /* packetErrorRate */ - tmp->packetErrorRate.pER_Scalar = drb_qos_char_in->dynamic.packet_error_rate.per_scalar; - tmp->packetErrorRate.pER_Exponent = drb_qos_char_in->dynamic.packet_error_rate.per_scalar; - - /* OPTIONAL delayCritical */ - // asn1cCallocOne(asn1_qosparam->qoS_Characteristics.choice.dynamic_5QI->delayCritical, 1L); - - /* OPTIONAL averagingWindow */ - // asn1cCallocOne(asn1_qosparam->qoS_Characteristics.choice.dynamic_5QI->averagingWindow, 1L); - - /* OPTIONAL maxDataBurstVolume */ - // asn1cCallocOne(asn1_qosparam->qoS_Characteristics.choice.dynamic_5QI->maxDataBurstVolume, 1L); - } - - { - asn1_qosparam->nGRANallocationRetentionPriority.priorityLevel = drb_qos_in->alloc_reten_priority.priority_level; - asn1_qosparam->nGRANallocationRetentionPriority.pre_emptionCapability = drb_qos_in->alloc_reten_priority.preemption_capability; - asn1_qosparam->nGRANallocationRetentionPriority.pre_emptionVulnerability = - drb_qos_in->alloc_reten_priority.preemption_vulnerability; - } // nGRANallocationRetentionPriority - - /* OPTIONAL */ - /* gBR_QoS_Flow_Information */ - if (0) { - asn1cCalloc(asn1_qosparam->gBR_QoS_Flow_Information, tmp); - asn_long2INTEGER(&tmp->maxFlowBitRateDownlink, 1L); - asn_long2INTEGER(&tmp->maxFlowBitRateUplink, 1L); - asn_long2INTEGER(&tmp->guaranteedFlowBitRateDownlink, 1L); - asn_long2INTEGER(&tmp->guaranteedFlowBitRateUplink, 1L); - - /* OPTIONAL */ - /* maxPacketLossRateDownlink */ - // asn1cCallocOne(asn1_qosparam->gBR_QoS_Flow_Information->maxPacketLossRateDownlink, 1L); - - /* OPTIONAL */ - /* maxPacketLossRateUplink */ - //asn1cCallocOne(asn1_qosparam->gBR_QoS_Flow_Information->maxPacketLossRateUplink, 1L); - } - - /* OPTIONAL */ - /* reflective_QoS_Attribute */ - if (0) { - asn1cCallocOne(asn1_qosparam->reflective_QoS_Attribute, 1L); - } -} - -static void f1ap_write_drb_nssai(const nssai_t *nssai, F1AP_SNSSAI_t *asn1_nssai) -{ - OCTET_STRING_fromBuf(&asn1_nssai->sST, (char *)&nssai->sst, 1); - - /* OPTIONAL */ - if (nssai->sd != 0xffffff) { - char sd_buffer[3]; - INT24_TO_BUFFER(nssai->sd, sd_buffer); - asn1cCalloc(asn1_nssai->sD, sD); - OCTET_STRING_fromBuf(sD, sd_buffer, 3); - } -} - -static void f1ap_write_flows_mapped(const f1ap_flows_mapped_to_drb_t *flows_mapped, F1AP_Flows_Mapped_To_DRB_List_t *asn1_flows_mapped, int n) -{ - for (int k = 0; k < n; k++) { - asn1cSequenceAdd(asn1_flows_mapped->list, F1AP_Flows_Mapped_To_DRB_Item_t, flow_item); - - const f1ap_flows_mapped_to_drb_t *qos_flow_in = flows_mapped + k; - - /* qoSFlowIndicator */ - flow_item->qoSFlowIdentifier = qos_flow_in->qfi; - - /* qoSFlowLevelQoSParameters */ - const f1ap_qos_flow_level_qos_parameters_t *flow_qos_params_in = &qos_flow_in->qos_params; - /* qoS_Characteristics */ - - F1AP_QoS_Characteristics_t *QosParams = &flow_item->qoSFlowLevelQoSParameters.qoS_Characteristics; - const f1ap_qos_characteristics_t *flow_qos_char_in = &flow_qos_params_in->qos_characteristics; - - int type = flow_qos_params_in->qos_characteristics.qos_type; - if (type == NON_DYNAMIC) { - QosParams->present = F1AP_QoS_Characteristics_PR_non_Dynamic_5QI; - asn1cCalloc(QosParams->choice.non_Dynamic_5QI, tmp); - - /* 5QI */ - tmp->fiveQI = flow_qos_char_in->non_dynamic.fiveqi; - } else { - QosParams->present = F1AP_QoS_Characteristics_PR_dynamic_5QI; - asn1cCalloc(QosParams->choice.dynamic_5QI, tmp); - /* qoSPriorityLevel */ - tmp->qoSPriorityLevel = flow_qos_char_in->dynamic.qos_priority_level; - /* packetDelayBudget */ - tmp->packetDelayBudget = flow_qos_char_in->dynamic.packet_delay_budget; - /* packetErrorRate */ - tmp->packetErrorRate.pER_Scalar = flow_qos_char_in->dynamic.packet_error_rate.per_scalar; - tmp->packetErrorRate.pER_Exponent = flow_qos_char_in->dynamic.packet_error_rate.per_exponent; - - /* OPTIONAL delayCritical */ - //asn1cCallocOne(QosParams->choice.dynamic_5QI->delayCritical, 1); - - /* OPTIONAL averagingWindow */ - //asn1cCallocOne(QosParams->choice.dynamic_5QI->averagingWindow, 1); - - /* OPTIONAL maxDataBurstVolume */ - //asn1cCallocOne(QosParams->choice.dynamic_5QI->maxDataBurstVolume, 1); - } - - /* nGRANallocationRetentionPriority */ - { - flow_item->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.priorityLevel = - flow_qos_params_in->alloc_reten_priority.priority_level; - flow_item->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.pre_emptionCapability = - flow_qos_params_in->alloc_reten_priority.preemption_capability; - flow_item->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.pre_emptionVulnerability = - flow_qos_params_in->alloc_reten_priority.preemption_vulnerability; - } // nGRANallocationRetentionPriority - - /* OPTIONAL */ - /* gBR_QoS_Flow_Information */ - if (0) { - asn1cCalloc(flow_item->qoSFlowLevelQoSParameters.gBR_QoS_Flow_Information, tmp); - asn_long2INTEGER(&tmp->maxFlowBitRateDownlink, 1L); - asn_long2INTEGER(&tmp->maxFlowBitRateUplink, 1L); - asn_long2INTEGER(&tmp->guaranteedFlowBitRateDownlink, 1L); - asn_long2INTEGER(&tmp->guaranteedFlowBitRateUplink, 1L); - - /* OPTIONAL maxPacketLossRateDownlink */ - //asn1cCallocOne(flows_mapped_to_drb_item->qoSFlowLevelQoSParameters.gBR_QoS_Flow_Information->maxPacketLossRateDownlink, 1L); - - /* OPTIONAL maxPacketLossRateUplink */ - //asn1cCallocOne(flows_mapped_to_drb_item->qoSFlowLevelQoSParameters.gBR_QoS_Flow_Information->maxPacketLossRateUplink, 1L); - } - - /* OPTIONAL reflective_QoS_Attribute */ - //asn1cCallocOne(flows_mapped_to_drb_item->qoSFlowLevelQoSParameters.reflective_QoS_Attribute, 1L); - } -} - -int CU_send_UE_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_context_setup_t *f1ap_ue_context_setup_req) -{ - F1AP_F1AP_PDU_t pdu= {0}; - /* Create */ - /* 0. Message Type */ - pdu.present = F1AP_F1AP_PDU_PR_initiatingMessage; - asn1cCalloc(pdu.choice.initiatingMessage, tmp); - tmp->procedureCode = F1AP_ProcedureCode_id_UEContextSetup; - tmp->criticality = F1AP_Criticality_reject; - tmp->value.present = F1AP_InitiatingMessage__value_PR_UEContextSetupRequest; - F1AP_UEContextSetupRequest_t *out = &pdu.choice.initiatingMessage->value.choice.UEContextSetupRequest; - /* mandatory */ - /* c1. GNB_CU_UE_F1AP_ID */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie1); - ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; - ie1->criticality = F1AP_Criticality_reject; - ie1->value.present = F1AP_UEContextSetupRequestIEs__value_PR_GNB_CU_UE_F1AP_ID; - ie1->value.choice.GNB_CU_UE_F1AP_ID = f1ap_ue_context_setup_req->gNB_CU_ue_id; - - /* optional */ - /* c2. GNB_DU_UE_F1AP_ID */ - if (f1ap_ue_context_setup_req->gNB_DU_ue_id) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie2); - ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; - ie2->criticality = F1AP_Criticality_ignore; - ie2->value.present = F1AP_UEContextSetupRequestIEs__value_PR_GNB_DU_UE_F1AP_ID; - ie2->value.choice.GNB_DU_UE_F1AP_ID = f1ap_ue_context_setup_req->gNB_DU_ue_id; - } - - /* mandatory */ - /* c3. SpCell_ID */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie3); - ie3->id = F1AP_ProtocolIE_ID_id_SpCell_ID; - ie3->criticality = F1AP_Criticality_reject; - ie3->value.present = F1AP_UEContextSetupRequestIEs__value_PR_NRCGI; - /* - nRCGI */ - addnRCGI(ie3->value.choice.NRCGI, f1ap_ue_context_setup_req); - /* mandatory */ - /* c4. ServCellIndex */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie4); - ie4->id = F1AP_ProtocolIE_ID_id_ServCellIndex; - ie4->criticality = F1AP_Criticality_reject; - ie4->value.present = F1AP_UEContextSetupRequestIEs__value_PR_ServCellIndex; - ie4->value.choice.ServCellIndex = 0; - - /* optional */ - /* c5. CellULConfigured */ - if (0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie5); - ie5->id = F1AP_ProtocolIE_ID_id_SpCellULConfigured; - ie5->criticality = F1AP_Criticality_ignore; - ie5->value.present = F1AP_UEContextSetupRequestIEs__value_PR_CellULConfigured; - ie5->value.choice.CellULConfigured = F1AP_CellULConfigured_ul; - } - - /* mandatory */ - /* c6. CUtoDURRCInformation */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie6); - ie6->id = F1AP_ProtocolIE_ID_id_CUtoDURRCInformation; - ie6->criticality = F1AP_Criticality_reject; - ie6->value.present = F1AP_UEContextSetupRequestIEs__value_PR_CUtoDURRCInformation; - - if (f1ap_ue_context_setup_req->cu_to_du_rrc_information!=NULL) { - /* optional */ - /* 6.1 cG_ConfigInfo */ - if(f1ap_ue_context_setup_req->cu_to_du_rrc_information->cG_ConfigInfo_length > 0) { - DevAssert(f1ap_ue_context_setup_req->cu_to_du_rrc_information->cG_ConfigInfo != NULL); - asn1cCalloc(ie6->value.choice.CUtoDURRCInformation.cG_ConfigInfo, cG_ConfigInfo); - OCTET_STRING_fromBuf(cG_ConfigInfo, (const char *)f1ap_ue_context_setup_req->cu_to_du_rrc_information->cG_ConfigInfo, - f1ap_ue_context_setup_req->cu_to_du_rrc_information->cG_ConfigInfo_length); - } - - /* optional */ - /* 6.2 uE_CapabilityRAT_ContainerList */ - if(f1ap_ue_context_setup_req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList!=NULL){ - asn1cCalloc(ie6->value.choice.CUtoDURRCInformation.uE_CapabilityRAT_ContainerList, uE_CapabilityRAT_ContainerList ); - OCTET_STRING_fromBuf(uE_CapabilityRAT_ContainerList, (const char *)f1ap_ue_context_setup_req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList, - f1ap_ue_context_setup_req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList_length); - } - /* optional */ - /* 6.3 measConfig */ - if(f1ap_ue_context_setup_req->cu_to_du_rrc_information->measConfig!=NULL){ - asn1cCalloc(ie6->value.choice.CUtoDURRCInformation.measConfig, measConfig); - OCTET_STRING_fromBuf(measConfig, (const char*)f1ap_ue_context_setup_req->cu_to_du_rrc_information->measConfig, - f1ap_ue_context_setup_req->cu_to_du_rrc_information->measConfig_length); - } - - /* optional */ - /* HandoverPreparationInformation */ - if (f1ap_ue_context_setup_req->cu_to_du_rrc_information->handoverPreparationInfo_length > 0) { - DevAssert(f1ap_ue_context_setup_req->cu_to_du_rrc_information->handoverPreparationInfo != NULL); - F1AP_ProtocolExtensionContainer_10696P60_t *p = calloc(1, sizeof(*p)); - ie6->value.choice.CUtoDURRCInformation.iE_Extensions = (struct F1AP_ProtocolExtensionContainer *)p; - asn1cSequenceAdd(p->list, F1AP_CUtoDURRCInformation_ExtIEs_t, ie_ext); - ie_ext->id = F1AP_ProtocolIE_ID_id_HandoverPreparationInformation; - ie_ext->criticality = F1AP_Criticality_ignore; - ie_ext->extensionValue.present = F1AP_CUtoDURRCInformation_ExtIEs__extensionValue_PR_HandoverPreparationInformation; - OCTET_STRING_fromBuf(&ie_ext->extensionValue.choice.HandoverPreparationInformation, - (const char *)f1ap_ue_context_setup_req->cu_to_du_rrc_information->handoverPreparationInfo, - f1ap_ue_context_setup_req->cu_to_du_rrc_information->handoverPreparationInfo_length); - } - } - - /* optional */ - if (0) { - /* c7. Candidate_SpCell_List */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie7); - ie7->id = F1AP_ProtocolIE_ID_id_Candidate_SpCell_List; // 90 - ie7->criticality = F1AP_Criticality_ignore; - ie7->value.present = F1AP_UEContextSetupRequestIEs__value_PR_Candidate_SpCell_List; - - for (int i = 0; i < 1; i++) { - asn1cSequenceAdd(ie7->value.choice.Candidate_SpCell_List.list, F1AP_Candidate_SpCell_ItemIEs_t, candidate_spCell_item_ies); - candidate_spCell_item_ies->id = F1AP_ProtocolIE_ID_id_Candidate_SpCell_Item; // 91 - candidate_spCell_item_ies->criticality = F1AP_Criticality_ignore; - candidate_spCell_item_ies->value.present = F1AP_Candidate_SpCell_ItemIEs__value_PR_Candidate_SpCell_Item; - /* 7.1 Candidate_SpCell_Item */ - F1AP_Candidate_SpCell_Item_t *candidate_spCell_item = &candidate_spCell_item_ies->value.choice.Candidate_SpCell_Item; - /* - candidate_SpCell_ID */ - // FixMe: first cell ??? - addnRCGI(candidate_spCell_item->candidate_SpCell_ID, f1ap_ue_context_setup_req); - /* TODO add correct mcc/mnc */ - } - } - - /* optional */ - /* c8. DRXCycle */ - if (0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie8); - ie8->id = F1AP_ProtocolIE_ID_id_DRXCycle; - ie8->criticality = F1AP_Criticality_ignore; - ie8->value.present = F1AP_UEContextSetupRequestIEs__value_PR_DRXCycle; - /* 8.1 longDRXCycleLength */ - ie8->value.choice.DRXCycle.longDRXCycleLength = F1AP_LongDRXCycleLength_ms10; // enum - - /* optional */ - /* 8.2 shortDRXCycleLength */ - if (0) { - asn1cCallocOne(ie6->value.choice.DRXCycle.shortDRXCycleLength, - F1AP_ShortDRXCycleLength_ms2); // enum - } - - /* optional */ - /* 8.3 shortDRXCycleTimer */ - if (0) { - asn1cCallocOne(ie8->value.choice.DRXCycle.shortDRXCycleTimer, - 123L); - } - } - - /* optional */ - /* c9. ResourceCoordinationTransferContainer */ - if (0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie9); - ie9->id = F1AP_ProtocolIE_ID_id_ResourceCoordinationTransferContainer; - ie9->criticality = F1AP_Criticality_ignore; - ie9->value.present = F1AP_UEContextSetupRequestIEs__value_PR_ResourceCoordinationTransferContainer; - ie9->value.choice.ResourceCoordinationTransferContainer.buf = malloc(4); - ie9->value.choice.ResourceCoordinationTransferContainer.size = 4; - strncpy((char *)ie9->value.choice.ResourceCoordinationTransferContainer.buf, "123", 4); - OCTET_STRING_fromBuf(&ie9->value.choice.ResourceCoordinationTransferContainer, "asdsa1d32sa1d31asd31as", - strlen("asdsa1d32sa1d31asd31as")); - } - - /* optional */ - if (0) { - /* c10. SCell_ToBeSetup_List */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie10); - ie10->id = F1AP_ProtocolIE_ID_id_SCell_ToBeSetup_List; - ie10->criticality = F1AP_Criticality_ignore; - ie10->value.present = F1AP_UEContextSetupRequestIEs__value_PR_SCell_ToBeSetup_List; - - for (int i = 0; i < 1; i++) { - asn1cSequenceAdd(ie10->value.choice.SCell_ToBeSetup_List.list, F1AP_SCell_ToBeSetup_ItemIEs_t, scell_toBeSetup_item_ies); - scell_toBeSetup_item_ies->id = F1AP_ProtocolIE_ID_id_SCell_ToBeSetup_Item; // 53 - scell_toBeSetup_item_ies->criticality = F1AP_Criticality_ignore; - scell_toBeSetup_item_ies->value.present = F1AP_SCell_ToBeSetup_ItemIEs__value_PR_SCell_ToBeSetup_Item; - /* 10.1 SCell_ToBeSetup_Item */ - F1AP_SCell_ToBeSetup_Item_t *scell_toBeSetup_item = &scell_toBeSetup_item_ies->value.choice.SCell_ToBeSetup_Item; - /* 10.1.1 sCell_ID */ - addnRCGI(scell_toBeSetup_item->sCell_ID, f1ap_ue_context_setup_req); - /* TODO correct MCC/MNC */ - /* 10.1.2 sCellIndex */ - scell_toBeSetup_item->sCellIndex = 3; // issue here - - /* OPTIONAL */ - /* 10.1.3 sCellULConfigured*/ - if (0) { - asn1cCallocOne(scell_toBeSetup_item->sCellULConfigured, - F1AP_CellULConfigured_ul_and_sul); // enum - } - } - } - - /* mandatory */ - /* c11. SRBs_ToBeSetup_List */ - if(f1ap_ue_context_setup_req->srbs_to_be_setup_length > 0){ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie11); - ie11->id = F1AP_ProtocolIE_ID_id_SRBs_ToBeSetup_List; - ie11->criticality = F1AP_Criticality_reject; // ? - ie11->value.present = F1AP_UEContextSetupRequestIEs__value_PR_SRBs_ToBeSetup_List; - - for (int i=0; isrbs_to_be_setup_length; i++) { - asn1cSequenceAdd(ie11->value.choice.SRBs_ToBeSetup_List.list, F1AP_SRBs_ToBeSetup_ItemIEs_t, srbs_toBeSetup_item_ies); - srbs_toBeSetup_item_ies->id = F1AP_ProtocolIE_ID_id_SRBs_ToBeSetup_Item; // 73 - srbs_toBeSetup_item_ies->criticality = F1AP_Criticality_reject; - srbs_toBeSetup_item_ies->value.present = F1AP_SRBs_ToBeSetup_ItemIEs__value_PR_SRBs_ToBeSetup_Item; - /* 11.1 SRBs_ToBeSetup_Item */ - F1AP_SRBs_ToBeSetup_Item_t *srbs_toBeSetup_item=&srbs_toBeSetup_item_ies->value.choice.SRBs_ToBeSetup_Item; - /* 11.1.1 sRBID */ - srbs_toBeSetup_item->sRBID = f1ap_ue_context_setup_req->srbs_to_be_setup[i].srb_id; - /* OPTIONAL */ - /* 11.1.2 duplicationIndication */ - asn1cCallocOne(srbs_toBeSetup_item->duplicationIndication, - F1AP_DuplicationIndication_true); // enum - } - } - - /* mandatory */ - /* c12. DRBs_ToBeSetup_List */ - if(f1ap_ue_context_setup_req->drbs_to_be_setup_length){ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie12); - ie12->id = F1AP_ProtocolIE_ID_id_DRBs_ToBeSetup_List; - ie12->criticality = F1AP_Criticality_reject; - ie12->value.present = F1AP_UEContextSetupRequestIEs__value_PR_DRBs_ToBeSetup_List; - - for (int i = 0; i < f1ap_ue_context_setup_req->drbs_to_be_setup_length; i++) { - const f1ap_drb_to_be_setup_t *drb = &f1ap_ue_context_setup_req->drbs_to_be_setup[i]; - asn1cSequenceAdd(ie12->value.choice.DRBs_ToBeSetup_List.list, F1AP_DRBs_ToBeSetup_ItemIEs_t, drbs_toBeSetup_item_ies); - drbs_toBeSetup_item_ies->id = F1AP_ProtocolIE_ID_id_DRBs_ToBeSetup_Item; - drbs_toBeSetup_item_ies->criticality = F1AP_Criticality_reject; - drbs_toBeSetup_item_ies->value.present = F1AP_DRBs_ToBeSetup_ItemIEs__value_PR_DRBs_ToBeSetup_Item; - /* 12.1 DRBs_ToBeSetup_Item */ - F1AP_DRBs_ToBeSetup_Item_t *drbs_toBeSetup_item=&drbs_toBeSetup_item_ies->value.choice.DRBs_ToBeSetup_Item; - /* 12.1.1 dRBID */ - drbs_toBeSetup_item->dRBID = drb->drb_id; - /* 12.1.2 qoSInformation */ - int some_decide_qos = 0; // BK: Need Check - - if (some_decide_qos) { - drbs_toBeSetup_item->qoSInformation.present = F1AP_QoSInformation_PR_eUTRANQoS; - /* 12.1.2.1 eUTRANQoS */ - asn1cCalloc(drbs_toBeSetup_item->qoSInformation.choice.eUTRANQoS, eUTRANQoS); - /* 12.1.2.1.1 qCI */ - eUTRANQoS->qCI = 254L; - /* 12.1.2.1.2 allocationAndRetentionPriority */ - { - /* 12.1.2.1.2.1 priorityLevel */ - eUTRANQoS->allocationAndRetentionPriority.priorityLevel = F1AP_PriorityLevel_highest; // enum - /* 12.1.2.1.2.2 pre_emptionCapability */ - eUTRANQoS->allocationAndRetentionPriority.pre_emptionCapability = F1AP_Pre_emptionCapability_may_trigger_pre_emption; // enum - /* 12.1.2.1.2.2 pre_emptionVulnerability */ - eUTRANQoS->allocationAndRetentionPriority.pre_emptionVulnerability = F1AP_Pre_emptionVulnerability_not_pre_emptable; // enum - } - - /* OPTIONAL */ - /* 12.1.2.1.3 gbrQosInformation */ - if (0) { - eUTRANQoS->gbrQosInformation = (F1AP_GBR_QosInformation_t *)calloc(1, sizeof(F1AP_GBR_QosInformation_t)); - asn_long2INTEGER(&eUTRANQoS->gbrQosInformation->e_RAB_MaximumBitrateDL, 1L); - asn_long2INTEGER(&eUTRANQoS->gbrQosInformation->e_RAB_MaximumBitrateUL, 1L); - asn_long2INTEGER(&eUTRANQoS->gbrQosInformation->e_RAB_GuaranteedBitrateDL, 1L); - asn_long2INTEGER(&eUTRANQoS->gbrQosInformation->e_RAB_GuaranteedBitrateUL, 1L); - } - } else { - /* 12.1.2 DRB_Information */ - const f1ap_drb_information_t *drb_info = &drb->drb_info; - drbs_toBeSetup_item->qoSInformation.present = F1AP_QoSInformation_PR_choice_extension; - F1AP_QoSInformation_ExtIEs_t *ie = (F1AP_QoSInformation_ExtIEs_t *)calloc(1, sizeof(*ie)); - ie->id = F1AP_ProtocolIE_ID_id_DRB_Information; - ie->criticality = F1AP_Criticality_reject; - ie->value.present = F1AP_QoSInformation_ExtIEs__value_PR_DRB_Information; - F1AP_DRB_Information_t *DRB_Information = &ie->value.choice.DRB_Information; - drbs_toBeSetup_item->qoSInformation.choice.choice_extension = (struct F1AP_ProtocolIE_SingleContainer *)ie; - - /* 12.1.2.1 dRB_QoS */ - f1ap_write_drb_qos_param(&drb_info->drb_qos, &DRB_Information->dRB_QoS); - - /* 12.1.2.2 sNSSAI */ - f1ap_write_drb_nssai(&drb->nssai, &DRB_Information->sNSSAI); - - /* OPTIONAL */ - /* 12.1.2.3 notificationControl */ - if (0) { - asn1cCallocOne(DRB_Information->notificationControl, - F1AP_NotificationControl_active); // enum - } - - /* 12.1.2.4 flows_Mapped_To_DRB_List */ // BK: need verifiy - f1ap_write_flows_mapped(drb_info->flows_mapped_to_drb, &DRB_Information->flows_Mapped_To_DRB_List, drb_info->flows_to_be_setup_length); - } // if some_decide_qos - - /* 12.1.3 uLUPTNLInformation_ToBeSetup_List */ - for (int j = 0; j < f1ap_ue_context_setup_req->drbs_to_be_setup[i].up_ul_tnl_length; j++) { - DevAssert(f1ap_ue_context_setup_req->drbs_to_be_setup[i].up_ul_tnl[j].teid > 0); - /* 12.3.1 ULTunnels_ToBeSetup_Item */ - asn1cSequenceAdd(drbs_toBeSetup_item->uLUPTNLInformation_ToBeSetup_List.list, - F1AP_ULUPTNLInformation_ToBeSetup_Item_t, uLUPTNLInformation_ToBeSetup_Item); - uLUPTNLInformation_ToBeSetup_Item->uLUPTNLInformation.present = F1AP_UPTransportLayerInformation_PR_gTPTunnel; - asn1cCalloc( uLUPTNLInformation_ToBeSetup_Item->uLUPTNLInformation.choice.gTPTunnel, - gTPTunnel); - /* 12.3.1.1.1 transportLayerAddress */ - TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(f1ap_ue_context_setup_req->drbs_to_be_setup[i].up_ul_tnl[j].tl_address, - &gTPTunnel->transportLayerAddress); - /* 12.3.1.1.2 gTP_TEID */ - INT32_TO_OCTET_STRING(f1ap_ue_context_setup_req->drbs_to_be_setup[i].up_ul_tnl[j].teid, - &gTPTunnel->gTP_TEID); - } - - /* 12.1.4 rLCMode */ - /* TODO use rlc_mode from f1ap_drb_to_be_setup */ - switch (f1ap_ue_context_setup_req->drbs_to_be_setup[i].rlc_mode) { - case F1AP_RLC_MODE_AM: - drbs_toBeSetup_item->rLCMode = F1AP_RLCMode_rlc_am; - break; - case F1AP_RLC_MODE_UM_BIDIR: - drbs_toBeSetup_item->rLCMode = F1AP_RLCMode_rlc_um_bidirectional; - break; - default: - AssertFatal(false, "modes other than AM/UM-Bidir not supported\n"); - break; - } - - /* OPTIONAL */ - /* 12.1.5 ULConfiguration */ - if (0) { - asn1cCalloc(drbs_toBeSetup_item->uLConfiguration, tmp); - tmp->uLUEConfiguration = F1AP_ULUEConfiguration_no_data; - } - - /* OPTIONAL */ - /* 12.1.6 duplicationActivation */ - if (0) { - asn1cCalloc(drbs_toBeSetup_item->duplicationActivation, tmp); - *tmp = F1AP_DuplicationActivation_active; // enum - } - } - } - - /* OPTIONAL */ - /* InactivityMonitoringRequest */ - if (0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie12); - ie12->id = F1AP_ProtocolIE_ID_id_InactivityMonitoringRequest; - ie12->criticality = F1AP_Criticality_reject; - ie12->value.present = F1AP_UEContextSetupRequestIEs__value_PR_InactivityMonitoringRequest; - ie12->value.choice.InactivityMonitoringRequest = F1AP_InactivityMonitoringRequest_true; // 0 - } - - /* OPTIONAL */ - /* RAT_FrequencyPriorityInformation */ - if (0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie13); - ie13->id = F1AP_ProtocolIE_ID_id_RAT_FrequencyPriorityInformation; - ie13->criticality = F1AP_Criticality_reject; - ie13->value.present = F1AP_UEContextSetupRequestIEs__value_PR_RAT_FrequencyPriorityInformation; - int endc = 1; // RK: Get this from somewhere ... - - if (endc) { - ie13->value.choice.RAT_FrequencyPriorityInformation.present = F1AP_RAT_FrequencyPriorityInformation_PR_eNDC; - ie13->value.choice.RAT_FrequencyPriorityInformation.choice.eNDC = 11L; - } else { - ie13->value.choice.RAT_FrequencyPriorityInformation.present = F1AP_RAT_FrequencyPriorityInformation_PR_nGRAN; - ie13->value.choice.RAT_FrequencyPriorityInformation.choice.nGRAN = 11L; - } - } - - /* OPTIONAL */ - /* RRCContainer */ - if(f1ap_ue_context_setup_req->rrc_container_length > 0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie14); - ie14->id = F1AP_ProtocolIE_ID_id_RRCContainer; - ie14->criticality = F1AP_Criticality_ignore; - ie14->value.present = F1AP_UEContextSetupRequestIEs__value_PR_RRCContainer; - OCTET_STRING_fromBuf(&ie14->value.choice.RRCContainer, (const char *)f1ap_ue_context_setup_req->rrc_container, - f1ap_ue_context_setup_req->rrc_container_length); - } - - /* OPTIONAL */ - /* MaskedIMEISV */ - if (0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie15); - ie15->id = F1AP_ProtocolIE_ID_id_MaskedIMEISV; - ie15->criticality = F1AP_Criticality_reject; - ie15->value.present = F1AP_UEContextSetupRequestIEs__value_PR_MaskedIMEISV; - MaskedIMEISV_TO_BIT_STRING(12340000l, &ie15->value.choice.MaskedIMEISV); // size (64) - } - - /* encode */ - uint8_t *buffer=NULL; - uint32_t len=0; - - if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { + uint8_t *buffer = NULL; + uint32_t len = 0; + if (f1ap_encode_pdu(pdu, &buffer, &len) < 0) { LOG_E(F1AP, "Failed to encode F1 UE CONTEXT SETUP REQUEST\n"); return -1; } + f1ap_itti_send_sctp_data_req(assoc_id, buffer, len); + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); + #ifdef E2_AGENT - rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(RC.nrrrc[0], f1ap_ue_context_setup_req->gNB_CU_ue_id); + rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(RC.nrrrc[0], req->gNB_CU_ue_id); signal_ue_id(&ue_context_p->ue_context, F1_NETWORK_INTERFACE_TYPE, 0); #endif - // xer_fprint(stdout, &asn_DEF_F1AP_F1AP_PDU, (void *)pdu); - // asn_encode_to_new_buffer_result_t res = { NULL, {0, NULL, NULL} }; - // res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_F1AP_F1AP_PDU, pdu); - // buffer = res.buffer; - // len = res.result.encoded; - // if (res.result.encoded <= 0) { - // LOG_E(F1AP, "ASN1 message encoding failed (%s, %lu)!\n", res.result.failed_type->name, res.result.encoded); - // return -1; - // } - LOG_D(F1AP,"F1AP UEContextSetupRequest Encoded %u bits\n", len); - f1ap_itti_send_sctp_data_req(assoc_id, buffer, len); return 0; } @@ -935,459 +389,19 @@ int CU_handle_UE_CONTEXT_RELEASE_COMPLETE(instance_t instance, sctp_assoc_t asso return 0; } -int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_context_modif_req_t *f1ap_ue_context_modification_req) +int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc_id, const f1ap_ue_context_mod_req_t *req) { - F1AP_F1AP_PDU_t pdu= {0}; - F1AP_UEContextModificationRequest_t *out; + F1AP_F1AP_PDU_t *pdu = encode_ue_context_mod_req(req); + uint8_t *buffer=NULL; uint32_t len=0; - - /* Create */ - /* 0. Message Type */ - pdu.present = F1AP_F1AP_PDU_PR_initiatingMessage; - asn1cCalloc(pdu.choice.initiatingMessage, tmp); - tmp->procedureCode = F1AP_ProcedureCode_id_UEContextModification; - tmp->criticality = F1AP_Criticality_reject; - tmp->value.present = F1AP_InitiatingMessage__value_PR_UEContextModificationRequest; - out = &tmp->value.choice.UEContextModificationRequest; - /* mandatory */ - /* c1. GNB_CU_UE_F1AP_ID */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie1); - ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; - ie1->criticality = F1AP_Criticality_reject; - ie1->value.present = F1AP_UEContextModificationRequestIEs__value_PR_GNB_CU_UE_F1AP_ID; - ie1->value.choice.GNB_CU_UE_F1AP_ID = f1ap_ue_context_modification_req->gNB_CU_ue_id; - /* mandatory */ - /* c2. GNB_DU_UE_F1AP_ID */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie2); - ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; - ie2->criticality = F1AP_Criticality_reject; - ie2->value.present = F1AP_UEContextModificationRequestIEs__value_PR_GNB_DU_UE_F1AP_ID; - ie2->value.choice.GNB_DU_UE_F1AP_ID = f1ap_ue_context_modification_req->gNB_DU_ue_id; - - /* optional */ - /* c3. NRCGI */ - if (true) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie3); - ie3->id = F1AP_ProtocolIE_ID_id_SpCell_ID; - ie3->criticality = F1AP_Criticality_ignore; - ie3->value.present = F1AP_UEContextModificationRequestIEs__value_PR_NRCGI; - /* - nRCGI */ - - f1ap_served_cell_info_t nrcgi = { - .plmn = f1ap_ue_context_modification_req->plmn, - .nr_cellid = f1ap_ue_context_modification_req->nr_cellid, - }; - addnRCGI(ie3->value.choice.NRCGI, &nrcgi); - } - - /* optional */ - /* c4. ServCellIndex */ - if(0){ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie4); - ie4->id = F1AP_ProtocolIE_ID_id_ServCellIndex; - ie4->criticality = F1AP_Criticality_reject; - ie4->value.present = F1AP_UEContextModificationRequestIEs__value_PR_ServCellIndex; - ie4->value.choice.ServCellIndex = 5L; - } - - /* optional */ - /* c5. DRXCycle */ - if (0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie5); - ie5->id = F1AP_ProtocolIE_ID_id_DRXCycle; - ie5->criticality = F1AP_Criticality_ignore; - ie5->value.present = F1AP_UEContextModificationRequestIEs__value_PR_DRXCycle; - ie5->value.choice.DRXCycle.longDRXCycleLength = F1AP_LongDRXCycleLength_ms10; // enum - - if (0) { - asn1cCallocOne(ie5->value.choice.DRXCycle.shortDRXCycleLength, - F1AP_ShortDRXCycleLength_ms2); // enum - } - - if (0) { - asn1cCallocOne(ie5->value.choice.DRXCycle.shortDRXCycleTimer, 123L); - } - } - - /* optional */ - /* c6. CUtoDURRCInformation */ - if (f1ap_ue_context_modification_req->cu_to_du_rrc_information!=NULL) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie6); - ie6->id = F1AP_ProtocolIE_ID_id_CUtoDURRCInformation; - ie6->criticality = F1AP_Criticality_reject; - ie6->value.present = F1AP_UEContextModificationRequestIEs__value_PR_CUtoDURRCInformation; - /* 6.1 cG_ConfigInfo */ - if(f1ap_ue_context_modification_req->cu_to_du_rrc_information->cG_ConfigInfo!=NULL){ - asn1cCalloc(ie6->value.choice.CUtoDURRCInformation.cG_ConfigInfo, cG_ConfigInfo); - OCTET_STRING_fromBuf(cG_ConfigInfo, (const char *)f1ap_ue_context_modification_req->cu_to_du_rrc_information->cG_ConfigInfo, - f1ap_ue_context_modification_req->cu_to_du_rrc_information->cG_ConfigInfo_length); - } - /* optional */ - /* 6.2 uE_CapabilityRAT_ContainerList */ - if(f1ap_ue_context_modification_req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList!=NULL){ - asn1cCalloc(ie6->value.choice.CUtoDURRCInformation.uE_CapabilityRAT_ContainerList, uE_CapabilityRAT_ContainerList ); - OCTET_STRING_fromBuf(uE_CapabilityRAT_ContainerList, (const char *)f1ap_ue_context_modification_req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList, - f1ap_ue_context_modification_req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList_length) ; - } - /* optional */ - /* 6.3 measConfig */ - if(f1ap_ue_context_modification_req->cu_to_du_rrc_information->measConfig!=NULL){ - asn1cCalloc(ie6->value.choice.CUtoDURRCInformation.measConfig, measConfig); - OCTET_STRING_fromBuf(measConfig, (const char *)f1ap_ue_context_modification_req->cu_to_du_rrc_information->measConfig, - f1ap_ue_context_modification_req->cu_to_du_rrc_information->measConfig_length); - } - } - - /* optional */ - /* c7. TransmissionActionIndicator */ - if (f1ap_ue_context_modification_req->transm_action_ind != NULL) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie7); - ie7->id = F1AP_ProtocolIE_ID_id_TransmissionActionIndicator; - ie7->criticality = F1AP_Criticality_ignore; - ie7->value.present = F1AP_UEContextModificationRequestIEs__value_PR_TransmissionActionIndicator; - ie7->value.choice.TransmissionActionIndicator = *f1ap_ue_context_modification_req->transm_action_ind; - // Stop is guaranteed to be 0, by restart might be different from 1 - static_assert((int)F1AP_TransmissionActionIndicator_restart == (int)TransmActionInd_RESTART, - "mismatch of ASN.1 and internal representation\n"); - } - - /* optional */ - /* c8. ResourceCoordinationTransferContainer */ - if (0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie8); - ie8->id = F1AP_ProtocolIE_ID_id_ResourceCoordinationTransferContainer; - ie8->criticality = F1AP_Criticality_ignore; - ie8->value.present = F1AP_UEContextModificationRequestIEs__value_PR_ResourceCoordinationTransferContainer; - OCTET_STRING_fromBuf(&ie8->value.choice.ResourceCoordinationTransferContainer, "asdsa1d32sa1d31asd31as", - strlen("asdsa1d32sa1d31asd31as")); - } - - /* optional */ - /* c7. RRCRconfigurationCompleteIndicator */ - if (f1ap_ue_context_modification_req->ReconfigComplOutcome == RRCreconf_success) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie71); - ie71->id = F1AP_ProtocolIE_ID_id_RRCReconfigurationCompleteIndicator; - ie71->criticality = F1AP_Criticality_ignore; - ie71->value.present = F1AP_UEContextModificationRequestIEs__value_PR_RRCReconfigurationCompleteIndicator; - ie71->value.choice.RRCReconfigurationCompleteIndicator = F1AP_RRCReconfigurationCompleteIndicator_true; - } - - /* optional */ - /* c8. RRCContainer */ - if (f1ap_ue_context_modification_req->rrc_container != NULL) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie81); - ie81->id = F1AP_ProtocolIE_ID_id_RRCContainer; - ie81->criticality = F1AP_Criticality_ignore; - ie81->value.present = F1AP_UEContextModificationRequestIEs__value_PR_RRCContainer; - OCTET_STRING_fromBuf(&ie81->value.choice.RRCContainer, (const char*)f1ap_ue_context_modification_req->rrc_container, - f1ap_ue_context_modification_req->rrc_container_length); - } - - /* optional */ - /* c9. SCell_ToBeSetupMod_List */ - if(0){ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie9); - ie9->id = F1AP_ProtocolIE_ID_id_SCell_ToBeSetupMod_List; - ie9->criticality = F1AP_Criticality_ignore; - ie9->value.present = F1AP_UEContextModificationRequestIEs__value_PR_SCell_ToBeSetupMod_List; - - for (int i=0; i<1; i++) { - // - asn1cSequenceAdd(ie9->value.choice.SCell_ToBeSetupMod_List.list, - F1AP_SCell_ToBeSetupMod_ItemIEs_t, scell_toBeSetupMod_item_ies); - scell_toBeSetupMod_item_ies->id = F1AP_ProtocolIE_ID_id_SCell_ToBeSetupMod_Item; - scell_toBeSetupMod_item_ies->criticality = F1AP_Criticality_ignore; - scell_toBeSetupMod_item_ies->value.present = F1AP_SCell_ToBeSetupMod_ItemIEs__value_PR_SCell_ToBeSetupMod_Item; - /* 8.1 SCell_ToBeSetup_Item */ - F1AP_SCell_ToBeSetupMod_Item_t *scell_toBeSetupMod_item= - &scell_toBeSetupMod_item_ies->value.choice.SCell_ToBeSetupMod_Item; - // /* - sCell_ID */ - f1ap_served_cell_info_t hardCoded = {0}; - addnRCGI(scell_toBeSetupMod_item->sCell_ID, &hardCoded); - /* sCellIndex */ - scell_toBeSetupMod_item->sCellIndex = 6; // issue here - } - } - - /* optional */ - /* c10. SCell_ToBeRemoved_List */ - if(0){ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie10); - ie10->id = F1AP_ProtocolIE_ID_id_SCell_ToBeRemoved_List; - ie10->criticality = F1AP_Criticality_ignore; - ie10->value.present = F1AP_UEContextModificationRequestIEs__value_PR_SCell_ToBeRemoved_List; - - for (int i=0; i<1; i++) { - // - asn1cSequenceAdd(ie10->value.choice.SCell_ToBeRemoved_List.list, - F1AP_SCell_ToBeRemoved_ItemIEs_t, scell_toBeRemoved_item_ies); - scell_toBeRemoved_item_ies = (F1AP_SCell_ToBeRemoved_ItemIEs_t *)calloc(1, sizeof(F1AP_SCell_ToBeRemoved_ItemIEs_t)); - //memset((void *)&scell_toBeRemoved_item_ies, 0, sizeof(F1AP_SCell_ToBeRemoved_ItemIEs_t)); - scell_toBeRemoved_item_ies->id = F1AP_ProtocolIE_ID_id_SCell_ToBeRemoved_Item; - scell_toBeRemoved_item_ies->criticality = F1AP_Criticality_ignore; - scell_toBeRemoved_item_ies->value.present = F1AP_SCell_ToBeRemoved_ItemIEs__value_PR_SCell_ToBeRemoved_Item; - /* 10.1 SCell_ToBeRemoved_Item */ - F1AP_SCell_ToBeRemoved_Item_t *scell_toBeRemoved_item= - &scell_toBeRemoved_item_ies->value.choice.SCell_ToBeRemoved_Item; - /* - sCell_ID */ - f1ap_served_cell_info_t hardCoded = {0}; - addnRCGI(scell_toBeRemoved_item->sCell_ID, &hardCoded); - } - } - - /* mandatory */ - /* c11. SRBs_ToBeSetupMod_List */ - if(f1ap_ue_context_modification_req->srbs_to_be_setup_length > 0){ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie11); - ie11->id = F1AP_ProtocolIE_ID_id_SRBs_ToBeSetupMod_List; - ie11->criticality = F1AP_Criticality_reject; - ie11->value.present = F1AP_UEContextModificationRequestIEs__value_PR_SRBs_ToBeSetupMod_List; - - for (int i=0; isrbs_to_be_setup_length; i++) { - // - asn1cSequenceAdd(ie11->value.choice.SRBs_ToBeSetupMod_List, F1AP_SRBs_ToBeSetupMod_ItemIEs_t, srbs_toBeSetupMod_item_ies); - srbs_toBeSetupMod_item_ies->id = F1AP_ProtocolIE_ID_id_SRBs_ToBeSetupMod_Item; // 73 - srbs_toBeSetupMod_item_ies->criticality = F1AP_Criticality_reject; - srbs_toBeSetupMod_item_ies->value.present = F1AP_SRBs_ToBeSetupMod_ItemIEs__value_PR_SRBs_ToBeSetupMod_Item; - /* 11.1 SRBs_ToBeSetup_Item */ - F1AP_SRBs_ToBeSetupMod_Item_t *srbs_toBeSetupMod_item=&srbs_toBeSetupMod_item_ies->value.choice.SRBs_ToBeSetupMod_Item; - /* 11.1.1 sRBID */ - srbs_toBeSetupMod_item->sRBID = f1ap_ue_context_modification_req->srbs_to_be_setup[i].srb_id; - /* OPTIONAL */ - /* 11.1.2 duplicationIndication */ - asn1cCallocOne(srbs_toBeSetupMod_item->duplicationIndication, - F1AP_DuplicationIndication_true); // enum - } - } - - /* mandatory */ - /* c12. DRBs_ToBeSetupMod_List */ - if(f1ap_ue_context_modification_req->drbs_to_be_setup_length){ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie12); - ie12->id = F1AP_ProtocolIE_ID_id_DRBs_ToBeSetupMod_List; - ie12->criticality = F1AP_Criticality_reject; - ie12->value.present = F1AP_UEContextModificationRequestIEs__value_PR_DRBs_ToBeSetupMod_List; - - for (int i = 0; i < f1ap_ue_context_modification_req->drbs_to_be_setup_length; i++) { - const f1ap_drb_to_be_setup_t *drb = &f1ap_ue_context_modification_req->drbs_to_be_setup[i]; - asn1cSequenceAdd(ie12->value.choice.DRBs_ToBeSetupMod_List.list, - F1AP_DRBs_ToBeSetupMod_ItemIEs_t, drbs_toBeSetupMod_item_ies); - drbs_toBeSetupMod_item_ies->id = F1AP_ProtocolIE_ID_id_DRBs_ToBeSetupMod_Item; - drbs_toBeSetupMod_item_ies->criticality = F1AP_Criticality_reject; - drbs_toBeSetupMod_item_ies->value.present = F1AP_DRBs_ToBeSetupMod_ItemIEs__value_PR_DRBs_ToBeSetupMod_Item; - /* 12.1 DRBs_ToBeSetupMod_Item */ - F1AP_DRBs_ToBeSetupMod_Item_t *drbs_toBeSetupMod_item= - &drbs_toBeSetupMod_item_ies->value.choice.DRBs_ToBeSetupMod_Item; - /* dRBID */ - drbs_toBeSetupMod_item->dRBID = drb->drb_id; - /* qoSInformation */ - - if(f1ap_ue_context_modification_req->QoS_information_type == EUTRAN_QoS){ - drbs_toBeSetupMod_item->qoSInformation.present = F1AP_QoSInformation_PR_eUTRANQoS; - drbs_toBeSetupMod_item->qoSInformation.choice.eUTRANQoS = (F1AP_EUTRANQoS_t *)calloc(1, sizeof(F1AP_EUTRANQoS_t)); - drbs_toBeSetupMod_item->qoSInformation.choice.eUTRANQoS->qCI = 253L; - /* uLUPTNLInformation_ToBeSetup_List */ - int maxnoofULTunnels = 1; // 2; - - for (int j=0; juLUPTNLInformation_ToBeSetup_List.list, - F1AP_ULUPTNLInformation_ToBeSetup_Item_t, uLUPTNLInformation_ToBeSetup_Item); - uLUPTNLInformation_ToBeSetup_Item->uLUPTNLInformation.present = F1AP_UPTransportLayerInformation_PR_gTPTunnel; - asn1cCalloc(uLUPTNLInformation_ToBeSetup_Item->uLUPTNLInformation.choice.gTPTunnel, - gTPTunnel); - /* transportLayerAddress */ - TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(1234, &gTPTunnel->transportLayerAddress); - /* gTP_TEID */ - OCTET_STRING_fromBuf(&gTPTunnel->gTP_TEID, "4567", - strlen("4567")); - } - - /* rLCMode */ - drbs_toBeSetupMod_item->rLCMode = F1AP_RLCMode_rlc_um_bidirectional; // enum - - /* OPTIONAL */ - /* ULConfiguration */ - if (0) { - drbs_toBeSetupMod_item->uLConfiguration = (F1AP_ULConfiguration_t *)calloc(1, sizeof(F1AP_ULConfiguration_t)); - } - } //QoS information - - else{ - /* 12.1.2 DRB_Information */ - f1ap_drb_information_t *drb_info_in = &f1ap_ue_context_modification_req->drbs_to_be_setup[i].drb_info; - drbs_toBeSetupMod_item->qoSInformation.present = F1AP_QoSInformation_PR_choice_extension; - F1AP_QoSInformation_ExtIEs_t *ie = (F1AP_QoSInformation_ExtIEs_t *)calloc(1, sizeof(*ie)); - ie->id = F1AP_ProtocolIE_ID_id_DRB_Information; - ie->criticality = F1AP_Criticality_reject; - ie->value.present = F1AP_QoSInformation_ExtIEs__value_PR_DRB_Information; - F1AP_DRB_Information_t *DRB_Information = &ie->value.choice.DRB_Information; - drbs_toBeSetupMod_item->qoSInformation.choice.choice_extension = (struct F1AP_ProtocolIE_SingleContainer *)ie; - - /* 12.1.2.1 dRB_QoS */ - f1ap_write_drb_qos_param(&drb_info_in->drb_qos, &DRB_Information->dRB_QoS); - - /* 12.1.2.2 sNSSAI */ - f1ap_write_drb_nssai(&drb->nssai, &DRB_Information->sNSSAI); - - /* OPTIONAL */ - /* 12.1.2.3 notificationControl */ - if (0) { - asn1cCallocOne(DRB_Information->notificationControl, - F1AP_NotificationControl_active); // enum - } - - /* 12.1.2.4 flows_Mapped_To_DRB_List */ - f1ap_write_flows_mapped(drb_info_in->flows_mapped_to_drb, &DRB_Information->flows_Mapped_To_DRB_List, drb_info_in->flows_to_be_setup_length); - - } //QoS information - - /* 12.1.3 uLUPTNLInformation_ToBeSetup_List */ - for (int j = 0; j < f1ap_ue_context_modification_req->drbs_to_be_setup[i].up_ul_tnl_length; j++) { - /* Use a dummy address and teid for the outgoing GTP-U tunnel (DU) which will be updated once we get the UE context modification response from the DU */ - asn1cSequenceAdd(drbs_toBeSetupMod_item->uLUPTNLInformation_ToBeSetup_List.list, - F1AP_ULUPTNLInformation_ToBeSetup_Item_t, uLUPTNLInformation_ToBeSetup_Item); - uLUPTNLInformation_ToBeSetup_Item->uLUPTNLInformation.present = F1AP_UPTransportLayerInformation_PR_gTPTunnel; - asn1cCalloc( uLUPTNLInformation_ToBeSetup_Item->uLUPTNLInformation.choice.gTPTunnel, - gTPTunnel); - /* 12.3.1.1.1 transportLayerAddress */ - TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(f1ap_ue_context_modification_req->drbs_to_be_setup[i].up_ul_tnl[j].tl_address, - &gTPTunnel->transportLayerAddress); - /* 12.3.1.1.2 gTP_TEID */ - INT32_TO_OCTET_STRING(f1ap_ue_context_modification_req->drbs_to_be_setup[i].up_ul_tnl[j].teid, - &gTPTunnel->gTP_TEID); - } - /* 12.1.4 rLCMode */ - /* TODO use rlc_mode from f1ap_drb_to_be_setup */ - switch (f1ap_ue_context_modification_req->drbs_to_be_setup[i].rlc_mode) { - case F1AP_RLC_MODE_AM: - drbs_toBeSetupMod_item->rLCMode = F1AP_RLCMode_rlc_am; - break; - case F1AP_RLC_MODE_UM_BIDIR: - drbs_toBeSetupMod_item->rLCMode = F1AP_RLCMode_rlc_um_bidirectional; - break; - default: - AssertFatal(false, "modes other than AM/UM-Bidir not supported\n"); - break; - } - - /* OPTIONAL */ - /* 12.1.5 ULConfiguration */ - if (0) { - asn1cCalloc(drbs_toBeSetupMod_item->uLConfiguration, tmp); - tmp->uLUEConfiguration = F1AP_ULUEConfiguration_no_data; - } - - /* OPTIONAL */ - /* 12.1.6 duplicationActivation */ - if (0) { - asn1cCalloc(drbs_toBeSetupMod_item->duplicationActivation, tmp); - *tmp = F1AP_DuplicationActivation_active; // enum - } - } - } - - /* optional */ - if(0){ - /* c13. DRBs_ToBeModified_List */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie13); - ie13->id = F1AP_ProtocolIE_ID_id_DRBs_ToBeModified_List; - ie13->criticality = F1AP_Criticality_reject; - ie13->value.present = F1AP_UEContextModificationRequestIEs__value_PR_DRBs_ToBeModified_List; - - for (int i=0; i<1; i++) { - // - asn1cSequenceAdd( ie13->value.choice.DRBs_ToBeModified_List.list, - F1AP_DRBs_ToBeModified_ItemIEs_t, drbs_toBeModified_item_ies); - drbs_toBeModified_item_ies->id = F1AP_ProtocolIE_ID_id_DRBs_ToBeModified_Item; - drbs_toBeModified_item_ies->criticality = F1AP_Criticality_reject; - drbs_toBeModified_item_ies->value.present = F1AP_DRBs_ToBeModified_ItemIEs__value_PR_DRBs_ToBeModified_Item; - /* 13.1 SRBs_ToBeModified_Item */ - F1AP_DRBs_ToBeModified_Item_t *drbs_toBeModified_item= - &drbs_toBeModified_item_ies->value.choice.DRBs_ToBeModified_Item; - /* dRBID */ - drbs_toBeModified_item->dRBID = 30L; - /* qoSInformation */ - asn1cCalloc(drbs_toBeModified_item->qoSInformation, tmp); - tmp->present = F1AP_QoSInformation_PR_eUTRANQoS; - tmp->choice.eUTRANQoS = (F1AP_EUTRANQoS_t *)calloc(1, sizeof(F1AP_EUTRANQoS_t)); - tmp->choice.eUTRANQoS->qCI = 254L; - /* ULTunnels_ToBeModified_List */ - int maxnoofULTunnels = 1; // 2; - - for (int j=0; juLUPTNLInformation_ToBeSetup_List.list, - F1AP_ULUPTNLInformation_ToBeSetup_Item_t, uLUPTNLInformation_ToBeSetup_Item); - uLUPTNLInformation_ToBeSetup_Item->uLUPTNLInformation.present = F1AP_UPTransportLayerInformation_PR_gTPTunnel; - asn1cCalloc(uLUPTNLInformation_ToBeSetup_Item->uLUPTNLInformation.choice.gTPTunnel, - gTPTunnel); - TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(1234, &gTPTunnel->transportLayerAddress); - OCTET_STRING_fromBuf(&gTPTunnel->gTP_TEID, "1204", - strlen("1204")); - } - - /* OPTIONAL */ - /* ULConfiguration */ - if (0) { - drbs_toBeModified_item->uLConfiguration = (F1AP_ULConfiguration_t *)calloc(1, sizeof(F1AP_ULConfiguration_t)); - } - } - } - - /* optional */ - if(0){ - /* c14. SRBs_ToBeReleased_List */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie14); - ie14->id = F1AP_ProtocolIE_ID_id_SRBs_ToBeReleased_List; - ie14->criticality = F1AP_Criticality_reject; - ie14->value.present = F1AP_UEContextModificationRequestIEs__value_PR_SRBs_ToBeReleased_List; - - for (int i=0; i<1; i++) { - // - asn1cSequenceAdd(ie14->value.choice.SRBs_ToBeReleased_List.list, - F1AP_SRBs_ToBeReleased_ItemIEs_t, srbs_toBeReleased_item_ies); - srbs_toBeReleased_item_ies->id = F1AP_ProtocolIE_ID_id_SRBs_ToBeReleased_Item; - srbs_toBeReleased_item_ies->criticality = F1AP_Criticality_ignore; - srbs_toBeReleased_item_ies->value.present = F1AP_SRBs_ToBeReleased_ItemIEs__value_PR_SRBs_ToBeReleased_Item; - /* 9.1 SRBs_ToBeReleased_Item */ - F1AP_SRBs_ToBeReleased_Item_t *srbs_toBeReleased_item= - &srbs_toBeReleased_item_ies->value.choice.SRBs_ToBeReleased_Item; - /* - sRBID */ - srbs_toBeReleased_item->sRBID = 2L; - } - } - - /* optional */ - if (f1ap_ue_context_modification_req->drbs_to_be_released_length > 0) { - /* c15. DRBs_ToBeReleased_List */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie15); - ie15->id = F1AP_ProtocolIE_ID_id_DRBs_ToBeReleased_List; - ie15->criticality = F1AP_Criticality_reject; - ie15->value.present = F1AP_UEContextModificationRequestIEs__value_PR_DRBs_ToBeReleased_List; - - for (int i = 0; i < f1ap_ue_context_modification_req->drbs_to_be_released_length; i++) { - // - asn1cSequenceAdd(ie15->value.choice.DRBs_ToBeReleased_List.list, - F1AP_DRBs_ToBeReleased_ItemIEs_t, drbs_toBeReleased_item_ies); - drbs_toBeReleased_item_ies->id = F1AP_ProtocolIE_ID_id_DRBs_ToBeReleased_Item; - drbs_toBeReleased_item_ies->criticality = F1AP_Criticality_reject; - drbs_toBeReleased_item_ies->value.present = F1AP_DRBs_ToBeReleased_ItemIEs__value_PR_DRBs_ToBeReleased_Item; - /* 14.1 SRBs_ToBeReleased_Item */ - F1AP_DRBs_ToBeReleased_Item_t *drbs_toBeReleased_item= - &drbs_toBeReleased_item_ies->value.choice.DRBs_ToBeReleased_Item; - /* dRBID */ - drbs_toBeReleased_item->dRBID = f1ap_ue_context_modification_req->drbs_to_be_released[i].rb_id; - } - } - - /* encode */ - if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { - LOG_E(F1AP, "Failed to encode F1 UE CONTEXT_MODIFICATION REQUEST\n"); + if (f1ap_encode_pdu(pdu, &buffer, &len) < 0) { + LOG_E(F1AP, "Failed to encode F1 UE Context Modification Request\n"); return -1; } + f1ap_itti_send_sctp_data_req(assoc_id, buffer, len); + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); return 0; } diff --git a/openair2/F1AP/f1ap_cu_ue_context_management.h b/openair2/F1AP/f1ap_cu_ue_context_management.h index 05e67930b3..ed76189c19 100644 --- a/openair2/F1AP/f1ap_cu_ue_context_management.h +++ b/openair2/F1AP/f1ap_cu_ue_context_management.h @@ -36,8 +36,7 @@ /* * UE Context Setup */ -int CU_send_UE_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, - f1ap_ue_context_setup_t *f1ap_ue_context_setup_req); +int CU_send_UE_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, const f1ap_ue_context_setup_req_t *req); int CU_handle_UE_CONTEXT_SETUP_RESPONSE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu); @@ -59,7 +58,7 @@ int CU_handle_UE_CONTEXT_RELEASE_COMPLETE(instance_t instance, sctp_assoc_t asso /* * UE Context Modification (gNB-CU initiated) */ -int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_context_modif_req_t *f1ap_ue_context_modification_req); +int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc_id, const f1ap_ue_context_mod_req_t *req); int CU_handle_UE_CONTEXT_MODIFICATION_RESPONSE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu); int CU_handle_UE_CONTEXT_MODIFICATION_FAILURE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu); diff --git a/openair2/F1AP/f1ap_du_task.c b/openair2/F1AP/f1ap_du_task.c index c231561eec..cd76933d44 100644 --- a/openair2/F1AP/f1ap_du_task.c +++ b/openair2/F1AP/f1ap_du_task.c @@ -36,6 +36,7 @@ #include "f1ap_du_rrc_message_transfer.h" #include "lib/f1ap_rrc_message_transfer.h" #include "lib/f1ap_interface_management.h" +#include "lib/f1ap_ue_context.h" #include "f1ap_du_task.h" #include diff --git a/openair2/F1AP/f1ap_du_ue_context_management.c b/openair2/F1AP/f1ap_du_ue_context_management.c index cd9b2865c9..13c9e92ec5 100644 --- a/openair2/F1AP/f1ap_du_ue_context_management.c +++ b/openair2/F1AP/f1ap_du_ue_context_management.c @@ -34,295 +34,24 @@ #include "f1ap_encoder.h" #include "f1ap_itti_messaging.h" #include "f1ap_du_ue_context_management.h" +#include "lib/f1ap_ue_context.h" #include "openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h" #include "openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h" #include "openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h" -static void f1ap_read_drb_qos_param(const F1AP_QoSFlowLevelQoSParameters_t *asn1_qos, f1ap_qos_flow_level_qos_parameters_t *drb_qos) -{ - f1ap_qos_characteristics_t *drb_qos_char = &drb_qos->qos_characteristics; - const F1AP_QoS_Characteristics_t *dRB_QoS_Char = &asn1_qos->qoS_Characteristics; - - if (dRB_QoS_Char->present == F1AP_QoS_Characteristics_PR_non_Dynamic_5QI) { - drb_qos_char->qos_type = NON_DYNAMIC; - drb_qos_char->non_dynamic.fiveqi = dRB_QoS_Char->choice.non_Dynamic_5QI->fiveQI; - drb_qos_char->non_dynamic.qos_priority_level = (dRB_QoS_Char->choice.non_Dynamic_5QI->qoSPriorityLevel != NULL) - ? *dRB_QoS_Char->choice.non_Dynamic_5QI->qoSPriorityLevel - : -1; - } else { - drb_qos_char->qos_type = DYNAMIC; - drb_qos_char->dynamic.fiveqi = - (dRB_QoS_Char->choice.dynamic_5QI->fiveQI != NULL) ? *dRB_QoS_Char->choice.dynamic_5QI->fiveQI : -1; - drb_qos_char->dynamic.qos_priority_level = dRB_QoS_Char->choice.dynamic_5QI->qoSPriorityLevel; - drb_qos_char->dynamic.packet_delay_budget = dRB_QoS_Char->choice.dynamic_5QI->packetDelayBudget; - drb_qos_char->dynamic.packet_error_rate.per_scalar = dRB_QoS_Char->choice.dynamic_5QI->packetErrorRate.pER_Scalar; - drb_qos_char->dynamic.packet_error_rate.per_exponent = dRB_QoS_Char->choice.dynamic_5QI->packetErrorRate.pER_Exponent; - } - - /* nGRANallocationRetentionPriority */ - drb_qos->alloc_reten_priority.priority_level = asn1_qos->nGRANallocationRetentionPriority.priorityLevel; - drb_qos->alloc_reten_priority.preemption_vulnerability = asn1_qos->nGRANallocationRetentionPriority.pre_emptionVulnerability; - drb_qos->alloc_reten_priority.preemption_capability = asn1_qos->nGRANallocationRetentionPriority.pre_emptionVulnerability; -} - -static void f1ap_read_flows_mapped(const F1AP_Flows_Mapped_To_DRB_List_t *asn1_flows_mapped, f1ap_flows_mapped_to_drb_t *flows_mapped, int n) -{ - for (int k = 0; k < n; k++) { - f1ap_flows_mapped_to_drb_t *flows_mapped_to_drb = flows_mapped + k; - const F1AP_Flows_Mapped_To_DRB_Item_t *flows_Mapped_To_Drb = asn1_flows_mapped->list.array[0] + k; - - flows_mapped_to_drb->qfi = flows_Mapped_To_Drb->qoSFlowIdentifier; - - /* QoS-Flow-Level-QoS-Parameters */ - { - f1ap_qos_flow_level_qos_parameters_t *flow_qos = &flows_mapped_to_drb->qos_params; - const F1AP_QoSFlowLevelQoSParameters_t *Flow_QoS = &flows_Mapped_To_Drb->qoSFlowLevelQoSParameters; - - /* QoS Characteristics*/ - f1ap_qos_characteristics_t *flow_qos_char = &flow_qos->qos_characteristics; - const F1AP_QoS_Characteristics_t *Flow_QoS_Char = &Flow_QoS->qoS_Characteristics; - - if (Flow_QoS_Char->present == F1AP_QoS_Characteristics_PR_non_Dynamic_5QI) { - flow_qos_char->qos_type = NON_DYNAMIC; - flow_qos_char->non_dynamic.fiveqi = Flow_QoS_Char->choice.non_Dynamic_5QI->fiveQI; - flow_qos_char->non_dynamic.qos_priority_level = (Flow_QoS_Char->choice.non_Dynamic_5QI->qoSPriorityLevel != NULL) - ? *Flow_QoS_Char->choice.non_Dynamic_5QI->qoSPriorityLevel - : -1; - } else { - flow_qos_char->qos_type = DYNAMIC; - flow_qos_char->dynamic.fiveqi = - (Flow_QoS_Char->choice.dynamic_5QI->fiveQI != NULL) ? *Flow_QoS_Char->choice.dynamic_5QI->fiveQI : -1; - flow_qos_char->dynamic.qos_priority_level = Flow_QoS_Char->choice.dynamic_5QI->qoSPriorityLevel; - flow_qos_char->dynamic.packet_delay_budget = Flow_QoS_Char->choice.dynamic_5QI->packetDelayBudget; - flow_qos_char->dynamic.packet_error_rate.per_scalar = Flow_QoS_Char->choice.dynamic_5QI->packetErrorRate.pER_Scalar; - flow_qos_char->dynamic.packet_error_rate.per_exponent = Flow_QoS_Char->choice.dynamic_5QI->packetErrorRate.pER_Exponent; - } - - /* nGRANallocationRetentionPriority */ - flow_qos->alloc_reten_priority.priority_level = Flow_QoS->nGRANallocationRetentionPriority.priorityLevel; - flow_qos->alloc_reten_priority.preemption_vulnerability = Flow_QoS->nGRANallocationRetentionPriority.pre_emptionVulnerability; - flow_qos->alloc_reten_priority.preemption_capability = Flow_QoS->nGRANallocationRetentionPriority.pre_emptionVulnerability; - } - } -} - -static void f1ap_read_drb_nssai(const F1AP_SNSSAI_t *asn1_nssai, nssai_t *nssai) -{ - OCTET_STRING_TO_INT8(&asn1_nssai->sST, nssai->sst); - nssai->sd = 0xffffff; - if (asn1_nssai->sD != NULL) { - BUFFER_TO_INT24(asn1_nssai->sD->buf, nssai->sd); - } -} - int DU_handle_UE_CONTEXT_SETUP_REQUEST(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { - F1AP_UEContextSetupRequest_t *container; - int i; - DevAssert(pdu); - f1ap_ue_context_setup_t ue_context_setup = {0}; - f1ap_ue_context_setup_t *f1ap_ue_context_setup_req = &ue_context_setup; - container = &pdu->choice.initiatingMessage->value.choice.UEContextSetupRequest; - /* GNB_CU_UE_F1AP_ID */ - F1AP_UEContextSetupRequestIEs_t *ieCU; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupRequestIEs_t, ieCU, container, - F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); - f1ap_ue_context_setup_req->gNB_CU_ue_id = ieCU->value.choice.GNB_CU_UE_F1AP_ID; - /* optional */ - /* GNB_DU_UE_F1AP_ID */ - F1AP_UEContextSetupRequestIEs_t *ieDU_UE; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupRequestIEs_t, ieDU_UE, container, - F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, false); - // this should be optional. At present, the DU uses the RNTI, and hence, this - // value cannot exceed 0xffff (or something below, whatever is a valid - // C-RNTI). So we use a value > 0xffff to mark optionality - f1ap_ue_context_setup_req->gNB_DU_ue_id = -1; // 0xffffffff - if (ieDU_UE != NULL) - f1ap_ue_context_setup_req->gNB_DU_ue_id = ieDU_UE->value.choice.GNB_DU_UE_F1AP_ID; - - /* SpCell_ID */ - F1AP_UEContextSetupRequestIEs_t *ieNet; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupRequestIEs_t, ieNet, container, - F1AP_ProtocolIE_ID_id_SpCell_ID, true); - PLMNID_TO_MCC_MNC(&ieNet->value.choice.NRCGI.pLMN_Identity, - f1ap_ue_context_setup_req->plmn.mcc, - f1ap_ue_context_setup_req->plmn.mnc, - f1ap_ue_context_setup_req->plmn.mnc_digit_length); - BIT_STRING_TO_NR_CELL_IDENTITY(&ieNet->value.choice.NRCGI.nRCellIdentity, f1ap_ue_context_setup_req->nr_cellid); - /* ServCellIndex */ - F1AP_UEContextSetupRequestIEs_t *ieCell; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupRequestIEs_t, ieCell, container, - F1AP_ProtocolIE_ID_id_ServCellIndex, true); - f1ap_ue_context_setup_req->servCellIndex = ieCell->value.choice.ServCellIndex; - /* optional */ - /* CellULConfigured */ - F1AP_UEContextSetupRequestIEs_t *ieULCell; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupRequestIEs_t, ieULCell, container, - F1AP_ProtocolIE_ID_id_SpCellULConfigured, false); // SpCellULConfigured - - if (ieULCell) { - /* correct here */ - f1ap_ue_context_setup_req->cellULConfigured = malloc(sizeof(uint32_t)); - - if (f1ap_ue_context_setup_req->cellULConfigured) - *f1ap_ue_context_setup_req->cellULConfigured = ieULCell->value.choice.CellULConfigured; - } else { - f1ap_ue_context_setup_req->cellULConfigured = NULL; + f1ap_ue_context_setup_req_t req = {0}; + if (!decode_ue_context_setup_req(pdu, &req)) { + LOG_E(F1AP, "cannot decode F1 UE Context Setup Request\n"); + free_ue_context_setup_req(&req); + return -1; } - F1AP_UEContextSetupRequestIEs_t *ieCuRrcInfo; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupRequestIEs_t, ieCuRrcInfo, container, - F1AP_ProtocolIE_ID_id_CUtoDURRCInformation, false); - if(ieCuRrcInfo!=NULL){ - f1ap_ue_context_setup_req->cu_to_du_rrc_information = (cu_to_du_rrc_information_t *)calloc(1,sizeof(cu_to_du_rrc_information_t)); - cu_to_du_rrc_information_t *cu2du = f1ap_ue_context_setup_req->cu_to_du_rrc_information; - const F1AP_CUtoDURRCInformation_t *cu2duie = &ieCuRrcInfo->value.choice.CUtoDURRCInformation; - if (cu2duie->cG_ConfigInfo != NULL) { - cu2du->cG_ConfigInfo = malloc_or_fail(cu2duie->cG_ConfigInfo->size); - cu2du->cG_ConfigInfo_length = cu2duie->cG_ConfigInfo->size; - memcpy(cu2du->cG_ConfigInfo, cu2duie->cG_ConfigInfo->buf, cu2du->cG_ConfigInfo_length); - } - if(cu2duie->uE_CapabilityRAT_ContainerList!=NULL){ - cu2du->uE_CapabilityRAT_ContainerList = calloc(1, cu2duie->uE_CapabilityRAT_ContainerList->size); - memcpy(cu2du->uE_CapabilityRAT_ContainerList, - cu2duie->uE_CapabilityRAT_ContainerList->buf, - cu2duie->uE_CapabilityRAT_ContainerList->size); - cu2du->uE_CapabilityRAT_ContainerList_length = cu2duie->uE_CapabilityRAT_ContainerList->size; - LOG_D(F1AP, "Size f1ap_ue_context_setup_req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList_length: %d \n", f1ap_ue_context_setup_req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList_length); - } - if (cu2duie->iE_Extensions != NULL) { - const F1AP_ProtocolExtensionContainer_10696P60_t *ext = (const F1AP_ProtocolExtensionContainer_10696P60_t *)cu2duie->iE_Extensions; - for (int i = 0; i < ext->list.count; ++i) { - const F1AP_CUtoDURRCInformation_ExtIEs_t *cu2du_info = ext->list.array[i]; - switch (cu2du_info->id) { - case F1AP_ProtocolIE_ID_id_HandoverPreparationInformation: - DevAssert(cu2du_info->extensionValue.present == F1AP_CUtoDURRCInformation_ExtIEs__extensionValue_PR_HandoverPreparationInformation); - const F1AP_HandoverPreparationInformation_t *hopi = &cu2du_info->extensionValue.choice.MeasurementTimingConfiguration; - cu2du->handoverPreparationInfo = calloc_or_fail(1, hopi->size); - memcpy(cu2du->handoverPreparationInfo, hopi->buf, hopi->size); - cu2du->handoverPreparationInfo_length = hopi->size; - break; - default: - LOG_W(F1AP, "unsupported CUtoDURRCInformation_ExtIE %ld encountered, ignoring\n", cu2du_info->id); - break; - } - } - } - } + ue_context_setup_request(&req); + free_ue_context_setup_req(&req); - /* DRB */ - F1AP_UEContextSetupRequestIEs_t *ieDrb; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupRequestIEs_t, ieDrb, container, - F1AP_ProtocolIE_ID_id_DRBs_ToBeSetup_List, false); - - if(ieDrb!=NULL) { - f1ap_ue_context_setup_req->drbs_to_be_setup_length = ieDrb->value.choice.DRBs_ToBeSetup_List.list.count; - f1ap_ue_context_setup_req->drbs_to_be_setup = calloc(f1ap_ue_context_setup_req->drbs_to_be_setup_length, - sizeof(f1ap_drb_to_be_setup_t)); - AssertFatal(f1ap_ue_context_setup_req->drbs_to_be_setup, - "could not allocate memory for f1ap_ue_context_setup_req->drbs_to_be_setup\n"); - - for (i = 0; i < f1ap_ue_context_setup_req->drbs_to_be_setup_length; ++i) { - f1ap_drb_to_be_setup_t *drb_p = &f1ap_ue_context_setup_req->drbs_to_be_setup[i]; - F1AP_DRBs_ToBeSetup_Item_t *drbs_tobesetup_item_p = - &((F1AP_DRBs_ToBeSetup_ItemIEs_t *)ieDrb->value.choice.DRBs_ToBeSetup_List.list.array[i])->value.choice.DRBs_ToBeSetup_Item; - drb_p->drb_id = drbs_tobesetup_item_p->dRBID; - /* TODO in the following, assume only one UP UL TNL is present. - * this matches/assumes OAI CU implementation, can be up to 2! */ - drb_p->up_ul_tnl_length = 1; - AssertFatal(drbs_tobesetup_item_p->uLUPTNLInformation_ToBeSetup_List.list.count > 0, - "no UL UP TNL Information in DRBs to be Setup list\n"); - F1AP_ULUPTNLInformation_ToBeSetup_Item_t *ul_up_tnl_info_p = (F1AP_ULUPTNLInformation_ToBeSetup_Item_t *)drbs_tobesetup_item_p->uLUPTNLInformation_ToBeSetup_List.list.array[0]; - F1AP_GTPTunnel_t *ul_up_tnl0 = ul_up_tnl_info_p->uLUPTNLInformation.choice.gTPTunnel; - BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&ul_up_tnl0->transportLayerAddress, drb_p->up_ul_tnl[0].tl_address); - OCTET_STRING_TO_UINT32(&ul_up_tnl0->gTP_TEID, drb_p->up_ul_tnl[0].teid); - // 3GPP assumes GTP-U is on port 2152, but OAI is configurable - drb_p->up_ul_tnl[0].port = getCxt(instance)->net_config.CUport; - - switch (drbs_tobesetup_item_p->rLCMode) { - case F1AP_RLCMode_rlc_am: - drb_p->rlc_mode = F1AP_RLC_MODE_AM; - break; - case F1AP_RLCMode_rlc_um_bidirectional: - drb_p->rlc_mode = F1AP_RLC_MODE_UM_BIDIR; - break; - default: - LOG_W(F1AP, "unsupported RLC Mode %ld received: setting UM bidir\n", drbs_tobesetup_item_p->rLCMode); - drb_p->rlc_mode = F1AP_RLC_MODE_UM_BIDIR; - break; - } - - if (drbs_tobesetup_item_p->qoSInformation.present == F1AP_QoSInformation_PR_eUTRANQoS) { - AssertFatal(false, "Decode of eUTRANQoS is not implemented yet"); - } // EUTRAN QoS Information - else { - /* 12.1.2 DRB_Information */ - if (drbs_tobesetup_item_p->qoSInformation.present == F1AP_QoSInformation_PR_choice_extension) { - F1AP_QoSInformation_ExtIEs_t *ie = - (F1AP_QoSInformation_ExtIEs_t *)drbs_tobesetup_item_p->qoSInformation.choice.choice_extension; - if (ie->id == F1AP_ProtocolIE_ID_id_DRB_Information && ie->criticality == F1AP_Criticality_reject - && ie->value.present == F1AP_QoSInformation_ExtIEs__value_PR_DRB_Information) { - - const F1AP_DRB_Information_t *dRB_Info = &ie->value.choice.DRB_Information; - f1ap_drb_information_t *drb_info = &drb_p->drb_info; - - /* QoS-Flow-Level-QoS-Parameters */ - /* QoS Characteristics*/ - f1ap_read_drb_qos_param(&dRB_Info->dRB_QoS, &drb_info->drb_qos); - - // 12.1.2.4 flows_Mapped_To_DRB_List - drb_info->flows_to_be_setup_length = dRB_Info->flows_Mapped_To_DRB_List.list.count; - drb_info->flows_mapped_to_drb = calloc(drb_info->flows_to_be_setup_length, sizeof(f1ap_flows_mapped_to_drb_t)); - AssertFatal(drb_info->flows_mapped_to_drb, "could not allocate memory for drb_p->drb_info.flows_mapped_to_drb\n"); - f1ap_read_flows_mapped(&dRB_Info->flows_Mapped_To_DRB_List, drb_info->flows_mapped_to_drb, drb_info->flows_to_be_setup_length); - - /* S-NSSAI */ - f1ap_read_drb_nssai(&dRB_Info->sNSSAI, &drb_p->nssai); - } - } - } - } - } - - /* SRB */ - F1AP_UEContextSetupRequestIEs_t *ieSrb; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupRequestIEs_t, ieSrb, container, - F1AP_ProtocolIE_ID_id_SRBs_ToBeSetup_List, false); - - if(ieSrb != NULL) { - f1ap_ue_context_setup_req->srbs_to_be_setup_length = ieSrb->value.choice.SRBs_ToBeSetup_List.list.count; - f1ap_ue_context_setup_req->srbs_to_be_setup = calloc(f1ap_ue_context_setup_req->srbs_to_be_setup_length, - sizeof(f1ap_srb_to_be_setup_t)); - AssertFatal(f1ap_ue_context_setup_req->srbs_to_be_setup, - "could not allocate memory for f1ap_ue_context_setup_req->srbs_to_be_setup\n"); - - for (i = 0; i < f1ap_ue_context_setup_req->srbs_to_be_setup_length; ++i) { - f1ap_srb_to_be_setup_t *srb_p = &f1ap_ue_context_setup_req->srbs_to_be_setup[i]; - F1AP_SRBs_ToBeSetup_Item_t *srbs_tobesetup_item_p; - srbs_tobesetup_item_p = &((F1AP_SRBs_ToBeSetup_ItemIEs_t *)ieSrb->value.choice.SRBs_ToBeSetup_List.list.array[i])->value.choice.SRBs_ToBeSetup_Item; - srb_p->srb_id = srbs_tobesetup_item_p->sRBID; - } - } - - /* RRCContainer */ - F1AP_UEContextSetupRequestIEs_t *ieRRC; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupRequestIEs_t, ieRRC, container, - F1AP_ProtocolIE_ID_id_RRCContainer, false); - - if (ieRRC) { - /* correct here */ - if ( ieRRC->value.choice.RRCContainer.size ) { - f1ap_ue_context_setup_req->rrc_container = malloc(ieRRC->value.choice.RRCContainer.size); - memcpy(f1ap_ue_context_setup_req->rrc_container, - ieRRC->value.choice.RRCContainer.buf, ieRRC->value.choice.RRCContainer.size); - f1ap_ue_context_setup_req->rrc_container_length = ieRRC->value.choice.RRCContainer.size; - } else { - LOG_E(F1AP, " RRCContainer in UEContextSetupRequestIEs size id 0\n"); - } - } - - ue_context_setup_request(f1ap_ue_context_setup_req); return 0; } @@ -893,214 +622,16 @@ int DU_send_UE_CONTEXT_RELEASE_COMPLETE(sctp_assoc_t assoc_id, f1ap_ue_context_r int DU_handle_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { - F1AP_UEContextModificationRequest_t *container; - int i; - f1ap_ue_context_modif_req_t ue_context_modification = {0}; - f1ap_ue_context_modif_req_t *f1ap_ue_context_modification_req = &ue_context_modification; - container = &pdu->choice.initiatingMessage->value.choice.UEContextModificationRequest; - - /* mandatory */ - /* GNB_CU_UE_F1AP_ID */ - F1AP_UEContextModificationRequestIEs_t *ieCU; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequestIEs_t, ieCU, container, - F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); - f1ap_ue_context_modification_req->gNB_CU_ue_id = ieCU->value.choice.GNB_CU_UE_F1AP_ID; - - /* mandatory */ - /* GNB_DU_UE_F1AP_ID */ - F1AP_UEContextModificationRequestIEs_t *ieDU_UE; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequestIEs_t, ieDU_UE, container, - F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); - f1ap_ue_context_modification_req->gNB_DU_ue_id = ieDU_UE->value.choice.GNB_DU_UE_F1AP_ID; - - /* SRB */ - F1AP_UEContextModificationRequestIEs_t *ieSrb; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequestIEs_t, ieSrb, container, - F1AP_ProtocolIE_ID_id_SRBs_ToBeSetupMod_List, false); - - F1AP_UEContextModificationRequestIEs_t *ieTxInd; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequestIEs_t, - ieTxInd, - container, - F1AP_ProtocolIE_ID_id_TransmissionActionIndicator, - false); - - if (ieTxInd != NULL) { - f1ap_ue_context_modification_req->transm_action_ind = calloc_or_fail(1, sizeof(*f1ap_ue_context_modification_req->transm_action_ind)); - *f1ap_ue_context_modification_req->transm_action_ind = ieTxInd->value.choice.TransmissionActionIndicator; - // Stop is guaranteed to be 0, by restart might be different from 1 - static_assert((int)F1AP_TransmissionActionIndicator_restart == (int)TransmActionInd_RESTART, - "mismatch of ASN.1 and internal representation\n"); + f1ap_ue_context_mod_req_t req = {0}; + if (!decode_ue_context_mod_req(pdu, &req)) { + LOG_E(F1AP, "cannot decode F1 UE Context Modification Request\n"); + free_ue_context_mod_req(&req); + return -1; } - if(ieSrb != NULL) { - f1ap_ue_context_modification_req->srbs_to_be_setup_length = ieSrb->value.choice.SRBs_ToBeSetupMod_List.list.count; - f1ap_ue_context_modification_req->srbs_to_be_setup = calloc(f1ap_ue_context_modification_req->srbs_to_be_setup_length, - sizeof(f1ap_srb_to_be_setup_t)); - AssertFatal(f1ap_ue_context_modification_req->srbs_to_be_setup, - "could not allocate memory for f1ap_ue_context_setup_req->srbs_to_be_setup\n"); + ue_context_modification_request(&req); + free_ue_context_mod_req(&req); - for (i = 0; i < f1ap_ue_context_modification_req->srbs_to_be_setup_length; ++i) { - f1ap_srb_to_be_setup_t *srb_p = &f1ap_ue_context_modification_req->srbs_to_be_setup[i]; - F1AP_SRBs_ToBeSetupMod_Item_t *srbs_tobesetupmod_item_p; - srbs_tobesetupmod_item_p = &((F1AP_SRBs_ToBeSetupMod_ItemIEs_t *)ieSrb->value.choice.SRBs_ToBeSetupMod_List.list.array[i])->value.choice.SRBs_ToBeSetupMod_Item; - srb_p->srb_id = srbs_tobesetupmod_item_p->sRBID; - } - } - - /* DRB */ - F1AP_UEContextModificationRequestIEs_t *ieDrb; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequestIEs_t, ieDrb, container, - F1AP_ProtocolIE_ID_id_DRBs_ToBeSetupMod_List, false); - - if(ieDrb!=NULL) { - f1ap_ue_context_modification_req->drbs_to_be_setup_length = ieDrb->value.choice.DRBs_ToBeSetupMod_List.list.count; - f1ap_ue_context_modification_req->drbs_to_be_setup = calloc(f1ap_ue_context_modification_req->drbs_to_be_setup_length, - sizeof(f1ap_drb_to_be_setup_t)); - AssertFatal(f1ap_ue_context_modification_req->drbs_to_be_setup, - "could not allocate memory for f1ap_ue_context_setup_req->drbs_to_be_setup\n"); - - for (i = 0; i < f1ap_ue_context_modification_req->drbs_to_be_setup_length; ++i) { - f1ap_drb_to_be_setup_t *drb_p = &f1ap_ue_context_modification_req->drbs_to_be_setup[i]; - F1AP_DRBs_ToBeSetupMod_Item_t *drbs_tobesetupmod_item_p = - &((F1AP_DRBs_ToBeSetupMod_ItemIEs_t *)ieDrb->value.choice.DRBs_ToBeSetupMod_List.list.array[i])->value.choice.DRBs_ToBeSetupMod_Item; - drb_p->drb_id = drbs_tobesetupmod_item_p->dRBID; - /* TODO in the following, assume only one UP UL TNL is present. - * this matches/assumes OAI CU implementation, can be up to 2! */ - drb_p->up_ul_tnl_length = 1; - AssertFatal(drbs_tobesetupmod_item_p->uLUPTNLInformation_ToBeSetup_List.list.count > 0, - "no UL UP TNL Information in DRBs to be Setup list\n"); - F1AP_ULUPTNLInformation_ToBeSetup_Item_t *ul_up_tnl_info_p = (F1AP_ULUPTNLInformation_ToBeSetup_Item_t *)drbs_tobesetupmod_item_p->uLUPTNLInformation_ToBeSetup_List.list.array[0]; - F1AP_GTPTunnel_t *ul_up_tnl0 = ul_up_tnl_info_p->uLUPTNLInformation.choice.gTPTunnel; - BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&ul_up_tnl0->transportLayerAddress, drb_p->up_ul_tnl[0].tl_address); - OCTET_STRING_TO_UINT32(&ul_up_tnl0->gTP_TEID, drb_p->up_ul_tnl[0].teid); - // 3GPP assumes GTP-U is on port 2152, but OAI is configurable - drb_p->up_ul_tnl[0].port = getCxt(instance)->net_config.CUport; - - switch (drbs_tobesetupmod_item_p->rLCMode) { - case F1AP_RLCMode_rlc_am: - drb_p->rlc_mode = F1AP_RLC_MODE_AM; - break; - case F1AP_RLCMode_rlc_um_bidirectional: - drb_p->rlc_mode = F1AP_RLC_MODE_UM_BIDIR; - break; - default: - LOG_W(F1AP, "unsupported RLC Mode %ld received: setting UM bidir\n", drbs_tobesetupmod_item_p->rLCMode); - drb_p->rlc_mode = F1AP_RLC_MODE_UM_BIDIR; - break; - } - - if (drbs_tobesetupmod_item_p->qoSInformation.present == F1AP_QoSInformation_PR_eUTRANQoS) { - AssertFatal(false, "Decode of eUTRANQoS is not implemented yet"); - } // EUTRAN QoS Information - else { - /* 12.1.2 DRB_Information */ - if (drbs_tobesetupmod_item_p->qoSInformation.present == F1AP_QoSInformation_PR_choice_extension) { - F1AP_QoSInformation_ExtIEs_t *ie = - (F1AP_QoSInformation_ExtIEs_t *)drbs_tobesetupmod_item_p->qoSInformation.choice.choice_extension; - if (ie->id == F1AP_ProtocolIE_ID_id_DRB_Information && ie->criticality == F1AP_Criticality_reject - && ie->value.present == F1AP_QoSInformation_ExtIEs__value_PR_DRB_Information) { - - const F1AP_DRB_Information_t *dRB_Info = &ie->value.choice.DRB_Information; - f1ap_drb_information_t *drb_info = &drb_p->drb_info; - - /* QoS-Flow-Level-QoS-Parameters */ - /* QoS Characteristics*/ - f1ap_read_drb_qos_param(&dRB_Info->dRB_QoS, &drb_info->drb_qos); - - // 12.1.2.4 flows_Mapped_To_DRB_List - drb_info->flows_to_be_setup_length = dRB_Info->flows_Mapped_To_DRB_List.list.count; - drb_info->flows_mapped_to_drb = calloc(drb_info->flows_to_be_setup_length, sizeof(f1ap_flows_mapped_to_drb_t)); - AssertFatal(drb_info->flows_mapped_to_drb, "could not allocate memory for drb_p->drb_info.flows_mapped_to_drb\n"); - f1ap_read_flows_mapped(&dRB_Info->flows_Mapped_To_DRB_List, drb_info->flows_mapped_to_drb, drb_info->flows_to_be_setup_length); - - /* S-NSSAI */ - f1ap_read_drb_nssai(&dRB_Info->sNSSAI, &drb_p->nssai); - } - } - } - } - } - - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequestIEs_t, ieDrb, container, - F1AP_ProtocolIE_ID_id_DRBs_ToBeReleased_List, false); - if (ieDrb != NULL) { - f1ap_ue_context_modification_req->drbs_to_be_released_length = ieDrb->value.choice.DRBs_ToBeReleased_List.list.count; - f1ap_ue_context_modification_req->drbs_to_be_released = - calloc(f1ap_ue_context_modification_req->drbs_to_be_released_length, sizeof(f1ap_drb_to_be_released_t)); - AssertFatal(f1ap_ue_context_modification_req->drbs_to_be_released, - "could not allocate memory for f1ap_ue_context_released_req->drbs_to_be_released\n"); - for (i = 0; i < f1ap_ue_context_modification_req->drbs_to_be_released_length; ++i) { - F1AP_DRBs_ToBeReleased_ItemIEs_t *tbrel = (F1AP_DRBs_ToBeReleased_ItemIEs_t *)ieDrb->value.choice.DRBs_ToBeReleased_List.list.array[i]; - DevAssert(tbrel->id == F1AP_ProtocolIE_ID_id_DRBs_ToBeReleased_Item); - DevAssert(tbrel->value.present == F1AP_DRBs_ToBeReleased_ItemIEs__value_PR_DRBs_ToBeReleased_Item); - f1ap_ue_context_modification_req->drbs_to_be_released[i].rb_id = tbrel->value.choice.DRBs_ToBeReleased_Item.dRBID; - } - } - - /* RRC Reconfiguration Complete indicator */ - F1AP_UEContextModificationRequestIEs_t *ieReconf; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequestIEs_t, ieReconf, container, - F1AP_ProtocolIE_ID_id_RRCReconfigurationCompleteIndicator, false); - - if(ieReconf) { - switch(ieReconf->value.choice.RRCReconfigurationCompleteIndicator){ - case F1AP_RRCReconfigurationCompleteIndicator_true: - f1ap_ue_context_modification_req->ReconfigComplOutcome = RRCreconf_success; - break; - - case F1AP_RRCReconfigurationCompleteIndicator_failure: - f1ap_ue_context_modification_req->ReconfigComplOutcome = RRCreconf_failure; - break; - } - } - - /* RRCContainer */ - F1AP_UEContextModificationRequestIEs_t *ieRRC; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequestIEs_t, ieRRC, container, - F1AP_ProtocolIE_ID_id_RRCContainer, false); - - if (ieRRC) { - /* correct here */ - if ( ieRRC->value.choice.RRCContainer.size ) { - f1ap_ue_context_modification_req->rrc_container = malloc(ieRRC->value.choice.RRCContainer.size); - memcpy(f1ap_ue_context_modification_req->rrc_container, - ieRRC->value.choice.RRCContainer.buf, ieRRC->value.choice.RRCContainer.size); - f1ap_ue_context_modification_req->rrc_container_length = ieRRC->value.choice.RRCContainer.size; - } else { - LOG_E(F1AP, " RRCContainer in UEContextModificationRequestIEs size id 0\n"); - } - } else { - LOG_D(F1AP, "can't find RRCContainer in UEContextModificationRequestIEs by id %ld \n", F1AP_ProtocolIE_ID_id_RRCContainer); - } - - /* CU2DU Information */ - F1AP_UEContextModificationRequestIEs_t *ieCU2DU = NULL; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequestIEs_t, - ieCU2DU, - container, - F1AP_ProtocolIE_ID_id_CUtoDURRCInformation, - false); - if (ieCU2DU != NULL) { - f1ap_ue_context_modification_req->cu_to_du_rrc_information = - calloc(1, sizeof(*f1ap_ue_context_modification_req->cu_to_du_rrc_information)); - AssertFatal(f1ap_ue_context_modification_req->cu_to_du_rrc_information != NULL, "out of memory\n"); - cu_to_du_rrc_information_t *cu2du = f1ap_ue_context_modification_req->cu_to_du_rrc_information; - const F1AP_CUtoDURRCInformation_t *cu2duie = &ieCU2DU->value.choice.CUtoDURRCInformation; - if (cu2duie->cG_ConfigInfo != NULL) - LOG_W(F1AP, "UE RNTI %04x: ignoring cg_ConfigInfo, not implemented\n", f1ap_ue_context_modification_req->gNB_DU_ue_id); - if (cu2duie->measConfig != NULL) - LOG_W(F1AP, "UE RNTI %04x: ignoring measConfig, not implemented\n", f1ap_ue_context_modification_req->gNB_DU_ue_id); - if (cu2duie->uE_CapabilityRAT_ContainerList != NULL) { - F1AP_UE_CapabilityRAT_ContainerList_t *uecap = cu2duie->uE_CapabilityRAT_ContainerList; - cu2du->uE_CapabilityRAT_ContainerList = calloc(uecap->size, sizeof(*cu2du->uE_CapabilityRAT_ContainerList)); - AssertFatal(cu2du->uE_CapabilityRAT_ContainerList != NULL, "out of memory\n"); - cu2du->uE_CapabilityRAT_ContainerList_length = uecap->size; - memcpy(cu2du->uE_CapabilityRAT_ContainerList, uecap->buf, uecap->size); - } - } - - ue_context_modification_request(f1ap_ue_context_modification_req); return 0; } diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c index ed03ba76a5..5f2e9b9dfa 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -33,6 +33,7 @@ #include "openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h" #include "lib/f1ap_rrc_message_transfer.h" #include "lib/f1ap_interface_management.h" +#include "lib/f1ap_ue_context.h" #include "executables/softmodem-common.h" @@ -222,18 +223,18 @@ void gnb_du_configuration_update_acknowledge(const f1ap_gnb_du_configuration_upd LOG_I(MAC, "received gNB-DU configuration update acknowledge\n"); } -static NR_RLC_BearerConfig_t *get_bearerconfig_from_srb(const f1ap_srb_to_be_setup_t *srb, +static NR_RLC_BearerConfig_t *get_bearerconfig_from_srb(const f1ap_srb_to_setup_t *srb, const nr_rlc_configuration_t *rlc_config) { - long priority = srb->srb_id == 2 ? 3 : 1; // see 38.331 sec 9.2.1 + long priority = srb->id == 2 ? 3 : 1; // see 38.331 sec 9.2.1 e_NR_LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration bucket = NR_LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms5; - return get_SRB_RLC_BearerConfig(get_lcid_from_srbid(srb->srb_id), priority, bucket, rlc_config); + return get_SRB_RLC_BearerConfig(get_lcid_from_srbid(srb->id), priority, bucket, rlc_config); } static int handle_ue_context_srbs_setup(NR_UE_info_t *UE, int srbs_len, - const f1ap_srb_to_be_setup_t *req_srbs, + const f1ap_srb_to_setup_t *req_srbs, f1ap_srb_to_be_setup_t **resp_srbs, NR_CellGroupConfig_t *cellGroupConfig, const nr_rlc_configuration_t *rlc_config) @@ -243,15 +244,15 @@ static int handle_ue_context_srbs_setup(NR_UE_info_t *UE, *resp_srbs = calloc(srbs_len, sizeof(**resp_srbs)); AssertFatal(*resp_srbs != NULL, "out of memory\n"); for (int i = 0; i < srbs_len; i++) { - const f1ap_srb_to_be_setup_t *srb = &req_srbs[i]; + const f1ap_srb_to_setup_t *srb = &req_srbs[i]; NR_RLC_BearerConfig_t *rlc_BearerConfig = get_bearerconfig_from_srb(srb, rlc_config); - nr_rlc_add_srb(UE->rnti, srb->srb_id, rlc_BearerConfig); + nr_rlc_add_srb(UE->rnti, srb->id, rlc_BearerConfig); int priority = rlc_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->priority; nr_lc_config_t c = {.lcid = rlc_BearerConfig->logicalChannelIdentity, .priority = priority}; nr_mac_add_lcid(&UE->UE_sched_ctrl, &c); - (*resp_srbs)[i].srb_id = srb->srb_id; + (*resp_srbs)[i].srb_id = srb->id; (*resp_srbs)[i].lcid = c.lcid; if (rlc_BearerConfig->logicalChannelIdentity == 1) { @@ -268,12 +269,12 @@ static int handle_ue_context_srbs_setup(NR_UE_info_t *UE, return srbs_len; } -static NR_RLC_BearerConfig_t *get_bearerconfig_from_drb(const f1ap_drb_to_be_setup_t *drb, +static NR_RLC_BearerConfig_t *get_bearerconfig_from_drb(const f1ap_drb_to_setup_t *drb, const nr_rlc_configuration_t *rlc_config) { const NR_RLC_Config_PR rlc_conf = drb->rlc_mode == F1AP_RLC_MODE_AM ? NR_RLC_Config_PR_am : NR_RLC_Config_PR_um_Bi_Directional; long priority = 13; // hardcoded for the moment - return get_DRB_RLC_BearerConfig(get_lcid_from_drbid(drb->drb_id), drb->drb_id, rlc_conf, priority, rlc_config); + return get_DRB_RLC_BearerConfig(get_lcid_from_drbid(drb->id), drb->id, rlc_conf, priority, rlc_config); } static int get_non_dynamic_priority(int fiveqi) @@ -285,20 +286,20 @@ static int get_non_dynamic_priority(int fiveqi) return 0; } -static NR_QoS_config_t get_qos_config(const f1ap_qos_characteristics_t *qos_char) +static NR_QoS_config_t get_qos_config(const f1ap_qos_flow_param_t *qos) { NR_QoS_config_t qos_c = {0}; - switch (qos_char->qos_type) { + switch (qos->qos_type) { case DYNAMIC: - qos_c.priority = qos_char->dynamic.qos_priority_level; - qos_c.fiveQI = qos_char->dynamic.fiveqi > 0 ? qos_char->dynamic.fiveqi : 0; + qos_c.priority = qos->dyn.prio; + qos_c.fiveQI = 0; // does not exist for non-dynamic break; case NON_DYNAMIC: - qos_c.fiveQI = qos_char->non_dynamic.fiveqi; - qos_c.priority = get_non_dynamic_priority(qos_char->non_dynamic.fiveqi); + qos_c.fiveQI = qos->nondyn.fiveQI; + qos_c.priority = get_non_dynamic_priority(qos_c.fiveQI); break; default: - AssertFatal(false, "illegal QoS type %d\n", qos_char->qos_type); + AssertFatal(false, "illegal QoS type %d\n", qos->qos_type); break; } return qos_c; @@ -306,7 +307,7 @@ static NR_QoS_config_t get_qos_config(const f1ap_qos_characteristics_t *qos_char static int handle_ue_context_drbs_setup(NR_UE_info_t *UE, int drbs_len, - const f1ap_drb_to_be_setup_t *req_drbs, + const f1ap_drb_to_setup_t *req_drbs, f1ap_drb_to_be_setup_t **resp_drbs, NR_CellGroupConfig_t *cellGroupConfig, const nr_rlc_configuration_t *rlc_config) @@ -319,32 +320,34 @@ static int handle_ue_context_drbs_setup(NR_UE_info_t *UE, *resp_drbs = calloc(drbs_len, sizeof(**resp_drbs)); AssertFatal(*resp_drbs != NULL, "out of memory\n"); for (int i = 0; i < drbs_len; i++) { - const f1ap_drb_to_be_setup_t *drb = &req_drbs[i]; + const f1ap_drb_to_setup_t *drb = &req_drbs[i]; + AssertFatal(drb->qos_choice == F1AP_QOS_CHOICE_NR, "only NR QoS supported\n"); f1ap_drb_to_be_setup_t *resp_drb = &(*resp_drbs)[i]; NR_RLC_BearerConfig_t *rlc_BearerConfig = get_bearerconfig_from_drb(drb, rlc_config); - nr_rlc_add_drb(UE->rnti, drb->drb_id, rlc_BearerConfig); + nr_rlc_add_drb(UE->rnti, drb->id, rlc_BearerConfig); - nr_lc_config_t c = {.lcid = rlc_BearerConfig->logicalChannelIdentity, .nssai = drb->nssai}; + nr_lc_config_t c = {.lcid = rlc_BearerConfig->logicalChannelIdentity, .nssai = drb->nr.nssai}; int prio = 100; - for (int q = 0; q < drb->drb_info.flows_to_be_setup_length; ++q) { - c.qos_config[q] = get_qos_config(&drb->drb_info.flows_mapped_to_drb[q].qos_params.qos_characteristics); + for (int q = 0; q < drb->nr.flows_len; ++q) { + c.qos_config[q] = get_qos_config(&drb->nr.flows[q].param); prio = min(prio, c.qos_config[q].priority); } c.priority = prio; nr_mac_add_lcid(&UE->UE_sched_ctrl, &c); - *resp_drb = *drb; + resp_drb->drb_id = drb->id; + // TODO lcid // just put same number of tunnels in DL as in UL - DevAssert(drb->up_ul_tnl_length == 1); - resp_drb->up_dl_tnl_length = drb->up_ul_tnl_length; + DevAssert(drb->up_ul_tnl_len == 1); + resp_drb->up_dl_tnl_length = drb->up_ul_tnl_len; if (f1inst >= 0) { // we actually use F1-U int qfi = -1; // don't put PDU session marker in GTP gtpv1u_gnb_create_tunnel_resp_t resp_f1 = {0}; int ret = drb_gtpu_create(f1inst, UE->rnti, - drb->drb_id, - drb->drb_id, + drb->id, + drb->id, qfi, drb->up_ul_tnl[0].tl_address, drb->up_ul_tnl[0].teid, @@ -366,7 +369,7 @@ static int handle_ue_context_drbs_setup(NR_UE_info_t *UE, static int handle_ue_context_drbs_release(NR_UE_info_t *UE, int drbs_len, - const f1ap_drb_to_be_released_t *req_drbs, + const f1ap_drb_to_release_t *req_drbs, NR_CellGroupConfig_t *cellGroupConfig) { DevAssert(req_drbs != NULL && cellGroupConfig != NULL); @@ -378,9 +381,9 @@ static int handle_ue_context_drbs_release(NR_UE_info_t *UE, /* Note: the actual GTP tunnels are already removed in the F1AP message * decoding */ for (int i = 0; i < drbs_len; i++) { - const f1ap_drb_to_be_released_t *drb = &req_drbs[i]; + const f1ap_drb_to_release_t *drb = &req_drbs[i]; - long lcid = get_lcid_from_drbid(drb->rb_id); + long lcid = get_lcid_from_drbid(drb->id); int idx = 0; while (idx < cellGroupConfig->rlc_BearerToAddModList->list.count) { const NR_RLC_BearerConfig_t *bc = cellGroupConfig->rlc_BearerToAddModList->list.array[idx]; @@ -392,7 +395,7 @@ static int handle_ue_context_drbs_release(NR_UE_info_t *UE, nr_mac_remove_lcid(&UE->UE_sched_ctrl, lcid); nr_rlc_release_entity(UE->rnti, lcid); if (f1inst >= 0) - newGtpuDeleteOneTunnel(f1inst, UE->rnti, drb->rb_id); + newGtpuDeleteOneTunnel(f1inst, UE->rnti, drb->id); asn_sequence_del(&cellGroupConfig->rlc_BearerToAddModList->list, idx, 1); long *plcid = malloc(sizeof(*plcid)); AssertFatal(plcid, "out of memory\n"); @@ -600,34 +603,30 @@ static NR_UE_info_t *create_new_UE(gNB_MAC_INST *mac, uint32_t cu_id, const NR_C return UE; } -void ue_context_setup_request(const f1ap_ue_context_setup_t *req) +void ue_context_setup_request(const f1ap_ue_context_setup_req_t *req) { const bool is_SA = IS_SA_MODE(get_softmodem_params()); gNB_MAC_INST *mac = RC.nrmac[0]; - /* response has same type as request... */ + + /* TODO: update response */ f1ap_ue_context_setup_t resp = { .gNB_CU_ue_id = req->gNB_CU_ue_id, - .gNB_DU_ue_id = req->gNB_DU_ue_id, }; - /* gNB-DU UE ID is optional. As of now, the F1AP module fills -1 (on uint, so - * 0xffffffff), but the DU uses the RNTI, so check if it's a legal RNTI in - * which case we consider; if not, assume no DU UE ID given */ - bool ue_id_provided = resp.gNB_DU_ue_id > 0 && resp.gNB_DU_ue_id < 0xffff; + bool ue_id_provided = req->gNB_DU_ue_id != NULL; - NR_UE_NR_Capability_t *ue_cap = NULL; + const f1ap_cu_to_du_rrc_info_t *cu2du = &req->cu_to_du_rrc_info; NR_CG_ConfigInfo_t *cg_configinfo = NULL; - if (req->cu_to_du_rrc_information != NULL) { - const cu_to_du_rrc_information_t *cu2du = req->cu_to_du_rrc_information; - if (cu2du->cG_ConfigInfo != NULL) - cg_configinfo = get_cg_config_info(cu2du->cG_ConfigInfo, cu2du->cG_ConfigInfo_length); - if (cu2du->handoverPreparationInfo != NULL) { - ue_cap = get_ue_nr_cap_from_ho_prep_info(cu2du->handoverPreparationInfo, cu2du->handoverPreparationInfo_length); - } else if (cu2du->uE_CapabilityRAT_ContainerList != NULL) { - ue_cap = get_ue_nr_cap(req->gNB_DU_ue_id, cu2du->uE_CapabilityRAT_ContainerList, cu2du->uE_CapabilityRAT_ContainerList_length); - } - AssertFatal(cu2du->measConfig == NULL, "MeasConfig not handled\n"); + if (cu2du->cg_configinfo != NULL) + cg_configinfo = get_cg_config_info(cu2du->cg_configinfo->buf, cu2du->cg_configinfo->len); + NR_UE_NR_Capability_t *ue_cap = NULL; + if (cu2du->ho_prep_info != NULL) { + ue_cap = get_ue_nr_cap_from_ho_prep_info(cu2du->ho_prep_info->buf, cu2du->ho_prep_info->len); + } else if (cu2du->ue_cap != NULL) { + ue_cap = get_ue_nr_cap(*req->gNB_DU_ue_id, cu2du->ue_cap->buf, cu2du->ue_cap->len); } + AssertFatal(cu2du->meas_config == NULL, "MeasConfig not handled\n"); + /* 38.473: "For DC operation, the CG-ConfigInfo IE shall be included in the CU * to DU RRC Information IE at the gNB acting as secondary node" As of now, * we only handle NSA => we check we have CG-ConfigInfo if not SA or have SA @@ -643,25 +642,26 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req) resp.crnti = &UE->rnti; } else { DevAssert(is_SA); - UE = find_nr_UE(&mac->UE_info, req->gNB_DU_ue_id); + UE = find_nr_UE(&mac->UE_info, *req->gNB_DU_ue_id); } AssertFatal(UE, "no UE found or could not be created, but UE Context Setup Failed not implemented\n"); + resp.gNB_DU_ue_id = UE->rnti; NR_CellGroupConfig_t *new_CellGroup = clone_CellGroupConfig(UE->CellGroup); - if (req->srbs_to_be_setup_length > 0) { + if (req->srbs_len > 0) { resp.srbs_to_be_setup_length = handle_ue_context_srbs_setup(UE, - req->srbs_to_be_setup_length, - req->srbs_to_be_setup, + req->srbs_len, + req->srbs, &resp.srbs_to_be_setup, new_CellGroup, &mac->rlc_config); } - if (req->drbs_to_be_setup_length > 0) { + if (req->drbs_len > 0) { resp.drbs_to_be_setup_length = handle_ue_context_drbs_setup(UE, - req->drbs_to_be_setup_length, - req->drbs_to_be_setup, + req->drbs_len, + req->drbs, &resp.drbs_to_be_setup, new_CellGroup, &mac->rlc_config); @@ -669,7 +669,7 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req) if (req->rrc_container != NULL) { logical_chan_id_t id = 1; - nr_rlc_srb_recv_sdu(req->gNB_DU_ue_id, id, req->rrc_container, req->rrc_container_length); + nr_rlc_srb_recv_sdu(UE->rnti, id, req->rrc_container->buf, req->rrc_container->len); } NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon; @@ -722,7 +722,7 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req) free(resp.du_to_cu_rrc_information); } -void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req) +void ue_context_modification_request(const f1ap_ue_context_mod_req_t *req) { gNB_MAC_INST *mac = RC.nrmac[0]; f1ap_ue_context_modif_resp_t resp = { @@ -731,12 +731,13 @@ void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req) }; NR_UE_NR_Capability_t *ue_cap = NULL; - if (req->cu_to_du_rrc_information != NULL) { - AssertFatal(req->cu_to_du_rrc_information->cG_ConfigInfo == NULL, "CG-ConfigInfo not handled\n"); - ue_cap = get_ue_nr_cap(req->gNB_DU_ue_id, - req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList, - req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList_length); - AssertFatal(req->cu_to_du_rrc_information->measConfig == NULL, "MeasConfig not handled\n"); + if (req->cu_to_du_rrc_info != NULL) { + AssertFatal(req->cu_to_du_rrc_info->cg_configinfo == NULL, "CG-ConfigInfo not handled\n"); + if (req->cu_to_du_rrc_info->ue_cap) { + byte_array_t *b = req->cu_to_du_rrc_info->ue_cap; + ue_cap = get_ue_nr_cap(req->gNB_DU_ue_id, b->buf, b->len); + } + AssertFatal(req->cu_to_du_rrc_info->meas_config == NULL, "MeasConfig not handled\n"); } NR_SCHED_LOCK(&mac->sched_lock); @@ -749,39 +750,38 @@ void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req) NR_CellGroupConfig_t *new_CellGroup = clone_CellGroupConfig(UE->CellGroup); - if (req->srbs_to_be_setup_length > 0) { + if (req->srbs_len > 0) { resp.srbs_to_be_setup_length = handle_ue_context_srbs_setup(UE, - req->srbs_to_be_setup_length, - req->srbs_to_be_setup, + req->srbs_len, + req->srbs, &resp.srbs_to_be_setup, new_CellGroup, &mac->rlc_config); } - if (req->drbs_to_be_setup_length > 0) { + if (req->drbs_len > 0) { resp.drbs_to_be_setup_length = handle_ue_context_drbs_setup(UE, - req->drbs_to_be_setup_length, - req->drbs_to_be_setup, + req->drbs_len, + req->drbs, &resp.drbs_to_be_setup, new_CellGroup, &mac->rlc_config); } - if (req->drbs_to_be_released_length > 0) { - resp.drbs_to_be_released_length = - handle_ue_context_drbs_release(UE, req->drbs_to_be_released_length, req->drbs_to_be_released, new_CellGroup); + if (req->drbs_rel_len > 0) { + resp.drbs_to_be_released_length = handle_ue_context_drbs_release(UE, req->drbs_rel_len, req->drbs_rel, new_CellGroup); } if (req->rrc_container != NULL) { logical_chan_id_t id = 1; - nr_rlc_srb_recv_sdu(req->gNB_DU_ue_id, id, req->rrc_container, req->rrc_container_length); + nr_rlc_srb_recv_sdu(req->gNB_DU_ue_id, id, req->rrc_container->buf, req->rrc_container->len); } NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon; - if (req->ReconfigComplOutcome != RRCreconf_info_not_present && req->ReconfigComplOutcome != RRCreconf_success) { + if (req->reconfig_compl && *req->reconfig_compl != RRCreconf_success) { LOG_E(NR_MAC, "RRC reconfiguration outcome unsuccessful, but no rollback mechanism implemented to come back to old configuration\n"); - } else if (req->ReconfigComplOutcome == RRCreconf_success) { + } else if (req->reconfig_compl) { LOG_I(NR_MAC, "DU received confirmation of successful RRC Reconfiguration\n"); if (UE->reconfigSpCellConfig) { // in case of reestablishment, the spCellConfig had to be released @@ -807,8 +807,7 @@ void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req) update_cellGroupConfig(new_CellGroup, UE->uid, UE->capability, &mac->radio_config, scc); } - if (req->srbs_to_be_setup_length > 0 || req->drbs_to_be_setup_length > 0 || req->drbs_to_be_released_length > 0 - || ue_cap != NULL) { + if (req->srbs_len > 0 || req->drbs_len > 0 || req->drbs_rel_len > 0 || ue_cap != NULL) { resp.du_to_cu_rrc_information = calloc(1, sizeof(du_to_cu_rrc_information_t)); AssertFatal(resp.du_to_cu_rrc_information != NULL, "out of memory\n"); resp.du_to_cu_rrc_information->cellGroupConfig = calloc(1, 1024); diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h index e9aceb1192..b3ecdad270 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h @@ -32,8 +32,8 @@ void f1_setup_response(const f1ap_setup_resp_t *resp); void f1_setup_failure(const f1ap_setup_failure_t *failure); void gnb_du_configuration_update_acknowledge(const f1ap_gnb_du_configuration_update_acknowledge_t *ack); NR_CellGroupConfig_t *clone_CellGroupConfig(const NR_CellGroupConfig_t *orig); -void ue_context_setup_request(const f1ap_ue_context_setup_t *req); -void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req); +void ue_context_setup_request(const f1ap_ue_context_setup_req_t *req); +void ue_context_modification_request(const f1ap_ue_context_mod_req_t *req); void ue_context_modification_confirm(const f1ap_ue_context_modif_confirm_t *confirm); void ue_context_modification_refuse(const f1ap_ue_context_modif_refuse_t *refuse); void ue_context_release_command(const f1ap_ue_context_release_cmd_t *cmd); diff --git a/openair2/RRC/NR/mac_rrc_dl.h b/openair2/RRC/NR/mac_rrc_dl.h index d6937591b5..f93bc1b7fe 100644 --- a/openair2/RRC/NR/mac_rrc_dl.h +++ b/openair2/RRC/NR/mac_rrc_dl.h @@ -33,8 +33,8 @@ typedef void (*f1_setup_failure_func_t)(sctp_assoc_t assoc_id, const f1ap_setup_ typedef void (*gnb_du_configuration_update_ack_func_t)(sctp_assoc_t assoc_id, const f1ap_gnb_du_configuration_update_acknowledge_t *ack); -typedef void (*ue_context_setup_request_func_t)(sctp_assoc_t assoc_id, const f1ap_ue_context_setup_t *req); -typedef void (*ue_context_modification_request_func_t)(sctp_assoc_t assoc_id, const f1ap_ue_context_modif_req_t *req); +typedef void (*ue_context_setup_request_func_t)(sctp_assoc_t assoc_id, const f1ap_ue_context_setup_req_t *req); +typedef void (*ue_context_modification_request_func_t)(sctp_assoc_t assoc_id, const f1ap_ue_context_mod_req_t *req); typedef void (*ue_context_modification_confirm_func_t)(sctp_assoc_t assoc_id, const f1ap_ue_context_modif_confirm_t *confirm); typedef void (*ue_context_modification_refuse_func_t)(sctp_assoc_t assoc_id, const f1ap_ue_context_modif_refuse_t *refuse); typedef void (*ue_context_release_command_func_t)(sctp_assoc_t assoc_id, const f1ap_ue_context_release_cmd_t *cmd); diff --git a/openair2/RRC/NR/mac_rrc_dl_direct.c b/openair2/RRC/NR/mac_rrc_dl_direct.c index 4f8d45ac8c..29592d4e43 100644 --- a/openair2/RRC/NR/mac_rrc_dl_direct.c +++ b/openair2/RRC/NR/mac_rrc_dl_direct.c @@ -58,13 +58,13 @@ static void gnb_du_configuration_update_ack_direct(sctp_assoc_t assoc_id, const gnb_du_configuration_update_acknowledge(ack); } -static void ue_context_setup_request_direct(sctp_assoc_t assoc_id, const f1ap_ue_context_setup_t *req) +static void ue_context_setup_request_direct(sctp_assoc_t assoc_id, const f1ap_ue_context_setup_req_t *req) { AssertFatal(assoc_id == -1, "illegal assoc_id %d\n", assoc_id); ue_context_setup_request(req); } -static void ue_context_modification_request_direct(sctp_assoc_t assoc_id, const f1ap_ue_context_modif_req_t *req) +static void ue_context_modification_request_direct(sctp_assoc_t assoc_id, const f1ap_ue_context_mod_req_t *req) { AssertFatal(assoc_id == -1, "illegal assoc_id %d\n", assoc_id); ue_context_modification_request(req); diff --git a/openair2/RRC/NR/mac_rrc_dl_f1ap.c b/openair2/RRC/NR/mac_rrc_dl_f1ap.c index 30c4f910ee..47d1bc1d7e 100644 --- a/openair2/RRC/NR/mac_rrc_dl_f1ap.c +++ b/openair2/RRC/NR/mac_rrc_dl_f1ap.c @@ -32,6 +32,7 @@ #include "nr_rrc_defs.h" #include "lib/f1ap_rrc_message_transfer.h" #include "lib/f1ap_interface_management.h" +#include "lib/f1ap_ue_context.h" static void f1_reset_cu_initiated_f1ap(sctp_assoc_t assoc_id, const f1ap_reset_t *reset) { @@ -75,116 +76,19 @@ static void gnb_du_configuration_update_ack_f1ap(sctp_assoc_t assoc_id, const f1 itti_send_msg_to_task(TASK_CU_F1, 0, msg); } -static void ue_context_setup_request_f1ap(sctp_assoc_t assoc_id, const f1ap_ue_context_setup_t *req) +static void ue_context_setup_request_f1ap(sctp_assoc_t assoc_id, const f1ap_ue_context_setup_req_t *req) { MessageDef *msg = itti_alloc_new_message(TASK_RRC_GNB, 0, F1AP_UE_CONTEXT_SETUP_REQ); msg->ittiMsgHeader.originInstance = assoc_id; - f1ap_ue_context_setup_t *f1ap_msg = &F1AP_UE_CONTEXT_SETUP_REQ(msg); - *f1ap_msg = *req; - if (req->cu_to_du_rrc_information != NULL) { - f1ap_msg->cu_to_du_rrc_information = calloc(1, sizeof(*f1ap_msg->cu_to_du_rrc_information)); - AssertFatal(f1ap_msg->cu_to_du_rrc_information != NULL, "out of memory\n"); - const cu_to_du_rrc_information_t *du2cu_req = req->cu_to_du_rrc_information; - if (req->cu_to_du_rrc_information->cG_ConfigInfo != NULL) { - cu_to_du_rrc_information_t* du2cu_new = f1ap_msg->cu_to_du_rrc_information; - du2cu_new->cG_ConfigInfo_length = du2cu_req->cG_ConfigInfo_length; - du2cu_new->cG_ConfigInfo = malloc_or_fail(du2cu_new->cG_ConfigInfo_length); - memcpy(du2cu_new->cG_ConfigInfo, du2cu_req->cG_ConfigInfo, du2cu_new->cG_ConfigInfo_length); - } - AssertFatal(req->cu_to_du_rrc_information->measConfig == NULL && req->cu_to_du_rrc_information->measConfig_length == 0, "cg_ConfigInfo not implemented\n"); - if (req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList != NULL) { - cu_to_du_rrc_information_t* du2cu_new = f1ap_msg->cu_to_du_rrc_information; - DevAssert(du2cu_req->uE_CapabilityRAT_ContainerList_length > 0); - du2cu_new->uE_CapabilityRAT_ContainerList_length = du2cu_req->uE_CapabilityRAT_ContainerList_length; - du2cu_new->uE_CapabilityRAT_ContainerList = malloc(du2cu_new->uE_CapabilityRAT_ContainerList_length); - AssertFatal(du2cu_new->uE_CapabilityRAT_ContainerList != NULL, "out of memory\n"); - memcpy(du2cu_new->uE_CapabilityRAT_ContainerList, du2cu_req->uE_CapabilityRAT_ContainerList, du2cu_new->uE_CapabilityRAT_ContainerList_length); - } - if (req->cu_to_du_rrc_information->handoverPreparationInfo != NULL) { - cu_to_du_rrc_information_t *du2cu_new = f1ap_msg->cu_to_du_rrc_information; - DevAssert(du2cu_req->handoverPreparationInfo_length > 0); - du2cu_new->handoverPreparationInfo_length = du2cu_req->handoverPreparationInfo_length; - du2cu_new->handoverPreparationInfo = malloc_or_fail(du2cu_new->handoverPreparationInfo_length); - memcpy(du2cu_new->handoverPreparationInfo, du2cu_req->handoverPreparationInfo, du2cu_new->handoverPreparationInfo_length); - } - } - if (req->drbs_to_be_setup_length > 0) { - int n = req->drbs_to_be_setup_length; - f1ap_msg->drbs_to_be_setup_length = n; - f1ap_msg->drbs_to_be_setup = calloc(n, sizeof(*f1ap_msg->drbs_to_be_setup)); - AssertFatal(f1ap_msg->drbs_to_be_setup != NULL, "out of memory\n"); - memcpy(f1ap_msg->drbs_to_be_setup, req->drbs_to_be_setup, n * sizeof(*f1ap_msg->drbs_to_be_setup)); - } - if (req->srbs_to_be_setup_length > 0) { - int n = req->srbs_to_be_setup_length; - f1ap_msg->srbs_to_be_setup_length = n; - f1ap_msg->srbs_to_be_setup = calloc(n, sizeof(*f1ap_msg->srbs_to_be_setup)); - AssertFatal(f1ap_msg->srbs_to_be_setup != NULL, "out of memory\n"); - memcpy(f1ap_msg->srbs_to_be_setup, req->srbs_to_be_setup, n * sizeof(*f1ap_msg->srbs_to_be_setup)); - } - if (req->rrc_container_length > 0) { - f1ap_msg->rrc_container = calloc(req->rrc_container_length, sizeof(*f1ap_msg->rrc_container)); - AssertFatal(f1ap_msg->rrc_container != NULL, "out of memory\n"); - f1ap_msg->rrc_container_length = req->rrc_container_length; - memcpy(f1ap_msg->rrc_container, req->rrc_container, req->rrc_container_length); - } + F1AP_UE_CONTEXT_SETUP_REQ(msg) = cp_ue_context_setup_req(req); itti_send_msg_to_task(TASK_CU_F1, 0, msg); } -static void ue_context_modification_request_f1ap(sctp_assoc_t assoc_id, const f1ap_ue_context_modif_req_t *req) +static void ue_context_modification_request_f1ap(sctp_assoc_t assoc_id, const f1ap_ue_context_mod_req_t *req) { MessageDef *msg = itti_alloc_new_message(TASK_RRC_GNB, 0, F1AP_UE_CONTEXT_MODIFICATION_REQ); msg->ittiMsgHeader.originInstance = assoc_id; - f1ap_ue_context_modif_req_t *f1ap_msg = &F1AP_UE_CONTEXT_MODIFICATION_REQ(msg); - *f1ap_msg = *req; - if (req->cu_to_du_rrc_information != NULL) { - f1ap_msg->cu_to_du_rrc_information = calloc(1, sizeof(*f1ap_msg->cu_to_du_rrc_information)); - AssertFatal(f1ap_msg->cu_to_du_rrc_information != NULL, "out of memory\n"); - AssertFatal(req->cu_to_du_rrc_information->cG_ConfigInfo == NULL && req->cu_to_du_rrc_information->cG_ConfigInfo_length == 0, "cg_ConfigInfo not implemented\n"); - AssertFatal(req->cu_to_du_rrc_information->measConfig == NULL && req->cu_to_du_rrc_information->measConfig_length == 0, "cg_ConfigInfo not implemented\n"); - if (req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList != NULL) { - const cu_to_du_rrc_information_t *du2cu_req = req->cu_to_du_rrc_information; - cu_to_du_rrc_information_t* du2cu_new = f1ap_msg->cu_to_du_rrc_information; - DevAssert(du2cu_req->uE_CapabilityRAT_ContainerList_length > 0); - du2cu_new->uE_CapabilityRAT_ContainerList_length = du2cu_req->uE_CapabilityRAT_ContainerList_length; - du2cu_new->uE_CapabilityRAT_ContainerList = malloc(du2cu_new->uE_CapabilityRAT_ContainerList_length); - AssertFatal(du2cu_new->uE_CapabilityRAT_ContainerList != NULL, "out of memory\n"); - memcpy(du2cu_new->uE_CapabilityRAT_ContainerList, du2cu_req->uE_CapabilityRAT_ContainerList, du2cu_new->uE_CapabilityRAT_ContainerList_length); - } - } - AssertFatal(req->drbs_to_be_modified_length == 0, "drbs_to_be_modified not supported yet\n"); - if (req->drbs_to_be_setup_length > 0) { - int n = req->drbs_to_be_setup_length; - f1ap_msg->drbs_to_be_setup_length = n; - f1ap_msg->drbs_to_be_setup = calloc(n, sizeof(*f1ap_msg->drbs_to_be_setup)); - AssertFatal(f1ap_msg->drbs_to_be_setup != NULL, "out of memory\n"); - memcpy(f1ap_msg->drbs_to_be_setup, req->drbs_to_be_setup, n * sizeof(*f1ap_msg->drbs_to_be_setup)); - } - if (req->srbs_to_be_setup_length > 0) { - int n = req->srbs_to_be_setup_length; - f1ap_msg->srbs_to_be_setup_length = n; - f1ap_msg->srbs_to_be_setup = calloc(n, sizeof(*f1ap_msg->srbs_to_be_setup)); - AssertFatal(f1ap_msg->srbs_to_be_setup != NULL, "out of memory\n"); - memcpy(f1ap_msg->srbs_to_be_setup, req->srbs_to_be_setup, n * sizeof(*f1ap_msg->srbs_to_be_setup)); - } - if (req->drbs_to_be_released_length > 0) { - int n = req->drbs_to_be_released_length; - f1ap_msg->drbs_to_be_released_length = n; - f1ap_msg->drbs_to_be_released = calloc(n, sizeof(*f1ap_msg->drbs_to_be_released)); - AssertFatal(f1ap_msg->drbs_to_be_released != NULL, "out of memory\n"); - memcpy(f1ap_msg->drbs_to_be_released, req->drbs_to_be_released, n * sizeof(*f1ap_msg->drbs_to_be_released)); - } - if (req->rrc_container_length > 0) { - f1ap_msg->rrc_container = calloc(req->rrc_container_length, sizeof(*f1ap_msg->rrc_container)); - AssertFatal(f1ap_msg->rrc_container != NULL, "out of memory\n"); - f1ap_msg->rrc_container_length = req->rrc_container_length; - memcpy(f1ap_msg->rrc_container, req->rrc_container, req->rrc_container_length); - } - if (req->transm_action_ind != NULL) { - f1ap_msg->transm_action_ind = malloc(sizeof *f1ap_msg->transm_action_ind); - AssertFatal(f1ap_msg->transm_action_ind != NULL, "out of memory\n"); - *f1ap_msg->transm_action_ind = *req->transm_action_ind; - } + F1AP_UE_CONTEXT_MODIFICATION_REQ(msg) = cp_ue_context_mod_req(req); itti_send_msg_to_task(TASK_CU_F1, 0, msg); } diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h index 3a4fed6411..3ac774c69f 100644 --- a/openair2/RRC/NR/nr_rrc_proto.h +++ b/openair2/RRC/NR/nr_rrc_proto.h @@ -107,14 +107,14 @@ int rrc_gNB_generate_pcch_msg(sctp_assoc_t assoc_id, const NR_SIB1_t *sib, uint3 void rrc_gNB_generate_UeContextSetupRequest(const gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *const ue_context_pP, int n_drbs, - const f1ap_drb_to_be_setup_t *drbs); + const f1ap_drb_to_setup_t *drbs); void rrc_gNB_generate_UeContextModificationRequest(const gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *const ue_context_pP, int n_drbs, - const f1ap_drb_to_be_setup_t *drbs, + const f1ap_drb_to_setup_t *drbs, int n_rel_drbs, - const f1ap_drb_to_be_released_t *rel_drbs); + const f1ap_drb_to_release_t *rel_drbs); void free_RRCReconfiguration_params(nr_rrc_reconfig_param_t params); @@ -123,6 +123,6 @@ byte_array_t rrc_gNB_encode_RRCReconfiguration(gNB_RRC_INST *rrc, gNB_RRC_UE_t * nr_rrc_reconfig_param_t get_RRCReconfiguration_params(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, uint8_t srb_reest_bitmap, bool drb_reestablish); pdusession_level_qos_parameter_t *get_qos_characteristics(const int qfi, rrc_pdu_session_param_t *pduSession); -f1ap_qos_characteristics_t get_qos_char_from_qos_flow_param(const pdusession_level_qos_parameter_t *qos_param); +f1ap_qos_flow_param_t get_qos_char_from_qos_flow_param(const pdusession_level_qos_parameter_t *qos_param); void openair_rrc_gNB_configuration(gNB_RRC_INST *rrc, gNB_RrcConfigurationReq *configuration); #endif diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index e08a0a4d9e..6e53de1c10 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -80,6 +80,7 @@ #include "openair2/F1AP/f1ap_ids.h" #include "openair2/F1AP/lib/f1ap_rrc_message_transfer.h" #include "openair2/F1AP/lib/f1ap_interface_management.h" +#include "openair2/F1AP/lib/f1ap_ue_context.h" #include "rrc_gNB_NGAP.h" #include "rrc_gNB_du.h" #include "rrc_gNB_mobility.h" @@ -1774,12 +1775,14 @@ static void handle_rrcReconfigurationComplete(gNB_RRC_INST *rrc, gNB_RRC_UE_t *U f1_ue_data_t ue_data = cu_get_f1_ue_data(UE->rrc_ue_id); RETURN_IF_INVALID_ASSOC_ID(ue_data.du_assoc_id); - f1ap_ue_context_modif_req_t ue_context_modif_req = { + ReconfigurationCompl_t rc = RRCreconf_success; + f1ap_ue_context_mod_req_t req = { .gNB_CU_ue_id = UE->rrc_ue_id, .gNB_DU_ue_id = ue_data.secondary_ue, - .ReconfigComplOutcome = RRCreconf_success, + .reconfig_compl = &rc, }; - rrc->mac_rrc.ue_context_modification_request(ue_data.du_assoc_id, &ue_context_modif_req); + rrc->mac_rrc.ue_context_modification_request(ue_data.du_assoc_id, &req); + /* nothing to be freed */ } static void rrc_gNB_generate_UECapabilityEnquiry(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue) @@ -2364,18 +2367,26 @@ pdusession_level_qos_parameter_t *get_qos_characteristics(const int qfi, rrc_pdu } /* \bref return F1AP QoS characteristics based on Qos flow parameters */ -f1ap_qos_characteristics_t get_qos_char_from_qos_flow_param(const pdusession_level_qos_parameter_t *qos_param) +f1ap_qos_flow_param_t get_qos_char_from_qos_flow_param(const pdusession_level_qos_parameter_t *qos_param) { - f1ap_qos_characteristics_t qos_char = {0}; + f1ap_qos_flow_param_t qos_char = {0}; if (qos_param->fiveQI_type == DYNAMIC) { qos_char.qos_type = DYNAMIC; - qos_char.dynamic.fiveqi = qos_param->fiveQI; - qos_char.dynamic.qos_priority_level = qos_param->qos_priority; + qos_char.dyn.prio = qos_param->qos_priority; + qos_char.dyn.pdb = 100; // TODO + qos_char.dyn.per.scalar = 10; // TODO + qos_char.dyn.per.exponent = 100; // TODO } else { qos_char.qos_type = NON_DYNAMIC; - qos_char.non_dynamic.fiveqi = qos_param->fiveQI; - qos_char.non_dynamic.qos_priority_level = qos_param->qos_priority; + qos_char.nondyn.fiveQI = qos_param->fiveQI; } + const ngap_allocation_retention_priority_t *a = &qos_param->allocation_retention_priority; + qos_char.arp.prio = a->priority_level; + qos_char.arp.preempt_cap = a->pre_emp_capability == NGAP_PRE_EMPTION_CAPABILITY_MAY_TRIGGER_PREEMPTION + ? MAY_TRIGGER_PREEMPTION + : SHALL_NOT_TRIGGER_PREEMPTION; + qos_char.arp.preempt_vuln = + a->pre_emp_vulnerability == NGAP_PRE_EMPTION_VULNERABILITY_PREEMPTABLE ? PREEMPTABLE : NOT_PREEMPTABLE; return qos_char; } @@ -2385,38 +2396,52 @@ static int fill_drb_to_be_setup_from_e1_resp(const gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const pdu_session_setup_t *pduSession, int numPduSession, - f1ap_drb_to_be_setup_t drbs[32]) + f1ap_drb_to_setup_t drbs[32]) { int nb_drb = 0; for (int p = 0; p < numPduSession; ++p) { - rrc_pdu_session_param_t *RRC_pduSession = find_pduSession(UE, pduSession[p].id, false); - DevAssert(RRC_pduSession); + rrc_pdu_session_param_t *pdu = find_pduSession(UE, pduSession[p].id, false); + DevAssert(pdu); for (int i = 0; i < pduSession[p].numDRBSetup; i++) { const DRB_nGRAN_setup_t *drb_config = &pduSession[p].DRBnGRanList[i]; - f1ap_drb_to_be_setup_t *drb = &drbs[nb_drb]; - drb->drb_id = pduSession[p].DRBnGRanList[i].id; - drb->rlc_mode = rrc->configuration.um_on_default_drb ? F1AP_RLC_MODE_UM_BIDIR : F1AP_RLC_MODE_AM; - drb->up_ul_tnl[0].tl_address = drb_config->UpParamList[0].tl_info.tlAddress; - drb->up_ul_tnl[0].port = rrc->eth_params_s.my_portd; - drb->up_ul_tnl[0].teid = drb_config->UpParamList[0].tl_info.teId; - drb->up_ul_tnl_length = 1; + drb_t *rrc_drb = get_drb(UE, pduSession[p].DRBnGRanList[i].id); + DevAssert(rrc_drb); + + f1ap_drb_to_setup_t *drb = &drbs[nb_drb]; + drb->id = rrc_drb->drb_id; + + drb->qos_choice = F1AP_QOS_CHOICE_NR; /* pass QoS info to MAC */ int nb_qos_flows = drb_config->numQosFlowSetup; AssertFatal(nb_qos_flows > 0, "must map at least one flow to a DRB\n"); - drb->drb_info.flows_to_be_setup_length = nb_qos_flows; - drb->drb_info.flows_mapped_to_drb = calloc(nb_qos_flows, sizeof(f1ap_flows_mapped_to_drb_t)); - AssertFatal(drb->drb_info.flows_mapped_to_drb, "could not allocate memory\n"); + drb->nr.flows_len = nb_qos_flows; + drb->nr.flows = calloc_or_fail(nb_qos_flows, sizeof(*drb->nr.flows)); for (int j = 0; j < nb_qos_flows; j++) { - drb->drb_info.flows_mapped_to_drb[j].qfi = drb_config->qosFlows[j].qfi; - pdusession_level_qos_parameter_t *in_qos_char = get_qos_characteristics(drb_config->qosFlows[j].qfi, RRC_pduSession); - drb->drb_info.flows_mapped_to_drb[j].qos_params.qos_characteristics = get_qos_char_from_qos_flow_param(in_qos_char); + int qfi = drb_config->qosFlows[j].qfi; + /* find the QoS characteristics stored at RRC based on QFI returned + * from E1. We expect this to correspond to a QFI we passed to E1 + * previously, so we expect it to exist. */ + pdusession_level_qos_parameter_t *qos_param = get_qos_characteristics(qfi, pdu); + DevAssert(qos_param); + f1ap_drb_flows_mapped_t *flow = &drb->nr.flows[j]; + flow->qfi = qfi; + flow->param = get_qos_char_from_qos_flow_param(qos_param); } /* the DRB QoS parameters: we just reuse the ones from the first flow */ - drb->drb_info.drb_qos = drb->drb_info.flows_mapped_to_drb[0].qos_params; + drb->nr.drb_qos = drb->nr.flows[0].param; /* pass NSSAI info to MAC */ - drb->nssai = RRC_pduSession->param.nssai; + drb->nr.nssai = pdu->param.nssai; + + drb->up_ul_tnl[0].tl_address = drb_config->UpParamList[0].tl_info.tlAddress; + drb->up_ul_tnl[0].teid = drb_config->UpParamList[0].tl_info.teId; + drb->up_ul_tnl_len = 1; + drb->rlc_mode = rrc->configuration.um_on_default_drb ? F1AP_RLC_MODE_UM_BIDIR : F1AP_RLC_MODE_AM; + drb->dl_pdcp_sn_len = malloc_or_fail(sizeof(*drb->dl_pdcp_sn_len)); + *drb->dl_pdcp_sn_len = rrc_drb->pdcp_config.pdcp_SN_SizeDL == 1 ? F1AP_PDCP_SN_18B : F1AP_PDCP_SN_12B; + drb->ul_pdcp_sn_len = malloc_or_fail(sizeof(*drb->ul_pdcp_sn_len)); + *drb->ul_pdcp_sn_len = rrc_drb->pdcp_config.pdcp_SN_SizeUL == 1 ? F1AP_PDCP_SN_18B : F1AP_PDCP_SN_12B; nb_drb++; } @@ -2463,7 +2488,7 @@ void rrc_gNB_process_e1_bearer_context_setup_resp(e1ap_bearer_setup_resp_t *resp } /* Instruction towards the DU for DRB configuration and tunnel creation */ - f1ap_drb_to_be_setup_t drbs[32]; // maximum DRB can be 32 + f1ap_drb_to_setup_t drbs[32]; // maximum DRB can be 32 int nb_drb = fill_drb_to_be_setup_from_e1_resp(rrc, UE, resp->pduSession, resp->numPDUSessions, drbs); if (!UE->f1_ue_context_active) @@ -3001,7 +3026,7 @@ int rrc_gNB_generate_pcch_msg(sctp_assoc_t assoc_id, const NR_SIB1_t *sib1, uint void rrc_gNB_generate_UeContextSetupRequest(const gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *const ue_context_pP, int n_drbs, - const f1ap_drb_to_be_setup_t *drbs) + const f1ap_drb_to_setup_t *drbs) //----------------------------------------------------------------------------- { gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; @@ -3009,47 +3034,51 @@ void rrc_gNB_generate_UeContextSetupRequest(const gNB_RRC_INST *rrc, AssertFatal(!NODE_IS_DU(rrc->node_type), "illegal node type DU!\n"); - cu_to_du_rrc_information_t cu2du = {0}; - cu_to_du_rrc_information_t *cu2du_p = NULL; + f1ap_cu_to_du_rrc_info_t cu2du = {0}; if (ue_p->ue_cap_buffer.len > 0 && ue_p->ue_cap_buffer.buf != NULL) { - cu2du_p = &cu2du; - cu2du.uE_CapabilityRAT_ContainerList = ue_p->ue_cap_buffer.buf; - cu2du.uE_CapabilityRAT_ContainerList_length = ue_p->ue_cap_buffer.len; + cu2du.ue_cap = &ue_p->ue_cap_buffer; } int nb_srb = 1; - f1ap_srb_to_be_setup_t srbs[1] = {{.srb_id = 2, .lcid = 2}}; + f1ap_srb_to_setup_t srbs[1] = {{.id = 2, }}; activate_srb(ue_p, 2); + /* gNB-DU UE Aggregate Maximum Bit Rate Uplink is C- ifDRBSetup */ + uint64_t agg_mbr = 1000000000 /* bps */, *agg_mbr_p = NULL; + if (n_drbs > 0) + agg_mbr_p = &agg_mbr; + /* the callback will fill the UE context setup request and forward it */ f1_ue_data_t ue_data = cu_get_f1_ue_data(ue_p->rrc_ue_id); RETURN_IF_INVALID_ASSOC_ID(ue_data.du_assoc_id); - f1ap_ue_context_setup_t ue_context_setup_req = { + f1ap_ue_context_setup_req_t ue_context_setup_req = { .gNB_CU_ue_id = ue_p->rrc_ue_id, - .gNB_DU_ue_id = ue_data.secondary_ue, + .gNB_DU_ue_id = &ue_data.secondary_ue, .plmn.mcc = rrc->configuration.plmn[0].mcc, .plmn.mnc = rrc->configuration.plmn[0].mnc, .plmn.mnc_digit_length = rrc->configuration.plmn[0].mnc_digit_length, .nr_cellid = rrc->nr_cellid, - .servCellId = 0, /* TODO: correct value? */ - .srbs_to_be_setup_length = nb_srb, - .srbs_to_be_setup = srbs, - .drbs_to_be_setup_length = n_drbs, - .drbs_to_be_setup = (f1ap_drb_to_be_setup_t *)drbs, - .cu_to_du_rrc_information = cu2du_p, + .servCellIndex = 0, /* TODO: correct value? */ + .srbs_len = nb_srb, + .srbs = srbs, + .drbs_len = n_drbs, + .drbs = (f1ap_drb_to_setup_t *) drbs, // cast to avoid warning on const + .cu_to_du_rrc_info = cu2du, + .gnb_du_ue_agg_mbr_ul = agg_mbr_p, }; rrc->mac_rrc.ue_context_setup_request(ue_data.du_assoc_id, &ue_context_setup_req); LOG_I(RRC, "UE %d trigger UE context setup request with %d DRBs\n", ue_p->rrc_ue_id, n_drbs); + // nothing to free for ue_context_setup_req } //----------------------------------------------------------------------------- void rrc_gNB_generate_UeContextModificationRequest(const gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *const ue_context_pP, int n_drbs, - const f1ap_drb_to_be_setup_t *drbs, + const f1ap_drb_to_setup_t *drbs, int n_rel_drbs, - const f1ap_drb_to_be_released_t *rel_drbs) + const f1ap_drb_to_release_t *rel_drbs) //----------------------------------------------------------------------------- { gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; @@ -3058,30 +3087,23 @@ void rrc_gNB_generate_UeContextModificationRequest(const gNB_RRC_INST *rrc, AssertFatal(!NODE_IS_DU(rrc->node_type), "illegal node type DU!\n"); - cu_to_du_rrc_information_t cu2du = {0}; - cu_to_du_rrc_information_t *cu2du_p = NULL; + f1ap_cu_to_du_rrc_info_t cu2du = {0}; if (ue_p->ue_cap_buffer.len > 0 && ue_p->ue_cap_buffer.buf != NULL) { - cu2du_p = &cu2du; - cu2du.uE_CapabilityRAT_ContainerList = ue_p->ue_cap_buffer.buf; - cu2du.uE_CapabilityRAT_ContainerList_length = ue_p->ue_cap_buffer.len; + cu2du.ue_cap = &ue_p->ue_cap_buffer; } f1_ue_data_t ue_data = cu_get_f1_ue_data(ue_p->rrc_ue_id); RETURN_IF_INVALID_ASSOC_ID(ue_data.du_assoc_id); - f1ap_ue_context_modif_req_t ue_context_modif_req = { + f1ap_ue_context_mod_req_t ue_context_modif_req = { .gNB_CU_ue_id = ue_p->rrc_ue_id, .gNB_DU_ue_id = ue_data.secondary_ue, - .plmn.mcc = rrc->configuration.plmn[0].mcc, - .plmn.mnc = rrc->configuration.plmn[0].mnc, - .plmn.mnc_digit_length = rrc->configuration.plmn[0].mnc_digit_length, - .nr_cellid = rrc->nr_cellid, - .servCellId = 0, /* TODO: correct value? */ - .drbs_to_be_setup_length = n_drbs, - .drbs_to_be_setup = (f1ap_drb_to_be_setup_t *)drbs, - .drbs_to_be_released_length = n_rel_drbs, - .drbs_to_be_released = (f1ap_drb_to_be_released_t *)rel_drbs, - .cu_to_du_rrc_information = cu2du_p, + .drbs_len = n_drbs, + .drbs = (f1ap_drb_to_setup_t *)drbs, + .drbs_rel_len = n_rel_drbs, + .drbs_rel = (f1ap_drb_to_release_t *)rel_drbs, + .cu_to_du_rrc_info = &cu2du, }; rrc->mac_rrc.ue_context_modification_request(ue_data.du_assoc_id, &ue_context_modif_req); LOG_I(RRC, "UE %d trigger UE context modification request with %d DRBs\n", ue_p->rrc_ue_id, n_drbs); + // nothing to free } diff --git a/openair2/RRC/NR/rrc_gNB_mobility.c b/openair2/RRC/NR/rrc_gNB_mobility.c index 647f253989..a08e446ef1 100644 --- a/openair2/RRC/NR/rrc_gNB_mobility.c +++ b/openair2/RRC/NR/rrc_gNB_mobility.c @@ -31,6 +31,7 @@ #include "rrc_gNB_UE_context.h" #include "openair2/LAYER2/NR_MAC_COMMON/nr_mac.h" #include "openair2/F1AP/f1ap_ids.h" +#include "openair2/F1AP/lib/f1ap_ue_context.h" #include "MESSAGES/asn1_msg.h" #include "nr_pdcp/nr_pdcp_oai_api.h" #include "openair3/SECU/key_nas_deriver.h" @@ -61,7 +62,7 @@ static void free_ho_ctx(nr_handover_context_t *ho_ctx) free(ho_ctx); } -static int fill_drb_to_be_setup(const gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue, f1ap_drb_to_be_setup_t drbs[MAX_DRBS_PER_UE]) +static int fill_drb_to_be_setup(const gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue, f1ap_drb_to_setup_t drbs[MAX_DRBS_PER_UE]) { int nb_drb = 0; for (int i = 0; i < MAX_DRBS_PER_UE; ++i) { @@ -69,34 +70,38 @@ static int fill_drb_to_be_setup(const gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue, f1ap_ if (rrc_drb->status == DRB_INACTIVE) continue; - f1ap_drb_to_be_setup_t *drb = &drbs[nb_drb]; + f1ap_drb_to_setup_t *drb = &drbs[nb_drb]; nb_drb++; - drb->drb_id = rrc_drb->drb_id; - drb->rlc_mode = rrc->configuration.um_on_default_drb ? F1AP_RLC_MODE_UM_BIDIR : F1AP_RLC_MODE_AM; - memcpy(&drb->up_ul_tnl[0].tl_address, &rrc_drb->cuup_tunnel_config.addr.buffer, sizeof(uint8_t) * 4); - drb->up_ul_tnl[0].port = rrc->eth_params_s.my_portd; - drb->up_ul_tnl[0].teid = rrc_drb->cuup_tunnel_config.teid; - drb->up_ul_tnl_length = 1; - /* fetch an existing PDU session for this DRB */ - rrc_pdu_session_param_t *pdu = find_pduSession_from_drbId(ue, drb->drb_id); - AssertFatal(pdu != NULL, "no PDU session for DRB ID %ld\n", drb->drb_id); - drb->nssai = pdu->param.nssai; - + rrc_pdu_session_param_t *pdu = find_pduSession_from_drbId(ue, rrc_drb->drb_id); + AssertFatal(pdu != NULL, "no PDU session for DRB ID %d\n", rrc_drb->drb_id); // for the moment, we only support one QoS flow. Put a reminder in case // this changes AssertFatal(pdu->param.nb_qos == 1, "only 1 Qos flow supported\n"); - drb->drb_info.flows_to_be_setup_length = 1; - drb->drb_info.flows_mapped_to_drb = calloc_or_fail(1, sizeof(drb->drb_info.flows_mapped_to_drb[0])); - AssertFatal(drb->drb_info.flows_mapped_to_drb, "could not allocate memory\n"); int qfi = rrc_drb->cnAssociation.sdap_config.mappedQoS_FlowsToAdd[0]; - DevAssert(qfi > 0); - drb->drb_info.flows_mapped_to_drb[0].qfi = qfi; - pdusession_level_qos_parameter_t *in_qos_char = get_qos_characteristics(qfi, pdu); - drb->drb_info.flows_mapped_to_drb[0].qos_params.qos_characteristics = get_qos_char_from_qos_flow_param(in_qos_char); + pdusession_level_qos_parameter_t *qos_param = get_qos_characteristics(qfi, pdu); + drb->id = rrc_drb->drb_id; + + drb->qos_choice = F1AP_QOS_CHOICE_NR; + drb->nr.nssai = pdu->param.nssai; + drb->nr.flows_len = 1; + drb->nr.flows = calloc_or_fail(1, sizeof(*drb->nr.flows)); + DevAssert(qfi > 0); + drb->nr.flows[0].qfi = qfi; + drb->nr.flows[0].param = get_qos_char_from_qos_flow_param(qos_param); /* the DRB QoS parameters: we just reuse the ones from the first flow */ - drb->drb_info.drb_qos = drb->drb_info.flows_mapped_to_drb[0].qos_params; + drb->nr.drb_qos = drb->nr.flows[0].param; + + memcpy(&drb->up_ul_tnl[0].tl_address, &rrc_drb->cuup_tunnel_config.addr.buffer, sizeof(uint8_t) * 4); + drb->up_ul_tnl[0].teid = rrc_drb->cuup_tunnel_config.teid; + drb->up_ul_tnl_len = 1; + + drb->rlc_mode = rrc->configuration.um_on_default_drb ? F1AP_RLC_MODE_UM_BIDIR : F1AP_RLC_MODE_AM; + drb->dl_pdcp_sn_len = malloc_or_fail(sizeof(*drb->dl_pdcp_sn_len)); + *drb->dl_pdcp_sn_len = rrc_drb->pdcp_config.pdcp_SN_SizeDL == 1 ? F1AP_PDCP_SN_18B : F1AP_PDCP_SN_12B; + drb->ul_pdcp_sn_len = malloc_or_fail(sizeof(*drb->ul_pdcp_sn_len)); + *drb->ul_pdcp_sn_len = rrc_drb->pdcp_config.pdcp_SN_SizeUL == 1 ? F1AP_PDCP_SN_18B : F1AP_PDCP_SN_12B;; } return nb_drb; } @@ -168,32 +173,38 @@ static void nr_initiate_handover(const gNB_RRC_INST *rrc, target_du->assoc_id, target_du->setup_req->cell[0].info.nr_pci); - cu_to_du_rrc_information_t cu2du = { - .handoverPreparationInfo = ho_prep_info->buf, - .handoverPreparationInfo_length = ho_prep_info->len, - }; - - f1ap_drb_to_be_setup_t drbs[MAX_DRBS_PER_UE] = {0}; + f1ap_drb_to_setup_t *drbs = calloc_or_fail(MAX_DRBS_PER_UE, sizeof(*drbs)); int nb_drb = fill_drb_to_be_setup(rrc, ue, drbs); - f1ap_srb_to_be_setup_t srbs[2] = {{.srb_id = 1, .lcid = 1}, {.srb_id = 2, .lcid = 2}}; + int nb_srb = 2; + f1ap_srb_to_setup_t *srbs = calloc_or_fail(nb_srb, sizeof(*srbs)); + srbs[0].id = 1; + srbs[1].id = 2; + + byte_array_t *hpi = malloc_or_fail(sizeof(*hpi)); + *hpi = copy_byte_array(*ho_prep_info); + + uint64_t *ue_agg_mbr = malloc_or_fail(sizeof(*ue_agg_mbr)); + *ue_agg_mbr = 1000000000 /*bps*/; + f1ap_served_cell_info_t *cell_info = &target_du->setup_req->cell[0].info; RETURN_IF_INVALID_ASSOC_ID(target_du->assoc_id); - f1ap_ue_context_setup_t ue_context_setup_req = { + f1ap_ue_context_setup_req_t ue_context_setup_req = { .gNB_CU_ue_id = ue->rrc_ue_id, - .gNB_DU_ue_id = 0, /* TODO: this should be optional! */ .plmn.mcc = cell_info->plmn.mcc, .plmn.mnc = cell_info->plmn.mnc, .plmn.mnc_digit_length = cell_info->plmn.mnc_digit_length, .nr_cellid = cell_info->nr_cellid, - .servCellId = 0, // TODO: correct value? - .srbs_to_be_setup_length = 2, - .srbs_to_be_setup = srbs, - .drbs_to_be_setup_length = nb_drb, - .drbs_to_be_setup = drbs, - .cu_to_du_rrc_information = &cu2du, + .servCellIndex = 0, // TODO: correct value? + .srbs_len = nb_srb, + .srbs = srbs, + .drbs_len = nb_drb, + .drbs = drbs, + .cu_to_du_rrc_info.ho_prep_info = hpi, + .gnb_du_ue_agg_mbr_ul = ue_agg_mbr, }; rrc->mac_rrc.ue_context_setup_request(target_du->assoc_id, &ue_context_setup_req); + free_ue_context_setup_req(&ue_context_setup_req); } /* @@ -214,15 +225,15 @@ void nr_rrc_trigger_n2_ho(gNB_RRC_INST *rrc, int nr_cgi, uint8_t *ho_prep_info, typedef struct deliver_ue_ctxt_modification_data_t { gNB_RRC_INST *rrc; - f1ap_ue_context_modif_req_t *modification_req; + f1ap_ue_context_mod_req_t *modification_req; sctp_assoc_t assoc_id; } deliver_ue_ctxt_modification_data_t; static void rrc_deliver_ue_ctxt_modif_req(void *deliver_pdu_data, ue_id_t ue_id, int srb_id, char *buf, int size, int sdu_id) { DevAssert(deliver_pdu_data != NULL); deliver_ue_ctxt_modification_data_t *data = deliver_pdu_data; - data->modification_req->rrc_container = (uint8_t*)buf; - data->modification_req->rrc_container_length = size; + byte_array_t ba = {.buf = (uint8_t *) buf, .len = size}; + data->modification_req->rrc_container = &ba; data->rrc->mac_rrc.ue_context_modification_request(data->assoc_id, data->modification_req); } static void rrc_gNB_trigger_reconfiguration_for_handover(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue, uint8_t *rrc_reconf, int rrc_reconf_len) @@ -231,12 +242,9 @@ static void rrc_gNB_trigger_reconfiguration_for_handover(gNB_RRC_INST *rrc, gNB_ TransmActionInd_t transmission_action_indicator = TransmActionInd_STOP; RETURN_IF_INVALID_ASSOC_ID(ue_data.du_assoc_id); - f1ap_ue_context_modif_req_t ue_context_modif_req = { + f1ap_ue_context_mod_req_t ue_context_modif_req = { .gNB_CU_ue_id = ue->rrc_ue_id, .gNB_DU_ue_id = ue_data.secondary_ue, - .plmn = rrc->configuration.plmn[0], - .nr_cellid = rrc->nr_cellid, // TODO target cell ID - .servCellId = 0, // TODO: correct value? .transm_action_ind = &transmission_action_indicator, }; deliver_ue_ctxt_modification_data_t data = {.rrc = rrc, diff --git a/openair2/RRC/NR/rrc_gNB_nsa.c b/openair2/RRC/NR/rrc_gNB_nsa.c index 8ac172a21e..1ccdb3439a 100644 --- a/openair2/RRC/NR/rrc_gNB_nsa.c +++ b/openair2/RRC/NR/rrc_gNB_nsa.c @@ -71,6 +71,7 @@ #include "xer_decoder.h" #include "xer_encoder.h" #include "f1ap_common.h" +#include "lib/f1ap_ue_context.h" // In case of phy-test and do-ra mode, read UE capabilities directly from file // and put it into a CG-ConfigInfo field @@ -137,18 +138,16 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc, x2ap_ENDC_sgnb_addition_req_t *m, sctp_ nr_pdcp_entity_security_keys_and_algos_t security_parameters = {0}; uint8_t tmp[1024]; - uint8_t *cgci_buf = NULL; - uint32_t cgci_len = 0; + byte_array_t cgci = {0}; if (get_softmodem_params()->phy_test == 1 || get_softmodem_params()->do_ra == 1) { DevAssert(m == NULL); UE->rb_config = get_default_rbconfig(10 /* EPS bearer ID */, 1 /* drb ID */, NR_CipheringAlgorithm_nea0, NR_SecurityConfig__keyToUse_master, &rrc->pdcp_config); - cgci_len = cg_config_info_from_ue_cap_file(sizeof tmp, tmp); - DevAssert(cgci_len > 0); - cgci_buf = tmp; + int len = cg_config_info_from_ue_cap_file(sizeof tmp, tmp); + DevAssert(len > 0); + cgci = create_byte_array(len, tmp); } else { DevAssert(m != NULL); - cgci_buf = m->rrc_buffer; - cgci_len = m->rrc_buffer_size; + cgci = create_byte_array(m->rrc_buffer_size, m->rrc_buffer); /* TODO: handle more than one bearer */ if (m->nb_e_rabs_tobeadded != 1) { @@ -272,25 +271,24 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc, x2ap_ENDC_sgnb_addition_req_t *m, sctp_ UE->rb_config->drb_ToAddModList, &security_parameters); - cu_to_du_rrc_information_t cu2du = { - .cG_ConfigInfo = cgci_buf, - .cG_ConfigInfo_length = cgci_len, - }; /* assumption: only a single bearer, see above */ NR_DRB_ToAddModList_t *rb_list = UE->rb_config->drb_ToAddModList; AssertFatal(rb_list->list.count == 1, "can only handle one bearer for NSA/phy-test/do-ra, but has %d\n", rb_list->list.count); int drb_id = rb_list->list.array[0]->drb_Identity; - f1ap_flows_mapped_to_drb_t *flow = calloc(1, sizeof(f1ap_flows_mapped_to_drb_t)); - flow->qos_params.qos_characteristics.qos_type = NON_DYNAMIC; - flow->qfi = flow->qos_params.qos_characteristics.non_dynamic.fiveqi = 9; - f1ap_drb_to_be_setup_t drbs = { - .drb_id = drb_id, - .rlc_mode = F1AP_RLC_MODE_UM_BIDIR, // hardcoded keep it backwards compatible for now - // rrc->configuration.um_on_default_drb ? F1AP_RLC_MODE_UM_BIDIR : F1AP_RLC_MODE_AM, - .up_ul_tnl_length = 1, - .drb_info.flows_to_be_setup_length = 1, - .drb_info.flows_mapped_to_drb = flow, - }; + f1ap_drb_to_setup_t *drb = calloc_or_fail(1, sizeof(*drb)); + drb->id = drb_id; + // hardcoded keep it backwards compatible for now + // rrc->configuration.um_on_default_drb ? F1AP_RLC_MODE_UM_BIDIR : F1AP_RLC_MODE_AM, + drb->rlc_mode = F1AP_RLC_MODE_UM_BIDIR; + drb->up_ul_tnl_len = 1; + drb->qos_choice = F1AP_QOS_CHOICE_NR; // we don't have EUTRAN yet, "approximate" it + drb->nr.flows_len = 1; + f1ap_drb_flows_mapped_t *flow = drb->nr.flows = calloc_or_fail(drb->nr.flows_len, sizeof(*flow)); + flow->qfi = 9; + flow->param.qos_type = NON_DYNAMIC; + flow->param.nondyn.fiveQI = 9; + flow->param.arp.prio = 5; + // Note: E1 support for NSA/phy-test/do-ra not implemented yet instance_t f1inst = get_f1_gtp_instance(); if (f1inst >= 0) { @@ -305,25 +303,30 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc, x2ap_ENDC_sgnb_addition_req_t *m, sctp_ gtpv1u_gnb_create_tunnel_resp_t resp = {0}; int ret = gtpv1u_create_ngu_tunnel(f1inst, &req, &resp, NULL, NULL); AssertFatal(ret == 0, "gtpv1u_create_ngu_tunnel failed: ret %d\n", ret); - drbs.up_ul_tnl[0].port = rrc->eth_params_s.my_portd; - memcpy(&drbs.up_ul_tnl[0].tl_address, &resp.gnb_addr.buffer, 4); - drbs.up_ul_tnl[0].teid = resp.gnb_NGu_teid[0]; + memcpy(&drb->up_ul_tnl[0].tl_address, &resp.gnb_addr.buffer, 4); + drb->up_ul_tnl[0].teid = resp.gnb_NGu_teid[0]; + drb->up_ul_tnl_len = 1; } - f1ap_ue_context_setup_t req = { + uint64_t *ue_agg_mbr_ul = malloc_or_fail(sizeof(*ue_agg_mbr_ul)); + *ue_agg_mbr_ul = 1000000000; + byte_array_t *cg_configinfo = malloc_or_fail(sizeof(*cg_configinfo)); + *cg_configinfo = cgci; + f1ap_ue_context_setup_req_t req = { .gNB_CU_ue_id = UE->rrc_ue_id, - .gNB_DU_ue_id = 0xffffffff, /* not known yet */ .plmn.mcc = rrc->configuration.plmn[0].mcc, .plmn.mnc = rrc->configuration.plmn[0].mnc, .plmn.mnc_digit_length = rrc->configuration.plmn[0].mnc_digit_length, .nr_cellid = rrc->nr_cellid, - .servCellId = 0, - .drbs_to_be_setup_length = 1, - .drbs_to_be_setup = &drbs, - .cu_to_du_rrc_information = &cu2du, + .servCellIndex = 0, + .drbs_len = 1, + .drbs = drb, + .cu_to_du_rrc_info.cg_configinfo = cg_configinfo, + .gnb_du_ue_agg_mbr_ul = ue_agg_mbr_ul, }; f1_ue_data_t ue_data = cu_get_f1_ue_data(UE->rrc_ue_id); RETURN_IF_INVALID_ASSOC_ID(ue_data.du_assoc_id); rrc->mac_rrc.ue_context_setup_request(ue_data.du_assoc_id, &req); + free_ue_context_setup_req(&req); } static NR_RRCReconfiguration_IEs_t *get_default_reconfig(const NR_CellGroupConfig_t *secondaryCellGroup) From 6956e6ed11b5bc9d895ac7820e0b2d9ff19e3490 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 2 Jun 2025 09:01:38 +0200 Subject: [PATCH 122/964] Add F1AP UE context setup response message enc/dec + test See commit "Add F1AP UE context setup request message enc/dec + test" for more details on the approach taken. --- openair2/COMMON/f1ap_messages_types.h | 32 +++ openair2/F1AP/lib/f1ap_lib_includes.h | 1 + openair2/F1AP/lib/f1ap_ue_context.c | 375 ++++++++++++++++++++++++++ openair2/F1AP/lib/f1ap_ue_context.h | 6 + openair2/F1AP/tests/f1ap_lib_test.c | 96 +++++++ 5 files changed, 510 insertions(+) diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h index 73b8162eb4..c8ebde936a 100644 --- a/openair2/COMMON/f1ap_messages_types.h +++ b/openair2/COMMON/f1ap_messages_types.h @@ -460,6 +460,11 @@ typedef struct f1ap_cu_to_du_rrc_info_s { byte_array_t *ho_prep_info; } f1ap_cu_to_du_rrc_info_t; +typedef struct f1ap_du_to_cu_rrc_info_t { + byte_array_t cell_group_config; + byte_array_t *meas_gap_config; +} f1ap_du_to_cu_rrc_info_t; + typedef struct du_to_cu_rrc_information_s { uint8_t * cellGroupConfig; uint32_t cellGroupConfig_length; @@ -494,6 +499,11 @@ typedef struct f1ap_srb_to_setup_t { int id; } f1ap_srb_to_setup_t; +typedef struct f1ap_srb_setup_t { + int id; + int lcid; +} f1ap_srb_setup_t; + /// 9.3.1.52 Packet Error Rate typedef struct f1ap_per_t { uint8_t scalar; @@ -560,6 +570,13 @@ typedef struct f1ap_drb_to_setup_t { f1ap_pdcp_sn_len_t *ul_pdcp_sn_len; } f1ap_drb_to_setup_t; +typedef struct f1ap_drb_setup_t { + int id; + int *lcid; + int up_dl_tnl_len; + f1ap_up_tnl_t up_dl_tnl[2]; +} f1ap_drb_setup_t; + typedef struct f1ap_drb_to_release_t { int id; } f1ap_drb_to_release_t; @@ -585,6 +602,21 @@ typedef struct f1ap_ue_context_setup_req_s { uint64_t *gnb_du_ue_agg_mbr_ul; // C-ifDRBSetup } f1ap_ue_context_setup_req_t; +typedef struct f1ap_ue_context_setup_resp_s { + uint32_t gNB_CU_ue_id; + uint32_t gNB_DU_ue_id; + + f1ap_du_to_cu_rrc_info_t du_to_cu_rrc_info; + + uint16_t *crnti; + + int drbs_len; + f1ap_drb_setup_t *drbs; + + int srbs_len; + f1ap_srb_setup_t *srbs; +} f1ap_ue_context_setup_resp_t; + typedef struct f1ap_ue_context_mod_req_t { uint32_t gNB_CU_ue_id; uint32_t gNB_DU_ue_id; diff --git a/openair2/F1AP/lib/f1ap_lib_includes.h b/openair2/F1AP/lib/f1ap_lib_includes.h index e34ec0598d..3f039bf6f0 100644 --- a/openair2/F1AP/lib/f1ap_lib_includes.h +++ b/openair2/F1AP/lib/f1ap_lib_includes.h @@ -46,5 +46,6 @@ #include "F1AP_Flows-Mapped-To-DRB-Item.h" #include "F1AP_NonDynamic5QIDescriptor.h" #include "F1AP_Dynamic5QIDescriptor.h" +#include "F1AP_DLUPTNLInformation-ToBeSetup-Item.h" #endif /* F1AP_LIB_INCLUDES_H_ */ diff --git a/openair2/F1AP/lib/f1ap_ue_context.c b/openair2/F1AP/lib/f1ap_ue_context.c index 332b0ad130..1559ee30d9 100644 --- a/openair2/F1AP/lib/f1ap_ue_context.c +++ b/openair2/F1AP/lib/f1ap_ue_context.c @@ -138,6 +138,58 @@ static void free_cu_to_du_rrc_info(f1ap_cu_to_du_rrc_info_t *cu2du) FREE_OPT_BYTE_ARRAY(cu2du->ho_prep_info); } +static F1AP_DUtoCURRCInformation_t encode_du_to_cu_rrc_info(const f1ap_du_to_cu_rrc_info_t *du2cu) +{ + F1AP_DUtoCURRCInformation_t enc = {0}; + + /* mandatory: cellGroupConfig */ + const byte_array_t *ba = &du2cu->cell_group_config; + OCTET_STRING_fromBuf(&enc.cellGroupConfig, (const char *)ba->buf, ba->len); + + /* optional: MeasGapConfig */ + if (du2cu->meas_gap_config) { + ba = du2cu->meas_gap_config; + asn1cCalloc(enc.measGapConfig, measGapConfig); + OCTET_STRING_fromBuf(measGapConfig, (const char *)ba->buf, ba->len); + } + + return enc; +} + +static bool decode_du_to_cu_rrc_info(f1ap_du_to_cu_rrc_info_t *dec, const F1AP_DUtoCURRCInformation_t *du2cu) +{ + const F1AP_CellGroupConfig_t *cgc = &du2cu->cellGroupConfig; + dec->cell_group_config = create_byte_array(cgc->size, (uint8_t *)cgc->buf); + + if (du2cu->measGapConfig) { + const F1AP_MeasGapConfig_t *mgc = du2cu->measGapConfig; + dec->meas_gap_config = calloc_or_fail(1, sizeof(*dec->meas_gap_config)); + *dec->meas_gap_config = create_byte_array(mgc->size, (uint8_t *)mgc->buf); + } + return true; +} + +static f1ap_du_to_cu_rrc_info_t cp_du_to_cu_rrc_info(const f1ap_du_to_cu_rrc_info_t *src) +{ + f1ap_du_to_cu_rrc_info_t cp = {0}; + cp.cell_group_config = copy_byte_array(src->cell_group_config); + CP_OPT_BYTE_ARRAY(cp.meas_gap_config, src->meas_gap_config); + return cp; +} + +static bool eq_du_to_cu_rrc_info(const f1ap_du_to_cu_rrc_info_t *a, const f1ap_du_to_cu_rrc_info_t *b) +{ + _F1_CHECK_EXP(eq_byte_array(&a->cell_group_config, &b->cell_group_config)); + _F1_EQ_CHECK_OPTIONAL_IE(a, b, meas_gap_config, eq_ba); + return true; +} + +static void free_du_to_cu_rrc_info(f1ap_du_to_cu_rrc_info_t *du2cu) +{ + free_byte_array(du2cu->cell_group_config); + FREE_OPT_BYTE_ARRAY(du2cu->meas_gap_config); +} + /* \brief Encode SRB-ToBeSetup List, for UE Context Setup Request, from * f1ap_srb_to_setup_t. */ static F1AP_SRBs_ToBeSetup_List_t encode_srbs_to_setup(int n, const f1ap_srb_to_setup_t *srbs) @@ -231,6 +283,59 @@ static void free_srb_to_setup(f1ap_srb_to_setup_t *srbs) // nothing to free } +static F1AP_SRBs_Setup_List_t encode_srbs_setup(int n, const f1ap_srb_setup_t *srbs) +{ + F1AP_SRBs_Setup_List_t list = {0}; + for (int i = 0; i < n; ++i) { + asn1cSequenceAdd(list, F1AP_SRBs_Setup_ItemIEs_t, itie); + itie->id = F1AP_ProtocolIE_ID_id_SRBs_Setup_Item; + itie->criticality = F1AP_Criticality_ignore; + itie->value.present = F1AP_SRBs_Setup_ItemIEs__value_PR_SRBs_Setup_Item; + F1AP_SRBs_Setup_Item_t *it = &itie->value.choice.SRBs_Setup_Item; + it->sRBID = srbs[i].id; + it->lCID = srbs[i].lcid; + } + return list; +} + +static bool decode_srbs_setup(const F1AP_SRBs_Setup_List_t *f1ap, int *n, f1ap_srb_setup_t **out) +{ + DevAssert(out != NULL); + *out = NULL; + int count = *n = f1ap->list.count; + if (count == 0) + return true; + + f1ap_srb_setup_t *srbs = *out = calloc_or_fail(count, sizeof(*srbs)); + for (int i = 0; i < count; ++i) { + const F1AP_SRBs_Setup_ItemIEs_t *itie = (F1AP_SRBs_Setup_ItemIEs_t *)f1ap->list.array[i]; + _F1_EQ_CHECK_LONG(itie->id, F1AP_ProtocolIE_ID_id_SRBs_Setup_Item); + _F1_EQ_CHECK_INT(itie->value.present, F1AP_SRBs_Setup_ItemIEs__value_PR_SRBs_Setup_Item); + const F1AP_SRBs_Setup_Item_t *it = &itie->value.choice.SRBs_Setup_Item; + srbs[i].id = it->sRBID; + srbs[i].lcid = it->lCID; + } + return true; +} + +static f1ap_srb_setup_t cp_srb_setup(const f1ap_srb_setup_t *orig) +{ + f1ap_srb_setup_t cp = {.id = orig->id, .lcid = orig->lcid}; + return cp; +} + +static bool eq_srb_setup(const f1ap_srb_setup_t *a, const f1ap_srb_setup_t *b) +{ + _F1_EQ_CHECK_INT(a->id, b->id); + _F1_EQ_CHECK_INT(a->lcid, b->lcid); + return true; +} + +static void free_srb_setup(f1ap_srb_setup_t *srbs) +{ + // nothing to free +} + static F1AP_QoSFlowLevelQoSParameters_t encode_qos_flow_param(const f1ap_qos_flow_param_t *p) { F1AP_QoSFlowLevelQoSParameters_t f1ap = {0}; @@ -784,6 +889,88 @@ static void free_drb_to_setup(f1ap_drb_to_setup_t *drb) free(drb->ul_pdcp_sn_len); } +static F1AP_DRBs_Setup_List_t encode_drbs_setup(int n, const f1ap_drb_setup_t *drbs) +{ + F1AP_DRBs_Setup_List_t list = {0}; + for (int i = 0; i < n; ++i) { + const f1ap_drb_setup_t *drb = &drbs[i]; + asn1cSequenceAdd(list, F1AP_DRBs_Setup_ItemIEs_t, itie); + itie->id = F1AP_ProtocolIE_ID_id_DRBs_Setup_Item; + itie->criticality = F1AP_Criticality_ignore; + itie->value.present = F1AP_DRBs_Setup_ItemIEs__value_PR_DRBs_Setup_Item; + + F1AP_DRBs_Setup_Item_t *it = &itie->value.choice.DRBs_Setup_Item; + it->dRBID = drb->id; + if (drb->lcid) + asn1cCallocOne(it->lCID, *drb->lcid); + for (int j = 0; j < drb->up_dl_tnl_len; ++j) { + DevAssert(drb->up_dl_tnl[j].teid > 0); + asn1cSequenceAdd(it->dLUPTNLInformation_ToBeSetup_List.list, F1AP_DLUPTNLInformation_ToBeSetup_Item_t, tnl_it); + tnl_it->dLUPTNLInformation = encode_up_tnl(&drb->up_dl_tnl[j]); + } + } + return list; +} + +static bool decode_drbs_setup(const F1AP_DRBs_Setup_List_t *f1ap, int *n, f1ap_drb_setup_t **out) +{ + DevAssert(out != NULL); + *out = NULL; + int count = *n = f1ap->list.count; + if (count == 0) + return true; + + f1ap_drb_setup_t *drbs = *out = calloc_or_fail(count, sizeof(*drbs)); + for (int i = 0; i < count; ++i) { + const F1AP_DRBs_Setup_ItemIEs_t *itie = (const F1AP_DRBs_Setup_ItemIEs_t *)f1ap->list.array[i]; + _F1_EQ_CHECK_LONG(itie->id, F1AP_ProtocolIE_ID_id_DRBs_Setup_Item); + _F1_EQ_CHECK_INT(itie->value.present, F1AP_DRBs_Setup_ItemIEs__value_PR_DRBs_Setup_Item); + const F1AP_DRBs_Setup_Item_t *it = &itie->value.choice.DRBs_Setup_Item; + + f1ap_drb_setup_t *drb = &drbs[i]; + drb->id = it->dRBID; + if (it->lCID) + _F1_MALLOC(drb->lcid, *it->lCID); + + drb->up_dl_tnl_len = it->dLUPTNLInformation_ToBeSetup_List.list.count; + _F1_EQ_CHECK_GENERIC(drb->up_dl_tnl_len > 0 && drb->up_dl_tnl_len <= 2, "%d", drb->up_dl_tnl_len, 1); + for (int j = 0; j < drb->up_dl_tnl_len; ++j) { + F1AP_DLUPTNLInformation_ToBeSetup_Item_t *it_tnl = it->dLUPTNLInformation_ToBeSetup_List.list.array[j]; + _F1_CHECK_EXP(decode_up_tnl(&it_tnl->dLUPTNLInformation, &drb->up_dl_tnl[j])); + } + } + + return true; +} + +static f1ap_drb_setup_t cp_drb_setup(const f1ap_drb_setup_t *orig) +{ + f1ap_drb_setup_t cp = { + .id = orig->id, + .up_dl_tnl_len = orig->up_dl_tnl_len, + .up_dl_tnl[0] = cp_up_tnl(&orig->up_dl_tnl[0]), + .up_dl_tnl[1] = cp_up_tnl(&orig->up_dl_tnl[1]), + }; + if (orig->lcid) + _F1_MALLOC(cp.lcid, *orig->lcid); + return cp; +} + +static bool eq_drb_setup(const f1ap_drb_setup_t *a, const f1ap_drb_setup_t *b) +{ + _F1_EQ_CHECK_INT(a->id, b->id); + _F1_EQ_CHECK_OPTIONAL_IE(a, b, lcid, _F1_EQ_CHECK_INT); + _F1_EQ_CHECK_INT(a->up_dl_tnl_len, b->up_dl_tnl_len); + for (int i = 0; i < a->up_dl_tnl_len; ++i) + _F1_CHECK_EXP(eq_up_tnl(&a->up_dl_tnl[i], &b->up_dl_tnl[i])); + return true; +} + +static void free_drb_setup(f1ap_drb_setup_t *drb) +{ + free(drb->lcid); +} + static F1AP_DRBs_ToBeReleased_List_t encode_drbs_to_release(int n, const f1ap_drb_to_release_t *drbs) { F1AP_DRBs_ToBeReleased_List_t list = {0}; @@ -1087,6 +1274,194 @@ void free_ue_context_setup_req(f1ap_ue_context_setup_req_t *req) free(req->gnb_du_ue_agg_mbr_ul); } +/** + * @brief Encode F1 UE context setup response to ASN.1 + */ +F1AP_F1AP_PDU_t *encode_ue_context_setup_resp(const f1ap_ue_context_setup_resp_t *msg) +{ + F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); + + /* Message Type */ + pdu->present = F1AP_F1AP_PDU_PR_successfulOutcome; + asn1cCalloc(pdu->choice.successfulOutcome, tmp); + tmp->procedureCode = F1AP_ProcedureCode_id_UEContextSetup; + tmp->criticality = F1AP_Criticality_reject; + tmp->value.present = F1AP_SuccessfulOutcome__value_PR_UEContextSetupResponse; + F1AP_UEContextSetupResponse_t *out = &tmp->value.choice.UEContextSetupResponse; + + /* mandatory: GNB_CU_UE_F1AP_ID */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie1); + ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; + ie1->criticality = F1AP_Criticality_reject; + ie1->value.present = F1AP_UEContextSetupResponseIEs__value_PR_GNB_CU_UE_F1AP_ID; + ie1->value.choice.GNB_CU_UE_F1AP_ID = msg->gNB_CU_ue_id; + + /* mandatory: GNB_DU_UE_F1AP_ID */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie2); + ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; + ie2->criticality = F1AP_Criticality_reject; + ie2->value.present = F1AP_UEContextSetupResponseIEs__value_PR_GNB_DU_UE_F1AP_ID; + ie2->value.choice.GNB_DU_UE_F1AP_ID = msg->gNB_DU_ue_id; + + /* mandatory: DUtoCURRCInformation */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie3); + ie3->id = F1AP_ProtocolIE_ID_id_DUtoCURRCInformation; + ie3->criticality = F1AP_Criticality_reject; + ie3->value.present = F1AP_UEContextSetupResponseIEs__value_PR_DUtoCURRCInformation; + ie3->value.choice.DUtoCURRCInformation = encode_du_to_cu_rrc_info(&msg->du_to_cu_rrc_info); + + /* optional: C-RNTI */ + if (msg->crnti) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie4); + ie4->id = F1AP_ProtocolIE_ID_id_C_RNTI; + ie4->criticality = F1AP_Criticality_ignore; + ie4->value.present = F1AP_UEContextSetupResponseIEs__value_PR_C_RNTI; + ie4->value.choice.C_RNTI = *msg->crnti; + } + + /* optional: DRB Setup List */ + if (msg->drbs_len > 0) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie7); + ie7->id = F1AP_ProtocolIE_ID_id_DRBs_Setup_List; + ie7->criticality = F1AP_Criticality_ignore; + ie7->value.present = F1AP_UEContextSetupResponseIEs__value_PR_DRBs_Setup_List; + ie7->value.choice.DRBs_Setup_List = encode_drbs_setup(msg->drbs_len, msg->drbs); + } + + /* optional: SRB Setup List */ + if (msg->srbs_len > 0) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie11); + ie11->id = F1AP_ProtocolIE_ID_id_SRBs_Setup_List; + ie11->criticality = F1AP_Criticality_ignore; + ie11->value.present = F1AP_UEContextSetupResponseIEs__value_PR_SRBs_Setup_List; + ie11->value.choice.SRBs_Setup_List = encode_srbs_setup(msg->srbs_len, msg->srbs); + } + + return pdu; +} + +/** + * @brief Decode F1 UE Context Setup Response + */ +bool decode_ue_context_setup_resp(const struct F1AP_F1AP_PDU *pdu, f1ap_ue_context_setup_resp_t *out) +{ + DevAssert(out != NULL); + memset(out, 0, sizeof(*out)); + + F1AP_UEContextSetupResponse_t *in = &pdu->choice.successfulOutcome->value.choice.UEContextSetupResponse; + F1AP_UEContextSetupResponseIEs_t *ie; + + F1AP_LIB_FIND_IE(F1AP_UEContextSetupResponseIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); + F1AP_LIB_FIND_IE(F1AP_UEContextSetupResponseIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); + F1AP_LIB_FIND_IE(F1AP_UEContextSetupResponseIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_DUtoCURRCInformation, true); + + for (int i = 0; i < in->protocolIEs.list.count; ++i) { + ie = in->protocolIEs.list.array[i]; + AssertError(ie != NULL, return false, "in->protocolIEs.list.array[i] is NULL"); + switch (ie->id) { + case F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupResponseIEs__value_PR_GNB_CU_UE_F1AP_ID); + out->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID; + break; + case F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupResponseIEs__value_PR_GNB_DU_UE_F1AP_ID); + out->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; + break; + case F1AP_ProtocolIE_ID_id_DUtoCURRCInformation: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupResponseIEs__value_PR_DUtoCURRCInformation); + _F1_CHECK_EXP(decode_du_to_cu_rrc_info(&out->du_to_cu_rrc_info, &ie->value.choice.DUtoCURRCInformation)); + break; + case F1AP_ProtocolIE_ID_id_C_RNTI: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupResponseIEs__value_PR_C_RNTI); + _F1_MALLOC(out->crnti, ie->value.choice.C_RNTI); + break; + case F1AP_ProtocolIE_ID_id_DRBs_Setup_List: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupResponseIEs__value_PR_DRBs_Setup_List); + _F1_CHECK_EXP(decode_drbs_setup(&ie->value.choice.DRBs_Setup_List, &out->drbs_len, &out->drbs)); + break; + case F1AP_ProtocolIE_ID_id_SRBs_Setup_List: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupResponseIEs__value_PR_SRBs_Setup_List); + _F1_CHECK_EXP(decode_srbs_setup(&ie->value.choice.SRBs_Setup_List, &out->srbs_len, &out->srbs)); + break; + default: + PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld unknown, skipping\n", ie->id); + break; + } + } + + return true; +} + +/** + * @brief F1 UE Context Setup Response deep copy + */ +f1ap_ue_context_setup_resp_t cp_ue_context_setup_resp(const f1ap_ue_context_setup_resp_t *orig) +{ + f1ap_ue_context_setup_resp_t cp = { + .gNB_CU_ue_id = orig->gNB_CU_ue_id, + .gNB_DU_ue_id = orig->gNB_DU_ue_id, + .du_to_cu_rrc_info = cp_du_to_cu_rrc_info(&orig->du_to_cu_rrc_info), + // crnti below + .drbs_len = orig->drbs_len, + // drbs below + .srbs_len = orig->srbs_len, + // srbs below + }; + if (orig->crnti) + _F1_MALLOC(cp.crnti, *orig->crnti); + if (orig->drbs_len > 0 && orig->drbs) { + cp.drbs = calloc_or_fail(orig->drbs_len, sizeof(*cp.drbs)); + cp.drbs_len = orig->drbs_len; + for (int i = 0; i < cp.drbs_len; ++i) + cp.drbs[i] = cp_drb_setup(&orig->drbs[i]); + } + if (orig->srbs_len > 0 && orig->srbs) { + cp.srbs = calloc_or_fail(orig->srbs_len, sizeof(*cp.srbs)); + cp.srbs_len = orig->srbs_len; + for (int i = 0; i < cp.srbs_len; ++i) + cp.srbs[i] = cp_srb_setup(&orig->srbs[i]); + } + return cp; +} + +/** + * @brief F1 UE Context Setup Response equality check + */ +bool eq_ue_context_setup_resp(const f1ap_ue_context_setup_resp_t *a, const f1ap_ue_context_setup_resp_t *b) +{ + _F1_EQ_CHECK_INT(a->gNB_CU_ue_id, b->gNB_CU_ue_id); + _F1_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id); + _F1_CHECK_EXP(eq_du_to_cu_rrc_info(&a->du_to_cu_rrc_info, &b->du_to_cu_rrc_info)); + _F1_EQ_CHECK_OPTIONAL_IE(a, b, crnti, _F1_EQ_CHECK_INT); + + _F1_EQ_CHECK_INT(a->drbs_len, b->drbs_len); + _F1_CHECK_EXP(a->drbs_len == 0 || (a->drbs && b->drbs)); + for (int i = 0; i < a->drbs_len; ++i) + _F1_CHECK_EXP(eq_drb_setup(&a->drbs[i], &b->drbs[i])); + + _F1_EQ_CHECK_INT(a->srbs_len, b->srbs_len); + _F1_CHECK_EXP(a->srbs_len == 0 || (a->srbs && b->srbs)); + for (int i = 0; i < a->srbs_len; ++i) + _F1_CHECK_EXP(eq_srb_setup(&a->srbs[i], &b->srbs[i])); + + return true; +} + +/** + * @brief Free Allocated F1 UE Context Setup Response + */ +void free_ue_context_setup_resp(f1ap_ue_context_setup_resp_t *resp) +{ + free_du_to_cu_rrc_info(&resp->du_to_cu_rrc_info); + free(resp->crnti); + for (int i = 0; i < resp->drbs_len; ++i) + free_drb_setup(&resp->drbs[i]); + free(resp->drbs); + for (int i = 0; i < resp->srbs_len; ++i) + free_srb_setup(&resp->srbs[i]); + free(resp->srbs); +} + /** * @brief Encode F1 UE context modification request to ASN.1 */ diff --git a/openair2/F1AP/lib/f1ap_ue_context.h b/openair2/F1AP/lib/f1ap_ue_context.h index 6ac521085b..3afb96fcc4 100644 --- a/openair2/F1AP/lib/f1ap_ue_context.h +++ b/openair2/F1AP/lib/f1ap_ue_context.h @@ -33,6 +33,12 @@ f1ap_ue_context_setup_req_t cp_ue_context_setup_req(const f1ap_ue_context_setup_ bool eq_ue_context_setup_req(const f1ap_ue_context_setup_req_t *a, const f1ap_ue_context_setup_req_t *b); void free_ue_context_setup_req(f1ap_ue_context_setup_req_t *req); +struct F1AP_F1AP_PDU *encode_ue_context_setup_resp(const f1ap_ue_context_setup_resp_t *msg); +bool decode_ue_context_setup_resp(const struct F1AP_F1AP_PDU *pdu, f1ap_ue_context_setup_resp_t *out); +f1ap_ue_context_setup_resp_t cp_ue_context_setup_resp(const f1ap_ue_context_setup_resp_t *orig); +bool eq_ue_context_setup_resp(const f1ap_ue_context_setup_resp_t *a, const f1ap_ue_context_setup_resp_t *b); +void free_ue_context_setup_resp(f1ap_ue_context_setup_resp_t *resp); + struct F1AP_F1AP_PDU *encode_ue_context_mod_req(const f1ap_ue_context_mod_req_t *msg); bool decode_ue_context_mod_req(const struct F1AP_F1AP_PDU *pdu, f1ap_ue_context_mod_req_t *out); f1ap_ue_context_mod_req_t cp_ue_context_mod_req(const f1ap_ue_context_mod_req_t *orig); diff --git a/openair2/F1AP/tests/f1ap_lib_test.c b/openair2/F1AP/tests/f1ap_lib_test.c index 159ea41470..0b0511c6bb 100644 --- a/openair2/F1AP/tests/f1ap_lib_test.c +++ b/openair2/F1AP/tests/f1ap_lib_test.c @@ -885,6 +885,100 @@ static void test_f1ap_ue_context_setup_request_simple() printf("%s() successful\n", __func__); } +static void test_f1ap_ue_context_setup_response() +{ + f1ap_ue_context_setup_resp_t orig = { + .gNB_CU_ue_id = 12, + .gNB_DU_ue_id = 13, + //.du_to_cu_rrc_info below + //.crnti below + //.drbs below + //.srbs below + }; + + orig.du_to_cu_rrc_info.cell_group_config = get_test_ba("CELL GROUP CONFIG"); + orig.du_to_cu_rrc_info.meas_gap_config = get_malloced_test_ba("MGC"); + + _F1_MALLOC(orig.crnti, 0x1234); + + orig.drbs_len = 2; + orig.drbs = calloc_or_fail(orig.drbs_len, sizeof(*orig.drbs)); + f1ap_drb_setup_t *drb1 = &orig.drbs[0]; + drb1->id = 12; + _F1_MALLOC(drb1->lcid, 12); + drb1->up_dl_tnl_len = 2; + inet_pton(AF_INET, "192.168.40.23", &drb1->up_dl_tnl[0].tl_address); + drb1->up_dl_tnl[0].teid = 0x11223344; + inet_pton(AF_INET, "192.168.40.23", &drb1->up_dl_tnl[1].tl_address); + drb1->up_dl_tnl[1].teid = 0x11223345; + f1ap_drb_setup_t *drb2 = &orig.drbs[1]; + drb2->id = 13; + _F1_MALLOC(drb2->lcid, 13); + drb2->up_dl_tnl_len = 2; + inet_pton(AF_INET, "192.168.50.23", &drb2->up_dl_tnl[0].tl_address); + drb2->up_dl_tnl[0].teid = 0x21223354; + inet_pton(AF_INET, "192.168.50.23", &drb2->up_dl_tnl[1].tl_address); + drb2->up_dl_tnl[1].teid = 0x21223355; + + orig.srbs_len = 2; + orig.srbs = calloc_or_fail(orig.srbs_len, sizeof(*orig.srbs)); + for (int i = 0; i < orig.srbs_len; ++i) { + orig.srbs[i].id = 1 + i; + orig.srbs[i].lcid = 1+i+10; + } + + F1AP_F1AP_PDU_t *f1enc = encode_ue_context_setup_resp(&orig); + F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + + f1ap_ue_context_setup_resp_t decoded = {0}; + bool ret = decode_ue_context_setup_resp(f1dec, &decoded); + AssertFatal(ret, "decode_ue_context_setup_resp(): could not decode message\n"); + f1ap_msg_free(f1dec); + + ret = eq_ue_context_setup_resp(&orig, &decoded); + AssertFatal(ret, "eq_ue_context_setup_resp(): decoded message doesn't match\n"); + free_ue_context_setup_resp(&decoded); + + f1ap_ue_context_setup_resp_t cp = cp_ue_context_setup_resp(&orig); + ret = eq_ue_context_setup_resp(&orig, &cp); + AssertFatal(ret, "eq_ue_context_setup_resp(): copied message doesn't match\n"); + free_ue_context_setup_resp(&orig); + free_ue_context_setup_resp(&cp); + + printf("%s() successful\n", __func__); +} + +static void test_f1ap_ue_context_setup_response_simple() +{ + f1ap_ue_context_setup_resp_t orig = { + .gNB_CU_ue_id = 12, + .gNB_DU_ue_id = 13, + .du_to_cu_rrc_info.cell_group_config = get_test_ba("small cg"), + // rest is optional and intentionally left empty + }; + + F1AP_F1AP_PDU_t *f1enc = encode_ue_context_setup_resp(&orig); + F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + + f1ap_ue_context_setup_resp_t decoded = {0}; + bool ret = decode_ue_context_setup_resp(f1dec, &decoded); + AssertFatal(ret, "decode_ue_context_setup_resp(): could not decode message\n"); + f1ap_msg_free(f1dec); + + ret = eq_ue_context_setup_resp(&orig, &decoded); + AssertFatal(ret, "eq_ue_context_setup_resp(): decoded message doesn't match\n"); + free_ue_context_setup_resp(&decoded); + + f1ap_ue_context_setup_resp_t cp = cp_ue_context_setup_resp(&orig); + ret = eq_ue_context_setup_resp(&orig, &cp); + AssertFatal(ret, "eq_ue_context_setup_resp(): copied message doesn't match\n"); + free_ue_context_setup_resp(&orig); + free_ue_context_setup_resp(&cp); + + printf("%s() successful\n", __func__); +} static void test_f1ap_ue_context_modification_request() { @@ -1012,6 +1106,8 @@ int main() test_f1ap_du_configuration_update_acknowledge(); test_f1ap_ue_context_setup_request(); test_f1ap_ue_context_setup_request_simple(); + test_f1ap_ue_context_setup_response(); + test_f1ap_ue_context_setup_response_simple(); test_f1ap_ue_context_modification_request(); test_f1ap_ue_context_modification_request_simple(); return 0; From 5c6aa46b03e3ddc71085ff88ee103db9099898e5 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 19 Jun 2025 08:39:14 +0200 Subject: [PATCH 123/964] Add F1AP UE context modification response message enc/dec + tes See commit "Add F1AP UE context setup request message enc/dec + test" for more details on the approach taken. --- openair2/COMMON/f1ap_messages_types.h | 13 ++ openair2/F1AP/lib/f1ap_ue_context.c | 273 ++++++++++++++++++++++++++ openair2/F1AP/lib/f1ap_ue_context.h | 6 + openair2/F1AP/tests/f1ap_lib_test.c | 84 ++++++++ 4 files changed, 376 insertions(+) diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h index c8ebde936a..396b0837b7 100644 --- a/openair2/COMMON/f1ap_messages_types.h +++ b/openair2/COMMON/f1ap_messages_types.h @@ -645,6 +645,19 @@ typedef struct f1ap_ue_context_mod_req_t { lower_layer_status_t *status; } f1ap_ue_context_mod_req_t; +typedef struct f1ap_ue_context_mod_resp { + uint32_t gNB_CU_ue_id; + uint32_t gNB_DU_ue_id; + + f1ap_du_to_cu_rrc_info_t *du_to_cu_rrc_info; + + int drbs_len; + f1ap_drb_setup_t *drbs; + + int srbs_len; + f1ap_srb_setup_t *srbs; +} f1ap_ue_context_mod_resp_t; + typedef struct f1ap_ue_context_setup_s { uint32_t gNB_CU_ue_id; uint32_t gNB_DU_ue_id; diff --git a/openair2/F1AP/lib/f1ap_ue_context.c b/openair2/F1AP/lib/f1ap_ue_context.c index 1559ee30d9..588648fe37 100644 --- a/openair2/F1AP/lib/f1ap_ue_context.c +++ b/openair2/F1AP/lib/f1ap_ue_context.c @@ -298,6 +298,21 @@ static F1AP_SRBs_Setup_List_t encode_srbs_setup(int n, const f1ap_srb_setup_t *s return list; } +static F1AP_SRBs_SetupMod_List_t encode_srbs_setupmod(int n, const f1ap_srb_setup_t *srbs) +{ + F1AP_SRBs_SetupMod_List_t list = {0}; + for (int i = 0; i < n; ++i) { + asn1cSequenceAdd(list, F1AP_SRBs_SetupMod_ItemIEs_t, itie); + itie->id = F1AP_ProtocolIE_ID_id_SRBs_SetupMod_Item; + itie->criticality = F1AP_Criticality_ignore; + itie->value.present = F1AP_SRBs_SetupMod_ItemIEs__value_PR_SRBs_SetupMod_Item; + F1AP_SRBs_SetupMod_Item_t *it = &itie->value.choice.SRBs_SetupMod_Item; + it->sRBID = srbs[i].id; + it->lCID = srbs[i].lcid; + } + return list; +} + static bool decode_srbs_setup(const F1AP_SRBs_Setup_List_t *f1ap, int *n, f1ap_srb_setup_t **out) { DevAssert(out != NULL); @@ -318,6 +333,26 @@ static bool decode_srbs_setup(const F1AP_SRBs_Setup_List_t *f1ap, int *n, f1ap_s return true; } +static bool decode_srbs_setupmod(const F1AP_SRBs_SetupMod_List_t *f1ap, int *n, f1ap_srb_setup_t **out) +{ + DevAssert(out != NULL); + *out = NULL; + int count = *n = f1ap->list.count; + if (count == 0) + return true; + + f1ap_srb_setup_t *srbs = *out = calloc_or_fail(count, sizeof(*srbs)); + for (int i = 0; i < count; ++i) { + const F1AP_SRBs_SetupMod_ItemIEs_t *itie = (F1AP_SRBs_SetupMod_ItemIEs_t *)f1ap->list.array[i]; + _F1_EQ_CHECK_LONG(itie->id, F1AP_ProtocolIE_ID_id_SRBs_SetupMod_Item); + _F1_EQ_CHECK_INT(itie->value.present, F1AP_SRBs_SetupMod_ItemIEs__value_PR_SRBs_SetupMod_Item); + const F1AP_SRBs_SetupMod_Item_t *it = &itie->value.choice.SRBs_SetupMod_Item; + srbs[i].id = it->sRBID; + srbs[i].lcid = it->lCID; + } + return true; +} + static f1ap_srb_setup_t cp_srb_setup(const f1ap_srb_setup_t *orig) { f1ap_srb_setup_t cp = {.id = orig->id, .lcid = orig->lcid}; @@ -912,6 +947,29 @@ static F1AP_DRBs_Setup_List_t encode_drbs_setup(int n, const f1ap_drb_setup_t *d return list; } +static F1AP_DRBs_SetupMod_List_t encode_drbs_setupmod(int n, const f1ap_drb_setup_t *drbs) +{ + F1AP_DRBs_SetupMod_List_t list = {0}; + for (int i = 0; i < n; ++i) { + const f1ap_drb_setup_t *drb = &drbs[i]; + asn1cSequenceAdd(list, F1AP_DRBs_SetupMod_ItemIEs_t, itie); + itie->id = F1AP_ProtocolIE_ID_id_DRBs_SetupMod_Item; + itie->criticality = F1AP_Criticality_ignore; + itie->value.present = F1AP_DRBs_SetupMod_ItemIEs__value_PR_DRBs_SetupMod_Item; + + F1AP_DRBs_SetupMod_Item_t *it = &itie->value.choice.DRBs_SetupMod_Item; + it->dRBID = drb->id; + if (drb->lcid) + asn1cCallocOne(it->lCID, *drb->lcid); + for (int j = 0; j < drb->up_dl_tnl_len; ++j) { + DevAssert(drb->up_dl_tnl[j].teid > 0); + asn1cSequenceAdd(it->dLUPTNLInformation_ToBeSetup_List.list, F1AP_DLUPTNLInformation_ToBeSetup_Item_t, tnl_it); + tnl_it->dLUPTNLInformation = encode_up_tnl(&drb->up_dl_tnl[j]); + } + } + return list; +} + static bool decode_drbs_setup(const F1AP_DRBs_Setup_List_t *f1ap, int *n, f1ap_drb_setup_t **out) { DevAssert(out != NULL); @@ -943,6 +1001,37 @@ static bool decode_drbs_setup(const F1AP_DRBs_Setup_List_t *f1ap, int *n, f1ap_d return true; } +static bool decode_drbs_setupmod(const F1AP_DRBs_SetupMod_List_t *f1ap, int *n, f1ap_drb_setup_t **out) +{ + DevAssert(out != NULL); + *out = NULL; + int count = *n = f1ap->list.count; + if (count == 0) + return true; + + f1ap_drb_setup_t *drbs = *out = calloc_or_fail(count, sizeof(*drbs)); + for (int i = 0; i < count; ++i) { + const F1AP_DRBs_SetupMod_ItemIEs_t *itie = (const F1AP_DRBs_SetupMod_ItemIEs_t *)f1ap->list.array[i]; + _F1_EQ_CHECK_LONG(itie->id, F1AP_ProtocolIE_ID_id_DRBs_SetupMod_Item); + _F1_EQ_CHECK_INT(itie->value.present, F1AP_DRBs_SetupMod_ItemIEs__value_PR_DRBs_SetupMod_Item); + const F1AP_DRBs_SetupMod_Item_t *it = &itie->value.choice.DRBs_SetupMod_Item; + + f1ap_drb_setup_t *drb = &drbs[i]; + drb->id = it->dRBID; + if (it->lCID) + _F1_MALLOC(drb->lcid, *it->lCID); + + drb->up_dl_tnl_len = it->dLUPTNLInformation_ToBeSetup_List.list.count; + _F1_EQ_CHECK_GENERIC(drb->up_dl_tnl_len > 0 && drb->up_dl_tnl_len <= 2, "%d", drb->up_dl_tnl_len, 1); + for (int j = 0; j < drb->up_dl_tnl_len; ++j) { + F1AP_DLUPTNLInformation_ToBeSetup_Item_t *it_tnl = it->dLUPTNLInformation_ToBeSetup_List.list.array[j]; + _F1_CHECK_EXP(decode_up_tnl(&it_tnl->dLUPTNLInformation, &drb->up_dl_tnl[j])); + } + } + + return true; +} + static f1ap_drb_setup_t cp_drb_setup(const f1ap_drb_setup_t *orig) { f1ap_drb_setup_t cp = { @@ -1814,3 +1903,187 @@ void free_ue_context_mod_req(f1ap_ue_context_mod_req_t *req) free(req->drbs_rel); free(req->status); } + +/** + * @brief Encode F1 UE context modification response to ASN.1 + */ +F1AP_F1AP_PDU_t *encode_ue_context_mod_resp(const f1ap_ue_context_mod_resp_t *msg) +{ + F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); + + /* Message Type */ + pdu->present = F1AP_F1AP_PDU_PR_successfulOutcome; + asn1cCalloc(pdu->choice.successfulOutcome, tmp); + tmp->procedureCode = F1AP_ProcedureCode_id_UEContextModification; + tmp->criticality = F1AP_Criticality_reject; + tmp->value.present = F1AP_SuccessfulOutcome__value_PR_UEContextModificationResponse; + F1AP_UEContextModificationResponse_t *out = &tmp->value.choice.UEContextModificationResponse; + + /* mandatory: GNB_CU_UE_F1AP_ID */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationResponseIEs_t, ie1); + ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; + ie1->criticality = F1AP_Criticality_reject; + ie1->value.present = F1AP_UEContextModificationResponseIEs__value_PR_GNB_CU_UE_F1AP_ID; + ie1->value.choice.GNB_CU_UE_F1AP_ID = msg->gNB_CU_ue_id; + + /* mandatory: GNB_DU_UE_F1AP_ID */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationResponseIEs_t, ie2); + ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; + ie2->criticality = F1AP_Criticality_reject; + ie2->value.present = F1AP_UEContextModificationResponseIEs__value_PR_GNB_DU_UE_F1AP_ID; + ie2->value.choice.GNB_DU_UE_F1AP_ID = msg->gNB_DU_ue_id; + + /* optional: DUtoCURRCInformation */ + if (msg->du_to_cu_rrc_info != NULL) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationResponseIEs_t, ie4); + ie4->id = F1AP_ProtocolIE_ID_id_DUtoCURRCInformation; + ie4->criticality = F1AP_Criticality_reject; + ie4->value.present = F1AP_UEContextModificationResponseIEs__value_PR_DUtoCURRCInformation; + ie4->value.choice.DUtoCURRCInformation = encode_du_to_cu_rrc_info(msg->du_to_cu_rrc_info); + } + + /* optional: DRBs_Setup_List */ + if (msg->drbs_len > 0) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationResponseIEs_t, ie5); + ie5->id = F1AP_ProtocolIE_ID_id_DRBs_SetupMod_List; + ie5->criticality = F1AP_Criticality_ignore; + ie5->value.present = F1AP_UEContextModificationResponseIEs__value_PR_DRBs_SetupMod_List; + ie5->value.choice.DRBs_SetupMod_List = encode_drbs_setupmod(msg->drbs_len, msg->drbs); + } + + if (msg->srbs_len > 0) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationResponseIEs_t, ie12); + ie12->id = F1AP_ProtocolIE_ID_id_SRBs_SetupMod_List; + ie12->criticality = F1AP_Criticality_ignore; + ie12->value.present = F1AP_UEContextModificationResponseIEs__value_PR_SRBs_SetupMod_List; + ie12->value.choice.SRBs_SetupMod_List = encode_srbs_setupmod(msg->srbs_len, msg->srbs); + } + + return pdu; +} + +/** + * @brief Decode F1 UE Context modification Response + */ +bool decode_ue_context_mod_resp(const struct F1AP_F1AP_PDU *pdu, f1ap_ue_context_mod_resp_t *out) +{ + DevAssert(out != NULL); + memset(out, 0, sizeof(*out)); + + F1AP_UEContextModificationResponse_t *in = &pdu->choice.successfulOutcome->value.choice.UEContextModificationResponse; + F1AP_UEContextModificationResponseIEs_t *ie; + + F1AP_LIB_FIND_IE(F1AP_UEContextModificationResponseIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); + F1AP_LIB_FIND_IE(F1AP_UEContextModificationResponseIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); + + for (int i = 0; i < in->protocolIEs.list.count; ++i) { + ie = in->protocolIEs.list.array[i]; + AssertError(ie != NULL, return false, "in->protocolIEs.list.array[i] is NULL"); + switch (ie->id) { + case F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationResponseIEs__value_PR_GNB_CU_UE_F1AP_ID); + out->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID; + break; + case F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationResponseIEs__value_PR_GNB_DU_UE_F1AP_ID); + out->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; + break; + case F1AP_ProtocolIE_ID_id_DUtoCURRCInformation: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationResponseIEs__value_PR_DUtoCURRCInformation); + out->du_to_cu_rrc_info = calloc(1, sizeof(*out->du_to_cu_rrc_info)); + _F1_CHECK_EXP(decode_du_to_cu_rrc_info(out->du_to_cu_rrc_info, &ie->value.choice.DUtoCURRCInformation)); + break; + case F1AP_ProtocolIE_ID_id_DRBs_SetupMod_List: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationResponseIEs__value_PR_DRBs_SetupMod_List); + _F1_CHECK_EXP(decode_drbs_setupmod(&ie->value.choice.DRBs_SetupMod_List, &out->drbs_len, &out->drbs)); + break; + case F1AP_ProtocolIE_ID_id_SRBs_SetupMod_List: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationResponseIEs__value_PR_SRBs_SetupMod_List); + _F1_CHECK_EXP(decode_srbs_setupmod(&ie->value.choice.SRBs_SetupMod_List, &out->srbs_len, &out->srbs)); + break; + default: + PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld unknown, skipping\n", ie->id); + break; + } + } + + return true; +} + +/** + * @brief F1 UE Context modification Response deep copy + */ +f1ap_ue_context_mod_resp_t cp_ue_context_mod_resp(const f1ap_ue_context_mod_resp_t *orig) +{ + f1ap_ue_context_mod_resp_t cp = { + .gNB_CU_ue_id = orig->gNB_CU_ue_id, + .gNB_DU_ue_id = orig->gNB_DU_ue_id, + // du_to_cu_rrc_info + .drbs_len = orig->drbs_len, + // drbs below + .srbs_len = orig->srbs_len, + // srbs below + }; + + if (orig->du_to_cu_rrc_info) { + f1ap_du_to_cu_rrc_info_t du2cu = cp_du_to_cu_rrc_info(orig->du_to_cu_rrc_info); + _F1_MALLOC(cp.du_to_cu_rrc_info, du2cu); + } + + if (orig->drbs_len > 0) { + DevAssert(orig->drbs); + cp.drbs = calloc_or_fail(orig->drbs_len, sizeof(*cp.drbs)); + cp.drbs_len = orig->drbs_len; + for (int i = 0; i < cp.drbs_len; ++i) + cp.drbs[i] = cp_drb_setup(&orig->drbs[i]); + } + + if (orig->srbs_len > 0) { + DevAssert(orig->srbs); + cp.srbs = calloc_or_fail(orig->srbs_len, sizeof(*cp.srbs)); + cp.srbs_len = orig->srbs_len; + for (int i = 0; i < cp.srbs_len; ++i) + cp.srbs[i] = cp_srb_setup(&orig->srbs[i]); + } + + return cp; +} + +/** + * @brief F1 UE Context modification Response equality check + */ +bool eq_ue_context_mod_resp(const f1ap_ue_context_mod_resp_t *a, const f1ap_ue_context_mod_resp_t *b) +{ + _F1_EQ_CHECK_INT(a->gNB_CU_ue_id, b->gNB_CU_ue_id); + _F1_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id); + //_F1_EQ_CHECK_OPTIONAL_IE(a, b, du_to_cu_rrc_info, eq_du_to_cu_rrc_info); + _F1_CHECK_EXP((a->du_to_cu_rrc_info && b->du_to_cu_rrc_info) || (!a->du_to_cu_rrc_info && !b->du_to_cu_rrc_info)); + _F1_CHECK_EXP(!a->du_to_cu_rrc_info || eq_du_to_cu_rrc_info(a->du_to_cu_rrc_info, b->du_to_cu_rrc_info)); + + _F1_CHECK_EXP(a->drbs_len == 0 || (a->drbs && b->drbs)); + for (int i = 0; i < a->drbs_len; ++i) + _F1_CHECK_EXP(eq_drb_setup(&a->drbs[i], &b->drbs[i])); + + _F1_EQ_CHECK_INT(a->srbs_len, b->srbs_len); + _F1_CHECK_EXP(a->srbs_len == 0 || (a->srbs && b->srbs)); + for (int i = 0; i < a->srbs_len; ++i) + _F1_CHECK_EXP(eq_srb_setup(&a->srbs[i], &b->srbs[i])); + + return true; +} + +/** + * @brief Free Allocated F1 UE Context modification Response + */ +void free_ue_context_mod_resp(f1ap_ue_context_mod_resp_t *resp) +{ + if (resp->du_to_cu_rrc_info) + free_du_to_cu_rrc_info(resp->du_to_cu_rrc_info); + free(resp->du_to_cu_rrc_info); + for (int i = 0; i < resp->drbs_len; ++i) + free_drb_setup(&resp->drbs[i]); + free(resp->drbs); + for (int i = 0; i < resp->srbs_len; ++i) + free_srb_setup(&resp->srbs[i]); + free(resp->srbs); +} diff --git a/openair2/F1AP/lib/f1ap_ue_context.h b/openair2/F1AP/lib/f1ap_ue_context.h index 3afb96fcc4..ddf41689e0 100644 --- a/openair2/F1AP/lib/f1ap_ue_context.h +++ b/openair2/F1AP/lib/f1ap_ue_context.h @@ -45,4 +45,10 @@ f1ap_ue_context_mod_req_t cp_ue_context_mod_req(const f1ap_ue_context_mod_req_t bool eq_ue_context_mod_req(const f1ap_ue_context_mod_req_t *a, const f1ap_ue_context_mod_req_t *b); void free_ue_context_mod_req(f1ap_ue_context_mod_req_t *req); +struct F1AP_F1AP_PDU *encode_ue_context_mod_resp(const f1ap_ue_context_mod_resp_t *msg); +bool decode_ue_context_mod_resp(const struct F1AP_F1AP_PDU *pdu, f1ap_ue_context_mod_resp_t *out); +f1ap_ue_context_mod_resp_t cp_ue_context_mod_resp(const f1ap_ue_context_mod_resp_t *orig); +bool eq_ue_context_mod_resp(const f1ap_ue_context_mod_resp_t *a, const f1ap_ue_context_mod_resp_t *b); +void free_ue_context_mod_resp(f1ap_ue_context_mod_resp_t *resp); + #endif /* F1AP_UE_CONTEXT_SETUP_REQ_H_ */ diff --git a/openair2/F1AP/tests/f1ap_lib_test.c b/openair2/F1AP/tests/f1ap_lib_test.c index 0b0511c6bb..5baac1f5c6 100644 --- a/openair2/F1AP/tests/f1ap_lib_test.c +++ b/openair2/F1AP/tests/f1ap_lib_test.c @@ -1089,6 +1089,88 @@ static void test_f1ap_ue_context_modification_request_simple() printf("%s() successful\n", __func__); } +static void test_f1ap_ue_context_modification_response() +{ + f1ap_ue_context_mod_resp_t orig = { + .gNB_CU_ue_id = 9876, + .gNB_DU_ue_id = 5432, + // rest below + }; + + f1ap_du_to_cu_rrc_info_t cu2du = { + .cell_group_config = get_test_ba("update for the cellgroupconfig, extra long"), + .meas_gap_config = get_malloced_test_ba("new and shiny MeAs GaP cOnFiG"), + }; + _F1_MALLOC(orig.du_to_cu_rrc_info, cu2du); + + orig.drbs_len = 1; + orig.drbs = calloc_or_fail(orig.drbs_len, sizeof(*orig.drbs)); + f1ap_drb_setup_t *drb1 = &orig.drbs[0]; + drb1->id = 4; + _F1_MALLOC(drb1->lcid, 7); + drb1->up_dl_tnl_len = 1; + inet_pton(AF_INET, "127.0.0.1", &drb1->up_dl_tnl[0].tl_address); + drb1->up_dl_tnl[0].teid = 0xcafe; + + orig.srbs_len = 2; + orig.srbs = calloc_or_fail(orig.srbs_len, sizeof(*orig.srbs)); + orig.srbs[0].id = 1; + orig.srbs[0].lcid = 1; + orig.srbs[1].id = 2; + orig.srbs[1].lcid = 2; + + F1AP_F1AP_PDU_t *f1enc = encode_ue_context_mod_resp(&orig); + F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + + f1ap_ue_context_mod_resp_t decoded = {0}; + bool ret = decode_ue_context_mod_resp(f1dec, &decoded); + AssertFatal(ret, "decode_ue_context_mod_resp(): could not decode message\n"); + f1ap_msg_free(f1dec); + + ret = eq_ue_context_mod_resp(&orig, &decoded); + AssertFatal(ret, "eq_ue_context_mod_resp(): decoded message doesn't match\n"); + free_ue_context_mod_resp(&decoded); + + f1ap_ue_context_mod_resp_t cp = cp_ue_context_mod_resp(&orig); + ret = eq_ue_context_mod_resp(&orig, &cp); + AssertFatal(ret, "eq_ue_context_mod_resp(): copied message doesn't match\n"); + free_ue_context_mod_resp(&orig); + free_ue_context_mod_resp(&cp); + + printf("%s() successful\n", __func__); +} + +static void test_f1ap_ue_context_modification_response_simple() +{ + f1ap_ue_context_mod_resp_t orig = { + .gNB_CU_ue_id = 9876, + .gNB_DU_ue_id = 5432, + // rest is optional and intentionally left out + }; + + F1AP_F1AP_PDU_t *f1enc = encode_ue_context_mod_resp(&orig); + F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + + f1ap_ue_context_mod_resp_t decoded = {0}; + bool ret = decode_ue_context_mod_resp(f1dec, &decoded); + AssertFatal(ret, "decode_ue_context_mod_resp(): could not decode message\n"); + f1ap_msg_free(f1dec); + + ret = eq_ue_context_mod_resp(&orig, &decoded); + AssertFatal(ret, "eq_ue_context_mod_resp(): decoded message doesn't match\n"); + free_ue_context_mod_resp(&decoded); + + f1ap_ue_context_mod_resp_t cp = cp_ue_context_mod_resp(&orig); + ret = eq_ue_context_mod_resp(&orig, &cp); + AssertFatal(ret, "eq_ue_context_mod_resp(): copied message doesn't match\n"); + free_ue_context_mod_resp(&orig); + free_ue_context_mod_resp(&cp); + + printf("%s() successful\n", __func__); +} + int main() { test_initial_ul_rrc_message_transfer(); @@ -1110,5 +1192,7 @@ int main() test_f1ap_ue_context_setup_response_simple(); test_f1ap_ue_context_modification_request(); test_f1ap_ue_context_modification_request_simple(); + test_f1ap_ue_context_modification_response(); + test_f1ap_ue_context_modification_response_simple(); return 0; } From 04b5e1d7da37533229de79f5f0578042a6375429 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 27 Jun 2025 11:46:15 +0200 Subject: [PATCH 124/964] Use F1 UE context setup/mod Response in stack Similarly to the commit "Use F1 UE context setup/modif Request in stack", we do both UE context setup/modification response at once because of some functions that are shared by the MAC message handler. --- openair2/COMMON/f1ap_messages_def.h | 4 +- openair2/COMMON/f1ap_messages_types.h | 73 -- openair2/F1AP/f1ap_cu_ue_context_management.c | 258 +------ openair2/F1AP/f1ap_du_task.c | 1 + openair2/F1AP/f1ap_du_ue_context_management.c | 658 +----------------- openair2/F1AP/f1ap_du_ue_context_management.h | 4 +- .../LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c | 97 +-- openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h | 4 +- .../LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c | 81 +-- openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c | 69 +- openair2/RRC/NR/nr_rrc_proto.h | 2 +- openair2/RRC/NR/rrc_gNB.c | 62 +- openair2/RRC/NR/rrc_gNB_nsa.c | 10 +- 13 files changed, 112 insertions(+), 1211 deletions(-) diff --git a/openair2/COMMON/f1ap_messages_def.h b/openair2/COMMON/f1ap_messages_def.h index c713361aa5..5681848029 100644 --- a/openair2/COMMON/f1ap_messages_def.h +++ b/openair2/COMMON/f1ap_messages_def.h @@ -57,9 +57,9 @@ MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_REQUIRED, MESSAGE_PRIORITY_MED, f1ap_ue MESSAGE_DEF(F1AP_DL_RRC_MESSAGE , MESSAGE_PRIORITY_MED, f1ap_dl_rrc_message_t , f1ap_dl_rrc_message ) //MESSAGE_DEF(F1AP_INITIAL_CONTEXT_SETUP_REQ , MESSAGE_PRIORITY_MED, f1ap_initial_context_setup_req_t , f1ap_initial_context_setup_req ) MESSAGE_DEF(F1AP_UE_CONTEXT_SETUP_REQ, MESSAGE_PRIORITY_MED, f1ap_ue_context_setup_req_t, f1ap_ue_context_setup_req) -MESSAGE_DEF(F1AP_UE_CONTEXT_SETUP_RESP, MESSAGE_PRIORITY_MED, f1ap_ue_context_setup_t, f1ap_ue_context_setup_resp) +MESSAGE_DEF(F1AP_UE_CONTEXT_SETUP_RESP, MESSAGE_PRIORITY_MED, f1ap_ue_context_setup_resp_t, f1ap_ue_context_setup_resp) MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_REQ, MESSAGE_PRIORITY_MED, f1ap_ue_context_mod_req_t, f1ap_ue_context_mod_req) -MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_RESP, MESSAGE_PRIORITY_MED, f1ap_ue_context_modif_resp_t, f1ap_ue_context_modification_resp) +MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_RESP, MESSAGE_PRIORITY_MED, f1ap_ue_context_mod_resp_t, f1ap_ue_context_modification_resp) MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_CONFIRM, MESSAGE_PRIORITY_MED, f1ap_ue_context_modif_confirm_t, f1ap_ue_context_modification_confirm) MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_REFUSE, MESSAGE_PRIORITY_MED, f1ap_ue_context_modif_refuse_t, f1ap_ue_context_modification_refuse) diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h index 396b0837b7..9394daa7f0 100644 --- a/openair2/COMMON/f1ap_messages_types.h +++ b/openair2/COMMON/f1ap_messages_types.h @@ -418,40 +418,6 @@ typedef struct f1ap_drb_information_s { } f1ap_drb_information_t; typedef enum f1ap_rlc_mode_t { F1AP_RLC_MODE_AM, F1AP_RLC_MODE_UM_BIDIR, F1AP_RLC_UM_UNI_UL, F1AP_RLC_UM_UNI_DL } f1ap_rlc_mode_t; -typedef struct f1ap_drb_to_be_setup_s { - long drb_id; - f1ap_up_tnl_t up_ul_tnl[2]; - uint8_t up_ul_tnl_length; - f1ap_up_tnl_t up_dl_tnl[2]; - uint8_t up_dl_tnl_length; - f1ap_drb_information_t drb_info; - f1ap_rlc_mode_t rlc_mode; - nssai_t nssai; -} f1ap_drb_to_be_setup_t; - -typedef struct f1ap_srb_to_be_setup_s { - long srb_id; - uint8_t lcid; -} f1ap_srb_to_be_setup_t; - -typedef struct f1ap_rb_failed_to_be_setup_s { - long rb_id; -} f1ap_rb_failed_to_be_setup_t; - -typedef struct f1ap_drb_to_be_released_t { - long rb_id; -} f1ap_drb_to_be_released_t; - -typedef struct cu_to_du_rrc_information_s { - uint8_t * cG_ConfigInfo; - uint32_t cG_ConfigInfo_length; - uint8_t * uE_CapabilityRAT_ContainerList; - uint32_t uE_CapabilityRAT_ContainerList_length; - uint8_t * measConfig; - uint32_t measConfig_length; - uint8_t *handoverPreparationInfo; - uint32_t handoverPreparationInfo_length; -}cu_to_du_rrc_information_t; typedef struct f1ap_cu_to_du_rrc_info_s { byte_array_t *cg_configinfo; @@ -474,11 +440,6 @@ typedef struct du_to_cu_rrc_information_s { uint32_t requestedP_MaxFR1_length; }du_to_cu_rrc_information_t; -typedef enum QoS_information_e { - NG_RAN_QoS = 0, - EUTRAN_QoS = 1, -} QoS_information_t; - typedef enum ReconfigurationCompl_e { RRCreconf_info_not_present = 0, RRCreconf_failure = 1, @@ -658,40 +619,6 @@ typedef struct f1ap_ue_context_mod_resp { f1ap_srb_setup_t *srbs; } f1ap_ue_context_mod_resp_t; -typedef struct f1ap_ue_context_setup_s { - uint32_t gNB_CU_ue_id; - uint32_t gNB_DU_ue_id; - // SpCell Info - plmn_id_t plmn; - uint64_t nr_cellid; - uint8_t servCellIndex; - uint8_t *cellULConfigured; - uint32_t servCellId; - cu_to_du_rrc_information_t *cu_to_du_rrc_information; - uint8_t cu_to_du_rrc_information_length; - //uint8_t *du_to_cu_rrc_information; - du_to_cu_rrc_information_t *du_to_cu_rrc_information; - uint32_t du_to_cu_rrc_information_length; - uint16_t *crnti; - f1ap_drb_to_be_setup_t *drbs_to_be_setup; - uint8_t drbs_to_be_setup_length; - f1ap_drb_to_be_setup_t *drbs_to_be_modified; - uint8_t drbs_to_be_modified_length; - QoS_information_t QoS_information_type; - uint8_t drbs_failed_to_be_setup_length; - f1ap_rb_failed_to_be_setup_t *drbs_failed_to_be_setup; - f1ap_srb_to_be_setup_t *srbs_to_be_setup; - uint8_t srbs_to_be_setup_length; - uint8_t srbs_failed_to_be_setup_length; - uint8_t drbs_to_be_released_length; - f1ap_drb_to_be_released_t *drbs_to_be_released; - f1ap_rb_failed_to_be_setup_t *srbs_failed_to_be_setup; - ReconfigurationCompl_t ReconfigComplOutcome; - uint8_t *rrc_container; - int rrc_container_length; - TransmActionInd_t *transm_action_ind; -} f1ap_ue_context_setup_t, f1ap_ue_context_modif_resp_t; - typedef enum F1ap_Cause_e { F1AP_CAUSE_NOTHING, /* No components present */ F1AP_CAUSE_RADIO_NETWORK, diff --git a/openair2/F1AP/f1ap_cu_ue_context_management.c b/openair2/F1AP/f1ap_cu_ue_context_management.c index 9dc9e8c086..597c20d258 100644 --- a/openair2/F1AP/f1ap_cu_ue_context_management.c +++ b/openair2/F1AP/f1ap_cu_ue_context_management.c @@ -69,134 +69,16 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, const f1ap_ue_contex int CU_handle_UE_CONTEXT_SETUP_RESPONSE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { - MessageDef *msg_p; - F1AP_UEContextSetupResponse_t *container; - F1AP_UEContextSetupResponseIEs_t *ie; - DevAssert(pdu); - msg_p = itti_alloc_new_message(TASK_DU_F1, 0, F1AP_UE_CONTEXT_SETUP_RESP); - msg_p->ittiMsgHeader.originInstance = assoc_id; - f1ap_ue_context_setup_t *f1ap_ue_context_setup_resp = &F1AP_UE_CONTEXT_SETUP_RESP(msg_p); - container = &pdu->choice.successfulOutcome->value.choice.UEContextSetupResponse; - int i; - /* GNB_CU_UE_F1AP_ID */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupResponseIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); - f1ap_ue_context_setup_resp->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID; - LOG_D(F1AP, "f1ap_ue_context_setup_resp->gNB_CU_ue_id is: %d \n", f1ap_ue_context_setup_resp->gNB_CU_ue_id); - /* GNB_DU_UE_F1AP_ID */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupResponseIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); - f1ap_ue_context_setup_resp->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; - LOG_D(F1AP, "f1ap_ue_context_setup_resp->gNB_DU_ue_id is: %d \n", f1ap_ue_context_setup_resp->gNB_DU_ue_id); - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupResponseIEs_t, ie, container, F1AP_ProtocolIE_ID_id_C_RNTI, false); - if (ie) { - f1ap_ue_context_setup_resp->crnti = calloc(1, sizeof(uint16_t)); - *f1ap_ue_context_setup_resp->crnti = ie->value.choice.C_RNTI; - } - - // DUtoCURRCInformation - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupResponseIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_DUtoCURRCInformation, true); - - if (ie == NULL) { - LOG_E(F1AP,"%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); + f1ap_ue_context_setup_resp_t resp = {0}; + if (!decode_ue_context_setup_resp(pdu, &resp)) { + LOG_E(F1AP, "cannot decode F1 UE Context Setup Resp\n"); + free_ue_context_setup_resp(&resp); return -1; } - f1ap_ue_context_setup_resp->du_to_cu_rrc_information = (du_to_cu_rrc_information_t *)calloc(1,sizeof(du_to_cu_rrc_information_t)); - f1ap_ue_context_setup_resp->du_to_cu_rrc_information->cellGroupConfig = (uint8_t *)calloc(1,ie->value.choice.DUtoCURRCInformation.cellGroupConfig.size); - memcpy(f1ap_ue_context_setup_resp->du_to_cu_rrc_information->cellGroupConfig, ie->value.choice.DUtoCURRCInformation.cellGroupConfig.buf, ie->value.choice.DUtoCURRCInformation.cellGroupConfig.size); - f1ap_ue_context_setup_resp->du_to_cu_rrc_information->cellGroupConfig_length = ie->value.choice.DUtoCURRCInformation.cellGroupConfig.size; - // DRBs_Setup_List - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupResponseIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_DRBs_Setup_List, false); - - if(ie!=NULL) { - f1ap_ue_context_setup_resp->drbs_to_be_setup_length = ie->value.choice.DRBs_Setup_List.list.count; - f1ap_ue_context_setup_resp->drbs_to_be_setup = calloc(f1ap_ue_context_setup_resp->drbs_to_be_setup_length, - sizeof(f1ap_drb_to_be_setup_t)); - AssertFatal(f1ap_ue_context_setup_resp->drbs_to_be_setup, - "could not allocate memory for f1ap_ue_context_setup_resp->drbs_setup\n"); - - for (i = 0; i < f1ap_ue_context_setup_resp->drbs_to_be_setup_length; ++i) { - f1ap_drb_to_be_setup_t *drb_p = &f1ap_ue_context_setup_resp->drbs_to_be_setup[i]; - F1AP_DRBs_Setup_Item_t *drbs_setup_item_p; - drbs_setup_item_p = &((F1AP_DRBs_Setup_ItemIEs_t *)ie->value.choice.DRBs_Setup_List.list.array[i])->value.choice.DRBs_Setup_Item; - drb_p->drb_id = drbs_setup_item_p->dRBID; - // TODO in the following, assume only one UP UL TNL is present. - // this matches/assumes OAI CU/DU implementation, can be up to 2! - drb_p->up_dl_tnl_length = 1; - AssertFatal(drbs_setup_item_p->dLUPTNLInformation_ToBeSetup_List.list.count > 0, - "no DL UP TNL Information in DRBs to be Setup list\n"); - F1AP_DLUPTNLInformation_ToBeSetup_Item_t *dl_up_tnl_info_p = (F1AP_DLUPTNLInformation_ToBeSetup_Item_t *)drbs_setup_item_p->dLUPTNLInformation_ToBeSetup_List.list.array[0]; - F1AP_GTPTunnel_t *dl_up_tnl0 = dl_up_tnl_info_p->dLUPTNLInformation.choice.gTPTunnel; - BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&dl_up_tnl0->transportLayerAddress, drb_p->up_dl_tnl[0].tl_address); - OCTET_STRING_TO_UINT32(&dl_up_tnl0->gTP_TEID, drb_p->up_dl_tnl[0].teid); - } - } - - // SRBs_FailedToBeSetup_List - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupResponseIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_SRBs_FailedToBeSetup_List, false); - - if(ie!=NULL) { - f1ap_ue_context_setup_resp->srbs_failed_to_be_setup_length = ie->value.choice.SRBs_FailedToBeSetup_List.list.count; - f1ap_ue_context_setup_resp->srbs_failed_to_be_setup = calloc(f1ap_ue_context_setup_resp->srbs_failed_to_be_setup_length, - sizeof(f1ap_rb_failed_to_be_setup_t)); - AssertFatal(f1ap_ue_context_setup_resp->srbs_failed_to_be_setup, - "could not allocate memory for f1ap_ue_context_setup_resp->srbs_failed_to_be_setup\n"); - - for (i = 0; i < f1ap_ue_context_setup_resp->srbs_failed_to_be_setup_length; ++i) { - f1ap_rb_failed_to_be_setup_t *srb_p = &f1ap_ue_context_setup_resp->srbs_failed_to_be_setup[i]; - srb_p->rb_id = ((F1AP_SRBs_FailedToBeSetup_Item_t *)ie->value.choice.SRBs_FailedToBeSetup_List.list.array[i])->sRBID; - } - } - - // DRBs_FailedToBeSetup_List - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupResponseIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_DRBs_FailedToBeSetup_List, false); - - if(ie!=NULL) { - f1ap_ue_context_setup_resp->drbs_failed_to_be_setup_length = ie->value.choice.DRBs_FailedToBeSetup_List.list.count; - f1ap_ue_context_setup_resp->drbs_failed_to_be_setup = calloc(f1ap_ue_context_setup_resp->drbs_failed_to_be_setup_length, - sizeof(f1ap_rb_failed_to_be_setup_t)); - AssertFatal(f1ap_ue_context_setup_resp->drbs_failed_to_be_setup, - "could not allocate memory for f1ap_ue_context_setup_resp->drbs_failed_to_be_setup\n"); - - for (i = 0; i < f1ap_ue_context_setup_resp->drbs_failed_to_be_setup_length; ++i) { - f1ap_rb_failed_to_be_setup_t *drb_p = &f1ap_ue_context_setup_resp->drbs_failed_to_be_setup[i]; - drb_p->rb_id = ((F1AP_DRBs_FailedToBeSetup_Item_t *)ie->value.choice.DRBs_FailedToBeSetup_List.list.array[i])->dRBID; - } - } - - // SCell_FailedtoSetup_List - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupResponseIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_SCell_FailedtoSetup_List, false); - - if(ie!=NULL) { - LOG_E (F1AP, "Not supporting handling of SCell_FailedtoSetup_List \n"); - } - - // SRBs_Setup_List - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupResponseIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_SRBs_Setup_List, false); - - if(ie!=NULL) { - f1ap_ue_context_setup_resp->srbs_to_be_setup_length = ie->value.choice.SRBs_Setup_List.list.count; - f1ap_ue_context_setup_resp->srbs_to_be_setup = calloc(f1ap_ue_context_setup_resp->srbs_to_be_setup_length, - sizeof(f1ap_srb_to_be_setup_t)); - AssertFatal(f1ap_ue_context_setup_resp->srbs_to_be_setup, - "could not allocate memory for f1ap_ue_context_setup_resp->drbs_setup\n"); - - for (i = 0; i < f1ap_ue_context_setup_resp->srbs_to_be_setup_length; ++i) { - f1ap_srb_to_be_setup_t *srb_p = &f1ap_ue_context_setup_resp->srbs_to_be_setup[i]; - F1AP_SRBs_Setup_Item_t *srbs_setup_item_p; - srbs_setup_item_p = &((F1AP_SRBs_Setup_ItemIEs_t *)ie->value.choice.SRBs_Setup_List.list.array[i])->value.choice.SRBs_Setup_Item; - srb_p->srb_id = srbs_setup_item_p->sRBID; - srb_p->lcid = srbs_setup_item_p->lCID; - } - } - + MessageDef *msg_p = itti_alloc_new_message(TASK_DU_F1, 0, F1AP_UE_CONTEXT_SETUP_RESP); + msg_p->ittiMsgHeader.originInstance = assoc_id; + F1AP_UE_CONTEXT_SETUP_RESP(msg_p) = resp; itti_send_msg_to_task(TASK_RRC_GNB, instance, msg_p); return 0; } @@ -407,123 +289,17 @@ int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc_id, const f1ap_ue int CU_handle_UE_CONTEXT_MODIFICATION_RESPONSE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { - MessageDef *msg_p; - F1AP_UEContextModificationResponse_t *container; - F1AP_UEContextModificationResponseIEs_t *ie; - DevAssert(pdu); - msg_p = itti_alloc_new_message(TASK_DU_F1, 0, F1AP_UE_CONTEXT_MODIFICATION_RESP); + f1ap_ue_context_mod_resp_t resp = {0}; + if (!decode_ue_context_mod_resp(pdu, &resp)) { + LOG_E(F1AP, "cannot decode F1 UE Context Modification Response\n"); + free_ue_context_mod_resp(&resp); + return -1; + } + MessageDef *msg_p = itti_alloc_new_message(TASK_DU_F1, 0, F1AP_UE_CONTEXT_MODIFICATION_RESP); msg_p->ittiMsgHeader.originInstance = assoc_id; - f1ap_ue_context_modif_resp_t *f1ap_ue_context_modification_resp = &F1AP_UE_CONTEXT_MODIFICATION_RESP(msg_p); - container = &pdu->choice.successfulOutcome->value.choice.UEContextModificationResponse; - int i; - - /* GNB_CU_UE_F1AP_ID */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationResponseIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); - f1ap_ue_context_modification_resp->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID; - - LOG_D(F1AP, "f1ap_ue_context_modif_resp->gNB_CU_ue_id is: %d \n", f1ap_ue_context_modification_resp->gNB_CU_ue_id); - - /* GNB_DU_UE_F1AP_ID */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationResponseIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); - f1ap_ue_context_modification_resp->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; - - LOG_D(F1AP, "f1ap_ue_context_modification_resp->gNB_DU_ue_id is: %d \n", f1ap_ue_context_modification_resp->gNB_DU_ue_id); - - // DUtoCURRCInformation - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationResponseIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_DUtoCURRCInformation, false); - if(ie!=NULL){ - f1ap_ue_context_modification_resp->du_to_cu_rrc_information = (du_to_cu_rrc_information_t *)calloc(1, sizeof(du_to_cu_rrc_information_t)); - f1ap_ue_context_modification_resp->du_to_cu_rrc_information->cellGroupConfig = (uint8_t *)calloc(1,ie->value.choice.DUtoCURRCInformation.cellGroupConfig.size); - - memcpy(f1ap_ue_context_modification_resp->du_to_cu_rrc_information->cellGroupConfig, ie->value.choice.DUtoCURRCInformation.cellGroupConfig.buf, ie->value.choice.DUtoCURRCInformation.cellGroupConfig.size); - f1ap_ue_context_modification_resp->du_to_cu_rrc_information->cellGroupConfig_length = ie->value.choice.DUtoCURRCInformation.cellGroupConfig.size; - } - - // DRBs_SetupMod_List - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationResponseIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_DRBs_SetupMod_List, false); - if(ie!=NULL){ - f1ap_ue_context_modification_resp->drbs_to_be_setup_length = ie->value.choice.DRBs_SetupMod_List.list.count; - f1ap_ue_context_modification_resp->drbs_to_be_setup = calloc(f1ap_ue_context_modification_resp->drbs_to_be_setup_length, - sizeof(f1ap_drb_to_be_setup_t)); - AssertFatal(f1ap_ue_context_modification_resp->drbs_to_be_setup, - "could not allocate memory for f1ap_ue_context_setup_resp->drbs_setup\n"); - for (i = 0; i < f1ap_ue_context_modification_resp->drbs_to_be_setup_length; ++i) { - f1ap_drb_to_be_setup_t *drb_p = &f1ap_ue_context_modification_resp->drbs_to_be_setup[i]; - F1AP_DRBs_SetupMod_Item_t *drbs_setupmod_item_p; - drbs_setupmod_item_p = &((F1AP_DRBs_SetupMod_ItemIEs_t *)ie->value.choice.DRBs_SetupMod_List.list.array[i])->value.choice.DRBs_SetupMod_Item; - drb_p->drb_id = drbs_setupmod_item_p->dRBID; - // TODO in the following, assume only one UP UL TNL is present. - // this matches/assumes OAI CU/DU implementation, can be up to 2! - drb_p->up_dl_tnl_length = 1; - AssertFatal(drbs_setupmod_item_p->dLUPTNLInformation_ToBeSetup_List.list.count > 0, - "no DL UP TNL Information in DRBs to be Setup list\n"); - F1AP_DLUPTNLInformation_ToBeSetup_Item_t *dl_up_tnl_info_p = (F1AP_DLUPTNLInformation_ToBeSetup_Item_t *)drbs_setupmod_item_p->dLUPTNLInformation_ToBeSetup_List.list.array[0]; - F1AP_GTPTunnel_t *dl_up_tnl0 = dl_up_tnl_info_p->dLUPTNLInformation.choice.gTPTunnel; - BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&dl_up_tnl0->transportLayerAddress, drb_p->up_dl_tnl[0].tl_address); - OCTET_STRING_TO_UINT32(&dl_up_tnl0->gTP_TEID, drb_p->up_dl_tnl[0].teid); - } - } - // SRBs_FailedToBeSetupMod_List - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationResponseIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_SRBs_FailedToBeSetupMod_List, false); - if(ie!=NULL){ - f1ap_ue_context_modification_resp->srbs_failed_to_be_setup_length = ie->value.choice.SRBs_FailedToBeSetupMod_List.list.count; - f1ap_ue_context_modification_resp->srbs_failed_to_be_setup = calloc(f1ap_ue_context_modification_resp->srbs_failed_to_be_setup_length, - sizeof(f1ap_rb_failed_to_be_setup_t)); - AssertFatal(f1ap_ue_context_modification_resp->srbs_failed_to_be_setup, - "could not allocate memory for f1ap_ue_context_setup_resp->srbs_failed_to_be_setup\n"); - for (i = 0; i < f1ap_ue_context_modification_resp->srbs_failed_to_be_setup_length; ++i) { - f1ap_rb_failed_to_be_setup_t *srb_p = &f1ap_ue_context_modification_resp->srbs_failed_to_be_setup[i]; - srb_p->rb_id = ((F1AP_SRBs_FailedToBeSetupMod_Item_t *)ie->value.choice.SRBs_FailedToBeSetupMod_List.list.array[i])->sRBID; - } - - } - // DRBs_FailedToBeSetupMod_List - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationResponseIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_DRBs_FailedToBeSetupMod_List, false); - if(ie!=NULL){ - f1ap_ue_context_modification_resp->drbs_failed_to_be_setup_length = ie->value.choice.DRBs_FailedToBeSetupMod_List.list.count; - f1ap_ue_context_modification_resp->drbs_failed_to_be_setup = calloc(f1ap_ue_context_modification_resp->drbs_failed_to_be_setup_length, - sizeof(f1ap_rb_failed_to_be_setup_t)); - AssertFatal(f1ap_ue_context_modification_resp->drbs_failed_to_be_setup, - "could not allocate memory for f1ap_ue_context_setup_resp->drbs_failed_to_be_setup\n"); - for (i = 0; i < f1ap_ue_context_modification_resp->drbs_failed_to_be_setup_length; ++i) { - f1ap_rb_failed_to_be_setup_t *drb_p = &f1ap_ue_context_modification_resp->drbs_failed_to_be_setup[i]; - drb_p->rb_id = ((F1AP_DRBs_FailedToBeSetupMod_Item_t *)ie->value.choice.DRBs_FailedToBeSetupMod_List.list.array[i])->dRBID; - } - } - - // SCell_FailedtoSetupMod_List - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationResponseIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_SCell_FailedtoSetupMod_List, false); - if(ie!=NULL){ - LOG_E (F1AP, "Not supporting handling of SCell_FailedtoSetupMod_List \n"); - } - - // SRBs_Setup_List - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationResponseIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_SRBs_SetupMod_List, false); - if(ie!=NULL){ - f1ap_ue_context_modification_resp->srbs_to_be_setup_length = ie->value.choice.SRBs_SetupMod_List.list.count; - f1ap_ue_context_modification_resp->srbs_to_be_setup = calloc(f1ap_ue_context_modification_resp->srbs_to_be_setup_length, - sizeof(f1ap_srb_to_be_setup_t)); - AssertFatal(f1ap_ue_context_modification_resp->srbs_to_be_setup, - "could not allocate memory for f1ap_ue_context_setup_resp->drbs_setup\n"); - for (i = 0; i < f1ap_ue_context_modification_resp->srbs_to_be_setup_length; ++i) { - f1ap_srb_to_be_setup_t *srb_p = &f1ap_ue_context_modification_resp->srbs_to_be_setup[i]; - F1AP_SRBs_SetupMod_Item_t *srbs_setup_item_p; - srbs_setup_item_p = &((F1AP_SRBs_SetupMod_ItemIEs_t *)ie->value.choice.SRBs_SetupMod_List.list.array[i])->value.choice.SRBs_SetupMod_Item; - srb_p->srb_id = srbs_setup_item_p->sRBID; - srb_p->lcid = srbs_setup_item_p->lCID; - } - } - - itti_send_msg_to_task(TASK_RRC_GNB, instance, msg_p); - return 0; + F1AP_UE_CONTEXT_MODIFICATION_RESP(msg_p) = resp; + itti_send_msg_to_task(TASK_RRC_GNB, instance, msg_p); + return 0; } int CU_handle_UE_CONTEXT_MODIFICATION_FAILURE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) diff --git a/openair2/F1AP/f1ap_du_task.c b/openair2/F1AP/f1ap_du_task.c index cd76933d44..94b4befb76 100644 --- a/openair2/F1AP/f1ap_du_task.c +++ b/openair2/F1AP/f1ap_du_task.c @@ -189,6 +189,7 @@ void *F1AP_DU_task(void *arg) { case F1AP_UE_CONTEXT_SETUP_RESP: DU_send_UE_CONTEXT_SETUP_RESPONSE(assoc_id, &F1AP_UE_CONTEXT_SETUP_RESP(msg)); + free_ue_context_setup_resp(&F1AP_UE_CONTEXT_SETUP_RESP(msg)); break; case F1AP_UE_CONTEXT_MODIFICATION_RESP: diff --git a/openair2/F1AP/f1ap_du_ue_context_management.c b/openair2/F1AP/f1ap_du_ue_context_management.c index 13c9e92ec5..e6d36f9019 100644 --- a/openair2/F1AP/f1ap_du_ue_context_management.c +++ b/openair2/F1AP/f1ap_du_ue_context_management.c @@ -55,344 +55,19 @@ int DU_handle_UE_CONTEXT_SETUP_REQUEST(instance_t instance, sctp_assoc_t assoc_i return 0; } -int DU_send_UE_CONTEXT_SETUP_RESPONSE(sctp_assoc_t assoc_id, f1ap_ue_context_setup_t *resp) +int DU_send_UE_CONTEXT_SETUP_RESPONSE(sctp_assoc_t assoc_id, f1ap_ue_context_setup_resp_t *resp) { - F1AP_F1AP_PDU_t pdu= {0}; - F1AP_UEContextSetupResponse_t *out; - uint8_t *buffer=NULL; - uint32_t len=0; - /* Create */ - /* 0. Message Type */ - pdu.present = F1AP_F1AP_PDU_PR_successfulOutcome; - asn1cCalloc(pdu.choice.successfulOutcome, tmp); - tmp->procedureCode = F1AP_ProcedureCode_id_UEContextSetup; - tmp->criticality = F1AP_Criticality_reject; - tmp->value.present = F1AP_SuccessfulOutcome__value_PR_UEContextSetupResponse; - out = &tmp->value.choice.UEContextSetupResponse; - /* mandatory */ - /* c1. GNB_CU_UE_F1AP_ID */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie1); - ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; - ie1->criticality = F1AP_Criticality_reject; - ie1->value.present = F1AP_UEContextSetupResponseIEs__value_PR_GNB_CU_UE_F1AP_ID; - ie1->value.choice.GNB_CU_UE_F1AP_ID = resp->gNB_CU_ue_id; - /* mandatory */ - /* c2. GNB_DU_UE_F1AP_ID */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie2); - ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; - ie2->criticality = F1AP_Criticality_reject; - ie2->value.present = F1AP_UEContextSetupResponseIEs__value_PR_GNB_DU_UE_F1AP_ID; - ie2->value.choice.GNB_DU_UE_F1AP_ID = resp->gNB_DU_ue_id; + F1AP_F1AP_PDU_t *pdu = encode_ue_context_setup_resp(resp); - /* mandatory */ - /* c3. DUtoCURRCInformation */ - if(resp->du_to_cu_rrc_information){ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie3); - ie3->id = F1AP_ProtocolIE_ID_id_DUtoCURRCInformation; - ie3->criticality = F1AP_Criticality_reject; - ie3->value.present = F1AP_UEContextSetupResponseIEs__value_PR_DUtoCURRCInformation; - if(resp->du_to_cu_rrc_information->cellGroupConfig!=NULL){ - /* cellGroupConfig */ - OCTET_STRING_fromBuf(&ie3->value.choice.DUtoCURRCInformation.cellGroupConfig, (const char *)resp->du_to_cu_rrc_information->cellGroupConfig, - resp->du_to_cu_rrc_information->cellGroupConfig_length); - } - - /* OPTIONAL */ - /* measGapConfig */ - if (resp->du_to_cu_rrc_information->measGapConfig!=NULL) { - OCTET_STRING_fromBuf(ie3->value.choice.DUtoCURRCInformation.measGapConfig, (const char *)resp->du_to_cu_rrc_information->measGapConfig, - resp->du_to_cu_rrc_information->measGapConfig_length); - } - - /* OPTIONAL */ - /* requestedP_MaxFR1 */ - if (resp->du_to_cu_rrc_information->requestedP_MaxFR1!=NULL) { - OCTET_STRING_fromBuf(ie3->value.choice.DUtoCURRCInformation.requestedP_MaxFR1, (const char *)resp->du_to_cu_rrc_information->requestedP_MaxFR1, - resp->du_to_cu_rrc_information->requestedP_MaxFR1_length); - } - } - - /* optional */ - /* c4. C_RNTI */ - if (resp->crnti!=NULL) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie4); - ie4->id = F1AP_ProtocolIE_ID_id_C_RNTI; - ie4->criticality = F1AP_Criticality_ignore; - ie4->value.present = F1AP_UEContextSetupResponseIEs__value_PR_C_RNTI; - ie4->value.choice.C_RNTI = *resp->crnti; - } - - /* optional */ - /* c5. ResourceCoordinationTransferContainer */ - if (0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie5); - ie5->id = F1AP_ProtocolIE_ID_id_ResourceCoordinationTransferContainer; - ie5->criticality = F1AP_Criticality_ignore; - ie5->value.present = F1AP_UEContextSetupResponseIEs__value_PR_ResourceCoordinationTransferContainer; - OCTET_STRING_fromBuf(&ie5->value.choice.ResourceCoordinationTransferContainer, "asdsa", - strlen("asdsa")); - } - - /* optional */ - /* c6. FullConfiguration */ - if (0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie6); - ie6->id = F1AP_ProtocolIE_ID_id_FullConfiguration; - ie6->criticality = F1AP_Criticality_ignore; - ie6->value.present = F1AP_UEContextSetupResponseIEs__value_PR_FullConfiguration; - ie6->value.choice.FullConfiguration = F1AP_FullConfiguration_full; //enum - } - - /* mandatory */ - /* c7. DRBs_Setup_List */ - if(resp->drbs_to_be_setup_length > 0){ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie7); - ie7->id = F1AP_ProtocolIE_ID_id_DRBs_Setup_List; - ie7->criticality = F1AP_Criticality_ignore; - ie7->value.present = F1AP_UEContextSetupResponseIEs__value_PR_DRBs_Setup_List; - for (int i=0; i< resp->drbs_to_be_setup_length; i++) { - f1ap_drb_to_be_setup_t *drb = &resp->drbs_to_be_setup[i]; - // - asn1cSequenceAdd(ie7->value.choice.DRBs_Setup_List.list, - F1AP_DRBs_Setup_ItemIEs_t, drbs_setup_item_ies); - drbs_setup_item_ies->id = F1AP_ProtocolIE_ID_id_DRBs_Setup_Item; - drbs_setup_item_ies->criticality = F1AP_Criticality_ignore; - drbs_setup_item_ies->value.present = F1AP_DRBs_Setup_ItemIEs__value_PR_DRBs_Setup_Item; - /* 7.1 DRBs_Setup_Item */ - /* ADD */ - F1AP_DRBs_Setup_Item_t *drbs_setup_item=&drbs_setup_item_ies->value.choice.DRBs_Setup_Item; - /* dRBID */ - drbs_setup_item->dRBID = drb->drb_id; - - /* OPTIONAL */ - /* lCID */ - //drbs_setup_item.lCID = (F1AP_LCID_t *)calloc(1, sizeof(F1AP_LCID_t)); - //drbs_setup_item.lCID = 1L; - - for (int j = 0; j < drb->up_dl_tnl_length; j++) { - const f1ap_up_tnl_t *tnl = &drb->up_dl_tnl[j]; - DevAssert(tnl->teid > 0); - - /* ADD */ - asn1cSequenceAdd(drbs_setup_item->dLUPTNLInformation_ToBeSetup_List.list, - F1AP_DLUPTNLInformation_ToBeSetup_Item_t, dLUPTNLInformation_ToBeSetup_Item); - dLUPTNLInformation_ToBeSetup_Item->dLUPTNLInformation.present = F1AP_UPTransportLayerInformation_PR_gTPTunnel; - /* gTPTunnel */ - asn1cCalloc(dLUPTNLInformation_ToBeSetup_Item->dLUPTNLInformation.choice.gTPTunnel,gTPTunnel); - /* transportLayerAddress */ - TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(tnl->tl_address, &gTPTunnel->transportLayerAddress); - /* gTP_TEID */ - INT32_TO_OCTET_STRING(tnl->teid, &gTPTunnel->gTP_TEID); - } // for j - } // for i - - } - - /* mandatory */ - /* c8. SRBs_FailedToBeSetup_List */ - if(0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie8); - ie8->id = F1AP_ProtocolIE_ID_id_SRBs_FailedToBeSetup_List; - ie8->criticality = F1AP_Criticality_ignore; - ie8->value.present = F1AP_UEContextSetupResponseIEs__value_PR_SRBs_FailedToBeSetup_List; - - for (int i=0; i<1; i++) { - // - asn1cSequenceAdd(ie8->value.choice.SRBs_FailedToBeSetup_List.list, - F1AP_SRBs_FailedToBeSetup_ItemIEs_t, srbs_failedToBeSetup_item_ies); - srbs_failedToBeSetup_item_ies->id = F1AP_ProtocolIE_ID_id_SRBs_FailedToBeSetup_Item; - srbs_failedToBeSetup_item_ies->criticality = F1AP_Criticality_ignore; - srbs_failedToBeSetup_item_ies->value.present = F1AP_SRBs_FailedToBeSetup_ItemIEs__value_PR_SRBs_FailedToBeSetup_Item; - /* 8.1 SRBs_Setup_Item */ - F1AP_SRBs_FailedToBeSetup_Item_t *srbs_failedToBeSetup_item= - &srbs_failedToBeSetup_item_ies->value.choice.SRBs_FailedToBeSetup_Item; - /* sRBID */ - srbs_failedToBeSetup_item->sRBID = 13L; - /* cause */ - asn1cCalloc(srbs_failedToBeSetup_item->cause, tmp); - // dummy value - tmp->present = F1AP_Cause_PR_radioNetwork; - - switch(tmp->present) { - case F1AP_Cause_PR_radioNetwork: - tmp->choice.radioNetwork = F1AP_CauseRadioNetwork_unspecified; - break; - - case F1AP_Cause_PR_transport: - tmp->choice.transport = F1AP_CauseTransport_unspecified; - break; - - case F1AP_Cause_PR_protocol: - tmp->choice.protocol = F1AP_CauseProtocol_unspecified; - break; - - case F1AP_Cause_PR_misc: - tmp->choice.misc = F1AP_CauseMisc_unspecified; - break; - - case F1AP_Cause_PR_NOTHING: - default: - break; - } // switch - } // for i - } - - /* */ - /* c9. DRBs_FailedToBeSetup_List */ - if(0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie9); - ie9->id = F1AP_ProtocolIE_ID_id_DRBs_FailedToBeSetup_List; - ie9->criticality = F1AP_Criticality_ignore; - ie9->value.present = F1AP_UEContextSetupResponseIEs__value_PR_DRBs_FailedToBeSetup_List; - - for (int i=0; i<1; i++) { - asn1cSequenceAdd(ie9->value.choice.DRBs_FailedToBeSetup_List.list, - F1AP_DRBs_FailedToBeSetup_ItemIEs_t, drbs_failedToBeSetup_item_ies); - drbs_failedToBeSetup_item_ies->id = F1AP_ProtocolIE_ID_id_DRBs_FailedToBeSetup_Item; - drbs_failedToBeSetup_item_ies->criticality = F1AP_Criticality_ignore; - drbs_failedToBeSetup_item_ies->value.present = F1AP_DRBs_FailedToBeSetup_ItemIEs__value_PR_DRBs_FailedToBeSetup_Item; - /* 9.1 DRBs_Setup_Item */ - /* ADD */ - F1AP_DRBs_FailedToBeSetup_Item_t *drbs_failedToBeSetup_item= - &drbs_failedToBeSetup_item_ies->value.choice.DRBs_FailedToBeSetup_Item; - /* dRBID */ - drbs_failedToBeSetup_item->dRBID = 14; - /* cause */ - asn1cCalloc(drbs_failedToBeSetup_item->cause,tmp); - // dummy value - tmp->present = F1AP_Cause_PR_radioNetwork; - - switch(tmp->present) { - case F1AP_Cause_PR_radioNetwork: - tmp->choice.radioNetwork = F1AP_CauseRadioNetwork_unspecified; - break; - - case F1AP_Cause_PR_transport: - tmp->choice.transport = F1AP_CauseTransport_unspecified; - break; - - case F1AP_Cause_PR_protocol: - tmp->choice.protocol = F1AP_CauseProtocol_unspecified; - break; - - case F1AP_Cause_PR_misc: - tmp->choice.misc = F1AP_CauseMisc_unspecified; - break; - - case F1AP_Cause_PR_NOTHING: - default: - break; - } // switch - } // for i - } - - // /* */ - /* c10. SCell_FailedtoSetup_List */ - if(0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie10); - ie10->id = F1AP_ProtocolIE_ID_id_SCell_FailedtoSetup_List; - ie10->criticality = F1AP_Criticality_ignore; - ie10->value.present = F1AP_UEContextSetupResponseIEs__value_PR_SCell_FailedtoSetup_List; - - for (int i=0; i<1; i++) { - asn1cSequenceAdd(ie10->value.choice.SCell_FailedtoSetup_List.list, - F1AP_SCell_FailedtoSetup_ItemIEs_t, sCell_FailedtoSetup_item_ies); - sCell_FailedtoSetup_item_ies->id = F1AP_ProtocolIE_ID_id_SCell_FailedtoSetup_Item; - sCell_FailedtoSetup_item_ies->criticality = F1AP_Criticality_ignore; - sCell_FailedtoSetup_item_ies->value.present = F1AP_SCell_FailedtoSetup_ItemIEs__value_PR_SCell_FailedtoSetup_Item; - /* 10.1 DRBs_Setup_Item */ - F1AP_SCell_FailedtoSetup_Item_t *sCell_FailedtoSetup_item= - &sCell_FailedtoSetup_item_ies->value.choice.SCell_FailedtoSetup_Item; - /* sCell_ID */ - AssertFatal(false, "handle correct CellID\n"); - f1ap_served_cell_info_t cellID = {0}; - addnRCGI(sCell_FailedtoSetup_item->sCell_ID, &cellID); - /* cause */ - asn1cCalloc(sCell_FailedtoSetup_item->cause, tmp); - // dummy value - tmp->present = F1AP_Cause_PR_radioNetwork; - - switch(tmp->present) { - case F1AP_Cause_PR_radioNetwork: - tmp->choice.radioNetwork = F1AP_CauseRadioNetwork_unspecified; - break; - - case F1AP_Cause_PR_transport: - tmp->choice.transport = F1AP_CauseTransport_unspecified; - break; - - case F1AP_Cause_PR_protocol: - tmp->choice.protocol = F1AP_CauseProtocol_unspecified; - break; - - case F1AP_Cause_PR_misc: - tmp->choice.misc = F1AP_CauseMisc_unspecified; - break; - - case F1AP_Cause_PR_NOTHING: - default: - break; - } // switch - } // for i - } - - /* mandatory */ - /* c11. SRBs_Setup_List */ - if(resp->srbs_to_be_setup_length > 0){ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie11); - ie11->id = F1AP_ProtocolIE_ID_id_SRBs_Setup_List; - ie11->criticality = F1AP_Criticality_ignore; - ie11->value.present = F1AP_UEContextSetupResponseIEs__value_PR_SRBs_Setup_List; - - for (int i=0; i< resp->srbs_to_be_setup_length; i++) {// - asn1cSequenceAdd(ie11->value.choice.SRBs_Setup_List.list, - F1AP_SRBs_Setup_ItemIEs_t, srbs_setup_item_ies); - srbs_setup_item_ies->id = F1AP_ProtocolIE_ID_id_SRBs_Setup_Item; - srbs_setup_item_ies->criticality = F1AP_Criticality_ignore; - srbs_setup_item_ies->value.present = F1AP_SRBs_Setup_ItemIEs__value_PR_SRBs_Setup_Item; - /* 11.1 SRBs_Setup_Item */ - /* ADD */ - F1AP_SRBs_Setup_Item_t *srbs_setup_item=&srbs_setup_item_ies->value.choice.SRBs_Setup_Item; - /* sRBID */ - srbs_setup_item->sRBID = resp->srbs_to_be_setup[i].srb_id; - srbs_setup_item->lCID = resp->srbs_to_be_setup[i].lcid; - } - } - - /* Optional */ - /* c12. InactivityMonitoringResponse */ - if (0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie11); - ie11->id = F1AP_ProtocolIE_ID_id_InactivityMonitoringResponse; - ie11->criticality = F1AP_Criticality_ignore; - ie11->value.present = F1AP_UEContextSetupResponseIEs__value_PR_InactivityMonitoringResponse; - ie11->value.choice.InactivityMonitoringResponse = F1AP_InactivityMonitoringResponse_not_supported; - } - - /* Optional */ - /* c13. CriticalityDiagnostics */ - if (0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie12); - ie12->id = F1AP_ProtocolIE_ID_id_CriticalityDiagnostics; - ie12->criticality = F1AP_Criticality_ignore; - ie12->value.present = F1AP_UEContextSetupResponseIEs__value_PR_CriticalityDiagnostics; - asn1cCallocOne(ie12->value.choice.CriticalityDiagnostics.procedureCode, - F1AP_ProcedureCode_id_UEContextSetup); - asn1cCallocOne(ie12->value.choice.CriticalityDiagnostics.triggeringMessage, - F1AP_TriggeringMessage_initiating_message); - asn1cCallocOne(ie12->value.choice.CriticalityDiagnostics.procedureCriticality, - F1AP_Criticality_reject); - asn1cCallocOne(ie12->value.choice.CriticalityDiagnostics.transactionID, - 0); - } - - /* encode */ - if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { + uint8_t *buffer = NULL; + uint32_t len = 0; + if (f1ap_encode_pdu(pdu, &buffer, &len) < 0) { LOG_E(F1AP, "Failed to encode F1 UE CONTEXT SETUP RESPONSE\n"); return -1; } f1ap_itti_send_sctp_data_req(assoc_id, buffer, len); + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); return 0; } @@ -635,325 +310,18 @@ int DU_handle_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance, sctp_assoc_t return 0; } -int DU_send_UE_CONTEXT_MODIFICATION_RESPONSE(sctp_assoc_t assoc_id, f1ap_ue_context_modif_resp_t *resp) +int DU_send_UE_CONTEXT_MODIFICATION_RESPONSE(sctp_assoc_t assoc_id, f1ap_ue_context_mod_resp_t *resp) { - F1AP_F1AP_PDU_t pdu= {0}; - F1AP_UEContextModificationResponse_t *out; - uint8_t *buffer=NULL; - uint32_t len=0; - /* Create */ - /* 0. Message Type */ - pdu.present = F1AP_F1AP_PDU_PR_successfulOutcome; - asn1cCalloc(pdu.choice.successfulOutcome,tmp); - tmp->procedureCode = F1AP_ProcedureCode_id_UEContextModification; - tmp->criticality = F1AP_Criticality_reject; - tmp->value.present = F1AP_SuccessfulOutcome__value_PR_UEContextModificationResponse; - out = &tmp->value.choice.UEContextModificationResponse; - /* mandatory */ - /* c1. GNB_CU_UE_F1AP_ID */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationResponseIEs_t, ie1); - ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; - ie1->criticality = F1AP_Criticality_reject; - ie1->value.present = F1AP_UEContextModificationResponseIEs__value_PR_GNB_CU_UE_F1AP_ID; - ie1->value.choice.GNB_CU_UE_F1AP_ID = resp->gNB_CU_ue_id; - /* mandatory */ - /* c2. GNB_DU_UE_F1AP_ID */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationResponseIEs_t, ie2); - ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; - ie2->criticality = F1AP_Criticality_reject; - ie2->value.present = F1AP_UEContextModificationResponseIEs__value_PR_GNB_DU_UE_F1AP_ID; - ie2->value.choice.GNB_DU_UE_F1AP_ID = resp->gNB_DU_ue_id; + F1AP_F1AP_PDU_t *pdu = encode_ue_context_mod_resp(resp); - /* optional */ - /* c3. ResourceCoordinationTransferContainer */ - if (0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationResponseIEs_t, ie3); - ie3->id = F1AP_ProtocolIE_ID_id_ResourceCoordinationTransferContainer; - ie3->criticality = F1AP_Criticality_ignore; - ie3->value.present = F1AP_UEContextModificationResponseIEs__value_PR_ResourceCoordinationTransferContainer; - OCTET_STRING_fromBuf(&ie3->value.choice.ResourceCoordinationTransferContainer, "asdsa1d32sa1d31asd31as", - strlen("asdsa1d32sa1d31asd31as")); - } - - /* optional */ - /* c4. DUtoCURRCInformation */ - if(resp->du_to_cu_rrc_information!=NULL){ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationResponseIEs_t, ie4); - ie4->id = F1AP_ProtocolIE_ID_id_DUtoCURRCInformation; - ie4->criticality = F1AP_Criticality_reject; - ie4->value.present = F1AP_UEContextModificationResponseIEs__value_PR_DUtoCURRCInformation; - if(resp->du_to_cu_rrc_information->cellGroupConfig!=NULL){ - /* cellGroupConfig */ - OCTET_STRING_fromBuf(&ie4->value.choice.DUtoCURRCInformation.cellGroupConfig, (const char *)resp->du_to_cu_rrc_information->cellGroupConfig, - resp->du_to_cu_rrc_information->cellGroupConfig_length); - } - - /* OPTIONAL */ - /* measGapConfig */ - if (resp->du_to_cu_rrc_information->measGapConfig!=NULL) { - OCTET_STRING_fromBuf(ie4->value.choice.DUtoCURRCInformation.measGapConfig, (const char *)resp->du_to_cu_rrc_information->measGapConfig, - resp->du_to_cu_rrc_information->measGapConfig_length); - } - - /* OPTIONAL */ - /* requestedP_MaxFR1 */ - if (resp->du_to_cu_rrc_information->requestedP_MaxFR1!=NULL) { - OCTET_STRING_fromBuf(ie4->value.choice.DUtoCURRCInformation.requestedP_MaxFR1, (const char *)resp->du_to_cu_rrc_information->requestedP_MaxFR1, - resp->du_to_cu_rrc_information->requestedP_MaxFR1_length); - } - } - - - /* optional */ - /* c5. DRBs_Setup_List */ - if(resp->drbs_to_be_setup_length > 0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationResponseIEs_t, ie5); - ie5->id = F1AP_ProtocolIE_ID_id_DRBs_SetupMod_List; - ie5->criticality = F1AP_Criticality_ignore; - ie5->value.present = F1AP_UEContextModificationResponseIEs__value_PR_DRBs_SetupMod_List; - for (int i=0; i< resp->drbs_to_be_setup_length; i++) { - asn1cSequenceAdd(ie5->value.choice.DRBs_SetupMod_List.list, F1AP_DRBs_SetupMod_ItemIEs_t, drbs_setupmod_item_ies); - drbs_setupmod_item_ies->id = F1AP_ProtocolIE_ID_id_DRBs_SetupMod_Item; - drbs_setupmod_item_ies->criticality = F1AP_Criticality_ignore; - drbs_setupmod_item_ies->value.present = F1AP_DRBs_SetupMod_ItemIEs__value_PR_DRBs_SetupMod_Item; - /* 7.1 DRBs_Setup_Item */ - /* ADD */ - F1AP_DRBs_SetupMod_Item_t *drbs_setupmod_item=&drbs_setupmod_item_ies->value.choice.DRBs_SetupMod_Item; - /* dRBID */ - drbs_setupmod_item->dRBID = resp->drbs_to_be_setup[i].drb_id; - - for (int j=0; jdrbs_to_be_setup[i].up_dl_tnl_length; j++) { - const f1ap_up_tnl_t *tnl = &resp->drbs_to_be_setup[i].up_dl_tnl[j]; - DevAssert(tnl->teid > 0); - - /* ADD */ - asn1cSequenceAdd(drbs_setupmod_item->dLUPTNLInformation_ToBeSetup_List.list, - F1AP_DLUPTNLInformation_ToBeSetup_Item_t, dLUPTNLInformation_ToBeSetup_Item); - dLUPTNLInformation_ToBeSetup_Item->dLUPTNLInformation.present = F1AP_UPTransportLayerInformation_PR_gTPTunnel; - /* gTPTunnel */ - asn1cCalloc(dLUPTNLInformation_ToBeSetup_Item->dLUPTNLInformation.choice.gTPTunnel,gTPTunnel); - /* transportLayerAddress */ - TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(tnl->tl_address, &gTPTunnel->transportLayerAddress); - /* gTP_TEID */ - INT32_TO_OCTET_STRING(tnl->teid, &gTPTunnel->gTP_TEID); - } // for j - } // for i - } - - /* optional */ - /* c6. DRBs_Modified_List */ - if(resp->drbs_to_be_modified_length > 0){ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationResponseIEs_t, ie6); - ie6->id = F1AP_ProtocolIE_ID_id_DRBs_Modified_List; - ie6->criticality = F1AP_Criticality_ignore; - ie6->value.present = F1AP_UEContextModificationResponseIEs__value_PR_DRBs_Modified_List; - - for (int i=0; idrbs_to_be_modified_length; i++) { - asn1cSequenceAdd(ie6->value.choice.DRBs_Modified_List.list, - F1AP_DRBs_Modified_ItemIEs_t, drbs_modified_item_ies); - drbs_modified_item_ies->id = F1AP_ProtocolIE_ID_id_DRBs_Modified_Item; - drbs_modified_item_ies->criticality = F1AP_Criticality_ignore; - drbs_modified_item_ies->value.present = F1AP_DRBs_Modified_ItemIEs__value_PR_DRBs_Modified_Item; - /* DRBs_modified_Item */ - F1AP_DRBs_Modified_Item_t *drbs_modified_item= &drbs_modified_item_ies->value.choice.DRBs_Modified_Item; - /* dRBID */ - drbs_modified_item->dRBID = resp->drbs_to_be_modified[i].drb_id; - - /* ULTunnels_Modified_List */ - for (int j=0; jdrbs_to_be_modified[i].up_dl_tnl_length; j++) { - /* DLTunnels_Modified_Item */ - asn1cSequenceAdd(drbs_modified_item->dLUPTNLInformation_ToBeSetup_List.list, - F1AP_DLUPTNLInformation_ToBeSetup_Item_t, dLUPTNLInformation_ToBeSetup_Item); - asn1cCalloc(dLUPTNLInformation_ToBeSetup_Item, tmp); - tmp->dLUPTNLInformation.present = F1AP_UPTransportLayerInformation_PR_gTPTunnel; - asn1cCalloc(dLUPTNLInformation_ToBeSetup_Item->dLUPTNLInformation.choice.gTPTunnel, gTPTunnel); - /* transportLayerAddress */ - struct sockaddr_in addr= {0}; - inet_pton(AF_INET, getCxt(0)->net_config.DU_f1u_ip_address, &addr.sin_addr.s_addr); - TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(addr.sin_addr.s_addr, &gTPTunnel->transportLayerAddress); - /* gTP_TEID */ - INT32_TO_OCTET_STRING(resp->drbs_to_be_modified[i].up_dl_tnl[j].teid, &gTPTunnel->gTP_TEID); - } - } - } - - /* optional */ - /* c7. SRBs_FailedToBeSetupMod_List */ - if(resp->srbs_failed_to_be_setup_length > 0){ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationResponseIEs_t, ie7); - ie7->id = F1AP_ProtocolIE_ID_id_SRBs_FailedToBeSetupMod_List; - ie7->criticality = F1AP_Criticality_reject; - ie7->value.present = F1AP_UEContextModificationResponseIEs__value_PR_SRBs_FailedToBeSetupMod_List; - - for (int i=0; isrbs_to_be_setup_length; i++) { - asn1cSequenceAdd(ie7->value.choice.SRBs_FailedToBeSetupMod_List.list, - F1AP_SRBs_FailedToBeSetupMod_ItemIEs_t, srbs_failedToBeSetupMod_item_ies); - srbs_failedToBeSetupMod_item_ies->id = F1AP_ProtocolIE_ID_id_SRBs_FailedToBeSetupMod_Item; - srbs_failedToBeSetupMod_item_ies->criticality = F1AP_Criticality_ignore; - srbs_failedToBeSetupMod_item_ies->value.present = F1AP_SRBs_FailedToBeSetupMod_ItemIEs__value_PR_SRBs_FailedToBeSetupMod_Item; - /* 9.1 SRBs_FailedToBeSetupMod_Item */ - F1AP_SRBs_FailedToBeSetupMod_Item_t *srbs_failedToBeSetupMod_item= - &srbs_failedToBeSetupMod_item_ies->value.choice.SRBs_FailedToBeSetupMod_Item; - /* - sRBID */ - srbs_failedToBeSetupMod_item->sRBID = resp->srbs_failed_to_be_setup[i].rb_id; - asn1cCalloc(srbs_failedToBeSetupMod_item->cause, tmp); - tmp->present = F1AP_Cause_PR_radioNetwork; - tmp->choice.radioNetwork = F1AP_CauseRadioNetwork_unknown_or_already_allocated_gnb_du_ue_f1ap_id; - } - } - - /* optional */ - /* c8. DRBs_FailedToBeSetupMod_List */ - if(resp->drbs_failed_to_be_setup_length > 0){ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationResponseIEs_t, ie8); - ie8->id = F1AP_ProtocolIE_ID_id_DRBs_FailedToBeSetupMod_List; - ie8->criticality = F1AP_Criticality_reject; - ie8->value.present = F1AP_UEContextModificationResponseIEs__value_PR_DRBs_FailedToBeSetupMod_List; - - for (int i=0; idrbs_failed_to_be_setup_length; i++) { - asn1cSequenceAdd(ie8->value.choice.DRBs_FailedToBeSetupMod_List.list, - F1AP_DRBs_FailedToBeSetupMod_ItemIEs_t, drbs_failedToBeSetupMod_item_ies); - drbs_failedToBeSetupMod_item_ies->id = F1AP_ProtocolIE_ID_id_DRBs_FailedToBeSetupMod_Item; - drbs_failedToBeSetupMod_item_ies->criticality = F1AP_Criticality_reject; - drbs_failedToBeSetupMod_item_ies->value.present = F1AP_DRBs_FailedToBeSetupMod_ItemIEs__value_PR_DRBs_FailedToBeSetupMod_Item; - /* DRBs_FailedToBeSetupMod_Item */ - F1AP_DRBs_FailedToBeSetupMod_Item_t *drbs_failedToBeSetupMod_item= - &drbs_failedToBeSetupMod_item_ies->value.choice.DRBs_FailedToBeSetupMod_Item; - /* dRBID */ - drbs_failedToBeSetupMod_item->dRBID = resp->drbs_failed_to_be_setup[i].rb_id; - drbs_failedToBeSetupMod_item->cause = (F1AP_Cause_t *)calloc(1, sizeof(F1AP_Cause_t)); - drbs_failedToBeSetupMod_item->cause->present = F1AP_Cause_PR_radioNetwork; - drbs_failedToBeSetupMod_item->cause->choice.radioNetwork = F1AP_CauseRadioNetwork_unknown_or_already_allocated_gnb_du_ue_f1ap_id; - } - } - - /* optional */ - /* c9. SCell_FailedtoSetupMod_List */ - if(0){ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationResponseIEs_t, ie9); - ie9->id = F1AP_ProtocolIE_ID_id_SCell_FailedtoSetupMod_List; - ie9->criticality = F1AP_Criticality_ignore; - ie9->value.present = F1AP_UEContextModificationResponseIEs__value_PR_SCell_FailedtoSetupMod_List; - - for (int i=0; i<1; i++) { - asn1cSequenceAdd(ie9->value.choice.SCell_FailedtoSetupMod_List.list, - F1AP_SCell_FailedtoSetupMod_ItemIEs_t, scell_failedtoSetupMod_item_ies); - scell_failedtoSetupMod_item_ies->id = F1AP_ProtocolIE_ID_id_SCell_FailedtoSetupMod_Item; - scell_failedtoSetupMod_item_ies->criticality = F1AP_Criticality_ignore; - scell_failedtoSetupMod_item_ies->value.present = F1AP_SCell_FailedtoSetupMod_ItemIEs__value_PR_SCell_FailedtoSetupMod_Item; - /* 8.1 SCell_ToBeSetup_Item */ - F1AP_SCell_FailedtoSetupMod_Item_t *scell_failedtoSetupMod_item=&scell_failedtoSetupMod_item_ies->value.choice.SCell_FailedtoSetupMod_Item; - /* - sCell_ID */ - addnRCGI(scell_failedtoSetupMod_item->sCell_ID, &getCxt(0)->setupReq.cell[i].info); - asn1cCalloc(scell_failedtoSetupMod_item->cause, tmp); - tmp->present = F1AP_Cause_PR_radioNetwork; - tmp->choice.radioNetwork = F1AP_CauseRadioNetwork_unknown_or_already_allocated_gnb_du_ue_f1ap_id; - } - } - - /* optional */ - /* c10. DRBs_FailedToBeModified_List */ - if(0){ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationResponseIEs_t, ie10); - ie10->id = F1AP_ProtocolIE_ID_id_DRBs_FailedToBeModified_List; - ie10->criticality = F1AP_Criticality_reject; - ie10->value.present = F1AP_UEContextModificationResponseIEs__value_PR_DRBs_FailedToBeModified_List; - - for (int i=0; i<1; i++) { - asn1cSequenceAdd(ie10->value.choice.DRBs_FailedToBeModified_List.list, - F1AP_DRBs_FailedToBeModified_ItemIEs_t, drbs_failedToBeModified_item_ies); - drbs_failedToBeModified_item_ies->id = F1AP_ProtocolIE_ID_id_DRBs_FailedToBeModified_Item; - drbs_failedToBeModified_item_ies->criticality = F1AP_Criticality_reject; - drbs_failedToBeModified_item_ies->value.present = F1AP_DRBs_FailedToBeModified_ItemIEs__value_PR_DRBs_FailedToBeModified_Item; - /* 13.1 DRBs_FailedToBeModified_Item */ - F1AP_DRBs_FailedToBeModified_Item_t *drbs_failedToBeModified_item= - &drbs_failedToBeModified_item_ies->value.choice.DRBs_FailedToBeModified_Item ; - /* dRBID */ - drbs_failedToBeModified_item->dRBID = 30L; - asn1cCalloc(drbs_failedToBeModified_item->cause, tmp); - tmp->present = F1AP_Cause_PR_radioNetwork; - tmp->choice.radioNetwork = F1AP_CauseRadioNetwork_unknown_or_already_allocated_gnb_du_ue_f1ap_id; - } - } - - // /* */ - /* c11. CriticalityDiagnostics */ - if (0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationResponseIEs_t, ie11); - ie11->id = F1AP_ProtocolIE_ID_id_CriticalityDiagnostics; - ie11->criticality = F1AP_Criticality_ignore; - ie11->value.present = F1AP_UEContextModificationResponseIEs__value_PR_CriticalityDiagnostics; - - // dummy value - /* optional */ - /* procedureCode */ - if (0) { - ie11->value.choice.CriticalityDiagnostics.procedureCode = (F1AP_ProcedureCode_t *)calloc(1, sizeof(F1AP_ProcedureCode_t)); - *ie11->value.choice.CriticalityDiagnostics.procedureCode = 0L; - } - - /* optional */ - /* triggeringMessage */ - if (0) { - ie11->value.choice.CriticalityDiagnostics.triggeringMessage = (F1AP_TriggeringMessage_t *)calloc(1, sizeof(F1AP_TriggeringMessage_t)); - *ie11->value.choice.CriticalityDiagnostics.triggeringMessage = F1AP_TriggeringMessage_successful_outcome; - } - - /* optional */ - /* procedureCriticality */ - if (0) { - ie11->value.choice.CriticalityDiagnostics.procedureCriticality = (F1AP_Criticality_t *)calloc(1, sizeof(F1AP_Criticality_t)); - *ie11->value.choice.CriticalityDiagnostics.procedureCriticality = F1AP_Criticality_reject; - } - - /* optional */ - /* transactionID */ - if (0) { - ie11->value.choice.CriticalityDiagnostics.transactionID = (F1AP_TransactionID_t *)calloc(1, sizeof(F1AP_TransactionID_t)); - *ie11->value.choice.CriticalityDiagnostics.transactionID = 0L; - } - - /* optional */ - /* F1AP_CriticalityDiagnostics_IE_List */ - if (0) { - for (int i=0; i<0; i++) { - asn1cSequenceAdd(ie11->value.choice.CriticalityDiagnostics.iEsCriticalityDiagnostics->list, F1AP_CriticalityDiagnostics_IE_Item_t, criticalityDiagnostics_ie_item); - criticalityDiagnostics_ie_item->iECriticality = F1AP_Criticality_reject; - criticalityDiagnostics_ie_item->iE_ID = 0L; - criticalityDiagnostics_ie_item->typeOfError = F1AP_TypeOfError_not_understood; - } - } - } - /* optional */ - /* c12. SRBs_Setup_List */ - if(resp->srbs_to_be_setup_length > 0){ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationResponseIEs_t, ie12); - ie12->id = F1AP_ProtocolIE_ID_id_SRBs_SetupMod_List; - ie12->criticality = F1AP_Criticality_ignore; - ie12->value.present = F1AP_UEContextModificationResponseIEs__value_PR_SRBs_SetupMod_List; - - for (int i=0; i< resp->srbs_to_be_setup_length; i++) {// - asn1cSequenceAdd(ie12->value.choice.SRBs_SetupMod_List.list, - F1AP_SRBs_SetupMod_ItemIEs_t, srbs_setupmod_item_ies); - srbs_setupmod_item_ies->id = F1AP_ProtocolIE_ID_id_SRBs_SetupMod_Item; - srbs_setupmod_item_ies->criticality = F1AP_Criticality_ignore; - srbs_setupmod_item_ies->value.present = F1AP_SRBs_SetupMod_ItemIEs__value_PR_SRBs_SetupMod_Item; - /* 11.1 SRBs_Setup_Item */ - /* ADD */ - F1AP_SRBs_SetupMod_Item_t *srbs_setupmod_item=&srbs_setupmod_item_ies->value.choice.SRBs_SetupMod_Item; - /* sRBID */ - srbs_setupmod_item->sRBID = resp->srbs_to_be_setup[i].srb_id; - srbs_setupmod_item->lCID = resp->srbs_to_be_setup[i].srb_id; - } - } - - /* encode */ - if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { - LOG_E(F1AP, "Failed to encode F1 UE CONTEXT MODIFICATION RESPONSE\n"); + uint8_t *buffer = NULL; + uint32_t len = 0; + if (f1ap_encode_pdu(pdu, &buffer, &len) < 0) { + LOG_E(F1AP, "Failed to encode F1 UE CONTEXT SETUP RESPONSE\n"); return -1; } - f1ap_itti_send_sctp_data_req(assoc_id, buffer, len); + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); return 0; } diff --git a/openair2/F1AP/f1ap_du_ue_context_management.h b/openair2/F1AP/f1ap_du_ue_context_management.h index 43663ba538..8f38ac8dd9 100644 --- a/openair2/F1AP/f1ap_du_ue_context_management.h +++ b/openair2/F1AP/f1ap_du_ue_context_management.h @@ -36,7 +36,7 @@ /* * UE Context Setup */ -int DU_send_UE_CONTEXT_SETUP_RESPONSE(sctp_assoc_t assoc_id, f1ap_ue_context_setup_t *req); +int DU_send_UE_CONTEXT_SETUP_RESPONSE(sctp_assoc_t assoc_id, f1ap_ue_context_setup_resp_t *resp); int DU_handle_UE_CONTEXT_SETUP_REQUEST(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu); int DU_send_UE_CONTEXT_SETUP_FAILURE(sctp_assoc_t assoc_id); @@ -63,7 +63,7 @@ int DU_send_UE_CONTEXT_RELEASE_COMPLETE(sctp_assoc_t assoc_id, f1ap_ue_context_r * UE Context Modification (gNB-CU initiated) */ int DU_handle_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu); -int DU_send_UE_CONTEXT_MODIFICATION_RESPONSE(sctp_assoc_t assoc_id, f1ap_ue_context_modif_resp_t *resp); +int DU_send_UE_CONTEXT_MODIFICATION_RESPONSE(sctp_assoc_t assoc_id, f1ap_ue_context_mod_resp_t *resp); int DU_send_UE_CONTEXT_MODIFICATION_FAILURE(sctp_assoc_t assoc_id); diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c index 5f2e9b9dfa..58d8dbf86c 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -235,7 +235,7 @@ static NR_RLC_BearerConfig_t *get_bearerconfig_from_srb(const f1ap_srb_to_setup_ static int handle_ue_context_srbs_setup(NR_UE_info_t *UE, int srbs_len, const f1ap_srb_to_setup_t *req_srbs, - f1ap_srb_to_be_setup_t **resp_srbs, + f1ap_srb_setup_t **resp_srbs, NR_CellGroupConfig_t *cellGroupConfig, const nr_rlc_configuration_t *rlc_config) { @@ -252,7 +252,7 @@ static int handle_ue_context_srbs_setup(NR_UE_info_t *UE, nr_lc_config_t c = {.lcid = rlc_BearerConfig->logicalChannelIdentity, .priority = priority}; nr_mac_add_lcid(&UE->UE_sched_ctrl, &c); - (*resp_srbs)[i].srb_id = srb->id; + (*resp_srbs)[i].id = srb->id; (*resp_srbs)[i].lcid = c.lcid; if (rlc_BearerConfig->logicalChannelIdentity == 1) { @@ -308,7 +308,7 @@ static NR_QoS_config_t get_qos_config(const f1ap_qos_flow_param_t *qos) static int handle_ue_context_drbs_setup(NR_UE_info_t *UE, int drbs_len, const f1ap_drb_to_setup_t *req_drbs, - f1ap_drb_to_be_setup_t **resp_drbs, + f1ap_drb_setup_t **resp_drbs, NR_CellGroupConfig_t *cellGroupConfig, const nr_rlc_configuration_t *rlc_config) { @@ -322,7 +322,7 @@ static int handle_ue_context_drbs_setup(NR_UE_info_t *UE, for (int i = 0; i < drbs_len; i++) { const f1ap_drb_to_setup_t *drb = &req_drbs[i]; AssertFatal(drb->qos_choice == F1AP_QOS_CHOICE_NR, "only NR QoS supported\n"); - f1ap_drb_to_be_setup_t *resp_drb = &(*resp_drbs)[i]; + f1ap_drb_setup_t *resp_drb = &(*resp_drbs)[i]; NR_RLC_BearerConfig_t *rlc_BearerConfig = get_bearerconfig_from_drb(drb, rlc_config); nr_rlc_add_drb(UE->rnti, drb->id, rlc_BearerConfig); @@ -335,11 +335,12 @@ static int handle_ue_context_drbs_setup(NR_UE_info_t *UE, c.priority = prio; nr_mac_add_lcid(&UE->UE_sched_ctrl, &c); - resp_drb->drb_id = drb->id; - // TODO lcid + resp_drb->id = drb->id; + resp_drb->lcid = malloc_or_fail(sizeof(*resp_drb->lcid)); + *resp_drb->lcid = c.lcid; // just put same number of tunnels in DL as in UL DevAssert(drb->up_ul_tnl_len == 1); - resp_drb->up_dl_tnl_length = drb->up_ul_tnl_len; + resp_drb->up_dl_tnl_len = drb->up_ul_tnl_len; if (f1inst >= 0) { // we actually use F1-U int qfi = -1; // don't put PDU session marker in GTP @@ -608,8 +609,7 @@ void ue_context_setup_request(const f1ap_ue_context_setup_req_t *req) const bool is_SA = IS_SA_MODE(get_softmodem_params()); gNB_MAC_INST *mac = RC.nrmac[0]; - /* TODO: update response */ - f1ap_ue_context_setup_t resp = { + f1ap_ue_context_setup_resp_t resp = { .gNB_CU_ue_id = req->gNB_CU_ue_id, }; @@ -639,7 +639,8 @@ void ue_context_setup_request(const f1ap_ue_context_setup_req_t *req) if (!ue_id_provided) { UE = create_new_UE(mac, req->gNB_CU_ue_id, cg_configinfo); resp.gNB_DU_ue_id = UE->rnti; - resp.crnti = &UE->rnti; + resp.crnti = malloc_or_fail(sizeof(*resp.crnti)); + *resp.crnti = UE->rnti; } else { DevAssert(is_SA); UE = find_nr_UE(&mac->UE_info, *req->gNB_DU_ue_id); @@ -650,21 +651,12 @@ void ue_context_setup_request(const f1ap_ue_context_setup_req_t *req) NR_CellGroupConfig_t *new_CellGroup = clone_CellGroupConfig(UE->CellGroup); if (req->srbs_len > 0) { - resp.srbs_to_be_setup_length = handle_ue_context_srbs_setup(UE, - req->srbs_len, - req->srbs, - &resp.srbs_to_be_setup, - new_CellGroup, - &mac->rlc_config); + resp.srbs_len = handle_ue_context_srbs_setup(UE, req->srbs_len, req->srbs, &resp.srbs, new_CellGroup, &mac->rlc_config); } if (req->drbs_len > 0) { - resp.drbs_to_be_setup_length = handle_ue_context_drbs_setup(UE, - req->drbs_len, - req->drbs, - &resp.drbs_to_be_setup, - new_CellGroup, - &mac->rlc_config); + resp.drbs_len = + handle_ue_context_drbs_setup(UE, req->drbs_len, req->drbs, &resp.drbs, new_CellGroup, &mac->rlc_config); } if (req->rrc_container != NULL) { @@ -692,14 +684,12 @@ void ue_context_setup_request(const f1ap_ue_context_setup_req_t *req) } } - resp.du_to_cu_rrc_information = calloc(1, sizeof(du_to_cu_rrc_information_t)); - AssertFatal(resp.du_to_cu_rrc_information != NULL, "out of memory\n"); - resp.du_to_cu_rrc_information->cellGroupConfig = calloc(1,1024); - AssertFatal(resp.du_to_cu_rrc_information->cellGroupConfig != NULL, "out of memory\n"); + byte_array_t cgc = { .buf = calloc_or_fail(1,1024) }; asn_enc_rval_t enc_rval = - uper_encode_to_buffer(&asn_DEF_NR_CellGroupConfig, NULL, new_CellGroup, resp.du_to_cu_rrc_information->cellGroupConfig, 1024); + uper_encode_to_buffer(&asn_DEF_NR_CellGroupConfig, NULL, new_CellGroup, cgc.buf, 1024); AssertFatal(enc_rval.encoded > 0, "Could not encode CellGroup, failed element %s\n", enc_rval.failed_type->name); - resp.du_to_cu_rrc_information->cellGroupConfig_length = (enc_rval.encoded + 7) >> 3; + cgc.len = (enc_rval.encoded + 7) >> 3; + resp.du_to_cu_rrc_info.cell_group_config = cgc; ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->CellGroup); UE->CellGroup = new_CellGroup; @@ -708,24 +698,16 @@ void ue_context_setup_request(const f1ap_ue_context_setup_req_t *req) NR_SCHED_UNLOCK(&mac->sched_lock); - /* some sanity checks, since we use the same type for request and response */ - DevAssert(resp.cu_to_du_rrc_information == NULL); - DevAssert(resp.du_to_cu_rrc_information != NULL); - DevAssert(resp.rrc_container == NULL && resp.rrc_container_length == 0); - mac->mac_rrc.ue_context_setup_response(&resp); /* free the memory we allocated above */ - free(resp.srbs_to_be_setup); - free(resp.drbs_to_be_setup); - free(resp.du_to_cu_rrc_information->cellGroupConfig); - free(resp.du_to_cu_rrc_information); + free_ue_context_setup_resp(&resp); } void ue_context_modification_request(const f1ap_ue_context_mod_req_t *req) { gNB_MAC_INST *mac = RC.nrmac[0]; - f1ap_ue_context_modif_resp_t resp = { + f1ap_ue_context_mod_resp_t resp = { .gNB_CU_ue_id = req->gNB_CU_ue_id, .gNB_DU_ue_id = req->gNB_DU_ue_id, }; @@ -751,25 +733,15 @@ void ue_context_modification_request(const f1ap_ue_context_mod_req_t *req) NR_CellGroupConfig_t *new_CellGroup = clone_CellGroupConfig(UE->CellGroup); if (req->srbs_len > 0) { - resp.srbs_to_be_setup_length = handle_ue_context_srbs_setup(UE, - req->srbs_len, - req->srbs, - &resp.srbs_to_be_setup, - new_CellGroup, - &mac->rlc_config); + resp.srbs_len = handle_ue_context_srbs_setup(UE, req->srbs_len, req->srbs, &resp.srbs, new_CellGroup, &mac->rlc_config); } if (req->drbs_len > 0) { - resp.drbs_to_be_setup_length = handle_ue_context_drbs_setup(UE, - req->drbs_len, - req->drbs, - &resp.drbs_to_be_setup, - new_CellGroup, - &mac->rlc_config); + resp.drbs_len = handle_ue_context_drbs_setup(UE, req->drbs_len, req->drbs, &resp.drbs, new_CellGroup, &mac->rlc_config); } if (req->drbs_rel_len > 0) { - resp.drbs_to_be_released_length = handle_ue_context_drbs_release(UE, req->drbs_rel_len, req->drbs_rel, new_CellGroup); + handle_ue_context_drbs_release(UE, req->drbs_rel_len, req->drbs_rel, new_CellGroup); } if (req->rrc_container != NULL) { @@ -808,17 +780,16 @@ void ue_context_modification_request(const f1ap_ue_context_mod_req_t *req) } if (req->srbs_len > 0 || req->drbs_len > 0 || req->drbs_rel_len > 0 || ue_cap != NULL) { - resp.du_to_cu_rrc_information = calloc(1, sizeof(du_to_cu_rrc_information_t)); - AssertFatal(resp.du_to_cu_rrc_information != NULL, "out of memory\n"); - resp.du_to_cu_rrc_information->cellGroupConfig = calloc(1, 1024); - AssertFatal(resp.du_to_cu_rrc_information->cellGroupConfig != NULL, "out of memory\n"); + resp.du_to_cu_rrc_info = calloc_or_fail(1, sizeof(du_to_cu_rrc_information_t)); + byte_array_t cgc = { .buf = calloc_or_fail(1, 1024) }; asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_CellGroupConfig, NULL, new_CellGroup, - resp.du_to_cu_rrc_information->cellGroupConfig, + cgc.buf, 1024); AssertFatal(enc_rval.encoded > 0, "Could not encode CellGroup, failed element %s\n", enc_rval.failed_type->name); - resp.du_to_cu_rrc_information->cellGroupConfig_length = (enc_rval.encoded + 7) >> 3; + cgc.len = (enc_rval.encoded + 7) >> 3; + resp.du_to_cu_rrc_info->cell_group_config = cgc; ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->CellGroup); UE->CellGroup = new_CellGroup; @@ -833,20 +804,10 @@ void ue_context_modification_request(const f1ap_ue_context_mod_req_t *req) } NR_SCHED_UNLOCK(&mac->sched_lock); - /* some sanity checks, since we use the same type for request and response */ - DevAssert(resp.cu_to_du_rrc_information == NULL); - // resp.du_to_cu_rrc_information can be either NULL or not - DevAssert(resp.rrc_container == NULL && resp.rrc_container_length == 0); - mac->mac_rrc.ue_context_modification_response(&resp); /* free the memory we allocated above */ - free(resp.srbs_to_be_setup); - free(resp.drbs_to_be_setup); - if (resp.du_to_cu_rrc_information != NULL) { - free(resp.du_to_cu_rrc_information->cellGroupConfig); - free(resp.du_to_cu_rrc_information); - } + free_ue_context_mod_resp(&resp); } void ue_context_modification_confirm(const f1ap_ue_context_modif_confirm_t *confirm) diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h index 6681b96032..033e8590d2 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h @@ -31,8 +31,8 @@ typedef void (*f1_reset_acknowledge_cu_initiated_func_t)(const f1ap_reset_ack_t typedef void (*f1_setup_request_func_t)(const f1ap_setup_req_t* req); typedef void (*gnb_du_configuration_update_t)(const f1ap_gnb_du_configuration_update_t *upd); -typedef void (*ue_context_setup_response_func_t)(const f1ap_ue_context_setup_t *resp); -typedef void (*ue_context_modification_response_func_t)(const f1ap_ue_context_modif_resp_t *resp); +typedef void (*ue_context_setup_response_func_t)(const f1ap_ue_context_setup_resp_t *resp); +typedef void (*ue_context_modification_response_func_t)(const f1ap_ue_context_mod_resp_t *resp); typedef void (*ue_context_modification_required_func_t)(const f1ap_ue_context_modif_required_t *t); typedef void (*ue_context_release_request_func_t)(const f1ap_ue_context_release_req_t* req); typedef void (*ue_context_release_complete_func_t)(const f1ap_ue_context_release_complete_t *complete); diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c index d1c9efbdfb..72308bdd66 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c @@ -25,6 +25,7 @@ #include "mac_rrc_ul.h" #include "lib/f1ap_rrc_message_transfer.h" #include "lib/f1ap_interface_management.h" +#include "lib/f1ap_ue_context.h" static void f1_reset_du_initiated_direct(const f1ap_reset_t *reset) { @@ -58,91 +59,19 @@ static void gnb_du_configuration_update_direct(const f1ap_gnb_du_configuration_u itti_send_msg_to_task(TASK_RRC_GNB, 0, msg); } -static void ue_context_setup_response_direct(const f1ap_ue_context_setup_t *resp) +static void ue_context_setup_response_direct(const f1ap_ue_context_setup_resp_t *resp) { MessageDef *msg = itti_alloc_new_message (TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_SETUP_RESP); msg->ittiMsgHeader.originInstance = -1; // means monolithic - f1ap_ue_context_setup_t *f1ap_msg = &F1AP_UE_CONTEXT_SETUP_RESP(msg); - /* copy all fields, but reallocate memory buffers! */ - *f1ap_msg = *resp; - - if (resp->srbs_to_be_setup_length > 0) { - DevAssert(resp->srbs_to_be_setup != NULL); - f1ap_msg->srbs_to_be_setup_length = resp->srbs_to_be_setup_length; - f1ap_msg->srbs_to_be_setup = calloc(f1ap_msg->srbs_to_be_setup_length, sizeof(*f1ap_msg->srbs_to_be_setup)); - for (int i = 0; i < f1ap_msg->srbs_to_be_setup_length; ++i) - f1ap_msg->srbs_to_be_setup[i] = resp->srbs_to_be_setup[i]; - } - if (resp->drbs_to_be_setup_length > 0) { - DevAssert(resp->drbs_to_be_setup != NULL); - f1ap_msg->drbs_to_be_setup_length = resp->drbs_to_be_setup_length; - f1ap_msg->drbs_to_be_setup = calloc(f1ap_msg->drbs_to_be_setup_length, sizeof(*f1ap_msg->drbs_to_be_setup)); - for (int i = 0; i < f1ap_msg->drbs_to_be_setup_length; ++i) - f1ap_msg->drbs_to_be_setup[i] = resp->drbs_to_be_setup[i]; - } - - f1ap_msg->du_to_cu_rrc_information = malloc(sizeof(*resp->du_to_cu_rrc_information)); - AssertFatal(f1ap_msg->du_to_cu_rrc_information != NULL, "out of memory\n"); - f1ap_msg->du_to_cu_rrc_information_length = resp->du_to_cu_rrc_information_length; - du_to_cu_rrc_information_t *du2cu = f1ap_msg->du_to_cu_rrc_information; - du2cu->cellGroupConfig_length = resp->du_to_cu_rrc_information->cellGroupConfig_length; - du2cu->cellGroupConfig = calloc(du2cu->cellGroupConfig_length, sizeof(*du2cu->cellGroupConfig)); - AssertFatal(du2cu->cellGroupConfig != NULL, "out of memory\n"); - memcpy(du2cu->cellGroupConfig, resp->du_to_cu_rrc_information->cellGroupConfig, du2cu->cellGroupConfig_length); - + F1AP_UE_CONTEXT_SETUP_RESP(msg) = cp_ue_context_setup_resp(resp); itti_send_msg_to_task(TASK_RRC_GNB, 0, msg); } -static void ue_context_modification_response_direct(const f1ap_ue_context_modif_resp_t *resp) +static void ue_context_modification_response_direct(const f1ap_ue_context_mod_resp_t *resp) { MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_MODIFICATION_RESP); msg->ittiMsgHeader.originInstance = -1; // means monolithic - f1ap_ue_context_modif_resp_t *f1ap_msg = &F1AP_UE_CONTEXT_MODIFICATION_RESP(msg); - - f1ap_msg->gNB_CU_ue_id = resp->gNB_CU_ue_id; - f1ap_msg->gNB_DU_ue_id = resp->gNB_DU_ue_id; - f1ap_msg->plmn = resp->plmn; - f1ap_msg->nr_cellid = resp->nr_cellid; - f1ap_msg->servCellIndex = resp->servCellIndex; - AssertFatal(resp->cellULConfigured == NULL, "not handled\n"); - f1ap_msg->servCellId = resp->servCellId; - - DevAssert(resp->cu_to_du_rrc_information == NULL && resp->cu_to_du_rrc_information_length == 0); - if (resp->du_to_cu_rrc_information) { - f1ap_msg->du_to_cu_rrc_information = malloc(sizeof(*resp->du_to_cu_rrc_information)); - AssertFatal(f1ap_msg->du_to_cu_rrc_information != NULL, "out of memory\n"); - f1ap_msg->du_to_cu_rrc_information_length = resp->du_to_cu_rrc_information_length; - du_to_cu_rrc_information_t *du2cu = f1ap_msg->du_to_cu_rrc_information; - du2cu->cellGroupConfig_length = resp->du_to_cu_rrc_information->cellGroupConfig_length; - du2cu->cellGroupConfig = calloc(du2cu->cellGroupConfig_length, sizeof(*du2cu->cellGroupConfig)); - AssertFatal(du2cu->cellGroupConfig != NULL, "out of memory\n"); - memcpy(du2cu->cellGroupConfig, resp->du_to_cu_rrc_information->cellGroupConfig, du2cu->cellGroupConfig_length); - } - - if (resp->drbs_to_be_setup_length > 0) { - DevAssert(resp->drbs_to_be_setup != NULL); - f1ap_msg->drbs_to_be_setup_length = resp->drbs_to_be_setup_length; - f1ap_msg->drbs_to_be_setup = calloc(f1ap_msg->drbs_to_be_setup_length, sizeof(*f1ap_msg->drbs_to_be_setup)); - for (int i = 0; i < f1ap_msg->drbs_to_be_setup_length; ++i) - f1ap_msg->drbs_to_be_setup[i] = resp->drbs_to_be_setup[i]; - } - - DevAssert(resp->drbs_to_be_modified == NULL && resp->drbs_to_be_modified_length == 0); - f1ap_msg->QoS_information_type = resp->QoS_information_type; - AssertFatal(resp->drbs_failed_to_be_setup_length == 0 && resp->drbs_failed_to_be_setup == NULL, "not implemented yet\n"); - - if (resp->srbs_to_be_setup_length > 0) { - DevAssert(resp->srbs_to_be_setup != NULL); - f1ap_msg->srbs_to_be_setup_length = resp->srbs_to_be_setup_length; - f1ap_msg->srbs_to_be_setup = calloc(f1ap_msg->srbs_to_be_setup_length, sizeof(*f1ap_msg->srbs_to_be_setup)); - for (int i = 0; i < f1ap_msg->srbs_to_be_setup_length; ++i) - f1ap_msg->srbs_to_be_setup[i] = resp->srbs_to_be_setup[i]; - } - - AssertFatal(resp->srbs_failed_to_be_setup_length == 0 && resp->srbs_failed_to_be_setup == NULL, "not implemented yet\n"); - - DevAssert(resp->rrc_container == NULL && resp->rrc_container_length == 0); - + F1AP_UE_CONTEXT_MODIFICATION_RESP(msg) = cp_ue_context_mod_resp(resp); itti_send_msg_to_task(TASK_RRC_GNB, 0, msg); } diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c index 10b6206204..15101928e5 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c @@ -31,6 +31,7 @@ #include "lib/f1ap_rrc_message_transfer.h" #include "lib/f1ap_interface_management.h" +#include "lib/f1ap_ue_context.h" static f1ap_net_config_t read_DU_IP_config(const eth_params_t* f1_params, const char *f1u_ip_addr) { @@ -85,77 +86,17 @@ static void gnb_du_configuration_update_f1ap(const f1ap_gnb_du_configuration_upd itti_send_msg_to_task(TASK_DU_F1, 0, msg); } -static void ue_context_setup_response_f1ap(const f1ap_ue_context_setup_t *resp) +static void ue_context_setup_response_f1ap(const f1ap_ue_context_setup_resp_t *resp) { MessageDef *msg = itti_alloc_new_message (TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_SETUP_RESP); - f1ap_ue_context_setup_t *f1ap_msg = &F1AP_UE_CONTEXT_SETUP_RESP(msg); - /* copy all fields, but reallocate rrc_containers! */ - *f1ap_msg = *resp; - - if (resp->srbs_to_be_setup_length > 0) { - DevAssert(resp->srbs_to_be_setup != NULL); - f1ap_msg->srbs_to_be_setup_length = resp->srbs_to_be_setup_length; - f1ap_msg->srbs_to_be_setup = calloc(f1ap_msg->srbs_to_be_setup_length, sizeof(*f1ap_msg->srbs_to_be_setup)); - for (int i = 0; i < f1ap_msg->srbs_to_be_setup_length; ++i) - f1ap_msg->srbs_to_be_setup[i] = resp->srbs_to_be_setup[i]; - } - if (resp->drbs_to_be_setup_length > 0) { - DevAssert(resp->drbs_to_be_setup != NULL); - f1ap_msg->drbs_to_be_setup_length = resp->drbs_to_be_setup_length; - f1ap_msg->drbs_to_be_setup = calloc(f1ap_msg->drbs_to_be_setup_length, sizeof(*f1ap_msg->drbs_to_be_setup)); - for (int i = 0; i < f1ap_msg->drbs_to_be_setup_length; ++i) - f1ap_msg->drbs_to_be_setup[i] = resp->drbs_to_be_setup[i]; - } - if (resp->crnti) { - f1ap_msg->crnti = calloc(1, sizeof(uint16_t)); - *f1ap_msg->crnti = *resp->crnti; - } - - f1ap_msg->du_to_cu_rrc_information = malloc(sizeof(*resp->du_to_cu_rrc_information)); - AssertFatal(f1ap_msg->du_to_cu_rrc_information != NULL, "out of memory\n"); - f1ap_msg->du_to_cu_rrc_information_length = resp->du_to_cu_rrc_information_length; - du_to_cu_rrc_information_t *du2cu = f1ap_msg->du_to_cu_rrc_information; - du2cu->cellGroupConfig_length = resp->du_to_cu_rrc_information->cellGroupConfig_length; - du2cu->cellGroupConfig = calloc(du2cu->cellGroupConfig_length, sizeof(*du2cu->cellGroupConfig)); - AssertFatal(du2cu->cellGroupConfig != NULL, "out of memory\n"); - memcpy(du2cu->cellGroupConfig, resp->du_to_cu_rrc_information->cellGroupConfig, du2cu->cellGroupConfig_length); - + F1AP_UE_CONTEXT_SETUP_RESP(msg) = cp_ue_context_setup_resp(resp); itti_send_msg_to_task(TASK_DU_F1, 0, msg); } -static void ue_context_modification_response_f1ap(const f1ap_ue_context_modif_resp_t *resp) +static void ue_context_modification_response_f1ap(const f1ap_ue_context_mod_resp_t *resp) { MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_MODIFICATION_RESP); - f1ap_ue_context_modif_resp_t *f1ap_msg = &F1AP_UE_CONTEXT_MODIFICATION_RESP(msg); - /* copy all fields, but reallocate rrc_containers! */ - *f1ap_msg = *resp; - - if (resp->srbs_to_be_setup_length > 0) { - DevAssert(resp->srbs_to_be_setup != NULL); - f1ap_msg->srbs_to_be_setup_length = resp->srbs_to_be_setup_length; - f1ap_msg->srbs_to_be_setup = calloc(f1ap_msg->srbs_to_be_setup_length, sizeof(*f1ap_msg->srbs_to_be_setup)); - for (int i = 0; i < f1ap_msg->srbs_to_be_setup_length; ++i) - f1ap_msg->srbs_to_be_setup[i] = resp->srbs_to_be_setup[i]; - } - if (resp->drbs_to_be_setup_length > 0) { - DevAssert(resp->drbs_to_be_setup != NULL); - f1ap_msg->drbs_to_be_setup_length = resp->drbs_to_be_setup_length; - f1ap_msg->drbs_to_be_setup = calloc(f1ap_msg->drbs_to_be_setup_length, sizeof(*f1ap_msg->drbs_to_be_setup)); - for (int i = 0; i < f1ap_msg->drbs_to_be_setup_length; ++i) - f1ap_msg->drbs_to_be_setup[i] = resp->drbs_to_be_setup[i]; - } - - if (resp->du_to_cu_rrc_information != NULL) { - f1ap_msg->du_to_cu_rrc_information = calloc(1, sizeof(*resp->du_to_cu_rrc_information)); - AssertFatal(f1ap_msg->du_to_cu_rrc_information != NULL, "out of memory\n"); - f1ap_msg->du_to_cu_rrc_information_length = resp->du_to_cu_rrc_information_length; - du_to_cu_rrc_information_t *du2cu = f1ap_msg->du_to_cu_rrc_information; - du2cu->cellGroupConfig_length = resp->du_to_cu_rrc_information->cellGroupConfig_length; - du2cu->cellGroupConfig = calloc(du2cu->cellGroupConfig_length, sizeof(*du2cu->cellGroupConfig)); - AssertFatal(du2cu->cellGroupConfig != NULL, "out of memory\n"); - memcpy(du2cu->cellGroupConfig, resp->du_to_cu_rrc_information->cellGroupConfig, du2cu->cellGroupConfig_length); - } - + F1AP_UE_CONTEXT_MODIFICATION_RESP(msg) = cp_ue_context_mod_resp(resp); itti_send_msg_to_task(TASK_DU_F1, 0, msg); } diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h index 3ac774c69f..c49a419556 100644 --- a/openair2/RRC/NR/nr_rrc_proto.h +++ b/openair2/RRC/NR/nr_rrc_proto.h @@ -44,7 +44,7 @@ #define SRB2 2 void rrc_add_nsa_user(gNB_RRC_INST *rrc, x2ap_ENDC_sgnb_addition_req_t *m, sctp_assoc_t assoc_id); -void rrc_add_nsa_user_resp(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const f1ap_ue_context_setup_t *resp); +void rrc_add_nsa_user_resp(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const f1ap_ue_context_setup_resp_t *resp); void rrc_release_nsa_user(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context); void rrc_remove_nsa_user_context(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context); diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 6e53de1c10..eb51d4b799 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -1999,10 +1999,10 @@ void rrc_gNB_process_dc_overall_timeout(const module_id_t gnb_mod_idP, x2ap_ENDC /* \brief fill E1 bearer modification's DRB from F1 DRB * \param drb_e1 pointer to a DRB inside an E1 bearer modification message * \param drb_f1 pointer to a DRB inside an F1 UE Ctxt modification Response */ -static void fill_e1_bearer_modif(DRB_nGRAN_to_mod_t *drb_e1, const f1ap_drb_to_be_setup_t *drb_f1) +static void fill_e1_bearer_modif(DRB_nGRAN_to_mod_t *drb_e1, const f1ap_drb_setup_t *drb_f1) { - drb_e1->id = drb_f1->drb_id; - drb_e1->numDlUpParam = drb_f1->up_dl_tnl_length; + drb_e1->id = drb_f1->id; + drb_e1->numDlUpParam = drb_f1->up_dl_tnl_len; drb_e1->DlUpParamList[0].tl_info.tlAddress = drb_f1->up_dl_tnl[0].tl_address; drb_e1->DlUpParamList[0].tl_info.teId = drb_f1->up_dl_tnl[0].teid; } @@ -2019,20 +2019,20 @@ static gtpu_tunnel_t f1u_gtp_update(uint32_t teid, const in_addr_t addr) /** * @brief Update DRB TEID information in RRC storage from received DRB list */ -static void store_du_f1u_tunnel(const f1ap_drb_to_be_setup_t *drbs, int n, gNB_RRC_UE_t *ue) +static void store_du_f1u_tunnel(const f1ap_drb_setup_t *drbs, int n, gNB_RRC_UE_t *ue) { for (int i = 0; i < n; i++) { - const f1ap_drb_to_be_setup_t *drb_f1 = &drbs[i]; - AssertFatal(drb_f1->up_dl_tnl_length == 1, "can handle only one UP param\n"); - AssertFatal(drb_f1->drb_id < MAX_DRBS_PER_UE, "illegal DRB ID %ld\n", drb_f1->drb_id); - drb_t *drb = get_drb(ue, drb_f1->drb_id); + const f1ap_drb_setup_t *drb_f1 = &drbs[i]; + AssertFatal(drb_f1->up_dl_tnl_len == 1, "can handle only one UP param\n"); + AssertFatal(drb_f1->id < MAX_DRBS_PER_UE, "illegal DRB ID %d\n", drb_f1->id); + drb_t *drb = get_drb(ue, drb_f1->id); drb->du_tunnel_config = f1u_gtp_update(drb_f1->up_dl_tnl[0].teid, drb_f1->up_dl_tnl[0].tl_address); } } /* \brief use list of DRBs and send the corresponding bearer update message via * E1 to the CU of this UE. Also updates TEID info internally */ -static void e1_send_bearer_updates(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, f1ap_drb_to_be_setup_t *drbs) +static void e1_send_bearer_updates(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, f1ap_drb_setup_t *drbs) { // Quit bearer updates if no CU-UP is associated if (!is_cuup_associated(rrc)) { @@ -2046,10 +2046,10 @@ static void e1_send_bearer_updates(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, f }; for (int i = 0; i < n; i++) { - const f1ap_drb_to_be_setup_t *drb_f1 = &drbs[i]; - rrc_pdu_session_param_t *pdu_ue = find_pduSession_from_drbId(UE, drb_f1->drb_id); + const f1ap_drb_setup_t *drb_f1 = &drbs[i]; + rrc_pdu_session_param_t *pdu_ue = find_pduSession_from_drbId(UE, drb_f1->id); if (pdu_ue == NULL) { - LOG_E(RRC, "UE %d: UE Context Modif Response: no PDU session for DRB ID %ld\n", UE->rrc_ue_id, drb_f1->drb_id); + LOG_E(RRC, "UE %d: UE Context Modif Response: no PDU session for DRB ID %d\n", UE->rrc_ue_id, drb_f1->id); continue; } pdu_session_to_mod_t *pdu_e1 = find_or_next_pdu_session(&req, pdu_ue->param.pdusession_id); @@ -2074,7 +2074,7 @@ static void e1_send_bearer_updates(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, f static void rrc_CU_process_ue_context_setup_response(MessageDef *msg_p, instance_t instance) { - f1ap_ue_context_setup_t *resp = &F1AP_UE_CONTEXT_SETUP_RESP(msg_p); + f1ap_ue_context_setup_resp_t *resp = &F1AP_UE_CONTEXT_SETUP_RESP(msg_p); gNB_RRC_INST *rrc = RC.nrrrc[instance]; rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(rrc, resp->gNB_CU_ue_id); if (!ue_context_p) { @@ -2085,11 +2085,9 @@ static void rrc_CU_process_ue_context_setup_response(MessageDef *msg_p, instance UE->f1_ue_context_active = true; NR_CellGroupConfig_t *cellGroupConfig = NULL; - asn_dec_rval_t dec_rval = uper_decode_complete(NULL, - &asn_DEF_NR_CellGroupConfig, - (void **)&cellGroupConfig, - (uint8_t *)resp->du_to_cu_rrc_information->cellGroupConfig, - resp->du_to_cu_rrc_information->cellGroupConfig_length); + byte_array_t *cgc = &resp->du_to_cu_rrc_info.cell_group_config; + asn_dec_rval_t dec_rval = + uper_decode_complete(NULL, &asn_DEF_NR_CellGroupConfig, (void **)&cellGroupConfig, (uint8_t *)cgc->buf, cgc->len); AssertFatal(dec_rval.code == RC_OK && dec_rval.consumed > 0, "Cell group config decode error\n"); if (UE->masterCellGroup) { @@ -2105,16 +2103,16 @@ static void rrc_CU_process_ue_context_setup_response(MessageDef *msg_p, instance return; } - if (resp->drbs_to_be_setup_length > 0) { + if (resp->drbs_len > 0) { int num_drb = get_number_active_drbs(UE); - DevAssert(num_drb == 0 || num_drb == resp->drbs_to_be_setup_length); + DevAssert(num_drb == 0 || num_drb == resp->drbs_len); /* Note: we would ideally check that SRB2 is acked, but at least LiteOn DU * seems buggy and does not ack, so simply check that locally we activated */ AssertFatal(UE->Srb[1].Active && UE->Srb[2].Active, "SRBs 1 and 2 must be active during DRB Establishment"); - store_du_f1u_tunnel(resp->drbs_to_be_setup, resp->drbs_to_be_setup_length, UE); + store_du_f1u_tunnel(resp->drbs, resp->drbs_len, UE); if (num_drb == 0) - e1_send_bearer_updates(rrc, UE, resp->drbs_to_be_setup_length, resp->drbs_to_be_setup); + e1_send_bearer_updates(rrc, UE, resp->drbs_len, resp->drbs); else cuup_notify_reestablishment(rrc, UE); } @@ -2232,7 +2230,7 @@ static void rrc_CU_process_ue_context_release_complete(MessageDef *msg_p) static void rrc_CU_process_ue_context_modification_response(MessageDef *msg_p, instance_t instance) { - f1ap_ue_context_modif_resp_t *resp = &F1AP_UE_CONTEXT_MODIFICATION_RESP(msg_p); + f1ap_ue_context_mod_resp_t *resp = &F1AP_UE_CONTEXT_MODIFICATION_RESP(msg_p); gNB_RRC_INST *rrc = RC.nrrrc[instance]; rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(rrc, resp->gNB_CU_ue_id); if (!ue_context_p) { @@ -2241,18 +2239,16 @@ static void rrc_CU_process_ue_context_modification_response(MessageDef *msg_p, i } gNB_RRC_UE_t *UE = &ue_context_p->ue_context; - if (resp->drbs_to_be_setup_length > 0) { - store_du_f1u_tunnel(resp->drbs_to_be_setup, resp->drbs_to_be_setup_length, UE); - e1_send_bearer_updates(rrc, UE, resp->drbs_to_be_setup_length, resp->drbs_to_be_setup); + if (resp->drbs_len > 0) { + store_du_f1u_tunnel(resp->drbs, resp->drbs_len, UE); + e1_send_bearer_updates(rrc, UE, resp->drbs_len, resp->drbs); } - if (resp->du_to_cu_rrc_information != NULL && resp->du_to_cu_rrc_information->cellGroupConfig != NULL) { + if (resp->du_to_cu_rrc_info) { NR_CellGroupConfig_t *cellGroupConfig = NULL; - asn_dec_rval_t dec_rval = uper_decode_complete(NULL, - &asn_DEF_NR_CellGroupConfig, - (void **)&cellGroupConfig, - (uint8_t *)resp->du_to_cu_rrc_information->cellGroupConfig, - resp->du_to_cu_rrc_information->cellGroupConfig_length); + byte_array_t *cgc = &resp->du_to_cu_rrc_info->cell_group_config; + asn_dec_rval_t dec_rval = + uper_decode_complete(NULL, &asn_DEF_NR_CellGroupConfig, (void **)&cellGroupConfig, (uint8_t *)cgc->buf, cgc->len); AssertFatal(dec_rval.code == RC_OK && dec_rval.consumed > 0, "Cell group config decode error\n"); if (UE->masterCellGroup) { @@ -2769,10 +2765,12 @@ void *rrc_gnb_task(void *args_p) { case F1AP_UE_CONTEXT_SETUP_RESP: rrc_CU_process_ue_context_setup_response(msg_p, instance); + free_ue_context_setup_resp(&F1AP_UE_CONTEXT_SETUP_RESP(msg_p)); break; case F1AP_UE_CONTEXT_MODIFICATION_RESP: rrc_CU_process_ue_context_modification_response(msg_p, instance); + free_ue_context_mod_resp(&F1AP_UE_CONTEXT_MODIFICATION_RESP(msg_p)); break; case F1AP_UE_CONTEXT_MODIFICATION_REQUIRED: diff --git a/openair2/RRC/NR/rrc_gNB_nsa.c b/openair2/RRC/NR/rrc_gNB_nsa.c index 1ccdb3439a..78be16b100 100644 --- a/openair2/RRC/NR/rrc_gNB_nsa.c +++ b/openair2/RRC/NR/rrc_gNB_nsa.c @@ -385,7 +385,7 @@ static NR_CG_Config_t *generate_CG_Config(const NR_RRCReconfiguration_t *reconfi return cg_Config; } -void rrc_add_nsa_user_resp(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const f1ap_ue_context_setup_t *resp) +void rrc_add_nsa_user_resp(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const f1ap_ue_context_setup_resp_t *resp) { DevAssert(resp->crnti != NULL); /* we did not fill any DU-related ID info in rrc_add_nsa_user() */ @@ -400,12 +400,12 @@ void rrc_add_nsa_user_resp(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const f1ap_ue_co if (f1inst >= 0) { // Note: E1 support for NSA/phy-test/do-ra not implemented yet // so set up GTP from here - for (int i = 0; i < resp->drbs_to_be_setup_length; ++i) { - f1ap_drb_to_be_setup_t *drb = &resp->drbs_to_be_setup[i]; - DevAssert(drb->up_dl_tnl_length == 1); + for (int i = 0; i < resp->drbs_len; ++i) { + f1ap_drb_setup_t *drb = &resp->drbs[i]; + DevAssert(drb->up_dl_tnl_len == 1); in_addr_t addr = drb->up_dl_tnl[0].tl_address; uint32_t teid = drb->up_dl_tnl[0].teid; - GtpuUpdateTunnelOutgoingAddressAndTeid(f1inst, UE->rrc_ue_id, drb->drb_id, addr, teid); + GtpuUpdateTunnelOutgoingAddressAndTeid(f1inst, UE->rrc_ue_id, drb->id, addr, teid); } } From 4d08801e9a87355d3e7dde263b13a2b95a4afbc5 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 19 Jun 2025 18:14:14 +0200 Subject: [PATCH 125/964] Refactor: use malloc to avoid mem leaks Move the filling of DRBs to set up for UE context setup/modification request into the corresponding functions, and use malloc() deliberately to avoid memory leaks. In fact fill_drb_to_be_setup_from_e1_resp() allocates memory dynamically (and has to do that), so the easiest is to do the same for DRBs. The most straight-forward way seems to be to then dynamically allocate all memory for F1 UE context setup/modification request messages, and free with the corresponding free functions, which removes a couple of memory leaks. --- openair2/RRC/NR/nr_rrc_proto.h | 6 ++-- openair2/RRC/NR/rrc_gNB.c | 65 +++++++++++++++++++--------------- 2 files changed, 39 insertions(+), 32 deletions(-) diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h index c49a419556..094f1791c1 100644 --- a/openair2/RRC/NR/nr_rrc_proto.h +++ b/openair2/RRC/NR/nr_rrc_proto.h @@ -106,13 +106,11 @@ int rrc_gNB_generate_pcch_msg(sctp_assoc_t assoc_id, const NR_SIB1_t *sib, uint3 void rrc_gNB_generate_UeContextSetupRequest(const gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *const ue_context_pP, - int n_drbs, - const f1ap_drb_to_setup_t *drbs); + const e1ap_bearer_setup_resp_t *resp); void rrc_gNB_generate_UeContextModificationRequest(const gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *const ue_context_pP, - int n_drbs, - const f1ap_drb_to_setup_t *drbs, + const e1ap_bearer_setup_resp_t *resp, int n_rel_drbs, const f1ap_drb_to_release_t *rel_drbs); diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index eb51d4b799..096e67ce0a 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -2483,14 +2483,10 @@ void rrc_gNB_process_e1_bearer_context_setup_resp(e1ap_bearer_setup_resp_t *resp } } - /* Instruction towards the DU for DRB configuration and tunnel creation */ - f1ap_drb_to_setup_t drbs[32]; // maximum DRB can be 32 - int nb_drb = fill_drb_to_be_setup_from_e1_resp(rrc, UE, resp->pduSession, resp->numPDUSessions, drbs); - if (!UE->f1_ue_context_active) - rrc_gNB_generate_UeContextSetupRequest(rrc, ue_context_p, nb_drb, drbs); + rrc_gNB_generate_UeContextSetupRequest(rrc, ue_context_p, resp); else - rrc_gNB_generate_UeContextModificationRequest(rrc, ue_context_p, nb_drb, drbs, 0, NULL); + rrc_gNB_generate_UeContextModificationRequest(rrc, ue_context_p, resp, 0, NULL); } /** @brief E1AP Bearer Context Setup Failure processing on CU-CP */ @@ -3023,8 +3019,7 @@ int rrc_gNB_generate_pcch_msg(sctp_assoc_t assoc_id, const NR_SIB1_t *sib1, uint //----------------------------------------------------------------------------- void rrc_gNB_generate_UeContextSetupRequest(const gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *const ue_context_pP, - int n_drbs, - const f1ap_drb_to_setup_t *drbs) + const e1ap_bearer_setup_resp_t *resp) //----------------------------------------------------------------------------- { gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; @@ -3033,25 +3028,31 @@ void rrc_gNB_generate_UeContextSetupRequest(const gNB_RRC_INST *rrc, AssertFatal(!NODE_IS_DU(rrc->node_type), "illegal node type DU!\n"); f1ap_cu_to_du_rrc_info_t cu2du = {0}; - if (ue_p->ue_cap_buffer.len > 0 && ue_p->ue_cap_buffer.buf != NULL) { - cu2du.ue_cap = &ue_p->ue_cap_buffer; + if (ue_p->ue_cap_buffer.len > 0) { + cu2du.ue_cap = malloc_or_fail(sizeof(byte_array_t)); + *cu2du.ue_cap = copy_byte_array(ue_p->ue_cap_buffer); } int nb_srb = 1; - f1ap_srb_to_setup_t srbs[1] = {{.id = 2, }}; - activate_srb(ue_p, 2); + f1ap_srb_to_setup_t *srbs = calloc_or_fail(nb_srb, sizeof(*srbs)); + srbs[0].id = 2; + activate_srb(ue_p, srbs[0].id); + + /* Instruction towards the DU for DRB configuration and tunnel creation */ + f1ap_drb_to_setup_t *drbs = calloc_or_fail(32, sizeof(*drbs)); // maximum DRB can be 32 + int n_drbs = fill_drb_to_be_setup_from_e1_resp(rrc, ue_p, resp->pduSession, resp->numPDUSessions, drbs); /* gNB-DU UE Aggregate Maximum Bit Rate Uplink is C- ifDRBSetup */ - uint64_t agg_mbr = 1000000000 /* bps */, *agg_mbr_p = NULL; - if (n_drbs > 0) - agg_mbr_p = &agg_mbr; + uint64_t *agg_mbr = malloc_or_fail(sizeof(*agg_mbr)); + *agg_mbr = 1000000000 /* bps */; - /* the callback will fill the UE context setup request and forward it */ f1_ue_data_t ue_data = cu_get_f1_ue_data(ue_p->rrc_ue_id); RETURN_IF_INVALID_ASSOC_ID(ue_data.du_assoc_id); + uint32_t *du_ue_id = malloc_or_fail(sizeof(*du_ue_id)); + *du_ue_id = ue_data.secondary_ue; f1ap_ue_context_setup_req_t ue_context_setup_req = { .gNB_CU_ue_id = ue_p->rrc_ue_id, - .gNB_DU_ue_id = &ue_data.secondary_ue, + .gNB_DU_ue_id = du_ue_id, .plmn.mcc = rrc->configuration.plmn[0].mcc, .plmn.mnc = rrc->configuration.plmn[0].mnc, .plmn.mnc_digit_length = rrc->configuration.plmn[0].mnc_digit_length, @@ -3060,21 +3061,20 @@ void rrc_gNB_generate_UeContextSetupRequest(const gNB_RRC_INST *rrc, .srbs_len = nb_srb, .srbs = srbs, .drbs_len = n_drbs, - .drbs = (f1ap_drb_to_setup_t *) drbs, // cast to avoid warning on const + .drbs = drbs, .cu_to_du_rrc_info = cu2du, - .gnb_du_ue_agg_mbr_ul = agg_mbr_p, + .gnb_du_ue_agg_mbr_ul = agg_mbr, }; rrc->mac_rrc.ue_context_setup_request(ue_data.du_assoc_id, &ue_context_setup_req); + free_ue_context_setup_req(&ue_context_setup_req); LOG_I(RRC, "UE %d trigger UE context setup request with %d DRBs\n", ue_p->rrc_ue_id, n_drbs); - // nothing to free for ue_context_setup_req } //----------------------------------------------------------------------------- void rrc_gNB_generate_UeContextModificationRequest(const gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *const ue_context_pP, - int n_drbs, - const f1ap_drb_to_setup_t *drbs, + const e1ap_bearer_setup_resp_t *resp, int n_rel_drbs, const f1ap_drb_to_release_t *rel_drbs) //----------------------------------------------------------------------------- @@ -3085,23 +3085,32 @@ void rrc_gNB_generate_UeContextModificationRequest(const gNB_RRC_INST *rrc, AssertFatal(!NODE_IS_DU(rrc->node_type), "illegal node type DU!\n"); - f1ap_cu_to_du_rrc_info_t cu2du = {0}; - if (ue_p->ue_cap_buffer.len > 0 && ue_p->ue_cap_buffer.buf != NULL) { - cu2du.ue_cap = &ue_p->ue_cap_buffer; + f1ap_cu_to_du_rrc_info_t *cu2du = NULL; + if (ue_p->ue_cap_buffer.len > 0) { + cu2du = calloc_or_fail(1, sizeof(*cu2du)); + cu2du->ue_cap = calloc_or_fail(1, sizeof(*cu2du->ue_cap)); + *cu2du->ue_cap = copy_byte_array(ue_p->ue_cap_buffer); } + /* Instruction towards the DU for DRB configuration and tunnel creation */ + f1ap_drb_to_setup_t *drbs = calloc_or_fail(32, sizeof(*drbs)); // maximum DRB can be 32 + int n_drbs = fill_drb_to_be_setup_from_e1_resp(rrc, ue_p, resp->pduSession, resp->numPDUSessions, drbs); + f1_ue_data_t ue_data = cu_get_f1_ue_data(ue_p->rrc_ue_id); RETURN_IF_INVALID_ASSOC_ID(ue_data.du_assoc_id); f1ap_ue_context_mod_req_t ue_context_modif_req = { .gNB_CU_ue_id = ue_p->rrc_ue_id, .gNB_DU_ue_id = ue_data.secondary_ue, .drbs_len = n_drbs, - .drbs = (f1ap_drb_to_setup_t *)drbs, + .drbs = drbs, .drbs_rel_len = n_rel_drbs, .drbs_rel = (f1ap_drb_to_release_t *)rel_drbs, - .cu_to_du_rrc_info = &cu2du, + .cu_to_du_rrc_info = cu2du, }; rrc->mac_rrc.ue_context_modification_request(ue_data.du_assoc_id, &ue_context_modif_req); + // avoid attempt to release rel_drbs + ue_context_modif_req.drbs_rel_len = 0; + ue_context_modif_req.drbs_rel = NULL; + free_ue_context_mod_req(&ue_context_modif_req); LOG_I(RRC, "UE %d trigger UE context modification request with %d DRBs\n", ue_p->rrc_ue_id, n_drbs); - // nothing to free } From d13c94457ae11a9264d910718f0634dd8eb563d9 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 11 Jun 2025 07:59:29 +0200 Subject: [PATCH 126/964] Add F1AP UE context release request message enc/dec + test See commit "Add F1AP UE context setup request message enc/dec + test" for more details on the approach taken. --- openair2/COMMON/f1ap_messages_types.h | 7 ++ openair2/F1AP/lib/f1ap_ue_context.c | 112 ++++++++++++++++++++++++++ openair2/F1AP/lib/f1ap_ue_context.h | 6 ++ openair2/F1AP/tests/f1ap_lib_test.c | 32 ++++++++ 4 files changed, 157 insertions(+) diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h index 9394daa7f0..c67a97b0f8 100644 --- a/openair2/COMMON/f1ap_messages_types.h +++ b/openair2/COMMON/f1ap_messages_types.h @@ -649,6 +649,13 @@ typedef struct f1ap_ue_context_modif_refuse_t { long cause_value; } f1ap_ue_context_modif_refuse_t; +typedef struct f1ap_ue_context_rel_req_t { + uint32_t gNB_CU_ue_id; + uint32_t gNB_DU_ue_id; + f1ap_Cause_t cause; + long cause_value; +} f1ap_ue_context_rel_req_t; + typedef struct f1ap_ue_context_release_s { uint32_t gNB_CU_ue_id; uint32_t gNB_DU_ue_id; diff --git a/openair2/F1AP/lib/f1ap_ue_context.c b/openair2/F1AP/lib/f1ap_ue_context.c index 588648fe37..53f1e11c67 100644 --- a/openair2/F1AP/lib/f1ap_ue_context.c +++ b/openair2/F1AP/lib/f1ap_ue_context.c @@ -2087,3 +2087,115 @@ void free_ue_context_mod_resp(f1ap_ue_context_mod_resp_t *resp) free_srb_setup(&resp->srbs[i]); free(resp->srbs); } + +/* + * @brief Encode F1 UE context release request to ASN.1 + */ +struct F1AP_F1AP_PDU *encode_ue_context_rel_req(const f1ap_ue_context_rel_req_t *msg) +{ + F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); + + /* Message Type */ + pdu->present = F1AP_F1AP_PDU_PR_initiatingMessage; + asn1cCalloc(pdu->choice.initiatingMessage, tmp); + tmp->procedureCode = F1AP_ProcedureCode_id_UEContextReleaseRequest; + tmp->criticality = F1AP_Criticality_reject; + tmp->value.present = F1AP_InitiatingMessage__value_PR_UEContextReleaseRequest; + F1AP_UEContextReleaseRequest_t *out = &tmp->value.choice.UEContextReleaseRequest; + + /* mandatory: GNB_CU_UE_F1AP_ID */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseRequestIEs_t, ie1); + ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; + ie1->criticality = F1AP_Criticality_reject; + ie1->value.present = F1AP_UEContextReleaseRequestIEs__value_PR_GNB_CU_UE_F1AP_ID; + ie1->value.choice.GNB_CU_UE_F1AP_ID = msg->gNB_CU_ue_id; + + /* mandatory: GNB_DU_UE_F1AP_ID */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseRequestIEs_t, ie2); + ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; + ie2->criticality = F1AP_Criticality_reject; + ie2->value.present = F1AP_UEContextReleaseRequestIEs__value_PR_GNB_DU_UE_F1AP_ID; + ie2->value.choice.GNB_DU_UE_F1AP_ID = msg->gNB_DU_ue_id; + + /* mandatory: Cause */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseRequestIEs_t, ie3); + ie3->id = F1AP_ProtocolIE_ID_id_Cause; + ie3->criticality = F1AP_Criticality_ignore; + ie3->value.present = F1AP_UEContextReleaseRequestIEs__value_PR_Cause; + ie3->value.choice.Cause = encode_f1ap_cause(msg->cause, msg->cause_value); + + return pdu; +} + +/** + * @brief Decode F1 UE Context Release Request + */ +bool decode_ue_context_rel_req(const struct F1AP_F1AP_PDU *pdu, f1ap_ue_context_rel_req_t *out) +{ + DevAssert(out != NULL); + memset(out, 0, sizeof(*out)); + + F1AP_UEContextReleaseRequest_t *in = &pdu->choice.initiatingMessage->value.choice.UEContextReleaseRequest; + F1AP_UEContextReleaseRequestIEs_t *ie; + F1AP_LIB_FIND_IE(F1AP_UEContextReleaseRequestIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); + F1AP_LIB_FIND_IE(F1AP_UEContextReleaseRequestIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); + F1AP_LIB_FIND_IE(F1AP_UEContextReleaseRequestIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_Cause, true); + + for (int i = 0; i < in->protocolIEs.list.count; ++i) { + ie = in->protocolIEs.list.array[i]; + AssertError(ie != NULL, return false, "in->protocolIEs.list.array[i] is NULL"); + switch (ie->id) { + case F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextReleaseRequestIEs__value_PR_GNB_CU_UE_F1AP_ID); + out->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID; + break; + case F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextReleaseRequestIEs__value_PR_GNB_DU_UE_F1AP_ID); + out->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; + break; + case F1AP_ProtocolIE_ID_id_Cause: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextReleaseRequestIEs__value_PR_Cause); + _F1_CHECK_EXP(decode_f1ap_cause(ie->value.choice.Cause, &out->cause, &out->cause_value)); + break; + default: + PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld unknown, skipping\n", ie->id); + break; + } + } + + return true; +} + +/** + * @brief F1 UE Context Release Request deep copy + */ +f1ap_ue_context_rel_req_t cp_ue_context_rel_req(const f1ap_ue_context_rel_req_t *orig) +{ + f1ap_ue_context_rel_req_t cp = { + .gNB_CU_ue_id = orig->gNB_CU_ue_id, + .gNB_DU_ue_id = orig->gNB_DU_ue_id, + .cause = orig->cause, + .cause_value = orig->cause_value, + }; + return cp; +} + +/** + * @brief F1 UE Context Release Request equality check + */ +bool eq_ue_context_rel_req(const f1ap_ue_context_rel_req_t *a, const f1ap_ue_context_rel_req_t *b) +{ + _F1_EQ_CHECK_INT(a->gNB_CU_ue_id, b->gNB_CU_ue_id); + _F1_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id); + _F1_EQ_CHECK_INT(a->cause, b->cause); + _F1_EQ_CHECK_LONG(a->cause_value, b->cause_value); + return true; +} + +/** + * @brief Free Allocated F1 UE Context Release Request + */ +void free_ue_context_rel_req(f1ap_ue_context_rel_req_t *req) +{ + // nothing to free +} diff --git a/openair2/F1AP/lib/f1ap_ue_context.h b/openair2/F1AP/lib/f1ap_ue_context.h index ddf41689e0..5e683fe1ab 100644 --- a/openair2/F1AP/lib/f1ap_ue_context.h +++ b/openair2/F1AP/lib/f1ap_ue_context.h @@ -51,4 +51,10 @@ f1ap_ue_context_mod_resp_t cp_ue_context_mod_resp(const f1ap_ue_context_mod_resp bool eq_ue_context_mod_resp(const f1ap_ue_context_mod_resp_t *a, const f1ap_ue_context_mod_resp_t *b); void free_ue_context_mod_resp(f1ap_ue_context_mod_resp_t *resp); +struct F1AP_F1AP_PDU *encode_ue_context_rel_req(const f1ap_ue_context_rel_req_t *msg); +bool decode_ue_context_rel_req(const struct F1AP_F1AP_PDU *pdu, f1ap_ue_context_rel_req_t *out); +f1ap_ue_context_rel_req_t cp_ue_context_rel_req(const f1ap_ue_context_rel_req_t *orig); +bool eq_ue_context_rel_req(const f1ap_ue_context_rel_req_t *a, const f1ap_ue_context_rel_req_t *b); +void free_ue_context_rel_req(f1ap_ue_context_rel_req_t *req); + #endif /* F1AP_UE_CONTEXT_SETUP_REQ_H_ */ diff --git a/openair2/F1AP/tests/f1ap_lib_test.c b/openair2/F1AP/tests/f1ap_lib_test.c index 5baac1f5c6..a26a80823e 100644 --- a/openair2/F1AP/tests/f1ap_lib_test.c +++ b/openair2/F1AP/tests/f1ap_lib_test.c @@ -1171,6 +1171,37 @@ static void test_f1ap_ue_context_modification_response_simple() printf("%s() successful\n", __func__); } +static void test_f1ap_ue_context_release_request() +{ + f1ap_ue_context_rel_req_t orig = { + .gNB_CU_ue_id = 1111, + .gNB_DU_ue_id = 2222, + .cause = F1AP_CAUSE_MISC, + .cause_value = 3, + }; + + F1AP_F1AP_PDU_t *f1enc = encode_ue_context_rel_req(&orig); + F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + + f1ap_ue_context_rel_req_t decoded = {0}; + bool ret = decode_ue_context_rel_req(f1dec, &decoded); + AssertFatal(ret, "decode_ue_context_rel_req(): could not decode message\n"); + f1ap_msg_free(f1dec); + + ret = eq_ue_context_rel_req(&orig, &decoded); + AssertFatal(ret, "eq_ue_context_rel_req(): decoded message doesn't match\n"); + free_ue_context_rel_req(&decoded); + + f1ap_ue_context_rel_req_t cp = cp_ue_context_rel_req(&orig); + ret = eq_ue_context_rel_req(&orig, &cp); + AssertFatal(ret, "eq_ue_context_rel_req(): copied message doesn't match\n"); + free_ue_context_rel_req(&orig); + free_ue_context_rel_req(&cp); + + printf("%s() successful\n", __func__); +} + int main() { test_initial_ul_rrc_message_transfer(); @@ -1194,5 +1225,6 @@ int main() test_f1ap_ue_context_modification_request_simple(); test_f1ap_ue_context_modification_response(); test_f1ap_ue_context_modification_response_simple(); + test_f1ap_ue_context_release_request(); return 0; } From f7d747164da19b63c672a5df00daba1b9dab577c Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 19 Jun 2025 16:59:23 +0200 Subject: [PATCH 127/964] Use F1 UE context Release Request in stack Switch to the new type, remove the old one. --- openair2/COMMON/f1ap_messages_def.h | 2 +- openair2/COMMON/f1ap_messages_types.h | 2 +- openair2/F1AP/f1ap_cu_ue_context_management.c | 57 +++------------ openair2/F1AP/f1ap_du_ue_context_management.c | 72 +++---------------- openair2/F1AP/f1ap_du_ue_context_management.h | 4 +- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 2 +- .../LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c | 2 +- openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h | 2 +- .../LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c | 5 +- openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c | 5 +- openair2/RRC/NR/rrc_gNB.c | 3 +- 11 files changed, 28 insertions(+), 128 deletions(-) diff --git a/openair2/COMMON/f1ap_messages_def.h b/openair2/COMMON/f1ap_messages_def.h index 5681848029..e9776c58ff 100644 --- a/openair2/COMMON/f1ap_messages_def.h +++ b/openair2/COMMON/f1ap_messages_def.h @@ -48,7 +48,7 @@ MESSAGE_DEF(F1AP_INITIAL_UL_RRC_MESSAGE , MESSAGE_PRIORITY_MED, f1ap_i MESSAGE_DEF(F1AP_UL_RRC_MESSAGE , MESSAGE_PRIORITY_MED, f1ap_ul_rrc_message_t , f1ap_ul_rrc_message) //MESSAGE_DEF(F1AP_INITIAL_CONTEXT_SETUP_RESP, MESSAGE_PRIORITY_MED, f1ap_initial_context_setup_resp_t, f1ap_initial_context_setup_resp) //MESSAGE_DEF(F1AP_INITIAL_CONTEXT_SETUP_FAILURE, MESSAGE_PRIORITY_MED, f1ap_initial_context_setup_failure_t, f1ap_initial_context_setup_failure) -MESSAGE_DEF(F1AP_UE_CONTEXT_RELEASE_REQ, MESSAGE_PRIORITY_MED, f1ap_ue_context_release_req_t, f1ap_ue_context_release_req) +MESSAGE_DEF(F1AP_UE_CONTEXT_RELEASE_REQ, MESSAGE_PRIORITY_MED, f1ap_ue_context_rel_req_t, f1ap_ue_context_release_req) MESSAGE_DEF(F1AP_UE_CONTEXT_RELEASE_CMD, MESSAGE_PRIORITY_MED, f1ap_ue_context_release_cmd_t, f1ap_ue_context_release_cmd) MESSAGE_DEF(F1AP_UE_CONTEXT_RELEASE_COMPLETE, MESSAGE_PRIORITY_MED, f1ap_ue_context_release_complete_t, f1ap_ue_context_release_complete) MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_REQUIRED, MESSAGE_PRIORITY_MED, f1ap_ue_context_modif_required_t, f1ap_ue_context_modification_required) diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h index c67a97b0f8..57365c931e 100644 --- a/openair2/COMMON/f1ap_messages_types.h +++ b/openair2/COMMON/f1ap_messages_types.h @@ -664,7 +664,7 @@ typedef struct f1ap_ue_context_release_s { uint8_t *rrc_container; int rrc_container_length; int srb_id; -} f1ap_ue_context_release_req_t, f1ap_ue_context_release_cmd_t, f1ap_ue_context_release_complete_t; +} f1ap_ue_context_release_cmd_t, f1ap_ue_context_release_complete_t; typedef struct f1ap_paging_ind_s { uint16_t ueidentityindexvalue; diff --git a/openair2/F1AP/f1ap_cu_ue_context_management.c b/openair2/F1AP/f1ap_cu_ue_context_management.c index 597c20d258..e0f1495f86 100644 --- a/openair2/F1AP/f1ap_cu_ue_context_management.c +++ b/openair2/F1AP/f1ap_cu_ue_context_management.c @@ -90,58 +90,17 @@ int CU_handle_UE_CONTEXT_SETUP_FAILURE(instance_t instance, sctp_assoc_t assoc_i int CU_handle_UE_CONTEXT_RELEASE_REQUEST(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { + f1ap_ue_context_rel_req_t req = {0}; + if (!decode_ue_context_rel_req(pdu, &req)) { + LOG_E(F1AP, "cannot decode F1 UE Context Release Request\n"); + free_ue_context_rel_req(&req); + return -1; + } + MessageDef *msg = itti_alloc_new_message(TASK_CU_F1, 0, F1AP_UE_CONTEXT_RELEASE_REQ); msg->ittiMsgHeader.originInstance = assoc_id; - f1ap_ue_context_release_req_t *req = &F1AP_UE_CONTEXT_RELEASE_REQ(msg); - F1AP_UEContextReleaseRequest_t *container; - F1AP_UEContextReleaseRequestIEs_t *ie; - DevAssert(pdu); - container = &pdu->choice.initiatingMessage->value.choice.UEContextReleaseRequest; - /* GNB_CU_UE_F1AP_ID */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextReleaseRequestIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); - req->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID; - - /* GNB_DU_UE_F1AP_ID */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextReleaseRequestIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); - req->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; - - /* Cause */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextReleaseRequestIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_Cause, true); - - switch(ie->value.choice.Cause.present) - { - case F1AP_Cause_PR_radioNetwork: - req->cause = F1AP_CAUSE_RADIO_NETWORK; - req->cause_value = ie->value.choice.Cause.choice.radioNetwork; - break; - case F1AP_Cause_PR_transport: - req->cause = F1AP_CAUSE_TRANSPORT; - req->cause_value = ie->value.choice.Cause.choice.transport; - break; - case F1AP_Cause_PR_protocol: - req->cause = F1AP_CAUSE_PROTOCOL; - req->cause_value = ie->value.choice.Cause.choice.protocol; - break; - case F1AP_Cause_PR_misc: - req->cause = F1AP_CAUSE_MISC; - req->cause_value = ie->value.choice.Cause.choice.misc; - break; - case F1AP_Cause_PR_NOTHING: - default: - req->cause = F1AP_CAUSE_NOTHING; - break; - } - - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextReleaseRequestIEs_t, ie, container, F1AP_ProtocolIE_ID_id_targetCellsToCancel, false); - if (ie != NULL) { - LOG_W(F1AP, "ignoring list of target cells to cancel in UE Context Release Request: implementation missing\n"); - } - + F1AP_UE_CONTEXT_RELEASE_REQ(msg) = req; itti_send_msg_to_task(TASK_RRC_GNB, instance, msg); - return 0; } diff --git a/openair2/F1AP/f1ap_du_ue_context_management.c b/openair2/F1AP/f1ap_du_ue_context_management.c index e6d36f9019..a2179b8583 100644 --- a/openair2/F1AP/f1ap_du_ue_context_management.c +++ b/openair2/F1AP/f1ap_du_ue_context_management.c @@ -76,75 +76,19 @@ int DU_send_UE_CONTEXT_SETUP_FAILURE(sctp_assoc_t assoc_id) AssertFatal(1==0,"Not implemented yet\n"); } -int DU_send_UE_CONTEXT_RELEASE_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_context_release_req_t *req) +int DU_send_UE_CONTEXT_RELEASE_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_context_rel_req_t *req) { - F1AP_F1AP_PDU_t pdu = {0}; - F1AP_UEContextReleaseRequest_t *out; - uint8_t *buffer=NULL; - uint32_t len=0; - /* Create */ - /* 0. Message Type */ - pdu.present = F1AP_F1AP_PDU_PR_initiatingMessage; - asn1cCalloc(pdu.choice.initiatingMessage, tmp); - tmp->procedureCode = F1AP_ProcedureCode_id_UEContextReleaseRequest; - tmp->criticality = F1AP_Criticality_reject; - tmp->value.present = F1AP_InitiatingMessage__value_PR_UEContextReleaseRequest; - out = &tmp->value.choice.UEContextReleaseRequest; - /* mandatory */ - /* c1. GNB_CU_UE_F1AP_ID */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseRequestIEs_t, ie1); - ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; - ie1->criticality = F1AP_Criticality_reject; - ie1->value.present = F1AP_UEContextReleaseRequestIEs__value_PR_GNB_CU_UE_F1AP_ID; - ie1->value.choice.GNB_CU_UE_F1AP_ID = req->gNB_CU_ue_id; - /* mandatory */ - /* c2. GNB_DU_UE_F1AP_ID */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseRequestIEs_t, ie2); - ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; - ie2->criticality = F1AP_Criticality_reject; - ie2->value.present = F1AP_UEContextReleaseRequestIEs__value_PR_GNB_DU_UE_F1AP_ID; - ie2->value.choice.GNB_DU_UE_F1AP_ID = req->gNB_DU_ue_id; - /* mandatory */ - /* c3. Cause */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseRequestIEs_t, ie3); - ie3->id = F1AP_ProtocolIE_ID_id_Cause; - ie3->criticality = F1AP_Criticality_ignore; - ie3->value.present = F1AP_UEContextReleaseRequestIEs__value_PR_Cause; + F1AP_F1AP_PDU_t *pdu = encode_ue_context_rel_req(req); - switch (req->cause) { - case F1AP_CAUSE_RADIO_NETWORK: - ie3->value.choice.Cause.present = F1AP_Cause_PR_radioNetwork; - ie3->value.choice.Cause.choice.radioNetwork = req->cause_value; - break; - - case F1AP_CAUSE_TRANSPORT: - ie3->value.choice.Cause.present = F1AP_Cause_PR_transport; - ie3->value.choice.Cause.choice.transport = req->cause_value; - break; - - case F1AP_CAUSE_PROTOCOL: - ie3->value.choice.Cause.present = F1AP_Cause_PR_protocol; - ie3->value.choice.Cause.choice.protocol = req->cause_value; - break; - - case F1AP_CAUSE_MISC: - ie3->value.choice.Cause.present = F1AP_Cause_PR_misc; - ie3->value.choice.Cause.choice.misc = req->cause_value; - break; - - case F1AP_CAUSE_NOTHING: - default: - ie3->value.choice.Cause.present = F1AP_Cause_PR_NOTHING; - break; - } - - /* encode */ - if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { + uint8_t *buffer = NULL; + uint32_t len = 0; + if (f1ap_encode_pdu(pdu, &buffer, &len) < 0) { LOG_E(F1AP, "Failed to encode F1 context release request\n"); return -1; } f1ap_itti_send_sctp_data_req(assoc_id, buffer, len); + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); return 0; } @@ -153,8 +97,8 @@ int DU_handle_UE_CONTEXT_RELEASE_COMMAND(instance_t instance, sctp_assoc_t assoc F1AP_UEContextReleaseCommand_t *container; F1AP_UEContextReleaseCommandIEs_t *ie; - f1ap_ue_context_release_req_t ue_context_release = {0}; - f1ap_ue_context_release_req_t *f1ap_ue_context_release_cmd = &ue_context_release; + f1ap_ue_context_release_cmd_t ue_context_release = {0}; + f1ap_ue_context_release_cmd_t *f1ap_ue_context_release_cmd = &ue_context_release; DevAssert(pdu); container = &pdu->choice.initiatingMessage->value.choice.UEContextReleaseCommand; diff --git a/openair2/F1AP/f1ap_du_ue_context_management.h b/openair2/F1AP/f1ap_du_ue_context_management.h index 8f38ac8dd9..e9ef2bef8c 100644 --- a/openair2/F1AP/f1ap_du_ue_context_management.h +++ b/openair2/F1AP/f1ap_du_ue_context_management.h @@ -45,9 +45,7 @@ int DU_send_UE_CONTEXT_SETUP_FAILURE(sctp_assoc_t assoc_id); /* * UE Context Release Request (gNB-DU initiated) */ -int DU_send_UE_CONTEXT_RELEASE_REQUEST(sctp_assoc_t assoc_id, - f1ap_ue_context_release_req_t *req); - +int DU_send_UE_CONTEXT_RELEASE_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_context_rel_req_t *req); /* * UE Context Release Command (gNB-CU initiated) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index a447d9f91c..b85c26b1a3 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -3385,7 +3385,7 @@ bool nr_mac_request_release_ue(const gNB_MAC_INST *nrmac, int rnti) return false; } f1_ue_data_t ue_data = du_get_f1_ue_data(rnti); - f1ap_ue_context_release_req_t request = { + f1ap_ue_context_rel_req_t request = { .gNB_CU_ue_id = ue_data.secondary_ue, .gNB_DU_ue_id = rnti, .cause = F1AP_CAUSE_RADIO_NETWORK, diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c index 58d8dbf86c..c625343c10 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -852,7 +852,7 @@ void ue_context_modification_refuse(const f1ap_ue_context_modif_refuse_t *refuse NR_SCHED_UNLOCK(&mac->sched_lock); - f1ap_ue_context_release_req_t request = { + f1ap_ue_context_rel_req_t request = { .gNB_CU_ue_id = refuse->gNB_CU_ue_id, .gNB_DU_ue_id = refuse->gNB_DU_ue_id, .cause = F1AP_CAUSE_RADIO_NETWORK, diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h index 033e8590d2..3f54ae53b8 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h @@ -34,7 +34,7 @@ typedef void (*gnb_du_configuration_update_t)(const f1ap_gnb_du_configuration_up typedef void (*ue_context_setup_response_func_t)(const f1ap_ue_context_setup_resp_t *resp); typedef void (*ue_context_modification_response_func_t)(const f1ap_ue_context_mod_resp_t *resp); typedef void (*ue_context_modification_required_func_t)(const f1ap_ue_context_modif_required_t *t); -typedef void (*ue_context_release_request_func_t)(const f1ap_ue_context_release_req_t* req); +typedef void (*ue_context_release_request_func_t)(const f1ap_ue_context_rel_req_t* req); typedef void (*ue_context_release_complete_func_t)(const f1ap_ue_context_release_complete_t *complete); typedef void (*initial_ul_rrc_message_transfer_func_t)(module_id_t module_id, const f1ap_initial_ul_rrc_message_t *ul_rrc); diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c index 72308bdd66..9f719374c1 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c @@ -101,12 +101,11 @@ static void ue_context_modification_required_direct(const f1ap_ue_context_modif_ itti_send_msg_to_task(TASK_RRC_GNB, 0, msg); } -static void ue_context_release_request_direct(const f1ap_ue_context_release_req_t* req) +static void ue_context_release_request_direct(const f1ap_ue_context_rel_req_t* req) { MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_RELEASE_REQ); msg->ittiMsgHeader.originInstance = -1; // means monolithic - f1ap_ue_context_release_req_t *f1ap_msg = &F1AP_UE_CONTEXT_RELEASE_REQ(msg); - *f1ap_msg = *req; + F1AP_UE_CONTEXT_RELEASE_REQ(msg) = cp_ue_context_rel_req(req); itti_send_msg_to_task(TASK_RRC_GNB, 0, msg); } diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c index 15101928e5..29990cf3a9 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c @@ -125,11 +125,10 @@ static void ue_context_modification_required_f1ap(const f1ap_ue_context_modif_re itti_send_msg_to_task(TASK_DU_F1, 0, msg); } -static void ue_context_release_request_f1ap(const f1ap_ue_context_release_req_t* req) +static void ue_context_release_request_f1ap(const f1ap_ue_context_rel_req_t* req) { MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_RELEASE_REQ); - f1ap_ue_context_release_req_t *f1ap_msg = &F1AP_UE_CONTEXT_RELEASE_REQ(msg); - *f1ap_msg = *req; + F1AP_UE_CONTEXT_RELEASE_REQ(msg) = cp_ue_context_rel_req(req); itti_send_msg_to_task(TASK_DU_F1, 0, msg); } diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 096e67ce0a..a7ba899c82 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -2133,7 +2133,7 @@ static void rrc_CU_process_ue_context_setup_response(MessageDef *msg_p, instance static void rrc_CU_process_ue_context_release_request(MessageDef *msg_p, sctp_assoc_t assoc_id) { const int instance = 0; - f1ap_ue_context_release_req_t *req = &F1AP_UE_CONTEXT_RELEASE_REQ(msg_p); + f1ap_ue_context_rel_req_t *req = &F1AP_UE_CONTEXT_RELEASE_REQ(msg_p); gNB_RRC_INST *rrc = RC.nrrrc[instance]; rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(rrc, req->gNB_CU_ue_id); // TODO what happens if no AMF connected? should also handle, set an_release true @@ -2775,6 +2775,7 @@ void *rrc_gnb_task(void *args_p) { case F1AP_UE_CONTEXT_RELEASE_REQ: rrc_CU_process_ue_context_release_request(msg_p, msg_p->ittiMsgHeader.originInstance); + free_ue_context_rel_req(&F1AP_UE_CONTEXT_RELEASE_REQ(msg_p)); break; case F1AP_UE_CONTEXT_RELEASE_COMPLETE: From ec7a7973fb3c822c4f545f3520baf158a22a6b50 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 11 Jun 2025 08:59:43 +0200 Subject: [PATCH 128/964] Add F1AP UE context release command message enc/dec + test See commit "Add F1AP UE context setup request message enc/dec + test" for more details on the approach taken. --- openair2/COMMON/f1ap_messages_types.h | 12 ++ openair2/F1AP/lib/f1ap_ue_context.c | 171 ++++++++++++++++++++++++++ openair2/F1AP/lib/f1ap_ue_context.h | 6 + openair2/F1AP/tests/f1ap_lib_test.c | 36 ++++++ 4 files changed, 225 insertions(+) diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h index 57365c931e..882ead3998 100644 --- a/openair2/COMMON/f1ap_messages_types.h +++ b/openair2/COMMON/f1ap_messages_types.h @@ -656,6 +656,18 @@ typedef struct f1ap_ue_context_rel_req_t { long cause_value; } f1ap_ue_context_rel_req_t; +typedef struct f1ap_ue_context_rel_cmd_t { + uint32_t gNB_CU_ue_id; + uint32_t gNB_DU_ue_id; + f1ap_Cause_t cause; + long cause_value; + + byte_array_t *rrc_container; + int *srb_id; // C-ifRRCContainer + + uint32_t *old_gNB_DU_ue_id; // if after reestablishment request +} f1ap_ue_context_rel_cmd_t; + typedef struct f1ap_ue_context_release_s { uint32_t gNB_CU_ue_id; uint32_t gNB_DU_ue_id; diff --git a/openair2/F1AP/lib/f1ap_ue_context.c b/openair2/F1AP/lib/f1ap_ue_context.c index 53f1e11c67..d070ca0cde 100644 --- a/openair2/F1AP/lib/f1ap_ue_context.c +++ b/openair2/F1AP/lib/f1ap_ue_context.c @@ -2199,3 +2199,174 @@ void free_ue_context_rel_req(f1ap_ue_context_rel_req_t *req) { // nothing to free } + +/* + * @brief Encode F1 UE context release command to ASN.1 + */ +struct F1AP_F1AP_PDU *encode_ue_context_rel_cmd(const f1ap_ue_context_rel_cmd_t *cmd) +{ + F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); + + /* Message Type */ + pdu->present = F1AP_F1AP_PDU_PR_initiatingMessage; + asn1cCalloc(pdu->choice.initiatingMessage, tmp); + tmp->procedureCode = F1AP_ProcedureCode_id_UEContextRelease; + tmp->criticality = F1AP_Criticality_reject; + tmp->value.present = F1AP_InitiatingMessage__value_PR_UEContextReleaseCommand; + F1AP_UEContextReleaseCommand_t *out = &tmp->value.choice.UEContextReleaseCommand; + + /* mandatory: GNB_CU_UE_F1AP_ID */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseCommandIEs_t, ie1); + ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; + ie1->criticality = F1AP_Criticality_reject; + ie1->value.present = F1AP_UEContextReleaseCommandIEs__value_PR_GNB_CU_UE_F1AP_ID; + ie1->value.choice.GNB_CU_UE_F1AP_ID = cmd->gNB_CU_ue_id; + + /* mandatory: GNB_DU_UE_F1AP_ID */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseCommandIEs_t, ie2); + ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; + ie2->criticality = F1AP_Criticality_reject; + ie2->value.present = F1AP_UEContextReleaseCommandIEs__value_PR_GNB_DU_UE_F1AP_ID; + ie2->value.choice.GNB_DU_UE_F1AP_ID = cmd->gNB_DU_ue_id; + + /* mandatory: Cause */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseCommandIEs_t, ie3); + ie3->id = F1AP_ProtocolIE_ID_id_Cause; + ie3->criticality = F1AP_Criticality_ignore; + ie3->value.present = F1AP_UEContextReleaseCommandIEs__value_PR_Cause; + ie3->value.choice.Cause = encode_f1ap_cause(cmd->cause, cmd->cause_value); + + /* optional: RRC Container */ + if (cmd->rrc_container != NULL) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseCommandIEs_t, ie4); + ie4->id = F1AP_ProtocolIE_ID_id_RRCContainer; + ie4->criticality = F1AP_Criticality_ignore; + ie4->value.present = F1AP_UEContextReleaseCommandIEs__value_PR_RRCContainer; + const byte_array_t *ba = cmd->rrc_container; + OCTET_STRING_fromBuf(&ie4->value.choice.RRCContainer, (const char *)ba->buf, ba->len); + + // conditionally have SRBID if RRC Container + AssertFatal(cmd->srb_id != NULL, "UEContextReleaseCommand SRB-ID C-ifRRCContainer violated\n"); + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseCommandIEs_t, ie5); + ie5->id = F1AP_ProtocolIE_ID_id_SRBID; + ie5->criticality = F1AP_Criticality_ignore; + ie5->value.present = F1AP_UEContextReleaseCommandIEs__value_PR_SRBID; + ie5->value.choice.SRBID = *cmd->srb_id; + } + + if (cmd->old_gNB_DU_ue_id != NULL) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseCommandIEs_t, ie5); + ie5->id = F1AP_ProtocolIE_ID_id_oldgNB_DU_UE_F1AP_ID; + ie5->criticality = F1AP_Criticality_ignore; + ie5->value.present = F1AP_UEContextReleaseCommandIEs__value_PR_GNB_DU_UE_F1AP_ID_1; + ie5->value.choice.GNB_DU_UE_F1AP_ID_1 = *cmd->old_gNB_DU_ue_id; + } + + return pdu; +} + +/** + * @brief Decode F1 UE Context Release Command + */ +bool decode_ue_context_rel_cmd(const struct F1AP_F1AP_PDU *pdu, f1ap_ue_context_rel_cmd_t *out) +{ + DevAssert(out != NULL); + memset(out, 0, sizeof(*out)); + + F1AP_UEContextReleaseCommand_t *in = &pdu->choice.initiatingMessage->value.choice.UEContextReleaseCommand; + F1AP_UEContextReleaseCommandIEs_t *ie; + F1AP_LIB_FIND_IE(F1AP_UEContextReleaseCommandIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); + F1AP_LIB_FIND_IE(F1AP_UEContextReleaseCommandIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); + F1AP_LIB_FIND_IE(F1AP_UEContextReleaseCommandIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_Cause, true); + + for (int i = 0; i < in->protocolIEs.list.count; ++i) { + ie = in->protocolIEs.list.array[i]; + AssertError(ie != NULL, return false, "in->protocolIEs.list.array[i] is NULL"); + switch (ie->id) { + case F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextReleaseCommandIEs__value_PR_GNB_CU_UE_F1AP_ID); + out->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID; + break; + case F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextReleaseCommandIEs__value_PR_GNB_DU_UE_F1AP_ID); + out->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; + break; + case F1AP_ProtocolIE_ID_id_Cause: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextReleaseCommandIEs__value_PR_Cause); + _F1_CHECK_EXP(decode_f1ap_cause(ie->value.choice.Cause, &out->cause, &out->cause_value)); + break; + case F1AP_ProtocolIE_ID_id_RRCContainer: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextReleaseCommandIEs__value_PR_RRCContainer); + out->rrc_container = malloc_or_fail(sizeof(*out->rrc_container)); + { + OCTET_STRING_t *os = &ie->value.choice.RRCContainer; + *out->rrc_container = create_byte_array(os->size, os->buf); + } + break; + case F1AP_ProtocolIE_ID_id_SRBID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextReleaseCommandIEs__value_PR_SRBID); + { + // SRB-ID + F1AP_UEContextReleaseCommandIEs_t *check_ie; + F1AP_LIB_FIND_IE(F1AP_UEContextReleaseCommandIEs_t, check_ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_RRCContainer, true); + } + _F1_MALLOC(out->srb_id, ie->value.choice.SRBID); + break; + case F1AP_ProtocolIE_ID_id_oldgNB_DU_UE_F1AP_ID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextReleaseCommandIEs__value_PR_GNB_DU_UE_F1AP_ID_1); + _F1_MALLOC(out->old_gNB_DU_ue_id, ie->value.choice.GNB_DU_UE_F1AP_ID_1); + break; + default: + PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld unknown, skipping\n", ie->id); + break; + } + } + + return true; +} + +/** + * @brief F1 UE Context Release Command deep copy + */ +f1ap_ue_context_rel_cmd_t cp_ue_context_rel_cmd(const f1ap_ue_context_rel_cmd_t *orig) +{ + f1ap_ue_context_rel_cmd_t cp = { + .gNB_CU_ue_id = orig->gNB_CU_ue_id, + .gNB_DU_ue_id = orig->gNB_DU_ue_id, + .cause = orig->cause, + .cause_value = orig->cause_value, + }; + CP_OPT_BYTE_ARRAY(cp.rrc_container, orig->rrc_container); + if (orig->rrc_container) { + AssertFatal(orig->srb_id != NULL, "UEContextReleaseCommand SRB-ID C-ifRRCContainer violated\n"); + _F1_MALLOC(cp.srb_id, *orig->srb_id); + } + if (orig->old_gNB_DU_ue_id) + _F1_MALLOC(cp.old_gNB_DU_ue_id, *orig->old_gNB_DU_ue_id); + return cp; +} + +/** + * @brief F1 UE Context Release Command equality check + */ +bool eq_ue_context_rel_cmd(const f1ap_ue_context_rel_cmd_t *a, const f1ap_ue_context_rel_cmd_t *b) +{ + _F1_EQ_CHECK_INT(a->gNB_CU_ue_id, b->gNB_CU_ue_id); + _F1_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id); + _F1_EQ_CHECK_INT(a->cause, b->cause); + _F1_EQ_CHECK_LONG(a->cause_value, b->cause_value); + _F1_EQ_CHECK_OPTIONAL_IE(a, b, rrc_container, eq_ba); + _F1_EQ_CHECK_OPTIONAL_IE(a, b, srb_id, _F1_EQ_CHECK_INT); + _F1_EQ_CHECK_OPTIONAL_IE(a, b, old_gNB_DU_ue_id, _F1_EQ_CHECK_INT); + return true; +} + +/** + * @brief Free Allocated F1 UE Context Release Command + */ +void free_ue_context_rel_cmd(f1ap_ue_context_rel_cmd_t *cmd) +{ + FREE_OPT_BYTE_ARRAY(cmd->rrc_container); + free(cmd->srb_id); + free(cmd->old_gNB_DU_ue_id); +} diff --git a/openair2/F1AP/lib/f1ap_ue_context.h b/openair2/F1AP/lib/f1ap_ue_context.h index 5e683fe1ab..34dd3035a3 100644 --- a/openair2/F1AP/lib/f1ap_ue_context.h +++ b/openair2/F1AP/lib/f1ap_ue_context.h @@ -57,4 +57,10 @@ f1ap_ue_context_rel_req_t cp_ue_context_rel_req(const f1ap_ue_context_rel_req_t bool eq_ue_context_rel_req(const f1ap_ue_context_rel_req_t *a, const f1ap_ue_context_rel_req_t *b); void free_ue_context_rel_req(f1ap_ue_context_rel_req_t *req); +struct F1AP_F1AP_PDU *encode_ue_context_rel_cmd(const f1ap_ue_context_rel_cmd_t *msg); +bool decode_ue_context_rel_cmd(const struct F1AP_F1AP_PDU *pdu, f1ap_ue_context_rel_cmd_t *out); +f1ap_ue_context_rel_cmd_t cp_ue_context_rel_cmd(const f1ap_ue_context_rel_cmd_t *orig); +bool eq_ue_context_rel_cmd(const f1ap_ue_context_rel_cmd_t *a, const f1ap_ue_context_rel_cmd_t *b); +void free_ue_context_rel_cmd(f1ap_ue_context_rel_cmd_t *cmd); + #endif /* F1AP_UE_CONTEXT_SETUP_REQ_H_ */ diff --git a/openair2/F1AP/tests/f1ap_lib_test.c b/openair2/F1AP/tests/f1ap_lib_test.c index a26a80823e..d46b93983b 100644 --- a/openair2/F1AP/tests/f1ap_lib_test.c +++ b/openair2/F1AP/tests/f1ap_lib_test.c @@ -1202,6 +1202,41 @@ static void test_f1ap_ue_context_release_request() printf("%s() successful\n", __func__); } +static void test_f1ap_ue_context_release_command() +{ + f1ap_ue_context_rel_cmd_t orig = { + .gNB_CU_ue_id = 1111, + .gNB_DU_ue_id = 2222, + .cause = F1AP_CAUSE_RADIO_NETWORK, + .cause_value = 2, + }; + + orig.rrc_container = get_malloced_test_ba("some reject message"); + _F1_MALLOC(orig.srb_id, 1); + _F1_MALLOC(orig.old_gNB_DU_ue_id, 3333); + + F1AP_F1AP_PDU_t *f1enc = encode_ue_context_rel_cmd(&orig); + F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + + f1ap_ue_context_rel_cmd_t decoded = {0}; + bool ret = decode_ue_context_rel_cmd(f1dec, &decoded); + AssertFatal(ret, "decode_ue_context_rel_cmd(): could not decode message\n"); + f1ap_msg_free(f1dec); + + ret = eq_ue_context_rel_cmd(&orig, &decoded); + AssertFatal(ret, "eq_ue_context_rel_cmd(): decoded message doesn't match\n"); + free_ue_context_rel_cmd(&decoded); + + f1ap_ue_context_rel_cmd_t cp = cp_ue_context_rel_cmd(&orig); + ret = eq_ue_context_rel_cmd(&orig, &cp); + AssertFatal(ret, "eq_ue_context_rel_cmd(): copied message doesn't match\n"); + free_ue_context_rel_cmd(&orig); + free_ue_context_rel_cmd(&cp); + + printf("%s() successful\n", __func__); +} + int main() { test_initial_ul_rrc_message_transfer(); @@ -1226,5 +1261,6 @@ int main() test_f1ap_ue_context_modification_response(); test_f1ap_ue_context_modification_response_simple(); test_f1ap_ue_context_release_request(); + test_f1ap_ue_context_release_command(); return 0; } From e3b8121035aed0b9c4a06c06b572175c5f2cf96f Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 19 Jun 2025 17:11:04 +0200 Subject: [PATCH 129/964] Use F1 UE Context Release Command in stack Use the new type and remove the old one. --- openair2/COMMON/f1ap_messages_def.h | 2 +- openair2/COMMON/f1ap_messages_types.h | 2 +- openair2/F1AP/f1ap_cu_task.c | 1 + openair2/F1AP/f1ap_cu_ue_context_management.c | 86 ++----------------- openair2/F1AP/f1ap_cu_ue_context_management.h | 3 +- openair2/F1AP/f1ap_du_ue_context_management.c | 60 ++----------- .../LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c | 9 +- .../LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h | 2 +- openair2/RRC/NR/mac_rrc_dl.h | 2 +- openair2/RRC/NR/mac_rrc_dl_direct.c | 2 +- openair2/RRC/NR/mac_rrc_dl_f1ap.c | 11 +-- openair2/RRC/NR/rrc_gNB.c | 18 ++-- openair2/RRC/NR/rrc_gNB_mobility.c | 6 +- openair2/RRC/NR/rrc_gNB_nsa.c | 2 +- 14 files changed, 39 insertions(+), 167 deletions(-) diff --git a/openair2/COMMON/f1ap_messages_def.h b/openair2/COMMON/f1ap_messages_def.h index e9776c58ff..f46120a037 100644 --- a/openair2/COMMON/f1ap_messages_def.h +++ b/openair2/COMMON/f1ap_messages_def.h @@ -49,7 +49,7 @@ MESSAGE_DEF(F1AP_UL_RRC_MESSAGE , MESSAGE_PRIORITY_MED, f1ap_ul_r //MESSAGE_DEF(F1AP_INITIAL_CONTEXT_SETUP_RESP, MESSAGE_PRIORITY_MED, f1ap_initial_context_setup_resp_t, f1ap_initial_context_setup_resp) //MESSAGE_DEF(F1AP_INITIAL_CONTEXT_SETUP_FAILURE, MESSAGE_PRIORITY_MED, f1ap_initial_context_setup_failure_t, f1ap_initial_context_setup_failure) MESSAGE_DEF(F1AP_UE_CONTEXT_RELEASE_REQ, MESSAGE_PRIORITY_MED, f1ap_ue_context_rel_req_t, f1ap_ue_context_release_req) -MESSAGE_DEF(F1AP_UE_CONTEXT_RELEASE_CMD, MESSAGE_PRIORITY_MED, f1ap_ue_context_release_cmd_t, f1ap_ue_context_release_cmd) +MESSAGE_DEF(F1AP_UE_CONTEXT_RELEASE_CMD, MESSAGE_PRIORITY_MED, f1ap_ue_context_rel_cmd_t, f1ap_ue_context_release_cmd) MESSAGE_DEF(F1AP_UE_CONTEXT_RELEASE_COMPLETE, MESSAGE_PRIORITY_MED, f1ap_ue_context_release_complete_t, f1ap_ue_context_release_complete) MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_REQUIRED, MESSAGE_PRIORITY_MED, f1ap_ue_context_modif_required_t, f1ap_ue_context_modification_required) diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h index 882ead3998..243a8e5bcc 100644 --- a/openair2/COMMON/f1ap_messages_types.h +++ b/openair2/COMMON/f1ap_messages_types.h @@ -676,7 +676,7 @@ typedef struct f1ap_ue_context_release_s { uint8_t *rrc_container; int rrc_container_length; int srb_id; -} f1ap_ue_context_release_cmd_t, f1ap_ue_context_release_complete_t; +} f1ap_ue_context_release_complete_t; typedef struct f1ap_paging_ind_s { uint16_t ueidentityindexvalue; diff --git a/openair2/F1AP/f1ap_cu_task.c b/openair2/F1AP/f1ap_cu_task.c index 85375e4109..b7d19b7a6a 100644 --- a/openair2/F1AP/f1ap_cu_task.c +++ b/openair2/F1AP/f1ap_cu_task.c @@ -199,6 +199,7 @@ void *F1AP_CU_task(void *arg) { case F1AP_UE_CONTEXT_RELEASE_CMD: // from rrc CU_send_UE_CONTEXT_RELEASE_COMMAND(assoc_id, &F1AP_UE_CONTEXT_RELEASE_CMD(received_msg)); + free_ue_context_rel_cmd(&F1AP_UE_CONTEXT_RELEASE_CMD(received_msg)); break; case F1AP_PAGING_IND: diff --git a/openair2/F1AP/f1ap_cu_ue_context_management.c b/openair2/F1AP/f1ap_cu_ue_context_management.c index e0f1495f86..d29c52dec5 100644 --- a/openair2/F1AP/f1ap_cu_ue_context_management.c +++ b/openair2/F1AP/f1ap_cu_ue_context_management.c @@ -104,93 +104,19 @@ int CU_handle_UE_CONTEXT_RELEASE_REQUEST(instance_t instance, sctp_assoc_t assoc return 0; } -int CU_send_UE_CONTEXT_RELEASE_COMMAND(sctp_assoc_t assoc_id, f1ap_ue_context_release_cmd_t *cmd) +int CU_send_UE_CONTEXT_RELEASE_COMMAND(sctp_assoc_t assoc_id, f1ap_ue_context_rel_cmd_t *cmd) { - F1AP_F1AP_PDU_t pdu= {0}; - F1AP_UEContextReleaseCommand_t *out; - uint8_t *buffer=NULL; - uint32_t len=0; - /* Create */ - /* 0. Message Type */ - pdu.present = F1AP_F1AP_PDU_PR_initiatingMessage; - asn1cCalloc(pdu.choice.initiatingMessage, tmp); - tmp->procedureCode = F1AP_ProcedureCode_id_UEContextRelease; - tmp->criticality = F1AP_Criticality_reject; - tmp->value.present = F1AP_InitiatingMessage__value_PR_UEContextReleaseCommand; - out = &tmp->value.choice.UEContextReleaseCommand; - /* mandatory */ - /* c1. GNB_CU_UE_F1AP_ID */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseCommandIEs_t, ie1); - ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; - ie1->criticality = F1AP_Criticality_reject; - ie1->value.present = F1AP_UEContextReleaseCommandIEs__value_PR_GNB_CU_UE_F1AP_ID; - ie1->value.choice.GNB_CU_UE_F1AP_ID = cmd->gNB_CU_ue_id; - /* mandatory */ - /* c2. GNB_DU_UE_F1AP_ID */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseCommandIEs_t, ie2); - ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; - ie2->criticality = F1AP_Criticality_reject; - ie2->value.present = F1AP_UEContextReleaseCommandIEs__value_PR_GNB_DU_UE_F1AP_ID; - ie2->value.choice.GNB_DU_UE_F1AP_ID = cmd->gNB_DU_ue_id; - /* mandatory */ - /* c3. Cause */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseCommandIEs_t, ie3); - ie3->id = F1AP_ProtocolIE_ID_id_Cause; - ie3->criticality = F1AP_Criticality_ignore; - ie3->value.present = F1AP_UEContextReleaseCommandIEs__value_PR_Cause; + F1AP_F1AP_PDU_t *pdu = encode_ue_context_rel_cmd(cmd); - switch (cmd->cause) { - case F1AP_CAUSE_RADIO_NETWORK: - ie3->value.choice.Cause.present = F1AP_Cause_PR_radioNetwork; - ie3->value.choice.Cause.choice.radioNetwork = cmd->cause_value; - break; - - case F1AP_CAUSE_TRANSPORT: - ie3->value.choice.Cause.present = F1AP_Cause_PR_transport; - ie3->value.choice.Cause.choice.transport = cmd->cause_value; - break; - - case F1AP_CAUSE_PROTOCOL: - ie3->value.choice.Cause.present = F1AP_Cause_PR_protocol; - ie3->value.choice.Cause.choice.protocol = cmd->cause_value; - break; - - case F1AP_CAUSE_MISC: - ie3->value.choice.Cause.present = F1AP_Cause_PR_misc; - ie3->value.choice.Cause.choice.misc = cmd->cause_value; - break; - - case F1AP_CAUSE_NOTHING: - default: - ie3->value.choice.Cause.present = F1AP_Cause_PR_NOTHING; - break; - } - - /* optional */ - /* c4. RRCContainer */ - if(cmd->rrc_container!=NULL){ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseCommandIEs_t, ie4); - ie4->id = F1AP_ProtocolIE_ID_id_RRCContainer; - ie4->criticality = F1AP_Criticality_ignore; - ie4->value.present = F1AP_UEContextReleaseCommandIEs__value_PR_RRCContainer; - OCTET_STRING_fromBuf(&ie4->value.choice.RRCContainer, (const char *)cmd->rrc_container, - cmd->rrc_container_length); - - // conditionally have SRBID if RRC Container - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseCommandIEs_t, ie5); - ie5->id = F1AP_ProtocolIE_ID_id_SRBID; - ie5->criticality = F1AP_Criticality_ignore; - ie5->value.present = F1AP_UEContextReleaseCommandIEs__value_PR_SRBID; - ie5->value.choice.SRBID = cmd->srb_id; - } - - /* encode */ - if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { + uint8_t *buffer = NULL; + uint32_t len = 0; + if (f1ap_encode_pdu(pdu, &buffer, &len) < 0) { LOG_E(F1AP, "Failed to encode F1 context release command\n"); return -1; } f1ap_itti_send_sctp_data_req(assoc_id, buffer, len); + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); return 0; } diff --git a/openair2/F1AP/f1ap_cu_ue_context_management.h b/openair2/F1AP/f1ap_cu_ue_context_management.h index ed76189c19..0bc1815658 100644 --- a/openair2/F1AP/f1ap_cu_ue_context_management.h +++ b/openair2/F1AP/f1ap_cu_ue_context_management.h @@ -50,8 +50,7 @@ int CU_handle_UE_CONTEXT_RELEASE_REQUEST(instance_t instance, sctp_assoc_t assoc /* * UE Context Release (gNB-CU initiated) */ -int CU_send_UE_CONTEXT_RELEASE_COMMAND(sctp_assoc_t assoc_id, - f1ap_ue_context_release_cmd_t *cmd); +int CU_send_UE_CONTEXT_RELEASE_COMMAND(sctp_assoc_t assoc_id, f1ap_ue_context_rel_cmd_t *cmd); int CU_handle_UE_CONTEXT_RELEASE_COMPLETE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu); diff --git a/openair2/F1AP/f1ap_du_ue_context_management.c b/openair2/F1AP/f1ap_du_ue_context_management.c index a2179b8583..7371b69a4f 100644 --- a/openair2/F1AP/f1ap_du_ue_context_management.c +++ b/openair2/F1AP/f1ap_du_ue_context_management.c @@ -94,61 +94,15 @@ int DU_send_UE_CONTEXT_RELEASE_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_context_re int DU_handle_UE_CONTEXT_RELEASE_COMMAND(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { - F1AP_UEContextReleaseCommand_t *container; - F1AP_UEContextReleaseCommandIEs_t *ie; - - f1ap_ue_context_release_cmd_t ue_context_release = {0}; - f1ap_ue_context_release_cmd_t *f1ap_ue_context_release_cmd = &ue_context_release; - - DevAssert(pdu); - container = &pdu->choice.initiatingMessage->value.choice.UEContextReleaseCommand; - // GNB_CU_UE_F1AP_ID - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextReleaseCommandIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); - f1ap_ue_context_release_cmd->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID; - // GNB_DU_UE_F1AP_ID - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextReleaseCommandIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); - f1ap_ue_context_release_cmd->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; - - // We don't need the Cause - // Optional RRC Container: if present, send to UE - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextReleaseCommandIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_RRCContainer, false); - - if (ie != NULL) { - f1ap_ue_context_release_cmd->rrc_container = malloc(ie->value.choice.RRCContainer.size); - AssertFatal(f1ap_ue_context_release_cmd->rrc_container != NULL, "out of memory\n"); - memcpy(f1ap_ue_context_release_cmd->rrc_container, ie->value.choice.RRCContainer.buf, ie->value.choice.RRCContainer.size); - f1ap_ue_context_release_cmd->rrc_container_length = ie->value.choice.RRCContainer.size; - - // conditionally have SRB ID if there is RRC container - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextReleaseCommandIEs_t, ie, container, F1AP_ProtocolIE_ID_id_SRBID, true); - f1ap_ue_context_release_cmd->srb_id = ie->value.choice.SRBID; + f1ap_ue_context_rel_cmd_t cmd = {0}; + if (!decode_ue_context_rel_cmd(pdu, &cmd)) { + LOG_E(F1AP, "cannot decode F1 UE Context Release Command\n"); + free_ue_context_rel_cmd(&cmd); + return -1; } - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextReleaseCommandIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_Cause, true); - switch (ie->value.choice.Cause.present){ - case F1AP_Cause_PR_radioNetwork: - f1ap_ue_context_release_cmd->cause = F1AP_CAUSE_RADIO_NETWORK; - break; - case F1AP_Cause_PR_transport: - f1ap_ue_context_release_cmd->cause = F1AP_CAUSE_TRANSPORT; - break; - case F1AP_Cause_PR_protocol: - f1ap_ue_context_release_cmd->cause = F1AP_CAUSE_PROTOCOL; - break; - case F1AP_Cause_PR_misc: - f1ap_ue_context_release_cmd->cause = F1AP_CAUSE_MISC; - break; - default: - LOG_W(F1AP, "Unknown cause for UE context release command\n"); - break; - - } - - ue_context_release_command(f1ap_ue_context_release_cmd); + ue_context_release_command(&cmd); + free_ue_context_rel_cmd(&cmd); return 0; } diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c index c625343c10..74529c9dde 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -861,7 +861,7 @@ void ue_context_modification_refuse(const f1ap_ue_context_modif_refuse_t *refuse mac->mac_rrc.ue_context_release_request(&request); } -void ue_context_release_command(const f1ap_ue_context_release_cmd_t *cmd) +void ue_context_release_command(const f1ap_ue_context_rel_cmd_t *cmd) { /* mark UE as to be deleted after PUSCH failure */ gNB_MAC_INST *mac = RC.nrmac[0]; @@ -881,14 +881,15 @@ void ue_context_release_command(const f1ap_ue_context_release_cmd_t *cmd) if (f1inst >= 0) newGtpuDeleteAllTunnels(f1inst, cmd->gNB_DU_ue_id); - if (UE->UE_sched_ctrl.ul_failure || cmd->rrc_container_length == 0) { + if (UE->UE_sched_ctrl.ul_failure || !cmd->rrc_container) { /* The UE is already not connected anymore or we have nothing to forward*/ nr_mac_release_ue(mac, cmd->gNB_DU_ue_id); nr_mac_trigger_release_complete(mac, cmd->gNB_DU_ue_id); - } else { + } else if (cmd->rrc_container && cmd->srb_id){ /* UE is in sync: forward release message and mark to be deleted * after UL failure */ - nr_rlc_srb_recv_sdu(cmd->gNB_DU_ue_id, cmd->srb_id, cmd->rrc_container, cmd->rrc_container_length); + byte_array_t *rrc_cont = cmd->rrc_container; + nr_rlc_srb_recv_sdu(cmd->gNB_DU_ue_id, *cmd->srb_id, (char *)rrc_cont->buf, rrc_cont->len); nr_mac_trigger_release_timer(&UE->UE_sched_ctrl, UE->current_UL_BWP.scs); } NR_SCHED_UNLOCK(&mac->sched_lock); diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h index b3ecdad270..1ba31f8e80 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h @@ -36,7 +36,7 @@ void ue_context_setup_request(const f1ap_ue_context_setup_req_t *req); void ue_context_modification_request(const f1ap_ue_context_mod_req_t *req); void ue_context_modification_confirm(const f1ap_ue_context_modif_confirm_t *confirm); void ue_context_modification_refuse(const f1ap_ue_context_modif_refuse_t *refuse); -void ue_context_release_command(const f1ap_ue_context_release_cmd_t *cmd); +void ue_context_release_command(const f1ap_ue_context_rel_cmd_t *cmd); void dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *dl_rrc); diff --git a/openair2/RRC/NR/mac_rrc_dl.h b/openair2/RRC/NR/mac_rrc_dl.h index f93bc1b7fe..4bd106d679 100644 --- a/openair2/RRC/NR/mac_rrc_dl.h +++ b/openair2/RRC/NR/mac_rrc_dl.h @@ -37,7 +37,7 @@ typedef void (*ue_context_setup_request_func_t)(sctp_assoc_t assoc_id, const f1a typedef void (*ue_context_modification_request_func_t)(sctp_assoc_t assoc_id, const f1ap_ue_context_mod_req_t *req); typedef void (*ue_context_modification_confirm_func_t)(sctp_assoc_t assoc_id, const f1ap_ue_context_modif_confirm_t *confirm); typedef void (*ue_context_modification_refuse_func_t)(sctp_assoc_t assoc_id, const f1ap_ue_context_modif_refuse_t *refuse); -typedef void (*ue_context_release_command_func_t)(sctp_assoc_t assoc_id, const f1ap_ue_context_release_cmd_t *cmd); +typedef void (*ue_context_release_command_func_t)(sctp_assoc_t assoc_id, const f1ap_ue_context_rel_cmd_t *cmd); typedef void (*dl_rrc_message_transfer_func_t)(sctp_assoc_t assoc_id, const f1ap_dl_rrc_message_t *dl_rrc); diff --git a/openair2/RRC/NR/mac_rrc_dl_direct.c b/openair2/RRC/NR/mac_rrc_dl_direct.c index 29592d4e43..83c1130fcb 100644 --- a/openair2/RRC/NR/mac_rrc_dl_direct.c +++ b/openair2/RRC/NR/mac_rrc_dl_direct.c @@ -82,7 +82,7 @@ static void ue_context_modification_refuse_direct(sctp_assoc_t assoc_id, const f ue_context_modification_refuse(refuse); } -static void ue_context_release_command_direct(sctp_assoc_t assoc_id, const f1ap_ue_context_release_cmd_t *cmd) +static void ue_context_release_command_direct(sctp_assoc_t assoc_id, const f1ap_ue_context_rel_cmd_t *cmd) { AssertFatal(assoc_id == -1, "illegal assoc_id %d\n", assoc_id); ue_context_release_command(cmd); diff --git a/openair2/RRC/NR/mac_rrc_dl_f1ap.c b/openair2/RRC/NR/mac_rrc_dl_f1ap.c index 47d1bc1d7e..37cb6d70f9 100644 --- a/openair2/RRC/NR/mac_rrc_dl_f1ap.c +++ b/openair2/RRC/NR/mac_rrc_dl_f1ap.c @@ -119,18 +119,11 @@ static void ue_context_modification_refuse_f1ap(sctp_assoc_t assoc_id, const f1a itti_send_msg_to_task(TASK_CU_F1, 0, msg); } -static void ue_context_release_command_f1ap(sctp_assoc_t assoc_id, const f1ap_ue_context_release_cmd_t *cmd) +static void ue_context_release_command_f1ap(sctp_assoc_t assoc_id, const f1ap_ue_context_rel_cmd_t *cmd) { MessageDef *message_p = itti_alloc_new_message (TASK_RRC_GNB, 0, F1AP_UE_CONTEXT_RELEASE_CMD); message_p->ittiMsgHeader.originInstance = assoc_id; - f1ap_ue_context_release_cmd_t *msg = &F1AP_UE_CONTEXT_RELEASE_CMD(message_p); - *msg = *cmd; - if (cmd->rrc_container_length > 0) { - msg->rrc_container = calloc(cmd->rrc_container_length, sizeof(*msg->rrc_container)); - AssertFatal(msg->rrc_container != NULL, "out of memory\n"); - msg->rrc_container_length = cmd->rrc_container_length; - memcpy(msg->rrc_container, cmd->rrc_container, cmd->rrc_container_length); - } + F1AP_UE_CONTEXT_RELEASE_CMD(message_p) = cp_ue_context_rel_cmd(cmd); itti_send_msg_to_task (TASK_CU_F1, 0, message_p); } diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index a7ba899c82..07f7eec659 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -113,7 +113,7 @@ mui_t rrc_gNB_mui = 0; typedef struct deliver_ue_ctxt_release_data_t { gNB_RRC_INST *rrc; - f1ap_ue_context_release_cmd_t *release_cmd; + f1ap_ue_context_rel_cmd_t *release_cmd; sctp_assoc_t assoc_id; } deliver_ue_ctxt_release_data_t; @@ -121,8 +121,8 @@ static void rrc_deliver_ue_ctxt_release_cmd(void *deliver_pdu_data, ue_id_t ue_i { DevAssert(deliver_pdu_data != NULL); deliver_ue_ctxt_release_data_t *data = deliver_pdu_data; - data->release_cmd->rrc_container = (uint8_t*) buf; - data->release_cmd->rrc_container_length = size; + byte_array_t rrc_cont = {.buf = (uint8_t *)buf, .len = size}; + data->release_cmd->rrc_container = &rrc_cont; data->rrc->mac_rrc.ue_context_release_command(data->assoc_id, data->release_cmd); } @@ -2142,12 +2142,12 @@ static void rrc_CU_process_ue_context_release_request(MessageDef *msg_p, sctp_as LOG_W(RRC, "could not find UE context for CU UE ID %u: auto-generate release command\n", req->gNB_CU_ue_id); uint8_t buffer[NR_RRC_BUF_SIZE] = {0}; int size = do_NR_RRCRelease(buffer, NR_RRC_BUF_SIZE, rrc_gNB_get_next_transaction_identifier(0)); - f1ap_ue_context_release_cmd_t ue_context_release_cmd = { + f1ap_ue_context_rel_cmd_t ue_context_release_cmd = { .gNB_CU_ue_id = req->gNB_CU_ue_id, .gNB_DU_ue_id = req->gNB_DU_ue_id, .cause = F1AP_CAUSE_RADIO_NETWORK, .cause_value = 10, // 10 = F1AP_CauseRadioNetwork_normal_release - .srb_id = srbid, + .srb_id = &srbid, // C-ifRRCContainer => is added below }; deliver_ue_ctxt_release_data_t data = {.rrc = rrc, .release_cmd = &ue_context_release_cmd}; nr_pdcp_data_req_srb(req->gNB_CU_ue_id, srbid, rrc_gNB_mui++, size, buffer, rrc_deliver_ue_ctxt_release_cmd, &data); @@ -2163,12 +2163,11 @@ static void rrc_CU_process_ue_context_release_request(MessageDef *msg_p, sctp_as // ongoing; free the UE, and remove the HO context. LOG_W(NR_RRC, "UE %d: release request from source DU ID %ld during HO, marking HO as complete\n", UE->rrc_ue_id, source_ctx->du->setup_req->gNB_DU_id); RETURN_IF_INVALID_ASSOC_ID(source_ctx->du->assoc_id); - f1ap_ue_context_release_cmd_t cmd = { + f1ap_ue_context_rel_cmd_t cmd = { .gNB_CU_ue_id = UE->rrc_ue_id, .gNB_DU_ue_id = source_ctx->du_ue_id, .cause = F1AP_CAUSE_RADIO_NETWORK, .cause_value = 5, // 5 = F1AP_CauseRadioNetwork_interaction_with_other_procedure - .srb_id = DL_SCH_LCID_DCCH, }; rrc->mac_rrc.ue_context_release_command(assoc_id, &cmd); nr_rrc_finalize_ho(UE); @@ -2914,12 +2913,13 @@ void rrc_gNB_generate_RRCRelease(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE) LOG_UE_DL_EVENT(UE, "Send RRC Release\n"); f1_ue_data_t ue_data = cu_get_f1_ue_data(UE->rrc_ue_id); RETURN_IF_INVALID_ASSOC_ID(ue_data.du_assoc_id); - f1ap_ue_context_release_cmd_t ue_context_release_cmd = { + int srbid = 1; + f1ap_ue_context_rel_cmd_t ue_context_release_cmd = { .gNB_CU_ue_id = UE->rrc_ue_id, .gNB_DU_ue_id = ue_data.secondary_ue, .cause = F1AP_CAUSE_RADIO_NETWORK, .cause_value = 10, // 10 = F1AP_CauseRadioNetwork_normal_release - .srb_id = DL_SCH_LCID_DCCH, + .srb_id = &srbid, // C-ifRRCContainer => is added below }; deliver_ue_ctxt_release_data_t data = {.rrc = rrc, .release_cmd = &ue_context_release_cmd, .assoc_id = ue_data.du_assoc_id}; nr_pdcp_data_req_srb(UE->rrc_ue_id, DL_SCH_LCID_DCCH, rrc_gNB_mui++, size, buffer, rrc_deliver_ue_ctxt_release_cmd, &data); diff --git a/openair2/RRC/NR/rrc_gNB_mobility.c b/openair2/RRC/NR/rrc_gNB_mobility.c index a08e446ef1..7312e2f631 100644 --- a/openair2/RRC/NR/rrc_gNB_mobility.c +++ b/openair2/RRC/NR/rrc_gNB_mobility.c @@ -307,12 +307,11 @@ static void nr_rrc_f1_ho_complete(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE) nr_ho_source_cu_t *source_ctx = UE->ho_context->source; DevAssert(source_ctx != NULL); RETURN_IF_INVALID_ASSOC_ID(source_ctx->du->assoc_id); - f1ap_ue_context_release_cmd_t cmd = { + f1ap_ue_context_rel_cmd_t cmd = { .gNB_CU_ue_id = UE->rrc_ue_id, .gNB_DU_ue_id = source_ctx->du_ue_id, .cause = F1AP_CAUSE_RADIO_NETWORK, .cause_value = 5, // 5 = F1AP_CauseRadioNetwork_interaction_with_other_procedure - .srb_id = DL_SCH_LCID_DCCH, }; rrc->mac_rrc.ue_context_release_command(source_ctx->du->assoc_id, &cmd); LOG_I(NR_RRC, "UE %d Handover: trigger release on DU assoc_id %d\n", UE->rrc_ue_id, source_ctx->du->assoc_id); @@ -323,12 +322,11 @@ static void nr_rrc_cancel_f1_ho(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE) DevAssert(UE->ho_context != NULL); nr_ho_target_cu_t *target_ctx = UE->ho_context->target; DevAssert(target_ctx != NULL); - f1ap_ue_context_release_cmd_t cmd = { + f1ap_ue_context_rel_cmd_t cmd = { .gNB_CU_ue_id = UE->rrc_ue_id, .gNB_DU_ue_id = target_ctx->du_ue_id, .cause = F1AP_CAUSE_RADIO_NETWORK, // better .cause_value = 5, // 5 = F1AP_CauseRadioNetwork_interaction_with_other_procedure - .srb_id = DL_SCH_LCID_DCCH, }; rrc->mac_rrc.ue_context_release_command(target_ctx->du->assoc_id, &cmd); } diff --git a/openair2/RRC/NR/rrc_gNB_nsa.c b/openair2/RRC/NR/rrc_gNB_nsa.c index 78be16b100..c2dfb3e20a 100644 --- a/openair2/RRC/NR/rrc_gNB_nsa.c +++ b/openair2/RRC/NR/rrc_gNB_nsa.c @@ -464,7 +464,7 @@ void rrc_release_nsa_user(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context) gNB_RRC_UE_t *UE = &ue_context->ue_context; f1_ue_data_t ue_data = cu_get_f1_ue_data(UE->rrc_ue_id); RETURN_IF_INVALID_ASSOC_ID(ue_data.du_assoc_id); - f1ap_ue_context_release_cmd_t cmd = { + f1ap_ue_context_rel_cmd_t cmd = { .gNB_CU_ue_id = UE->rrc_ue_id, .gNB_DU_ue_id = ue_data.secondary_ue, .cause = F1AP_CAUSE_RADIO_NETWORK, From bbb6b3f7ad2f93a7a5f87db1eac9ad53448da634 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 13 Jun 2025 11:26:23 +0200 Subject: [PATCH 130/964] Add F1AP UE context release complete message enc/dec + test See commit "Add F1AP UE context setup request message enc/dec + test" for more details on the approach taken. --- openair2/COMMON/f1ap_messages_types.h | 5 ++ openair2/F1AP/lib/f1ap_ue_context.c | 96 +++++++++++++++++++++++++++ openair2/F1AP/lib/f1ap_ue_context.h | 6 ++ openair2/F1AP/tests/f1ap_lib_test.c | 30 +++++++++ 4 files changed, 137 insertions(+) diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h index 243a8e5bcc..46697e532e 100644 --- a/openair2/COMMON/f1ap_messages_types.h +++ b/openair2/COMMON/f1ap_messages_types.h @@ -668,6 +668,11 @@ typedef struct f1ap_ue_context_rel_cmd_t { uint32_t *old_gNB_DU_ue_id; // if after reestablishment request } f1ap_ue_context_rel_cmd_t; +typedef struct f1ap_ue_context_rel_cplt_t { + uint32_t gNB_CU_ue_id; + uint32_t gNB_DU_ue_id; +} f1ap_ue_context_rel_cplt_t; + typedef struct f1ap_ue_context_release_s { uint32_t gNB_CU_ue_id; uint32_t gNB_DU_ue_id; diff --git a/openair2/F1AP/lib/f1ap_ue_context.c b/openair2/F1AP/lib/f1ap_ue_context.c index d070ca0cde..a1b5531c2b 100644 --- a/openair2/F1AP/lib/f1ap_ue_context.c +++ b/openair2/F1AP/lib/f1ap_ue_context.c @@ -2370,3 +2370,99 @@ void free_ue_context_rel_cmd(f1ap_ue_context_rel_cmd_t *cmd) free(cmd->srb_id); free(cmd->old_gNB_DU_ue_id); } + +/* + * @brief Encode F1 UE context release complete to ASN.1 + */ +struct F1AP_F1AP_PDU *encode_ue_context_rel_cplt(const f1ap_ue_context_rel_cplt_t *cplt) +{ + F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); + + /* Message Type */ + pdu->present = F1AP_F1AP_PDU_PR_successfulOutcome; + asn1cCalloc(pdu->choice.successfulOutcome, tmp); + tmp->procedureCode = F1AP_ProcedureCode_id_UEContextRelease; + tmp->criticality = F1AP_Criticality_reject; + tmp->value.present = F1AP_SuccessfulOutcome__value_PR_UEContextReleaseComplete; + F1AP_UEContextReleaseComplete_t *out = &tmp->value.choice.UEContextReleaseComplete; + + /* mandatory: GNB_CU_UE_F1AP_ID */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseCompleteIEs_t, ie1); + ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; + ie1->criticality = F1AP_Criticality_reject; + ie1->value.present = F1AP_UEContextReleaseCompleteIEs__value_PR_GNB_CU_UE_F1AP_ID; + ie1->value.choice.GNB_CU_UE_F1AP_ID = cplt->gNB_CU_ue_id; + + /* mandatory: GNB_DU_UE_F1AP_ID */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseCompleteIEs_t, ie2); + ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; + ie2->criticality = F1AP_Criticality_reject; + ie2->value.present = F1AP_UEContextReleaseCompleteIEs__value_PR_GNB_DU_UE_F1AP_ID; + ie2->value.choice.GNB_DU_UE_F1AP_ID = cplt->gNB_DU_ue_id; + + return pdu; +} + +/** + * @brief Decode F1 UE Context Release Complete + */ +bool decode_ue_context_rel_cplt(const struct F1AP_F1AP_PDU *pdu, f1ap_ue_context_rel_cplt_t *out) +{ + DevAssert(out != NULL); + memset(out, 0, sizeof(*out)); + + F1AP_UEContextReleaseComplete_t *in = &pdu->choice.successfulOutcome->value.choice.UEContextReleaseComplete; + F1AP_UEContextReleaseCompleteIEs_t *ie; + F1AP_LIB_FIND_IE(F1AP_UEContextReleaseCompleteIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); + F1AP_LIB_FIND_IE(F1AP_UEContextReleaseCompleteIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); + + for (int i = 0; i < in->protocolIEs.list.count; ++i) { + ie = in->protocolIEs.list.array[i]; + AssertError(ie != NULL, return false, "in->protocolIEs.list.array[i] is NULL"); + switch (ie->id) { + case F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextReleaseCompleteIEs__value_PR_GNB_CU_UE_F1AP_ID); + out->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID; + break; + case F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextReleaseCompleteIEs__value_PR_GNB_DU_UE_F1AP_ID); + out->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; + break; + default: + PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld unknown, skipping\n", ie->id); + break; + } + } + + return true; +} + +/** + * @brief F1 UE Context Release Complete deep copy + */ +f1ap_ue_context_rel_cplt_t cp_ue_context_rel_cplt(const f1ap_ue_context_rel_cplt_t *orig) +{ + f1ap_ue_context_rel_cplt_t cp = { + .gNB_CU_ue_id = orig->gNB_CU_ue_id, + .gNB_DU_ue_id = orig->gNB_DU_ue_id, + }; + return cp; +} + +/** + * @brief F1 UE Context Release Complete equality check + */ +bool eq_ue_context_rel_cplt(const f1ap_ue_context_rel_cplt_t *a, const f1ap_ue_context_rel_cplt_t *b) +{ + _F1_EQ_CHECK_INT(a->gNB_CU_ue_id, b->gNB_CU_ue_id); + _F1_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id); + return true; +} + +/** + * @brief Free Allocated F1 UE Context Release Complete + */ +void free_ue_context_rel_cplt(f1ap_ue_context_rel_cplt_t *cplt) +{ + // nothing to free +} diff --git a/openair2/F1AP/lib/f1ap_ue_context.h b/openair2/F1AP/lib/f1ap_ue_context.h index 34dd3035a3..0e82e82a85 100644 --- a/openair2/F1AP/lib/f1ap_ue_context.h +++ b/openair2/F1AP/lib/f1ap_ue_context.h @@ -63,4 +63,10 @@ f1ap_ue_context_rel_cmd_t cp_ue_context_rel_cmd(const f1ap_ue_context_rel_cmd_t bool eq_ue_context_rel_cmd(const f1ap_ue_context_rel_cmd_t *a, const f1ap_ue_context_rel_cmd_t *b); void free_ue_context_rel_cmd(f1ap_ue_context_rel_cmd_t *cmd); +struct F1AP_F1AP_PDU *encode_ue_context_rel_cplt(const f1ap_ue_context_rel_cplt_t *msg); +bool decode_ue_context_rel_cplt(const struct F1AP_F1AP_PDU *pdu, f1ap_ue_context_rel_cplt_t *out); +f1ap_ue_context_rel_cplt_t cp_ue_context_rel_cplt(const f1ap_ue_context_rel_cplt_t *orig); +bool eq_ue_context_rel_cplt(const f1ap_ue_context_rel_cplt_t *a, const f1ap_ue_context_rel_cplt_t *b); +void free_ue_context_rel_cplt(f1ap_ue_context_rel_cplt_t *cplt); + #endif /* F1AP_UE_CONTEXT_SETUP_REQ_H_ */ diff --git a/openair2/F1AP/tests/f1ap_lib_test.c b/openair2/F1AP/tests/f1ap_lib_test.c index d46b93983b..ebf90fc648 100644 --- a/openair2/F1AP/tests/f1ap_lib_test.c +++ b/openair2/F1AP/tests/f1ap_lib_test.c @@ -1237,6 +1237,35 @@ static void test_f1ap_ue_context_release_command() printf("%s() successful\n", __func__); } +static void test_f1ap_ue_context_release_complete() +{ + f1ap_ue_context_rel_cplt_t orig = { + .gNB_CU_ue_id = 1111, + .gNB_DU_ue_id = 2222, + }; + + F1AP_F1AP_PDU_t *f1enc = encode_ue_context_rel_cplt(&orig); + F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + + f1ap_ue_context_rel_cplt_t decoded = {0}; + bool ret = decode_ue_context_rel_cplt(f1dec, &decoded); + AssertFatal(ret, "decode_ue_context_rel_cplt(): could not decode message\n"); + f1ap_msg_free(f1dec); + + ret = eq_ue_context_rel_cplt(&orig, &decoded); + AssertFatal(ret, "eq_ue_context_rel_cplt(): decoded message doesn't match\n"); + free_ue_context_rel_cplt(&decoded); + + f1ap_ue_context_rel_cplt_t cp = cp_ue_context_rel_cplt(&orig); + ret = eq_ue_context_rel_cplt(&orig, &cp); + AssertFatal(ret, "eq_ue_context_rel_cplt(): copied message doesn't match\n"); + free_ue_context_rel_cplt(&orig); + free_ue_context_rel_cplt(&cp); + + printf("%s() successful\n", __func__); +} + int main() { test_initial_ul_rrc_message_transfer(); @@ -1262,5 +1291,6 @@ int main() test_f1ap_ue_context_modification_response_simple(); test_f1ap_ue_context_release_request(); test_f1ap_ue_context_release_command(); + test_f1ap_ue_context_release_complete(); return 0; } From abb3eff285a5193491f7290a333e3ea822c76793 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 19 Jun 2025 17:33:38 +0200 Subject: [PATCH 131/964] Use F1 UE context Release Complete in stack Use the new type and remove the old one. --- openair2/COMMON/f1ap_messages_def.h | 2 +- openair2/COMMON/f1ap_messages_types.h | 10 --- openair2/F1AP/f1ap_cu_ue_context_management.c | 36 ++------- openair2/F1AP/f1ap_du_ue_context_management.c | 81 ++----------------- openair2/F1AP/f1ap_du_ue_context_management.h | 2 +- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 2 +- .../LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c | 4 +- openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h | 2 +- .../LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c | 5 +- openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c | 5 +- openair2/RRC/NR/rrc_gNB.c | 3 +- 11 files changed, 25 insertions(+), 127 deletions(-) diff --git a/openair2/COMMON/f1ap_messages_def.h b/openair2/COMMON/f1ap_messages_def.h index f46120a037..18b16563d8 100644 --- a/openair2/COMMON/f1ap_messages_def.h +++ b/openair2/COMMON/f1ap_messages_def.h @@ -50,7 +50,7 @@ MESSAGE_DEF(F1AP_UL_RRC_MESSAGE , MESSAGE_PRIORITY_MED, f1ap_ul_r //MESSAGE_DEF(F1AP_INITIAL_CONTEXT_SETUP_FAILURE, MESSAGE_PRIORITY_MED, f1ap_initial_context_setup_failure_t, f1ap_initial_context_setup_failure) MESSAGE_DEF(F1AP_UE_CONTEXT_RELEASE_REQ, MESSAGE_PRIORITY_MED, f1ap_ue_context_rel_req_t, f1ap_ue_context_release_req) MESSAGE_DEF(F1AP_UE_CONTEXT_RELEASE_CMD, MESSAGE_PRIORITY_MED, f1ap_ue_context_rel_cmd_t, f1ap_ue_context_release_cmd) -MESSAGE_DEF(F1AP_UE_CONTEXT_RELEASE_COMPLETE, MESSAGE_PRIORITY_MED, f1ap_ue_context_release_complete_t, f1ap_ue_context_release_complete) +MESSAGE_DEF(F1AP_UE_CONTEXT_RELEASE_COMPLETE, MESSAGE_PRIORITY_MED, f1ap_ue_context_rel_cplt_t, f1ap_ue_context_release_complete) MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_REQUIRED, MESSAGE_PRIORITY_MED, f1ap_ue_context_modif_required_t, f1ap_ue_context_modification_required) /* RRC -> F1AP messages */ diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h index 46697e532e..12f41a81f9 100644 --- a/openair2/COMMON/f1ap_messages_types.h +++ b/openair2/COMMON/f1ap_messages_types.h @@ -673,16 +673,6 @@ typedef struct f1ap_ue_context_rel_cplt_t { uint32_t gNB_DU_ue_id; } f1ap_ue_context_rel_cplt_t; -typedef struct f1ap_ue_context_release_s { - uint32_t gNB_CU_ue_id; - uint32_t gNB_DU_ue_id; - f1ap_Cause_t cause; - long cause_value; - uint8_t *rrc_container; - int rrc_container_length; - int srb_id; -} f1ap_ue_context_release_complete_t; - typedef struct f1ap_paging_ind_s { uint16_t ueidentityindexvalue; uint64_t fiveg_s_tmsi; diff --git a/openair2/F1AP/f1ap_cu_ue_context_management.c b/openair2/F1AP/f1ap_cu_ue_context_management.c index d29c52dec5..2d0959eb25 100644 --- a/openair2/F1AP/f1ap_cu_ue_context_management.c +++ b/openair2/F1AP/f1ap_cu_ue_context_management.c @@ -122,37 +122,17 @@ int CU_send_UE_CONTEXT_RELEASE_COMMAND(sctp_assoc_t assoc_id, f1ap_ue_context_re int CU_handle_UE_CONTEXT_RELEASE_COMPLETE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { - F1AP_UEContextReleaseComplete_t *container; - F1AP_UEContextReleaseCompleteIEs_t *ie; - DevAssert(pdu); - MessageDef *msg_p = itti_alloc_new_message(TASK_DU_F1, 0, F1AP_UE_CONTEXT_RELEASE_COMPLETE); - msg_p->ittiMsgHeader.originInstance = assoc_id; - f1ap_ue_context_release_complete_t *complete = &F1AP_UE_CONTEXT_RELEASE_COMPLETE(msg_p); - container = &pdu->choice.successfulOutcome->value.choice.UEContextReleaseComplete; - /* GNB_CU_UE_F1AP_ID */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextReleaseCompleteIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); - complete->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID; - /* GNB_DU_UE_F1AP_ID */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextReleaseCompleteIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); - complete->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; - - /* Optional*/ - /* CriticalityDiagnostics */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextReleaseCompleteIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_CriticalityDiagnostics, false); - - if (ie) { - // ie->value.choice.CriticalityDiagnostics.procedureCode - // ie->value.choice.CriticalityDiagnostics.triggeringMessage - // ie->value.choice.CriticalityDiagnostics.procedureCriticality - // ie->value.choice.CriticalityDiagnostics.transactionID - // F1AP_CriticalityDiagnostics_IE_List + f1ap_ue_context_rel_cplt_t cplt = {0}; + if (!decode_ue_context_rel_cplt(pdu, &cplt)) { + LOG_E(F1AP, "cannot decode F1 UE Context Release Complete\n"); + free_ue_context_rel_cplt(&cplt); + return -1; } + MessageDef *msg_p = itti_alloc_new_message(TASK_DU_F1, 0, F1AP_UE_CONTEXT_RELEASE_COMPLETE); + msg_p->ittiMsgHeader.originInstance = assoc_id; + F1AP_UE_CONTEXT_RELEASE_COMPLETE(msg_p) = cplt; itti_send_msg_to_task(TASK_RRC_GNB, instance, msg_p); - return 0; } diff --git a/openair2/F1AP/f1ap_du_ue_context_management.c b/openair2/F1AP/f1ap_du_ue_context_management.c index 7371b69a4f..e09f038864 100644 --- a/openair2/F1AP/f1ap_du_ue_context_management.c +++ b/openair2/F1AP/f1ap_du_ue_context_management.c @@ -106,90 +106,19 @@ int DU_handle_UE_CONTEXT_RELEASE_COMMAND(instance_t instance, sctp_assoc_t assoc return 0; } -int DU_send_UE_CONTEXT_RELEASE_COMPLETE(sctp_assoc_t assoc_id, f1ap_ue_context_release_complete_t *complete) +int DU_send_UE_CONTEXT_RELEASE_COMPLETE(sctp_assoc_t assoc_id, f1ap_ue_context_rel_cplt_t *cplt) { - F1AP_F1AP_PDU_t pdu= {0}; - F1AP_UEContextReleaseComplete_t *out; - /* Create */ - /* 0. Message Type */ - pdu.present = F1AP_F1AP_PDU_PR_successfulOutcome; - asn1cCalloc(pdu.choice.successfulOutcome, tmp); - tmp->procedureCode = F1AP_ProcedureCode_id_UEContextRelease; - tmp->criticality = F1AP_Criticality_reject; - tmp->value.present = F1AP_SuccessfulOutcome__value_PR_UEContextReleaseComplete; - out = &tmp->value.choice.UEContextReleaseComplete; - /* mandatory */ - /* c1. GNB_CU_UE_F1AP_ID */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseCompleteIEs_t, ie1); - ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; - ie1->criticality = F1AP_Criticality_reject; - ie1->value.present = F1AP_UEContextReleaseCompleteIEs__value_PR_GNB_CU_UE_F1AP_ID; - ie1->value.choice.GNB_CU_UE_F1AP_ID = complete->gNB_CU_ue_id; - /* mandatory */ - /* c2. GNB_DU_UE_F1AP_ID */ - asn1cSequenceAdd(out->protocolIEs.list,F1AP_UEContextReleaseCompleteIEs_t, ie2); - ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; - ie2->criticality = F1AP_Criticality_reject; - ie2->value.present = F1AP_UEContextReleaseCompleteIEs__value_PR_GNB_DU_UE_F1AP_ID; - ie2->value.choice.GNB_DU_UE_F1AP_ID = complete->gNB_DU_ue_id; - /* optional -> currently not used */ - /* c3. CriticalityDiagnostics */ - //if (0) { - // ie = (F1AP_UEContextReleaseCompleteIEs_t *)calloc(1, sizeof(F1AP_UEContextReleaseCompleteIEs_t)); - // ie->id = F1AP_ProtocolIE_ID_id_CriticalityDiagnostics; - // ie->criticality = F1AP_Criticality_ignore; - // ie->value.present = F1AP_UEContextReleaseCompleteIEs__value_PR_CriticalityDiagnostics; - // // dummy value - // /* optional */ - // /* procedureCode */ - // if (0) { - // ie->value.choice.CriticalityDiagnostics.procedureCode = (F1AP_ProcedureCode_t *)calloc(1, sizeof(F1AP_ProcedureCode_t)); - // ie->value.choice.CriticalityDiagnostics.procedureCode = 0L; - // } - // /* optional */ - // /* triggeringMessage */ - // if (0) { - // ie->value.choice.CriticalityDiagnostics.triggeringMessage = (F1AP_TriggeringMessage_t *)calloc(1, sizeof(F1AP_TriggeringMessage_t)); - // ie->value.choice.CriticalityDiagnostics.triggeringMessage = (F1AP_TriggeringMessage_t *)F1AP_TriggeringMessage_successful_outcome; - // } - // /* optional */ - // /* procedureCriticality */ - // if (0) { - // ie->value.choice.CriticalityDiagnostics.procedureCriticality = (F1AP_Criticality_t *)calloc(1, sizeof(F1AP_Criticality_t)); - // ie->value.choice.CriticalityDiagnostics.procedureCriticality = F1AP_Criticality_reject; - // } - // /* optional */ - // /* transactionID */ - // if (0) { - // ie->value.choice.CriticalityDiagnostics.transactionID = (F1AP_TransactionID_t *)calloc(1, sizeof(F1AP_TransactionID_t)); - // ie->value.choice.CriticalityDiagnostics.transactionID = 0L; - // } - // /* optional */ - // /* F1AP_CriticalityDiagnostics_IE_List */ - // if (0) { - // for (i=0; - // i<0; - // i++) { - // F1AP_CriticalityDiagnostics_IE_Item_t *criticalityDiagnostics_ie_item = (F1AP_CriticalityDiagnostics_IE_Item_t *)calloc(1, sizeof(F1AP_CriticalityDiagnostics_IE_Item_t));; - // criticalityDiagnostics_ie_item->iECriticality = F1AP_Criticality_reject; - // criticalityDiagnostics_ie_item->iE_ID = 0L; - // criticalityDiagnostics_ie_item->typeOfError = F1AP_TypeOfError_not_understood; - // asn1cSeqAdd(&ie->value.choice.CriticalityDiagnostics.iEsCriticalityDiagnostics->list, - // criticalityDiagnostics_ie_item); - // } - // } - // asn1cSeqAdd(&out->protocolIEs.list, ie); - //} - /* encode */ + F1AP_F1AP_PDU_t *pdu = encode_ue_context_rel_cplt(cplt); + uint8_t *buffer; uint32_t len; - - if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { + if (f1ap_encode_pdu(pdu, &buffer, &len) < 0) { LOG_E(F1AP, "Failed to encode F1 context release complete\n"); return -1; } f1ap_itti_send_sctp_data_req(assoc_id, buffer, len); + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); return 0; } diff --git a/openair2/F1AP/f1ap_du_ue_context_management.h b/openair2/F1AP/f1ap_du_ue_context_management.h index e9ef2bef8c..b6c12de18b 100644 --- a/openair2/F1AP/f1ap_du_ue_context_management.h +++ b/openair2/F1AP/f1ap_du_ue_context_management.h @@ -55,7 +55,7 @@ int DU_handle_UE_CONTEXT_RELEASE_COMMAND(instance_t instance, sctp_assoc_t assoc /* * UE Context Release Complete (gNB-DU initiated) */ -int DU_send_UE_CONTEXT_RELEASE_COMPLETE(sctp_assoc_t assoc_id, f1ap_ue_context_release_complete_t *complete); +int DU_send_UE_CONTEXT_RELEASE_COMPLETE(sctp_assoc_t assoc_id, f1ap_ue_context_rel_cplt_t *cplt); /* * UE Context Modification (gNB-CU initiated) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index b85c26b1a3..48fabb45e8 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -3124,7 +3124,7 @@ void nr_mac_trigger_release_complete(gNB_MAC_INST *mac, int rnti) // du_remove_f1_ue_data() (and also while sending the message to RRC) NR_SCHED_UNLOCK(&mac->sched_lock); f1_ue_data_t ue_data = du_get_f1_ue_data(rnti); - f1ap_ue_context_release_complete_t complete = { + f1ap_ue_context_rel_cplt_t complete = { .gNB_CU_ue_id = ue_data.secondary_ue, .gNB_DU_ue_id = rnti, }; diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c index 74529c9dde..3b5fd80639 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -869,7 +869,7 @@ void ue_context_release_command(const f1ap_ue_context_rel_cmd_t *cmd) NR_UE_info_t *UE = find_nr_UE(&mac->UE_info, cmd->gNB_DU_ue_id); if (UE == NULL) { NR_SCHED_UNLOCK(&mac->sched_lock); - f1ap_ue_context_release_complete_t complete = { + f1ap_ue_context_rel_cplt_t complete = { .gNB_CU_ue_id = cmd->gNB_CU_ue_id, .gNB_DU_ue_id = cmd->gNB_DU_ue_id, }; @@ -889,7 +889,7 @@ void ue_context_release_command(const f1ap_ue_context_rel_cmd_t *cmd) /* UE is in sync: forward release message and mark to be deleted * after UL failure */ byte_array_t *rrc_cont = cmd->rrc_container; - nr_rlc_srb_recv_sdu(cmd->gNB_DU_ue_id, *cmd->srb_id, (char *)rrc_cont->buf, rrc_cont->len); + nr_rlc_srb_recv_sdu(cmd->gNB_DU_ue_id, *cmd->srb_id, rrc_cont->buf, rrc_cont->len); nr_mac_trigger_release_timer(&UE->UE_sched_ctrl, UE->current_UL_BWP.scs); } NR_SCHED_UNLOCK(&mac->sched_lock); diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h index 3f54ae53b8..23dda86dfb 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h @@ -35,7 +35,7 @@ typedef void (*ue_context_setup_response_func_t)(const f1ap_ue_context_setup_res typedef void (*ue_context_modification_response_func_t)(const f1ap_ue_context_mod_resp_t *resp); typedef void (*ue_context_modification_required_func_t)(const f1ap_ue_context_modif_required_t *t); typedef void (*ue_context_release_request_func_t)(const f1ap_ue_context_rel_req_t* req); -typedef void (*ue_context_release_complete_func_t)(const f1ap_ue_context_release_complete_t *complete); +typedef void (*ue_context_release_complete_func_t)(const f1ap_ue_context_rel_cplt_t *complete); typedef void (*initial_ul_rrc_message_transfer_func_t)(module_id_t module_id, const f1ap_initial_ul_rrc_message_t *ul_rrc); diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c index 9f719374c1..cf6c5b2563 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c @@ -109,12 +109,11 @@ static void ue_context_release_request_direct(const f1ap_ue_context_rel_req_t* r itti_send_msg_to_task(TASK_RRC_GNB, 0, msg); } -static void ue_context_release_complete_direct(const f1ap_ue_context_release_complete_t *complete) +static void ue_context_release_complete_direct(const f1ap_ue_context_rel_cplt_t *complete) { MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_RELEASE_COMPLETE); msg->ittiMsgHeader.originInstance = -1; // means monolithic - f1ap_ue_context_release_complete_t *f1ap_msg = &F1AP_UE_CONTEXT_RELEASE_COMPLETE(msg); - *f1ap_msg = *complete; + F1AP_UE_CONTEXT_RELEASE_COMPLETE(msg) = cp_ue_context_rel_cplt(complete); itti_send_msg_to_task(TASK_RRC_GNB, 0, msg); } diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c index 29990cf3a9..19bf8039b6 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c @@ -132,13 +132,12 @@ static void ue_context_release_request_f1ap(const f1ap_ue_context_rel_req_t* req itti_send_msg_to_task(TASK_DU_F1, 0, msg); } -static void ue_context_release_complete_f1ap(const f1ap_ue_context_release_complete_t *complete) +static void ue_context_release_complete_f1ap(const f1ap_ue_context_rel_cplt_t *complete) { newGtpuDeleteAllTunnels(0, complete->gNB_DU_ue_id); MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_RELEASE_COMPLETE); - f1ap_ue_context_release_complete_t *f1ap_msg = &F1AP_UE_CONTEXT_RELEASE_COMPLETE(msg); - *f1ap_msg = *complete; + F1AP_UE_CONTEXT_RELEASE_COMPLETE(msg) = cp_ue_context_rel_cplt(complete); itti_send_msg_to_task(TASK_DU_F1, 0, msg); } diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 07f7eec659..9630493d15 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -2207,7 +2207,7 @@ void rrc_remove_ue(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p) static void rrc_CU_process_ue_context_release_complete(MessageDef *msg_p) { const int instance = 0; - f1ap_ue_context_release_complete_t *complete = &F1AP_UE_CONTEXT_RELEASE_COMPLETE(msg_p); + f1ap_ue_context_rel_cplt_t *complete = &F1AP_UE_CONTEXT_RELEASE_COMPLETE(msg_p); gNB_RRC_INST *rrc = RC.nrrrc[instance]; rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(rrc, complete->gNB_CU_ue_id); if (!ue_context_p) { @@ -2779,6 +2779,7 @@ void *rrc_gnb_task(void *args_p) { case F1AP_UE_CONTEXT_RELEASE_COMPLETE: rrc_CU_process_ue_context_release_complete(msg_p); + free_ue_context_rel_cplt(&F1AP_UE_CONTEXT_RELEASE_COMPLETE(msg_p)); break; case F1AP_LOST_CONNECTION: From 1a2aa1266c3d4c9de8191ba11e614d1aa72b26fe Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 19 Jun 2025 19:07:54 +0200 Subject: [PATCH 132/964] Remove more unused types --- openair2/COMMON/f1ap_messages_types.h | 42 --------------------------- 1 file changed, 42 deletions(-) diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h index 12f41a81f9..89826e7ff5 100644 --- a/openair2/COMMON/f1ap_messages_types.h +++ b/openair2/COMMON/f1ap_messages_types.h @@ -363,7 +363,6 @@ typedef struct f1ap_ul_rrc_message_s { typedef struct f1ap_up_tnl_s { in_addr_t tl_address; // currently only IPv4 supported uint32_t teid; - uint16_t port; } f1ap_up_tnl_t; typedef enum preemption_capability_e { @@ -376,47 +375,6 @@ typedef enum preemption_vulnerability_e { PREEMPTABLE, } preemption_vulnerability_t; -typedef struct f1ap_qos_characteristics_s { - union { - struct { - long fiveqi; - long qos_priority_level; - } non_dynamic; - struct { - long fiveqi; // -1 -> optional - long qos_priority_level; - long packet_delay_budget; - struct { - long per_scalar; - long per_exponent; - } packet_error_rate; - } dynamic; - }; - fiveQI_t qos_type; -} f1ap_qos_characteristics_t; - -typedef struct f1ap_ngran_allocation_retention_priority_s { - uint16_t priority_level; - preemption_capability_t preemption_capability; - preemption_vulnerability_t preemption_vulnerability; -} f1ap_ngran_allocation_retention_priority_t; - -typedef struct f1ap_qos_flow_level_qos_parameters_s { - f1ap_qos_characteristics_t qos_characteristics; - f1ap_ngran_allocation_retention_priority_t alloc_reten_priority; -} f1ap_qos_flow_level_qos_parameters_t; - -typedef struct f1ap_flows_mapped_to_drb_s { - long qfi; // qos flow identifier - f1ap_qos_flow_level_qos_parameters_t qos_params; -} f1ap_flows_mapped_to_drb_t; - -typedef struct f1ap_drb_information_s { - f1ap_qos_flow_level_qos_parameters_t drb_qos; - f1ap_flows_mapped_to_drb_t *flows_mapped_to_drb; - uint8_t flows_to_be_setup_length; -} f1ap_drb_information_t; - typedef enum f1ap_rlc_mode_t { F1AP_RLC_MODE_AM, F1AP_RLC_MODE_UM_BIDIR, F1AP_RLC_UM_UNI_UL, F1AP_RLC_UM_UNI_DL } f1ap_rlc_mode_t; typedef struct f1ap_cu_to_du_rrc_info_s { From 332b2644e445eaaa59787e690a6207fd84019775 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 20 Jun 2025 08:13:50 +0200 Subject: [PATCH 133/964] Fix memory leak in cg_config_info_from_ue_cap_file() Indirect leak of 40 byte(s) in 1 object(s) allocated from: #0 0x7f7b2b4e6883 in calloc (/lib64/libasan.so.8+0xe6883) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) #1 0x00000083e6e6 in calloc_or_fail /home/richie/w/f1-refactor-ue-context/common/utils/utils.h:74 #2 0x00000083e6e6 in cg_config_info_from_ue_cap_file /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_nsa.c:82 #3 0x00000083e6e6 in rrc_add_nsa_user /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_nsa.c:145 #4 0x000000886bcb in rrc_gNB_process_f1_setup_req /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_du.c:444 #5 0x000000833902 in rrc_gnb_task /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2766 #6 0x7f7b2b428ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) Indirect leak of 128 byte(s) in 1 object(s) allocated from: #0 0x7f7b2b4e6883 in calloc (/lib64/libasan.so.8+0xe6883) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) #1 0x00000083e745 in calloc_or_fail /home/richie/w/f1-refactor-ue-context/common/utils/utils.h:74 #2 0x00000083e745 in cg_config_info_from_ue_cap_file /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_nsa.c:84 #3 0x00000083e745 in rrc_add_nsa_user /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_nsa.c:145 #4 0x000000886bcb in rrc_gNB_process_f1_setup_req /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_du.c:444 #5 0x000000833902 in rrc_gnb_task /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2766 #6 0x7f7b2b428ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) Direct leak of 64 byte(s) in 1 object(s) allocated from: #0 0x7f7b2b4e6883 in calloc (/lib64/libasan.so.8+0xe6883) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) #1 0x00000083e6a5 in calloc_or_fail /home/richie/w/f1-refactor-ue-context/common/utils/utils.h:74 #2 0x00000083e6a5 in cg_config_info_from_ue_cap_file /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_nsa.c:80 #3 0x00000083e6a5 in rrc_add_nsa_user /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_nsa.c:145 #4 0x000000886bcb in rrc_gNB_process_f1_setup_req /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_du.c:444 #5 0x000000833902 in rrc_gnb_task /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2766 #6 0x7f7b2b428ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) --- openair2/RRC/NR/rrc_gNB_nsa.c | 1 + 1 file changed, 1 insertion(+) diff --git a/openair2/RRC/NR/rrc_gNB_nsa.c b/openair2/RRC/NR/rrc_gNB_nsa.c index c2dfb3e20a..d722236ce8 100644 --- a/openair2/RRC/NR/rrc_gNB_nsa.c +++ b/openair2/RRC/NR/rrc_gNB_nsa.c @@ -112,6 +112,7 @@ static int cg_config_info_from_ue_cap_file(uint32_t maxlen, uint8_t buf[maxlen]) //xer_fprint(stdout, &asn_DEF_NR_CG_ConfigInfo, cgci); asn_enc_rval_t rval = uper_encode_to_buffer(&asn_DEF_NR_CG_ConfigInfo, NULL, cgci, buf, maxlen); DevAssert(rval.encoded > 0); + ASN_STRUCT_FREE(asn_DEF_NR_CG_ConfigInfo, cgci); return (rval.encoded + 7) >> 3; } From c6954d3f9d46dc8428e0c3ff3e29e9790d61bb31 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 19 Jun 2025 17:45:14 +0200 Subject: [PATCH 134/964] Free UE capabilities memory when removing UE context Direct leak of 32 byte(s) in 1 object(s) allocated from: #0 0x7f672d6e5e2b in realloc.part.0 (/lib64/libasan.so.8+0xe5e2b) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) #1 0x000000fbb4ed in encode_dyn_cb /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/per_encoder.c:23 #2 0x000000fbbeeb in _uper_encode_flush_outp /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/uper_encoder.c:126 #3 0x000000fbbeeb in uper_encode /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/uper_encoder.c:36 #4 0x000000fbc27a in uper_encode_to_new_buffer /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/uper_encoder.c:85 #5 0x00000081037c in handle_ueCapabilityInformation /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:1549 #6 0x000000813ced in rrc_gNB_decode_dcch /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:1902 #7 0x0000008334f2 in rrc_gnb_task /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2741 #8 0x7f672d628ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) --- openair2/RRC/NR/rrc_gNB.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 9630493d15..26193b7381 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -1547,7 +1547,7 @@ static void handle_ueCapabilityInformation(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, ue_cap_info->criticalExtensions.choice.ueCapabilityInformation->ue_CapabilityRAT_ContainerList; /* Encode UE-CapabilityRAT-ContainerList for sending to the DU */ - free(UE->ue_cap_buffer.buf); + FREE_AND_ZERO_BYTE_ARRAY(UE->ue_cap_buffer); UE->ue_cap_buffer.len = uper_encode_to_new_buffer(&asn_DEF_NR_UE_CapabilityRAT_ContainerList, NULL, ue_CapabilityRAT_ContainerList, @@ -2189,6 +2189,7 @@ static void rrc_delete_ue_data(gNB_RRC_UE_t *UE) ASN_STRUCT_FREE(asn_DEF_NR_UE_NR_Capability, UE->UE_Capability_nr); ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->masterCellGroup); ASN_STRUCT_FREE(asn_DEF_NR_MeasResults, UE->measResults); + FREE_AND_ZERO_BYTE_ARRAY(UE->ue_cap_buffer); free_MeasConfig(UE->measConfig); } From 5b9d682fdeeb86f51fdaa5832446ee763c568152 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 19 Jun 2025 17:45:28 +0200 Subject: [PATCH 135/964] Free F1 Setup Response after sending --- openair2/RRC/NR/rrc_gNB_du.c | 1 + 1 file changed, 1 insertion(+) diff --git a/openair2/RRC/NR/rrc_gNB_du.c b/openair2/RRC/NR/rrc_gNB_du.c index a650a03604..1b4e58489d 100644 --- a/openair2/RRC/NR/rrc_gNB_du.c +++ b/openair2/RRC/NR/rrc_gNB_du.c @@ -437,6 +437,7 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id) if (rrc->node_name != NULL) resp.gNB_CU_name = strdup(rrc->node_name); rrc->mac_rrc.f1_setup_response(assoc_id, &resp); + free_f1ap_setup_response(&resp); /* we need to setup one default UE for phy-test and do-ra modes in the MAC */ if (get_softmodem_params()->phy_test > 0 || get_softmodem_params()->do_ra > 0) From 7c65929ece779d69cb8d6636291d414d8ea6f63b Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 19 Jun 2025 17:45:49 +0200 Subject: [PATCH 136/964] Free cell F1 Setup Request after DU disconnection Direct leak of 72 byte(s) in 1 object(s) allocated from: #0 0x7fea71ee6883 in calloc (/lib64/libasan.so.8+0xe6883) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) #1 0x000000886124 in rrc_gNB_process_f1_setup_req /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_du.c:384 #2 0x000000833902 in rrc_gnb_task /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2765 #3 0x7fea71e28ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) Indirect leak of 16592 byte(s) in 1 object(s) allocated from: #0 0x7fea71ee6883 in calloc (/lib64/libasan.so.8+0xe6883) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) #1 0x000000886171 in rrc_gNB_process_f1_setup_req /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_du.c:391 #2 0x000000833902 in rrc_gnb_task /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2765 #3 0x7fea71e28ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) Indirect leak of 102 byte(s) in 1 object(s) allocated from: #0 0x7fea71ee6883 in calloc (/lib64/libasan.so.8+0xe6883) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) #1 0x000000adb79a in calloc_or_fail /home/richie/w/f1-refactor-ue-context/common/utils/utils.h:74 #2 0x000000adb79a in copy_f1ap_gnb_du_system_info /home/richie/w/f1-refactor-ue-context/openair2/F1AP/lib/f1ap_interface_management.c:933 #3 0x000000ae60c9 in cp_f1ap_setup_request /home/richie/w/f1-refactor-ue-context/openair2/F1AP/lib/f1ap_interface_management.c:959 #4 0x0000008861c0 in rrc_gNB_process_f1_setup_req /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_du.c:394 #5 0x000000833902 in rrc_gnb_task /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2765 #6 0x7fea71e28ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) Indirect leak of 32 byte(s) in 1 object(s) allocated from: #0 0x7fea71ee6883 in calloc (/lib64/libasan.so.8+0xe6883) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) #1 0x000000adb667 in calloc_or_fail /home/richie/w/f1-refactor-ue-context/common/utils/utils.h:74 #2 0x000000adb667 in copy_f1ap_gnb_du_system_info /home/richie/w/f1-refactor-ue-context/openair2/F1AP/lib/f1ap_interface_management.c:924 #3 0x000000ae60c9 in cp_f1ap_setup_request /home/richie/w/f1-refactor-ue-context/openair2/F1AP/lib/f1ap_interface_management.c:959 #4 0x0000008861c0 in rrc_gNB_process_f1_setup_req /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_du.c:394 #5 0x000000833902 in rrc_gnb_task /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2765 #6 0x7fea71e28ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) Indirect leak of 15 byte(s) in 1 object(s) allocated from: #0 0x7fea71ee0c80 in strdup (/lib64/libasan.so.8+0xe0c80) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) #1 0x000000ae5f57 in cp_f1ap_setup_request /home/richie/w/f1-refactor-ue-context/openair2/F1AP/lib/f1ap_interface_management.c:950 #2 0x0000008861c0 in rrc_gNB_process_f1_setup_req /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_du.c:394 #3 0x000000833902 in rrc_gnb_task /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2765 #4 0x7fea71e28ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) Indirect leak of 7 byte(s) in 1 object(s) allocated from: #0 0x7fea71ee6883 in calloc (/lib64/libasan.so.8+0xe6883) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) #1 0x000000ae5c28 in calloc_or_fail /home/richie/w/f1-refactor-ue-context/common/utils/utils.h:74 #2 0x000000ae5c28 in copy_f1ap_served_cell_info /home/richie/w/f1-refactor-ue-context/openair2/F1AP/lib/f1ap_interface_management.c:913 #3 0x000000ae609a in cp_f1ap_setup_request /home/richie/w/f1-refactor-ue-context/openair2/F1AP/lib/f1ap_interface_management.c:957 #4 0x0000008861c0 in rrc_gNB_process_f1_setup_req /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_du.c:394 #5 0x000000833902 in rrc_gnb_task /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2765 #6 0x7fea71e28ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) Indirect leak of 4 byte(s) in 1 object(s) allocated from: #0 0x7fea71ee6f0b in malloc (/lib64/libasan.so.8+0xe6f0b) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) #1 0x000000ae5ae7 in malloc_or_fail /home/richie/w/f1-refactor-ue-context/common/utils/utils.h:86 #2 0x000000ae5ae7 in copy_f1ap_served_cell_info /home/richie/w/f1-refactor-ue-context/openair2/F1AP/lib/f1ap_interface_management.c:907 #3 0x000000ae609a in cp_f1ap_setup_request /home/richie/w/f1-refactor-ue-context/openair2/F1AP/lib/f1ap_interface_management.c:957 #4 0x0000008861c0 in rrc_gNB_process_f1_setup_req /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_du.c:394 #5 0x000000833902 in rrc_gnb_task /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2765 #6 0x7fea71e28ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) Indirect leak of 3 byte(s) in 1 object(s) allocated from: #0 0x7fea71ee6883 in calloc (/lib64/libasan.so.8+0xe6883) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) #1 0x000000adb713 in calloc_or_fail /home/richie/w/f1-refactor-ue-context/common/utils/utils.h:74 #2 0x000000adb713 in copy_f1ap_gnb_du_system_info /home/richie/w/f1-refactor-ue-context/openair2/F1AP/lib/f1ap_interface_management.c:927 #3 0x000000ae60c9 in cp_f1ap_setup_request /home/richie/w/f1-refactor-ue-context/openair2/F1AP/lib/f1ap_interface_management.c:959 #4 0x0000008861c0 in rrc_gNB_process_f1_setup_req /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_du.c:394 #5 0x000000833902 in rrc_gnb_task /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2765 #6 0x7fea71e28ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) --- openair2/RRC/NR/rrc_gNB_du.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/openair2/RRC/NR/rrc_gNB_du.c b/openair2/RRC/NR/rrc_gNB_du.c index 1b4e58489d..868a7fb64a 100644 --- a/openair2/RRC/NR/rrc_gNB_du.c +++ b/openair2/RRC/NR/rrc_gNB_du.c @@ -601,9 +601,12 @@ void rrc_CU_process_f1_lost_connection(gNB_RRC_INST *rrc, f1ap_lost_connection_t ASN_STRUCT_FREE(asn_DEF_NR_MIB, du->mib); ASN_STRUCT_FREE(asn_DEF_NR_SIB1, du->sib1); ASN_STRUCT_FREE(asn_DEF_NR_MeasurementTimingConfiguration, du->mtc); - /* TODO: free setup request */ + if (du->setup_req) + free_f1ap_setup_request(du->setup_req); + free(du->setup_req); nr_rrc_du_container_t *removed = RB_REMOVE(rrc_du_tree, &rrc->dus, du); DevAssert(removed != NULL); + free(du); rrc->num_dus--; int num = invalidate_du_connections(rrc, assoc_id); From ec3ce8a3870c85f84868f10781028715b5890bbc Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 19 Jun 2025 18:20:28 +0200 Subject: [PATCH 137/964] Free at F1 Setup Response at MAC The F1 Setup Response is stored for possible look up of information. Free it at the end to avoid memory leaks. --- openair2/LAYER2/NR_MAC_gNB/main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openair2/LAYER2/NR_MAC_gNB/main.c b/openair2/LAYER2/NR_MAC_gNB/main.c index 0acc6fe0d2..fb932c83a3 100644 --- a/openair2/LAYER2/NR_MAC_gNB/main.c +++ b/openair2/LAYER2/NR_MAC_gNB/main.c @@ -63,6 +63,7 @@ #include "nr_pdcp/nr_pdcp_oai_api.h" #include "nr_rlc/nr_rlc_oai_api.h" #include "openair2/F1AP/f1ap_ids.h" +#include "openair2/F1AP/lib/f1ap_interface_management.h" #include "seq_arr.h" #include "system.h" #include "time_meas.h" @@ -342,6 +343,9 @@ void mac_top_destroy_gNB(gNB_MAC_INST *mac) for (int i = 0; i < sizeofArray(UE_info->access_ue_list); ++i) if (UE_info->access_ue_list[i]) delete_nr_ue_data(UE_info->access_ue_list[i], cc, &UE_info->uid_allocator); + if (mac->f1_config.setup_resp) + free_f1ap_setup_response(mac->f1_config.setup_resp); + free(mac->f1_config.setup_resp); } void nr_mac_send_f1_setup_req(void) From d4ad31bd1de6219fcbd8da4e8d6ac97c9b72cb00 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 19 Jun 2025 18:20:40 +0200 Subject: [PATCH 138/964] Correctly free E1AP context mod request Direct leak of 48 byte(s) in 1 object(s) allocated from: #0 0x7fea71ee6f0b in malloc (/lib64/libasan.so.8+0xe6f0b) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) #1 0x0000007f29c0 in malloc_or_fail /home/richie/w/f1-refactor-ue-context/common/utils/utils.h:86 #2 0x0000007f29c0 in cuup_notify_reestablishment /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:872 #3 0x000000808002 in rrc_CU_process_ue_context_setup_response /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2126 #4 0x0000008330d8 in rrc_gnb_task /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2770 #5 0x7fea71e28ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) --- openair2/RRC/NR/rrc_gNB.c | 1 + 1 file changed, 1 insertion(+) diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 26193b7381..8c04754df7 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -892,6 +892,7 @@ static void cuup_notify_reestablishment(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue_p) /* Send E1 Bearer Context Modification Request (3GPP TS 38.463) */ sctp_assoc_t assoc_id = get_existing_cuup_for_ue(rrc, ue_p); rrc->cucp_cuup.bearer_context_mod(assoc_id, &req); + free_e1ap_context_mod_request(&req); } /** From c54cbdae54ea6f0ba484aa35d2c129be1544664e Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 20 Jun 2025 08:19:08 +0200 Subject: [PATCH 139/964] Fix memory leak in rrc_add_nsa_user_resp() Direct leak of 72 byte(s) in 1 object(s) allocated from: #0 0x7f83c10e6883 in calloc (/lib64/libasan.so.8+0xe6883) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) #1 0x000000844ec5 in rrc_add_nsa_user_resp /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_nsa.c:413 #2 0x0000008079d1 in rrc_CU_process_ue_context_setup_response /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2111 #3 0x0000008330a8 in rrc_gnb_task /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2769 #4 0x7f83c1028ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) Indirect leak of 40 byte(s) in 1 object(s) allocated from: #0 0x7f83c10e6883 in calloc (/lib64/libasan.so.8+0xe6883) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) #1 0x000000844f9d in get_default_reconfig /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_nsa.c:343 #2 0x000000844f9d in rrc_add_nsa_user_resp /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_nsa.c:416 #3 0x0000008079d1 in rrc_CU_process_ue_context_setup_response /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2111 #4 0x0000008330a8 in rrc_gnb_task /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2769 #5 0x7f83c1028ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) Indirect leak of 64 byte(s) in 1 object(s) allocated from: #0 0x7f83c10e6883 in calloc (/lib64/libasan.so.8+0xe6883) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) #1 0x000000844f28 in get_default_reconfig /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_nsa.c:335 #2 0x000000844f28 in rrc_add_nsa_user_resp /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_nsa.c:416 #3 0x0000008079d1 in rrc_CU_process_ue_context_setup_response /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2111 #4 0x0000008330a8 in rrc_gnb_task /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2769 #5 0x7f83c1028ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) Indirect leak of 327 byte(s) in 1 object(s) allocated from: #0 0x7f83c10e6f0b in malloc (/lib64/libasan.so.8+0xe6f0b) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) #1 0x000000fb51ec in OCTET_STRING_fromBuf /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/OCTET_STRING.c:184 #2 0x000000844fd3 in get_default_reconfig /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_nsa.c:344 #3 0x000000844fd3 in rrc_add_nsa_user_resp /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_nsa.c:416 #4 0x0000008079d1 in rrc_CU_process_ue_context_setup_response /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2111 #5 0x0000008330a8 in rrc_gnb_task /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2769 #6 0x7f83c1028ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) --- openair2/RRC/NR/rrc_gNB_nsa.c | 1 + 1 file changed, 1 insertion(+) diff --git a/openair2/RRC/NR/rrc_gNB_nsa.c b/openair2/RRC/NR/rrc_gNB_nsa.c index d722236ce8..cd7b5fb8d4 100644 --- a/openair2/RRC/NR/rrc_gNB_nsa.c +++ b/openair2/RRC/NR/rrc_gNB_nsa.c @@ -416,6 +416,7 @@ void rrc_add_nsa_user_resp(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const f1ap_ue_co reconfig->criticalExtensions.choice.rrcReconfiguration = get_default_reconfig(UE->masterCellGroup); NR_CG_Config_t *CG_Config = generate_CG_Config(reconfig, UE->rb_config); + ASN_STRUCT_FREE(asn_DEF_NR_RRCReconfiguration, reconfig); if (get_softmodem_params()->phy_test > 0 || get_softmodem_params()->do_ra > 0) { /* we are done, no X2 answer necessary */ From c3bb7dfd0484a1375830b083669f487464c031a4 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 20 Jun 2025 08:21:19 +0200 Subject: [PATCH 140/964] Fix memory leak in ue_context_setup_request() Direct leak of 64 byte(s) in 1 object(s) allocated from: #0 0x7fc885ae6883 in calloc (/lib64/libasan.so.8+0xe6883) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) #1 0x000000fd0ac9 in SEQUENCE_decode_uper /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE_uper.c:37 #2 0x000000fbba1c in uper_decode /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/uper_decoder.c:83 #3 0x000000fbbbf9 in uper_decode_complete /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/uper_decoder.c:16 #4 0x0000009d65ce in get_cg_config_info /home/richie/w/f1-refactor-ue-context/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c:485 #5 0x0000009d65ce in ue_context_setup_request /home/richie/w/f1-refactor-ue-context/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c:619 #6 0x00000083fea2 in rrc_add_nsa_user /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_nsa.c:330 #7 0x000000886c8b in rrc_gNB_process_f1_setup_req /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_du.c:444 #8 0x000000833902 in rrc_gnb_task /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2766 #9 0x7fc885a28ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) Indirect leak of 128 byte(s) in 1 object(s) allocated from: #0 0x7fc885ae6883 in calloc (/lib64/libasan.so.8+0xe6883) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) #1 0x000000fd0ac9 in SEQUENCE_decode_uper /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE_uper.c:37 #2 0x000000fca638 in CHOICE_decode_uper /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_CHOICE_uper.c:84 #3 0x000000fca638 in CHOICE_decode_uper /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_CHOICE_uper.c:84 #4 0x000000fd058e in SEQUENCE_decode_uper /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE_uper.c:118 #5 0x000000fbba1c in uper_decode /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/uper_decoder.c:83 #6 0x000000fbbbf9 in uper_decode_complete /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/uper_decoder.c:16 #7 0x0000009d65ce in get_cg_config_info /home/richie/w/f1-refactor-ue-context/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c:485 #8 0x0000009d65ce in ue_context_setup_request /home/richie/w/f1-refactor-ue-context/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c:619 #9 0x00000083fea2 in rrc_add_nsa_user /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_nsa.c:330 #10 0x000000886c8b in rrc_gNB_process_f1_setup_req /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_du.c:444 #11 0x000000833902 in rrc_gnb_task /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2766 #12 0x7fc885a28ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) Indirect leak of 40 byte(s) in 1 object(s) allocated from: #0 0x7fc885ae6883 in calloc (/lib64/libasan.so.8+0xe6883) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) #1 0x000000fca7d7 in CHOICE_decode_uper /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_CHOICE_uper.c:32 #2 0x000000fca638 in CHOICE_decode_uper /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_CHOICE_uper.c:84 #3 0x000000fd058e in SEQUENCE_decode_uper /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE_uper.c:118 #4 0x000000fbba1c in uper_decode /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/uper_decoder.c:83 #5 0x000000fbbbf9 in uper_decode_complete /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/uper_decoder.c:16 #6 0x0000009d65ce in get_cg_config_info /home/richie/w/f1-refactor-ue-context/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c:485 #7 0x0000009d65ce in ue_context_setup_request /home/richie/w/f1-refactor-ue-context/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c:619 #8 0x00000083fea2 in rrc_add_nsa_user /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_nsa.c:330 #9 0x000000886c8b in rrc_gNB_process_f1_setup_req /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_du.c:444 #10 0x000000833902 in rrc_gnb_task /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2766 #11 0x7fc885a28ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) --- openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c | 1 + 1 file changed, 1 insertion(+) diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c index 3b5fd80639..9c6559ad10 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -702,6 +702,7 @@ void ue_context_setup_request(const f1ap_ue_context_setup_req_t *req) /* free the memory we allocated above */ free_ue_context_setup_resp(&resp); + ASN_STRUCT_FREE(asn_DEF_NR_CG_ConfigInfo, cg_configinfo); } void ue_context_modification_request(const f1ap_ue_context_mod_req_t *req) From f26cef9cbe18838f3db70344992cb737479c7943 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 20 Jun 2025 09:37:10 +0200 Subject: [PATCH 141/964] Add invariant check to help debug During refactoring, I had asan errors in the next line. It took me some time to figure out that a DRB ID 0 is not valid (cf. get_next_available_drb_id() and get_drb(), they enforce this). --- openair2/RRC/NR/rrc_gNB_radio_bearers.c | 1 + 1 file changed, 1 insertion(+) diff --git a/openair2/RRC/NR/rrc_gNB_radio_bearers.c b/openair2/RRC/NR/rrc_gNB_radio_bearers.c index 7bed45ee64..5112029f87 100644 --- a/openair2/RRC/NR/rrc_gNB_radio_bearers.c +++ b/openair2/RRC/NR/rrc_gNB_radio_bearers.c @@ -58,6 +58,7 @@ rrc_pdu_session_param_t *find_pduSession(gNB_RRC_UE_t *ue, int id, bool create) rrc_pdu_session_param_t *find_pduSession_from_drbId(gNB_RRC_UE_t *ue, int drb_id) { + DevAssert(drb_id > 0 && drb_id <= 32); const drb_t *drb = &ue->established_drbs[drb_id - 1]; if (drb->status == DRB_INACTIVE) { LOG_E(NR_RRC, "UE %d: DRB %d inactive\n", ue->rrc_ue_id, drb_id); From 6cf7fc2bb26a7d1ed1803c69b17cd312239a1ae4 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 20 Jun 2025 09:50:25 +0200 Subject: [PATCH 142/964] Fix memory leak in nr_rrc_f1_ho_acknowledge() Direct leak of 512 byte(s) in 1 object(s) allocated from: #0 0x7f37634e5e2b in realloc.part.0 (/lib64/libasan.so.8+0xe5e2b) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) #1 0x000000fbb9ad in encode_dyn_cb /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/per_encoder.c:23 #2 0x000000fc279e in asn_put_few_bits /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/asn_bit_data.c:220 #3 0x000000fc279e in asn_put_few_bits /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/asn_bit_data.c:192 #4 0x000000fc2ce5 in asn_put_many_bits /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/asn_bit_data.c:293 #5 0x000000fb8c33 in OCTET_STRING_encode_uper /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/OCTET_STRING_uper.c:306 #6 0x000000fd191a in SEQUENCE_encode_uper /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE_uper.c:403 #7 0x000000fd191a in SEQUENCE_encode_uper /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE_uper.c:403 #8 0x000000fcb140 in CHOICE_encode_uper /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_CHOICE_uper.c:177 #9 0x000000fd191a in SEQUENCE_encode_uper /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE_uper.c:403 #10 0x000000fcb140 in CHOICE_encode_uper /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_CHOICE_uper.c:177 #11 0x000000fcb140 in CHOICE_encode_uper /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_CHOICE_uper.c:177 #12 0x000000fd191a in SEQUENCE_encode_uper /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE_uper.c:403 #13 0x000000fbc1ed in uper_encode /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/uper_encoder.c:27 #14 0x000000fbc73a in uper_encode_to_new_buffer /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/uper_encoder.c:85 #15 0x000000e10fbd in do_RRCReconfiguration /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/MESSAGES/asn1_msg.c:586 #16 0x000000805712 in rrc_gNB_encode_RRCReconfiguration /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:652 #17 0x000000893860 in nr_rrc_f1_ho_acknowledge /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_mobility.c:280 #18 0x0000008079ac in rrc_CU_process_ue_context_setup_response /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2139 #19 0x0000008330d8 in rrc_gnb_task /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2771 #20 0x7f3763428ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) --- openair2/RRC/NR/rrc_gNB_mobility.c | 1 + 1 file changed, 1 insertion(+) diff --git a/openair2/RRC/NR/rrc_gNB_mobility.c b/openair2/RRC/NR/rrc_gNB_mobility.c index 7312e2f631..85c9597371 100644 --- a/openair2/RRC/NR/rrc_gNB_mobility.c +++ b/openair2/RRC/NR/rrc_gNB_mobility.c @@ -285,6 +285,7 @@ static void nr_rrc_f1_ho_acknowledge(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE) DevAssert(UE->ho_context->source != NULL); rrc_gNB_trigger_reconfiguration_for_handover(rrc, UE, buffer.buf, buffer.len); LOG_A(NR_RRC, "HO acknowledged: Send reconfiguration for UE %u/RNTI %04x...\n", UE->rrc_ue_id, UE->rnti); + free_byte_array(buffer); /* Re-establish SRB2 according to clause 5.3.5.6.3 of 3GPP TS 38.331 * (SRB1 is re-established with RRCReestablishment message) From bd5380ed097f0ebed0c9d2df16d42d697a23b9ba Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 20 Jun 2025 14:14:12 +0200 Subject: [PATCH 143/964] Make UE capabilities const: is read-only --- openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c | 2 +- openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c index 41ace5014b..004e08d3be 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c @@ -3524,7 +3524,7 @@ NR_CellGroupConfig_t *get_initial_cellGroupConfig(int uid, void update_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig, const int uid, - NR_UE_NR_Capability_t *uecap, + const NR_UE_NR_Capability_t *uecap, const nr_mac_config_t *configuration, const NR_ServingCellConfigCommon_t *scc) { diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h index cdb4f5b792..bdf56a3310 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h @@ -89,7 +89,7 @@ NR_CellGroupConfig_t *get_initial_cellGroupConfig(int uid, const nr_rlc_configuration_t *default_rlc_config); void update_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig, const int uid, - NR_UE_NR_Capability_t *uecap, + const NR_UE_NR_Capability_t *uecap, const nr_mac_config_t *configuration, const NR_ServingCellConfigCommon_t *scc); void free_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig); From 5766d7ff5110b7280b7ecd4c9d99526afa7c77d6 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 20 Jun 2025 16:10:44 +0200 Subject: [PATCH 144/964] Debug core images: mount sources to right directory --- docker/debug_core_image.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/debug_core_image.sh b/docker/debug_core_image.sh index 3b2fc5db0a..307bd90bc5 100755 --- a/docker/debug_core_image.sh +++ b/docker/debug_core_image.sh @@ -54,7 +54,7 @@ fi # the source directory to show correct line numbers docker run --rm -it \ -v $COREDUMP:/tmp/coredump \ - -v $SOURCES:/opt/$TYPEPATH/src \ + -v $SOURCES:/oai-ran/ \ --entrypoint bash \ $IMAGE \ -c "gdb --dir=src/cmake_targets/ran_build/build $EXEC /tmp/coredump" From e33711cffa2f97567823731d75995c2547155c72 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 20 Jun 2025 18:55:30 +0200 Subject: [PATCH 145/964] Allocate twice to avoid double free We use the same resource for CSI meas report and RSRP (judging by the name of the functions), but the memory allocations need to be separate to avoid a double free: ==2063066==ERROR: AddressSanitizer: heap-use-after-free on address 0x7c27d43e3ce8 at pc 0x000000fcd279 bp 0x7be7cc9e7120 sp 0x7be7cc9e7118 READ of size 8 at 0x7c27d43e3ce8 thread T6 #0 0x000000fcd278 in SEQUENCE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE.c:97 #1 0x000000fcd278 in SEQUENCE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE.c:69 #2 0x000000fd6249 in SET_OF_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SET_OF.c:236 #3 0x000000fd6249 in SET_OF_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SET_OF.c:220 #4 0x000000fcd103 in SEQUENCE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE.c:91 #5 0x000000fcd103 in SEQUENCE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE.c:69 #6 0x000000fc90c9 in CHOICE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_CHOICE.c:185 #7 0x000000fc90c9 in CHOICE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_CHOICE.c:158 #8 0x000000fcd103 in SEQUENCE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE.c:91 #9 0x000000fcd103 in SEQUENCE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE.c:69 #10 0x000000fd6249 in SET_OF_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SET_OF.c:236 #11 0x000000fd6249 in SET_OF_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SET_OF.c:220 #12 0x000000fcd01a in SEQUENCE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE.c:88 #13 0x000000fcd01a in SEQUENCE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE.c:69 #14 0x000000fc90c9 in CHOICE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_CHOICE.c:185 #15 0x000000fc90c9 in CHOICE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_CHOICE.c:158 #16 0x000000fcd01a in SEQUENCE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE.c:88 #17 0x000000fcd01a in SEQUENCE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE.c:69 #18 0x000000fcd01a in SEQUENCE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE.c:88 #19 0x000000fcd01a in SEQUENCE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE.c:69 #20 0x000000fcd01a in SEQUENCE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE.c:88 #21 0x000000fcd01a in SEQUENCE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE.c:69 #22 0x0000009d78ae in ue_context_setup_request /home/richie/w/f1-refactor-ue-context/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c:692 #23 0x00000083fee2 in rrc_add_nsa_user /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_nsa.c:330 #24 0x000000886e8b in rrc_gNB_process_f1_setup_req /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_du.c:444 #25 0x000000833942 in rrc_gnb_task /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2766 #26 0x7fe7d5e28ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) #27 0x7fe7d527f1d3 in start_thread (/lib64/libc.so.6+0x711d3) (BuildId: 2b3c02fe7e4d3811767175b6f323692a10a4e116) #28 0x7fe7d5301ceb in __GI___clone3 (/lib64/libc.so.6+0xf3ceb) (BuildId: 2b3c02fe7e4d3811767175b6f323692a10a4e116) 0x7c27d43e3ce8 is located 24 bytes inside of 40-byte region [0x7c27d43e3cd0,0x7c27d43e3cf8) freed by thread T6 here: #0 0x7fe7d5ee5bcb in free.part.0 (/lib64/libasan.so.8+0xe5bcb) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) #1 0x000000fd6249 in SET_OF_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SET_OF.c:236 #2 0x000000fd6249 in SET_OF_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SET_OF.c:220 #3 0x000000fcd103 in SEQUENCE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE.c:91 #4 0x000000fcd103 in SEQUENCE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE.c:69 #5 0x000000fc90c9 in CHOICE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_CHOICE.c:185 #6 0x000000fc90c9 in CHOICE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_CHOICE.c:158 #7 0x000000fcd103 in SEQUENCE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE.c:91 #8 0x000000fcd103 in SEQUENCE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE.c:69 #9 0x000000fd6249 in SET_OF_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SET_OF.c:236 #10 0x000000fd6249 in SET_OF_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SET_OF.c:220 #11 0x000000fcd01a in SEQUENCE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE.c:88 #12 0x000000fcd01a in SEQUENCE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE.c:69 #13 0x000000fc90c9 in CHOICE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_CHOICE.c:185 #14 0x000000fc90c9 in CHOICE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_CHOICE.c:158 #15 0x000000fcd01a in SEQUENCE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE.c:88 #16 0x000000fcd01a in SEQUENCE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE.c:69 #17 0x000000fcd01a in SEQUENCE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE.c:88 #18 0x000000fcd01a in SEQUENCE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE.c:69 #19 0x000000fcd01a in SEQUENCE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE.c:88 #20 0x000000fcd01a in SEQUENCE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE.c:69 #21 0x0000009d78ae in ue_context_setup_request /home/richie/w/f1-refactor-ue-context/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c:692 #22 0x00000083fee2 in rrc_add_nsa_user /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_nsa.c:330 #23 0x000000886e8b in rrc_gNB_process_f1_setup_req /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_du.c:444 #24 0x000000833942 in rrc_gnb_task /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2766 #25 0x7fe7d5e28ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) previously allocated by thread T6 here: #0 0x7fe7d5ee6883 in calloc (/lib64/libasan.so.8+0xe6883) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) #1 0x000000a1ac53 in get_default_secondaryCellGroup /home/richie/w/f1-refactor-ue-context/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c:3969 #2 0x0000009d8913 in create_new_UE /home/richie/w/f1-refactor-ue-context/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c:571 #3 0x0000009d8913 in ue_context_setup_request /home/richie/w/f1-refactor-ue-context/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c:638 #4 0x00000083fee2 in rrc_add_nsa_user /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_nsa.c:330 #5 0x000000886e8b in rrc_gNB_process_f1_setup_req /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_du.c:444 #6 0x000000833942 in rrc_gnb_task /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2766 #7 0x7fe7d5e28ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) Thread T6 created by T0 here: #0 0x7fe7d5ede492 in pthread_create (/lib64/libasan.so.8+0xde492) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) #1 0x0000012a4ba3 in threadCreate /home/richie/w/f1-refactor-ue-context/common/utils/system.c:283 #2 0x0000006b5fef in itti_create_task /home/richie/w/f1-refactor-ue-context/common/utils/ocp_itti/intertask_interface.cpp:317 #3 0x000000435c5f in create_gNB_tasks /home/richie/w/f1-refactor-ue-context/executables/nr-softmodem.c:310 #4 0x000000435c5f in main /home/richie/w/f1-refactor-ue-context/executables/nr-softmodem.c:620 #5 0x7fe7d52115f4 in __libc_start_call_main (/lib64/libc.so.6+0x35f4) (BuildId: 2b3c02fe7e4d3811767175b6f323692a10a4e116) #6 0x7fe7d52116a7 in __libc_start_main@@GLIBC_2.34 (/lib64/libc.so.6+0x36a7) (BuildId: 2b3c02fe7e4d3811767175b6f323692a10a4e116) #7 0x0000004672d4 in _start (/home/richie/w/f1-refactor-ue-context/build/nr-softmodem+0x4672d4) (BuildId: 81450e9a0b832ca9e36b1984ecc232efde59d424) Closes: #958 --- openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c index 004e08d3be..4246cc65aa 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c @@ -3969,7 +3969,6 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC NR_PUCCH_CSI_Resource_t *pucchcsires1 = calloc(1, sizeof(*pucchcsires1)); pucchcsires1->uplinkBandwidthPartId = bwp->bwp_Id; pucchcsires1->pucch_Resource = 2; - config_csi_meas_report(csi_MeasConfig, servingcellconfigcommon, pucchcsires1, @@ -3979,9 +3978,14 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC bwp->bwp_Id, uid, curr_bwp); + // this is the same resource as pucchcsires1, but duplicated to avoid + // double free when releasing the CellGroupConfig + NR_PUCCH_CSI_Resource_t *pucchcsires2 = calloc(1, sizeof(*pucchcsires2)); + pucchcsires2->uplinkBandwidthPartId = bwp->bwp_Id; + pucchcsires2->pucch_Resource = 2; config_rsrp_meas_report(csi_MeasConfig, servingcellconfigcommon, - pucchcsires1, + pucchcsires2, do_csirs, bwp->bwp_Id + 10, uid, From 43e87b669dc76ad17c42339c1f1f7fe9448f40d3 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 26 Jun 2025 13:38:29 +0200 Subject: [PATCH 146/964] cg_config_info_from_ue_cap_file(): avoid potential memory leaks Avoid potential memory leaks by first reading UE capabilities file (if present), and allocating only after the file read was successful. --- openair2/RRC/NR/rrc_gNB_nsa.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/openair2/RRC/NR/rrc_gNB_nsa.c b/openair2/RRC/NR/rrc_gNB_nsa.c index cd7b5fb8d4..d0cc63062b 100644 --- a/openair2/RRC/NR/rrc_gNB_nsa.c +++ b/openair2/RRC/NR/rrc_gNB_nsa.c @@ -77,13 +77,7 @@ // and put it into a CG-ConfigInfo field static int cg_config_info_from_ue_cap_file(uint32_t maxlen, uint8_t buf[maxlen]) { - NR_CG_ConfigInfo_t *cgci = calloc_or_fail(1, sizeof(*cgci)); - cgci->criticalExtensions.present = NR_CG_ConfigInfo__criticalExtensions_PR_c1; - cgci->criticalExtensions.choice.c1 = calloc_or_fail(1, sizeof(*cgci->criticalExtensions.choice.c1)); - cgci->criticalExtensions.choice.c1->present = NR_CG_ConfigInfo__criticalExtensions__c1_PR_cg_ConfigInfo; - NR_CG_ConfigInfo_IEs_t *cgci_ies = calloc_or_fail(1, sizeof(*cgci_ies)); - cgci->criticalExtensions.choice.c1->choice.cg_ConfigInfo = cgci_ies; - + OCTET_STRING_t *os_cap = NULL; if (uecap_file != NULL) { LOG_I(NR_RRC, "creating CG-ConfigInfo from UE capability file %s\n", uecap_file); @@ -104,11 +98,18 @@ static int cg_config_info_from_ue_cap_file(uint32_t maxlen, uint8_t buf[maxlen]) DevAssert(dec_rval.code == RC_OK); //xer_fprint(stdout, &asn_DEF_NR_UE_NR_Capability, cap); - OCTET_STRING_t *os_cap = calloc_or_fail(1, sizeof(*os_cap)); + os_cap = calloc_or_fail(1, sizeof(*os_cap)); os_cap->size = uper_encode_to_new_buffer(&asn_DEF_NR_UE_NR_Capability, NULL, cap, (void **)&os_cap->buf); - cgci_ies->ue_CapabilityInfo = os_cap; } + NR_CG_ConfigInfo_t *cgci = calloc_or_fail(1, sizeof(*cgci)); + cgci->criticalExtensions.present = NR_CG_ConfigInfo__criticalExtensions_PR_c1; + cgci->criticalExtensions.choice.c1 = calloc_or_fail(1, sizeof(*cgci->criticalExtensions.choice.c1)); + cgci->criticalExtensions.choice.c1->present = NR_CG_ConfigInfo__criticalExtensions__c1_PR_cg_ConfigInfo; + NR_CG_ConfigInfo_IEs_t *cgci_ies = calloc_or_fail(1, sizeof(*cgci_ies)); + cgci->criticalExtensions.choice.c1->choice.cg_ConfigInfo = cgci_ies; + cgci_ies->ue_CapabilityInfo = os_cap; + //xer_fprint(stdout, &asn_DEF_NR_CG_ConfigInfo, cgci); asn_enc_rval_t rval = uper_encode_to_buffer(&asn_DEF_NR_CG_ConfigInfo, NULL, cgci, buf, maxlen); DevAssert(rval.encoded > 0); From 98e6d60337ee8699149f686d7cfb4c3f0724bb83 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Tue, 27 May 2025 15:21:34 +0200 Subject: [PATCH 147/964] RF simulator: Fix concurrency issues during new client connections Fix concurrency issues happening when a new client connects, sometimes leading to a total softmodem deadlock. Key changes: - Fix sample sending on new client connection: send the first sample only to the newly connected client. - Remove the --rfsimulator.hanging-workaround option - Replace global nb_ue and Sockmutex with nb_cnx and Sockmutex in rfsimulator_state_t for better concurrency and clarity. --- .../5g_f1_rfsimulator/docker-compose.yaml | 1 - radio/rfsimulator/README.md | 1 - radio/rfsimulator/simulator.c | 135 +++++++----------- 3 files changed, 53 insertions(+), 84 deletions(-) diff --git a/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml b/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml index fb1d5a95ce..6dd2dec52a 100644 --- a/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml @@ -179,7 +179,6 @@ services: --uicc0.imsi 208990100001100 --rfsimulator.options chanmod --rfsimulator.serveraddr server - --rfsimulator.hanging-workaround 1 --telnetsrv --telnetsrv.shrmod ciUE --telnetsrv.listenaddr 192.168.71.181 --telnetsrv.listenport 8091 --channelmod.modellist_rfsimu_1.[0].model_name rfsimu_channel_ue0 --channelmod.modellist_rfsimu_1.[1].model_name rfsimu_channel_ue1 diff --git a/radio/rfsimulator/README.md b/radio/rfsimulator/README.md index ae46034cec..40688b755a 100644 --- a/radio/rfsimulator/README.md +++ b/radio/rfsimulator/README.md @@ -79,7 +79,6 @@ The RF simulator is using the configuration module, and its parameters are defin |`--rfsimulator.IQfile ` | path to a file to store the IQ samples to (only with `saviq`) | `/tmp/rfsimulator.iqs` | |`--rfsimulator.prop_delay` | simulated receive-path (gNB: UL, UE: DL) propagation delay in ms | 0 | |`--rfsimulator.wait_timeout` | wait timeout when no UE is connected | 1 | -|`--rfismulator.hanging-workaround`| Enable workaround to de-block potentially hanging server on new client connection. | 0 | Please refer to this document [`SIMULATION/TOOLS/DOC/channel_simulation.md`](../../openair1/SIMULATION/TOOLS/DOC/channel_simulation.md) for information about using the RFSimulator options to run the simulator with a channel model. diff --git a/radio/rfsimulator/simulator.c b/radio/rfsimulator/simulator.c index 32648758c8..1cfc7dd7cc 100644 --- a/radio/rfsimulator/simulator.c +++ b/radio/rfsimulator/simulator.c @@ -80,31 +80,30 @@ typedef enum { SIMU_ROLE_SERVER = 1, SIMU_ROLE_CLIENT } simuRole; #define RFSIMU_SECTION "rfsimulator" #define RFSIMU_OPTIONS_PARAMNAME "options" - -#define RFSIM_CONFIG_HELP_OPTIONS " list of comma separated options to enable rf simulator functionalities. Available options: \n"\ - " chanmod: enable channel modelisation\n"\ +#define RFSIM_CONFIG_HELP_OPTIONS \ + " list of comma separated options to enable rf simulator functionalities. Available options: \n" \ + " chanmod: enable channel modelisation\n" \ " saviq: enable saving written iqs to a file\n" -#define CONFIG_HELP_HANG_WORKAROUND "Enable workaroud for server mode hanging on new client connection.\n" /*-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ /* configuration parameters for the rfsimulator device */ /* optname helpstr paramflags XXXptr defXXXval type numelt */ /*-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ #define simOpt PARAMFLAG_NOFREE|PARAMFLAG_CMDLINE_NOPREFIXENABLED +// clang-format off #define RFSIMULATOR_PARAMS_DESC { \ {"serveraddr", "\n", simOpt, .strptr=&rfsimulator->ip, .defstrval="127.0.0.1", TYPE_STRING, 0 },\ - {"serverport", "\n", simOpt, .u16ptr=&(rfsimulator->port), .defuintval=PORT, TYPE_UINT16, 0 },\ - {RFSIMU_OPTIONS_PARAMNAME, RFSIM_CONFIG_HELP_OPTIONS, 0, .strlistptr=NULL, .defstrlistval=NULL, TYPE_STRINGLIST,0 },\ + {"serverport", "\n", simOpt, .u16ptr = &(rfsimulator->port), .defuintval = PORT, TYPE_UINT16, 0}, \ + {RFSIMU_OPTIONS_PARAMNAME, RFSIM_CONFIG_HELP_OPTIONS, 0, .strlistptr = NULL, .defstrlistval = NULL, TYPE_STRINGLIST, 0}, \ {"IQfile", "\n",simOpt, .strptr=&saveF, .defstrval="/tmp/rfsimulator.iqs",TYPE_STRING, 0 },\ - {"modelname", "\n", simOpt, .strptr=&modelname, .defstrval="AWGN", TYPE_STRING, 0 },\ - {"ploss", "\n", simOpt, .dblptr=&(rfsimulator->chan_pathloss), .defdblval=0, TYPE_DOUBLE, 0 },\ + {"modelname", "\n", simOpt, .strptr = &modelname, .defstrval = "AWGN", TYPE_STRING, 0}, \ + {"ploss", "\n", simOpt, .dblptr = &(rfsimulator->chan_pathloss), .defdblval = 0, TYPE_DOUBLE, 0}, \ {"forgetfact", "\n", simOpt, .dblptr=&(rfsimulator->chan_forgetfact),.defdblval=0, TYPE_DOUBLE, 0 },\ - {"offset", "\n", simOpt, .u64ptr=&(rfsimulator->chan_offset), .defint64val=0, TYPE_UINT64, 0 },\ + {"offset", "\n", simOpt, .u64ptr = &(rfsimulator->chan_offset), .defint64val = 0, TYPE_UINT64, 0}, \ {"prop_delay", "\n", simOpt, .dblptr=&(rfsimulator->prop_delay_ms), .defdblval=0.0, TYPE_DOUBLE, 0 },\ {"wait_timeout", "\n", simOpt, .iptr=&(rfsimulator->wait_timeout), .defintval=1, TYPE_INT, 0 },\ - {"hanging-workaround", CONFIG_HELP_HANG_WORKAROUND, simOpt, .iptr=&rfsimulator->hanging_workaround, .defintval=0, TYPE_INT, 0 },\ }; - +// clang-format on static void getset_currentchannels_type(char *buf, int debug, webdatadef_t *tdata, telnet_printfunc_t prnt); extern int get_currentchannels_type(char *buf, int debug, webdatadef_t *tdata, telnet_printfunc_t prnt); // in random_channel.c static int rfsimu_setchanmod_cmd(char *buff, int debug, telnet_printfunc_t prnt, void *arg); @@ -122,11 +121,7 @@ static telnetshell_cmddef_t rfsimu_cmdarray[] = { static telnetshell_cmddef_t *setmodel_cmddef = &(rfsimu_cmdarray[1]); static telnetshell_vardef_t rfsimu_vardef[] = {{"", 0, 0, NULL}}; -pthread_mutex_t Sockmutex; -unsigned int nb_ue = 0; - static uint64_t CirSize = minCirSize; - typedef c16_t sample_t; // 2*16 bits complex number typedef struct buffer_s { @@ -144,6 +139,8 @@ typedef struct buffer_s { typedef struct { int listen_sock, epollfd; + pthread_mutex_t Sockmutex; + unsigned int nb_cnx; openair0_timestamp nextRxTstamp; openair0_timestamp lastWroteTS; simuRole role; @@ -165,7 +162,6 @@ typedef struct { poll_telnetcmdq_func_t poll_telnetcmdq; int wait_timeout; double prop_delay_ms; - int hanging_workaround; } rfsimulator_state_t; static buffer_t *allocCirBuf(rfsimulator_state_t *bridge, int sock) @@ -214,7 +210,11 @@ static buffer_t *allocCirBuf(rfsimulator_state_t *bridge, int sock) init_done=true; } char modelname[30]; - snprintf(modelname, sizeofArray(modelname), "rfsimu_channel_%s%d", (bridge->role == SIMU_ROLE_SERVER) ? "ue" : "enB", nb_ue); + snprintf(modelname, + sizeofArray(modelname), + "rfsimu_channel_%s%d", + (bridge->role == SIMU_ROLE_SERVER) ? "ue" : "enB", + bridge->nb_cnx); ptr->channel_model = find_channel_desc_fromname(modelname); // path_loss in dB if (!ptr->channel_model) { // Use legacy method to find channel model - this will use the same channel model for all clients @@ -246,7 +246,7 @@ static void removeCirBuf(rfsimulator_state_t *bridge, buffer_t *buf) // free(bridge->buf[sock].channel_model); memset(buf, 0, sizeof(buffer_t)); buf->conn_sock = -1; - nb_ue--; + bridge->nb_cnx--; } static void socketError(rfsimulator_state_t *bridge, buffer_t *buf) @@ -286,8 +286,6 @@ static int setblocking(int sock, enum blocking_t active) return 0; } -static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps); - static void fullwrite(int fd, void *_buf, ssize_t count, rfsimulator_state_t *t) { if (t->saveIQfile != -1) { if (write(t->saveIQfile, _buf, count) != count ) @@ -450,25 +448,6 @@ static void getset_currentchannels_type(char *buf, int debug, webdatadef_t *tdat get_currentchannels_type("modify type", debug, tdata, prnt); } } -/*getset_currentchannels_type */ - -//static void print_cirBuf(struct complex16 *circularBuf, -// uint64_t firstSample, -// uint32_t cirSize, -// int neg, -// int pos, -// int nbTx) -//{ -// for (int i = -neg; i < pos ; ++i) { -// for (int txAnt = 0; txAnt < nbTx; txAnt++) { -// const int idx = ((firstSample + i) * nbTx + txAnt + cirSize) % cirSize; -// if (i == 0) -// printf("->"); -// printf("%08x%08x\n", circularBuf[idx].r, circularBuf[idx].i); -// } -// } -// printf("\n"); -//} static int rfsimu_setdistance_cmd(char *buff, int debug, telnet_printfunc_t prnt, void *arg) { @@ -681,10 +660,14 @@ static int startClient(openair0_device *device) return allocCirBuf(t, sock) == NULL ? -1 : 0; } -static int rfsimulator_write_internal(rfsimulator_state_t *t, openair0_timestamp timestamp, void **samplesVoid, int nsamps, int nbAnt, int flags, bool alreadyLocked) { - if (!alreadyLocked) - pthread_mutex_lock(&Sockmutex); - +static int rfsimulator_write_internal(rfsimulator_state_t *t, + openair0_timestamp timestamp, + void **samplesVoid, + int nsamps, + int nbAnt, + int flags) +{ + mutexlock(t->Sockmutex); LOG_D(HW, "Sending %d samples at time: %ld, nbAnt %d\n", nsamps, timestamp, nbAnt); for (int i = 0; i < MAX_FD_RFSIMU; i++) { @@ -692,24 +675,17 @@ static int rfsimulator_write_internal(rfsimulator_state_t *t, openair0_timestamp if (b->conn_sock >= 0 ) { samplesBlockHeader_t header = {nsamps, nbAnt, timestamp}; - fullwrite(b->conn_sock,&header, sizeof(header), t); - sample_t tmpSamples[nsamps][nbAnt]; - + fullwrite(b->conn_sock, &header, sizeof(header), t); if (nbAnt == 1) { - if (b->conn_sock >= 0) { - fullwrite(b->conn_sock, samplesVoid[0], sampleToByte(nsamps, nbAnt), t); - } + fullwrite(b->conn_sock, samplesVoid[0], sampleToByte(nsamps, nbAnt), t); } else { + sample_t tmpSamples[nsamps][nbAnt]; for (int a = 0; a < nbAnt; a++) { sample_t *in = (sample_t *)samplesVoid[a]; - for (int s = 0; s < nsamps; s++) tmpSamples[s][a] = in[s]; } - - if (b->conn_sock >= 0) { - fullwrite(b->conn_sock, (void *)tmpSamples, sampleToByte(nsamps, nbAnt), t); - } + fullwrite(b->conn_sock, (void *)tmpSamples, sampleToByte(nsamps, nbAnt), t); } } } @@ -727,10 +703,8 @@ static int rfsimulator_write_internal(rfsimulator_state_t *t, openair0_timestamp timestamp, timestamp - t->lastWroteTS); - t->lastWroteTS=timestamp+nsamps; - - if (!alreadyLocked) - pthread_mutex_unlock(&Sockmutex); + t->lastWroteTS = timestamp + nsamps; + mutexunlock(t->Sockmutex); LOG_D(HW, "Sent %d samples at time: %ld->%ld, energy in first antenna: %d\n", @@ -743,8 +717,7 @@ static int rfsimulator_write_internal(rfsimulator_state_t *t, openair0_timestamp static int rfsimulator_write(openair0_device *device, openair0_timestamp timestamp, void **samplesVoid, int nsamps, int nbAnt, int flags) { timestamp -= device->openair0_cfg->command_line_sample_advance; - return rfsimulator_write_internal(device->priv, timestamp, samplesVoid, nsamps, nbAnt, flags, false); // false = with lock - // return rfsimulator_write_internal(device->priv, timestamp, samplesVoid, nsamps, nbAnt, flags, true); + return rfsimulator_write_internal(device->priv, timestamp, samplesVoid, nsamps, nbAnt, flags); } static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps_for_initial) { @@ -766,8 +739,9 @@ static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps_for_initi buffer_t *b = events[nbEv].data.ptr; if (events[nbEv].events & EPOLLIN && b == NULL) { - int conn_sock; - conn_sock = accept(t->listen_sock, NULL, NULL); + struct sockaddr_storage sa = {0}; + socklen_t socklen = sizeof(sa); + int conn_sock = accept(t->listen_sock, (struct sockaddr *)&sa, &socklen); if (conn_sock == -1) { LOG_E(HW, "accept() failed, errno(%d)\n", errno); return false; @@ -775,22 +749,28 @@ static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps_for_initi if (setblocking(conn_sock, notBlocking)) { return false; } + mutexlock(t->Sockmutex); buffer_t *new_buf = allocCirBuf(t, conn_sock); if (new_buf == NULL) { + mutexunlock(t->Sockmutex); return false; } - LOG_I(HW, "A client connects, sending the current time\n"); - c16_t v= {0}; - nb_ue++; + t->nb_cnx++; + char ip[INET6_ADDRSTRLEN]; + getnameinfo((struct sockaddr*)&sa, socklen, ip, sizeof(ip), NULL, 0, NI_NUMERICHOST); + uint16_t port = ((struct sockaddr_in *)&sa)->sin_port; + LOG_I(HW, "Client connects from %s:%d\n", ip, port); + c16_t v = {0}; void *samplesVoid[t->tx_num_channels]; - for ( int i=0; i < t->tx_num_channels; i++) - samplesVoid[i]=(void *)&v; - - rfsimulator_write_internal(t, t->lastWroteTS > 1 ? t->lastWroteTS - 1 : 0, samplesVoid, 1, t->tx_num_channels, 1, false); + samplesVoid[i] = (void *)&v; + samplesBlockHeader_t header = {1, t->tx_num_channels, t->lastWroteTS}; + fullwrite(conn_sock, &header, sizeof(header), t); + fullwrite(conn_sock, samplesVoid, sampleToByte(1, t->tx_num_channels), t); if (new_buf->channel_model) new_buf->channel_model->start_TS = t->lastWroteTS; + mutexunlock(t->Sockmutex); } else { if ( events[nbEv].events & (EPOLLHUP | EPOLLERR | EPOLLRDHUP) ) { socketError(t, b); @@ -867,12 +847,11 @@ static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps_for_initi b->trashingPacket=true; } - pthread_mutex_lock(&Sockmutex); - + mutexlock(t->Sockmutex); if (t->lastWroteTS != 0 && (fabs((double)t->lastWroteTS-b->lastReceivedTS) > (double)CirSize)) LOG_W(HW, "UEsock(%d) Tx/Rx shift too large Tx:%lu, Rx:%lu\n", b->conn_sock, t->lastWroteTS, b->lastReceivedTS); + mutexunlock(t->Sockmutex); - pthread_mutex_unlock(&Sockmutex); b->transferPtr=(char *)&b->circularBuf[(b->lastReceivedTS*b->th.nbAnt)%CirSize]; b->remainToTransfer=sampleToByte(b->th.size, b->th.nbAnt); } @@ -929,7 +908,6 @@ static int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimest } } else { bool have_to_wait; - int loops = 0; do { have_to_wait=false; @@ -951,16 +929,9 @@ static int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimest t->nextRxTstamp + nsamps); flushInput(t, 3, nsamps); } - if (t->hanging_workaround && loops++ > 10 && t->role == SIMU_ROLE_SERVER && nb_ue > 1) { - // Just start producing samples. The clients will catch up. - have_to_wait = false; - LOG_W(HW, - "No longer waiting for clients to catch up, starting to produce samples\n"); - } } while (have_to_wait); } - struct timespec start_time; int ret = clock_gettime(CLOCK_REALTIME, &start_time); AssertFatal(ret == 0, "clock_gettime() failed: errno %d, %s\n", errno, strerror(errno)); @@ -1005,7 +976,7 @@ static int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimest int nbAnt_tx = ptr->th.nbAnt; // number of Tx antennas int firstIndex = (CirSize + t->nextRxTstamp - t->chan_offset) % CirSize; sample_t *out = (sample_t *)samplesVoid[a]; - if ((nbAnt_tx == 1) && ((nb_ue == 1) || (t->role == SIMU_ROLE_CLIENT))) { // optimized for 1 Tx and 1 UE + if ((nbAnt_tx == 1) && ((t->nb_cnx == 1) || (t->role == SIMU_ROLE_CLIENT))) { // optimized for 1 Tx and 1 UE sample_t *firstSample = (sample_t *)&(ptr->circularBuf[firstIndex]); if (firstIndex + nsamps > CirSize) { int tailSz = CirSize - firstIndex; @@ -1137,7 +1108,7 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) { rfsimulator->prop_delay_ms = rfsimulator->chan_offset * 1000 / rfsimulator->sample_rate; LOG_I(HW, "propagation delay %f ms, %lu samples\n", rfsimulator->prop_delay_ms, rfsimulator->chan_offset); } - pthread_mutex_init(&Sockmutex, NULL); + mutexinit(rfsimulator->Sockmutex); LOG_I(HW, "Running as %s\n", rfsimulator->role == SIMU_ROLE_SERVER ? "server waiting opposite rfsimulators to connect" From b9c066329ed072e170faea6ff61a01b1e57b9e71 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Fri, 30 May 2025 12:20:30 +0200 Subject: [PATCH 148/964] trace in 4G RAR processing to debug ci result --- openair1/PHY/LTE_UE_TRANSPORT/rar_tools_ue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair1/PHY/LTE_UE_TRANSPORT/rar_tools_ue.c b/openair1/PHY/LTE_UE_TRANSPORT/rar_tools_ue.c index ad513a424e..778b9ecfa0 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/rar_tools_ue.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/rar_tools_ue.c @@ -105,7 +105,7 @@ int generate_ue_ulsch_params_from_rar(PHY_VARS_UE *ue, cqireq=rar[3]&1; if (rballoc>RIV_max) { - LOG_D(PHY,"rar_tools.c: ERROR: rb_alloc (%x) > RIV_max\n",rballoc); + LOG_W(PHY,"rar_tools.c: ERROR: rb_alloc (%x) > RIV_max\n",rballoc); return(-1); } From 68857114a68d1fb48e85f999c33bd9085868ec25 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Mon, 16 Jun 2025 10:36:44 +0200 Subject: [PATCH 149/964] split rfsimulator too long function in smaller ones. Clean code for bad "UE" instead of rfsim client/server. Simplify logic --- radio/rfsimulator/simulator.c | 574 +++++++++++++++++----------------- 1 file changed, 293 insertions(+), 281 deletions(-) diff --git a/radio/rfsimulator/simulator.c b/radio/rfsimulator/simulator.c index 1cfc7dd7cc..1b40b66aa7 100644 --- a/radio/rfsimulator/simulator.c +++ b/radio/rfsimulator/simulator.c @@ -1,26 +1,25 @@ /* -* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more -* contributor license agreements. See the NOTICE file distributed with -* this work for additional information regarding copyright ownership. -* The OpenAirInterface Software Alliance licenses this file to You under -* the OAI Public License, Version 1.1 (the "License"); you may not use this file -* except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.openairinterface.org/?page_id=698 -* -* Author and copyright: Laurent Thomas, open-cells.com -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*------------------------------------------------------------------------------- -* For more information about the OpenAirInterface (OAI) Software Alliance: -* contact@openairinterface.org -*/ - + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Author and copyright: Laurent Thomas, open-cells.com + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ /* * Open issues and limitations @@ -51,7 +50,7 @@ #include #include "rfsimulator.h" -#define PORT 4043 //default TCP port for this simulator +#define PORT 4043 // default TCP port for this simulator // // CirSize defines the number of samples inquired for a read cycle // It is bounded by a slot read capability (which depends on bandwidth and numerology) @@ -65,8 +64,8 @@ // The previous value is kept below in comment it was computed for 100ms 1x 20MHz // #define CirSize 6144000 // 100ms SiSo 20MHz LTE #define minCirSize 460800 // 10ms SiSo 40Mhz 3/4 sampling NR78 FR1 -#define sampleToByte(a,b) ((a)*(b)*sizeof(sample_t)) -#define byteToSample(a,b) ((a)/(sizeof(sample_t)*(b))) +#define sampleToByte(a, b) ((a) * (b) * sizeof(sample_t)) +#define byteToSample(a, b) ((a) / (sizeof(sample_t) * (b))) #define GENERATE_CHANNEL 10 // each frame (or slot?) in DL #define MAX_FD_RFSIMU 250 @@ -77,7 +76,7 @@ typedef enum { SIMU_ROLE_SERVER = 1, SIMU_ROLE_CLIENT } simuRole; // -#define RFSIMU_SECTION "rfsimulator" +#define RFSIMU_SECTION "rfsimulator" #define RFSIMU_OPTIONS_PARAMNAME "options" #define RFSIM_CONFIG_HELP_OPTIONS \ @@ -85,12 +84,12 @@ typedef enum { SIMU_ROLE_SERVER = 1, SIMU_ROLE_CLIENT } simuRole; " chanmod: enable channel modelisation\n" \ " saviq: enable saving written iqs to a file\n" +// clang-format off /*-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ -/* configuration parameters for the rfsimulator device */ +/* configuration parameters for the rfsimulator device */ /* optname helpstr paramflags XXXptr defXXXval type numelt */ /*-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ -#define simOpt PARAMFLAG_NOFREE|PARAMFLAG_CMDLINE_NOPREFIXENABLED -// clang-format off +#define simOpt PARAMFLAG_NOFREE | PARAMFLAG_CMDLINE_NOPREFIXENABLED #define RFSIMULATOR_PARAMS_DESC { \ {"serveraddr", "\n", simOpt, .strptr=&rfsimulator->ip, .defstrval="127.0.0.1", TYPE_STRING, 0 },\ {"serverport", "\n", simOpt, .u16ptr = &(rfsimulator->port), .defuintval = PORT, TYPE_UINT16, 0}, \ @@ -110,6 +109,7 @@ static int rfsimu_setchanmod_cmd(char *buff, int debug, telnet_printfunc_t prnt, static int rfsimu_setdistance_cmd(char *buff, int debug, telnet_printfunc_t prnt, void *arg); static int rfsimu_getdistance_cmd(char *buff, int debug, telnet_printfunc_t prnt, void *arg); static int rfsimu_vtime_cmd(char *buff, int debug, telnet_printfunc_t prnt, void *arg); +// clang-format off static telnetshell_cmddef_t rfsimu_cmdarray[] = { {"show models", "", (cmdfunc_t)rfsimu_setchanmod_cmd, {(webfunc_t)getset_currentchannels_type}, TELNETSRV_CMDFLAG_WEBSRVONLY | TELNETSRV_CMDFLAG_GETWEBTBLDATA, NULL}, {"setmodel", " ", (cmdfunc_t)rfsimu_setchanmod_cmd, {NULL}, TELNETSRV_CMDFLAG_PUSHINTPOOLQ | TELNETSRV_CMDFLAG_TELNETONLY, NULL}, @@ -118,6 +118,7 @@ static telnetshell_cmddef_t rfsimu_cmdarray[] = { {"vtime", "", (cmdfunc_t)rfsimu_vtime_cmd, {NULL}, TELNETSRV_CMDFLAG_PUSHINTPOOLQ | TELNETSRV_CMDFLAG_AUTOUPDATE}, {"", "", NULL}, }; +// clang-format on static telnetshell_cmddef_t *setmodel_cmddef = &(rfsimu_cmdarray[1]); static telnetshell_vardef_t rfsimu_vardef[] = {{"", 0, 0, NULL}}; @@ -167,25 +168,25 @@ typedef struct { static buffer_t *allocCirBuf(rfsimulator_state_t *bridge, int sock) { uint64_t buff_index = bridge->next_buf++ % MAX_FD_RFSIMU; - buffer_t *ptr=&bridge->buf[buff_index]; + buffer_t *ptr = &bridge->buf[buff_index]; ptr->circularBuf = calloc(1, sampleToByte(CirSize, 1)); if (ptr->circularBuf == NULL) { LOG_E(HW, "malloc(%lu) failed\n", sampleToByte(CirSize, 1)); return NULL; } - ptr->circularBufEnd=((char *)ptr->circularBuf)+sampleToByte(CirSize,1); - ptr->conn_sock=sock; - ptr->lastReceivedTS=0; - ptr->headerMode=true; - ptr->trashingPacket=false; - ptr->transferPtr=(char *)&ptr->th; - ptr->remainToTransfer=sizeof(samplesBlockHeader_t); + ptr->circularBufEnd = ((char *)ptr->circularBuf) + sampleToByte(CirSize, 1); + ptr->conn_sock = sock; + ptr->lastReceivedTS = 0; + ptr->headerMode = true; + ptr->trashingPacket = false; + ptr->transferPtr = (char *)&ptr->th; + ptr->remainToTransfer = sizeof(samplesBlockHeader_t); int sendbuff = SEND_BUFF_SIZE; if (setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &sendbuff, sizeof(sendbuff)) != 0) { LOG_E(HW, "setsockopt(SO_SNDBUF) failed\n"); return NULL; } - struct epoll_event ev= {0}; + struct epoll_event ev = {0}; ev.events = EPOLLIN | EPOLLRDHUP; ev.data.ptr = ptr; if (epoll_ctl(bridge->epollfd, EPOLL_CTL_ADD, sock, &ev) != 0) { @@ -193,21 +194,21 @@ static buffer_t *allocCirBuf(rfsimulator_state_t *bridge, int sock) return NULL; } - if ( bridge->channelmod > 0) { + if (bridge->channelmod > 0) { // create channel simulation model for this mode reception - static bool init_done=false; + static bool init_done = false; if (!init_done) { uint64_t rand; - FILE *h=fopen("/dev/random","r"); + FILE *h = fopen("/dev/random", "r"); - if ( 1 != fread(&rand,sizeof(rand),1,h) ) + if (1 != fread(&rand, sizeof(rand), 1, h)) LOG_W(HW, "Can't read /dev/random\n"); fclose(h); randominit(rand); tableNor(rand); - init_done=true; + init_done = true; } char modelname[30]; snprintf(modelname, @@ -228,7 +229,7 @@ static buffer_t *allocCirBuf(rfsimulator_state_t *bridge, int sock) set_channeldesc_owner(ptr->channel_model, RFSIMU_MODULEID); set_channeldesc_direction(ptr->channel_model, bridge->role == SIMU_ROLE_SERVER); - random_channel(ptr->channel_model,false); + random_channel(ptr->channel_model, false); LOG_I(HW, "Random channel %s in rfsimulator activated\n", modelname); } return ptr; @@ -273,7 +274,7 @@ static int setblocking(int sock, enum blocking_t active) return -1; } - if (active==blocking) + if (active == blocking) opts = opts & ~O_NONBLOCK; else opts = opts | O_NONBLOCK; @@ -288,7 +289,7 @@ static int setblocking(int sock, enum blocking_t active) static void fullwrite(int fd, void *_buf, ssize_t count, rfsimulator_state_t *t) { if (t->saveIQfile != -1) { - if (write(t->saveIQfile, _buf, count) != count ) + if (write(t->saveIQfile, _buf, count) != count) LOG_E(HW, "write() in save iq file failed (%d)\n", errno); } @@ -299,12 +300,12 @@ static void fullwrite(int fd, void *_buf, ssize_t count, rfsimulator_state_t *t) l = write(fd, buf, count); if (l == 0) { - LOG_E(HW, "write() failed, returned 0\n"); - return; + LOG_E(HW, "write() failed, returned 0\n"); + return; } if (l < 0) { - if (errno==EINTR) + if (errno == EINTR) continue; if (errno == EAGAIN) { @@ -323,8 +324,8 @@ static void fullwrite(int fd, void *_buf, ssize_t count, rfsimulator_state_t *t) } static void rfsimulator_readconfig(rfsimulator_state_t *rfsimulator) { - char *saveF=NULL; - char *modelname=NULL; + char *saveF = NULL; + char *modelname = NULL; paramdef_t rfsimu_params[] = RFSIMULATOR_PARAMS_DESC; int p = config_paramidx_fromname(rfsimu_params, sizeofArray(rfsimu_params), RFSIMU_OPTIONS_PARAMNAME); int ret = config_get(config_get_if(), rfsimu_params, sizeofArray(rfsimu_params), RFSIMU_SECTION); @@ -332,11 +333,11 @@ static void rfsimulator_readconfig(rfsimulator_state_t *rfsimulator) { rfsimulator->saveIQfile = -1; - for(int i=0; isaveIQfile=open(saveF,O_APPEND| O_CREAT|O_TRUNC | O_WRONLY, 0666); + for (int i = 0; i < rfsimu_params[p].numelt; i++) { + if (strcmp(rfsimu_params[p].strlistptr[i], "saviq") == 0) { + rfsimulator->saveIQfile = open(saveF, O_APPEND | O_CREAT | O_TRUNC | O_WRONLY, 0666); - if ( rfsimulator->saveIQfile != -1 ) + if (rfsimulator->saveIQfile != -1) LOG_I(HW, "Will save written IQ samples in %s\n", saveF); else { LOG_E(HW, "open(%s) failed for IQ saving, errno(%d)\n", saveF, errno); @@ -344,10 +345,10 @@ static void rfsimulator_readconfig(rfsimulator_state_t *rfsimulator) { } break; - } else if (strcmp(rfsimu_params[p].strlistptr[i],"chanmod") == 0) { + } else if (strcmp(rfsimu_params[p].strlistptr[i], "chanmod") == 0) { init_channelmod(); load_channellist(rfsimulator->tx_num_channels, rfsimulator->rx_num_channels, rfsimulator->sample_rate, rfsimulator->rx_freq, rfsimulator->tx_bw); - rfsimulator->channelmod=true; + rfsimulator->channelmod = true; } else { fprintf(stderr, "unknown rfsimulator option: %s\n", rfsimu_params[p].strlistptr[i]); exit(-1); @@ -355,8 +356,8 @@ static void rfsimulator_readconfig(rfsimulator_state_t *rfsimulator) { } /* for compatibility keep environment variable usage */ - if ( getenv("RFSIMULATOR") != NULL ) { - rfsimulator->ip=getenv("RFSIMULATOR"); + if (getenv("RFSIMULATOR") != NULL) { + rfsimulator->ip = getenv("RFSIMULATOR"); LOG_W(HW, "The RFSIMULATOR environment variable is deprecated and support will be removed in the future. Instead, add parameter --rfsimulator.serveraddr %s to set the server address. Note: the default is \"server\"; for the gNB/eNB, you don't have to set any configuration.\n", rfsimulator->ip); LOG_I(HW, "Remove RFSIMULATOR environment variable to get rid of this message and the sleep.\n"); sleep(10); @@ -370,8 +371,8 @@ static void rfsimulator_readconfig(rfsimulator_state_t *rfsimulator) { } static int rfsimu_setchanmod_cmd(char *buff, int debug, telnet_printfunc_t prnt, void *arg) { - char *modelname=NULL; - char *modeltype=NULL; + char *modelname = NULL; + char *modeltype = NULL; rfsimulator_state_t *t = (rfsimulator_state_t *)arg; if (t->channelmod == false) { prnt("%s: ERROR channel modelisation disabled...\n", __func__); @@ -383,23 +384,23 @@ static int rfsimu_setchanmod_cmd(char *buff, int debug, telnet_printfunc_t prnt, } if (debug) prnt("%s: rfsimu_setchanmod_cmd buffer \"%s\"\n", __func__, buff); - int s = sscanf(buff,"%m[^ ] %ms\n",&modelname, &modeltype); + int s = sscanf(buff, "%m[^ ] %ms\n", &modelname, &modeltype); if (s == 2) { - int channelmod=modelid_fromstrtype(modeltype); + int channelmod = modelid_fromstrtype(modeltype); - if (channelmod<0) + if (channelmod < 0) prnt("%s: ERROR: model type %s unknown\n", __func__, modeltype); else { rfsimulator_state_t *t = (rfsimulator_state_t *)arg; - int found=0; + int found = 0; for (int i = 0; i < MAX_FD_RFSIMU; i++) { - buffer_t *b=&t->buf[i]; - if ( b->channel_model==NULL) + buffer_t *b = &t->buf[i]; + if (b->channel_model == NULL) continue; - if (b->channel_model->model_name==NULL) + if (b->channel_model->model_name == NULL) continue; - if (b->conn_sock >= 0 && (strcmp(b->channel_model->model_name,modelname)==0)) { + if (b->conn_sock >= 0 && (strcmp(b->channel_model->model_name, modelname) == 0)) { channel_desc_t *newmodel = new_channel_desc_scm(t->tx_num_channels, t->rx_num_channels, channelmod, @@ -415,17 +416,17 @@ static int rfsimu_setchanmod_cmd(char *buff, int debug, telnet_printfunc_t prnt, 0); // noise_power set_channeldesc_owner(newmodel, RFSIMU_MODULEID); set_channeldesc_direction(newmodel, t->role == SIMU_ROLE_SERVER); - set_channeldesc_name(newmodel,modelname); - random_channel(newmodel,false); - channel_desc_t *oldmodel=b->channel_model; - b->channel_model=newmodel; + set_channeldesc_name(newmodel, modelname); + random_channel(newmodel, false); + channel_desc_t *oldmodel = b->channel_model; + b->channel_model = newmodel; free_channel_desc_scm(oldmodel); prnt("%s: New model type %s applied to channel %s connected to sock %d\n", __func__, modeltype, modelname, i); - found=1; + found = 1; break; } } /* for */ - if (found==0) + if (found == 0) prnt("%s: Channel %s not found or not currently used\n", __func__, modelname); } } else { @@ -456,7 +457,7 @@ static int rfsimu_setdistance_cmd(char *buff, int debug, telnet_printfunc_t prnt char *modelname; int distance; - int s = sscanf(buff,"%m[^ ] %d\n", &modelname, &distance); + int s = sscanf(buff, "%m[^ ] %d\n", &modelname, &distance); if (s != 2) { prnt("%s: require exact two parameters\n", __func__); return CMDSTATUS_VARNOTFOUND; @@ -466,8 +467,8 @@ static int rfsimu_setdistance_cmd(char *buff, int debug, telnet_printfunc_t prnt const double sample_rate = t->sample_rate; const double c = 299792458; /* 3e8 */ - const uint64_t new_offset = (double) distance * sample_rate / c; - const double new_distance = (double) new_offset * c / sample_rate; + const uint64_t new_offset = (double)distance * sample_rate / c; + const double new_distance = (double)new_offset * c / sample_rate; const double new_delay_ms = new_offset * 1000.0 / sample_rate; prnt("\n%s: new_offset %lu, new (exact) distance %.3f m, new delay %f ms\n", __func__, new_offset, new_distance, new_delay_ms); @@ -476,7 +477,7 @@ static int rfsimu_setdistance_cmd(char *buff, int debug, telnet_printfunc_t prnt /* Set distance in rfsim and channel model, update channel and ringbuffer */ for (int i = 0; i < MAX_FD_RFSIMU; i++) { - buffer_t *b=&t->buf[i]; + buffer_t *b = &t->buf[i]; if (b->conn_sock <= 0 || b->channel_model == NULL || b->channel_model->model_name == NULL || strcmp(b->channel_model->model_name, modelname) != 0) { if (b->channel_model != NULL && b->channel_model->model_name != NULL) prnt(" %s: model %s unmodified\n", __func__, b->channel_model->model_name); @@ -502,13 +503,13 @@ static int rfsimu_getdistance_cmd(char *buff, int debug, telnet_printfunc_t prnt const double c = 299792458; /* 3e8 */ for (int i = 0; i < MAX_FD_RFSIMU; i++) { - buffer_t *b=&t->buf[i]; + buffer_t *b = &t->buf[i]; if (b->conn_sock <= 0 || b->channel_model == NULL || b->channel_model->model_name == NULL) continue; channel_desc_t *cd = b->channel_model; const uint64_t offset = cd->channel_offset; - const double distance = (double) offset * c / sample_rate; + const double distance = (double)offset * c / sample_rate; prnt("%s: %s offset %lu distance %.3f m\n", __func__, cd->model_name, offset, distance); } prnt("%s: offset %lu delay %f ms\n", __func__, t->chan_offset, t->prop_delay_ms); @@ -529,7 +530,7 @@ static int startServer(openair0_device *device) { int sock = -1; struct addrinfo *results = NULL; - struct addrinfo *rp= NULL; + struct addrinfo *rp = NULL; rfsimulator_state_t *t = (rfsimulator_state_t *)device->priv; t->role = SIMU_ROLE_SERVER; @@ -538,9 +539,9 @@ static int startServer(openair0_device *device) snprintf(port, sizeof(port), "%d", t->port); struct addrinfo hints = { - .ai_family = AF_INET6, - .ai_socktype = SOCK_STREAM, - .ai_flags = AI_PASSIVE, + .ai_family = AF_INET6, + .ai_socktype = SOCK_STREAM, + .ai_flags = AI_PASSIVE, }; int s = getaddrinfo(NULL, port, &hints, &results); @@ -607,8 +608,8 @@ static int client_try_connect(const char *host, uint16_t port) snprintf(dport, sizeof(dport), "%d", port); struct addrinfo hints = { - .ai_family = AF_UNSPEC, - .ai_socktype = SOCK_STREAM, + .ai_family = AF_UNSPEC, + .ai_socktype = SOCK_STREAM, }; s = getaddrinfo(host, dport, &hints, &result); @@ -671,9 +672,9 @@ static int rfsimulator_write_internal(rfsimulator_state_t *t, LOG_D(HW, "Sending %d samples at time: %ld, nbAnt %d\n", nsamps, timestamp, nbAnt); for (int i = 0; i < MAX_FD_RFSIMU; i++) { - buffer_t *b=&t->buf[i]; + buffer_t *b = &t->buf[i]; - if (b->conn_sock >= 0 ) { + if (b->conn_sock >= 0) { samplesBlockHeader_t header = {nsamps, nbAnt, timestamp}; fullwrite(b->conn_sock, &header, sizeof(header), t); if (nbAnt == 1) { @@ -690,7 +691,7 @@ static int rfsimulator_write_internal(rfsimulator_state_t *t, } } - if ( t->lastWroteTS != 0 && fabs((double)t->lastWroteTS-timestamp) > (double)CirSize) + if (t->lastWroteTS != 0 && fabs((double)t->lastWroteTS - timestamp) > (double)CirSize) LOG_W(HW, "Discontinuous TX gap too large Tx:%lu, %lu\n", t->lastWroteTS, timestamp); if (t->lastWroteTS > timestamp) @@ -715,211 +716,223 @@ static int rfsimulator_write_internal(rfsimulator_state_t *t, return nsamps; } -static int rfsimulator_write(openair0_device *device, openair0_timestamp timestamp, void **samplesVoid, int nsamps, int nbAnt, int flags) { +static int rfsimulator_write(openair0_device *device, + openair0_timestamp timestamp, + void **samplesVoid, + int nsamps, + int nbAnt, + int flags) +{ timestamp -= device->openair0_cfg->command_line_sample_advance; return rfsimulator_write_internal(device->priv, timestamp, samplesVoid, nsamps, nbAnt, flags); } -static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps_for_initial) { +static bool add_client(rfsimulator_state_t *t) +{ + struct sockaddr_storage sa = {0}; + socklen_t socklen = sizeof(sa); + int conn_sock = accept(t->listen_sock, (struct sockaddr *)&sa, &socklen); + if (conn_sock == -1) { + LOG_E(HW, "accept() failed, errno(%d)\n", errno); + return false; + } + if (setblocking(conn_sock, notBlocking)) { + return false; + } + mutexlock(t->Sockmutex); + buffer_t *new_buf = allocCirBuf(t, conn_sock); + if (new_buf == NULL) { + mutexunlock(t->Sockmutex); + return false; + } + t->nb_cnx++; + new_buf->lastReceivedTS = t->lastWroteTS; + char ip[INET6_ADDRSTRLEN]; + getnameinfo((struct sockaddr *)&sa, socklen, ip, sizeof(ip), NULL, 0, NI_NUMERICHOST); + uint16_t port = ((struct sockaddr_in *)&sa)->sin_port; + LOG_I(HW, "Client connects from %s:%d\n", ip, port); + c16_t v = {0}; + void *samplesVoid[t->tx_num_channels]; + for (int i = 0; i < t->tx_num_channels; i++) + samplesVoid[i] = (void *)&v; + samplesBlockHeader_t header = {1, t->tx_num_channels, t->lastWroteTS}; + fullwrite(conn_sock, &header, sizeof(header), t); + fullwrite(conn_sock, samplesVoid, sampleToByte(1, t->tx_num_channels), t); + + if (new_buf->channel_model) + new_buf->channel_model->start_TS = t->lastWroteTS; + mutexunlock(t->Sockmutex); + return true; +} + +static void process_recv(rfsimulator_state_t *t, buffer_t *b, int size_for_first_pack) +{ + if (b->transferPtr == b->circularBufEnd) + b->transferPtr = (char *)b->circularBuf; + + // check the header and start block transfer + if (b->headerMode == true) { + if (b->remainToTransfer == 0) { + b->headerMode = false; // We got the header + if (t->nextRxTstamp == 0) { // First block in a client, resync with the server current TS + t->nextRxTstamp = b->th.timestamp; + // we need to bootstrap from one side, else each side will wait forever + b->lastReceivedTS = b->th.timestamp + size_for_first_pack; + LOG_D(HW, "Client got first timestamp: starting at %lu\n", t->nextRxTstamp); + b->trashingPacket = true; + if (b->channel_model) + b->channel_model->start_TS = t->nextRxTstamp; + } else if (b->lastReceivedTS < b->th.timestamp) { + // We have a transmission hole to fill, like TDD + // we create no signal samples up to the beginning of this reception + int nbAnt = b->th.nbAnt; + if (b->th.timestamp - b->lastReceivedTS < CirSize) { + for (uint64_t index = b->lastReceivedTS; index < b->th.timestamp; index++) { + for (int a = 0; a < nbAnt; a++) { + b->circularBuf[(index * nbAnt + a) % CirSize].r = 0; + b->circularBuf[(index * nbAnt + a) % CirSize].i = 0; + } + } + } else { + memset(b->circularBuf, 0, sampleToByte(CirSize, 1)); + } + b->lastReceivedTS = b->th.timestamp; + } else if (b->lastReceivedTS > b->th.timestamp) { + if (b->th.size == 1) + LOG_W(HW, "Received Rx/Tx synchro out of order\n"); + else + LOG_W(HW, "Received data in past: current is %lu, new reception: %lu!\n", b->lastReceivedTS, b->th.timestamp); + b->trashingPacket = true; + } + // normal case, we have the header + // verify the time gap is not too large + mutexlock(t->Sockmutex); + if (t->lastWroteTS != 0 && (fabs((double)t->lastWroteTS - b->lastReceivedTS) > (double)CirSize)) + LOG_W(HW, "UEsock(%d) Tx/Rx shift too large Tx:%lu, Rx:%lu\n", b->conn_sock, t->lastWroteTS, b->lastReceivedTS); + mutexunlock(t->Sockmutex); + + // move back the pointer to overwrite the header, we don't need it anymore + b->transferPtr = (char *)&b->circularBuf[(b->lastReceivedTS * b->th.nbAnt) % CirSize]; + // we now need to read the samples + b->remainToTransfer = sampleToByte(b->th.size, b->th.nbAnt); + } + return; + } + + if (b->headerMode == false) { + if (!b->trashingPacket) { + b->lastReceivedTS = b->th.timestamp + b->th.size - byteToSample(b->remainToTransfer, b->th.nbAnt); + LOG_D(HW, "UEsock: %d Set b->lastReceivedTS %ld\n", b->conn_sock, b->lastReceivedTS); + } + if (b->remainToTransfer == 0) { + LOG_D(HW, "UEsock: %d Completed block reception: %ld\n", b->conn_sock, b->lastReceivedTS); + b->headerMode = true; + b->transferPtr = (char *)&b->th; + b->remainToTransfer = sizeof(samplesBlockHeader_t); + b->trashingPacket = false; + } + } +} + +static bool flushInput(rfsimulator_state_t *t, int timeout, int first_time_sz) +{ // Process all incoming events on sockets // store the data in lists struct epoll_event events[MAX_FD_RFSIMU] = {{0}}; int nfds = epoll_wait(t->epollfd, events, MAX_FD_RFSIMU, timeout); - if ( nfds==-1 ) { - if ( errno==EINTR || errno==EAGAIN ) { - return false; - } else { + if (nfds == -1) { + if (!(errno == EINTR || errno == EAGAIN)) LOG_W(HW, "epoll_wait() failed, errno(%d)\n", errno); - return false; - } + return false; } for (int nbEv = 0; nbEv < nfds; ++nbEv) { buffer_t *b = events[nbEv].data.ptr; if (events[nbEv].events & EPOLLIN && b == NULL) { - struct sockaddr_storage sa = {0}; - socklen_t socklen = sizeof(sa); - int conn_sock = accept(t->listen_sock, (struct sockaddr *)&sa, &socklen); - if (conn_sock == -1) { - LOG_E(HW, "accept() failed, errno(%d)\n", errno); - return false; - } - if (setblocking(conn_sock, notBlocking)) { - return false; - } - mutexlock(t->Sockmutex); - buffer_t *new_buf = allocCirBuf(t, conn_sock); - if (new_buf == NULL) { - mutexunlock(t->Sockmutex); - return false; - } - t->nb_cnx++; - char ip[INET6_ADDRSTRLEN]; - getnameinfo((struct sockaddr*)&sa, socklen, ip, sizeof(ip), NULL, 0, NI_NUMERICHOST); - uint16_t port = ((struct sockaddr_in *)&sa)->sin_port; - LOG_I(HW, "Client connects from %s:%d\n", ip, port); - c16_t v = {0}; - void *samplesVoid[t->tx_num_channels]; - for ( int i=0; i < t->tx_num_channels; i++) - samplesVoid[i] = (void *)&v; - samplesBlockHeader_t header = {1, t->tx_num_channels, t->lastWroteTS}; - fullwrite(conn_sock, &header, sizeof(header), t); - fullwrite(conn_sock, samplesVoid, sampleToByte(1, t->tx_num_channels), t); - - if (new_buf->channel_model) - new_buf->channel_model->start_TS = t->lastWroteTS; - mutexunlock(t->Sockmutex); + bool ret = add_client(t); + if (!ret) + return ret; + continue; } else { - if ( events[nbEv].events & (EPOLLHUP | EPOLLERR | EPOLLRDHUP) ) { + if (events[nbEv].events & (EPOLLHUP | EPOLLERR | EPOLLRDHUP)) { socketError(t, b); continue; } - if ( b->circularBuf == NULL ) { - LOG_E(HW, "Received data on not connected socket %d\n", events[nbEv].data.fd); - continue; - } - - ssize_t blockSz; - - if ( b->headerMode) - blockSz=b->remainToTransfer; - else - blockSz= b->transferPtr + b->remainToTransfer <= b->circularBufEnd ? - b->remainToTransfer : - b->circularBufEnd - b->transferPtr ; - - ssize_t sz = recv(b->conn_sock, b->transferPtr, blockSz, MSG_DONTWAIT); - - if ( sz < 0 ) { - if ( errno != EAGAIN ) { - LOG_E(HW, "recv() failed, errno(%d)\n", errno); - //abort(); - } - } else if ( sz == 0 ) - continue; - - LOG_D(HW, "Socket rcv %zd bytes\n", sz); - b->remainToTransfer -= sz; - b->transferPtr+=sz; - - if (b->transferPtr==b->circularBufEnd ) - b->transferPtr=(char *)b->circularBuf; - - // check the header and start block transfer - if ( b->headerMode==true && b->remainToTransfer==0) { - b->headerMode = false; - - if (t->nextRxTstamp == 0) { // First block in UE, resync with the gNB current TS - t->nextRxTstamp=b->th.timestamp> nsamps_for_initial ? - b->th.timestamp - nsamps_for_initial : - 0; - b->lastReceivedTS=b->th.timestamp> nsamps_for_initial ? - b->th.timestamp : - nsamps_for_initial; - LOG_D(HW, "UE got first timestamp: starting at %lu\n", t->nextRxTstamp); - b->trashingPacket=true; - if (b->channel_model) - b->channel_model->start_TS = t->nextRxTstamp; - } else if (b->lastReceivedTS < b->th.timestamp) { - int nbAnt= b->th.nbAnt; - - if ( b->th.timestamp-b->lastReceivedTS < CirSize ) { - for (uint64_t index=b->lastReceivedTS; index < b->th.timestamp; index++ ) { - for (int a=0; a < nbAnt; a++) { - b->circularBuf[(index*nbAnt+a)%CirSize].r = 0; - b->circularBuf[(index*nbAnt+a)%CirSize].i = 0; - } - } - } else { - memset(b->circularBuf, 0, sampleToByte(CirSize,1)); - } - - b->lastReceivedTS=b->th.timestamp; - } else if (b->lastReceivedTS > b->th.timestamp && b->th.size == 1) { - LOG_W(HW, "Received Rx/Tx synchro out of order\n"); - b->trashingPacket=true; - } else if (b->lastReceivedTS == b->th.timestamp) { - // normal case - } else { - LOG_W(HW, "Received data in past: current is %lu, new reception: %lu!\n", b->lastReceivedTS, b->th.timestamp); - b->trashingPacket=true; - } - - mutexlock(t->Sockmutex); - if (t->lastWroteTS != 0 && (fabs((double)t->lastWroteTS-b->lastReceivedTS) > (double)CirSize)) - LOG_W(HW, "UEsock(%d) Tx/Rx shift too large Tx:%lu, Rx:%lu\n", b->conn_sock, t->lastWroteTS, b->lastReceivedTS); - mutexunlock(t->Sockmutex); - - b->transferPtr=(char *)&b->circularBuf[(b->lastReceivedTS*b->th.nbAnt)%CirSize]; - b->remainToTransfer=sampleToByte(b->th.size, b->th.nbAnt); - } - - if ( b->headerMode==false ) { - if ( ! b->trashingPacket ) { - b->lastReceivedTS=b->th.timestamp+b->th.size-byteToSample(b->remainToTransfer,b->th.nbAnt); - LOG_D(HW, "UEsock: %d Set b->lastReceivedTS %ld\n", b->conn_sock, b->lastReceivedTS); - } - - if ( b->remainToTransfer==0) { - LOG_D(HW, "UEsock: %d Completed block reception: %ld\n", b->conn_sock, b->lastReceivedTS); - b->headerMode=true; - b->transferPtr=(char *)&b->th; - b->remainToTransfer = sizeof(samplesBlockHeader_t); - b->trashingPacket=false; - } - } } - } - return nfds>0; + if (b->circularBuf == NULL) { + LOG_E(HW, "Received data on not connected socket %d\n", events[nbEv].data.fd); + continue; + } + + ssize_t blockSz; + if (b->headerMode) + blockSz = b->remainToTransfer; + else + blockSz = + b->transferPtr + b->remainToTransfer <= b->circularBufEnd ? b->remainToTransfer : b->circularBufEnd - b->transferPtr; + + ssize_t sz = recv(b->conn_sock, b->transferPtr, blockSz, MSG_DONTWAIT); + if (sz <= 0) { + if (sz < 0 && errno != EAGAIN) + LOG_E(HW, "recv() failed, errno(%d)\n", errno); + continue; + } + LOG_D(HW, "Socket rcv %zd bytes\n", sz); + b->remainToTransfer -= sz; + b->transferPtr += sz; + process_recv(t, b, first_time_sz); + } + return nfds > 0; } static int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, void **samplesVoid, int nsamps, int nbAnt) { rfsimulator_state_t *t = device->priv; - LOG_D(HW, "Enter rfsimulator_read, expect %d samples, will release at TS: %ld, nbAnt %d\n", nsamps, t->nextRxTstamp+nsamps, nbAnt); + LOG_D(HW, + "Enter rfsimulator_read, expect %d samples, will release at TS: %ld, nbAnt %d\n", + nsamps, + t->nextRxTstamp + nsamps, + nbAnt); // deliver data from received data // check if a UE is connected int first_sock; for (first_sock = 0; first_sock < MAX_FD_RFSIMU; first_sock++) - if (t->buf[first_sock].circularBuf != NULL ) + if (t->buf[first_sock].circularBuf != NULL) break; if (first_sock == MAX_FD_RFSIMU) { // no connected device (we are eNB, no UE is connected) - if ( t->nextRxTstamp == 0) + if (t->nextRxTstamp == 0) LOG_I(HW, "No connected device, generating void samples...\n"); - if (!flushInput(t, t->wait_timeout, nsamps)) { - for (int x=0; x < nbAnt; x++) - memset(samplesVoid[x],0,sampleToByte(nsamps,1)); + if (!flushInput(t, t->wait_timeout, nsamps)) { + for (int x = 0; x < nbAnt; x++) + memset(samplesVoid[x], 0, sampleToByte(nsamps, 1)); - t->nextRxTstamp+=nsamps; + t->nextRxTstamp += nsamps; - if ( ((t->nextRxTstamp/nsamps)%100) == 0) + if (((t->nextRxTstamp / nsamps) % 100) == 0) LOG_D(HW, "No UE, Generating void samples for Rx: %ld\n", t->nextRxTstamp); - *ptimestamp = t->nextRxTstamp-nsamps; + *ptimestamp = t->nextRxTstamp - nsamps; return nsamps; } } else { bool have_to_wait; do { - have_to_wait=false; - + have_to_wait = false; buffer_t *b = NULL; for (int sock = 0; sock < MAX_FD_RFSIMU; sock++) { b = &t->buf[sock]; - - if ( b->circularBuf ) - if ( t->nextRxTstamp+nsamps > b->lastReceivedTS ) { - have_to_wait=true; + if (b->circularBuf && (t->nextRxTstamp + nsamps) > b->lastReceivedTS) { + have_to_wait = true; break; - } + } } if (have_to_wait) { @@ -937,28 +950,28 @@ static int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimest AssertFatal(ret == 0, "clock_gettime() failed: errno %d, %s\n", errno, strerror(errno)); // Clear the output buffer - for (int a=0; abuf[sock]; + buffer_t *ptr = &t->buf[sock]; - if ( ptr->circularBuf ) { - bool reGenerateChannel=false; + if (ptr->circularBuf) { + bool reGenerateChannel = false; - //fixme: when do we regenerate - // it seems legacy behavior is: never in UL, each frame in DL + // fixme: when do we regenerate + // it seems legacy behavior is: never in UL, each frame in DL if (reGenerateChannel) - random_channel(ptr->channel_model,0); + random_channel(ptr->channel_model, 0); if (t->poll_telnetcmdq) - t->poll_telnetcmdq(t->telnetcmd_qid,t); + t->poll_telnetcmdq(t->telnetcmd_qid, t); - for (int a=0; achannel_model != NULL ) { // apply a channel model + for (int a = 0; a < nbAnt; a++) { // loop over number of Rx antennas + if (ptr->channel_model != NULL) { // apply a channel model if (num_chanmod_channels == 0) { memset(temp_array, 0, sizeof(temp_array)); } @@ -971,12 +984,11 @@ static int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimest t->nextRxTstamp, CirSize, apply_noise_per_channel); - } - else { // no channel modeling + } else { // no channel modeling int nbAnt_tx = ptr->th.nbAnt; // number of Tx antennas int firstIndex = (CirSize + t->nextRxTstamp - t->chan_offset) % CirSize; sample_t *out = (sample_t *)samplesVoid[a]; - if ((nbAnt_tx == 1) && ((t->nb_cnx == 1) || (t->role == SIMU_ROLE_CLIENT))) { // optimized for 1 Tx and 1 UE + if (nbAnt_tx == 1 && t->nb_cnx == 1) { // optimized for 1 Tx and 1 UE sample_t *firstSample = (sample_t *)&(ptr->circularBuf[firstIndex]); if (firstIndex + nsamps > CirSize) { int tailSz = CirSize - firstIndex; @@ -1030,14 +1042,14 @@ static int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimest AssertFatal(ret == 0, "clock_gettime() failed: errno %d, %s\n", errno, strerror(errno)); double diff_ns = (end_time.tv_sec - start_time.tv_sec) * 1000000000 + (end_time.tv_nsec - start_time.tv_nsec); static double average = 0.0; - average = (average * 0.98) + ( nsamps / (diff_ns / 1e9) * 0.02); + average = (average * 0.98) + (nsamps / (diff_ns / 1e9) * 0.02); static int calls = 0; if (calls++ % 10000 == 0) { LOG_D(HW, "Rfsimulator: velocity %.2f Msps, realtime requirements %.2f Msps\n", average / 1e6, t->sample_rate / 1e6); } *ptimestamp = t->nextRxTstamp; // return the time of the first sample - t->nextRxTstamp+=nsamps; + t->nextRxTstamp += nsamps; LOG_D(HW, "Rx to upper layer: %d from %ld to %ld, energy in first antenna %d\n", nsamps, @@ -1054,10 +1066,10 @@ static int rfsimulator_reset_stats(openair0_device *device) { return 0; } static void rfsimulator_end(openair0_device *device) { - rfsimulator_state_t* s = device->priv; + rfsimulator_state_t *s = device->priv; for (int i = 0; i < MAX_FD_RFSIMU; i++) { buffer_t *b = &s->buf[i]; - if (b->conn_sock >= 0 ) + if (b->conn_sock >= 0) removeCirBuf(s, b); } close(s->epollfd); @@ -1065,7 +1077,7 @@ static void rfsimulator_end(openair0_device *device) { } static void stopServer(openair0_device *device) { - rfsimulator_state_t *t = (rfsimulator_state_t *) device->priv; + rfsimulator_state_t *t = (rfsimulator_state_t *)device->priv; DevAssert(t != NULL); close(t->listen_sock); rfsimulator_end(device); @@ -1075,7 +1087,7 @@ static int rfsimulator_stop(openair0_device *device) { return 0; } static int rfsimulator_set_freq(openair0_device *device, openair0_config_t *openair0_cfg) { - rfsimulator_state_t* s = device->priv; + rfsimulator_state_t *s = device->priv; s->rx_freq = openair0_cfg->rx_freq[0]; return 0; } @@ -1092,11 +1104,11 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) { // --log_config.hw_log_level debug rfsimulator_state_t *rfsimulator = calloc(sizeof(rfsimulator_state_t), 1); // initialize channel simulation - rfsimulator->tx_num_channels=openair0_cfg->tx_num_channels; - rfsimulator->rx_num_channels=openair0_cfg->rx_num_channels; - rfsimulator->sample_rate=openair0_cfg->sample_rate; - rfsimulator->rx_freq=openair0_cfg->rx_freq[0]; - rfsimulator->tx_bw=openair0_cfg->tx_bw; + rfsimulator->tx_num_channels = openair0_cfg->tx_num_channels; + rfsimulator->rx_num_channels = openair0_cfg->rx_num_channels; + rfsimulator->sample_rate = openair0_cfg->sample_rate; + rfsimulator->rx_freq = openair0_cfg->rx_freq[0]; + rfsimulator->tx_bw = openair0_cfg->tx_bw; rfsimulator_readconfig(rfsimulator); if (rfsimulator->prop_delay_ms > 0.0) rfsimulator->chan_offset = ceil(rfsimulator->sample_rate * rfsimulator->prop_delay_ms / 1000); @@ -1114,23 +1126,23 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) { rfsimulator->role == SIMU_ROLE_SERVER ? "server waiting opposite rfsimulators to connect" : "client: will connect to a rfsimulator server side"); device->trx_start_func = rfsimulator->role == SIMU_ROLE_SERVER ? startServer : startClient; - device->trx_get_stats_func = rfsimulator_get_stats; + device->trx_get_stats_func = rfsimulator_get_stats; device->trx_reset_stats_func = rfsimulator_reset_stats; - device->trx_end_func = rfsimulator->role == SIMU_ROLE_SERVER ? stopServer : rfsimulator_end; - device->trx_stop_func = rfsimulator_stop; - device->trx_set_freq_func = rfsimulator_set_freq; - device->trx_set_gains_func = rfsimulator_set_gains; - device->trx_write_func = rfsimulator_write; - device->trx_read_func = rfsimulator_read; + device->trx_end_func = rfsimulator->role == SIMU_ROLE_SERVER ? stopServer : rfsimulator_end; + device->trx_stop_func = rfsimulator_stop; + device->trx_set_freq_func = rfsimulator_set_freq; + device->trx_set_gains_func = rfsimulator_set_gains; + device->trx_write_func = rfsimulator_write; + device->trx_read_func = rfsimulator_read; /* let's pretend to be a b2x0 */ device->type = RFSIMULATOR; openair0_cfg[0].rx_gain[0] = 0; - device->openair0_cfg=&openair0_cfg[0]; + device->openair0_cfg = &openair0_cfg[0]; device->priv = rfsimulator; device->trx_write_init = rfsimulator_write_init; for (int i = 0; i < MAX_FD_RFSIMU; i++) - rfsimulator->buf[i].conn_sock=-1; + rfsimulator->buf[i].conn_sock = -1; rfsimulator->next_buf = 0; AssertFatal((rfsimulator->epollfd = epoll_create1(0)) != -1, "epoll_create1() failed, errno(%d)", errno); @@ -1141,11 +1153,11 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) { add_telnetcmd_func_t addcmd = (add_telnetcmd_func_t)get_shlibmodule_fptr("telnetsrv", TELNET_ADDCMD_FNAME); if (addcmd != NULL) { - rfsimulator->poll_telnetcmdq = (poll_telnetcmdq_func_t)get_shlibmodule_fptr("telnetsrv", TELNET_POLLCMDQ_FNAME); - addcmd("rfsimu",rfsimu_vardef,rfsimu_cmdarray); + rfsimulator->poll_telnetcmdq = (poll_telnetcmdq_func_t)get_shlibmodule_fptr("telnetsrv", TELNET_POLLCMDQ_FNAME); + addcmd("rfsimu", rfsimu_vardef, rfsimu_cmdarray); - for(int i=0; rfsimu_cmdarray[i].cmdfunc != NULL; i++) { - if ( rfsimu_cmdarray[i].qptr != NULL) { + for (int i = 0; rfsimu_cmdarray[i].cmdfunc != NULL; i++) { + if (rfsimu_cmdarray[i].qptr != NULL) { rfsimulator->telnetcmd_qid = rfsimu_cmdarray[i].qptr; break; } From f7598bf528fbfcb157cdd24603bcabbd666dd76b Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Mon, 16 Jun 2025 13:28:43 +0200 Subject: [PATCH 150/964] clarify first transmission to client, split process_recv in 2 functions --- radio/rfsimulator/simulator.c | 147 +++++++++++++++++++--------------- 1 file changed, 82 insertions(+), 65 deletions(-) diff --git a/radio/rfsimulator/simulator.c b/radio/rfsimulator/simulator.c index 1b40b66aa7..ca8540c821 100644 --- a/radio/rfsimulator/simulator.c +++ b/radio/rfsimulator/simulator.c @@ -165,6 +165,8 @@ typedef struct { double prop_delay_ms; } rfsimulator_state_t; +static bool flushInput(rfsimulator_state_t *t, int timeout, bool first_time); + static buffer_t *allocCirBuf(rfsimulator_state_t *bridge, int sock) { uint64_t buff_index = bridge->next_buf++ % MAX_FD_RFSIMU; @@ -658,7 +660,24 @@ static int startClient(openair0_device *device) if (setblocking(sock, notBlocking) == -1) { return -1; } - return allocCirBuf(t, sock) == NULL ? -1 : 0; + buffer_t *b = allocCirBuf(t, sock); + if (!b) + return -1; + // read a 1 sample block to initialize the current time + bool have_to_wait; + do { + have_to_wait = true; + flushInput(t, 3, true); + if (b->lastReceivedTS) + have_to_wait = false; + } while (have_to_wait); + if (b->lastReceivedTS > 0) + b->lastReceivedTS--; + t->nextRxTstamp = b->lastReceivedTS; + LOG_D(HW, "Client got first timestamp: starting at %lu\n", t->nextRxTstamp); + if (b->channel_model) + b->channel_model->start_TS = t->nextRxTstamp; + return 0; } static int rfsimulator_write_internal(rfsimulator_state_t *t, @@ -765,76 +784,71 @@ static bool add_client(rfsimulator_state_t *t) return true; } -static void process_recv(rfsimulator_state_t *t, buffer_t *b, int size_for_first_pack) +static void process_recv_header(rfsimulator_state_t *t, buffer_t *b, bool first_time) +{ + // check the header and start block transfer + if (b->remainToTransfer != 0) + return; + + b->headerMode = false; // We got the header + + if (first_time) { + b->lastReceivedTS = b->th.timestamp; + b->trashingPacket = true; + } else { + if (b->lastReceivedTS < b->th.timestamp) { + // We have a transmission hole to fill, like TDD + // we create no signal samples up to the beginning of this reception + int nbAnt = b->th.nbAnt; + if (b->th.timestamp - b->lastReceivedTS < CirSize) { + // case we wrap at circular buffer end + for (uint64_t index = b->lastReceivedTS; index < b->th.timestamp; index++) { + for (int a = 0; a < nbAnt; a++) { + b->circularBuf[(index * nbAnt + a) % CirSize] = (c16_t){0}; + } + } + } else { + // case no circular buffer wrap + memset(b->circularBuf, 0, sampleToByte(CirSize, 1)); + } + b->lastReceivedTS = b->th.timestamp; + } else if (b->lastReceivedTS > b->th.timestamp) { + LOG_W(HW, "Received data in past: current is %lu, new reception: %lu!\n", b->lastReceivedTS, b->th.timestamp); + b->trashingPacket = true; + } + // verify the time gap is not too large + mutexlock(t->Sockmutex); + if (t->lastWroteTS != 0 && (fabs((double)t->lastWroteTS - b->lastReceivedTS) > (double)CirSize)) + LOG_W(HW, "UEsock(%d) Tx/Rx shift too large Tx:%lu, Rx:%lu\n", b->conn_sock, t->lastWroteTS, b->lastReceivedTS); + mutexunlock(t->Sockmutex); + } + // move back the pointer to overwrite the header, we don't need it anymore + b->transferPtr = (char *)&b->circularBuf[(b->lastReceivedTS * b->th.nbAnt) % CirSize]; + // we now need to read the samples + b->remainToTransfer = sampleToByte(b->th.size, b->th.nbAnt); + return; +} + +static void process_recv(rfsimulator_state_t *t, buffer_t *b, bool first_time) { if (b->transferPtr == b->circularBufEnd) b->transferPtr = (char *)b->circularBuf; - // check the header and start block transfer - if (b->headerMode == true) { - if (b->remainToTransfer == 0) { - b->headerMode = false; // We got the header - if (t->nextRxTstamp == 0) { // First block in a client, resync with the server current TS - t->nextRxTstamp = b->th.timestamp; - // we need to bootstrap from one side, else each side will wait forever - b->lastReceivedTS = b->th.timestamp + size_for_first_pack; - LOG_D(HW, "Client got first timestamp: starting at %lu\n", t->nextRxTstamp); - b->trashingPacket = true; - if (b->channel_model) - b->channel_model->start_TS = t->nextRxTstamp; - } else if (b->lastReceivedTS < b->th.timestamp) { - // We have a transmission hole to fill, like TDD - // we create no signal samples up to the beginning of this reception - int nbAnt = b->th.nbAnt; - if (b->th.timestamp - b->lastReceivedTS < CirSize) { - for (uint64_t index = b->lastReceivedTS; index < b->th.timestamp; index++) { - for (int a = 0; a < nbAnt; a++) { - b->circularBuf[(index * nbAnt + a) % CirSize].r = 0; - b->circularBuf[(index * nbAnt + a) % CirSize].i = 0; - } - } - } else { - memset(b->circularBuf, 0, sampleToByte(CirSize, 1)); - } - b->lastReceivedTS = b->th.timestamp; - } else if (b->lastReceivedTS > b->th.timestamp) { - if (b->th.size == 1) - LOG_W(HW, "Received Rx/Tx synchro out of order\n"); - else - LOG_W(HW, "Received data in past: current is %lu, new reception: %lu!\n", b->lastReceivedTS, b->th.timestamp); - b->trashingPacket = true; - } - // normal case, we have the header - // verify the time gap is not too large - mutexlock(t->Sockmutex); - if (t->lastWroteTS != 0 && (fabs((double)t->lastWroteTS - b->lastReceivedTS) > (double)CirSize)) - LOG_W(HW, "UEsock(%d) Tx/Rx shift too large Tx:%lu, Rx:%lu\n", b->conn_sock, t->lastWroteTS, b->lastReceivedTS); - mutexunlock(t->Sockmutex); - - // move back the pointer to overwrite the header, we don't need it anymore - b->transferPtr = (char *)&b->circularBuf[(b->lastReceivedTS * b->th.nbAnt) % CirSize]; - // we now need to read the samples - b->remainToTransfer = sampleToByte(b->th.size, b->th.nbAnt); - } - return; + if (!b->trashingPacket) { + b->lastReceivedTS = b->th.timestamp + b->th.size - byteToSample(b->remainToTransfer, b->th.nbAnt); + LOG_D(HW, "UEsock: %d Set b->lastReceivedTS %ld\n", b->conn_sock, b->lastReceivedTS); } - if (b->headerMode == false) { - if (!b->trashingPacket) { - b->lastReceivedTS = b->th.timestamp + b->th.size - byteToSample(b->remainToTransfer, b->th.nbAnt); - LOG_D(HW, "UEsock: %d Set b->lastReceivedTS %ld\n", b->conn_sock, b->lastReceivedTS); - } - if (b->remainToTransfer == 0) { - LOG_D(HW, "UEsock: %d Completed block reception: %ld\n", b->conn_sock, b->lastReceivedTS); - b->headerMode = true; - b->transferPtr = (char *)&b->th; - b->remainToTransfer = sizeof(samplesBlockHeader_t); - b->trashingPacket = false; - } + if (b->remainToTransfer == 0) { + LOG_D(HW, "UEsock: %d Completed block reception: %ld\n", b->conn_sock, b->lastReceivedTS); + b->headerMode = true; + b->transferPtr = (char *)&b->th; + b->remainToTransfer = sizeof(samplesBlockHeader_t); + b->trashingPacket = false; } } -static bool flushInput(rfsimulator_state_t *t, int timeout, int first_time_sz) +static bool flushInput(rfsimulator_state_t *t, int timeout, bool first_time) { // Process all incoming events on sockets // store the data in lists @@ -883,7 +897,10 @@ static bool flushInput(rfsimulator_state_t *t, int timeout, int first_time_sz) LOG_D(HW, "Socket rcv %zd bytes\n", sz); b->remainToTransfer -= sz; b->transferPtr += sz; - process_recv(t, b, first_time_sz); + if (b->headerMode) + process_recv_header(t, b, first_time); + else + process_recv(t, b, first_time); } return nfds > 0; } @@ -910,7 +927,7 @@ static int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimest if (t->nextRxTstamp == 0) LOG_I(HW, "No connected device, generating void samples...\n"); - if (!flushInput(t, t->wait_timeout, nsamps)) { + if (!flushInput(t, t->wait_timeout, false)) { for (int x = 0; x < nbAnt; x++) memset(samplesVoid[x], 0, sampleToByte(nsamps, 1)); @@ -940,7 +957,7 @@ static int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimest "Waiting on socket, current last ts: %ld, expected at least : %ld\n", b->lastReceivedTS, t->nextRxTstamp + nsamps); - flushInput(t, 3, nsamps); + flushInput(t, 3, false); } } while (have_to_wait); } From 1540ca3ae5905a73b09d3d8e3f1f410a6519b6d2 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Mon, 23 Jun 2025 15:51:34 +0200 Subject: [PATCH 151/964] fix bug in rfsim->nb_cnx for client side. it has no usage except a cpu optimisation in case one single rfsim socket and SISO case --- radio/rfsimulator/simulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radio/rfsimulator/simulator.c b/radio/rfsimulator/simulator.c index ca8540c821..ca28dd2e79 100644 --- a/radio/rfsimulator/simulator.c +++ b/radio/rfsimulator/simulator.c @@ -171,6 +171,7 @@ static buffer_t *allocCirBuf(rfsimulator_state_t *bridge, int sock) { uint64_t buff_index = bridge->next_buf++ % MAX_FD_RFSIMU; buffer_t *ptr = &bridge->buf[buff_index]; + bridge->nb_cnx++; ptr->circularBuf = calloc(1, sampleToByte(CirSize, 1)); if (ptr->circularBuf == NULL) { LOG_E(HW, "malloc(%lu) failed\n", sampleToByte(CirSize, 1)); @@ -764,7 +765,6 @@ static bool add_client(rfsimulator_state_t *t) mutexunlock(t->Sockmutex); return false; } - t->nb_cnx++; new_buf->lastReceivedTS = t->lastWroteTS; char ip[INET6_ADDRSTRLEN]; getnameinfo((struct sockaddr *)&sa, socklen, ip, sizeof(ip), NULL, 0, NI_NUMERICHOST); From 0523bcfbde7407f2e7126d08a33597d19169c200 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Mon, 23 Jun 2025 15:58:03 +0200 Subject: [PATCH 152/964] fix gNB that should always perform tx in case of rfsim (like continuous-tx --- executables/nr-gnb.c | 2 +- executables/nr-ru.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index acab30751b..9e96ce6aed 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -114,7 +114,7 @@ static void tx_func(processingData_L1tx_t *info) pushNotifiedFIFO(&gNB->resp_L1, res); int tx_slot_type = nr_slot_select(cfg, frame_tx, slot_tx); - if (tx_slot_type == NR_DOWNLINK_SLOT || tx_slot_type == NR_MIXED_SLOT || get_softmodem_params()->continuous_tx) { + if (tx_slot_type == NR_DOWNLINK_SLOT || tx_slot_type == NR_MIXED_SLOT || get_softmodem_params()->continuous_tx || IS_SOFTMODEM_RFSIM) { start_meas(&info->gNB->phy_proc_tx); phy_procedures_gNB_TX(info, frame_tx, slot_tx, 1); diff --git a/executables/nr-ru.c b/executables/nr-ru.c index 411caf9a63..2bacf04aa3 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -759,7 +759,7 @@ void tx_rf(RU_t *ru, int frame,int slot, uint64_t timestamp) radio_tx_burst_flag_t flags_burst = TX_BURST_INVALID; radio_tx_gpio_flag_t flags_gpio = 0; - if (cfg->cell_config.frame_duplex_type.value == TDD && !get_softmodem_params()->continuous_tx) { + if (cfg->cell_config.frame_duplex_type.value == TDD && !get_softmodem_params()->continuous_tx && !IS_SOFTMODEM_RFSIM) { int slot_type = nr_slot_select(cfg,frame,slot%fp->slots_per_frame); if(slot_type == NR_MIXED_SLOT) { int txsymb = 0; From d868e2d7cc4b7a0ce2158654661fc1f9d29f9f90 Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 30 Jun 2025 14:50:43 +0200 Subject: [PATCH 153/964] DLSCH RB extraction bugfix: check DMRS bitmap only in DMRS symbols --- .../PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c index d266d443e9..b1e33054ba 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c @@ -1122,13 +1122,16 @@ static void nr_dlsch_extract_rbs(uint32_t rxdataF_sz, AssertFatal(n_dmrs_cdm_groups == 1 || n_dmrs_cdm_groups == 2 || n_dmrs_cdm_groups == 3, "n_dmrs_cdm_groups %d is illegal\n",n_dmrs_cdm_groups); - uint32_t dmrs_rb_bitmap = 0xfff; // all REs taken by dmrs - if (config_type == NFAPI_NR_DMRS_TYPE1 && n_dmrs_cdm_groups == 1) - dmrs_rb_bitmap = 0x555; // alternating REs starting from 0 - if (config_type == NFAPI_NR_DMRS_TYPE2 && n_dmrs_cdm_groups == 1) - dmrs_rb_bitmap = 0xc3; // REs 0,1 and 6,7 - if (config_type == NFAPI_NR_DMRS_TYPE2 && n_dmrs_cdm_groups == 2) - dmrs_rb_bitmap = 0x3cf; // REs 0,1,2,3 and 6,7,8,9 + uint32_t dmrs_rb_bitmap = 0; + if (pilots) { + dmrs_rb_bitmap = 0xfff; // all REs taken by dmrs + if (config_type == NFAPI_NR_DMRS_TYPE1 && n_dmrs_cdm_groups == 1) + dmrs_rb_bitmap = 0x555; // alternating REs starting from 0 + if (config_type == NFAPI_NR_DMRS_TYPE2 && n_dmrs_cdm_groups == 1) + dmrs_rb_bitmap = 0xc3; // REs 0,1 and 6,7 + if (config_type == NFAPI_NR_DMRS_TYPE2 && n_dmrs_cdm_groups == 2) + dmrs_rb_bitmap = 0x3cf; // REs 0,1,2,3 and 6,7,8,9 + } // csi_res_bitmap LS 16 bits for even RBs, MS 16 bits for odd RBs uint32_t csi_res_even = csi_res_bitmap & 0xfff; From b238c196ea396d6bea69c943445d4efb507f9016 Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 3 Jun 2025 17:16:02 +0200 Subject: [PATCH 154/964] take into account no UE case for get_pdsch_bwp_start_size --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index cb3c1bf801..2519ab59c9 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -386,10 +386,14 @@ void abort_nr_dl_harq(NR_UE_info_t* UE, int8_t harq_pid) static bwp_info_t get_pdsch_bwp_start_size(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE) { + bwp_info_t bwp_info; + if (!UE) { + bwp_info.bwpStart = nr_mac->cset0_bwp_start; + bwp_info.bwpSize = nr_mac->cset0_bwp_size; + return bwp_info; + } NR_UE_DL_BWP_t *dl_bwp = &UE->current_DL_BWP; NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; - bwp_info_t bwp_info; - // 3GPP TS 38.214 Section 5.1.2.2 Resource allocation in frequency domain // For a PDSCH scheduled with a DCI format 1_0 in any type of PDCCH common search space, regardless of which bandwidth part is the // active bandwidth part, RB numbering starts from the lowest RB of the CORESET in which the DCI was received; otherwise RB From ed303aa4d3c4d44ba9528db9518988a2f090bb44 Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 3 Jun 2025 18:01:37 +0200 Subject: [PATCH 155/964] extend the use of sched_pdsch in SIB functions --- .../LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c index bb8aea43fe..8f517115f5 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c @@ -360,6 +360,8 @@ static uint32_t schedule_control_sib1(gNB_MAC_INST *gNB_mac, pdsch->time_domain_allocation = time_domain_allocation; pdsch->dmrs_parms = *dmrs_parms; pdsch->tda_info = *tda_info; + pdsch->nrOfLayers = 1; + pdsch->pm_index = 0; pdsch->mcs = 0; // starting from mcs 0 gNB_mac->sched_ctrlCommon->num_total_bytes = num_total_bytes; @@ -386,6 +388,9 @@ static uint32_t schedule_control_sib1(gNB_MAC_INST *gNB_mac, gNB_mac->sched_ctrlCommon->num_total_bytes, vrb_map); + pdsch->R = nr_get_code_rate_dl(pdsch->mcs, 0); + pdsch->Qm = nr_get_Qm_dl(pdsch->mcs, 0); + // Mark the corresponding RBs as used fill_pdcch_vrb_map(gNB_mac, CC_id, @@ -410,14 +415,11 @@ static void nr_fill_nfapi_dl_SIB_pdu(gNB_MAC_INST *gNB_mac, int pdu_index, NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config, uint32_t TBS, - int StartSymbolIndex, - int NrOfSymbols, bool is_sib1, int beam_index) { NR_COMMON_channels_t *cc = gNB_mac->common_channels; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; - int mcsTableIdx = 0; nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdcch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs]; memset(dl_tti_pdcch_pdu, 0, sizeof(*dl_tti_pdcch_pdu)); @@ -453,10 +455,10 @@ static void nr_fill_nfapi_dl_SIB_pdu(gNB_MAC_INST *gNB_mac, pdsch_pdu_rel15->CyclicPrefix = 0; pdsch_pdu_rel15->NrOfCodewords = 1; - pdsch_pdu_rel15->targetCodeRate[0] = nr_get_code_rate_dl(pdsch->mcs, mcsTableIdx); - pdsch_pdu_rel15->qamModOrder[0] = nr_get_Qm_dl(pdsch->mcs, mcsTableIdx); + pdsch_pdu_rel15->targetCodeRate[0] = pdsch->R; + pdsch_pdu_rel15->qamModOrder[0] = pdsch->Qm; pdsch_pdu_rel15->mcsIndex[0] = pdsch->mcs; - pdsch_pdu_rel15->mcsTable[0] = mcsTableIdx; + pdsch_pdu_rel15->mcsTable[0] = 0; pdsch_pdu_rel15->rvIndex[0] = nr_get_rv(0); pdsch_pdu_rel15->dataScramblingId = *scc->physCellId; pdsch_pdu_rel15->nrOfLayers = 1; @@ -472,8 +474,8 @@ static void nr_fill_nfapi_dl_SIB_pdu(gNB_MAC_INST *gNB_mac, pdsch_pdu_rel15->rbSize = pdsch->rbSize; pdsch_pdu_rel15->VRBtoPRBMapping = 0; pdsch_pdu_rel15->TBSize[0] = TBS; - pdsch_pdu_rel15->StartSymbolIndex = StartSymbolIndex; - pdsch_pdu_rel15->NrOfSymbols = NrOfSymbols; + pdsch_pdu_rel15->StartSymbolIndex = pdsch->tda_info.startSymbolIndex; + pdsch_pdu_rel15->NrOfSymbols = pdsch->tda_info.nrOfSymbols; pdsch_pdu_rel15->dlDmrsSymbPos = pdsch->dmrs_parms.dl_dmrs_symb_pos; LOG_D(NR_MAC, @@ -657,8 +659,6 @@ void schedule_nr_sib1(module_id_t module_idP, pdu_index, type0_PDCCH_CSS_config, TBS, - tda_info.startSymbolIndex, - tda_info.nrOfSymbols, true, beam_index); @@ -766,12 +766,16 @@ static void other_sib_sched_control(module_id_t module_idP, sched_pdsch_otherSI.time_domain_allocation = time_domain_allocation; sched_pdsch_otherSI.dmrs_parms = dmrs_parms; sched_pdsch_otherSI.tda_info = tda_info; + sched_pdsch_otherSI.nrOfLayers = 1; + sched_pdsch_otherSI.pm_index = 0; sched_pdsch_otherSI.mcs = 0; // starting from mcs 0 uint16_t *vrb_map = cc->vrb_map[beam.idx]; uint8_t *sib_bcch_pdu = cc->other_sib_bcch_pdu[payload_idx]; int num_total_bytes = cc->other_sib_bcch_length[payload_idx]; uint32_t TBS = get_tbs_bch(type0_PDCCH_CSS_config, &sched_pdsch_otherSI, num_total_bytes, vrb_map); + sched_pdsch_otherSI.R = nr_get_code_rate_dl(sched_pdsch_otherSI.mcs, 0); + sched_pdsch_otherSI.Qm = nr_get_Qm_dl(sched_pdsch_otherSI.mcs, 0); for (int rb = 0; rb < sched_pdsch_otherSI.rbSize; rb++) { vrb_map[rb + type0_PDCCH_CSS_config->cset_start_rb] |= SL_to_bitmap(tda_info.startSymbolIndex, tda_info.nrOfSymbols); @@ -790,8 +794,6 @@ static void other_sib_sched_control(module_id_t module_idP, pdu_index, type0_PDCCH_CSS_config, TBS, - tda_info.startSymbolIndex, - tda_info.nrOfSymbols, false, beam_index); From 3b6b6e018dc0d20b688dca2c5f447125ee973fd2 Mon Sep 17 00:00:00 2001 From: francescomani Date: Wed, 4 Jun 2025 10:13:39 +0200 Subject: [PATCH 156/964] improve PDSCH DMRS structure with additional information --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 4 ++-- .../LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c | 4 ++-- .../LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 11 ++++------ .../NR_MAC_gNB/gNB_scheduler_primitives.c | 22 +++++++++++-------- openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 3 +++ 5 files changed, 24 insertions(+), 20 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index e398da1eaf..fa3b1e8c8d 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -1416,8 +1416,8 @@ static void prepare_dl_pdus(gNB_MAC_INST *nr_mac, pdsch_pdu_rel15->transmissionScheme = 0; pdsch_pdu_rel15->refPoint = 0; pdsch_pdu_rel15->dmrsConfigType = dmrs_info.dmrsConfigType; - pdsch_pdu_rel15->dlDmrsScramblingId = *scc->physCellId; - pdsch_pdu_rel15->SCID = 0; + pdsch_pdu_rel15->dlDmrsScramblingId = dmrs_info.scrambling_id; + pdsch_pdu_rel15->SCID = dmrs_info.n_scid; pdsch_pdu_rel15->numDmrsCdmGrpsNoData = dmrs_info.numDmrsCdmGrpsNoData; pdsch_pdu_rel15->dmrsPorts = 1; pdsch_pdu_rel15->resourceAlloc = 1; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c index 8f517115f5..b89def219b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c @@ -465,8 +465,8 @@ static void nr_fill_nfapi_dl_SIB_pdu(gNB_MAC_INST *gNB_mac, pdsch_pdu_rel15->transmissionScheme = 0; pdsch_pdu_rel15->refPoint = is_sib1; pdsch_pdu_rel15->dmrsConfigType = 0; - pdsch_pdu_rel15->dlDmrsScramblingId = *scc->physCellId; - pdsch_pdu_rel15->SCID = 0; + pdsch_pdu_rel15->dlDmrsScramblingId = pdsch->dmrs_parms.scrambling_id; + pdsch_pdu_rel15->SCID = pdsch->dmrs_parms.n_scid; pdsch_pdu_rel15->numDmrsCdmGrpsNoData = pdsch->dmrs_parms.numDmrsCdmGrpsNoData; pdsch_pdu_rel15->dmrsPorts = 1; pdsch_pdu_rel15->resourceAlloc = 1; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index 2519ab59c9..c887aaae88 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -1097,8 +1097,8 @@ void nr_schedule_ue_spec(module_id_t module_id, // DMRS pdsch_pdu->dlDmrsSymbPos = dmrs_parms->dl_dmrs_symb_pos; pdsch_pdu->dmrsConfigType = dmrs_parms->dmrsConfigType; - pdsch_pdu->dlDmrsScramblingId = *scc->physCellId; - pdsch_pdu->SCID = 0; + pdsch_pdu->dlDmrsScramblingId = dmrs_parms->scrambling_id; + pdsch_pdu->SCID = dmrs_parms->n_scid; pdsch_pdu->numDmrsCdmGrpsNoData = dmrs_parms->numDmrsCdmGrpsNoData; pdsch_pdu->dmrsPorts = (1<pdsch_Config; /* Check and validate PTRS values */ - struct NR_SetupRelease_PTRS_DownlinkConfig *phaseTrackingRS = - pdsch_Config ? pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS : NULL; - - if (phaseTrackingRS) { - bool valid_ptrs_setup = set_dl_ptrs_values(phaseTrackingRS->choice.setup, + if (dmrs_parms->phaseTrackingRS) { + bool valid_ptrs_setup = set_dl_ptrs_values(dmrs_parms->phaseTrackingRS, pdsch_pdu->rbSize, pdsch_pdu->mcsIndex[0], pdsch_pdu->mcsTable[0], diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index a447d9f91c..102c06bb49 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -300,8 +300,7 @@ NR_pdsch_dmrs_t get_dl_dmrs_params(const NR_ServingCellConfigCommon_t *scc, if (dci_format == NR_DL_DCI_FORMAT_1_0) { dmrs.numDmrsCdmGrpsNoData = tda_info->nrOfSymbols <= 2 ? 1 : 2; dmrs.dmrs_ports_id = 0; - } - else { + } else { //TODO first basic implementation of dmrs port selection // only vaild for a single codeword // for now it assumes a selection of Nl consecutive dmrs ports @@ -346,16 +345,21 @@ NR_pdsch_dmrs_t get_dl_dmrs_params(const NR_ServingCellConfigCommon_t *scc, } } + dmrs.n_scid = 0; + long *scramblingID = NULL; NR_PDSCH_Config_t *pdsch_Config = dl_bwp ? dl_bwp->pdsch_Config : NULL; if (pdsch_Config) { - if (tda_info->mapping_type == typeB) - dmrs.dmrsConfigType = pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeB->choice.setup->dmrs_Type != NULL; - else - dmrs.dmrsConfigType = pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type != NULL; - } - else + NR_DMRS_DownlinkConfig_t *dmrs_Config = tda_info->mapping_type == typeB ? + pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeB->choice.setup : + pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup; + dmrs.phaseTrackingRS = dmrs_Config->phaseTrackingRS ? dmrs_Config->phaseTrackingRS->choice.setup : NULL; + dmrs.dmrsConfigType = dmrs_Config->dmrs_Type != NULL; + scramblingID = dmrs.n_scid ? dmrs_Config->scramblingID1 : dmrs_Config->scramblingID0; + } else { dmrs.dmrsConfigType = NFAPI_NR_DMRS_TYPE1; - + dmrs.phaseTrackingRS = NULL; + } + dmrs.scrambling_id = scramblingID ? *scramblingID : *scc->physCellId; dmrs.N_PRB_DMRS = dmrs.numDmrsCdmGrpsNoData * (dmrs.dmrsConfigType == NFAPI_NR_DMRS_TYPE1 ? 6 : 4); dmrs.dl_dmrs_symb_pos = fill_dmrs_mask(pdsch_Config, dci_format, scc->dmrs_TypeA_Position, tda_info->nrOfSymbols, tda_info->startSymbolIndex, tda_info->mapping_type, frontloaded_symb); dmrs.N_DMRS_SLOT = get_num_dmrs(dmrs.dl_dmrs_symb_pos); diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 3918e0215c..239e0457f1 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -436,7 +436,10 @@ typedef struct NR_pdsch_dmrs { uint8_t N_DMRS_SLOT; uint16_t dl_dmrs_symb_pos; uint8_t numDmrsCdmGrpsNoData; + uint32_t scrambling_id; + int n_scid; nfapi_nr_dmrs_type_e dmrsConfigType; + NR_PTRS_DownlinkConfig_t *phaseTrackingRS; } NR_pdsch_dmrs_t; typedef struct NR_sched_pdsch { From 1eebd70cf35bf7f75649f7d20fdb43607643993e Mon Sep 17 00:00:00 2001 From: francescomani Date: Wed, 4 Jun 2025 12:51:46 +0200 Subject: [PATCH 157/964] use sched_pdsch in RA DL functions --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 85 ++++++++++--------- 1 file changed, 47 insertions(+), 38 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index fa3b1e8c8d..048fa29457 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -1342,10 +1342,9 @@ static bool msg2_in_response_window(int rach_frame, static void prepare_dl_pdus(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE, + NR_sched_pdsch_t *sched_pdsch, nfapi_nr_dl_tti_request_body_t *dl_req, NR_sched_pucch_t *pucch, - NR_pdsch_dmrs_t dmrs_info, - NR_tda_info_t tda, nr_rnti_type_t rnti_type, int aggregation_level, int CCEIndex, @@ -1358,13 +1357,10 @@ static void prepare_dl_pdus(gNB_MAC_INST *nr_mac, int CC_id, int rnti, int round, - int mcsIndex, int tb_scaling, int pduindex, long BWPStart, - long BWPSize, - int rbStart, - int rbSize) + long BWPSize) { // look up the PDCCH PDU for this CC, BWP, and CORESET. If it does not exist, create it. This is especially // important if we have multiple RAs, and the DLSCH has to reuse them, so we need to mark them @@ -1403,32 +1399,30 @@ static void prepare_dl_pdus(gNB_MAC_INST *nr_mac, pdsch_pdu_rel15->SubcarrierSpacing = dl_bwp->scs; pdsch_pdu_rel15->CyclicPrefix = 0; pdsch_pdu_rel15->NrOfCodewords = 1; - int R = nr_get_code_rate_dl(mcsIndex, mcsTableIdx); - pdsch_pdu_rel15->targetCodeRate[0] = R; - int Qm = nr_get_Qm_dl(mcsIndex, mcsTableIdx); - pdsch_pdu_rel15->qamModOrder[0] = Qm; + pdsch_pdu_rel15->targetCodeRate[0] = sched_pdsch->R; + pdsch_pdu_rel15->qamModOrder[0] = sched_pdsch->Qm; pdsch_pdu_rel15->TBSize[0] = tb_size; - pdsch_pdu_rel15->mcsIndex[0] = mcsIndex; + pdsch_pdu_rel15->mcsIndex[0] = sched_pdsch->mcs; pdsch_pdu_rel15->mcsTable[0] = mcsTableIdx; pdsch_pdu_rel15->rvIndex[0] = nr_get_rv(round % 4); pdsch_pdu_rel15->dataScramblingId = *scc->physCellId; pdsch_pdu_rel15->nrOfLayers = 1; pdsch_pdu_rel15->transmissionScheme = 0; pdsch_pdu_rel15->refPoint = 0; - pdsch_pdu_rel15->dmrsConfigType = dmrs_info.dmrsConfigType; - pdsch_pdu_rel15->dlDmrsScramblingId = dmrs_info.scrambling_id; - pdsch_pdu_rel15->SCID = dmrs_info.n_scid; - pdsch_pdu_rel15->numDmrsCdmGrpsNoData = dmrs_info.numDmrsCdmGrpsNoData; + pdsch_pdu_rel15->dmrsConfigType = sched_pdsch->dmrs_parms.dmrsConfigType; + pdsch_pdu_rel15->dlDmrsScramblingId = sched_pdsch->dmrs_parms.scrambling_id; + pdsch_pdu_rel15->SCID = sched_pdsch->dmrs_parms.n_scid; + pdsch_pdu_rel15->numDmrsCdmGrpsNoData = sched_pdsch->dmrs_parms.numDmrsCdmGrpsNoData; pdsch_pdu_rel15->dmrsPorts = 1; pdsch_pdu_rel15->resourceAlloc = 1; - pdsch_pdu_rel15->rbStart = rbStart; - pdsch_pdu_rel15->rbSize = rbSize; + pdsch_pdu_rel15->rbStart = sched_pdsch->rbStart; + pdsch_pdu_rel15->rbSize = sched_pdsch->rbSize; pdsch_pdu_rel15->VRBtoPRBMapping = 0; - pdsch_pdu_rel15->StartSymbolIndex = tda.startSymbolIndex; - pdsch_pdu_rel15->NrOfSymbols = tda.nrOfSymbols; - pdsch_pdu_rel15->dlDmrsSymbPos = dmrs_info.dl_dmrs_symb_pos; + pdsch_pdu_rel15->StartSymbolIndex = sched_pdsch->tda_info.startSymbolIndex; + pdsch_pdu_rel15->NrOfSymbols = sched_pdsch->tda_info.nrOfSymbols; + pdsch_pdu_rel15->dlDmrsSymbPos = sched_pdsch->dmrs_parms.dl_dmrs_symb_pos; pdsch_pdu_rel15->maintenance_parms_v3.tbSizeLbrmBytes = nr_compute_tbslbrm(mcsTableIdx, UE->sc_info.dl_bw_tbslbrm, 1); - pdsch_pdu_rel15->maintenance_parms_v3.ldpcBaseGraph = get_BG(tb_size << 3, R); + pdsch_pdu_rel15->maintenance_parms_v3.ldpcBaseGraph = get_BG(tb_size << 3, sched_pdsch->R); pdsch_pdu_rel15->precodingAndBeamforming.num_prgs = 1; pdsch_pdu_rel15->precodingAndBeamforming.prg_size = 275; @@ -1683,11 +1677,9 @@ static void nr_generate_Msg2(module_id_t module_idP, NR_pdsch_dmrs_t dmrs_parms = get_dl_dmrs_params(scc, dl_bwp, &tda_info, 1); - uint8_t tb_scaling = 0; int R, Qm; uint32_t TBS = 0; - while (TBS < 9) { // min TBS for RAR is 9 bytes mcsIndex++; R = nr_get_code_rate_dl(mcsIndex, mcsTableIdx); @@ -1703,12 +1695,22 @@ static void nr_generate_Msg2(module_id_t module_idP, >> 3; // layers } + NR_sched_pdsch_t sched_pdsch = { + .R = R, + .Qm = Qm, + .mcs = mcsIndex, + .nrOfLayers = 1, + .dmrs_parms = dmrs_parms, + .tda_info = tda_info, + .pm_index = 0, + .rbStart = rbStart, + .rbSize = rbSize + }; prepare_dl_pdus(nr_mac, UE, + &sched_pdsch, dl_req, NULL, - dmrs_parms, - tda_info, TYPE_RA_RNTI_, aggregation_level, CCEIndex, @@ -1721,13 +1723,10 @@ static void nr_generate_Msg2(module_id_t module_idP, CC_id, ra->RA_rnti, 0, - mcsIndex, tb_scaling, pduindex, BWPStart, - BWPSize, - rbStart, - rbSize); + BWPSize); // DL TX request nfapi_nr_pdu_t *tx_req = &TX_req->pdu_list[TX_req->Number_of_PDUs]; @@ -1907,8 +1906,12 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, mcsIndex++; LOG_D(NR_MAC,"Calling nr_compute_tbs with N_PRB_DMRS %d, N_DMRS_SLOT %d\n",dmrs_info.N_PRB_DMRS,dmrs_info.N_DMRS_SLOT); tb_size = nr_compute_tbs(nr_get_Qm_dl(mcsIndex, mcsTableIdx), - nr_get_code_rate_dl(mcsIndex, mcsTableIdx), - rbSize, msg4_tda.nrOfSymbols, dmrs_info.N_PRB_DMRS * dmrs_info.N_DMRS_SLOT, 0, tb_scaling,1) >> 3; + nr_get_code_rate_dl(mcsIndex, mcsTableIdx), + rbSize, + msg4_tda.nrOfSymbols, + dmrs_info.N_PRB_DMRS * dmrs_info.N_DMRS_SLOT, + 0, + tb_scaling,1) >> 3; } while (tb_size < pdu_length && mcsIndex<=28); AssertFatal(tb_size >= pdu_length, "Cannot allocate %s\n", ra_type_str); @@ -2000,14 +2003,23 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, } rnti_t rnti = ra->ra_type == RA_4_STEP ? UE->rnti : ra->MsgB_rnti; - + NR_sched_pdsch_t sched_pdsch = { + .R = nr_get_code_rate_dl(mcsIndex, mcsTableIdx), + .Qm = nr_get_Qm_dl(mcsIndex, mcsTableIdx), + .mcs = mcsIndex, + .nrOfLayers = 1, + .dmrs_parms = dmrs_info, + .tda_info = msg4_tda, + .pm_index = 0, + .rbStart = rbStart, + .rbSize = rbSize + }; const int pduindex = nr_mac->pdu_index[CC_id]++; prepare_dl_pdus(nr_mac, UE, + &sched_pdsch, dl_req, pucch, - dmrs_info, - msg4_tda, TYPE_TC_RNTI_, aggregation_level, CCEIndex, @@ -2020,13 +2032,10 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, CC_id, rnti, harq->round, - mcsIndex, tb_scaling, pduindex, BWPStart, - BWPSize, - rbStart, - rbSize); + BWPSize); // Reset TPC to 0 dB to not request new gain multiple times before computing new value for SNR sched_ctrl->tpc1 = 1; From e64516d22217f187a0d00198e67591d4236226e5 Mon Sep 17 00:00:00 2001 From: francescomani Date: Wed, 4 Jun 2025 14:24:02 +0200 Subject: [PATCH 158/964] common function to generate FAPI PDSCH payload --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 57 ++---- .../LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c | 71 ++------ .../LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 171 ++++++++++-------- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 12 +- 4 files changed, 134 insertions(+), 177 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 048fa29457..c1ba7b57f9 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -1348,7 +1348,6 @@ static void prepare_dl_pdus(gNB_MAC_INST *nr_mac, nr_rnti_type_t rnti_type, int aggregation_level, int CCEIndex, - int tb_size, int ndi, int tpc, int delta_PRI, @@ -1384,51 +1383,21 @@ static void prepare_dl_pdus(gNB_MAC_INST *nr_mac, dl_tti_pdsch_pdu->PDUType = NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE; dl_tti_pdsch_pdu->PDUSize = (uint8_t)(2 + sizeof(nfapi_nr_dl_tti_pdsch_pdu)); dl_req->nPDUs += 1; - nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = &dl_tti_pdsch_pdu->pdsch_pdu.pdsch_pdu_rel15; NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id]; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; NR_UE_DL_BWP_t *dl_bwp = &UE->current_DL_BWP; - int mcsTableIdx = dl_bwp->mcsTableIdx; - - pdsch_pdu_rel15->pduBitmap = 0; - pdsch_pdu_rel15->rnti = rnti; - pdsch_pdu_rel15->pduIndex = pduindex; - pdsch_pdu_rel15->BWPSize = BWPSize; - pdsch_pdu_rel15->BWPStart = BWPStart; - pdsch_pdu_rel15->SubcarrierSpacing = dl_bwp->scs; - pdsch_pdu_rel15->CyclicPrefix = 0; - pdsch_pdu_rel15->NrOfCodewords = 1; - pdsch_pdu_rel15->targetCodeRate[0] = sched_pdsch->R; - pdsch_pdu_rel15->qamModOrder[0] = sched_pdsch->Qm; - pdsch_pdu_rel15->TBSize[0] = tb_size; - pdsch_pdu_rel15->mcsIndex[0] = sched_pdsch->mcs; - pdsch_pdu_rel15->mcsTable[0] = mcsTableIdx; - pdsch_pdu_rel15->rvIndex[0] = nr_get_rv(round % 4); - pdsch_pdu_rel15->dataScramblingId = *scc->physCellId; - pdsch_pdu_rel15->nrOfLayers = 1; - pdsch_pdu_rel15->transmissionScheme = 0; - pdsch_pdu_rel15->refPoint = 0; - pdsch_pdu_rel15->dmrsConfigType = sched_pdsch->dmrs_parms.dmrsConfigType; - pdsch_pdu_rel15->dlDmrsScramblingId = sched_pdsch->dmrs_parms.scrambling_id; - pdsch_pdu_rel15->SCID = sched_pdsch->dmrs_parms.n_scid; - pdsch_pdu_rel15->numDmrsCdmGrpsNoData = sched_pdsch->dmrs_parms.numDmrsCdmGrpsNoData; - pdsch_pdu_rel15->dmrsPorts = 1; - pdsch_pdu_rel15->resourceAlloc = 1; - pdsch_pdu_rel15->rbStart = sched_pdsch->rbStart; - pdsch_pdu_rel15->rbSize = sched_pdsch->rbSize; - pdsch_pdu_rel15->VRBtoPRBMapping = 0; - pdsch_pdu_rel15->StartSymbolIndex = sched_pdsch->tda_info.startSymbolIndex; - pdsch_pdu_rel15->NrOfSymbols = sched_pdsch->tda_info.nrOfSymbols; - pdsch_pdu_rel15->dlDmrsSymbPos = sched_pdsch->dmrs_parms.dl_dmrs_symb_pos; - pdsch_pdu_rel15->maintenance_parms_v3.tbSizeLbrmBytes = nr_compute_tbslbrm(mcsTableIdx, UE->sc_info.dl_bw_tbslbrm, 1); - pdsch_pdu_rel15->maintenance_parms_v3.ldpcBaseGraph = get_BG(tb_size << 3, sched_pdsch->R); - - pdsch_pdu_rel15->precodingAndBeamforming.num_prgs = 1; - pdsch_pdu_rel15->precodingAndBeamforming.prg_size = 275; - pdsch_pdu_rel15->precodingAndBeamforming.dig_bf_interfaces = 1; - pdsch_pdu_rel15->precodingAndBeamforming.prgs_list[0].pm_idx = 0; - pdsch_pdu_rel15->precodingAndBeamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = UE->UE_beam_index; + nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = prepare_pdsch_pdu(dl_tti_pdsch_pdu, + nr_mac, + UE, + sched_pdsch, + dl_bwp->pdsch_Config, + false, + round, + rnti, + UE->UE_beam_index, + 1, + pduindex); /* Fill PDCCH DL DCI PDU */ nfapi_nr_dl_dci_pdu_t *dci_pdu = &pdcch_pdu_rel15->dci_pdu[pdcch_pdu_rel15->numDlDci]; @@ -1703,6 +1672,7 @@ static void nr_generate_Msg2(module_id_t module_idP, .dmrs_parms = dmrs_parms, .tda_info = tda_info, .pm_index = 0, + .tb_size = TBS, .rbStart = rbStart, .rbSize = rbSize }; @@ -1714,7 +1684,6 @@ static void nr_generate_Msg2(module_id_t module_idP, TYPE_RA_RNTI_, aggregation_level, CCEIndex, - TBS, 0, 0, 0, @@ -2011,6 +1980,7 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, .dmrs_parms = dmrs_info, .tda_info = msg4_tda, .pm_index = 0, + .tb_size = tb_size, .rbStart = rbStart, .rbSize = rbSize }; @@ -2023,7 +1993,6 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, TYPE_TC_RNTI_, aggregation_level, CCEIndex, - tb_size, harq->ndi, sched_ctrl->tpc1, delta_PRI, diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c index b89def219b..79f601362c 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c @@ -414,7 +414,6 @@ static void nr_fill_nfapi_dl_SIB_pdu(gNB_MAC_INST *gNB_mac, nfapi_nr_dl_tti_request_body_t *dl_req, int pdu_index, NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config, - uint32_t TBS, bool is_sib1, int beam_index) { @@ -434,50 +433,18 @@ static void nr_fill_nfapi_dl_SIB_pdu(gNB_MAC_INST *gNB_mac, dl_tti_pdsch_pdu->PDUType = NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE; dl_tti_pdsch_pdu->PDUSize = (uint16_t)(4+sizeof(nfapi_nr_dl_tti_pdsch_pdu)); dl_req->nPDUs += 1; - nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = &dl_tti_pdsch_pdu->pdsch_pdu.pdsch_pdu_rel15; - - pdsch_pdu_rel15->precodingAndBeamforming.num_prgs = 0; - pdsch_pdu_rel15->precodingAndBeamforming.prg_size = 0; - pdsch_pdu_rel15->precodingAndBeamforming.dig_bf_interfaces = 1; - pdsch_pdu_rel15->precodingAndBeamforming.prgs_list[0].pm_idx = 0; - pdsch_pdu_rel15->precodingAndBeamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = beam_index; - - pdcch_pdu_rel15->CoreSetType = NFAPI_NR_CSET_CONFIG_MIB_SIB1; - - pdsch_pdu_rel15->pduBitmap = 0; - pdsch_pdu_rel15->rnti = SI_RNTI; - pdsch_pdu_rel15->pduIndex = pdu_index; - - pdsch_pdu_rel15->BWPSize = type0_PDCCH_CSS_config->num_rbs; - pdsch_pdu_rel15->BWPStart = type0_PDCCH_CSS_config->cset_start_rb; - - pdsch_pdu_rel15->SubcarrierSpacing = type0_PDCCH_CSS_config->scs_pdcch; - pdsch_pdu_rel15->CyclicPrefix = 0; - - pdsch_pdu_rel15->NrOfCodewords = 1; - pdsch_pdu_rel15->targetCodeRate[0] = pdsch->R; - pdsch_pdu_rel15->qamModOrder[0] = pdsch->Qm; - pdsch_pdu_rel15->mcsIndex[0] = pdsch->mcs; - pdsch_pdu_rel15->mcsTable[0] = 0; - pdsch_pdu_rel15->rvIndex[0] = nr_get_rv(0); - pdsch_pdu_rel15->dataScramblingId = *scc->physCellId; - pdsch_pdu_rel15->nrOfLayers = 1; - pdsch_pdu_rel15->transmissionScheme = 0; - pdsch_pdu_rel15->refPoint = is_sib1; - pdsch_pdu_rel15->dmrsConfigType = 0; - pdsch_pdu_rel15->dlDmrsScramblingId = pdsch->dmrs_parms.scrambling_id; - pdsch_pdu_rel15->SCID = pdsch->dmrs_parms.n_scid; - pdsch_pdu_rel15->numDmrsCdmGrpsNoData = pdsch->dmrs_parms.numDmrsCdmGrpsNoData; - pdsch_pdu_rel15->dmrsPorts = 1; - pdsch_pdu_rel15->resourceAlloc = 1; - pdsch_pdu_rel15->rbStart = pdsch->rbStart; - pdsch_pdu_rel15->rbSize = pdsch->rbSize; - pdsch_pdu_rel15->VRBtoPRBMapping = 0; - pdsch_pdu_rel15->TBSize[0] = TBS; - pdsch_pdu_rel15->StartSymbolIndex = pdsch->tda_info.startSymbolIndex; - pdsch_pdu_rel15->NrOfSymbols = pdsch->tda_info.nrOfSymbols; - pdsch_pdu_rel15->dlDmrsSymbPos = pdsch->dmrs_parms.dl_dmrs_symb_pos; + nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = prepare_pdsch_pdu(dl_tti_pdsch_pdu, + gNB_mac, + NULL, + pdsch, + NULL, + is_sib1, + 0, + SI_RNTI, + beam_index, + 1, + pdu_index); LOG_D(NR_MAC, "OtherSI:bwpStart %d, bwpSize %d, rbStart %d, rbSize %d, dlDmrsSymbPos = 0x%x\n", pdsch_pdu_rel15->BWPStart, @@ -486,11 +453,6 @@ static void nr_fill_nfapi_dl_SIB_pdu(gNB_MAC_INST *gNB_mac, pdsch_pdu_rel15->rbSize, pdsch_pdu_rel15->dlDmrsSymbPos); - pdsch_pdu_rel15->maintenance_parms_v3.tbSizeLbrmBytes = nr_compute_tbslbrm(0, - pdsch_pdu_rel15->BWPSize, - 1); - pdsch_pdu_rel15->maintenance_parms_v3.ldpcBaseGraph = get_BG(TBS<<3,pdsch_pdu_rel15->targetCodeRate[0]); - /* Fill PDCCH DL DCI PDU */ nfapi_nr_dl_dci_pdu_t *dci_pdu = &pdcch_pdu_rel15->dci_pdu[pdcch_pdu_rel15->numDlDci]; pdcch_pdu_rel15->numDlDci++; @@ -646,6 +608,7 @@ void schedule_nr_sib1(module_id_t module_idP, beam.idx, cc->sib1_bcch_length); + gNB_mac->sched_ctrlCommon->sched_pdsch.tb_size = TBS; nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body; int pdu_index = gNB_mac->pdu_index[0]++; nr_fill_nfapi_dl_SIB_pdu(gNB_mac, @@ -658,7 +621,6 @@ void schedule_nr_sib1(module_id_t module_idP, dl_req, pdu_index, type0_PDCCH_CSS_config, - TBS, true, beam_index); @@ -773,7 +735,7 @@ static void other_sib_sched_control(module_id_t module_idP, uint16_t *vrb_map = cc->vrb_map[beam.idx]; uint8_t *sib_bcch_pdu = cc->other_sib_bcch_pdu[payload_idx]; int num_total_bytes = cc->other_sib_bcch_length[payload_idx]; - uint32_t TBS = get_tbs_bch(type0_PDCCH_CSS_config, &sched_pdsch_otherSI, num_total_bytes, vrb_map); + sched_pdsch_otherSI.tb_size = get_tbs_bch(type0_PDCCH_CSS_config, &sched_pdsch_otherSI, num_total_bytes, vrb_map); sched_pdsch_otherSI.R = nr_get_code_rate_dl(sched_pdsch_otherSI.mcs, 0); sched_pdsch_otherSI.Qm = nr_get_Qm_dl(sched_pdsch_otherSI.mcs, 0); @@ -793,7 +755,6 @@ static void other_sib_sched_control(module_id_t module_idP, dl_req, pdu_index, type0_PDCCH_CSS_config, - TBS, false, beam_index); @@ -801,12 +762,12 @@ static void other_sib_sched_control(module_id_t module_idP, nfapi_nr_pdu_t *tx_req = &TX_req->pdu_list[ntx_req]; // Data to be transmitted - memcpy(tx_req->TLVs[0].value.direct, sib_bcch_pdu, TBS); + memcpy(tx_req->TLVs[0].value.direct, sib_bcch_pdu, sched_pdsch_otherSI.tb_size); - tx_req->PDU_length = TBS; + tx_req->PDU_length = sched_pdsch_otherSI.tb_size; tx_req->PDU_index = pdu_index; tx_req->num_TLV = 1; - tx_req->TLVs[0].length = TBS + 2; + tx_req->TLVs[0].length = sched_pdsch_otherSI.tb_size + 2; TX_req->Number_of_PDUs++; TX_req->SFN = frame; TX_req->Slot = slot; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index c887aaae88..9e0b9dfbd7 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -923,6 +923,85 @@ nr_pp_impl_dl nr_init_dlsch_preprocessor(int CC_id) { return nr_dlsch_preprocessor; } +nfapi_nr_dl_tti_pdsch_pdu_rel15_t *prepare_pdsch_pdu(nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu, + const gNB_MAC_INST *mac, + const NR_UE_info_t *UE, + const NR_sched_pdsch_t *sched_pdsch, + const NR_PDSCH_Config_t *pdsch_Config, + bool is_sib1, + int harq_round, + int rnti, + int beam_index, + int nl_tbslbrm, + int pdu_index) +{ + const NR_UE_DL_BWP_t *dl_bwp = UE ? &UE->current_DL_BWP : NULL; + const NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon; + nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu = &dl_tti_pdsch_pdu->pdsch_pdu.pdsch_pdu_rel15; + pdsch_pdu->pduBitmap = 0; + pdsch_pdu->rnti = rnti; + pdsch_pdu->pduIndex = pdu_index; + bwp_info_t bwp_info = get_pdsch_bwp_start_size(mac, UE); + pdsch_pdu->BWPSize = bwp_info.bwpSize; + pdsch_pdu->BWPStart = bwp_info.bwpStart; + pdsch_pdu->SubcarrierSpacing = dl_bwp ? dl_bwp->scs : *scc->ssbSubcarrierSpacing; + pdsch_pdu->CyclicPrefix = dl_bwp && dl_bwp->cyclicprefix ? *dl_bwp->cyclicprefix : 0; + // Codeword information + pdsch_pdu->NrOfCodewords = 1; + pdsch_pdu->targetCodeRate[0] = sched_pdsch->R; + pdsch_pdu->qamModOrder[0] = sched_pdsch->Qm; + pdsch_pdu->mcsIndex[0] = sched_pdsch->mcs; + pdsch_pdu->mcsTable[0] = dl_bwp ? dl_bwp->mcsTableIdx : 0; + pdsch_pdu->rvIndex[0] = nr_get_rv(harq_round % 4); + pdsch_pdu->TBSize[0] = sched_pdsch->tb_size; + pdsch_pdu->dataScramblingId = pdsch_Config && pdsch_Config->dataScramblingIdentityPDSCH ? *pdsch_Config->dataScramblingIdentityPDSCH : *scc->physCellId; + pdsch_pdu->nrOfLayers = sched_pdsch->nrOfLayers; + pdsch_pdu->transmissionScheme = 0; + pdsch_pdu->refPoint = is_sib1; + // DMRS + const NR_pdsch_dmrs_t *dmrs_parms = &sched_pdsch->dmrs_parms; + pdsch_pdu->dlDmrsSymbPos = dmrs_parms->dl_dmrs_symb_pos; + pdsch_pdu->dmrsConfigType = dmrs_parms->dmrsConfigType; + pdsch_pdu->SCID = dmrs_parms->n_scid; + pdsch_pdu->dlDmrsScramblingId = dmrs_parms->scrambling_id; + pdsch_pdu->numDmrsCdmGrpsNoData = dmrs_parms->numDmrsCdmGrpsNoData; + pdsch_pdu->dmrsPorts = (1 << sched_pdsch->nrOfLayers) - 1; // FIXME with a better implementation + // Pdsch Allocation in frequency domain + pdsch_pdu->resourceAlloc = 1; + pdsch_pdu->rbStart = sched_pdsch->rbStart; + pdsch_pdu->rbSize = sched_pdsch->rbSize; + pdsch_pdu->VRBtoPRBMapping = 0; // non-interleaved + // Resource Allocation in time domain + const NR_tda_info_t *tda_info = &sched_pdsch->tda_info; + pdsch_pdu->StartSymbolIndex = tda_info->startSymbolIndex; + pdsch_pdu->NrOfSymbols = tda_info->nrOfSymbols; + /* Check and validate PTRS values */ + if (dmrs_parms->phaseTrackingRS) { + bool valid_ptrs_setup = set_dl_ptrs_values(dmrs_parms->phaseTrackingRS, + pdsch_pdu->rbSize, + pdsch_pdu->mcsIndex[0], + pdsch_pdu->mcsTable[0], + &pdsch_pdu->PTRSFreqDensity, + &pdsch_pdu->PTRSTimeDensity, + &pdsch_pdu->PTRSPortIndex, + &pdsch_pdu->nEpreRatioOfPDSCHToPTRS, + &pdsch_pdu->PTRSReOffset, + pdsch_pdu->NrOfSymbols); + if (valid_ptrs_setup) + pdsch_pdu->pduBitmap |= 0x1; // Bit 0: pdschPtrs - Indicates PTRS included (FR2) + } + int dl_bw_tbslbrm = UE ? UE->sc_info.dl_bw_tbslbrm : bwp_info.bwpSize; + pdsch_pdu->maintenance_parms_v3.tbSizeLbrmBytes = nr_compute_tbslbrm(pdsch_pdu->mcsTable[0], dl_bw_tbslbrm, nl_tbslbrm); + pdsch_pdu->maintenance_parms_v3.ldpcBaseGraph = get_BG(sched_pdsch->tb_size << 3, sched_pdsch->R); + // Precoding and beamforming + pdsch_pdu->precodingAndBeamforming.num_prgs = 0; + pdsch_pdu->precodingAndBeamforming.prg_size = pdsch_pdu->rbSize; + pdsch_pdu->precodingAndBeamforming.dig_bf_interfaces = 0; + pdsch_pdu->precodingAndBeamforming.prgs_list[0].pm_idx = sched_pdsch->pm_index; + pdsch_pdu->precodingAndBeamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = beam_index; + return pdsch_pdu; +} + void nr_schedule_ue_spec(module_id_t module_id, frame_t frame, slot_t slot, @@ -974,8 +1053,6 @@ void nr_schedule_ue_spec(module_id_t module_id, /* POST processing */ const uint8_t nrOfLayers = sched_pdsch->nrOfLayers; - const uint16_t R = sched_pdsch->R; - const uint8_t Qm = sched_pdsch->Qm; const uint32_t TBS = sched_pdsch->tb_size; int8_t current_harq_pid = sched_pdsch->dl_harq_pid; @@ -1059,91 +1136,29 @@ void nr_schedule_ue_spec(module_id_t module_id, nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs]; memset(dl_tti_pdsch_pdu, 0, sizeof(nfapi_nr_dl_tti_request_pdu_t)); dl_tti_pdsch_pdu->PDUType = NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE; - dl_tti_pdsch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdsch_pdu)); + dl_tti_pdsch_pdu->PDUSize = (uint8_t)(2 + sizeof(nfapi_nr_dl_tti_pdsch_pdu)); dl_req->nPDUs += 1; - nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu = &dl_tti_pdsch_pdu->pdsch_pdu.pdsch_pdu_rel15; - pdsch_pdu->pduBitmap = 0; - pdsch_pdu->rnti = rnti; /* SCF222: PDU index incremented for each PDSCH PDU sent in TX control * message. This is used to associate control information to data and is * reset every slot. */ const int pduindex = gNB_mac->pdu_index[CC_id]++; - pdsch_pdu->pduIndex = pduindex; - - bwp_info_t bwp_info = get_pdsch_bwp_start_size(gNB_mac, UE); - pdsch_pdu->BWPSize = bwp_info.bwpSize; - pdsch_pdu->BWPStart = bwp_info.bwpStart; - - pdsch_pdu->SubcarrierSpacing = current_BWP->scs; - pdsch_pdu->CyclicPrefix = current_BWP->cyclicprefix ? *current_BWP->cyclicprefix : 0; - // Codeword information - pdsch_pdu->NrOfCodewords = 1; - //number of information bits per 1024 coded bits expressed in 0.1 bit units - pdsch_pdu->targetCodeRate[0] = R; - pdsch_pdu->qamModOrder[0] = Qm; - pdsch_pdu->mcsIndex[0] = sched_pdsch->mcs; - pdsch_pdu->mcsTable[0] = current_BWP->mcsTableIdx; - // NVIDIA: Workaround for MCSTableIdx mismatch error - if (nr_get_code_rate_dl(sched_pdsch->mcs, current_BWP->mcsTableIdx) != R) { - pdsch_pdu->mcsTable[0] = 0; - } - AssertFatal(harq->round < gNB_mac->dl_bler.harq_round_max,"%d", harq->round); - pdsch_pdu->rvIndex[0] = nr_get_rv(harq->round % 4); - pdsch_pdu->TBSize[0] = TBS; - pdsch_pdu->dataScramblingId = *scc->physCellId; - pdsch_pdu->nrOfLayers = nrOfLayers; - pdsch_pdu->transmissionScheme = 0; - pdsch_pdu->refPoint = 0; // Point A - // DMRS - pdsch_pdu->dlDmrsSymbPos = dmrs_parms->dl_dmrs_symb_pos; - pdsch_pdu->dmrsConfigType = dmrs_parms->dmrsConfigType; - pdsch_pdu->dlDmrsScramblingId = dmrs_parms->scrambling_id; - pdsch_pdu->SCID = dmrs_parms->n_scid; - pdsch_pdu->numDmrsCdmGrpsNoData = dmrs_parms->numDmrsCdmGrpsNoData; - pdsch_pdu->dmrsPorts = (1<resourceAlloc = 1; - pdsch_pdu->rbStart = sched_pdsch->rbStart; - pdsch_pdu->rbSize = sched_pdsch->rbSize; - pdsch_pdu->VRBtoPRBMapping = 1; // non-interleaved, check if this is ok for initialBWP - // Resource Allocation in time domain - pdsch_pdu->StartSymbolIndex = tda_info->startSymbolIndex; - pdsch_pdu->NrOfSymbols = tda_info->nrOfSymbols; - // Precoding - pdsch_pdu->precodingAndBeamforming.num_prgs = 0; - pdsch_pdu->precodingAndBeamforming.prg_size = pdsch_pdu->rbSize; - pdsch_pdu->precodingAndBeamforming.dig_bf_interfaces = 0; - pdsch_pdu->precodingAndBeamforming.prgs_list[0].pm_idx = sched_pdsch->pm_index; - pdsch_pdu->precodingAndBeamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = UE->UE_beam_index; - // TBS_LBRM according to section 5.4.2.1 of 38.212 // TODO: verify the case where maxMIMO_Layers is NULL, in which case // in principle maxMIMO_layers should be given by the maximum number of layers // for PDSCH supported by the UE for the serving cell (5.4.2.1 of 38.212) long maxMIMO_Layers = UE->sc_info.maxMIMO_Layers_PDSCH ? *UE->sc_info.maxMIMO_Layers_PDSCH : 1; const int nl_tbslbrm = min(maxMIMO_Layers, 4); - // Maximum number of PRBs across all configured DL BWPs - pdsch_pdu->maintenance_parms_v3.tbSizeLbrmBytes = - nr_compute_tbslbrm(current_BWP->mcsTableIdx, UE->sc_info.dl_bw_tbslbrm, nl_tbslbrm); - pdsch_pdu->maintenance_parms_v3.ldpcBaseGraph = get_BG(TBS<<3,R); + nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu = prepare_pdsch_pdu(dl_tti_pdsch_pdu, + gNB_mac, + UE, + sched_pdsch, + current_BWP->pdsch_Config, + false, + harq->round, + rnti, + UE->UE_beam_index, + nl_tbslbrm, + pduindex); - NR_PDSCH_Config_t *pdsch_Config = current_BWP->pdsch_Config; - - /* Check and validate PTRS values */ - if (dmrs_parms->phaseTrackingRS) { - bool valid_ptrs_setup = set_dl_ptrs_values(dmrs_parms->phaseTrackingRS, - pdsch_pdu->rbSize, - pdsch_pdu->mcsIndex[0], - pdsch_pdu->mcsTable[0], - &pdsch_pdu->PTRSFreqDensity, - &pdsch_pdu->PTRSTimeDensity, - &pdsch_pdu->PTRSPortIndex, - &pdsch_pdu->nEpreRatioOfPDSCHToPTRS, - &pdsch_pdu->PTRSReOffset, - pdsch_pdu->NrOfSymbols); - - if (valid_ptrs_setup) - pdsch_pdu->pduBitmap |= 0x1; // Bit 0: pdschPtrs - Indicates PTRS included (FR2) - } LOG_D(NR_MAC,"Configuring DCI/PDCCH in %d.%d at CCE %d, rnti %x\n", frame,slot,sched_ctrl->cce_index,rnti); /* Fill PDCCH DL DCI PDU */ @@ -1180,7 +1195,9 @@ void nr_schedule_ue_spec(module_id_t module_id, // as per table 7.3.1.1.2-1 in 38.212 dci_payload.bwp_indicator.val = UE->sc_info.n_dl_bwp < 4 ? bwp_id : bwp_id - 1; - AssertFatal(pdsch_Config == NULL || pdsch_Config->resourceAllocation == NR_PDSCH_Config__resourceAllocation_resourceAllocationType1, + NR_PDSCH_Config_t *pdsch_Config = current_BWP->pdsch_Config; + AssertFatal(pdsch_Config == NULL + || pdsch_Config->resourceAllocation == NR_PDSCH_Config__resourceAllocation_resourceAllocationType1, "Only frequency resource allocation type 1 is currently supported\n"); // 3GPP TS 38.214 Section 5.1.2.2.2 Downlink resource allocation type 1 diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 6acf4ae1d8..527b733c02 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -323,7 +323,17 @@ void nr_check_Msg4_MsgB_Ack(module_id_t module_id, frame_t frame, slot_t slot, N void mac_remove_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rnti); NR_UE_info_t *get_new_nr_ue_inst(uid_allocator_t *uia, rnti_t rnti, NR_CellGroupConfig_t *CellGroup); int nr_get_default_pucch_res(int pucch_ResourceCommon); - +nfapi_nr_dl_tti_pdsch_pdu_rel15_t *prepare_pdsch_pdu(nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu, + const gNB_MAC_INST *mac, + const NR_UE_info_t *UE, + const NR_sched_pdsch_t *sched_pdsch, + const NR_PDSCH_Config_t *pdsch_Config, + bool is_sib1, + int harq_round, + int rnti, + int beam_index, + int nl_tbslbrm, + int pdu_index); int nr_write_ce_dlsch_pdu(module_id_t module_idP, const NR_UE_sched_ctrl_t *ue_sched_ctl, unsigned char *mac_pdu, From 548d6ec3a1fb2fd1cc2117b73a985d766ade55ad Mon Sep 17 00:00:00 2001 From: francescomani Date: Wed, 4 Jun 2025 15:44:19 +0200 Subject: [PATCH 159/964] include BWP info in sched_pdsch and use also for RA and BCH --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 68 ++++++------------- .../LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c | 14 ++-- .../LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 16 ++--- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 2 +- openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 2 +- 5 files changed, 38 insertions(+), 64 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index c1ba7b57f9..03f794473b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -1357,9 +1357,7 @@ static void prepare_dl_pdus(gNB_MAC_INST *nr_mac, int rnti, int round, int tb_scaling, - int pduindex, - long BWPStart, - long BWPSize) + int pduindex) { // look up the PDCCH PDU for this CC, BWP, and CORESET. If it does not exist, create it. This is especially // important if we have multiple RAs, and the DLSCH has to reuse them, so we need to mark them @@ -1419,7 +1417,7 @@ static void prepare_dl_pdus(gNB_MAC_INST *nr_mac, dci_pdu_rel15_t dci_payload; dci_payload.frequency_domain_assignment.val = PRBalloc_to_locationandbandwidth0(pdsch_pdu_rel15->rbSize, pdsch_pdu_rel15->rbStart, - BWPSize); + pdsch_pdu_rel15->BWPSize); dci_payload.time_domain_assignment.val = time_domain_assignment; dci_payload.vrb_to_prb_mapping.val = 0; @@ -1507,7 +1505,6 @@ static void nr_generate_Msg2(module_id_t module_idP, NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id]; NR_UE_DL_BWP_t *dl_bwp = &UE->current_DL_BWP; - NR_UE_ServingCell_Info_t *sc_info = &UE->sc_info; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; NR_RA_t *ra = UE->ra; long rrc_ra_ResponseWindow = @@ -1548,23 +1545,14 @@ static void nr_generate_Msg2(module_id_t module_idP, int mcsIndex = -1; // initialization value int rbStart = 0; int rbSize = 8; - long BWPStart = 0; - long BWPSize = 0; - NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config = NULL; - if (*ss->controlResourceSetId != 0) { - BWPStart = dl_bwp->BWPStart; - BWPSize = sc_info->initial_dl_BWPSize; - } else { - type0_PDCCH_CSS_config = &nr_mac->type0_PDCCH_CSS_config[cc->ssb_index[UE->UE_beam_index]]; - BWPStart = type0_PDCCH_CSS_config->cset_start_rb; - BWPSize = type0_PDCCH_CSS_config->num_rbs; - } - + bwp_info_t bwp_info = get_pdsch_bwp_start_size(nr_mac, UE); NR_ControlResourceSet_t *coreset = sched_ctrl->coreset; AssertFatal(coreset, "Coreset cannot be null for RA-Msg2\n"); const int coresetid = coreset->controlResourceSetId; // Calculate number of symbols int time_domain_assignment = get_dl_tda(nr_mac, slotP); + + NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config = &nr_mac->type0_PDCCH_CSS_config[cc->ssb_index[UE->UE_beam_index]]; int mux_pattern = type0_PDCCH_CSS_config ? type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern : 1; NR_tda_info_t tda_info = get_dl_tda_info(dl_bwp, ss->searchSpaceType->present, @@ -1578,14 +1566,14 @@ static void nr_generate_Msg2(module_id_t module_idP, return; uint16_t *vrb_map = cc[CC_id].vrb_map[beam.idx]; - for (int i = 0; (i < rbSize) && (rbStart <= (BWPSize - rbSize)); i++) { - if (vrb_map[BWPStart + rbStart + i] & SL_to_bitmap(tda_info.startSymbolIndex, tda_info.nrOfSymbols)) { + for (int i = 0; (i < rbSize) && (rbStart <= (bwp_info.bwpSize - rbSize)); i++) { + if (vrb_map[bwp_info.bwpStart + rbStart + i] & SL_to_bitmap(tda_info.startSymbolIndex, tda_info.nrOfSymbols)) { rbStart += i; i = 0; } } - if (rbStart > (BWPSize - rbSize)) { + if (rbStart > (bwp_info.bwpSize - rbSize)) { LOG_W(NR_MAC, "Cannot find free vrb_map for RA RNTI %04x!\n", ra->RA_rnti); reset_beam_status(&nr_mac->beam_info, ra->Msg3_frame, ra->Msg3_slot, UE->UE_beam_index, n_slots_frame, ra->Msg3_beam.new_beam); reset_beam_status(&nr_mac->beam_info, frameP, slotP, UE->UE_beam_index, n_slots_frame, beam.new_beam); @@ -1673,6 +1661,7 @@ static void nr_generate_Msg2(module_id_t module_idP, .tda_info = tda_info, .pm_index = 0, .tb_size = TBS, + .bwp_info = bwp_info, .rbStart = rbStart, .rbSize = rbSize }; @@ -1693,9 +1682,7 @@ static void nr_generate_Msg2(module_id_t module_idP, ra->RA_rnti, 0, tb_scaling, - pduindex, - BWPStart, - BWPSize); + pduindex); // DL TX request nfapi_nr_pdu_t *tx_req = &TX_req->pdu_list[TX_req->Number_of_PDUs]; @@ -1742,7 +1729,7 @@ static void nr_generate_Msg2(module_id_t module_idP, // Mark the corresponding symbols RBs as used fill_pdcch_vrb_map(nr_mac, CC_id, &sched_ctrl->sched_pdcch, CCEIndex, aggregation_level, beam.idx); for (int rb = 0; rb < rbSize; rb++) { - vrb_map[BWPStart + rb + rbStart] |= SL_to_bitmap(tda_info.startSymbolIndex, tda_info.nrOfSymbols); + vrb_map[bwp_info.bwpStart + rb + rbStart] |= SL_to_bitmap(tda_info.startSymbolIndex, tda_info.nrOfSymbols); } ra->ra_state = nrRA_WAIT_Msg3; @@ -1796,18 +1783,6 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, if (beam.idx < 0) return; - long BWPStart = 0; - long BWPSize = 0; - NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config = NULL; - if(*ss->controlResourceSetId!=0) { - BWPStart = dl_bwp->BWPStart; - BWPSize = dl_bwp->BWPSize; - } else { - type0_PDCCH_CSS_config = &nr_mac->type0_PDCCH_CSS_config[cc->ssb_index[UE->UE_beam_index]]; - BWPStart = type0_PDCCH_CSS_config->cset_start_rb; - BWPSize = type0_PDCCH_CSS_config->num_rbs; - } - // get CCEindex, needed also for PUCCH and then later for PDCCH uint8_t aggregation_level; int CCEIndex = get_cce_index(nr_mac, @@ -1835,6 +1810,7 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, } uint8_t time_domain_assignment = get_dl_tda(nr_mac, slotP); + NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config = &nr_mac->type0_PDCCH_CSS_config[cc->ssb_index[UE->UE_beam_index]]; int mux_pattern = type0_PDCCH_CSS_config ? type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern : 1; NR_tda_info_t msg4_tda = get_dl_tda_info(dl_bwp, ss->searchSpaceType->present, @@ -1848,7 +1824,7 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, return; NR_pdsch_dmrs_t dmrs_info = get_dl_dmrs_params(scc, dl_bwp, &msg4_tda, 1); - + bwp_info_t bwp_info = get_pdsch_bwp_start_size(nr_mac, UE); uint8_t mcsTableIdx = dl_bwp->mcsTableIdx; uint8_t mcsIndex = 0; int rbStart = 0; @@ -1860,8 +1836,7 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, NR_UE_harq_t *harq = &sched_ctrl->harq_processes[current_harq_pid]; DevAssert(!harq->is_waiting); pdu_length = harq->tb_size; - } - else { + } else { uint8_t subheader_len = (mac_sdu_length < 256) ? sizeof(NR_MAC_SUBHEADER_SHORT) : sizeof(NR_MAC_SUBHEADER_LONG); pdu_length = mac_sdu_length + subheader_len + 13; // 13 is contention resolution length of msgB. It is divided into 3 parts: // BI MAC subheader (1 Oct) + SuccessRAR MAC subheader (1 Oct) + SuccessRAR (11 Oct) @@ -1869,7 +1844,7 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, // increase PRBs until we get to BWPSize or TBS is bigger than MAC PDU size do { - if(rbSize < BWPSize) + if(rbSize < bwp_info.bwpSize) rbSize++; else mcsIndex++; @@ -1887,8 +1862,8 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, int i = 0; uint16_t *vrb_map = cc[CC_id].vrb_map[beam.idx]; - while ((i < rbSize) && (rbStart + rbSize <= BWPSize)) { - if (vrb_map[BWPStart + rbStart + i]&SL_to_bitmap(msg4_tda.startSymbolIndex, msg4_tda.nrOfSymbols)) { + while ((i < rbSize) && (rbStart + rbSize <= bwp_info.bwpSize)) { + if (vrb_map[bwp_info.bwpStart + rbStart + i]&SL_to_bitmap(msg4_tda.startSymbolIndex, msg4_tda.nrOfSymbols)) { rbStart += i+1; i = 0; } else { @@ -1896,7 +1871,7 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, } } - if (rbStart > (BWPSize - rbSize)) { + if (rbStart > (bwp_info.bwpSize - rbSize)) { LOG_E(NR_MAC, "Cannot find free vrb_map for RNTI %04x!\n", UE->rnti); reset_beam_status(&nr_mac->beam_info, frameP, slotP, UE->UE_beam_index, n_slots_frame, beam.new_beam); return; @@ -1981,6 +1956,7 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, .tda_info = msg4_tda, .pm_index = 0, .tb_size = tb_size, + .bwp_info = bwp_info, .rbStart = rbStart, .rbSize = rbSize }; @@ -2002,9 +1978,7 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, rnti, harq->round, tb_scaling, - pduindex, - BWPStart, - BWPSize); + pduindex); // Reset TPC to 0 dB to not request new gain multiple times before computing new value for SNR sched_ctrl->tpc1 = 1; @@ -2041,7 +2015,7 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, aggregation_level, beam.idx); for (int rb = 0; rb < rbSize; rb++) { - vrb_map[BWPStart + rb + rbStart] |= SL_to_bitmap(msg4_tda.startSymbolIndex, msg4_tda.nrOfSymbols); + vrb_map[bwp_info.bwpStart + rb + rbStart] |= SL_to_bitmap(msg4_tda.startSymbolIndex, msg4_tda.nrOfSymbols); } ra->ra_state = nrRA_WAIT_Msg4_MsgB_ACK; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c index 79f601362c..974cb9f3f1 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c @@ -274,8 +274,7 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, slot_t slotP, nfapi } } -static uint32_t get_tbs_bch(NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config, - NR_sched_pdsch_t *pdsch, +static uint32_t get_tbs_bch(NR_sched_pdsch_t *pdsch, uint32_t num_total_bytes, uint16_t *vrb_map) { @@ -287,8 +286,8 @@ static uint32_t get_tbs_bch(NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config, int mcsTableIdx = 0; uint32_t TBS = 0; const uint16_t slbitmap = SL_to_bitmap(tda_info->startSymbolIndex, tda_info->nrOfSymbols); - int bwpSize = type0_PDCCH_CSS_config->num_rbs; - int bwpStart = type0_PDCCH_CSS_config->cset_start_rb; + int bwpSize = pdsch->bwp_info.bwpSize; + int bwpStart = pdsch->bwp_info.bwpStart; int rbStop = bwpSize - 1; int rbStart = 0; uint16_t rbSize = 0; @@ -357,6 +356,7 @@ static uint32_t schedule_control_sib1(gNB_MAC_INST *gNB_mac, NR_COMMON_channels_t *cc = &gNB_mac->common_channels[CC_id]; uint16_t *vrb_map = cc->vrb_map[beam]; NR_sched_pdsch_t *pdsch = &gNB_mac->sched_ctrlCommon->sched_pdsch; + pdsch->bwp_info = get_pdsch_bwp_start_size(gNB_mac, NULL); pdsch->time_domain_allocation = time_domain_allocation; pdsch->dmrs_parms = *dmrs_parms; pdsch->tda_info = *tda_info; @@ -383,8 +383,7 @@ static uint32_t schedule_control_sib1(gNB_MAC_INST *gNB_mac, AssertFatal(gNB_mac->sched_ctrlCommon->cce_index >= 0, "Could not find CCE for coreset0\n"); - uint32_t TBS = get_tbs_bch(type0_PDCCH_CSS_config, - &gNB_mac->sched_ctrlCommon->sched_pdsch, + uint32_t TBS = get_tbs_bch(&gNB_mac->sched_ctrlCommon->sched_pdsch, gNB_mac->sched_ctrlCommon->num_total_bytes, vrb_map); @@ -726,6 +725,7 @@ static void other_sib_sched_control(module_id_t module_idP, NR_sched_pdsch_t sched_pdsch_otherSI = {0}; sched_pdsch_otherSI.time_domain_allocation = time_domain_allocation; + sched_pdsch_otherSI.bwp_info = get_pdsch_bwp_start_size(gNB_mac, NULL); sched_pdsch_otherSI.dmrs_parms = dmrs_parms; sched_pdsch_otherSI.tda_info = tda_info; sched_pdsch_otherSI.nrOfLayers = 1; @@ -735,7 +735,7 @@ static void other_sib_sched_control(module_id_t module_idP, uint16_t *vrb_map = cc->vrb_map[beam.idx]; uint8_t *sib_bcch_pdu = cc->other_sib_bcch_pdu[payload_idx]; int num_total_bytes = cc->other_sib_bcch_length[payload_idx]; - sched_pdsch_otherSI.tb_size = get_tbs_bch(type0_PDCCH_CSS_config, &sched_pdsch_otherSI, num_total_bytes, vrb_map); + sched_pdsch_otherSI.tb_size = get_tbs_bch(&sched_pdsch_otherSI, num_total_bytes, vrb_map); sched_pdsch_otherSI.R = nr_get_code_rate_dl(sched_pdsch_otherSI.mcs, 0); sched_pdsch_otherSI.Qm = nr_get_Qm_dl(sched_pdsch_otherSI.mcs, 0); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index 9e0b9dfbd7..416db3b083 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -384,7 +384,7 @@ void abort_nr_dl_harq(NR_UE_info_t* UE, int8_t harq_pid) UE->mac_stats.dl.errors++; } -static bwp_info_t get_pdsch_bwp_start_size(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE) +bwp_info_t get_pdsch_bwp_start_size(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE) { bwp_info_t bwp_info; if (!UE) { @@ -579,6 +579,7 @@ static bool allocate_dl_retransmission(module_id_t module_id, sched_ctrl->sched_pdsch = *retInfo; sched_ctrl->sched_pdsch.rbStart = rbStart - bwp_info.bwpStart; sched_ctrl->sched_pdsch.pucch_allocation = alloc; + sched_ctrl->sched_pdsch.bwp_info = bwp_info; /* retransmissions: directly allocate */ *n_rb_sched -= sched_ctrl->sched_pdsch.rbSize; @@ -768,10 +769,10 @@ static void pf_dl(module_id_t module_id, const uint16_t slbitmap = SL_to_bitmap(tda_info->startSymbolIndex, tda_info->nrOfSymbols); uint16_t *rballoc_mask = mac->common_channels[CC_id].vrb_map[beam.idx]; - bwp_info_t bwp_info = get_pdsch_bwp_start_size(mac, iterator->UE); + sched_pdsch->bwp_info = get_pdsch_bwp_start_size(mac, iterator->UE); int rbStart = 0; // WRT BWP start - int rbStop = bwp_info.bwpSize - 1; - int bwp_start = bwp_info.bwpStart; + int rbStop = sched_pdsch->bwp_info.bwpSize - 1; + int bwp_start = sched_pdsch->bwp_info.bwpStart; // Freq-demain allocation while (rbStart < rbStop && (rballoc_mask[rbStart + bwp_start] & slbitmap)) rbStart++; @@ -941,9 +942,8 @@ nfapi_nr_dl_tti_pdsch_pdu_rel15_t *prepare_pdsch_pdu(nfapi_nr_dl_tti_request_pdu pdsch_pdu->pduBitmap = 0; pdsch_pdu->rnti = rnti; pdsch_pdu->pduIndex = pdu_index; - bwp_info_t bwp_info = get_pdsch_bwp_start_size(mac, UE); - pdsch_pdu->BWPSize = bwp_info.bwpSize; - pdsch_pdu->BWPStart = bwp_info.bwpStart; + pdsch_pdu->BWPSize = sched_pdsch->bwp_info.bwpSize; + pdsch_pdu->BWPStart = sched_pdsch->bwp_info.bwpStart; pdsch_pdu->SubcarrierSpacing = dl_bwp ? dl_bwp->scs : *scc->ssbSubcarrierSpacing; pdsch_pdu->CyclicPrefix = dl_bwp && dl_bwp->cyclicprefix ? *dl_bwp->cyclicprefix : 0; // Codeword information @@ -990,7 +990,7 @@ nfapi_nr_dl_tti_pdsch_pdu_rel15_t *prepare_pdsch_pdu(nfapi_nr_dl_tti_request_pdu if (valid_ptrs_setup) pdsch_pdu->pduBitmap |= 0x1; // Bit 0: pdschPtrs - Indicates PTRS included (FR2) } - int dl_bw_tbslbrm = UE ? UE->sc_info.dl_bw_tbslbrm : bwp_info.bwpSize; + int dl_bw_tbslbrm = UE ? UE->sc_info.dl_bw_tbslbrm : sched_pdsch->bwp_info.bwpSize; pdsch_pdu->maintenance_parms_v3.tbSizeLbrmBytes = nr_compute_tbslbrm(pdsch_pdu->mcsTable[0], dl_bw_tbslbrm, nl_tbslbrm); pdsch_pdu->maintenance_parms_v3.ldpcBaseGraph = get_BG(sched_pdsch->tb_size << 3, sched_pdsch->R); // Precoding and beamforming diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 527b733c02..84382bbb9f 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -435,7 +435,7 @@ NR_beam_alloc_t beam_allocation_procedure(NR_beam_info_t *beam_info, int frame, void reset_beam_status(NR_beam_info_t *beam_info, int frame, int slot, int beam_index, int slots_per_frame, bool new_beam); void beam_selection_procedures(gNB_MAC_INST *mac, NR_UE_info_t *UE); void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t frameP, slot_t slotP); - +bwp_info_t get_pdsch_bwp_start_size(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE); size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset_rsrp); long get_lcid_from_drbid(int drb_id); diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 239e0457f1..e94b0f3adf 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -463,7 +463,7 @@ typedef struct NR_sched_pdsch { uint16_t pm_index; uint8_t nrOfLayers; - + bwp_info_t bwp_info; NR_pdsch_dmrs_t dmrs_parms; // time_domain_allocation is the index of a list of tda int time_domain_allocation; From 266f6fcebeea9884940ac07a63c00a4a194453ac Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 6 Jun 2025 10:18:20 +0200 Subject: [PATCH 160/964] using sched_pusch also in RA functions and other improvements --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 181 +++++++++++------- .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 24 +-- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 1 + openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 2 +- 4 files changed, 125 insertions(+), 83 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 03f794473b..82314fb18a 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -48,13 +48,10 @@ // forward declaration of functions used in this file static void fill_msg3_pusch_pdu(nfapi_nr_pusch_pdu_t *pusch_pdu, + const NR_sched_pusch_t *sched_pusch, NR_ServingCellConfigCommon_t *scc, NR_UE_info_t *UE, - int startSymbolAndLength, int scs, - int bwp_size, - int bwp_start, - int mappingtype, int fh); static void nr_fill_rar(uint8_t Mod_idP, NR_UE_info_t *UE, uint8_t *dlsch_buffer, nfapi_nr_pusch_pdu_t *pusch_pdu); @@ -807,11 +804,19 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP, NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP; NR_UE_ServingCell_Info_t *sc_info = &UE->sc_info; + NR_SearchSpace_t *ss = UE->UE_sched_ctrl.search_space; + NR_ControlResourceSet_t *coreset = UE->UE_sched_ctrl.coreset; + AssertFatal(coreset, "Coreset cannot be null for RA-Msg3 retransmission\n"); + const int coresetid = coreset->controlResourceSetId; + NR_tda_info_t tda_info = get_ul_tda_info(ul_bwp, + coresetid, + NR_SearchSpace__searchSpaceType_PR_common, + TYPE_TC_RNTI_, + ra->Msg3_tda_id); - NR_PUSCH_TimeDomainResourceAllocationList_t *pusch_TimeDomainAllocationList = ul_bwp->tdaList_Common; int mu = ul_bwp->scs; int slots_frame = nr_mac->frame_structure.numb_slots_frame; - uint16_t K2 = *pusch_TimeDomainAllocationList->list.array[ra->Msg3_tda_id]->k2 + get_NTN_Koffset(scc); + uint16_t K2 = tda_info.k2 + get_NTN_Koffset(scc); const int sched_frame = (frame + (slot + K2) / slots_frame) % MAX_FRAME_NUMBER; const int sched_slot = (slot + K2) % slots_frame; @@ -825,29 +830,54 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP, return; } int fh = 0; - int startSymbolAndLength = pusch_TimeDomainAllocationList->list.array[ra->Msg3_tda_id]->startSymbolAndLength; - int StartSymbolIndex, NrOfSymbols; - SLIV2SL(startSymbolAndLength, &StartSymbolIndex, &NrOfSymbols); - int mappingtype = pusch_TimeDomainAllocationList->list.array[ra->Msg3_tda_id]->mappingType; - int buffer_index = ul_buffer_index(sched_frame, sched_slot, slots_frame, nr_mac->vrb_map_UL_size); uint16_t *vrb_map_UL = &nr_mac->common_channels[CC_id].vrb_map_UL[beam_ul.idx][buffer_index * MAX_BWP_SIZE]; - const int BWPSize = sc_info->initial_ul_BWPSize; - const int BWPStart = sc_info->initial_ul_BWPStart; + NR_pusch_dmrs_t dmrs_info = get_ul_dmrs_params(scc, ul_bwp, &tda_info, 1); + int num_dmrs_symb = 0; + for(int i = tda_info.startSymbolIndex; i < tda_info.startSymbolIndex + tda_info.nrOfSymbols; i++) + num_dmrs_symb += (dmrs_info.ul_dmrs_symb_pos >> i) & 1; + int TBS = 0, mcsindex = 0, R = 0, Qm = 0; + while(TBS < 7) { // TBS for msg3 is 7 bytes (except for RRCResumeRequest1 currently not implemented) + mcsindex++; + AssertFatal(mcsindex <= 28, "Exceeding MCS limit for Msg3\n"); + R = nr_get_code_rate_ul(mcsindex, ul_bwp->mcs_table); + Qm = nr_get_Qm_ul(mcsindex, ul_bwp->mcs_table); + TBS = nr_compute_tbs(Qm, + R, + ra->msg3_nb_rb, + tda_info.nrOfSymbols, + num_dmrs_symb * 12, // nb dmrs set for no data in dmrs symbol + 0, //nb_rb_oh + 0, // to verify tb scaling + 1) >> 3; + } + + NR_sched_pusch_t sched_pusch = { + .bwp_info = get_pusch_bwp_start_size(UE), + .tb_size = TBS, + .rbSize = ra->msg3_nb_rb, + .R = R, + .Qm = Qm, + .mcs = mcsindex, + .nrOfLayers = 1, + .tda_info = tda_info, + .dmrs_info = dmrs_info, + }; int rbStart = 0; - for (int i = 0; (i < ra->msg3_nb_rb) && (rbStart <= (BWPSize - ra->msg3_nb_rb)); i++) { - if (vrb_map_UL[rbStart + BWPStart + i]&SL_to_bitmap(StartSymbolIndex, NrOfSymbols)) { + for (int i = 0; (i < ra->msg3_nb_rb) && (rbStart <= (sched_pusch.bwp_info.bwpSize - ra->msg3_nb_rb)); i++) { + if (vrb_map_UL[rbStart + sched_pusch.bwp_info.bwpStart + i] & SL_to_bitmap(tda_info.startSymbolIndex, tda_info.nrOfSymbols)) { rbStart += i; i = 0; } } - if (rbStart > (BWPSize - ra->msg3_nb_rb)) { + if (rbStart > (sched_pusch.bwp_info.bwpSize - ra->msg3_nb_rb)) { // cannot find free vrb_map for msg3 retransmission in this slot return; } + sched_pusch.rbStart = rbStart; LOG_I(NR_MAC, "%4d%2d: RA RNTI %04x CC_id %d Scheduling retransmission of Msg3 in (%d,%d)\n", frame, @@ -874,15 +904,10 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP, nfapi_nr_pusch_pdu_t *pusch_pdu = &future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pusch_pdu; memset(pusch_pdu, 0, sizeof(nfapi_nr_pusch_pdu_t)); - fill_msg3_pusch_pdu(pusch_pdu, scc, UE, startSymbolAndLength, mu, BWPSize, BWPStart, mappingtype, fh); + fill_msg3_pusch_pdu(pusch_pdu, &sched_pusch, scc, UE, mu, fh); future_ul_tti_req->n_pdus += 1; // generation of DCI 0_0 to schedule msg3 retransmission - NR_SearchSpace_t *ss = UE->UE_sched_ctrl.search_space; - NR_ControlResourceSet_t *coreset = UE->UE_sched_ctrl.coreset; - AssertFatal(coreset, "Coreset cannot be null for RA-Msg3 retransmission\n"); - - const int coresetid = coreset->controlResourceSetId; nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = nr_mac->pdcch_pdu_idx[CC_id][coresetid]; if (!pdcch_pdu_rel15) { nfapi_nr_ul_dci_request_pdus_t *ul_dci_request_pdu = &ul_dci_req->ul_dci_pdu_list[ul_dci_req->numPdus]; @@ -966,7 +991,7 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP, beam_dci.idx); for (int rb = 0; rb < ra->msg3_nb_rb; rb++) { - vrb_map_UL[rbStart + BWPStart + rb] |= SL_to_bitmap(StartSymbolIndex, NrOfSymbols); + vrb_map_UL[rbStart + sched_pusch.bwp_info.bwpStart + rb] |= SL_to_bitmap(tda_info.startSymbolIndex, tda_info.nrOfSymbols); } // Restart RA contention resolution timer in Msg3 retransmission slot (current slot + K2) @@ -1108,24 +1133,18 @@ static bool nr_get_Msg3alloc(gNB_MAC_INST *mac, int CC_id, int current_slot, fra } static void fill_msg3_pusch_pdu(nfapi_nr_pusch_pdu_t *pusch_pdu, + const NR_sched_pusch_t *sched_pusch, NR_ServingCellConfigCommon_t *scc, NR_UE_info_t *UE, - int startSymbolAndLength, int scs, - int bwp_size, - int bwp_start, - int mappingtype, int fh) { - int start_symbol_index,nr_of_symbols; - SLIV2SL(startSymbolAndLength, &start_symbol_index, &nr_of_symbols); - int mcsindex = -1; // init value const NR_RA_t *ra = UE->ra; pusch_pdu->pdu_bit_map = PUSCH_PDU_BITMAP_PUSCH_DATA; pusch_pdu->rnti = UE->rnti; pusch_pdu->handle = 0; - pusch_pdu->bwp_start = bwp_start; - pusch_pdu->bwp_size = bwp_size; + pusch_pdu->bwp_start = sched_pusch->bwp_info.bwpStart; + pusch_pdu->bwp_size = sched_pusch->bwp_info.bwpSize; pusch_pdu->subcarrier_spacing = scs; pusch_pdu->cyclic_prefix = 0; pusch_pdu->mcs_table = 0; @@ -1140,21 +1159,30 @@ static void fill_msg3_pusch_pdu(nfapi_nr_pusch_pdu_t *pusch_pdu, } pusch_pdu->data_scrambling_id = *scc->physCellId; pusch_pdu->nrOfLayers = 1; - pusch_pdu->ul_dmrs_symb_pos = get_l_prime(nr_of_symbols,mappingtype,pusch_dmrs_pos2,pusch_len1,start_symbol_index, scc->dmrs_TypeA_Position); - LOG_D(NR_MAC, "MSG3 start_sym:%d NR Symb:%d mappingtype:%d, ul_dmrs_symb_pos:%x\n", start_symbol_index, nr_of_symbols, mappingtype, pusch_pdu->ul_dmrs_symb_pos); + pusch_pdu->ul_dmrs_symb_pos = get_l_prime(sched_pusch->tda_info.nrOfSymbols, + sched_pusch->tda_info.mapping_type, + pusch_dmrs_pos2, + pusch_len1, + sched_pusch->tda_info.startSymbolIndex, + scc->dmrs_TypeA_Position); + LOG_D(NR_MAC, + "MSG3 start_sym:%d NR Symb:%d mappingtype:%d, ul_dmrs_symb_pos:%x\n", + sched_pusch->tda_info.startSymbolIndex, + sched_pusch->tda_info.nrOfSymbols, + sched_pusch->tda_info.mapping_type, + pusch_pdu->ul_dmrs_symb_pos); pusch_pdu->dmrs_config_type = 0; pusch_pdu->ul_dmrs_scrambling_id = *scc->physCellId; //If provided and the PUSCH is not a msg3 PUSCH, otherwise, L2 should set this to physical cell id. pusch_pdu->pusch_identity = *scc->physCellId; //If provided and the PUSCH is not a msg3 PUSCH, otherwise, L2 should set this to physical cell id. pusch_pdu->scid = 0; //DMRS sequence initialization [TS38.211, sec 6.4.1.1.1]. Should match what is sent in DCI 0_1, otherwise set to 0. pusch_pdu->dmrs_ports = 1; // 6.2.2 in 38.214 only port 0 to be used - pusch_pdu->num_dmrs_cdm_grps_no_data = nr_of_symbols <= 2 ? 1 : 2; // no data in dmrs symbols as in 6.2.2 in 38.214 + // no data in dmrs symbols as in 6.2.2 in 38.214 + pusch_pdu->num_dmrs_cdm_grps_no_data = sched_pusch->tda_info.nrOfSymbols <= 2 ? 1 : 2; pusch_pdu->resource_alloc = 1; //type 1 memset(pusch_pdu->rb_bitmap, 0, sizeof(pusch_pdu->rb_bitmap)); - pusch_pdu->rb_start = ra->msg3_first_rb; - if (ra->msg3_nb_rb > pusch_pdu->bwp_size) - AssertFatal(false, "MSG3 allocated number of RBs exceed the BWP size\n"); - else - pusch_pdu->rb_size = ra->msg3_nb_rb; + pusch_pdu->rb_start = sched_pusch->rbStart; + AssertFatal(sched_pusch->rbSize <= pusch_pdu->bwp_size, "MSG3 allocated number of RBs exceed the BWP size\n"); + pusch_pdu->rb_size = sched_pusch->rbSize; pusch_pdu->vrb_to_prb_mapping = 0; pusch_pdu->frequency_hopping = fh; @@ -1164,8 +1192,8 @@ static void fill_msg3_pusch_pdu(nfapi_nr_pusch_pdu_t *pusch_pdu, //which indicates "Outside the carrier" and value 3301, which indicates "Undetermined position within the carrier" are used. [TS38.331, UplinkTxDirectCurrentBWP IE] pusch_pdu->uplink_frequency_shift_7p5khz = 0; //Resource Allocation in time domain - pusch_pdu->start_symbol_index = start_symbol_index; - pusch_pdu->nr_of_symbols = nr_of_symbols; + pusch_pdu->start_symbol_index = sched_pusch->tda_info.startSymbolIndex; + pusch_pdu->nr_of_symbols = sched_pusch->tda_info.nrOfSymbols; //Optional Data only included if indicated in pduBitmap pusch_pdu->pusch_data.rv_index = nr_get_rv(ra->msg3_round % 4); pusch_pdu->pusch_data.harq_process_id = 0; @@ -1178,29 +1206,11 @@ static void fill_msg3_pusch_pdu(nfapi_nr_pusch_pdu_t *pusch_pdu, pusch_pdu->beamforming.dig_bf_interface = 1; pusch_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = UE->UE_beam_index; - int num_dmrs_symb = 0; - for(int i = start_symbol_index; i < start_symbol_index+nr_of_symbols; i++) - num_dmrs_symb += (pusch_pdu->ul_dmrs_symb_pos >> i) & 1; - int TBS = 0; - while(TBS<7) { // TBS for msg3 is 7 bytes (except for RRCResumeRequest1 currently not implemented) - mcsindex++; - AssertFatal(mcsindex <= 28, "Exceeding MCS limit for Msg3\n"); - int R = nr_get_code_rate_ul(mcsindex,pusch_pdu->mcs_table); - pusch_pdu->target_code_rate = R; - pusch_pdu->qam_mod_order = nr_get_Qm_ul(mcsindex,pusch_pdu->mcs_table); - TBS = nr_compute_tbs(pusch_pdu->qam_mod_order, - R, - pusch_pdu->rb_size, - pusch_pdu->nr_of_symbols, - num_dmrs_symb*12, // nb dmrs set for no data in dmrs symbol - 0, //nb_rb_oh - 0, // to verify tb scaling - pusch_pdu->nrOfLayers)>>3; - - pusch_pdu->mcs_index = mcsindex; - pusch_pdu->pusch_data.tb_size = TBS; - pusch_pdu->maintenance_parms_v3.ldpcBaseGraph = get_BG(TBS<<3,R); - } + pusch_pdu->target_code_rate = sched_pusch->R; + pusch_pdu->qam_mod_order = sched_pusch->Qm; + pusch_pdu->mcs_index = sched_pusch->mcs; + pusch_pdu->pusch_data.tb_size = sched_pusch->tb_size; + pusch_pdu->maintenance_parms_v3.ldpcBaseGraph = get_BG(sched_pusch->tb_size << 3, sched_pusch->R); } static void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, slot_t slotP, NR_UE_info_t *UE, uint8_t *RAR_pdu) @@ -1244,11 +1254,42 @@ static void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, slot_ nfapi_nr_pusch_pdu_t *pusch_pdu = &future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pusch_pdu; memset(pusch_pdu, 0, sizeof(nfapi_nr_pusch_pdu_t)); - const int ibwp_size = sc_info->initial_ul_BWPSize; - const int fh = (ul_bwp->pusch_Config && ul_bwp->pusch_Config->frequencyHopping) ? 1 : 0; - const int startSymbolAndLength = ul_bwp->tdaList_Common->list.array[ra->Msg3_tda_id]->startSymbolAndLength; - const int mappingtype = ul_bwp->tdaList_Common->list.array[ra->Msg3_tda_id]->mappingType; + NR_tda_info_t tda_info = get_ul_tda_info(ul_bwp, 0, NR_SearchSpace__searchSpaceType_PR_common, TYPE_TC_RNTI_, ra->Msg3_tda_id); + NR_pusch_dmrs_t dmrs_info = get_ul_dmrs_params(scc, ul_bwp, &tda_info, 1); + int num_dmrs_symb = 0; + for(int i = tda_info.startSymbolIndex; i < tda_info.startSymbolIndex + tda_info.nrOfSymbols; i++) + num_dmrs_symb += (dmrs_info.ul_dmrs_symb_pos >> i) & 1; + int TBS = 0, mcsindex = 0, R = 0, Qm = 0; + while(TBS < 7) { // TBS for msg3 is 7 bytes (except for RRCResumeRequest1 currently not implemented) + mcsindex++; + AssertFatal(mcsindex <= 28, "Exceeding MCS limit for Msg3\n"); + R = nr_get_code_rate_ul(mcsindex, ul_bwp->mcs_table); + Qm = nr_get_Qm_ul(mcsindex, ul_bwp->mcs_table); + TBS = nr_compute_tbs(Qm, + R, + ra->msg3_nb_rb, + tda_info.nrOfSymbols, + num_dmrs_symb * 12, // nb dmrs set for no data in dmrs symbol + 0, //nb_rb_oh + 0, // to verify tb scaling + 1) >> 3; + } + NR_sched_pusch_t sched_pusch = { + .bwp_info.bwpSize = sc_info->initial_ul_BWPSize, + .bwp_info.bwpStart = ra->msg3_bwp_start, + .rbSize = ra->msg3_nb_rb, + .rbStart = ra->msg3_first_rb, + .tb_size = TBS, + .R = R, + .Qm = Qm, + .mcs = mcsindex, + .nrOfLayers = 1, + .tda_info = tda_info, + .dmrs_info = dmrs_info + }; + + const int fh = (ul_bwp->pusch_Config && ul_bwp->pusch_Config->frequencyHopping) ? 1 : 0; LOG_D(NR_MAC, "UE %04x: %d.%d Adding Msg3 UL Config Request for (%d,%d) : (%d,%d,%d)\n", UE->rnti, @@ -1260,7 +1301,7 @@ static void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, slot_ ra->msg3_first_rb, ra->msg3_round); - fill_msg3_pusch_pdu(pusch_pdu, scc, UE, startSymbolAndLength, ul_bwp->scs, ibwp_size, ra->msg3_bwp_start, mappingtype, fh); + fill_msg3_pusch_pdu(pusch_pdu, &sched_pusch, scc, UE, ul_bwp->scs, fh); future_ul_tti_req->n_pdus += 1; // calling function to fill rar message diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 534b955f7b..1cd3181bf1 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -65,7 +65,7 @@ int get_ul_tda(gNB_MAC_INST *nrmac, int frame, int slot) return 0; // if FDD or not mixed slot in TDD, for now use default TDA (TODO handle CSI-RS slots) } -static bwp_info_t get_pusch_bwp_start_size(NR_UE_info_t *UE) +bwp_info_t get_pusch_bwp_start_size(NR_UE_info_t *UE) { NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP; NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; @@ -1819,6 +1819,7 @@ static bool allocate_ul_retransmission(gNB_MAC_INST *nrmac, sched_pusch->slot, sched_pusch->rbSize); + sched_pusch->bwp_info = bwp_info; sched_pusch->rbStart = rbStart; /* no need to recompute the TBS, it will be the same */ @@ -2029,6 +2030,7 @@ static void pf_ul(module_id_t module_id, update_ul_ue_R_Qm(sched_pusch->mcs, current_BWP->mcs_table, current_BWP->pusch_Config, &sched_pusch->R, &sched_pusch->Qm); sched_pusch->rbStart = rbStart; sched_pusch->rbSize = min_rb; + sched_pusch->bwp_info = bwp_info; sched_pusch->frame = sched_frame; sched_pusch->slot = sched_slot; sched_pusch->tb_size = nr_compute_tbs(sched_pusch->Qm, @@ -2222,6 +2224,7 @@ static void pf_ul(module_id_t module_id, sched_pusch->rbSize = rbSize; sched_pusch->tb_size = TBS; + sched_pusch->bwp_info = bwp_info; sched_pusch->frame = sched_frame; sched_pusch->slot = sched_slot; LOG_D(NR_MAC, @@ -2364,8 +2367,6 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, slot_t slot, nfapi_ uint16_t rnti = UE->rnti; sched_ctrl->SR = false; - int *tpmi = NULL; - int8_t harq_id = sched_pusch->ul_harq_pid; if (harq_id < 0) { /* PP has not selected a specific HARQ Process, get a new one */ @@ -2494,8 +2495,8 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, slot_t slot, nfapi_ /* FAPI: BWP */ - pusch_pdu->bwp_size = current_BWP->BWPSize; - pusch_pdu->bwp_start = current_BWP->BWPStart; + pusch_pdu->bwp_size = sched_pusch->bwp_info.bwpSize; + pusch_pdu->bwp_start = sched_pusch->bwp_info.bwpStart; pusch_pdu->subcarrier_spacing = current_BWP->scs; pusch_pdu->cyclic_prefix = 0; @@ -2510,11 +2511,6 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, slot_t slot, nfapi_ else pusch_pdu->data_scrambling_id = *scc->physCellId; pusch_pdu->nrOfLayers = sched_pusch->nrOfLayers; - // If nrOfLayers is the same as in srs_feedback, we use the best TPMI, i.e. the one in srs_feedback. - // Otherwise, we use the valid TPMI that we saved in the first transmission. - if (pusch_pdu->nrOfLayers != (sched_ctrl->srs_feedback.ul_ri + 1)) - tpmi = &sched_pusch->tpmi; - pusch_pdu->num_dmrs_cdm_grps_no_data = sched_pusch->dmrs_info.num_dmrs_cdm_grps_no_data; /* FAPI: DMRS */ pusch_pdu->num_dmrs_cdm_grps_no_data = sched_pusch->dmrs_info.num_dmrs_cdm_grps_no_data; @@ -2544,8 +2540,6 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, slot_t slot, nfapi_ else if (NR_DMRS_UplinkConfig) pusch_pdu->pusch_identity = *scc->physCellId; } - pusch_pdu->scid = 0; // DMRS sequence initialization [TS38.211, sec 6.4.1.1.1] - pusch_pdu->dmrs_ports = ((1<nrOfLayers) - 1); /* FAPI: Pusch Allocation in frequency domain */ pusch_pdu->resource_alloc = 1; //type 1 @@ -2695,6 +2689,12 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, slot_t slot, nfapi_ sched_pusch->frame, sched_pusch->slot, sched_ctrl->ul_harq_processes[harq_id].round); + + // If nrOfLayers is the same as in srs_feedback, we use the best TPMI, i.e. the one in srs_feedback. + // Otherwise, we use the valid TPMI that we saved in the first transmission. + int *tpmi = NULL; + if (pusch_pdu->nrOfLayers != (sched_ctrl->srs_feedback.ul_ri + 1)) + tpmi = &sched_pusch->tpmi; config_uldci(&UE->sc_info, pusch_pdu, &uldci_payload, diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 84382bbb9f..3b4bb46105 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -436,6 +436,7 @@ void reset_beam_status(NR_beam_info_t *beam_info, int frame, int slot, int beam_ void beam_selection_procedures(gNB_MAC_INST *mac, NR_UE_info_t *UE); void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t frameP, slot_t slotP); bwp_info_t get_pdsch_bwp_start_size(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE); +bwp_info_t get_pusch_bwp_start_size(NR_UE_info_t *UE); size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset_rsrp); long get_lcid_from_drbid(int drb_id); diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index e94b0f3adf..a29829f4f4 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -413,7 +413,6 @@ typedef struct NR_sched_pusch { /// UL HARQ PID to use for this UE, or -1 for "any new" int8_t ul_harq_pid; - uint8_t nrOfLayers; int tpmi; @@ -421,6 +420,7 @@ typedef struct NR_sched_pusch { int time_domain_allocation; NR_tda_info_t tda_info; NR_pusch_dmrs_t dmrs_info; + bwp_info_t bwp_info; int phr_txpower_calc; } NR_sched_pusch_t; From bd4cc0d60b9fc18e0b3c632da8555e180050c523 Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 6 Jun 2025 10:47:33 +0200 Subject: [PATCH 161/964] extending the scope of NR_pusch_dmrs_t --- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 37 ++++++++-- .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 70 ++++++------------- openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 5 ++ 3 files changed, 55 insertions(+), 57 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 102c06bb49..1bf7b38caf 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -706,8 +706,8 @@ const NR_DMRS_UplinkConfig_t *get_DMRS_UplinkConfig(const NR_PUSCH_Config_t *pus NR_pusch_dmrs_t get_ul_dmrs_params(const NR_ServingCellConfigCommon_t *scc, const NR_UE_UL_BWP_t *ul_bwp, const NR_tda_info_t *tda_info, - const int Layers) { - + const int Layers) +{ NR_pusch_dmrs_t dmrs = {0}; // TODO setting of cdm groups with no data to be redone for MIMO if(NFAPI_MODE == NFAPI_MODE_AERIAL) { @@ -719,13 +719,36 @@ NR_pusch_dmrs_t get_ul_dmrs_params(const NR_ServingCellConfigCommon_t *scc, dmrs.num_dmrs_cdm_grps_no_data = 2; } - NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig = ul_bwp->pusch_Config ? - (tda_info->mapping_type == typeA ? - ul_bwp->pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA->choice.setup : - ul_bwp->pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup) : NULL; + const NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig = get_DMRS_UplinkConfig(ul_bwp->pusch_Config, tda_info); + dmrs.ptrsConfig = NR_DMRS_UplinkConfig + && NR_DMRS_UplinkConfig->phaseTrackingRS ? + NR_DMRS_UplinkConfig->phaseTrackingRS->choice.setup : NULL; + + dmrs.pusch_identity = *scc->physCellId; + dmrs.dmrs_scrambling_id = *scc->physCellId; + dmrs.scid = 0; + if (ul_bwp->transform_precoding) { // transform precoding disabled + long *scramblingid = NULL; + if (NR_DMRS_UplinkConfig && dmrs.scid == 0) + scramblingid = NR_DMRS_UplinkConfig->transformPrecodingDisabled->scramblingID0; + else if (NR_DMRS_UplinkConfig) + scramblingid = NR_DMRS_UplinkConfig->transformPrecodingDisabled->scramblingID1; + if (scramblingid) + dmrs.dmrs_scrambling_id = *scramblingid; + } else { + if (NR_DMRS_UplinkConfig && NR_DMRS_UplinkConfig->transformPrecodingEnabled) { + if (NR_DMRS_UplinkConfig->transformPrecodingEnabled->nPUSCH_Identity) + dmrs.pusch_identity = *NR_DMRS_UplinkConfig->transformPrecodingEnabled->nPUSCH_Identity; + if ((!NR_DMRS_UplinkConfig->transformPrecodingEnabled->sequenceGroupHopping + && !NR_DMRS_UplinkConfig->transformPrecodingEnabled->sequenceHopping) + && !scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->groupHoppingEnabledTransformPrecoding) + dmrs.low_papr_sequence_number = 0; + else + AssertFatal(false, "Hopping mode is not supported in transform precoding\n"); + } + } dmrs.dmrs_config_type = NR_DMRS_UplinkConfig && NR_DMRS_UplinkConfig->dmrs_Type ? 1 : 0; - const pusch_dmrs_AdditionalPosition_t additional_pos = (NR_DMRS_UplinkConfig && NR_DMRS_UplinkConfig->dmrs_AdditionalPosition) ? (*NR_DMRS_UplinkConfig->dmrs_AdditionalPosition == NR_DMRS_UplinkConfig__dmrs_AdditionalPosition_pos3 ? diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 1cd3181bf1..1d1ce68ab5 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -2514,33 +2514,12 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, slot_t slot, nfapi_ /* FAPI: DMRS */ pusch_pdu->num_dmrs_cdm_grps_no_data = sched_pusch->dmrs_info.num_dmrs_cdm_grps_no_data; - pusch_pdu->dmrs_ports = ((1<nrOfLayers) - 1); + pusch_pdu->dmrs_ports = ((1 << sched_pusch->nrOfLayers) - 1); pusch_pdu->ul_dmrs_symb_pos = sched_pusch->dmrs_info.ul_dmrs_symb_pos; pusch_pdu->dmrs_config_type = sched_pusch->dmrs_info.dmrs_config_type; - pusch_pdu->scid = 0; // DMRS sequence initialization [TS38.211, sec 6.4.1.1.1] - const NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig = get_DMRS_UplinkConfig(current_BWP->pusch_Config, &sched_pusch->tda_info); - if (pusch_pdu->transform_precoding) { // transform precoding disabled - long *scramblingid=NULL; - pusch_pdu->pusch_identity = *scc->physCellId; - if (NR_DMRS_UplinkConfig && pusch_pdu->scid == 0) - scramblingid = NR_DMRS_UplinkConfig->transformPrecodingDisabled->scramblingID0; - else if (NR_DMRS_UplinkConfig) - scramblingid = NR_DMRS_UplinkConfig->transformPrecodingDisabled->scramblingID1; - if (scramblingid == NULL) - pusch_pdu->ul_dmrs_scrambling_id = *scc->physCellId; - else - pusch_pdu->ul_dmrs_scrambling_id = *scramblingid; - } - else { - pusch_pdu->ul_dmrs_scrambling_id = *scc->physCellId; - if (NR_DMRS_UplinkConfig && - NR_DMRS_UplinkConfig->transformPrecodingEnabled && - NR_DMRS_UplinkConfig->transformPrecodingEnabled->nPUSCH_Identity != NULL) - pusch_pdu->pusch_identity = *NR_DMRS_UplinkConfig->transformPrecodingEnabled->nPUSCH_Identity; - else if (NR_DMRS_UplinkConfig) - pusch_pdu->pusch_identity = *scc->physCellId; - } - + pusch_pdu->scid = sched_pusch->dmrs_info.scid; // DMRS sequence initialization [TS38.211, sec 6.4.1.1.1] + pusch_pdu->pusch_identity = sched_pusch->dmrs_info.pusch_identity; + pusch_pdu->ul_dmrs_scrambling_id = sched_pusch->dmrs_info.dmrs_scrambling_id; /* FAPI: Pusch Allocation in frequency domain */ pusch_pdu->resource_alloc = 1; //type 1 pusch_pdu->rb_start = sched_pusch->rbStart; @@ -2598,44 +2577,35 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, slot_t slot, nfapi_ } else pusch_pdu->maintenance_parms_v3.tbSizeLbrmBytes = 0; - LOG_D(NR_MAC,"PUSCH PDU : data_scrambling_identity %x, dmrs_scrambling_id %x\n",pusch_pdu->data_scrambling_id,pusch_pdu->ul_dmrs_scrambling_id); + LOG_D(NR_MAC, + "PUSCH PDU : data_scrambling_identity %x, dmrs_scrambling_id %x\n", + pusch_pdu->data_scrambling_id, + pusch_pdu->ul_dmrs_scrambling_id); /* TRANSFORM PRECODING --------------------------------------------------------*/ - - if (pusch_pdu->transform_precoding == NR_PUSCH_Config__transformPrecoder_enabled){ + if (pusch_pdu->transform_precoding == NR_PUSCH_Config__transformPrecoder_enabled) { // U as specified in section 6.4.1.1.1.2 in 38.211, if sequence hopping and group hopping are disabled pusch_pdu->dfts_ofdm.low_papr_group_number = pusch_pdu->pusch_identity % 30; - - // V as specified in section 6.4.1.1.1.2 in 38.211 V = 0 if sequence hopping and group hopping are disabled - if ((!NR_DMRS_UplinkConfig || - !NR_DMRS_UplinkConfig->transformPrecodingEnabled || - (!NR_DMRS_UplinkConfig->transformPrecodingEnabled->sequenceGroupHopping && !NR_DMRS_UplinkConfig->transformPrecodingEnabled->sequenceHopping)) && - !scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->groupHoppingEnabledTransformPrecoding) - pusch_pdu->dfts_ofdm.low_papr_sequence_number = 0; - else - AssertFatal(1==0,"Hopping mode is not supported in transform precoding\n"); - - LOG_D(NR_MAC,"TRANSFORM PRECODING IS ENABLED. CDM groups: %d, U: %d MCS table: %d\n", pusch_pdu->num_dmrs_cdm_grps_no_data, pusch_pdu->dfts_ofdm.low_papr_group_number, current_BWP->mcs_table); + pusch_pdu->dfts_ofdm.low_papr_sequence_number = sched_pusch->dmrs_info.low_papr_sequence_number; + LOG_D(NR_MAC, + "TRANSFORM PRECODING IS ENABLED. CDM groups: %d, U: %d MCS table: %d\n", + pusch_pdu->num_dmrs_cdm_grps_no_data, + pusch_pdu->dfts_ofdm.low_papr_group_number, + current_BWP->mcs_table); } - - /*-----------------------------------------------------------------------------*/ - /* PUSCH PTRS */ - if (NR_DMRS_UplinkConfig && NR_DMRS_UplinkConfig->phaseTrackingRS != NULL) { + if (sched_pusch->dmrs_info.ptrsConfig) { bool valid_ptrs_setup = false; - pusch_pdu->pusch_ptrs.ptrs_ports_list = (nfapi_nr_ptrs_ports_t *) malloc(2*sizeof(nfapi_nr_ptrs_ports_t)); - valid_ptrs_setup = set_ul_ptrs_values(NR_DMRS_UplinkConfig->phaseTrackingRS->choice.setup, + pusch_pdu->pusch_ptrs.ptrs_ports_list = calloc_or_fail(2, sizeof(nfapi_nr_ptrs_ports_t)); + valid_ptrs_setup = set_ul_ptrs_values(sched_pusch->dmrs_info.ptrsConfig, pusch_pdu->rb_size, pusch_pdu->mcs_index, pusch_pdu->mcs_table, &pusch_pdu->pusch_ptrs.ptrs_freq_density,&pusch_pdu->pusch_ptrs.ptrs_time_density, &pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_re_offset,&pusch_pdu->pusch_ptrs.num_ptrs_ports, &pusch_pdu->pusch_ptrs.ul_ptrs_power, pusch_pdu->nr_of_symbols); - if (valid_ptrs_setup==true) { + if (valid_ptrs_setup == true) pusch_pdu->pdu_bit_map |= PUSCH_PDU_BITMAP_PUSCH_PTRS; // enable PUSCH PTRS - } - } - else{ + } else pusch_pdu->pdu_bit_map &= ~PUSCH_PDU_BITMAP_PUSCH_PTRS; // disable PUSCH PTRS - } /* look up the PDCCH PDU for this BWP and CORESET. If it does not exist, * create it */ diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index a29829f4f4..31c00239d2 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -392,6 +392,11 @@ typedef struct NR_pusch_dmrs { uint16_t ul_dmrs_symb_pos; uint8_t num_dmrs_cdm_grps_no_data; nfapi_nr_dmrs_type_e dmrs_config_type; + int dmrs_scrambling_id; + int pusch_identity; + int scid; + int low_papr_sequence_number; + NR_PTRS_UplinkConfig_t *ptrsConfig; } NR_pusch_dmrs_t; typedef struct NR_sched_pusch { From dd281eba0f7c88fe14df3078e13301a542b73ea0 Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 6 Jun 2025 15:50:02 +0200 Subject: [PATCH 162/964] common function to generate FAPI PUSCH payload --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 116 ++-------- .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 218 +++++++++--------- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 9 + 3 files changed, 137 insertions(+), 206 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 82314fb18a..181eb4e0b9 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -46,13 +46,6 @@ #include -// forward declaration of functions used in this file -static void fill_msg3_pusch_pdu(nfapi_nr_pusch_pdu_t *pusch_pdu, - const NR_sched_pusch_t *sched_pusch, - NR_ServingCellConfigCommon_t *scc, - NR_UE_info_t *UE, - int scs, - int fh); static void nr_fill_rar(uint8_t Mod_idP, NR_UE_info_t *UE, uint8_t *dlsch_buffer, nfapi_nr_pusch_pdu_t *pusch_pdu); static const float ssb_per_rach_occasion[8] = {0.125, 0.25, 0.5, 1, 2, 4, 8}; @@ -814,7 +807,6 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP, TYPE_TC_RNTI_, ra->Msg3_tda_id); - int mu = ul_bwp->scs; int slots_frame = nr_mac->frame_structure.numb_slots_frame; uint16_t K2 = tda_info.k2 + get_NTN_Koffset(scc); const int sched_frame = (frame + (slot + K2) / slots_frame) % MAX_FRAME_NUMBER; @@ -829,7 +821,6 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP, reset_beam_status(&nr_mac->beam_info, sched_frame, sched_slot, UE->UE_beam_index, slots_frame, beam_ul.new_beam); return; } - int fh = 0; int buffer_index = ul_buffer_index(sched_frame, sched_slot, slots_frame, nr_mac->vrb_map_UL_size); uint16_t *vrb_map_UL = &nr_mac->common_channels[CC_id].vrb_map_UL[beam_ul.idx][buffer_index * MAX_BWP_SIZE]; @@ -901,10 +892,15 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP, "Invalid future_ul_tti_req->n_pdus %d\n", future_ul_tti_req->n_pdus); future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE; future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pdu_size = sizeof(nfapi_nr_pusch_pdu_t); - nfapi_nr_pusch_pdu_t *pusch_pdu = &future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pusch_pdu; - memset(pusch_pdu, 0, sizeof(nfapi_nr_pusch_pdu_t)); - - fill_msg3_pusch_pdu(pusch_pdu, &sched_pusch, scc, UE, mu, fh); + nfapi_nr_pusch_pdu_t *pusch_pdu = prepare_pusch_pdu(future_ul_tti_req, + UE, + scc, + &sched_pusch, + get_transformPrecoding(ul_bwp, NR_UL_DCI_FORMAT_0_0, 0), + 0, + ra->msg3_round, + ul_bwp->pusch_Config && ul_bwp->pusch_Config->frequencyHopping, + UE->rnti); future_ul_tti_req->n_pdus += 1; // generation of DCI 0_0 to schedule msg3 retransmission @@ -1132,87 +1128,6 @@ static bool nr_get_Msg3alloc(gNB_MAC_INST *mac, int CC_id, int current_slot, fra return true; } -static void fill_msg3_pusch_pdu(nfapi_nr_pusch_pdu_t *pusch_pdu, - const NR_sched_pusch_t *sched_pusch, - NR_ServingCellConfigCommon_t *scc, - NR_UE_info_t *UE, - int scs, - int fh) -{ - const NR_RA_t *ra = UE->ra; - pusch_pdu->pdu_bit_map = PUSCH_PDU_BITMAP_PUSCH_DATA; - pusch_pdu->rnti = UE->rnti; - pusch_pdu->handle = 0; - pusch_pdu->bwp_start = sched_pusch->bwp_info.bwpStart; - pusch_pdu->bwp_size = sched_pusch->bwp_info.bwpSize; - pusch_pdu->subcarrier_spacing = scs; - pusch_pdu->cyclic_prefix = 0; - pusch_pdu->mcs_table = 0; - if (scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder == NULL) - pusch_pdu->transform_precoding = 1; // disabled - else { - pusch_pdu->transform_precoding = 0; // enabled - pusch_pdu->dfts_ofdm.low_papr_group_number = *scc->physCellId % 30; - pusch_pdu->dfts_ofdm.low_papr_sequence_number = 0; - if (scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->groupHoppingEnabledTransformPrecoding) - AssertFatal(1==0,"Hopping mode is not supported in transform precoding\n"); - } - pusch_pdu->data_scrambling_id = *scc->physCellId; - pusch_pdu->nrOfLayers = 1; - pusch_pdu->ul_dmrs_symb_pos = get_l_prime(sched_pusch->tda_info.nrOfSymbols, - sched_pusch->tda_info.mapping_type, - pusch_dmrs_pos2, - pusch_len1, - sched_pusch->tda_info.startSymbolIndex, - scc->dmrs_TypeA_Position); - LOG_D(NR_MAC, - "MSG3 start_sym:%d NR Symb:%d mappingtype:%d, ul_dmrs_symb_pos:%x\n", - sched_pusch->tda_info.startSymbolIndex, - sched_pusch->tda_info.nrOfSymbols, - sched_pusch->tda_info.mapping_type, - pusch_pdu->ul_dmrs_symb_pos); - pusch_pdu->dmrs_config_type = 0; - pusch_pdu->ul_dmrs_scrambling_id = *scc->physCellId; //If provided and the PUSCH is not a msg3 PUSCH, otherwise, L2 should set this to physical cell id. - pusch_pdu->pusch_identity = *scc->physCellId; //If provided and the PUSCH is not a msg3 PUSCH, otherwise, L2 should set this to physical cell id. - pusch_pdu->scid = 0; //DMRS sequence initialization [TS38.211, sec 6.4.1.1.1]. Should match what is sent in DCI 0_1, otherwise set to 0. - pusch_pdu->dmrs_ports = 1; // 6.2.2 in 38.214 only port 0 to be used - // no data in dmrs symbols as in 6.2.2 in 38.214 - pusch_pdu->num_dmrs_cdm_grps_no_data = sched_pusch->tda_info.nrOfSymbols <= 2 ? 1 : 2; - pusch_pdu->resource_alloc = 1; //type 1 - memset(pusch_pdu->rb_bitmap, 0, sizeof(pusch_pdu->rb_bitmap)); - pusch_pdu->rb_start = sched_pusch->rbStart; - AssertFatal(sched_pusch->rbSize <= pusch_pdu->bwp_size, "MSG3 allocated number of RBs exceed the BWP size\n"); - pusch_pdu->rb_size = sched_pusch->rbSize; - pusch_pdu->vrb_to_prb_mapping = 0; - - pusch_pdu->frequency_hopping = fh; - //pusch_pdu->tx_direct_current_location; - //The uplink Tx Direct Current location for the carrier. Only values in the value range of this field between 0 and 3299, - //which indicate the subcarrier index within the carrier corresponding 1o the numerology of the corresponding uplink BWP and value 3300, - //which indicates "Outside the carrier" and value 3301, which indicates "Undetermined position within the carrier" are used. [TS38.331, UplinkTxDirectCurrentBWP IE] - pusch_pdu->uplink_frequency_shift_7p5khz = 0; - //Resource Allocation in time domain - pusch_pdu->start_symbol_index = sched_pusch->tda_info.startSymbolIndex; - pusch_pdu->nr_of_symbols = sched_pusch->tda_info.nrOfSymbols; - //Optional Data only included if indicated in pduBitmap - pusch_pdu->pusch_data.rv_index = nr_get_rv(ra->msg3_round % 4); - pusch_pdu->pusch_data.harq_process_id = 0; - pusch_pdu->pusch_data.new_data_indicator = (ra->msg3_round == 0) ? 1 : 0;; - pusch_pdu->pusch_data.num_cb = 0; - - // Beamforming - pusch_pdu->beamforming.num_prgs = 0; - pusch_pdu->beamforming.prg_size = 0; // bwp_size; - pusch_pdu->beamforming.dig_bf_interface = 1; - pusch_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = UE->UE_beam_index; - - pusch_pdu->target_code_rate = sched_pusch->R; - pusch_pdu->qam_mod_order = sched_pusch->Qm; - pusch_pdu->mcs_index = sched_pusch->mcs; - pusch_pdu->pusch_data.tb_size = sched_pusch->tb_size; - pusch_pdu->maintenance_parms_v3.ldpcBaseGraph = get_BG(sched_pusch->tb_size << 3, sched_pusch->R); -} - static void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, slot_t slotP, NR_UE_info_t *UE, uint8_t *RAR_pdu) { gNB_MAC_INST *mac = RC.nrmac[module_idP]; @@ -1251,8 +1166,6 @@ static void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, slot_ ra->Msg3_slot); future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE; future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pdu_size = sizeof(nfapi_nr_pusch_pdu_t); - nfapi_nr_pusch_pdu_t *pusch_pdu = &future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pusch_pdu; - memset(pusch_pdu, 0, sizeof(nfapi_nr_pusch_pdu_t)); NR_tda_info_t tda_info = get_ul_tda_info(ul_bwp, 0, NR_SearchSpace__searchSpaceType_PR_common, TYPE_TC_RNTI_, ra->Msg3_tda_id); NR_pusch_dmrs_t dmrs_info = get_ul_dmrs_params(scc, ul_bwp, &tda_info, 1); @@ -1289,7 +1202,6 @@ static void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, slot_ .dmrs_info = dmrs_info }; - const int fh = (ul_bwp->pusch_Config && ul_bwp->pusch_Config->frequencyHopping) ? 1 : 0; LOG_D(NR_MAC, "UE %04x: %d.%d Adding Msg3 UL Config Request for (%d,%d) : (%d,%d,%d)\n", UE->rnti, @@ -1301,7 +1213,15 @@ static void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, slot_ ra->msg3_first_rb, ra->msg3_round); - fill_msg3_pusch_pdu(pusch_pdu, &sched_pusch, scc, UE, ul_bwp->scs, fh); + nfapi_nr_pusch_pdu_t *pusch_pdu = prepare_pusch_pdu(future_ul_tti_req, + UE, + scc, + &sched_pusch, + get_transformPrecoding(ul_bwp, NR_UL_DCI_FORMAT_0_0, 0), + 0, + 0, + ul_bwp->pusch_Config && ul_bwp->pusch_Config->frequencyHopping, + UE->rnti); future_ul_tti_req->n_pdus += 1; // calling function to fill rar message diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 1d1ce68ab5..f00aa988ee 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -2254,6 +2254,106 @@ static void pf_ul(module_id_t module_id, } } +nfapi_nr_pusch_pdu_t *prepare_pusch_pdu(nfapi_nr_ul_tti_request_t *future_ul_tti_req, + const NR_UE_info_t *UE, + const NR_ServingCellConfigCommon_t *scc, + const NR_sched_pusch_t *sched_pusch, + int transform_precoding, + int harq_id, + int harq_round, + int fh, + int rnti) +{ + nfapi_nr_pusch_pdu_t *pusch_pdu = &future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pusch_pdu; + memset(pusch_pdu, 0, sizeof(nfapi_nr_pusch_pdu_t)); + const NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP; + + pusch_pdu->pdu_bit_map = PUSCH_PDU_BITMAP_PUSCH_DATA; + pusch_pdu->rnti = rnti; + pusch_pdu->handle = 0; //not yet used + pusch_pdu->bwp_size = sched_pusch->bwp_info.bwpSize; + pusch_pdu->bwp_start = sched_pusch->bwp_info.bwpStart; + pusch_pdu->subcarrier_spacing = ul_bwp->scs; + pusch_pdu->cyclic_prefix = 0; + pusch_pdu->target_code_rate = sched_pusch->R; + pusch_pdu->qam_mod_order = sched_pusch->Qm; + pusch_pdu->mcs_index = sched_pusch->mcs; + pusch_pdu->mcs_table = ul_bwp->mcs_table; + pusch_pdu->transform_precoding = transform_precoding; + if (ul_bwp->pusch_Config && ul_bwp->pusch_Config->dataScramblingIdentityPUSCH) + pusch_pdu->data_scrambling_id = *ul_bwp->pusch_Config->dataScramblingIdentityPUSCH; + else + pusch_pdu->data_scrambling_id = *scc->physCellId; + pusch_pdu->nrOfLayers = sched_pusch->nrOfLayers; + // DMRS + pusch_pdu->num_dmrs_cdm_grps_no_data = sched_pusch->dmrs_info.num_dmrs_cdm_grps_no_data; + pusch_pdu->dmrs_ports = ((1 << sched_pusch->nrOfLayers) - 1); + pusch_pdu->ul_dmrs_symb_pos = sched_pusch->dmrs_info.ul_dmrs_symb_pos; + pusch_pdu->dmrs_config_type = sched_pusch->dmrs_info.dmrs_config_type; + pusch_pdu->scid = sched_pusch->dmrs_info.scid; // DMRS sequence initialization [TS38.211, sec 6.4.1.1.1] + pusch_pdu->pusch_identity = sched_pusch->dmrs_info.pusch_identity; + pusch_pdu->ul_dmrs_scrambling_id = sched_pusch->dmrs_info.dmrs_scrambling_id; + /* Allocation in frequency domain */ + pusch_pdu->resource_alloc = 1; //type 1 + pusch_pdu->rb_start = sched_pusch->rbStart; + pusch_pdu->rb_size = sched_pusch->rbSize; + pusch_pdu->vrb_to_prb_mapping = 0; + pusch_pdu->frequency_hopping = fh; + /* Resource Allocation in time domain */ + pusch_pdu->start_symbol_index = sched_pusch->tda_info.startSymbolIndex; + pusch_pdu->nr_of_symbols = sched_pusch->tda_info.nrOfSymbols; + /* PUSCH PDU */ + pusch_pdu->pusch_data.rv_index = nr_get_rv(harq_round % 4); + pusch_pdu->pusch_data.harq_process_id = harq_id; + pusch_pdu->pusch_data.new_data_indicator = (harq_round == 0) ? 1 : 0; // not NDI but indicator for new transmission + pusch_pdu->pusch_data.tb_size = sched_pusch->tb_size; + pusch_pdu->pusch_data.num_cb = 0; // CBG not supported + // Beamforming + pusch_pdu->beamforming.num_prgs = 0; + pusch_pdu->beamforming.prg_size = 0; // bwp_size; + pusch_pdu->beamforming.dig_bf_interface = 1; + pusch_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = UE->UE_beam_index; + /* TRANSFORM PRECODING --------------------------------------------------------*/ + if (pusch_pdu->transform_precoding == NR_PUSCH_Config__transformPrecoder_enabled) { + // U as specified in section 6.4.1.1.1.2 in 38.211, if sequence hopping and group hopping are disabled + pusch_pdu->dfts_ofdm.low_papr_group_number = sched_pusch->dmrs_info.pusch_identity % 30; + pusch_pdu->dfts_ofdm.low_papr_sequence_number = sched_pusch->dmrs_info.low_papr_sequence_number; + } + + + pusch_pdu->maintenance_parms_v3.ldpcBaseGraph = get_BG(sched_pusch->tb_size << 3, sched_pusch->R); + pusch_pdu->maintenance_parms_v3.tbSizeLbrmBytes = 0; + if (UE->sc_info.rateMatching_PUSCH) { + // TBS_LBRM according to section 5.4.2.1 of 38.212 + long *maxMIMO_Layers = UE->sc_info.maxMIMO_Layers_PUSCH; + if (!maxMIMO_Layers && ul_bwp && ul_bwp->pusch_Config) + maxMIMO_Layers = ul_bwp->pusch_Config->maxRank; + AssertFatal (maxMIMO_Layers != NULL,"Option with max MIMO layers not configured is not supported\n"); + pusch_pdu->maintenance_parms_v3.tbSizeLbrmBytes = nr_compute_tbslbrm(ul_bwp->mcs_table, + UE->sc_info.ul_bw_tbslbrm, + *maxMIMO_Layers); + } + /* PUSCH PTRS */ + if (sched_pusch->dmrs_info.ptrsConfig) { + bool valid_ptrs_setup = false; + pusch_pdu->pusch_ptrs.ptrs_ports_list = calloc_or_fail(2, sizeof(nfapi_nr_ptrs_ports_t)); + valid_ptrs_setup = set_ul_ptrs_values(sched_pusch->dmrs_info.ptrsConfig, + pusch_pdu->rb_size, + pusch_pdu->mcs_index, + pusch_pdu->mcs_table, + &pusch_pdu->pusch_ptrs.ptrs_freq_density, + &pusch_pdu->pusch_ptrs.ptrs_time_density, + &pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_re_offset, + &pusch_pdu->pusch_ptrs.num_ptrs_ports, + &pusch_pdu->pusch_ptrs.ul_ptrs_power, + pusch_pdu->nr_of_symbols); + if (valid_ptrs_setup == true) + pusch_pdu->pdu_bit_map |= PUSCH_PDU_BITMAP_PUSCH_PTRS; // enable PUSCH PTRS + } else + pusch_pdu->pdu_bit_map &= ~PUSCH_PDU_BITMAP_PUSCH_PTRS; // disable PUSCH PTRS + return pusch_pdu; +} + static bool nr_ulsch_preprocessor(module_id_t module_id, frame_t frame, slot_t slot) { gNB_MAC_INST *nr_mac = RC.nrmac[module_id]; @@ -2475,9 +2575,16 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, slot_t slot, nfapi_ "Invalid future_ul_tti_req->n_pdus %d\n", future_ul_tti_req->n_pdus); future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE; - future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pdu_size = sizeof(nfapi_nr_pusch_pdu_t); - nfapi_nr_pusch_pdu_t *pusch_pdu = &future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pusch_pdu; - memset(pusch_pdu, 0, sizeof(nfapi_nr_pusch_pdu_t)); + future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pdu_size = sizeof(nfapi_nr_pusch_pdu_t); + nfapi_nr_pusch_pdu_t *pusch_pdu = prepare_pusch_pdu(future_ul_tti_req, + UE, + scc, + sched_pusch, + current_BWP->transform_precoding, + harq_id, + cur_harq->round, + current_BWP->pusch_Config && current_BWP->pusch_Config->frequencyHopping, + rnti); future_ul_tti_req->n_pdus += 1; LOG_D(NR_MAC, @@ -2489,73 +2596,10 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, slot_t slot, nfapi_ future_ul_tti_req->SFN, future_ul_tti_req->Slot); - pusch_pdu->pdu_bit_map = PUSCH_PDU_BITMAP_PUSCH_DATA; - pusch_pdu->rnti = rnti; - pusch_pdu->handle = 0; //not yet used - - /* FAPI: BWP */ - - pusch_pdu->bwp_size = sched_pusch->bwp_info.bwpSize; - pusch_pdu->bwp_start = sched_pusch->bwp_info.bwpStart; - pusch_pdu->subcarrier_spacing = current_BWP->scs; - pusch_pdu->cyclic_prefix = 0; - - /* FAPI: PUSCH information always included */ - pusch_pdu->target_code_rate = sched_pusch->R; - pusch_pdu->qam_mod_order = sched_pusch->Qm; - pusch_pdu->mcs_index = sched_pusch->mcs; - pusch_pdu->mcs_table = current_BWP->mcs_table; - pusch_pdu->transform_precoding = current_BWP->transform_precoding; - if (current_BWP->pusch_Config && current_BWP->pusch_Config->dataScramblingIdentityPUSCH) - pusch_pdu->data_scrambling_id = *current_BWP->pusch_Config->dataScramblingIdentityPUSCH; - else - pusch_pdu->data_scrambling_id = *scc->physCellId; - pusch_pdu->nrOfLayers = sched_pusch->nrOfLayers; - - /* FAPI: DMRS */ - pusch_pdu->num_dmrs_cdm_grps_no_data = sched_pusch->dmrs_info.num_dmrs_cdm_grps_no_data; - pusch_pdu->dmrs_ports = ((1 << sched_pusch->nrOfLayers) - 1); - pusch_pdu->ul_dmrs_symb_pos = sched_pusch->dmrs_info.ul_dmrs_symb_pos; - pusch_pdu->dmrs_config_type = sched_pusch->dmrs_info.dmrs_config_type; - pusch_pdu->scid = sched_pusch->dmrs_info.scid; // DMRS sequence initialization [TS38.211, sec 6.4.1.1.1] - pusch_pdu->pusch_identity = sched_pusch->dmrs_info.pusch_identity; - pusch_pdu->ul_dmrs_scrambling_id = sched_pusch->dmrs_info.dmrs_scrambling_id; - /* FAPI: Pusch Allocation in frequency domain */ - pusch_pdu->resource_alloc = 1; //type 1 - pusch_pdu->rb_start = sched_pusch->rbStart; - pusch_pdu->rb_size = sched_pusch->rbSize; - pusch_pdu->vrb_to_prb_mapping = 0; - if (current_BWP->pusch_Config==NULL || current_BWP->pusch_Config->frequencyHopping==NULL) - pusch_pdu->frequency_hopping = 0; - else - pusch_pdu->frequency_hopping = 1; - - /* FAPI: Resource Allocation in time domain */ - pusch_pdu->start_symbol_index = sched_pusch->tda_info.startSymbolIndex; - pusch_pdu->nr_of_symbols = sched_pusch->tda_info.nrOfSymbols; - - /* PUSCH PDU */ - AssertFatal(cur_harq->round < nr_mac->ul_bler.harq_round_max, - "RV index %d is out of bounds\n", - cur_harq->round % 4); - pusch_pdu->pusch_data.rv_index = nr_get_rv(cur_harq->round % 4); - pusch_pdu->pusch_data.harq_process_id = harq_id; - pusch_pdu->pusch_data.new_data_indicator = (cur_harq->round == 0) ? 1 : 0; // not NDI but indicator for new transmission - pusch_pdu->pusch_data.tb_size = sched_pusch->tb_size; - pusch_pdu->pusch_data.num_cb = 0; //CBG not supported - - // Beamforming - pusch_pdu->beamforming.num_prgs = 0; - pusch_pdu->beamforming.prg_size = 0; // bwp_size; - pusch_pdu->beamforming.dig_bf_interface = 1; - pusch_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = UE->UE_beam_index; - - pusch_pdu->maintenance_parms_v3.ldpcBaseGraph = get_BG(sched_pusch->tb_size<<3,sched_pusch->R); // Calacualte the normalized tx_power for PHR long *deltaMCS = current_BWP->pusch_Config ? current_BWP->pusch_Config->pusch_PowerControl->deltaMCS : NULL; int tbs_bits = pusch_pdu->pusch_data.tb_size << 3; - sched_pusch->phr_txpower_calc = compute_ph_factor(current_BWP->scs, tbs_bits, sched_pusch->rbSize, @@ -2565,48 +2609,6 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, slot_t slot, nfapi_ deltaMCS, false); - NR_UE_ServingCell_Info_t *sc_info = &UE->sc_info; - if (sc_info->rateMatching_PUSCH) { - // TBS_LBRM according to section 5.4.2.1 of 38.212 - long *maxMIMO_Layers = sc_info->maxMIMO_Layers_PUSCH; - if (!maxMIMO_Layers) - maxMIMO_Layers = current_BWP->pusch_Config->maxRank; - AssertFatal (maxMIMO_Layers != NULL,"Option with max MIMO layers not configured is not supported\n"); - pusch_pdu->maintenance_parms_v3.tbSizeLbrmBytes = - nr_compute_tbslbrm(current_BWP->mcs_table, sc_info->ul_bw_tbslbrm, *maxMIMO_Layers); - } else - pusch_pdu->maintenance_parms_v3.tbSizeLbrmBytes = 0; - - LOG_D(NR_MAC, - "PUSCH PDU : data_scrambling_identity %x, dmrs_scrambling_id %x\n", - pusch_pdu->data_scrambling_id, - pusch_pdu->ul_dmrs_scrambling_id); - /* TRANSFORM PRECODING --------------------------------------------------------*/ - if (pusch_pdu->transform_precoding == NR_PUSCH_Config__transformPrecoder_enabled) { - - // U as specified in section 6.4.1.1.1.2 in 38.211, if sequence hopping and group hopping are disabled - pusch_pdu->dfts_ofdm.low_papr_group_number = pusch_pdu->pusch_identity % 30; - pusch_pdu->dfts_ofdm.low_papr_sequence_number = sched_pusch->dmrs_info.low_papr_sequence_number; - LOG_D(NR_MAC, - "TRANSFORM PRECODING IS ENABLED. CDM groups: %d, U: %d MCS table: %d\n", - pusch_pdu->num_dmrs_cdm_grps_no_data, - pusch_pdu->dfts_ofdm.low_papr_group_number, - current_BWP->mcs_table); - } - /* PUSCH PTRS */ - if (sched_pusch->dmrs_info.ptrsConfig) { - bool valid_ptrs_setup = false; - pusch_pdu->pusch_ptrs.ptrs_ports_list = calloc_or_fail(2, sizeof(nfapi_nr_ptrs_ports_t)); - valid_ptrs_setup = set_ul_ptrs_values(sched_pusch->dmrs_info.ptrsConfig, - pusch_pdu->rb_size, pusch_pdu->mcs_index, pusch_pdu->mcs_table, - &pusch_pdu->pusch_ptrs.ptrs_freq_density,&pusch_pdu->pusch_ptrs.ptrs_time_density, - &pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_re_offset,&pusch_pdu->pusch_ptrs.num_ptrs_ports, - &pusch_pdu->pusch_ptrs.ul_ptrs_power, pusch_pdu->nr_of_symbols); - if (valid_ptrs_setup == true) - pusch_pdu->pdu_bit_map |= PUSCH_PDU_BITMAP_PUSCH_PTRS; // enable PUSCH PTRS - } else - pusch_pdu->pdu_bit_map &= ~PUSCH_PDU_BITMAP_PUSCH_PTRS; // disable PUSCH PTRS - /* look up the PDCCH PDU for this BWP and CORESET. If it does not exist, * create it */ NR_SearchSpace_t *ss = sched_ctrl->search_space; diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 3b4bb46105..51b604ec1c 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -323,6 +323,15 @@ void nr_check_Msg4_MsgB_Ack(module_id_t module_id, frame_t frame, slot_t slot, N void mac_remove_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rnti); NR_UE_info_t *get_new_nr_ue_inst(uid_allocator_t *uia, rnti_t rnti, NR_CellGroupConfig_t *CellGroup); int nr_get_default_pucch_res(int pucch_ResourceCommon); +nfapi_nr_pusch_pdu_t *prepare_pusch_pdu(nfapi_nr_ul_tti_request_t *future_ul_tti_req, + const NR_UE_info_t *UE, + const NR_ServingCellConfigCommon_t *scc, + const NR_sched_pusch_t *sched_pusch, + int transform_precoding, + int harq_id, + int harq_round, + int fh, + int rnti); nfapi_nr_dl_tti_pdsch_pdu_rel15_t *prepare_pdsch_pdu(nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu, const gNB_MAC_INST *mac, const NR_UE_info_t *UE, From 11711c4b7b18f4206a8c1aaaff381ba32830ae9c Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 9 Jun 2025 11:36:38 +0200 Subject: [PATCH 163/964] common function to generate FAPI DL DCI payload --- openair1/SIMULATION/NR_PHY/dlsim.c | 1 + openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 43 ++++-------- .../LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c | 32 +++------ .../LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 46 ++++--------- .../LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c | 2 +- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 67 +++++++++++++++++-- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 17 +++-- 7 files changed, 109 insertions(+), 99 deletions(-) diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index b858945018..291c16b1fa 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -216,6 +216,7 @@ void nr_dlsim_preprocessor(module_id_t module_id, frame_t frame, slot_t slot) NR_sched_pdsch_t *sched_pdsch = &sched_ctrl->sched_pdsch; sched_pdsch->rbStart = g_rbStart; sched_pdsch->rbSize = g_rbSize; + sched_pdsch->bwp_info = get_pdsch_bwp_start_size(RC.nrmac[module_id], UE_info); sched_pdsch->mcs = g_mcsIndex; sched_pdsch->nrOfLayers = g_nrOfLayers; sched_pdsch->pm_index = g_pmi; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 181eb4e0b9..987e6778bf 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -1310,10 +1310,7 @@ static void prepare_dl_pdus(gNB_MAC_INST *nr_mac, int aggregation_level, int CCEIndex, int ndi, - int tpc, - int delta_PRI, int current_harq_pid, - int time_domain_assignment, int CC_id, int rnti, int round, @@ -1375,25 +1372,16 @@ static void prepare_dl_pdus(gNB_MAC_INST *nr_mac, dci_pdu->precodingAndBeamforming.prgs_list[0].pm_idx = 0; dci_pdu->precodingAndBeamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = UE->UE_beam_index; - dci_pdu_rel15_t dci_payload; - dci_payload.frequency_domain_assignment.val = PRBalloc_to_locationandbandwidth0(pdsch_pdu_rel15->rbSize, - pdsch_pdu_rel15->rbStart, - pdsch_pdu_rel15->BWPSize); - - dci_payload.time_domain_assignment.val = time_domain_assignment; - dci_payload.vrb_to_prb_mapping.val = 0; - dci_payload.mcs = pdsch_pdu_rel15->mcsIndex[0]; - dci_payload.tb_scaling = tb_scaling; - if (rnti_type == TYPE_TC_RNTI_) { - dci_payload.format_indicator = 1; - dci_payload.rv = pdsch_pdu_rel15->rvIndex[0]; - dci_payload.harq_pid.val = current_harq_pid; - dci_payload.ndi = ndi; - dci_payload.dai[0].val = pucch ? (pucch->dai_c-1) & 3 : 0; - dci_payload.tpc = tpc; // TPC for PUCCH: table 7.2.1-1 in 38.213 - dci_payload.pucch_resource_indicator = delta_PRI; // This is delta_PRI from 9.2.1 in 38.213 - dci_payload.pdsch_to_harq_feedback_timing_indicator.val = pucch ? pucch->timing_indicator : 0; - } + dci_pdu_rel15_t dci_payload = prepare_dci_dl_payload(nr_mac, + UE, + rnti_type, + sched_ctrl->search_space->searchSpaceType->present, + pdsch_pdu_rel15, + sched_pdsch, + pucch, + current_harq_pid, + tb_scaling, + false); LOG_D(NR_MAC, "DCI 1_0 payload: freq_alloc %d (%d,%d,%d), time_alloc %d, vrb to prb %d, mcs %d tb_scaling %d pucchres %d harqtiming %d\n", @@ -1617,6 +1605,7 @@ static void nr_generate_Msg2(module_id_t module_idP, .R = R, .Qm = Qm, .mcs = mcsIndex, + .time_domain_allocation = time_domain_assignment, .nrOfLayers = 1, .dmrs_parms = dmrs_parms, .tda_info = tda_info, @@ -1636,9 +1625,6 @@ static void nr_generate_Msg2(module_id_t module_idP, CCEIndex, 0, 0, - 0, - 0, - time_domain_assignment, CC_id, ra->RA_rnti, 0, @@ -1838,9 +1824,8 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, return; } - const int delta_PRI = 0; int r_pucch = nr_get_pucch_resource(coreset, UE->current_UL_BWP.pucch_Config, CCEIndex); - LOG_D(NR_MAC, "Msg4 r_pucch %d (CCEIndex %d, delta_PRI %d)\n", r_pucch, CCEIndex, delta_PRI); + LOG_D(NR_MAC, "Msg4 r_pucch %d CCEIndex %d\n", r_pucch, CCEIndex); int alloc = nr_acknack_scheduling(nr_mac, UE, frameP, slotP, UE->UE_beam_index, r_pucch, 1); if (alloc < 0) { LOG_D(NR_MAC,"Couldn't find a pucch allocation for ack nack (msg4) in frame %d slot %d\n", frameP, slotP); @@ -1912,6 +1897,7 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, .R = nr_get_code_rate_dl(mcsIndex, mcsTableIdx), .Qm = nr_get_Qm_dl(mcsIndex, mcsTableIdx), .mcs = mcsIndex, + .time_domain_allocation = time_domain_assignment, .nrOfLayers = 1, .dmrs_parms = dmrs_info, .tda_info = msg4_tda, @@ -1931,10 +1917,7 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, aggregation_level, CCEIndex, harq->ndi, - sched_ctrl->tpc1, - delta_PRI, current_harq_pid, - time_domain_assignment, CC_id, rnti, harq->round, diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c index 974cb9f3f1..2d7f1e9ef5 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c @@ -470,30 +470,18 @@ static void nr_fill_nfapi_dl_SIB_pdu(gNB_MAC_INST *gNB_mac, dci_pdu->precodingAndBeamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = beam_index; /* DCI payload */ - dci_pdu_rel15_t dci_payload; - memset(&dci_payload, 0, sizeof(dci_pdu_rel15_t)); - - dci_payload.bwp_indicator.val = 0; - - // frequency domain assignment - dci_payload.frequency_domain_assignment.val = PRBalloc_to_locationandbandwidth0( - pdsch_pdu_rel15->rbSize, pdsch_pdu_rel15->rbStart, type0_PDCCH_CSS_config->num_rbs); - - dci_payload.time_domain_assignment.val = pdsch->time_domain_allocation; - dci_payload.mcs = pdsch->mcs; - dci_payload.rv = pdsch_pdu_rel15->rvIndex[0]; - dci_payload.harq_pid.val = 0; - dci_payload.ndi = 0; - dci_payload.dai[0].val = 0; - dci_payload.tpc = 0; // table 7.2.1-1 in 38.213 - dci_payload.pucch_resource_indicator = 0; - dci_payload.pdsch_to_harq_feedback_timing_indicator.val = 0; - dci_payload.antenna_ports.val = 0; - dci_payload.dmrs_sequence_initialization.val = pdsch_pdu_rel15->SCID; - dci_payload.system_info_indicator = is_sib1 ? 0 : 1; - int dci_format = NR_DL_DCI_FORMAT_1_0; int rnti_type = TYPE_SI_RNTI_; + dci_pdu_rel15_t dci_payload = prepare_dci_dl_payload(gNB_mac, + NULL, + rnti_type, + NR_SearchSpace__searchSpaceType_PR_common, + pdsch_pdu_rel15, + pdsch, + NULL, + 0, + 0, + is_sib1); fill_dci_pdu_rel15(NULL, NULL, diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index 416db3b083..59164014a3 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -1189,44 +1189,25 @@ void nr_schedule_ue_spec(module_id_t module_id, dci_pdu->precodingAndBeamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = UE->UE_beam_index; /* DCI payload */ - dci_pdu_rel15_t dci_payload; - memset(&dci_payload, 0, sizeof(dci_pdu_rel15_t)); - // bwp indicator - // as per table 7.3.1.1.2-1 in 38.212 - dci_payload.bwp_indicator.val = UE->sc_info.n_dl_bwp < 4 ? bwp_id : bwp_id - 1; + const int rnti_type = TYPE_C_RNTI_; + dci_pdu_rel15_t dci_payload = prepare_dci_dl_payload(gNB_mac, + UE, + rnti_type, + sched_ctrl->search_space->searchSpaceType->present, + pdsch_pdu, + sched_pdsch, + pucch, + current_harq_pid, + 0, + false); + // Reset TPC to 0 dB to not request new gain multiple times before computing new value for SNR + sched_ctrl->tpc1 = 1; NR_PDSCH_Config_t *pdsch_Config = current_BWP->pdsch_Config; AssertFatal(pdsch_Config == NULL || pdsch_Config->resourceAllocation == NR_PDSCH_Config__resourceAllocation_resourceAllocationType1, "Only frequency resource allocation type 1 is currently supported\n"); - // 3GPP TS 38.214 Section 5.1.2.2.2 Downlink resource allocation type 1 - uint16_t riv_bwp_size = pdsch_pdu->BWPSize; - if (current_BWP->dci_format == NR_DL_DCI_FORMAT_1_0 - && sched_ctrl->search_space->searchSpaceType->present == NR_SearchSpace__searchSpaceType_PR_common) { - if (gNB_mac->cset0_bwp_size > 0) { - riv_bwp_size = gNB_mac->cset0_bwp_size; - } else { - riv_bwp_size = UE->sc_info.initial_dl_BWPSize; - } - } - dci_payload.frequency_domain_assignment.val = - PRBalloc_to_locationandbandwidth0(pdsch_pdu->rbSize, pdsch_pdu->rbStart, riv_bwp_size); - - dci_payload.format_indicator = 1; - dci_payload.time_domain_assignment.val = sched_pdsch->time_domain_allocation; - dci_payload.mcs = sched_pdsch->mcs; - dci_payload.rv = pdsch_pdu->rvIndex[0]; - dci_payload.harq_pid.val = current_harq_pid; - dci_payload.ndi = harq->ndi; - dci_payload.dai[0].val = pucch ? (pucch->dai_c-1)&3 : 0; - dci_payload.tpc = sched_ctrl->tpc1; // TPC for PUCCH: table 7.2.1-1 in 38.213 - // Reset TPC to 0 dB to not request new gain multiple times before computing new value for SNR - sched_ctrl->tpc1 = 1; - dci_payload.pucch_resource_indicator = pucch ? pucch->resource_indicator : 0; - dci_payload.pdsch_to_harq_feedback_timing_indicator.val = pucch ? pucch->timing_indicator : 0; // PDSCH to HARQ TI - dci_payload.antenna_ports.val = dmrs_parms->dmrs_ports_id; - dci_payload.dmrs_sequence_initialization.val = pdsch_pdu->SCID; LOG_D(NR_MAC, "%4d.%2d DCI type 1 payload: freq_alloc %d (%d,%d,%d), " "nrOfLayers %d, time_alloc %d, vrb to prb %d, mcs %d tb_scaling %d ndi %d rv %d tpc %d ti %d\n", @@ -1246,7 +1227,6 @@ void nr_schedule_ue_spec(module_id_t module_id, dci_payload.tpc, pucch ? pucch->timing_indicator : 0); - const int rnti_type = TYPE_C_RNTI_; fill_dci_pdu_rel15(&UE->sc_info, current_BWP, &UE->current_UL_BWP, diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c index bc7b40937f..a470c48bc4 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c @@ -173,7 +173,7 @@ void nr_preprocessor_phytest(module_id_t module_id, frame_t frame, slot_t slot) sched_pdsch->pucch_allocation = alloc; sched_pdsch->rbStart = rbStart; sched_pdsch->rbSize = rbSize; - + sched_pdsch->bwp_info = get_pdsch_bwp_start_size(mac, UE); sched_pdsch->dmrs_parms = get_dl_dmrs_params(scc, dl_bwp, &tda_info, diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 1bf7b38caf..7b64cd93db 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -809,6 +809,61 @@ int get_mcs_from_bler(const NR_bler_options_t *bler_options, return new_mcs; } +dci_pdu_rel15_t prepare_dci_dl_payload(const gNB_MAC_INST *gNB_mac, + const NR_UE_info_t *UE, + nr_rnti_type_t rnti_type, + NR_SearchSpace__searchSpaceType_PR ss_type, + const nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu, + const NR_sched_pdsch_t *sched_pdsch, + const NR_sched_pucch_t *pucch, + int harq_pid, + int tb_scaling, + bool is_sib1) +{ + const NR_UE_DL_BWP_t *dl_BWP = UE ? &UE->current_DL_BWP : NULL; + dci_pdu_rel15_t dci_payload = {0}; + dci_payload.format_indicator = 1; + dci_payload.time_domain_assignment.val = sched_pdsch->time_domain_allocation; + dci_payload.mcs = sched_pdsch->mcs; + dci_payload.rv = pdsch_pdu->rvIndex[0]; + dci_payload.vrb_to_prb_mapping.val = 0; + int riv_bwp = pdsch_pdu->BWPSize; + if (!UE) + riv_bwp = gNB_mac->cset0_bwp_size; + else if (dl_BWP->dci_format == NR_DL_DCI_FORMAT_1_0 && ss_type == NR_SearchSpace__searchSpaceType_PR_common) { + if (gNB_mac->cset0_bwp_size > 0) + riv_bwp = gNB_mac->cset0_bwp_size; + else + riv_bwp = UE->sc_info.initial_dl_BWPSize; + } + dci_payload.frequency_domain_assignment.val = PRBalloc_to_locationandbandwidth0(pdsch_pdu->rbSize, pdsch_pdu->rbStart, riv_bwp); + if (rnti_type == TYPE_SI_RNTI_) { + dci_payload.system_info_indicator = !is_sib1; + return dci_payload; + } + if (rnti_type == TYPE_RA_RNTI_) { + dci_payload.tb_scaling = tb_scaling; + return dci_payload; + } + + const NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; + dci_payload.dmrs_sequence_initialization.val = pdsch_pdu->SCID; + dci_payload.antenna_ports.val = sched_pdsch->dmrs_parms.dmrs_ports_id; + dci_payload.tpc = sched_ctrl->tpc1; + const NR_UE_harq_t *harq = &sched_ctrl->harq_processes[harq_pid]; + AssertFatal(harq, "HARQ process should be available for DCI with RNTI %s\n", rnti_types(rnti_type)); + dci_payload.harq_pid.val = harq_pid; + dci_payload.ndi = harq->ndi; + dci_payload.pucch_resource_indicator = pucch ? pucch->resource_indicator : 0; + dci_payload.pdsch_to_harq_feedback_timing_indicator.val = pucch ? pucch->timing_indicator : 0; // PDSCH to HARQ TI + dci_payload.dai[0].val = pucch ? (pucch->dai_c - 1) & 3 : 0; + // bwp indicator + // as per table 7.3.1.1.2-1 in 38.212 + if (dl_BWP) + dci_payload.bwp_indicator.val = UE->sc_info.n_dl_bwp < 4 ? dl_BWP->bwp_id : dl_BWP->bwp_id - 1; + return dci_payload; +} + void config_uldci(const NR_UE_ServingCell_Info_t *sc_info, const nfapi_nr_pusch_pdu_t *pusch_pdu, dci_pdu_rel15_t *dci_pdu_rel15, @@ -1202,11 +1257,11 @@ void set_r_pucch_parms(int rsetindex, *start_symbol_index = default_pucch_firstsymb[rsetindex]; } -void prepare_dci(const NR_UE_ServingCell_Info_t *servingCellInfo, - const NR_UE_DL_BWP_t *current_BWP, - const NR_ControlResourceSet_t *coreset, - dci_pdu_rel15_t *dci_pdu_rel15, - nr_dci_format_t format) +static void prepare_dci_X1(const NR_UE_ServingCell_Info_t *servingCellInfo, + const NR_UE_DL_BWP_t *current_BWP, + const NR_ControlResourceSet_t *coreset, + dci_pdu_rel15_t *dci_pdu_rel15, + nr_dci_format_t format) { const NR_PDSCH_Config_t *pdsch_Config = current_BWP ? current_BWP->pdsch_Config : NULL; @@ -1353,7 +1408,7 @@ void fill_dci_pdu_rel15(const NR_UE_ServingCell_Info_t *servingCellInfo, pdcch_dci_pdu->PayloadSizeBits = dci_size; AssertFatal(dci_size <= 64, "DCI sizes above 64 bits not yet supported"); if (dci_format == NR_DL_DCI_FORMAT_1_1 || dci_format == NR_UL_DCI_FORMAT_0_1) - prepare_dci(servingCellInfo, current_DL_BWP, coreset, dci_pdu_rel15, dci_format); + prepare_dci_X1(servingCellInfo, current_DL_BWP, coreset, dci_pdu_rel15, dci_format); /// Payload generation switch (dci_format) { diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 51b604ec1c..bebf7e4ece 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -170,7 +170,16 @@ void config_uldci(const NR_UE_ServingCell_Info_t *sc_info, uint8_t ndi, NR_UE_UL_BWP_t *ul_bwp, NR_SearchSpace__searchSpaceType_PR ss_type); - +dci_pdu_rel15_t prepare_dci_dl_payload(const gNB_MAC_INST *gNB_mac, + const NR_UE_info_t *UE, + nr_rnti_type_t rnti_type, + NR_SearchSpace__searchSpaceType_PR ss_type, + const nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu, + const NR_sched_pdsch_t *sched_pdsch, + const NR_sched_pucch_t *pucch, + int harq_pid, + int tb_scaling, + bool is_sib1); void nr_schedule_pucch(gNB_MAC_INST *nrmac, frame_t frameP, slot_t slotP); void nr_srs_ri_computation(const nfapi_nr_srs_normalized_channel_iq_matrix_t *nr_srs_normalized_channel_iq_matrix, @@ -252,12 +261,6 @@ void fill_dci_pdu_rel15(const NR_UE_ServingCell_Info_t *servingCellInfo, long pdsch_HARQ_ACK_Codebook, uint16_t cset0_bwp_size); -void prepare_dci(const NR_UE_ServingCell_Info_t *servingCellInfo, - const NR_UE_DL_BWP_t *current_BWP, - const NR_ControlResourceSet_t *coreset, - dci_pdu_rel15_t *dci_pdu_rel15, - nr_dci_format_t format); - void set_r_pucch_parms(int rsetindex, int r_pucch, int bwp_size, From a9dc588921f782e45fdaa490841af156601bc42d Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 9 Jun 2025 18:45:03 +0200 Subject: [PATCH 164/964] common function to generate FAPI DCI PDU --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 51 +++++++------------ .../LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c | 24 ++++----- .../LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 32 +++--------- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 31 +++++++++++ .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 27 +++------- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 9 ++++ 6 files changed, 84 insertions(+), 90 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 987e6778bf..4a723263dc 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -932,24 +932,17 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP, } // Fill PDCCH DL DCI PDU - nfapi_nr_dl_dci_pdu_t *dci_pdu = &pdcch_pdu_rel15->dci_pdu[pdcch_pdu_rel15->numDlDci]; + nfapi_nr_dl_dci_pdu_t *dci_pdu = prepare_dci_pdu(pdcch_pdu_rel15, + scc, + ss, + coreset, + aggregation_level, + CCEIndex, + UE->UE_beam_index, + UE->rnti); pdcch_pdu_rel15->numDlDci++; - dci_pdu->RNTI = UE->rnti; - dci_pdu->ScramblingId = *scc->physCellId; - dci_pdu->ScramblingRNTI = 0; - dci_pdu->AggregationLevel = aggregation_level; - dci_pdu->CceIndex = CCEIndex; - dci_pdu->beta_PDCCH_1_0 = 0; - dci_pdu->powerControlOffsetSS = 1; - - dci_pdu->precodingAndBeamforming.num_prgs = 0; - dci_pdu->precodingAndBeamforming.prg_size = 0; - dci_pdu->precodingAndBeamforming.dig_bf_interfaces = 1; - dci_pdu->precodingAndBeamforming.prgs_list[0].pm_idx = 0; - dci_pdu->precodingAndBeamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = UE->UE_beam_index; - - dci_pdu_rel15_t uldci_payload={0}; + dci_pdu_rel15_t uldci_payload = {0}; config_uldci(sc_info, pusch_pdu, &uldci_payload, @@ -1356,21 +1349,15 @@ static void prepare_dl_pdus(gNB_MAC_INST *nr_mac, pduindex); /* Fill PDCCH DL DCI PDU */ - nfapi_nr_dl_dci_pdu_t *dci_pdu = &pdcch_pdu_rel15->dci_pdu[pdcch_pdu_rel15->numDlDci]; + nfapi_nr_dl_dci_pdu_t *dci_pdu = prepare_dci_pdu(pdcch_pdu_rel15, + scc, + sched_ctrl->search_space, + coreset, + aggregation_level, + CCEIndex, + UE->UE_beam_index, + rnti); pdcch_pdu_rel15->numDlDci++; - dci_pdu->RNTI = rnti; - dci_pdu->ScramblingId = *scc->physCellId; - dci_pdu->ScramblingRNTI = 0; - dci_pdu->AggregationLevel = aggregation_level; - dci_pdu->CceIndex = CCEIndex; - dci_pdu->beta_PDCCH_1_0 = 0; - dci_pdu->powerControlOffsetSS = 1; - - dci_pdu->precodingAndBeamforming.num_prgs = 0; - dci_pdu->precodingAndBeamforming.prg_size = 0; - dci_pdu->precodingAndBeamforming.dig_bf_interfaces = 1; - dci_pdu->precodingAndBeamforming.prgs_list[0].pm_idx = 0; - dci_pdu->precodingAndBeamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = UE->UE_beam_index; dci_pdu_rel15_t dci_payload = prepare_dci_dl_payload(nr_mac, UE, @@ -1399,7 +1386,7 @@ static void prepare_dl_pdus(gNB_MAC_INST *nr_mac, LOG_D(NR_MAC, "DCI params: rnti 0x%x, rnti_type %d, dci_format %d coreset params: FreqDomainResource %llx, start_symbol %d " "n_symb %d, BWPsize %d\n", - pdcch_pdu_rel15->dci_pdu[0].RNTI, + dci_pdu->RNTI, rnti_type, NR_DL_DCI_FORMAT_1_0, (unsigned long long)pdcch_pdu_rel15->FreqDomainResource, @@ -1410,7 +1397,7 @@ static void prepare_dl_pdus(gNB_MAC_INST *nr_mac, fill_dci_pdu_rel15(&UE->sc_info, dl_bwp, &UE->current_UL_BWP, - &pdcch_pdu_rel15->dci_pdu[pdcch_pdu_rel15->numDlDci - 1], + dci_pdu, &dci_payload, NR_DL_DCI_FORMAT_1_0, rnti_type, diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c index 2d7f1e9ef5..76e9db4fb3 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c @@ -453,21 +453,15 @@ static void nr_fill_nfapi_dl_SIB_pdu(gNB_MAC_INST *gNB_mac, pdsch_pdu_rel15->dlDmrsSymbPos); /* Fill PDCCH DL DCI PDU */ - nfapi_nr_dl_dci_pdu_t *dci_pdu = &pdcch_pdu_rel15->dci_pdu[pdcch_pdu_rel15->numDlDci]; + nfapi_nr_dl_dci_pdu_t *dci_pdu = prepare_dci_pdu(pdcch_pdu_rel15, + scc, + search_space, + coreset, + aggregation_level, + cce_index, + beam_index, + SI_RNTI); pdcch_pdu_rel15->numDlDci++; - dci_pdu->RNTI = SI_RNTI; - dci_pdu->ScramblingId = *scc->physCellId; - dci_pdu->ScramblingRNTI = 0; - dci_pdu->AggregationLevel = aggregation_level; - dci_pdu->CceIndex = cce_index; - dci_pdu->beta_PDCCH_1_0 = 0; - dci_pdu->powerControlOffsetSS = 1; - - dci_pdu->precodingAndBeamforming.num_prgs = 0; - dci_pdu->precodingAndBeamforming.prg_size = 0; - dci_pdu->precodingAndBeamforming.dig_bf_interfaces = 1; - dci_pdu->precodingAndBeamforming.prgs_list[0].pm_idx = 0; - dci_pdu->precodingAndBeamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = beam_index; /* DCI payload */ int dci_format = NR_DL_DCI_FORMAT_1_0; @@ -486,7 +480,7 @@ static void nr_fill_nfapi_dl_SIB_pdu(gNB_MAC_INST *gNB_mac, fill_dci_pdu_rel15(NULL, NULL, NULL, - &pdcch_pdu_rel15->dci_pdu[pdcch_pdu_rel15->numDlDci - 1], + dci_pdu, &dci_payload, dci_format, rnti_type, diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index 59164014a3..0ea552e64d 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -1162,31 +1162,15 @@ void nr_schedule_ue_spec(module_id_t module_id, LOG_D(NR_MAC,"Configuring DCI/PDCCH in %d.%d at CCE %d, rnti %x\n", frame,slot,sched_ctrl->cce_index,rnti); /* Fill PDCCH DL DCI PDU */ - nfapi_nr_dl_dci_pdu_t *dci_pdu = &pdcch_pdu->dci_pdu[pdcch_pdu->numDlDci]; + nfapi_nr_dl_dci_pdu_t *dci_pdu = prepare_dci_pdu(pdcch_pdu, + scc, + sched_ctrl->search_space, + sched_ctrl->coreset, + sched_ctrl->aggregation_level, + sched_ctrl->cce_index, + UE->UE_beam_index, + rnti); pdcch_pdu->numDlDci++; - dci_pdu->RNTI = rnti; - - if (sched_ctrl->coreset && - sched_ctrl->search_space && - sched_ctrl->coreset->pdcch_DMRS_ScramblingID && - sched_ctrl->search_space->searchSpaceType->present == NR_SearchSpace__searchSpaceType_PR_ue_Specific) { - dci_pdu->ScramblingId = *sched_ctrl->coreset->pdcch_DMRS_ScramblingID; - dci_pdu->ScramblingRNTI = rnti; - } else { - dci_pdu->ScramblingId = *scc->physCellId; - dci_pdu->ScramblingRNTI = 0; - } - - dci_pdu->AggregationLevel = sched_ctrl->aggregation_level; - dci_pdu->CceIndex = sched_ctrl->cce_index; - dci_pdu->beta_PDCCH_1_0 = 0; - dci_pdu->powerControlOffsetSS = 1; - - dci_pdu->precodingAndBeamforming.num_prgs = 0; - dci_pdu->precodingAndBeamforming.prg_size = 0; - dci_pdu->precodingAndBeamforming.dig_bf_interfaces = 0; - dci_pdu->precodingAndBeamforming.prgs_list[0].pm_idx = 0; - dci_pdu->precodingAndBeamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = UE->UE_beam_index; /* DCI payload */ const int rnti_type = TYPE_C_RNTI_; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 7b64cd93db..b894587854 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -809,6 +809,37 @@ int get_mcs_from_bler(const NR_bler_options_t *bler_options, return new_mcs; } +nfapi_nr_dl_dci_pdu_t *prepare_dci_pdu(nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu, + const NR_ServingCellConfigCommon_t *scc, + const NR_SearchSpace_t *ss, + const NR_ControlResourceSet_t *coreset, + int aggregation_level, + int cce_index, + int beam_index, + int rnti) +{ + nfapi_nr_dl_dci_pdu_t *dci_pdu = &pdcch_pdu->dci_pdu[pdcch_pdu->numDlDci]; + dci_pdu->RNTI = rnti; + dci_pdu->AggregationLevel = aggregation_level; + dci_pdu->CceIndex = cce_index; + if (coreset->pdcch_DMRS_ScramblingID && + ss->searchSpaceType->present == NR_SearchSpace__searchSpaceType_PR_ue_Specific) { + dci_pdu->ScramblingId = *coreset->pdcch_DMRS_ScramblingID; + dci_pdu->ScramblingRNTI = rnti; + } else { + dci_pdu->ScramblingId = *scc->physCellId; + dci_pdu->ScramblingRNTI = 0; + } + dci_pdu->beta_PDCCH_1_0 = 0; + dci_pdu->powerControlOffsetSS = 1; + dci_pdu->precodingAndBeamforming.num_prgs = 0; + dci_pdu->precodingAndBeamforming.prg_size = 0; + dci_pdu->precodingAndBeamforming.dig_bf_interfaces = 1; + dci_pdu->precodingAndBeamforming.prgs_list[0].pm_idx = 0; + dci_pdu->precodingAndBeamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = beam_index; + return dci_pdu; +} + dci_pdu_rel15_t prepare_dci_dl_payload(const gNB_MAC_INST *gNB_mac, const NR_UE_info_t *UE, nr_rnti_type_t rnti_type, diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index f00aa988ee..2896de953c 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -2629,26 +2629,15 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, slot_t slot, nfapi_ LOG_D(NR_MAC,"Configuring ULDCI/PDCCH in %d.%d at CCE %d, rnti %04x\n", frame,slot,sched_ctrl->cce_index,rnti); /* Fill PDCCH DL DCI PDU */ - nfapi_nr_dl_dci_pdu_t *dci_pdu = &pdcch_pdu->dci_pdu[pdcch_pdu->numDlDci]; + nfapi_nr_dl_dci_pdu_t *dci_pdu = prepare_dci_pdu(pdcch_pdu, + scc, + ss, + coreset, + sched_ctrl->aggregation_level, + sched_ctrl->cce_index, + UE->UE_beam_index, + rnti); pdcch_pdu->numDlDci++; - dci_pdu->RNTI = rnti; - if (coreset->pdcch_DMRS_ScramblingID && - ss->searchSpaceType->present == NR_SearchSpace__searchSpaceType_PR_ue_Specific) { - dci_pdu->ScramblingId = *coreset->pdcch_DMRS_ScramblingID; - dci_pdu->ScramblingRNTI = rnti; - } else { - dci_pdu->ScramblingId = *scc->physCellId; - dci_pdu->ScramblingRNTI = 0; - } - dci_pdu->AggregationLevel = sched_ctrl->aggregation_level; - dci_pdu->CceIndex = sched_ctrl->cce_index; - dci_pdu->beta_PDCCH_1_0 = 0; - dci_pdu->powerControlOffsetSS = 1; - dci_pdu->precodingAndBeamforming.num_prgs = 0; - dci_pdu->precodingAndBeamforming.prg_size = 0; - dci_pdu->precodingAndBeamforming.dig_bf_interfaces = 1; - dci_pdu->precodingAndBeamforming.prgs_list[0].pm_idx = 0; - dci_pdu->precodingAndBeamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = UE->UE_beam_index; dci_pdu_rel15_t uldci_payload; memset(&uldci_payload, 0, sizeof(uldci_payload)); diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index bebf7e4ece..a817378534 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -180,6 +180,15 @@ dci_pdu_rel15_t prepare_dci_dl_payload(const gNB_MAC_INST *gNB_mac, int harq_pid, int tb_scaling, bool is_sib1); +nfapi_nr_dl_dci_pdu_t *prepare_dci_pdu(nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu, + const NR_ServingCellConfigCommon_t *scc, + const NR_SearchSpace_t *ss, + const NR_ControlResourceSet_t *coreset, + int aggregation_level, + int cce_index, + int beam_index, + int rnti); + void nr_schedule_pucch(gNB_MAC_INST *nrmac, frame_t frameP, slot_t slotP); void nr_srs_ri_computation(const nfapi_nr_srs_normalized_channel_iq_matrix_t *nr_srs_normalized_channel_iq_matrix, From 5d04408f5c69cf2d24a36ec61021143aacc1e947 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 26 Jun 2025 12:08:08 +0200 Subject: [PATCH 165/964] Incorporate ru_stats_thread() stats into nrL1_stats.log Do not pollute periodic output, and rather print those into nrL1_stats.log. A number of them are already there anyway, so transfer the rest. Note: ru->ifdevice.tx_fhaul is omitted, as we don't have any IF5 split in 5G. --- ci-scripts/datalog_rt_stats.100.2x2.yaml | 6 ++++ ci-scripts/datalog_rt_stats.1x1.60.yaml | 6 ++++ ci-scripts/datalog_rt_stats.60.2x2.yaml | 6 ++++ ci-scripts/datalog_rt_stats.default.yaml | 6 ++++ executables/nr-gnb.c | 16 ++++++++-- executables/nr-ru.c | 37 ------------------------ 6 files changed, 38 insertions(+), 39 deletions(-) diff --git a/ci-scripts/datalog_rt_stats.100.2x2.yaml b/ci-scripts/datalog_rt_stats.100.2x2.yaml index 024dfa8e9e..7c5cb48add 100644 --- a/ci-scripts/datalog_rt_stats.100.2x2.yaml +++ b/ci-scripts/datalog_rt_stats.100.2x2.yaml @@ -19,6 +19,9 @@ Ref : DL & UL scheduling timing : 17.0 UL Indication : 1.0 Slot Indication : 13.0 + feprx : 151.0 + feptx_ofdm (per port, half_slot) : 57 + feptx_total : 148 DeviationThreshold : feprx : 0.25 feptx_prec : 0.25 @@ -32,3 +35,6 @@ DeviationThreshold : DL & UL scheduling timing : 0.25 UL Indication : 1.00 Slot Indication : 0.50 + feprx : 0.25 + feptx_ofdm (per port, half_slot) : 0.25 + feptx_total : 0.25 diff --git a/ci-scripts/datalog_rt_stats.1x1.60.yaml b/ci-scripts/datalog_rt_stats.1x1.60.yaml index 85075bac97..5e0564977b 100644 --- a/ci-scripts/datalog_rt_stats.1x1.60.yaml +++ b/ci-scripts/datalog_rt_stats.1x1.60.yaml @@ -19,6 +19,9 @@ Ref : DL & UL scheduling timing : 5.0 UL Indication : 1.0 Slot Indication : 6.0 + feprx : 44.0 + feptx_ofdm (per port, half_slot) : 31 + feptx_total : 58 DeviationThreshold : feprx : 0.25 feptx_prec : 0.25 @@ -32,3 +35,6 @@ DeviationThreshold : DL & UL scheduling timing : 0.50 UL Indication : 1.00 Slot Indication : 0.50 + feprx : 0.25 + feptx_ofdm (per port, half_slot) : 0.25 + feptx_total : 0.25 diff --git a/ci-scripts/datalog_rt_stats.60.2x2.yaml b/ci-scripts/datalog_rt_stats.60.2x2.yaml index b371356971..7352136764 100644 --- a/ci-scripts/datalog_rt_stats.60.2x2.yaml +++ b/ci-scripts/datalog_rt_stats.60.2x2.yaml @@ -19,6 +19,9 @@ Ref : DL & UL scheduling timing : 8.0 UL Indication : 3.0 Slot Indication : 9.0 + feprx : 85.0 + feptx_ofdm (per port, half_slot) : 31 + feptx_total : 92 DeviationThreshold : feprx : 0.25 feptx_prec : 0.25 @@ -32,3 +35,6 @@ DeviationThreshold : DL & UL scheduling timing : 0.35 UL Indication : 1.00 Slot Indication : 0.35 + feprx : 0.25 + feptx_ofdm (per port, half_slot) : 0.25 + feptx_total : 0.25 diff --git a/ci-scripts/datalog_rt_stats.default.yaml b/ci-scripts/datalog_rt_stats.default.yaml index 32977944a0..be3f8b277e 100644 --- a/ci-scripts/datalog_rt_stats.default.yaml +++ b/ci-scripts/datalog_rt_stats.default.yaml @@ -19,6 +19,9 @@ Ref : DL & UL scheduling timing : 4.0 UL Indication : 2.0 Slot Indication : 5.0 + feprx : 43.0 + feptx_ofdm (per port, half_slot) : 30 + feptx_total : 57 DeviationThreshold : feprx : 0.25 feptx_prec : 0.25 @@ -32,3 +35,6 @@ DeviationThreshold : DL & UL scheduling timing : 0.50 UL Indication : 1.00 Slot Indication : 0.50 + feprx : 0.25 + feptx_ofdm (per port, half_slot) : 0.25 + feptx_total : 0.25 diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index acab30751b..af2dede07f 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -239,14 +239,26 @@ static size_t dump_L1_meas_stats(PHY_VARS_gNB *gNB, RU_t *ru, char *output, size if (ru->feprx) output += print_meas_log(&ru->ofdm_demod_stats, "feprx", NULL, NULL, output, end - output); + bool full_slot = ru->half_slot_parallelization == 0; if (ru->feptx_prec) { - output += print_meas_log(&ru->precoding_stats,"feptx_prec",NULL,NULL, output, end - output); + output += print_meas_log(&ru->precoding_stats, + full_slot ? "feptx_prec (per port)" : "feptx_prec (per port, half_slot)", + NULL, + NULL, + output, + end - output); } if (ru->feptx_ofdm) { output += print_meas_log(&ru->txdataF_copy_stats,"txdataF_copy",NULL,NULL, output, end - output); - output += print_meas_log(&ru->ofdm_mod_stats,"feptx_ofdm",NULL,NULL, output, end - output); + output += print_meas_log(&ru->ofdm_mod_stats, + full_slot ? "feptx_ofdm (per port)" : "feptx_ofdm (per port, half_slot)", + NULL, + NULL, + output, + end - output); output += print_meas_log(&ru->ofdm_total_stats,"feptx_total",NULL,NULL, output, end - output); + output += print_meas_log(&ru->txdataF_copy_stats, "txdataF_copy", NULL, NULL, output, end - output); } if (ru->fh_north_asynch_in) diff --git a/executables/nr-ru.c b/executables/nr-ru.c index 411caf9a63..21fff0cd5a 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -992,36 +992,6 @@ int setup_RU_buffers(RU_t *ru) return(0); } -void *ru_stats_thread(void *param) { - RU_t *ru = (RU_t *)param; - wait_sync("ru_stats_thread"); - - while (!oai_exit) { - sleep(1); - - if (cpu_meas_enabled) { - if (ru->feprx) print_meas(&ru->ofdm_demod_stats,"feprx (all ports)",NULL,NULL); - - if (ru->feptx_ofdm) { - print_meas(&ru->precoding_stats,(ru->half_slot_parallelization==0)?"feptx_prec (per port)":"feptx_prec (per port, half_slot)",NULL,NULL); - print_meas(&ru->ofdm_mod_stats,(ru->half_slot_parallelization==0)?"feptx_ofdm (per port)":"feptx_ofdm (per port, half_slot)",NULL,NULL); - print_meas(&ru->txdataF_copy_stats,"txdataF_copy",NULL,NULL); - print_meas(&ru->ofdm_total_stats,"feptx_total",NULL,NULL); - } - print_meas(&ru->rx_fhaul,"rx_fhaul",NULL,NULL); - if (ru->if_south == REMOTE_IF5) print_meas(&ru->ifdevice.tx_fhaul,"tx_fhaul (IF5)",NULL,NULL); - else print_meas(&ru->tx_fhaul,"tx_fhaul",NULL,NULL); - - if (ru->fh_north_out) { - print_meas(&ru->compression,"compression",NULL,NULL); - print_meas(&ru->transport,"transport",NULL,NULL); - } - } - } - - return(NULL); -} - void ru_tx_func(void *param) { processingData_RU_t *info = (processingData_RU_t *) param; @@ -1399,8 +1369,6 @@ void init_RU_proc(RU_t *ru) { if(emulate_rf) threadCreate( &proc->pthread_emulateRF, emulatedRF_thread, (void *)proc, "emulateRF", -1, OAI_PRIORITY_RT ); - if (cpu_meas_enabled) - threadCreate(&ru->ru_stats_thread, ru_stats_thread, (void *)ru, "ru_stats", -1, OAI_PRIORITY_RT); LOG_I(PHY, "Initialized RU proc %d (%s,%s),\n", ru->idx, NB_functions[ru->function], NB_timing[ru->if_timing]); } @@ -1430,11 +1398,6 @@ void kill_NR_RU_proc(int inst) { pthread_mutex_unlock( &proc->mutex_fep[0] ); pthread_join(proc->pthread_FH, NULL); - if (cpu_meas_enabled) { - LOG_D(PHY, "Joining ru_stats_thread\n"); - pthread_join(ru->ru_stats_thread, NULL); - } - // everything should be stopped now, we can safely stop the RF device if (ru->stop_rf == NULL) { LOG_W(PHY, "No stop_rf() for RU %d defined, cannot stop RF!\n", ru->idx); From 786c9f26d59d689fb6943734d446c541c01af9e2 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 30 Jun 2025 18:48:53 +0200 Subject: [PATCH 166/964] Remove ctest option --output-on-failure in CI Remove this option: some tests produce an excessive amount of output on failure (e.g., googletest/benchmark). This seems to overwhelm the Python CI code. Suppress this output, because we can always manually run this test. A high-level "this test is ok/nok" should be fine for the CI. --- ci-scripts/cls_containerize.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index 12355ef6d7..b878e82caa 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -687,7 +687,7 @@ class Containerize(): HTML.CreateHtmlTestRowQueue("Build unit tests", 'OK', [dockerfile]) # it worked, build and execute tests, and close connection - ret = cmd.run(f'docker run -a STDOUT --workdir /oai-ran/build/ --env LD_LIBRARY_PATH=/oai-ran/build/ --rm ran-unittests:{baseTag} ctest --output-on-failure --no-label-summary -j$(nproc)') + ret = cmd.run(f'docker run -a STDOUT --workdir /oai-ran/build/ --env LD_LIBRARY_PATH=/oai-ran/build/ --rm ran-unittests:{baseTag} ctest --no-label-summary -j$(nproc)') cmd.run(f'docker rmi ran-unittests:{baseTag}') build_log_name = f'build_log_{self.testCase_id}' CopyLogsToExecutor(cmd, lSourcePath, build_log_name) From 5fb72906f38e33eeca790b4c923d099102fa0480 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Tue, 1 Jul 2025 07:48:21 +0000 Subject: [PATCH 167/964] gNB: fix NTN UL retransmissions Re-add to consider the cellSpecificKoffset_r17 for UL retransmissions. This got lost in commit c8387d706cbd7b0f4905b718bb4c84996e412966 --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 534b955f7b..c7f29a2c39 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -1804,8 +1804,8 @@ static bool allocate_ul_retransmission(gNB_MAC_INST *nrmac, sched_ctrl->cce_index = CCEIndex; fill_pdcch_vrb_map(nrmac, CC_id, &sched_ctrl->sched_pdcch, CCEIndex, sched_ctrl->aggregation_level, dci_beam_idx); int slots_frame = nrmac->frame_structure.numb_slots_frame; - retInfo->frame = (frame + (slot + tda_info.k2) / slots_frame) % MAX_FRAME_NUMBER; - retInfo->slot = (slot + tda_info.k2) % slots_frame; + retInfo->frame = (frame + (slot + tda_info.k2 + get_NTN_Koffset(scc)) / slots_frame) % MAX_FRAME_NUMBER; + retInfo->slot = (slot + tda_info.k2 + get_NTN_Koffset(scc)) % slots_frame; /* Get previous PSUCH field info */ sched_ctrl->sched_pusch = *retInfo; NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch; From 75be2a1a5957da991adf2cb531e62ff53b249a44 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 15 May 2025 12:53:14 +0200 Subject: [PATCH 168/964] When freeing UE contexts, check in both possible lists --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 2 +- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index e398da1eaf..698986354a 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -2242,7 +2242,7 @@ void nr_release_ra_UE(gNB_MAC_INST *mac, rnti_t rnti) if (UE) { delete_nr_ue_data(UE, mac->common_channels, &UE_info->uid_allocator); } else { - LOG_W(NR_MAC,"Call to del rnti %04x, but not existing\n", rnti); + LOG_W(NR_MAC,"Call to release RA UE with rnti %04x, but not existing\n", rnti); } } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index a447d9f91c..898722342b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -2621,6 +2621,8 @@ NR_UE_info_t *remove_UE_from_list(int list_size, NR_UE_info_t *list[list_size], { for (int i = 0; i < list_size; i++) { NR_UE_info_t *curr_UE = list[i]; + if (!curr_UE) + break; /* reached the end of the list */ if (curr_UE->rnti != rnti) continue; @@ -2629,7 +2631,6 @@ NR_UE_info_t *remove_UE_from_list(int list_size, NR_UE_info_t *list[list_size], list[list_size - 1] = NULL; return curr_UE; } - LOG_E(NR_MAC, "UE %04x to be removed not found in list\n", rnti); return NULL; } @@ -2735,8 +2736,10 @@ void mac_remove_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rnti) NR_SCHED_LOCK(&UE_info->mutex); NR_UE_info_t *UE = remove_UE_from_list(MAX_MOBILES_PER_GNB + 1, UE_info->connected_ue_list, rnti); NR_SCHED_UNLOCK(&UE_info->mutex); - - delete_nr_ue_data(UE, nr_mac->common_channels, &UE_info->uid_allocator); + if (UE) + delete_nr_ue_data(UE, nr_mac->common_channels, &UE_info->uid_allocator); + else + nr_release_ra_UE(nr_mac, rnti); } // all values passed to this function are in dB x10 From 1e6fb953a80877050d2f2de90ab470a9ce60533a Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 2 Jul 2025 18:45:14 +0200 Subject: [PATCH 169/964] Workaround: limit signal range for 2x2 RFsim test Limit the signal range to avoid clipping, leading to retransmissions in the 2x2. --- ci-scripts/conf_files/gnb.sa.band78.273prb.rfsim.2x2.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/ci-scripts/conf_files/gnb.sa.band78.273prb.rfsim.2x2.conf b/ci-scripts/conf_files/gnb.sa.band78.273prb.rfsim.2x2.conf index f158cb42bb..a9ef28fa5b 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.273prb.rfsim.2x2.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.273prb.rfsim.2x2.conf @@ -185,6 +185,7 @@ L1s = ( num_cc = 1; tr_n_preference = "local_mac"; prach_dtx_threshold = 120; + tx_amp_backoff_dB = 30; } ); From 6a1203bb159c5b30cf40e2c364306ab84af11916 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 30 Jun 2025 09:49:05 +0200 Subject: [PATCH 170/964] Set RRC reject waitTime to 10 --- openair2/RRC/NR/MESSAGES/asn1_msg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.c b/openair2/RRC/NR/MESSAGES/asn1_msg.c index ad973bdc5f..0f7ec6db1a 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.c +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.c @@ -248,7 +248,7 @@ int do_RRCReject(uint8_t *const buffer) rrcReject->criticalExtensions.choice.rrcReject = CALLOC(1, sizeof(struct NR_RRCReject_IEs)); rrcReject->criticalExtensions.choice.rrcReject->waitTime = CALLOC(1, sizeof(NR_RejectWaitTime_t)); - *rrcReject->criticalExtensions.choice.rrcReject->waitTime = 1; + *rrcReject->criticalExtensions.choice.rrcReject->waitTime = 10; rrcReject->criticalExtensions.present = NR_RRCReject__criticalExtensions_PR_rrcReject; From 511f2f2487e69d0032e8fef74f161113be03f463 Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 2 Jan 2025 17:22:35 +0100 Subject: [PATCH 171/964] generate RRCReject if no DU to CU container in initial UL RRC message slightly refactor rrc_gNB_generate_RRCReject() to take rrc pointer. Remove unused/illegal fields from the DL RRC message. --- openair2/RRC/NR/rrc_gNB.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 2ef11ce605..844cc1a104 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -393,10 +393,9 @@ static void rrc_gNB_generate_RRCSetup(instance_t instance, rrc->mac_rrc.dl_rrc_message_transfer(ue_data.du_assoc_id, &dl_rrc); } -static void rrc_gNB_generate_RRCReject(module_id_t module_id, rrc_gNB_ue_context_t *const ue_context_pP) +static void rrc_gNB_generate_RRCReject(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *const ue_context_pP) //----------------------------------------------------------------------------- { - gNB_RRC_INST *rrc = RC.nrrrc[module_id]; gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; LOG_A(NR_RRC, "Send RRCReject to RNTI %04x\n", ue_p->rnti); @@ -420,10 +419,10 @@ static void rrc_gNB_generate_RRCReject(module_id_t module_id, rrc_gNB_ue_context .rrc_container = buf, .rrc_container_length = size, .srb_id = srbid, - .execute_duplication = 1, - .RAT_frequency_priority_information.en_dc = 0 }; rrc->mac_rrc.dl_rrc_message_transfer(ue_data.du_assoc_id, &dl_rrc); + /* release the created UE context, we rejected the UE */ + rrc_remove_ue(rrc, ue_context_pP); } //----------------------------------------------------------------------------- @@ -1135,10 +1134,17 @@ static void rrc_handle_RRCSetupRequest(gNB_RRC_INST *rrc, ue_context_p = rrc_gNB_create_ue_context(assoc_id, msg->crnti, rrc, random_value, msg->gNB_DU_ue_id); LOG_E(NR_RRC, "RRCSetupRequest without random UE identity or S-TMSI not supported, let's reject the UE %04x\n", msg->crnti); - rrc_gNB_generate_RRCReject(0, ue_context_p); + rrc_gNB_generate_RRCReject(rrc, ue_context_p); return; } + // If the DU to CU RRC Container IE is not included in the INITIAL UL RRC MESSAGE TRANSFER, + // the gNB-CU should reject the UE under the assumption that the gNB-DU is not able to serve such UE + if (msg->du2cu_rrc_container == NULL) { + // this will remove the UE context + rrc_gNB_generate_RRCReject(rrc, ue_context_p); + return; + } NR_CellGroupConfig_t *cellGroupConfig = NULL; asn_dec_rval_t dec_rval = uper_decode_complete(NULL, &asn_DEF_NR_CellGroupConfig, From 69ac704adcc11c5cedc17635ed0e90e32e56b17a Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 2 Jan 2025 18:21:18 +0100 Subject: [PATCH 172/964] do not send DU to CU container to CU if we can't serve the UE --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 26 ++++++++++++++----- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 12 ++++++--- .../LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 9 +++++-- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 2 +- openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c | 6 ++++- 5 files changed, 41 insertions(+), 14 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index e398da1eaf..cbf414fb31 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -2077,7 +2077,7 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, } } -void nr_check_Msg4_MsgB_Ack(module_id_t module_id, frame_t frame, slot_t slot, NR_UE_info_t *UE, bool success) +bool nr_check_Msg4_MsgB_Ack(module_id_t module_id, frame_t frame, slot_t slot, NR_UE_info_t *UE, bool success) { NR_RA_t *ra = UE->ra; const char *ra_type_str = ra->ra_type == RA_2_STEP ? "MsgB" : "Msg4"; @@ -2092,10 +2092,21 @@ void nr_check_Msg4_MsgB_Ack(module_id_t module_id, frame_t frame, slot_t slot, N if (success) { gNB_MAC_INST *nr_mac = RC.nrmac[module_id]; NR_ServingCellConfigCommon_t *scc = nr_mac->common_channels[0].ServingCellConfigCommon; - // we configure the UE using common search space with DCIX0 while waiting for a reconfiguration - configure_UE_BWP(nr_mac, scc, UE, false, NR_SearchSpace__searchSpaceType_PR_common, -1, -1); - transition_ra_connected_nr_ue(nr_mac, UE); - LOG_A(NR_MAC, "%4d.%2d UE %04x: Received Ack of %s. CBRA procedure succeeded!\n", frame, slot, UE->rnti, ra_type_str); + LOG_A(NR_MAC, + "%4d.%2d UE %04x: Received Ack of %s. CBRA procedure succeeded (%s)\n", + frame, + slot, + UE->rnti, + ra_type_str, + UE->CellGroup ? "UE Connected" : "UE Rejected"); + if (UE->CellGroup) { + // we configure the UE using common search space with DCIX0 while waiting for a reconfiguration + configure_UE_BWP(nr_mac, scc, UE, false, NR_SearchSpace__searchSpaceType_PR_common, -1, -1); + transition_ra_connected_nr_ue(nr_mac, UE); + } else { // in case of UE reject + nr_release_ra_UE(nr_mac, UE->rnti); + return true; + } } else { LOG_I(NR_MAC, "%4d.%2d UE %04x: RA Procedure failed at %s!\n", frame, slot, UE->rnti, ra_type_str); nr_mac_trigger_ul_failure(sched_ctrl, UE->current_DL_BWP.scs); @@ -2108,6 +2119,7 @@ void nr_check_Msg4_MsgB_Ack(module_id_t module_id, frame_t frame, slot_t slot, N LOG_I(NR_MAC, "(UE %04x) Received Nack in %s, preparing retransmission!\n", UE->rnti, ra_type_str); ra->ra_state = ra->ra_type == RA_4_STEP ? nrRA_Msg4 : nrRA_MsgB; } + return false; } ///////////////////////////////////// @@ -2269,7 +2281,9 @@ void nr_schedule_RA(module_id_t module_idP, ra->contention_resolution_timer--; if (ra->contention_resolution_timer == 0) { LOG_W(NR_MAC, "(%d.%d) RA Contention Resolution timer expired for UE 0x%04x, RA procedure failed...\n", frameP, slotP, UE->rnti); - bool requested = nr_mac_request_release_ue(mac, UE->rnti); + bool requested = false; + if (UE->CellGroup) // request if we did not reject the UE + requested = nr_mac_request_release_ue(mac, UE->rnti); if (!requested) nr_release_ra_UE(mac, UE->rnti); continue; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index a447d9f91c..82fa6d828b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -3297,7 +3297,9 @@ void send_initial_ul_rrc_message(int rnti, const uint8_t *sdu, sdu_size_t sdu_le NR_SCHED_ENSURE_LOCKED(&mac->sched_lock); uint8_t du2cu[1024]; - int encoded = encode_cellGroupConfig(UE->CellGroup, du2cu, sizeof(du2cu)); + int encoded_len = 0; + if (UE->CellGroup) + encoded_len = encode_cellGroupConfig(UE->CellGroup, du2cu, sizeof(du2cu)); DevAssert(mac->f1_config.setup_req != NULL); AssertFatal(mac->f1_config.setup_req->num_cells_available == 1, "can handle only one cell\n"); @@ -3308,8 +3310,8 @@ void send_initial_ul_rrc_message(int rnti, const uint8_t *sdu, sdu_size_t sdu_le .crnti = rnti, .rrc_container = (uint8_t *) sdu, .rrc_container_length = sdu_len, - .du2cu_rrc_container = (uint8_t *) du2cu, - .du2cu_rrc_container_length = encoded + .du2cu_rrc_container = encoded_len ? (uint8_t *) du2cu : NULL, + .du2cu_rrc_container_length = encoded_len }; mac->mac_rrc.initial_ul_rrc_message_transfer(0, &ul_rrc_msg); } @@ -3331,12 +3333,14 @@ bool prepare_initial_ul_rrc_message(gNB_MAC_INST *mac, NR_UE_info_t *UE) ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->CellGroup); UE->CellGroup = cellGroupConfig; + if (!cellGroupConfig) + return true; + /* the cellGroup sent to CU specifies there is SRB1, so create it */ DevAssert(cellGroupConfig->rlc_BearerToAddModList->list.count == 1); const NR_RLC_BearerConfig_t *bearer = cellGroupConfig->rlc_BearerToAddModList->list.array[0]; DevAssert(bearer->servedRadioBearer->choice.srb_Identity == srb_id); nr_rlc_add_srb(UE->rnti, bearer->servedRadioBearer->choice.srb_Identity, bearer); - int priority = bearer->mac_LogicalChannelConfig->ul_SpecificParameters->priority; nr_lc_config_t c = {.lcid = bearer->logicalChannelIdentity, .priority = priority}; nr_mac_add_lcid(&UE->UE_sched_ctrl, &c); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index 29ff27d38e..00201cdd8d 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -899,8 +899,13 @@ void handle_nr_uci_pucch_0_1(module_id_t mod_id, frame_t frame, slot_t slot, con nr_mac_update_pdcch_closed_loop_adjust(sched_ctrl, harq_confidence != 0); bool success = harq_value == 0 && harq_confidence == 0; handle_dl_harq(UE, pid, success, nrmac->dl_bler.harq_round_max); - if (is_ra) - nr_check_Msg4_MsgB_Ack(mod_id, frame, slot, UE, success); + if (is_ra) { + bool ue_rejected = nr_check_Msg4_MsgB_Ack(mod_id, frame, slot, UE, success); + if (ue_rejected) { + NR_SCHED_UNLOCK(&nrmac->sched_lock); + return; + } + } if (harq_confidence == 1) UE->mac_stats.pucch0_DTX++; } diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 6acf4ae1d8..028cfcb0b2 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -319,7 +319,7 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac, bool transition_ra_connected_nr_ue(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE); bool add_connected_nr_ue(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE); -void nr_check_Msg4_MsgB_Ack(module_id_t module_id, frame_t frame, slot_t slot, NR_UE_info_t *UE, bool success); +bool nr_check_Msg4_MsgB_Ack(module_id_t module_id, frame_t frame, slot_t slot, NR_UE_info_t *UE, bool success); void mac_remove_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rnti); NR_UE_info_t *get_new_nr_ue_inst(uid_allocator_t *uia, rnti_t rnti, NR_CellGroupConfig_t *CellGroup); int nr_get_default_pucch_res(int pucch_ResourceCommon); diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c index 41ace5014b..d0d37bbab5 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c @@ -3498,6 +3498,10 @@ NR_CellGroupConfig_t *get_initial_cellGroupConfig(int uid, const nr_mac_config_t *configuration, const nr_rlc_configuration_t *default_rlc_config) { + NR_SpCellConfig_t *spCellConfig = get_initial_SpCellConfig(uid, scc, servingcellconfigdedicated, configuration); + if (!spCellConfig) + return NULL; + NR_CellGroupConfig_t *cellGroupConfig = calloc(1, sizeof(*cellGroupConfig)); cellGroupConfig->cellGroupId = 0; @@ -3515,7 +3519,7 @@ NR_CellGroupConfig_t *get_initial_cellGroupConfig(int uid, cellGroupConfig->physicalCellGroupConfig = configure_phy_cellgroup(); - cellGroupConfig->spCellConfig = get_initial_SpCellConfig(uid, scc, servingcellconfigdedicated, configuration); + cellGroupConfig->spCellConfig = spCellConfig; cellGroupConfig->sCellToAddModList = NULL; cellGroupConfig->sCellToReleaseList = NULL; From 88af2860a2966b169989835417f4e5268ee84e10 Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 9 Jan 2025 19:21:36 +0100 Subject: [PATCH 173/964] handle RRC reject at UE --- openair2/LAYER2/NR_MAC_UE/config_ue.c | 5 ++++ openair2/LAYER2/NR_MAC_UE/mac_defs.h | 2 ++ openair2/LAYER2/NR_MAC_UE/mac_proto.h | 5 +--- openair2/RRC/NR_UE/rrc_UE.c | 41 +++++++++++++++++++++++++-- 4 files changed, 47 insertions(+), 6 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index bfea78d540..9bdbeebe10 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -1725,6 +1725,11 @@ void nr_rrc_mac_config_req_reset(module_id_t module_id, NR_UE_MAC_reset_cause_t reset_mac_inst(mac); mac->state = UE_PERFORMING_RA; // still in sync but need to restart RA break; + case REJECT: + reset_ra(mac, false); + reset_mac_inst(mac); + mac->state = UE_BARRED; + break; case RE_ESTABLISHMENT: reset_mac_inst(mac); nr_ue_mac_default_configs(mac); diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index dee2a30c08..0174e88abc 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -148,6 +148,7 @@ // Define the UE L2 states with X-Macro #define NR_UE_L2_STATES \ UE_STATE(UE_NOT_SYNC) \ + UE_STATE(UE_BARRED) \ UE_STATE(UE_RECEIVING_SIB) \ UE_STATE(UE_PERFORMING_RA) \ UE_STATE(UE_CONNECTED) \ @@ -199,6 +200,7 @@ typedef enum { RE_ESTABLISHMENT, RRC_SETUP_REESTAB_RESUME, UL_SYNC_LOST_T430_EXPIRED, + REJECT, } 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 c8eab85462..0a7365ef5d 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -87,10 +87,7 @@ void nr_rrc_mac_config_req_cg(module_id_t module_id, NR_CellGroupConfig_t *cell_group_config, NR_UE_NR_Capability_t *ue_Capability); -void nr_rrc_mac_config_req_mib(module_id_t module_id, - int cc_idP, - NR_MIB_t *mibP, - int sched_sib1); +void nr_rrc_mac_config_req_mib(module_id_t module_id, int cc_idP, NR_MIB_t *mibP, int sched_sib1); void nr_rrc_mac_config_req_sib1(module_id_t module_id, int cc_idP, NR_SIB1_t *sib1, bool can_start_ra); diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 90713ff50c..af0c1350c1 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -1394,8 +1394,44 @@ static void nr_rrc_process_rrcsetup(NR_UE_RRC_INST_t *rrc, const NR_RRCSetup_t * rrc_ue_generate_RRCSetupComplete(rrc, rrcSetup->rrc_TransactionIdentifier); } -static int8_t nr_rrc_ue_decode_ccch(NR_UE_RRC_INST_t *rrc, - const NRRrcMacCcchDataInd *ind) +static void nr_rrc_process_rrcreject(NR_UE_RRC_INST_t *rrc, const NR_RRCReject_t *rrcReject) +{ + // stop timer T300, T302, T319 if running; + NR_UE_Timers_Constants_t *timers = &rrc->timers_and_constants; + nr_timer_stop(&timers->T300); + nr_timer_stop(&timers->T302); + nr_timer_stop(&timers->T319); + + // reset MAC and release the default MAC Cell Group configuration + NR_UE_MAC_reset_cause_t cause = REJECT; + 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); + + // if waitTime is configured in the RRCReject: start timer T302, with the timer value set to the waitTime + NR_RejectWaitTime_t *waitTime = NULL; + if (rrcReject->criticalExtensions.present == NR_RRCReject__criticalExtensions_PR_rrcReject) { + NR_RRCReject_IEs_t *ies = rrcReject->criticalExtensions.choice.rrcReject; + waitTime = ies->waitTime; // Wait time value in seconds + } + if (waitTime) { + nr_timer_setup(&timers->T302, *waitTime * 1000, 10); + nr_timer_start(&timers->T302); + } else { + LOG_W(RRC, "Error: waitTime should be always included in RRCReject message\n"); + } + + // TODO if RRCReject is received in response to a request from upper layers + // inform the upper layer that access barring is applicable for all access categories except categories '0' and '2' + + // TODO if RRCReject is received in response to an RRCSetupRequest + // inform upper layers about the failure to setup the RRC connection, upon which the procedure ends + + // TODO else if RRCReject is received in response to an RRCResumeRequest or an RRCResumeRequest1 + // Resume not implemented yet +} + +static int8_t nr_rrc_ue_decode_ccch(NR_UE_RRC_INST_t *rrc, const NRRrcMacCcchDataInd *ind) { NR_DL_CCCH_Message_t *dl_ccch_msg = NULL; asn_dec_rval_t dec_rval; @@ -1423,6 +1459,7 @@ static int8_t nr_rrc_ue_decode_ccch(NR_UE_RRC_INST_t *rrc, case NR_DL_CCCH_MessageType__c1_PR_rrcReject: LOG_I(NR_RRC, "[UE%ld] Logical Channel DL-CCCH (SRB0), Received RRCReject \n", rrc->ue_id); + nr_rrc_process_rrcreject(rrc, dl_ccch_msg->message.choice.c1->choice.rrcReject); rval = 0; break; From 8932566d2b60aba067702f381af926d1d48d2d1c Mon Sep 17 00:00:00 2001 From: francescomani Date: Sun, 19 Jan 2025 10:34:42 +0100 Subject: [PATCH 174/964] improvements in T302 handling at RRC UE --- openair1/SIMULATION/NR_PHY/dlsim.c | 2 +- openair2/COMMON/rrc_messages_types.h | 1 + openair2/LAYER2/NR_MAC_UE/config_ue.c | 9 +++++- openair2/LAYER2/NR_MAC_UE/mac_proto.h | 2 +- openair2/RRC/NR_UE/L2_interface_ue.c | 6 +++- openair2/RRC/NR_UE/rrc_UE.c | 30 ++++++++++++++----- openair2/RRC/NR_UE/rrc_defs.h | 2 +- openair2/RRC/NR_UE/rrc_proto.h | 1 + openair2/RRC/NR_UE/rrc_timers_and_constants.c | 8 +++++ 9 files changed, 48 insertions(+), 13 deletions(-) diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index b858945018..a327abb2d0 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -953,7 +953,7 @@ printf("%d\n", slot); //Configure UE NR_BCCH_BCH_Message_t *mib = get_new_MIB_NR(scc); - nr_rrc_mac_config_req_mib(0, 0, mib->message.choice.mib, false); + nr_rrc_mac_config_req_mib(0, 0, mib->message.choice.mib, false, false); nr_rrc_mac_config_req_cg(0, 0, UE_CellGroup, UE_Capability_nr); asn1cFreeStruc(asn_DEF_NR_CellGroupConfig, UE_CellGroup); diff --git a/openair2/COMMON/rrc_messages_types.h b/openair2/COMMON/rrc_messages_types.h index 094fd0fa40..1d35619ecc 100644 --- a/openair2/COMMON/rrc_messages_types.h +++ b/openair2/COMMON/rrc_messages_types.h @@ -486,6 +486,7 @@ typedef struct { typedef struct { NR_BCCH_BCH_Message_t *bcch; int get_sib; + bool access_barred; } nr_mac_rrc_config_mib_t; typedef struct { NR_SIB1_t *sib1; diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index 9bdbeebe10..8624766bd1 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -955,7 +955,7 @@ static void update_mib_conf(NR_MIB_t *target, NR_MIB_t *source) target->intraFreqReselection = source->intraFreqReselection; } -void nr_rrc_mac_config_req_mib(module_id_t module_id, int cc_idP, NR_MIB_t *mib, int sched_sib) +void nr_rrc_mac_config_req_mib(module_id_t module_id, int cc_idP, NR_MIB_t *mib, int sched_sib, bool barred) { NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); int ret = pthread_mutex_lock(&mac->if_mutex); @@ -963,6 +963,13 @@ void nr_rrc_mac_config_req_mib(module_id_t module_id, int cc_idP, NR_MIB_t *mib, AssertFatal(mib, "MIB should not be NULL\n"); if (!mac->mib) mac->mib = calloc(1, sizeof(*mac->mib)); + if (barred) + mac->state = UE_BARRED; + else if (mac->state == UE_BARRED) { + // it is synched as we received MIB + // nr_ue_decode_mib is transitionining to the correct state + mac->state = UE_NOT_SYNC; + } update_mib_conf(mac->mib, mib); mac->phy_config.Mod_id = module_id; mac->phy_config.CC_id = cc_idP; diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index 0a7365ef5d..aacbbdcab2 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -87,7 +87,7 @@ void nr_rrc_mac_config_req_cg(module_id_t module_id, NR_CellGroupConfig_t *cell_group_config, NR_UE_NR_Capability_t *ue_Capability); -void nr_rrc_mac_config_req_mib(module_id_t module_id, int cc_idP, NR_MIB_t *mibP, int sched_sib1); +void nr_rrc_mac_config_req_mib(module_id_t module_id, int cc_idP, NR_MIB_t *mibP, int sched_sib1, bool barred); void nr_rrc_mac_config_req_sib1(module_id_t module_id, int cc_idP, NR_SIB1_t *sib1, bool can_start_ra); diff --git a/openair2/RRC/NR_UE/L2_interface_ue.c b/openair2/RRC/NR_UE/L2_interface_ue.c index fe2eb2cfed..6271957f4f 100644 --- a/openair2/RRC/NR_UE/L2_interface_ue.c +++ b/openair2/RRC/NR_UE/L2_interface_ue.c @@ -133,7 +133,11 @@ void process_msg_rcc_to_mac(MessageDef *msg) asn1cFreeStruc(asn_DEF_NR_CellGroupConfig, NR_MAC_RRC_CONFIG_CG(msg).cellGroupConfig); break; case NR_MAC_RRC_CONFIG_MIB: - nr_rrc_mac_config_req_mib(ue_id, 0, NR_MAC_RRC_CONFIG_MIB(msg).bcch->message.choice.mib, NR_MAC_RRC_CONFIG_MIB(msg).get_sib); + nr_rrc_mac_config_req_mib(ue_id, + 0, + NR_MAC_RRC_CONFIG_MIB(msg).bcch->message.choice.mib, + NR_MAC_RRC_CONFIG_MIB(msg).get_sib, + NR_MAC_RRC_CONFIG_MIB(msg).access_barred); ASN_STRUCT_FREE(asn_DEF_NR_BCCH_BCH_Message, NR_MAC_RRC_CONFIG_MIB(msg).bcch); break; case NR_MAC_RRC_CONFIG_SIB1: { diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index af0c1350c1..f858a10599 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -749,6 +749,7 @@ NR_UE_RRC_INST_t* nr_rrc_init_ue(char* uecap_file, int nb_inst, int num_ant_tx) rrc->reconfig_after_reestab = false; /* 5G-S-TMSI */ rrc->fiveG_S_TMSI = UINT64_MAX; + rrc->access_barred = false; FILE *f = NULL; if (uecap_file) @@ -959,11 +960,12 @@ static void nr_rrc_ue_decode_NR_BCCH_BCH_Message(NR_UE_RRC_INST_t *rrc, } NR_UE_RRC_SI_INFO *SI_info = &rrc->perNB[gNB_index].SInfo; + bool barred = rrc->access_barred || bcch_message->message.choice.mib->cellBarred == NR_MIB__cellBarred_barred; int get_sib = 0; if (IS_SA_MODE(get_softmodem_params()) && !SI_info->sib_pending && bcch_message->message.present == NR_BCCH_BCH_MessageType_PR_mib - && bcch_message->message.choice.mib->cellBarred == NR_MIB__cellBarred_notBarred + && !barred && rrc->nrRrcState != RRC_STATE_DETACH_NR) { // to schedule MAC to get SI if required get_sib = check_si_status(SI_info); @@ -975,6 +977,7 @@ static void nr_rrc_ue_decode_NR_BCCH_BCH_Message(NR_UE_RRC_INST_t *rrc, // mac will manage the pointer NR_MAC_RRC_CONFIG_MIB(msg).bcch = bcch_message; NR_MAC_RRC_CONFIG_MIB(msg).get_sib = get_sib; + NR_MAC_RRC_CONFIG_MIB(msg).access_barred = barred; itti_send_msg_to_task(TASK_MAC_UE, rrc->ue_id, msg); } else { LOG_E(NR_RRC, "RRC-received BCCH message is not a MIB\n"); @@ -1376,7 +1379,11 @@ static void nr_rrc_process_rrcsetup(NR_UE_RRC_INST_t *rrc, const NR_RRCSetup_t * nr_timer_stop(&timers->T319); nr_timer_stop(&timers->T320); - // TODO if T390 and T302 are running (not implemented) + // if T390 (not implemented) and T302 are running + // stop timer + // perform the actions as specified in 5.3.14.4 + nr_timer_stop(&timers->T302); + handle_302_expired_stopped(rrc); // if the RRCSetup is received in response to an RRCResumeRequest, RRCResumeRequest1 or RRCSetupRequest // enter RRC_CONNECTED @@ -1417,6 +1424,7 @@ static void nr_rrc_process_rrcreject(NR_UE_RRC_INST_t *rrc, const NR_RRCReject_t if (waitTime) { nr_timer_setup(&timers->T302, *waitTime * 1000, 10); nr_timer_start(&timers->T302); + rrc->access_barred = true; } else { LOG_W(RRC, "Error: waitTime should be always included in RRCReject message\n"); } @@ -1458,7 +1466,7 @@ static int8_t nr_rrc_ue_decode_ccch(NR_UE_RRC_INST_t *rrc, const NRRrcMacCcchDat break; case NR_DL_CCCH_MessageType__c1_PR_rrcReject: - LOG_I(NR_RRC, "[UE%ld] Logical Channel DL-CCCH (SRB0), Received RRCReject \n", rrc->ue_id); + LOG_W(NR_RRC, "[UE%ld] Logical Channel DL-CCCH (SRB0), Received RRCReject \n", rrc->ue_id); nr_rrc_process_rrcreject(rrc, dl_ccch_msg->message.choice.c1->choice.rrcReject); rval = 0; break; @@ -2777,17 +2785,16 @@ void nr_rrc_going_to_IDLE(NR_UE_RRC_INST_t *rrc, nr_timer_setup(&tac->T302, target, 10); nr_timer_start(&tac->T302); // TODO inform upper layers that access barring is applicable - // for all access categories except categories '0' and '2'. - LOG_E(NR_RRC,"Go to IDLE. Handling RRCRelease message including a waitTime not implemented\n"); + // for all access categories except categories '0' and '2'. + // for now we just set the access barred in RRC + rrc->access_barred = true; } } } if (!waitTime) { if (nr_timer_is_active(&tac->T302)) { nr_timer_stop(&tac->T302); - // TODO barring alleviation as in 5.3.14.4 - // not implemented - LOG_E(NR_RRC,"Go to IDLE. Barring alleviation not implemented\n"); + handle_302_expired_stopped(rrc); } } if (nr_timer_is_active(&tac->T390)) { @@ -2897,6 +2904,13 @@ void nr_rrc_going_to_IDLE(NR_UE_RRC_INST_t *rrc, itti_send_msg_to_task(TASK_NAS_NRUE, rrc->ue_id, msg_p); } +void handle_302_expired_stopped(NR_UE_RRC_INST_t *rrc) +{ + // for each Access Category for which T390 (TODO not implemented) is not running + // consider the barring for this Access Category to be alleviated + rrc->access_barred = false; +} + void handle_t300_expiry(NR_UE_RRC_INST_t *rrc) { rrc->ra_trigger = RRC_CONNECTION_SETUP; diff --git a/openair2/RRC/NR_UE/rrc_defs.h b/openair2/RRC/NR_UE/rrc_defs.h index 960dc1aaa0..c71f7697a2 100644 --- a/openair2/RRC/NR_UE/rrc_defs.h +++ b/openair2/RRC/NR_UE/rrc_defs.h @@ -205,7 +205,7 @@ typedef struct rrcPerNB { typedef struct NR_UE_RRC_INST_s { instance_t ue_id; rrcPerNB_t perNB[NB_CNX_UE]; - + bool access_barred; rnti_t rnti; uint32_t phyCellID; long arfcn_ssb; diff --git a/openair2/RRC/NR_UE/rrc_proto.h b/openair2/RRC/NR_UE/rrc_proto.h index 7c5f749fa0..bc7f7001af 100644 --- a/openair2/RRC/NR_UE/rrc_proto.h +++ b/openair2/RRC/NR_UE/rrc_proto.h @@ -64,6 +64,7 @@ void *rrc_nrue(void *args_p); void nr_rrc_handle_timers(NR_UE_RRC_INST_t *rrc); void handle_rlf_detection(NR_UE_RRC_INST_t *rrc); +void handle_302_expired_stopped(NR_UE_RRC_INST_t *rrc); /**\brief RRC NSA UE task. \param void *args_p Pointer on arguments to start the task. */ diff --git a/openair2/RRC/NR_UE/rrc_timers_and_constants.c b/openair2/RRC/NR_UE/rrc_timers_and_constants.c index 9286494f0b..57f6be2eb6 100644 --- a/openair2/RRC/NR_UE/rrc_timers_and_constants.c +++ b/openair2/RRC/NR_UE/rrc_timers_and_constants.c @@ -144,6 +144,14 @@ void nr_rrc_handle_timers(NR_UE_RRC_INST_t *rrc) nr_rrc_going_to_IDLE(rrc, RRC_CONNECTION_FAILURE, NULL); } + bool t302_expired = nr_timer_tick(&timers->T302); + // 5.3.14.4 in 38.331 + // consider the barring for this Access Category to be alleviated + if (t302_expired) { + LOG_W(NR_RRC, "Timer T302 expired! Access barring alleviated!\n"); + handle_302_expired_stopped(rrc); + } + bool t304_expired = nr_timer_tick(&timers->T304); if(t304_expired) { LOG_W(NR_RRC, "Timer T304 expired\n"); From f9cf458b1c1e613234d511803238fb68f2b33d37 Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 13 May 2025 11:00:52 +0200 Subject: [PATCH 175/964] function to verify if we can allocare RRC resources to UE with given ID --- openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c | 55 +++++++++++++++++--- 1 file changed, 49 insertions(+), 6 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c index d0d37bbab5..e3b750c796 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c @@ -238,6 +238,7 @@ static int get_nb_pucch2_per_slot(const NR_ServingCellConfigCommon_t *scc, int b int nb_pucch2 = (max_csi_reports / (available_report_occasions + 1)) + 1; // in current implementation we need (nb_pucch2 * PUCCH2_SIZE) prbs for PUCCH2 // and MAX_MOBILES_PER_GNB prbs for PUCCH1 + // checked for validity in verify_radio_configuration AssertFatal((nb_pucch2 * PUCCH2_SIZE) + MAX_MOBILES_PER_GNB <= bwp_size, "Cannot allocate all required PUCCH resources for max number of %d UEs in BWP with %d PRBs\n", MAX_MOBILES_PER_GNB, bwp_size); @@ -402,6 +403,7 @@ static void set_csirs_periodicity(NR_NZP_CSI_RS_Resource_t *nzpcsi0, else { nzpcsi0->periodicityAndOffset->present = NR_CSI_ResourcePeriodicityAndOffset_PR_slots320; const int nb_dl_slots_period = get_full_dl_slots_per_period(fs); // full DL slots + // checked for validity in verify_radio_configuration AssertFatal(offset / 320 < nb_dl_slots_period, "Cannot allocate CSI-RS for BWP %d. Not enough resources for CSI-RS\n", id); nzpcsi0->periodicityAndOffset->choice.slots320 = (offset % 320) + (offset / 320); } @@ -661,7 +663,7 @@ static struct NR_SRS_Resource__resourceType__periodic *configure_periodic_srs(co { frame_structure_t *fs = &RC.nrmac[0]->frame_structure; int offset = get_ul_slot_offset(fs, uid, false); // only full UL slots for SRS - + // checked for validity in verify_radio_configuration AssertFatal(offset < 2560, "Cannot allocate SRS configuration for uid %d, not enough resources\n", uid); const int ideal_period = set_ideal_period(false); @@ -1169,6 +1171,7 @@ static void config_pucch_resset0(NR_PUCCH_Config_t *pucch_Config, NR_PUCCH_Resource_t *pucchres0 = calloc(1,sizeof(*pucchres0)); pucchres0->pucch_ResourceId = *pucchid; pucchres0->startingPRB = (PUCCH2_SIZE * num_pucch2) + uid; + // checked for validity in verify_radio_configuration AssertFatal(pucchres0->startingPRB < curr_bwp, "Not enough resources in current BWP (size %d) to allocate uid %d\n", curr_bwp, uid); pucchres0->intraSlotFrequencyHopping = NULL; pucchres0->secondHopPRB = NULL; @@ -1745,13 +1748,11 @@ static void set_csi_meas_periodicity(const NR_ServingCellConfigCommon_t *scc, const int ideal_period = set_ideal_period(true); const int num_pucch2 = get_nb_pucch2_per_slot(scc, curr_bwp); const int idx = (uid * 2 / num_pucch2) + is_rsrp; - frame_structure_t *fs = &RC.nrmac[0]->frame_structure; int offset = get_ul_slot_offset(fs, idx, true); - LOG_D(NR_MAC, "set_csi_meas_periodicity: uid = %d, offset = %d, ideal_period = %d", uid, offset, ideal_period); + // checked for validity in verify_radio_configuration AssertFatal(offset < 320, "Not enough UL slots to accomodate all possible UEs. Need to rework the implementation\n"); - if (check_periodicity(4, ideal_period, fs)) { csirep->reportConfigType.choice.periodic->reportSlotConfig.present = NR_CSI_ReportPeriodicityAndOffset_PR_slots4; csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots4 = offset; @@ -3492,16 +3493,58 @@ NR_RLC_BearerConfig_t *get_DRB_RLC_BearerConfig(long lcChannelId, return rlc_BearerConfig; } +static bool verify_radio_configuration(int uid, const NR_ServingCellConfigCommon_t *scc, const NR_ServingCellConfig_t *scd) +{ + frame_structure_t *fs = &RC.nrmac[0]->frame_structure; + int srs_offset = get_ul_slot_offset(fs, uid, false); + // see configure_periodic_srs + if (srs_offset >= 2560) { + LOG_E(NR_RRC, "UID %d, cannot allocate resources for SRS, rejecting UE\n", uid); + return false; + } + + int n_dl_bwp = scd->downlinkBWP_ToAddModList ? scd->downlinkBWP_ToAddModList->list.count : 1; + int csi_offset = fs->numb_slots_period * n_dl_bwp; + // see set_csirs_periodicity + if (csi_offset / 320 >= get_full_dl_slots_per_period(fs)) { + LOG_E(NR_RRC, "UID %d, cannot allocate resources for CSI-RS, rejecting UE\n", uid); + return false; // cannot allocate resources for CSI-RS + } + + int curr_bwp = NRRIV2BW(scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + int num_pucch2 = get_nb_pucch2_per_slot(scc, curr_bwp); + int pucchres0_startingPRB = (PUCCH2_SIZE * num_pucch2) + uid; + // see config_pucch_resset0 + if (pucchres0_startingPRB >= curr_bwp) { + LOG_E(NR_RRC, "UID %d, cannot allocate resources for PUCCH0, rejecting UE\n", uid); + return false; // cannot allocate resources for PUCCH0 + } + // see get_nb_pucch2_per_slot + if ((num_pucch2 * PUCCH2_SIZE) + MAX_MOBILES_PER_GNB > curr_bwp) { + LOG_E(NR_RRC, "UID %d, cannot allocate resources for PUCCH2, rejecting UE\n", uid); + return false; // cannot allocate resources for PUCCH2 + } + const int idx = (uid * 2 / num_pucch2) + 1; + int offset = get_ul_slot_offset(fs, idx, true); + // see set_csi_meas_periodicity + if (offset >= 320) { + LOG_E(NR_RRC, "UID %d, cannot allocate resources for CSI reporting, rejecting UE\n", uid); + return false; // cannot allocate resources for CSI report + } + + return true; +} + NR_CellGroupConfig_t *get_initial_cellGroupConfig(int uid, const NR_ServingCellConfigCommon_t *scc, const NR_ServingCellConfig_t *servingcellconfigdedicated, const nr_mac_config_t *configuration, const nr_rlc_configuration_t *default_rlc_config) { - NR_SpCellConfig_t *spCellConfig = get_initial_SpCellConfig(uid, scc, servingcellconfigdedicated, configuration); - if (!spCellConfig) + if (!verify_radio_configuration(uid, scc, servingcellconfigdedicated)) return NULL; + NR_SpCellConfig_t *spCellConfig = get_initial_SpCellConfig(uid, scc, servingcellconfigdedicated, configuration); NR_CellGroupConfig_t *cellGroupConfig = calloc(1, sizeof(*cellGroupConfig)); cellGroupConfig->cellGroupId = 0; From 41da4a3b3af385f155d4b3b5e08261668c5686e4 Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 13 May 2025 15:22:41 +0200 Subject: [PATCH 176/964] send reject if we reach the max number of UEs allowed --- openair2/LAYER2/NR_MAC_gNB/config.c | 2 +- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 5 ---- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 26 +++++++++++-------- .../LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c | 2 +- 4 files changed, 17 insertions(+), 18 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c index f87b4024b9..abe6e5218a 100644 --- a/openair2/LAYER2/NR_MAC_gNB/config.c +++ b/openair2/LAYER2/NR_MAC_gNB/config.c @@ -971,7 +971,7 @@ bool nr_mac_add_test_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t NR_SCHED_LOCK(&nrmac->sched_lock); NR_UE_info_t *UE = get_new_nr_ue_inst(&nrmac->UE_info.uid_allocator, rnti, CellGroup); - DevAssert(UE != NULL); // test-mode: we assume we can always create a UE + DevAssert(UE->uid < MAX_MOBILES_PER_GNB); // test-mode: we assume we can always create a UE free_and_zero(UE->ra); // test-mode (sims, phy-test): UE will not do RA bool res = add_connected_nr_ue(nrmac, UE); if (!res) { diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index cbf414fb31..7459a99579 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -727,11 +727,6 @@ void nr_initiate_ra_proc(module_id_t module_idP, } UE = get_new_nr_ue_inst(&nr_mac->UE_info.uid_allocator, rnti, NULL); - if (!UE) { - LOG_E(NR_MAC, "FAILURE: %4d.%2d cannot create UE context, ignoring RA because RRC Reject not implemented yet\n", frame, slot); - NR_SCHED_UNLOCK(&nr_mac->sched_lock); - return; - } if (!add_new_UE_RA(nr_mac, UE)) { LOG_E(NR_MAC, "FAILURE: %4d.%2d initiating RA procedure for preamble index %d: no free RA process\n", frame, slot, preamble_index); delete_nr_ue_data(UE, NULL, &nr_mac->UE_info.uid_allocator); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 82fa6d828b..f3c604740a 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -2577,19 +2577,10 @@ static void init_bler_stats(const NR_bler_options_t *bler_options, NR_bler_stats * error handling). Remove with delete_nr_ue_data(). */ NR_UE_info_t *get_new_nr_ue_inst(uid_allocator_t *uia, rnti_t rnti, NR_CellGroupConfig_t *CellGroup) { - uid_t uid = uid_linear_allocator_new(uia); - /* if the UE list is full, we should reject the UE with an RRC reject - * message, but we do not have this functionality. To keep it simple, do not - * create a UE context here, so we can print an error message. */ - if (uid >= MAX_MOBILES_PER_GNB) { - uid_linear_allocator_free(uia, uid); - return NULL; - } - NR_UE_info_t *UE = calloc_or_fail(1, sizeof(NR_UE_info_t)); + UE->uid = uid_linear_allocator_new(uia); UE->rnti = rnti; UE->CellGroup = CellGroup; - UE->uid = uid; UE->ra = calloc(1, sizeof(*UE->ra)); NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; sched_ctrl->ta_update = 31; @@ -3324,6 +3315,19 @@ bool prepare_initial_ul_rrc_message(gNB_MAC_INST *mac, NR_UE_info_t *UE) if (!nr_rlc_activate_srb0(UE->rnti, UE, send_initial_ul_rrc_message)) return false; + if (UE->uid >= MAX_MOBILES_PER_GNB) { + // verifying if any UE left in the meantime and it is possible to get a valid UID + uid_linear_allocator_free(&mac->UE_info.uid_allocator, UE->uid); + UE->uid = uid_linear_allocator_new(&mac->UE_info.uid_allocator); + if (UE->uid >= MAX_MOBILES_PER_GNB) { + // if the UE list is full, we should reject the UE with an RRC reject message + // to signal the upper layers to send a reject we send an empty CellGroup information element + UE->CellGroup = NULL; + LOG_W(NR_MAC, "Maximum number of UE alllowed at DU reached. Cannot serve UE %04x", UE->rnti); + return true; + } + } + /* create this UE's initial CellGroup */ int CC_id = 0; int srb_id = 1; @@ -3335,7 +3339,7 @@ bool prepare_initial_ul_rrc_message(gNB_MAC_INST *mac, NR_UE_info_t *UE) if (!cellGroupConfig) return true; - + /* the cellGroup sent to CU specifies there is SRB1, so create it */ DevAssert(cellGroupConfig->rlc_BearerToAddModList->list.count == 1); const NR_RLC_BearerConfig_t *bearer = cellGroupConfig->rlc_BearerToAddModList->list.array[0]; diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c index 5d7642c815..5236f817cc 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -553,7 +553,7 @@ static NR_UE_info_t *create_new_UE(gNB_MAC_INST *mac, uint32_t cu_id, const NR_C DevAssert(success); NR_UE_info_t *UE = get_new_nr_ue_inst(&mac->UE_info.uid_allocator, rnti, NULL); - AssertFatal(UE != NULL, "cannot create UE context, UE context setup failure not implemented\n"); + AssertFatal(UE->uid < MAX_MOBILES_PER_GNB, "cannot create UE context, UE context setup failure not implemented\n"); NR_CellGroupConfig_t *cellGroupConfig = NULL; NR_COMMON_channels_t *cc = &mac->common_channels[CC_id]; From a830cc2e0aeb087cc11c1e435cd6c63c6ba39857 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 15 May 2025 12:53:14 +0200 Subject: [PATCH 177/964] When freeing UE contexts, check in both possible lists --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 2 +- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 7459a99579..839930960b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -2249,7 +2249,7 @@ void nr_release_ra_UE(gNB_MAC_INST *mac, rnti_t rnti) if (UE) { delete_nr_ue_data(UE, mac->common_channels, &UE_info->uid_allocator); } else { - LOG_W(NR_MAC,"Call to del rnti %04x, but not existing\n", rnti); + LOG_W(NR_MAC,"Call to release RA UE with rnti %04x, but not existing\n", rnti); } } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index f3c604740a..908425651b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -2612,6 +2612,8 @@ NR_UE_info_t *remove_UE_from_list(int list_size, NR_UE_info_t *list[list_size], { for (int i = 0; i < list_size; i++) { NR_UE_info_t *curr_UE = list[i]; + if (!curr_UE) + break; /* reached the end of the list */ if (curr_UE->rnti != rnti) continue; @@ -2620,7 +2622,6 @@ NR_UE_info_t *remove_UE_from_list(int list_size, NR_UE_info_t *list[list_size], list[list_size - 1] = NULL; return curr_UE; } - LOG_E(NR_MAC, "UE %04x to be removed not found in list\n", rnti); return NULL; } @@ -2726,8 +2727,10 @@ void mac_remove_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rnti) NR_SCHED_LOCK(&UE_info->mutex); NR_UE_info_t *UE = remove_UE_from_list(MAX_MOBILES_PER_GNB + 1, UE_info->connected_ue_list, rnti); NR_SCHED_UNLOCK(&UE_info->mutex); - - delete_nr_ue_data(UE, nr_mac->common_channels, &UE_info->uid_allocator); + if (UE) + delete_nr_ue_data(UE, nr_mac->common_channels, &UE_info->uid_allocator); + else + nr_release_ra_UE(nr_mac, rnti); } // all values passed to this function are in dB x10 From 708dca1ab96d0426dc880868937859a71cfa5417 Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Thu, 3 Jul 2025 18:42:30 +0200 Subject: [PATCH 178/964] fix compilation of nr rlc tests ./run_tests.sh in openair2/LAYER2/nr_rlc/tests was not functional anymore. --- openair2/LAYER2/nr_rlc/nr_rlc_sdu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_sdu.c b/openair2/LAYER2/nr_rlc/nr_rlc_sdu.c index 60f50d0afd..d9e15b98c9 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_sdu.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_sdu.c @@ -25,6 +25,7 @@ #include #include "LOG/log.h" +#include "common/utils/assertions.h" nr_rlc_sdu_segment_t *nr_rlc_new_sdu( char *buffer, int size, From 2b4eb2fb55b525735509811dc885c8190ca08be4 Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Thu, 3 Jul 2025 18:46:09 +0200 Subject: [PATCH 179/964] nr rlc: discarding a packet when RX buffer is full is a warning We want to see it. It's not normal, may disturb the system. --- openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c b/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c index 4d288b48cb..0121c5b09d 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c @@ -833,7 +833,7 @@ void nr_rlc_entity_am_recv_pdu(nr_rlc_entity_t *_entity, /* dicard PDU if rx buffer is full */ if (entity->rx_size + data_size > entity->rx_maxsize) { - LOG_D(RLC, "%s:%d:%s: warning: discard PDU, RX buffer full\n", + LOG_W(RLC, "%s:%d:%s: warning: discard PDU, RX buffer full\n", __FILE__, __LINE__, __FUNCTION__); goto discard; } From c70e3360114594cc646e1d941ebac21a15d61a04 Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Thu, 3 Jul 2025 18:57:32 +0200 Subject: [PATCH 180/964] nr rlc: speedup RX path of RLC AM rx_list is replaced by an array of size 2^(SN size - 1) which is 131072 for an SN size of 18 bits, leading to 1048576 bytes of memory used. (Less for smaller SN sizes.) A lot of RX processing was to run through rx_list. When the list was big (with some non-ideal channel), it can take some time. Removing this list should improve things. Checking with benchmark_nr_rlc_am_entity a speedup of more thant x10 is achieved (except for the case 1024 which is surprisingly faster than the others in the develop branch). The only thing that may be slower is when looking for cur->next where the SN is different, in which case we need to look for all SN one by one until we find something or reach the limit (rx_highest_status). These are the functions get_first_rx_pdu() and get_next_rx_pdu(). --- openair2/LAYER2/nr_rlc/CMakeLists.txt | 3 +- openair2/LAYER2/nr_rlc/nr_rlc_entity.c | 2 + openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c | 151 ++++++++++++--------- openair2/LAYER2/nr_rlc/nr_rlc_entity_am.h | 7 +- openair2/LAYER2/nr_rlc/nr_rlc_rx_manager.c | 114 ++++++++++++++++ openair2/LAYER2/nr_rlc/nr_rlc_rx_manager.h | 49 +++++++ openair2/LAYER2/nr_rlc/tests/Makefile | 2 +- 7 files changed, 259 insertions(+), 69 deletions(-) create mode 100644 openair2/LAYER2/nr_rlc/nr_rlc_rx_manager.c create mode 100644 openair2/LAYER2/nr_rlc/nr_rlc_rx_manager.h diff --git a/openair2/LAYER2/nr_rlc/CMakeLists.txt b/openair2/LAYER2/nr_rlc/CMakeLists.txt index d72ac37d09..953822df10 100644 --- a/openair2/LAYER2/nr_rlc/CMakeLists.txt +++ b/openair2/LAYER2/nr_rlc/CMakeLists.txt @@ -4,7 +4,8 @@ add_library(nr_rlc_core OBJECT nr_rlc_entity_tm.c nr_rlc_entity_um.c nr_rlc_pdu.c - nr_rlc_sdu.c) + nr_rlc_sdu.c + nr_rlc_rx_manager.c) target_include_directories(nr_rlc_core PRIVATE ../../..) target_link_libraries(nr_rlc_core PRIVATE ${T_LIB}) add_library(nr_rlc STATIC diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_entity.c b/openair2/LAYER2/nr_rlc/nr_rlc_entity.c index 6d35460331..6103a7011a 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_entity.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_entity.c @@ -144,6 +144,8 @@ nr_rlc_entity_t *new_nr_rlc_entity_am( */ ret->common.txsdu_avg_time_to_tx = time_average_new(100 * 1000, 1024); + ret->rx = nr_rlc_new_rx_manager(1 << (sn_field_length - 1)); + return (nr_rlc_entity_t *)ret; } diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c b/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c index 0121c5b09d..a11f9b3027 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c @@ -111,19 +111,17 @@ nr_rlc_sdu_segment_t *nr_rlc_tx_sdu_segment_list_add(nr_rlc_entity_am_t *entity, static int segment_already_received(nr_rlc_entity_am_t *entity, int sn, int so, int size) { - nr_rlc_pdu_t *l = entity->rx_list; + nr_rlc_pdu_t *l = nr_rlc_rx_manager_get_pdu_from_sn(entity->rx, sn); int covered; while (l != NULL && size > 0) { - if (l->sn == sn) { - if (l->so <= so && so < l->so + l->size) { - covered = l->size - (so - l->so); - size -= covered; - so += covered; - } else if (l->so <= so+size-1 && so+size-1 < l->so + l->size) { - covered = size - (l->so - so); - size -= covered; - } + if (l->so <= so && so < l->so + l->size) { + covered = l->size - (so - l->so); + size -= covered; + so += covered; + } else if (l->so <= so+size-1 && so+size-1 < l->so + l->size) { + covered = size - (l->so - so); + size -= covered; } l = l->next; } @@ -136,27 +134,20 @@ static int segment_already_received(nr_rlc_entity_am_t *entity, */ static int sdu_full(nr_rlc_entity_am_t *entity, int sn) { - nr_rlc_pdu_t *l = entity->rx_list; - int last_byte; - int new_last_byte; + nr_rlc_pdu_t *l = nr_rlc_rx_manager_get_pdu_from_sn(entity->rx, sn); - last_byte = -1; - while (l != NULL) { - if (l->sn == sn) - break; - l = l->next; - } + int last_byte = -1; /* check if the data has already been processed */ if (l != NULL && l->data == NULL) return 0; - while (l != NULL && l->sn == sn) { + while (l != NULL) { if (l->so > last_byte + 1) return 0; if (l->is_last) return 1; - new_last_byte = l->so + l->size - 1; + int new_last_byte = l->so + l->size - 1; if (new_last_byte > last_byte) last_byte = new_last_byte; l = l->next; @@ -168,14 +159,7 @@ static int sdu_full(nr_rlc_entity_am_t *entity, int sn) /* checks that an SDU has already been delivered */ static int sdu_delivered(nr_rlc_entity_am_t *entity, int sn) { - nr_rlc_pdu_t *l = entity->rx_list; - - while (l != NULL) { - if (l->sn == sn) - break; - l = l->next; - } - + nr_rlc_pdu_t *l = nr_rlc_rx_manager_get_pdu_from_sn(entity->rx, sn); return l != NULL && l->data == NULL; } @@ -185,22 +169,17 @@ static int sdu_delivered(nr_rlc_entity_am_t *entity, int sn) */ static int sdu_has_missing_bytes(nr_rlc_entity_am_t *entity, int sn) { - nr_rlc_pdu_t *l = entity->rx_list; + nr_rlc_pdu_t *l = nr_rlc_rx_manager_get_pdu_from_sn(entity->rx, sn); int last_byte; int new_last_byte; last_byte = -1; - while (l != NULL) { - if (l->sn == sn) - break; - l = l->next; - } /* check if the data has already been processed */ if (l != NULL && l->data == NULL) return 0; /* data already processed: no missing byte */ - while (l != NULL && l->sn == sn) { + while (l != NULL) { if (l->so > last_byte + 1) return 1; new_last_byte = l->so + l->size - 1; @@ -219,13 +198,10 @@ static void reassemble_and_deliver(nr_rlc_entity_am_t *entity, int sn) int so = 0; int bad_sdu = 0; - /* go to first segment of sn */ - pdu = entity->rx_list; - while (pdu->sn != sn) - pdu = pdu->next; + pdu = nr_rlc_rx_manager_get_pdu_from_sn(entity->rx, sn); /* reassemble - free 'data' of each segment after processing */ - while (pdu != NULL && pdu->sn == sn) { + while (pdu != NULL) { int len = pdu->size - (so - pdu->so); if (so + len > NR_SDU_MAX && !bad_sdu) { LOG_E(RLC, "%s:%d:%s: bad SDU, too big, discarding\n", @@ -262,7 +238,6 @@ static void reception_actions(nr_rlc_entity_am_t *entity, nr_rlc_pdu_t *pdu) if (sn_compare_rx(entity, x, entity->rx_next_highest) >= 0) entity->rx_next_highest = (x + 1) % entity->sn_modulus; - /* todo: room for optimization: we can run through rx_list only once */ if (sdu_full(entity, x)) { reassemble_and_deliver(entity, x); @@ -275,21 +250,26 @@ static void reception_actions(nr_rlc_entity_am_t *entity, nr_rlc_pdu_t *pdu) if (x == entity->rx_next) { /* update rx_next and free all delivered SDUs at the head of the - * rx_list + * RX list */ int rx_next = entity->rx_next; - while (entity->rx_list != NULL && entity->rx_list->data == NULL && - entity->rx_list->sn == rx_next) { + int count = 0; + nr_rlc_pdu_t *l = nr_rlc_rx_manager_get_pdu_from_sn(entity->rx, rx_next); + while (l != NULL && l->data == NULL) { /* free all segments of this SDU */ do { - nr_rlc_pdu_t *p = entity->rx_list; - entity->rx_list = p->next; + nr_rlc_pdu_t *p = l; + l = l->next; free(p); - } while (entity->rx_list != NULL && - entity->rx_list->sn == rx_next); + } while (l != NULL); + nr_rlc_rx_manager_clear_pdu(entity->rx, rx_next); + count++; rx_next = (rx_next + 1) % entity->sn_modulus; + l = nr_rlc_rx_manager_get_pdu_from_sn(entity->rx, rx_next); } entity->rx_next = rx_next; + nr_rlc_rx_manager_advance(entity->rx, count); + nr_rlc_rx_manager_set_start(entity->rx, rx_next); } } @@ -864,8 +844,7 @@ void nr_rlc_entity_am_recv_pdu(nr_rlc_entity_t *_entity, entity->rx_size += data_size; pdu = nr_rlc_new_pdu(sn, so, is_first, is_last, buffer + size - data_size, data_size); - entity->rx_list = nr_rlc_pdu_list_add(sn_compare_rx, entity, - entity->rx_list, pdu); + nr_rlc_rx_manager_add_pdu(entity->rx, pdu); /* do reception actions (38.322 5.2.3.2.3) */ LOG_D(RLC, "RLC received PDU sn %d so %d is_first %d is_last %d data_size = %d \n", sn, so, is_first, is_last, data_size); @@ -1037,6 +1016,55 @@ typedef struct { nr_rlc_pdu_t *next; } missing_data_t; +/* returns the first RX PDU with rx_next <= sn <= rx_highest_status + * returns NULL if none is found + */ +static nr_rlc_pdu_t *get_first_rx_pdu(nr_rlc_entity_am_t *entity) +{ + int first_sn = entity->rx_next; + int last_sn = entity->rx_highest_status; + int sn = first_sn; + + while (sn != last_sn) { + nr_rlc_pdu_t *ret = nr_rlc_rx_manager_get_pdu_from_sn(entity->rx, sn); + if (ret) + return ret; + sn = (sn + 1) % entity->sn_modulus; + } + + return nr_rlc_rx_manager_get_pdu_from_sn(entity->rx, sn); +} + +/* find the next RX PDU coming after 'cur' + * two cases: + * - there is a PDU with same SN, return it + * - find PDU with SN <= rx_highest_status if any + * limit search to rx_highest_status + */ +static nr_rlc_pdu_t *get_next_rx_pdu(nr_rlc_entity_am_t *entity, + nr_rlc_pdu_t *cur) +{ + if (cur->next) + return cur->next; + + /* don't process past rx_highest_status */ + if (cur->sn == entity->rx_highest_status) + return NULL; + + int first_sn = (cur->sn + 1) % entity->sn_modulus; + int last_sn = entity->rx_highest_status; + int sn = first_sn; + + while (sn != last_sn) { + nr_rlc_pdu_t *ret = nr_rlc_rx_manager_get_pdu_from_sn(entity->rx, sn); + if (ret) + return ret; + sn = (sn + 1) % entity->sn_modulus; + } + + return nr_rlc_rx_manager_get_pdu_from_sn(entity->rx, sn); +} + /* todo: rewrite this function, too messy */ static missing_data_t next_missing(nr_rlc_entity_am_t *entity, nr_rlc_pdu_t *cur, int check_head) @@ -1076,8 +1104,10 @@ next_pdu: max_so = cur_max_so; last_reached = last_reached | cur->is_last; + nr_rlc_pdu_t *cur_next = get_next_rx_pdu(entity, cur); + /* no next? */ - if (cur->next == NULL) { + if (cur_next == NULL) { /* inform the caller that work is over */ ret.next = NULL; @@ -1118,7 +1148,7 @@ next_pdu: return ret; } - cur = cur->next; + cur = cur_next; /* no discontinuity in data => process to next PDU */ if (cur->sn == sn && max_so >= cur->so - 1) @@ -1374,7 +1404,7 @@ static int generate_status(nr_rlc_entity_am_t *entity, char *buffer, int size) /* first 3 bytes, ack_sn and e1 will be set later */ nr_rlc_pdu_encoder_put_bits(&encoder, 0, 8*3); - cur = entity->rx_list; + cur = get_first_rx_pdu(entity); /* store the position of the e1 bit to be set if * there is a nack following @@ -1538,7 +1568,7 @@ static int status_size(nr_rlc_entity_am_t *entity, int maxsize) /* minimum 3 bytes */ size = 3; - cur = entity->rx_list; + cur = get_first_rx_pdu(entity); while (cur != NULL) { m = next_missing(entity, cur, nack_count == 0); @@ -2020,8 +2050,6 @@ void nr_rlc_entity_am_discard_sdu(nr_rlc_entity_t *_entity, int sdu_id) static void clear_entity(nr_rlc_entity_am_t *entity) { - nr_rlc_pdu_t *cur_rx; - entity->rx_next = 0; entity->rx_next_status_trigger = 0; entity->rx_highest_status = 0; @@ -2045,13 +2073,7 @@ static void clear_entity(nr_rlc_entity_am_t *entity) entity->t_reassembly_start = 0; entity->t_status_prohibit_start = 0; - cur_rx = entity->rx_list; - while (cur_rx != NULL) { - nr_rlc_pdu_t *p = cur_rx; - cur_rx = cur_rx->next; - nr_rlc_free_pdu(p); - } - entity->rx_list = NULL; + nr_rlc_clear_rx_manager(entity->rx); entity->rx_size = 0; nr_rlc_free_sdu_segment_list(entity->tx_list); @@ -2081,6 +2103,7 @@ void nr_rlc_entity_am_delete(nr_rlc_entity_t *_entity) { nr_rlc_entity_am_t *entity = (nr_rlc_entity_am_t *)_entity; clear_entity(entity); + nr_rlc_free_rx_manager(entity->rx); time_average_free(entity->common.txsdu_avg_time_to_tx); free(entity); } diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.h b/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.h index 4c626c4826..6b61e84a2f 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.h +++ b/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.h @@ -25,6 +25,7 @@ #include "nr_rlc_entity.h" #include "nr_rlc_sdu.h" #include "nr_rlc_pdu.h" +#include "nr_rlc_rx_manager.h" typedef struct { nr_rlc_entity_t common; @@ -70,9 +71,9 @@ typedef struct { uint64_t t_status_prohibit_start; /* rx management */ - nr_rlc_pdu_t *rx_list; - int rx_size; - int rx_maxsize; + nr_rlc_rx_manager_t *rx; + int rx_size; + int rx_maxsize; /* tx management */ nr_rlc_sdu_segment_t *tx_list; diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_rx_manager.c b/openair2/LAYER2/nr_rlc/nr_rlc_rx_manager.c new file mode 100644 index 0000000000..eccf74a208 --- /dev/null +++ b/openair2/LAYER2/nr_rlc/nr_rlc_rx_manager.c @@ -0,0 +1,114 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include "nr_rlc_rx_manager.h" + +#include "common/utils/utils.h" + +nr_rlc_rx_manager_t *nr_rlc_new_rx_manager(int size) +{ + nr_rlc_rx_manager_t *ret = calloc_or_fail(1, sizeof(*ret)); + + ret->rx_list = calloc_or_fail(size, sizeof(*ret->rx_list)); + ret->size = size; + + return ret; +} + +void nr_rlc_clear_rx_manager(nr_rlc_rx_manager_t *m) +{ + for (int i = 0; i < m->size; i++) { + nr_rlc_pdu_t *cur = m->rx_list[i]; + while (cur) { + nr_rlc_pdu_t *f = cur; + cur = cur->next; + nr_rlc_free_pdu(f); + } + m->rx_list[i] = 0; + } + m->start = 0; + m->sn_start = 0; +} + +void nr_rlc_free_rx_manager(nr_rlc_rx_manager_t *m) +{ + nr_rlc_clear_rx_manager(m); + free(m->rx_list); + free(m); +} + +static inline int get_pos(nr_rlc_rx_manager_t *m, int sn) +{ + return (m->start + (sn - m->sn_start + m->size * 2)) % m->size; +} + +nr_rlc_pdu_t *nr_rlc_rx_manager_get_pdu_from_sn(nr_rlc_rx_manager_t *m, int sn) +{ + int pos = get_pos(m, sn); + return m->rx_list[pos]; +} + +void nr_rlc_rx_manager_clear_pdu(nr_rlc_rx_manager_t *m, int sn) +{ + int pos = get_pos(m, sn); + m->rx_list[pos] = 0; +} + +/* beware: after calling this function 'sn_start' is invalid, caller has + * to call nr_rlc_rx_manager_set_start() just after + */ +void nr_rlc_rx_manager_advance(nr_rlc_rx_manager_t *m, int count) +{ + m->start += count; + m->start %= m->size; +} + +void nr_rlc_rx_manager_set_start(nr_rlc_rx_manager_t *m, int sn_start) +{ + m->sn_start = sn_start; +} + +void nr_rlc_rx_manager_add_pdu(nr_rlc_rx_manager_t *m, nr_rlc_pdu_t *pdu) +{ + int pos = get_pos(m, pdu->sn); + + nr_rlc_pdu_t head; + nr_rlc_pdu_t *cur; + nr_rlc_pdu_t *prev; + + head.next = m->rx_list[pos]; + cur = m->rx_list[pos]; + prev = &head; + + /* order by 'so' */ + while (cur != NULL) { + /* check if 'pdu' is before 'cur' in the list */ + if (cur->so > pdu->so) { + break; + } + prev = cur; + cur = cur->next; + } + prev->next = pdu; + pdu->next = cur; + + m->rx_list[pos] = head.next; +} diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_rx_manager.h b/openair2/LAYER2/nr_rlc/nr_rlc_rx_manager.h new file mode 100644 index 0000000000..7de6984ce7 --- /dev/null +++ b/openair2/LAYER2/nr_rlc/nr_rlc_rx_manager.h @@ -0,0 +1,49 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef _NR_RLC_RX_MANAGER_H_ +#define _NR_RLC_RX_MANAGER_H_ + +#include "nr_rlc_pdu.h" + +typedef struct { + /* 'rx_list' is managed as a circular buffer + * starts at rx_list[start] where is stored 'sn_start' + * for an RLC entity with an SN of n bits, its size is 2^(n-1) + * corresponding the the window size + */ + nr_rlc_pdu_t **rx_list; + int size; + int start; + int sn_start; +} nr_rlc_rx_manager_t; + +nr_rlc_rx_manager_t *nr_rlc_new_rx_manager(int size); +void nr_rlc_free_rx_manager(nr_rlc_rx_manager_t *m); +void nr_rlc_clear_rx_manager(nr_rlc_rx_manager_t *m); + +nr_rlc_pdu_t *nr_rlc_rx_manager_get_pdu_from_sn(nr_rlc_rx_manager_t *m, int sn); +void nr_rlc_rx_manager_clear_pdu(nr_rlc_rx_manager_t *m, int sn); +void nr_rlc_rx_manager_advance(nr_rlc_rx_manager_t *m, int count); +void nr_rlc_rx_manager_set_start(nr_rlc_rx_manager_t *m, int sn_start); +void nr_rlc_rx_manager_add_pdu(nr_rlc_rx_manager_t *m, nr_rlc_pdu_t *pdu); + +#endif /* _NR_RLC_RX_MANAGER_H_ */ diff --git a/openair2/LAYER2/nr_rlc/tests/Makefile b/openair2/LAYER2/nr_rlc/tests/Makefile index 1e9cd432bf..2673d0955d 100644 --- a/openair2/LAYER2/nr_rlc/tests/Makefile +++ b/openair2/LAYER2/nr_rlc/tests/Makefile @@ -2,7 +2,7 @@ CC=gcc CFLAGS=-Wall -g --coverage -I. -I../../../.. -D_STANDALONE_TESTING_ LIB=nr_rlc_entity.o nr_rlc_entity_am.o nr_rlc_entity_um.o nr_rlc_entity_tm.o \ - nr_rlc_pdu.o nr_rlc_sdu.o time_stat.o + nr_rlc_pdu.o nr_rlc_sdu.o nr_rlc_rx_manager.o time_stat.o tests: @./run_tests.sh From 90cf2490184b612a08d20db97cacbeddd64090e7 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Fri, 4 Jul 2025 09:34:17 +0200 Subject: [PATCH 181/964] add telnet commands trace --- common/utils/telnetsrv/telnetsrv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/utils/telnetsrv/telnetsrv.c b/common/utils/telnetsrv/telnetsrv.c index de1c26d2e1..1d1a5be410 100644 --- a/common/utils/telnetsrv/telnetsrv.c +++ b/common/utils/telnetsrv/telnetsrv.c @@ -692,8 +692,8 @@ void run_telnetsrv(void) { break; } - if (telnetparams.telnetdbg > 0) - TELNET_LOG("Command received: readc %i filled %i \"%s\"\n", readc, filled, buf); + //if (telnetparams.telnetdbg > 0) + TELNET_LOG("Command received: readc %i filled %i \"%s\"\n", readc, filled, buf); if (buf[0] == '!') { if (buf[1] == '!') { From 67e9c9c26398f72b1d74c1cbcf7d80136468203d Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 27 Jun 2025 08:00:08 +0200 Subject: [PATCH 182/964] RRC: auto-generate release request when no AMF Mark non-existing AMF UE NGAP ID through invalid INT64_MAX number (permitted range is up to 2^40-1). Check for this range in the RAN function, as we might otherwise pass the invalid AMF UE NGAP ID to the agent, which would assert with nr-softmodem: /oai-ran/openair2/E2AP/flexric/src/lib/3gpp/enc/enc_gnb.c:83: enc_gNB_UE_asn: Assertion `gnb->amf_ue_ngap_id < 1UL << 40' failed. In other words, don't send KPM messages for a UE which has no valid AMF UE NGAP ID yet (which follows from the fact that the spec requires an AMF UE NGAP ID; the previous behavior of simply sending 0 could be considered a bug, because it's not the UE's true AMF UE NGAP ID). --- openair2/E2AP/RAN_FUNCTION/O-RAN/ran_e2sm_ue_id.c | 7 ++++++- openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c | 6 ++++++ openair2/RRC/NR/rrc_gNB.c | 10 ++++++---- openair2/RRC/NR/rrc_gNB_UE_context.c | 2 ++ 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_e2sm_ue_id.c b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_e2sm_ue_id.c index c3f6277f6f..a81a01d394 100644 --- a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_e2sm_ue_id.c +++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_e2sm_ue_id.c @@ -30,7 +30,12 @@ ue_id_e2sm_t fill_e2sm_gnb_ue_id_data(const gNB_RRC_UE_t *rrc_ue_context, __attr // 6.2.3.16 // Mandatory // AMF UE NGAP ID - ue_id.gnb.amf_ue_ngap_id = rrc_ue_context->amf_ue_ngap_id; + // it seems that certain messages can be triggered before the ue has an AMF + // UE NGAP ID (e.g., RRC setup). In that case, the AMF UE NGAP ID is set to + // an invalid value. Below, check for this, and set 0 in that case (which + // historically used to be in amf_ue_ngap_id). + uint64_t auni = rrc_ue_context->amf_ue_ngap_id; + ue_id.gnb.amf_ue_ngap_id = auni < (1LL << 40) ? auni : 0; // Mandatory //GUAMI 6.2.3.17 diff --git a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c index 4468cdf0b9..fd6578b3b2 100644 --- a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c +++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c @@ -209,6 +209,9 @@ static arr_ue_id_t filter_ues_by_s_nssai_in_cu(const test_info_lst_t test_info) struct rrc_gNB_ue_context_s* rrc_ue_context = NULL; RB_FOREACH(rrc_ue_context, rrc_nr_ue_tree_s, &RC.nrrrc[0]->rrc_ue_head) { gNB_RRC_UE_t *ue = &rrc_ue_context->ue_context; + /* UE has no AMF UE NGAP ID yet => can't send message */ + if (ue->amf_ue_ngap_id >= (1LL << 40)) + continue; for (int p = 0; p < ue->nb_of_pdusessions; ++p) { pdusession_t *pdu = &ue->pduSession[p].param; if (nssai_matches(pdu->nssai, sst, sd)) { @@ -296,6 +299,9 @@ static arr_ue_id_t filter_ues_by_s_nssai_in_du_or_monolithic(const test_info_lst arr_ue_id.ue_id[arr_ue_id.sz] = fill_ue_id_data[ngran_gNB_DU](NULL, rrc_ue_id.secondary_ue, 0); } else { rrc_gNB_ue_context_t* rrc_ue_context = rrc_gNB_get_ue_context_by_rnti(RC.nrrrc[0], -1, ue->rnti); + /* UE has no AMF UE NGAP ID yet => can't send message */ + if (rrc_ue_context->ue_context.amf_ue_ngap_id >= (1LL << 40)) + continue; arr_ue_id.ue_id[arr_ue_id.sz] = fill_ue_id_data[ngran_gNB](&rrc_ue_context->ue_context, 0, 0); } diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 2ef11ce605..f9952d0dae 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -2146,12 +2146,14 @@ static void rrc_CU_process_ue_context_release_request(MessageDef *msg_p, sctp_as f1ap_ue_context_release_req_t *req = &F1AP_UE_CONTEXT_RELEASE_REQ(msg_p); gNB_RRC_INST *rrc = RC.nrrrc[instance]; rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(rrc, req->gNB_CU_ue_id); - // TODO what happens if no AMF connected? should also handle, set an_release true int srbid = 1; - if (!ue_context_p) { - LOG_W(RRC, "could not find UE context for CU UE ID %u: auto-generate release command\n", req->gNB_CU_ue_id); + // valid AMF UE NGAP ID range is 0..2^40-1 + if (!ue_context_p || ue_context_p->ue_context.amf_ue_ngap_id >= (1LL << 40)) { + const char *reason = !ue_context_p ? "could not find UE context" : "no AMF"; + LOG_W(RRC, "%s for CU UE ID %u: auto-generate release command\n", reason, req->gNB_CU_ue_id); uint8_t buffer[NR_RRC_BUF_SIZE] = {0}; int size = do_NR_RRCRelease(buffer, NR_RRC_BUF_SIZE, rrc_gNB_get_next_transaction_identifier(0)); + RETURN_IF_INVALID_ASSOC_ID(assoc_id); f1ap_ue_context_release_cmd_t ue_context_release_cmd = { .gNB_CU_ue_id = req->gNB_CU_ue_id, .gNB_DU_ue_id = req->gNB_DU_ue_id, @@ -2159,7 +2161,7 @@ static void rrc_CU_process_ue_context_release_request(MessageDef *msg_p, sctp_as .cause_value = 10, // 10 = F1AP_CauseRadioNetwork_normal_release .srb_id = srbid, }; - deliver_ue_ctxt_release_data_t data = {.rrc = rrc, .release_cmd = &ue_context_release_cmd}; + deliver_ue_ctxt_release_data_t data = {.rrc = rrc, .release_cmd = &ue_context_release_cmd, .assoc_id = assoc_id}; nr_pdcp_data_req_srb(req->gNB_CU_ue_id, srbid, rrc_gNB_mui++, size, buffer, rrc_deliver_ue_ctxt_release_cmd, &data); return; } diff --git a/openair2/RRC/NR/rrc_gNB_UE_context.c b/openair2/RRC/NR/rrc_gNB_UE_context.c index b39abd9a30..cb3a04fbce 100644 --- a/openair2/RRC/NR/rrc_gNB_UE_context.c +++ b/openair2/RRC/NR/rrc_gNB_UE_context.c @@ -200,6 +200,8 @@ rrc_gNB_ue_context_t *rrc_gNB_create_ue_context(sctp_assoc_t assoc_id, gNB_RRC_UE_t *ue = &ue_context_p->ue_context; ue->rnti = rnti; ue->random_ue_identity = ue_identityP; + // signal "no AMF UE NGAP ID" because valid range is 0..2^40-1 + ue->amf_ue_ngap_id = INT64_MAX; f1_ue_data_t ue_data = {.secondary_ue = du_ue_id, .du_assoc_id = assoc_id}; AssertFatal(!cu_exists_f1_ue_data(ue->rrc_ue_id), "UE F1 Context for ID %d already exists, logic bug\n", From 2ea3ab5050ec7635700220e42fed1f5df7a2579c Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 27 Jun 2025 08:30:42 +0200 Subject: [PATCH 183/964] Introduce UE release request grace period It might happen that the CU does not answer a release request. In that case, the MAC would never free the UE context, potentially blocking the DU. Avoid this by introducing a "grace period" after which a UE context is automatically freed at the MAC (and RLC), currently at 10s after the 30s UL failure timer. --- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 33 ++++++++++++++----- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 2 +- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 898722342b..17263de461 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -3167,7 +3167,12 @@ void nr_mac_update_timers(module_id_t module_id, frame_t frame, slot_t slot) } /* check if UL failure and trigger release request if necessary */ - nr_mac_check_ul_failure(mac, UE->rnti, sched_ctrl); + bool released = nr_mac_check_ul_failure(mac, UE->rnti, sched_ctrl); + if (released) { + // go back to examine the next UE, which is at the position the current UE was + UE--; + continue; + } if (nr_timer_tick(&sched_ctrl->transm_interrupt)) { /* expired */ @@ -3360,6 +3365,8 @@ bool nr_mac_check_release(NR_UE_sched_ctrl_t *sched_ctrl, int rnti) return sched_ctrl->release_timer == 0; } +#define UL_FAILURE_REQ_GRACE 10000 +#define UL_FAILURE_TIMEOUT 30000 void nr_mac_trigger_ul_failure(NR_UE_sched_ctrl_t *sched_ctrl, NR_SubcarrierSpacing_t subcarrier_spacing) { if (sched_ctrl->ul_failure) { @@ -3367,8 +3374,9 @@ void nr_mac_trigger_ul_failure(NR_UE_sched_ctrl_t *sched_ctrl, NR_SubcarrierSpac return; } sched_ctrl->ul_failure = true; - // 30 seconds till triggering release request - sched_ctrl->ul_failure_timer = 30000 << subcarrier_spacing; + // UL_FAILURE_TIMEOUT ms till triggering release request + // UL_FAILURE_REQ_GRACE ms till automatically released after request + sched_ctrl->ul_failure_timer = (UL_FAILURE_REQ_GRACE + UL_FAILURE_TIMEOUT) << subcarrier_spacing; } void nr_mac_reset_ul_failure(NR_UE_sched_ctrl_t *sched_ctrl) @@ -3398,20 +3406,27 @@ bool nr_mac_request_release_ue(const gNB_MAC_INST *nrmac, int rnti) return true; } -void nr_mac_check_ul_failure(gNB_MAC_INST *nrmac, int rnti, NR_UE_sched_ctrl_t *sched_ctrl) +bool nr_mac_check_ul_failure(gNB_MAC_INST *nrmac, int rnti, NR_UE_sched_ctrl_t *sched_ctrl) { if (!sched_ctrl->ul_failure) - return; + return false; if (sched_ctrl->ul_failure_timer > 0) sched_ctrl->ul_failure_timer--; - /* to trigger only once: trigger when ul_failure_timer == 1, but timer will - * stop at 0 and we wait for a UE release command from upper layers */ - if (sched_ctrl->ul_failure_timer == 1) { + /* trigger once: trigger when ul_failure_timer == UL_FAILURE_REQ_GRACE( we + * wait for a UE release command from upper layers), and UE is automatically + * released when no answer after UL_FAILURE_REQ_GRACE */ + if (sched_ctrl->ul_failure_timer == UL_FAILURE_REQ_GRACE) { LOG_W(MAC, "UE %04x: request release after UL failure timer expiry\n", rnti); bool requested = nr_mac_request_release_ue(nrmac, rnti); if (!requested) - nr_mac_release_ue(nrmac, rnti); + sched_ctrl->ul_failure_timer = 0; /* force expiry */ } + if (sched_ctrl->ul_failure_timer == 0) { + LOG_W(NR_MAC, "UE %04x: no answer for release request, dropping UE\n", rnti); + nr_mac_release_ue(nrmac, rnti); + return true; + } + return false; } void nr_mac_trigger_reconfiguration(const gNB_MAC_INST *nrmac, const NR_UE_info_t *UE) diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 6acf4ae1d8..190efa0d1b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -445,7 +445,7 @@ bool nr_mac_request_release_ue(const gNB_MAC_INST *nrmac, int rnti); void nr_mac_trigger_ul_failure(NR_UE_sched_ctrl_t *sched_ctrl, NR_SubcarrierSpacing_t subcarrier_spacing); void nr_mac_reset_ul_failure(NR_UE_sched_ctrl_t *sched_ctrl); -void nr_mac_check_ul_failure(gNB_MAC_INST *nrmac, int rnti, NR_UE_sched_ctrl_t *sched_ctrl); +bool nr_mac_check_ul_failure(gNB_MAC_INST *nrmac, int rnti, NR_UE_sched_ctrl_t *sched_ctrl); void nr_mac_trigger_reconfiguration(const gNB_MAC_INST *nrmac, const NR_UE_info_t *UE); From b6a33777b91059afad54717e28a154b0329634ab Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 2 Jul 2025 17:57:20 +0200 Subject: [PATCH 184/964] Fix: on release command, search attach list When the RA procedure fails at Msg4, we trigger UL failure and send a message to the CU to request release. There was a bug in that upon the ensueing release command, we did not search in the attach list (only connected list). However, the UE failing at Msg4 does not have transitioned to the connected list yet, thus not freeing the context. Fixes: 8f62baefa61e ("Use list of UEs during RA instead of array of RA processes)" --- openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c | 1 + 1 file changed, 1 insertion(+) diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c index 5d7642c815..e8e727ff00 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -906,6 +906,7 @@ void ue_context_release_command(const f1ap_ue_context_release_cmd_t *cmd) gNB_MAC_INST *mac = RC.nrmac[0]; NR_SCHED_LOCK(&mac->sched_lock); NR_UE_info_t *UE = find_nr_UE(&mac->UE_info, cmd->gNB_DU_ue_id); + UE = UE ? UE : find_ra_UE(&mac->UE_info, cmd->gNB_DU_ue_id); if (UE == NULL) { NR_SCHED_UNLOCK(&mac->sched_lock); f1ap_ue_context_release_complete_t complete = { From d76f062d146537844fa63a95acd15b50e14c4d9c Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 4 Jul 2025 12:17:49 +0200 Subject: [PATCH 185/964] Revert "CI: reduce number of attach tries" Due to 5GC limitations, we sometimes need to try to attach multiple times. This reverts commit 874d2b73a4c043acbd7fa9a60407b7241e9ae12a. --- ci-scripts/cls_module.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci-scripts/cls_module.py b/ci-scripts/cls_module.py index 4ef5c67ccd..3ec6ffc9e5 100644 --- a/ci-scripts/cls_module.py +++ b/ci-scripts/cls_module.py @@ -107,7 +107,7 @@ class Module_UE: return self._logCollect() return None - def attach(self, attach_tries = 2, attach_timeout = 60): + def attach(self, attach_tries = 4, attach_timeout = 60): ip = None while attach_tries > 0: self._command(self.cmd_dict["attach"]) From 080a90c930743446c37a21ad4db9e50943f898db Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Thu, 26 Jun 2025 13:02:56 +0200 Subject: [PATCH 186/964] bugfix: UE AMBR is optional This was a problem with open5gs and more than one PDU session. The core network sets UE AMBR only once, leading to failure in the gNB for the second PDU session. (A proper handling of AMBR has to be develop at some point in the gNB.) --- openair2/COMMON/ngap_messages_types.h | 2 ++ openair2/RRC/NR/rrc_gNB_NGAP.c | 4 +++- openair3/NGAP/ngap_gNB_handlers.c | 8 ++++++-- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/openair2/COMMON/ngap_messages_types.h b/openair2/COMMON/ngap_messages_types.h index 2ad2db97bd..635fd2345d 100644 --- a/openair2/COMMON/ngap_messages_types.h +++ b/openair2/COMMON/ngap_messages_types.h @@ -561,6 +561,7 @@ typedef struct ngap_initial_context_setup_req_s { uint64_t amf_ue_ngap_id; /* UE aggregate maximum bitrate */ + bool has_ue_ambr; ngap_ambr_t ue_ambr; /* guami */ @@ -631,6 +632,7 @@ typedef struct ngap_pdusession_setup_req_s { pdusession_resource_item_t pdusession[NGAP_MAX_PDU_SESSION]; /* UE Aggregated Max Bitrates */ + bool has_ue_ambr; ngap_ambr_t ueAggMaxBitRate; } ngap_pdusession_setup_req_t; diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index 72aad97750..240a591846 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -841,7 +841,9 @@ void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(MessageDef *msg_p, instance_t ins for (int i = 0; i < msg->nb_pdusessions_tosetup; ++i) cp_pdusession_resource_item_to_pdusession(&to_setup[i], &msg->pdusession[i]); - if (!trigger_bearer_setup(rrc, UE, msg->nb_pdusessions_tosetup, to_setup, msg->ueAggMaxBitRate.br_dl)) { + uint64_t dl_ambr = msg->has_ue_ambr ? msg->ueAggMaxBitRate.br_dl : 0; + + if (!trigger_bearer_setup(rrc, UE, msg->nb_pdusessions_tosetup, to_setup, dl_ambr)) { // Reject PDU Session Resource setup if there's no CU-UP associated LOG_W(NR_RRC, "UE %d: reject PDU Session Setup in PDU Session Resource Setup Response\n", UE->rrc_ue_id); ngap_cause_t cause = {.type = NGAP_CAUSE_RADIO_NETWORK, .value = NGAP_CAUSE_RADIO_NETWORK_RESOURCES_NOT_AVAILABLE_FOR_THE_SLICE}; diff --git a/openair3/NGAP/ngap_gNB_handlers.c b/openair3/NGAP/ngap_gNB_handlers.c index f4c4ebb20f..b80902add9 100644 --- a/openair3/NGAP/ngap_gNB_handlers.c +++ b/openair3/NGAP/ngap_gNB_handlers.c @@ -843,6 +843,7 @@ static int ngap_gNB_handle_initial_context_request(sctp_assoc_t assoc_id, uint32 NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_InitialContextSetupRequestIEs_t, ie, container, NGAP_ProtocolIE_ID_id_UEAggregateMaximumBitRate, false); if (ie != NULL) { msg->ue_ambr = decode_ngap_UEAggregateMaximumBitRate(&ie->value.choice.UEAggregateMaximumBitRate); + msg->has_ue_ambr = true; } /* id-GUAMI */ @@ -1022,8 +1023,11 @@ static int ngap_gNB_handle_pdusession_setup_request(sctp_assoc_t assoc_id, uint3 /* UE Aggregated Maximum Bitrate */ NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PDUSessionResourceSetupRequestIEs_t, ie, container, - NGAP_ProtocolIE_ID_id_UEAggregateMaximumBitRate, true); - msg->ueAggMaxBitRate = decode_ngap_UEAggregateMaximumBitRate(&ie->value.choice.UEAggregateMaximumBitRate); + NGAP_ProtocolIE_ID_id_UEAggregateMaximumBitRate, false); + if (ie != NULL) { + msg->ueAggMaxBitRate = decode_ngap_UEAggregateMaximumBitRate(&ie->value.choice.UEAggregateMaximumBitRate); + msg->has_ue_ambr = true; + } NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PDUSessionResourceSetupRequestIEs_t, ie, container, NGAP_ProtocolIE_ID_id_PDUSessionResourceSetupListSUReq, true); From 8ef0bf84625923faf0431ffa5163cd5d8a46e964 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Tue, 8 Jul 2025 10:46:55 +0200 Subject: [PATCH 187/964] CI: specify interface names in UPF container --- .../yaml_files/5g_f1_rfsimulator/docker-compose.yaml | 2 ++ .../yaml_files/5g_fdd_rfsimulator/docker-compose.yaml | 2 ++ ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml | 2 ++ .../yaml_files/5g_rfsimulator_24prb/docker-compose.yaml | 2 ++ .../yaml_files/5g_rfsimulator_2x2/docker-compose.yaml | 2 ++ .../yaml_files/5g_rfsimulator_e1/docker-compose.yaml | 2 ++ .../5g_rfsimulator_fr2_32prb/docker-compose.yaml | 2 ++ .../yaml_files/5g_rfsimulator_ntn_geo/docker-compose.yaml | 2 ++ .../yaml_files/5g_rfsimulator_ntn_leo/docker-compose.yaml | 2 ++ .../5g_rfsimulator_sidelink/docker-compose.yaml | 8 -------- .../5g_rfsimulator_u0_25prb/docker-compose.yaml | 2 ++ 11 files changed, 20 insertions(+), 8 deletions(-) diff --git a/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml b/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml index b4bec0e486..5c3bdc7a18 100644 --- a/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml @@ -65,8 +65,10 @@ services: networks: public_net: ipv4_address: 192.168.71.134 + interface_name: eth0 traffic_net: ipv4_address: 192.168.72.134 + interface_name: eth1 oai-ext-dn: privileged: true diff --git a/ci-scripts/yaml_files/5g_fdd_rfsimulator/docker-compose.yaml b/ci-scripts/yaml_files/5g_fdd_rfsimulator/docker-compose.yaml index dd306c15f6..164a9bc0d4 100644 --- a/ci-scripts/yaml_files/5g_fdd_rfsimulator/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_fdd_rfsimulator/docker-compose.yaml @@ -65,8 +65,10 @@ services: networks: public_net: ipv4_address: 192.168.71.134 + interface_name: eth0 traffic_net: ipv4_address: 192.168.72.134 + interface_name: eth1 oai-ext-dn: privileged: true container_name: rfsim5g-oai-ext-dn diff --git a/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml index ac89f0d036..cdce17520a 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml @@ -65,8 +65,10 @@ services: networks: public_net: ipv4_address: 192.168.71.134 + interface_name: eth0 traffic_net: ipv4_address: 192.168.72.134 + interface_name: eth1 oai-ext-dn: privileged: true container_name: rfsim5g-oai-ext-dn diff --git a/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml index 8dfe5a5980..7b09c4a955 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml @@ -65,8 +65,10 @@ services: networks: public_net: ipv4_address: 192.168.71.134 + interface_name: eth0 traffic_net: ipv4_address: 192.168.72.134 + interface_name: eth1 oai-ext-dn: privileged: true container_name: rfsim5g-oai-ext-dn diff --git a/ci-scripts/yaml_files/5g_rfsimulator_2x2/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_2x2/docker-compose.yaml index 3231a2f76e..5d4970459a 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_2x2/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_2x2/docker-compose.yaml @@ -65,8 +65,10 @@ services: networks: public_net: ipv4_address: 192.168.71.134 + interface_name: eth0 traffic_net: ipv4_address: 192.168.72.134 + interface_name: eth1 oai-ext-dn: privileged: true container_name: rfsim5g-oai-ext-dn diff --git a/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml index 66b746b6f2..53fa6a8181 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml @@ -65,8 +65,10 @@ services: networks: core_net: ipv4_address: 192.168.71.134 + interface_name: eth0 traffic_net: ipv4_address: 192.168.72.134 + interface_name: eth1 oai-cucp: image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop} diff --git a/ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb/docker-compose.yaml index 413fdb1358..aa0b9a6ca3 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb/docker-compose.yaml @@ -65,8 +65,10 @@ services: networks: public_net: ipv4_address: 192.168.71.134 + interface_name: eth0 traffic_net: ipv4_address: 192.168.72.134 + interface_name: eth1 oai-ext-dn: privileged: true container_name: rfsim5g-oai-ext-dn diff --git a/ci-scripts/yaml_files/5g_rfsimulator_ntn_geo/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_ntn_geo/docker-compose.yaml index a8c9785f15..f127fdc3b0 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_ntn_geo/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_ntn_geo/docker-compose.yaml @@ -65,8 +65,10 @@ services: networks: public_net: ipv4_address: 192.168.71.134 + interface_name: eth0 traffic_net: ipv4_address: 192.168.72.134 + interface_name: eth1 oai-ext-dn: privileged: true container_name: rfsim5g-oai-ext-dn diff --git a/ci-scripts/yaml_files/5g_rfsimulator_ntn_leo/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_ntn_leo/docker-compose.yaml index 65de72fb51..a0c44153cd 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_ntn_leo/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_ntn_leo/docker-compose.yaml @@ -63,8 +63,10 @@ services: networks: public_net: ipv4_address: 192.168.71.134 + interface_name: eth0 traffic_net: ipv4_address: 192.168.72.134 + interface_name: eth1 oai-ext-dn: privileged: true container_name: rfsim5g-oai-ext-dn diff --git a/ci-scripts/yaml_files/5g_rfsimulator_sidelink/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_sidelink/docker-compose.yaml index cae436e001..c04e634ca2 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_sidelink/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_sidelink/docker-compose.yaml @@ -60,11 +60,3 @@ networks: - subnet: 192.168.71.128/26 driver_opts: com.docker.network.bridge.name: "rfsim5g-public" - traffic_net: - driver: bridge - name: rfsim5g-oai-traffic-net - ipam: - config: - - subnet: 192.168.72.128/26 - driver_opts: - com.docker.network.bridge.name: "rfsim5g-traffic" diff --git a/ci-scripts/yaml_files/5g_rfsimulator_u0_25prb/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_u0_25prb/docker-compose.yaml index 2dca6cc25f..24a9edd8d7 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_u0_25prb/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_u0_25prb/docker-compose.yaml @@ -65,8 +65,10 @@ services: networks: public_net: ipv4_address: 192.168.71.134 + interface_name: eth0 traffic_net: ipv4_address: 192.168.72.134 + interface_name: eth1 oai-ext-dn: privileged: true container_name: rfsim5g-oai-ext-dn From 4a169f6c8adb4fa4a8573e9d70ba27d61656c8a5 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Tue, 8 Jul 2025 13:49:46 +0200 Subject: [PATCH 188/964] Update documentation for RFSim5G test deployments --- ci-scripts/yaml_files/5g_rfsimulator/README.md | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/ci-scripts/yaml_files/5g_rfsimulator/README.md b/ci-scripts/yaml_files/5g_rfsimulator/README.md index ba3382c86c..7e0858457c 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator/README.md +++ b/ci-scripts/yaml_files/5g_rfsimulator/README.md @@ -67,6 +67,18 @@ All the following commands **SHALL** be run from the `ci-scripts/yaml_files/5g_r For a deployment with the gNB split in CU and DU components, please refer to the `../5g_f1_rfsimulator` folder. For a deployment with the gNB split in CU-CP, CU-UP, and DU components, please refer to the `../5g_rfsimulator_e1` folder. +Note: **These instructions require `docker compose` v2.36.0 or later** due to the +use of the `interface_name` property, which is necessary for ensuring consistent +IP address assignment to the container interface. + +If you're using an older version of `docker compose`, you may encounter the following +error: +``` +validating docker-compose.yaml: services.oai-upf.networks.public_net Additional property interface_name is not allowed +``` +To update to the required version, you can follow the official Docker documentation: +https://docs.docker.com/compose/install/linux/ + ## 2.1. Deploy OAI 5G Core Network ## ```bash @@ -546,8 +558,7 @@ section in the file for details. This includes an image build service as well as code compilation service. This is necessary as the executable has to be linked against the same libraries that are present in the executing image. This might take a while the first time but other that that is very fast. Here is a list of -commands (wait between each command). Tested with `docker compose` v2.27.0 - +commands (wait between each command). Tested with `docker compose` v2.36.2. This command deploys OAI 5G Core Network ```bash From 9b71f1d3241389a61c2ffab2401b8479589ee449 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Soares=20Silva?= Date: Mon, 17 Mar 2025 14:38:13 +0000 Subject: [PATCH 189/964] Separate VNF socket send functions into separate socket library --- nfapi/oai_integration/nfapi_vnf.c | 53 +- nfapi/oai_integration/socket/CMakeLists.txt | 1 + .../socket/include/socket_common.h | 6 + .../socket/include/socket_vnf.h | 34 + nfapi/oai_integration/socket/socket_vnf.c | 861 ++++++++++++++++++ nfapi/open-nFAPI/vnf/inc/vnf.h | 6 +- nfapi/open-nFAPI/vnf/inc/vnf_p7.h | 12 +- .../vnf/public_inc/nfapi_vnf_interface.h | 3 +- nfapi/open-nFAPI/vnf/src/vnf.c | 187 ---- nfapi/open-nFAPI/vnf/src/vnf_interface.c | 416 --------- nfapi/open-nFAPI/vnf/src/vnf_p7.c | 291 +----- nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c | 113 +-- 12 files changed, 946 insertions(+), 1037 deletions(-) create mode 100644 nfapi/oai_integration/socket/include/socket_vnf.h create mode 100644 nfapi/oai_integration/socket/socket_vnf.c diff --git a/nfapi/oai_integration/nfapi_vnf.c b/nfapi/oai_integration/nfapi_vnf.c index 32c0e61ee7..571fe7d55d 100644 --- a/nfapi/oai_integration/nfapi_vnf.c +++ b/nfapi/oai_integration/nfapi_vnf.c @@ -36,6 +36,13 @@ #include "nfapi_vnf.h" #include #include + +#ifdef ENABLE_SOCKET +#include +#endif +#include +#include + #include "nfapi.h" #include "vendor_ext.h" @@ -1391,16 +1398,9 @@ int vnf_nr_pack_p4_p5_vendor_extension(void *header, uint8_t **ppWritePackedMsg, return 0; } -static pthread_t vnf_start_pthread; +static pthread_t vnf_p5_init_and_receive_pthread; static pthread_t vnf_p7_start_pthread; -void *vnf_nr_p7_start_thread(void *ptr) { - NFAPI_TRACE(NFAPI_TRACE_INFO, "%s()\n", __FUNCTION__); - pthread_setname_np(pthread_self(), "VNF_P7"); - nfapi_vnf_p7_config_t *config = (nfapi_vnf_p7_config_t *)ptr; - nfapi_nr_vnf_p7_start(config); - return config; -} void *vnf_p7_start_thread(void *ptr) { NFAPI_TRACE(NFAPI_TRACE_INFO, "%s()\n", __FUNCTION__); @@ -1410,7 +1410,7 @@ void *vnf_p7_start_thread(void *ptr) { return config; } -void *vnf_nr_p7_thread_start(void *ptr) +void *configure_nr_p7_vnf(void *ptr) { init_queue(&gnb_rach_ind_queue); init_queue(&gnb_rx_ind_queue); @@ -1450,9 +1450,15 @@ void *vnf_nr_p7_thread_start(void *ptr) p7_vnf->config->unpack_func = &nfapi_nr_p7_message_unpack; p7_vnf->config->hdr_unpack_func = &nfapi_nr_p7_message_header_unpack; p7_vnf->config->pack_func = &nfapi_nr_p7_message_pack; + +#ifdef ENABLE_SOCKET + p7_vnf->config->unpack_func = &nfapi_nr_p7_message_unpack; + p7_vnf->config->hdr_unpack_func = &nfapi_nr_p7_message_header_unpack; + p7_vnf->config->pack_func = &nfapi_nr_p7_message_pack; p7_vnf->config->send_p7_msg = &vnf_nr_send_p7_msg; NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Creating VNF NFAPI P7 start thread %s\n", __FUNCTION__); - pthread_create(&vnf_p7_start_pthread, NULL, &vnf_nr_p7_start_thread, p7_vnf->config); + threadCreate(&vnf_p7_start_pthread, &vnf_nr_start_p7_thread, p7_vnf->config, "vnf_p7_thread", -1, OAI_PRIORITY_RT); +#endif return 0; } @@ -1500,7 +1506,7 @@ int pnf_nr_start_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_nr_pnf_st if(p7_vnf->thread_started == 0) { pthread_t vnf_p7_thread; - threadCreate(&vnf_p7_thread, &vnf_nr_p7_thread_start, p7_vnf, "vnf_p7_thread", -1, OAI_PRIORITY_RT); + threadCreate(&vnf_p7_thread, &configure_nr_p7_vnf, p7_vnf, "vnf_p7_thread", -1, OAI_PRIORITY_RT); p7_vnf->thread_started = 1; } else { // P7 thread already running. @@ -1510,7 +1516,10 @@ int pnf_nr_start_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_nr_pnf_st NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Sending NFAPI_VNF_PARAM_REQUEST phy_id:%d\n", pnf->phys[0].id); memset(&req, 0, sizeof(req)); req.header.message_id = NFAPI_NR_PHY_MSG_TYPE_PARAM_REQUEST; + +#ifdef ENABLE_SOCKET req.header.phy_id = pnf->phys[0].id; +#endif nfapi_nr_vnf_param_req(config, p5_idx, &req); return 0; } @@ -1800,21 +1809,10 @@ void vnf_nr_deallocate_p4_p5_vendor_ext(void *header) { free(header); } - -nfapi_vnf_config_t *config = 0; - -void vnf_nr_start_thread(void *ptr) { - NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] VNF NFAPI thread - nfapi_vnf_start()%s\n", __FUNCTION__); - pthread_setname_np(pthread_self(), "VNF"); - config = (nfapi_vnf_config_t *)ptr; - nfapi_nr_vnf_start(config); -} - void vnf_start_thread(void *ptr) { NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] VNF NFAPI thread - nfapi_vnf_start()%s\n", __FUNCTION__); pthread_setname_np(pthread_self(), "VNF"); - config = (nfapi_vnf_config_t *)ptr; - nfapi_vnf_start(config); + nfapi_vnf_start((nfapi_vnf_config_t *)ptr); } static vnf_info vnf; @@ -1868,13 +1866,16 @@ void configure_nr_nfapi_vnf(char *vnf_addr, int vnf_p5_port, char *pnf_ip_addr, config->codec_config.allocate = &vnf_nr_allocate; config->codec_config.deallocate = &vnf_nr_deallocate; memset(&UL_RCC_INFO, 0, sizeof(UL_RCC_IND_t)); + +#ifdef ENABLE_SOCKET config->unpack_func = &nfapi_nr_p5_message_unpack; config->hdr_unpack_func = &nfapi_nr_p5_message_header_unpack; config->pack_func = &nfapi_nr_p5_message_pack; - config->send_p5_msg = &vnf_nr_send_p5_message; + config->send_p5_msg = &vnf_nr_send_p5_msg; NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Creating VNF NFAPI start thread %s\n", __FUNCTION__); - pthread_create(&vnf_start_pthread, NULL, (void *)&vnf_nr_start_thread, config); + pthread_create(&vnf_p5_init_and_receive_pthread, NULL, (void *)&vnf_start_p5_thread, config); NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Created VNF NFAPI start thread %s\n", __FUNCTION__); +#endif } @@ -1922,7 +1923,7 @@ void configure_nfapi_vnf(char *vnf_addr, int vnf_p5_port, char *pnf_ip_addr, int config->codec_config.deallocate = &vnf_deallocate; memset(&UL_RCC_INFO,0,sizeof(UL_RCC_IND_t)); NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Creating VNF NFAPI start thread %s\n", __FUNCTION__); - pthread_create(&vnf_start_pthread, NULL, (void *)&vnf_start_thread, config); + pthread_create(&vnf_p5_init_and_receive_pthread, NULL, (void *)&vnf_start_thread, config); NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Created VNF NFAPI start thread %s\n", __FUNCTION__); } diff --git a/nfapi/oai_integration/socket/CMakeLists.txt b/nfapi/oai_integration/socket/CMakeLists.txt index edf5457cea..57cad36362 100644 --- a/nfapi/oai_integration/socket/CMakeLists.txt +++ b/nfapi/oai_integration/socket/CMakeLists.txt @@ -1,5 +1,6 @@ add_library(nfapi_socket_lib socket_pnf.c + socket_vnf.c socket_common.c ) diff --git a/nfapi/oai_integration/socket/include/socket_common.h b/nfapi/oai_integration/socket/include/socket_common.h index 2456740ec4..1817507733 100644 --- a/nfapi/oai_integration/socket/include/socket_common.h +++ b/nfapi/oai_integration/socket/include/socket_common.h @@ -21,12 +21,18 @@ #ifndef SOCKET_COMMON_H #define SOCKET_COMMON_H +#define _GNU_SOURCE /* required for pthread_getname_np */ #include #include #include #include #include +#include +#include +#include #include +#include +#include int socket_send_p5_msg(const int sctp, const int socket, diff --git a/nfapi/oai_integration/socket/include/socket_vnf.h b/nfapi/oai_integration/socket/include/socket_vnf.h new file mode 100644 index 0000000000..c11e009153 --- /dev/null +++ b/nfapi/oai_integration/socket/include/socket_vnf.h @@ -0,0 +1,34 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef SOCKET_VNF_H +#define SOCKET_VNF_H +#include "socket_common.h" +#include "vnf.h" +#include "vnf_p7.h" +#include "nr_fapi_p5.h" +#include "nr_nfapi_p7.h" +#include "nr_fapi_p7.h" +bool vnf_nr_send_p5_msg(vnf_t *vnf, uint16_t p5_idx, nfapi_nr_p4_p5_message_header_t* msg, uint32_t msg_len); +bool vnf_nr_send_p7_msg(vnf_p7_t *vnf_p7, nfapi_nr_p7_message_header_t* header); +void vnf_start_p5_thread(void* ptr); +void* vnf_nr_start_p7_thread(void* ptr); +#endif // SOCKET_VNF_H diff --git a/nfapi/oai_integration/socket/socket_vnf.c b/nfapi/oai_integration/socket/socket_vnf.c new file mode 100644 index 0000000000..d5f26a25df --- /dev/null +++ b/nfapi/oai_integration/socket/socket_vnf.c @@ -0,0 +1,861 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ +#include "socket_vnf.h" + +#include "nfapi.h" +#include "nfapi/oai_integration/vendor_ext.h" //TODO: Remove this include when removing the Aerial transport stuff + +static bool send_p5_msg(vnf_t *vnf, nfapi_vnf_pnf_info_t *pnf, const void *msg, int len, uint8_t stream) +{ + int result = socket_send_p5_msg(vnf->sctp, pnf->p5_sock, &pnf->p5_pnf_sockaddr, msg, len, stream); + + if (result != len) { + if (result < 0) { + // error + NFAPI_TRACE(NFAPI_TRACE_ERROR, "sctp sendto failed errno: %d\n", errno); + } else { + // did not send the entire message + } + } + return result == len; +} + +bool vnf_nr_send_p5_msg(vnf_t *vnf, uint16_t p5_idx, nfapi_nr_p4_p5_message_header_t *msg, uint32_t msg_len) +{ + nfapi_vnf_pnf_info_t *pnf = nfapi_vnf_pnf_list_find(&(vnf->_public), p5_idx); + + if (pnf) { + // pack the message for transmission + int packedMessageLength = 0; + if (NFAPI_MODE == NFAPI_MODE_AERIAL) { +#ifdef ENABLE_AERIAL // TODO: Remove this into the aerial VNF transport module + // In case it is a FAPI message, create 2 messages, one with nFAPI header for OAI PNF and one with no nFAPI header for Aerial + // L1 + // create FAPI tx_buffer + uint8_t tx_messagebufferFAPI[sizeof(vnf->tx_message_buffer)]; + int packedMessageLengthFAPI = -1; + packedMessageLengthFAPI = + fapi_nr_p5_message_pack(msg, msg_len, tx_messagebufferFAPI, sizeof(tx_messagebufferFAPI), &vnf->_public.codec_config); + return aerial_send_P5_msg(tx_messagebufferFAPI, packedMessageLengthFAPI, msg); +#else + return 0; +#endif + } else { + packedMessageLength = + vnf->_public.pack_func(msg, msg_len, vnf->tx_message_buffer, sizeof(vnf->tx_message_buffer), &vnf->_public.codec_config); + + if (packedMessageLength < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi_nr_p5_message_pack failed with return %d\n", packedMessageLength); + return false; + } + + return send_p5_msg(vnf, pnf, vnf->tx_message_buffer, packedMessageLength, 0); + } + } else { + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() cannot find pnf info for p5_idx:%d\n", __FUNCTION__, p5_idx); + return false; + } +} + +bool vnf_nr_send_p7_msg(vnf_p7_t *vnf_p7, nfapi_nr_p7_message_header_t *header) +{ + nfapi_vnf_p7_connection_info_t *p7_connection = vnf_p7_connection_info_list_find(vnf_p7, header->phy_id); + if (p7_connection) { + int send_result = 0; + uint8_t buffer[1024 * 1024 * 3]; + + header->m_segment_sequence = NFAPI_NR_P7_SET_MSS(0, 0, p7_connection->sequence_number); + + int len = vnf_p7->_public.pack_func(header, buffer, sizeof(buffer), &vnf_p7->_public.codec_config); + + if (len < 0) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() failed to pack p7 message phy_id:%d\n", __FUNCTION__, header->phy_id); + return false; + } + + if (len > vnf_p7->_public.segment_size) { + // todo : consider replacing with the sendmmsg call + // todo : worry about blocking writes? + + // segmenting the transmit + int msg_body_len = len - NFAPI_NR_P7_HEADER_LENGTH; + int seg_body_len = vnf_p7->_public.segment_size - NFAPI_NR_P7_HEADER_LENGTH; + int segment_count = (msg_body_len / (seg_body_len)) + ((msg_body_len % seg_body_len) ? 1 : 0); + + int segment = 0; + int offset = NFAPI_NR_P7_HEADER_LENGTH; + uint8_t tx_buffer[vnf_p7->_public.segment_size]; + NFAPI_TRACE(NFAPI_TRACE_DEBUG, + "%s() MORE THAN ONE SEGMENT phy_id:%d nfapi_p7_message_pack()=len=%d vnf_p7->_public.segment_size:%u\n", + __FUNCTION__, + header->phy_id, + len, + vnf_p7->_public.segment_size); + for (segment = 0; segment < segment_count; ++segment) { + uint8_t last = 0; + uint16_t size = vnf_p7->_public.segment_size - NFAPI_NR_P7_HEADER_LENGTH; + if (segment + 1 == segment_count) { + last = 1; + size = (msg_body_len) - (seg_body_len * segment); + } + + uint32_t segment_size = size + NFAPI_NR_P7_HEADER_LENGTH; + + // Update the header with the m and segement + memcpy(&tx_buffer[0], buffer, NFAPI_NR_P7_HEADER_LENGTH); + + // set the segment length, update and push m_segment_sequence + uint8_t *buf_ptr = &tx_buffer[4]; + uint8_t *buf_ptr_end = &tx_buffer[10]; + push32(segment_size, (&buf_ptr), buf_ptr_end); + header->m_segment_sequence = NFAPI_NR_P7_SET_MSS((!last), segment, p7_connection->sequence_number); + push16(header->m_segment_sequence, (&buf_ptr), buf_ptr_end); + + memcpy(&tx_buffer[NFAPI_NR_P7_HEADER_LENGTH], &buffer[0] + offset, size); + offset += size; + + if (vnf_p7->_public.checksum_enabled) { + nfapi_nr_p7_update_checksum(tx_buffer, segment_size); + } + const uint32_t time = + calculate_transmit_timestamp(p7_connection->mu, p7_connection->sfn, p7_connection->slot, vnf_p7->slot_start_time_hr); + nfapi_nr_p7_update_transmit_timestamp(tx_buffer, time); + send_result = socket_send_p7_msg(vnf_p7->socket, &(p7_connection->remote_addr), &tx_buffer[0], segment_size); + } + } else { + if (vnf_p7->_public.checksum_enabled) { + nfapi_nr_p7_update_checksum(buffer, len); + } + const uint32_t time = + calculate_transmit_timestamp(p7_connection->mu, p7_connection->sfn, p7_connection->slot, vnf_p7->slot_start_time_hr); + nfapi_nr_p7_update_transmit_timestamp(buffer, time); + send_result = socket_send_p7_msg(vnf_p7->socket, &(p7_connection->remote_addr), &buffer[0], len); + } + p7_connection->sequence_number++; + return send_result == 0; + } else { + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() cannot find p7 connection info for phy_id:%d\n", __FUNCTION__, header->phy_id); + return false; + } +} + +static int vnf_nr_read_dispatch_message(nfapi_vnf_config_t *config, nfapi_vnf_pnf_info_t *pnf) +{ + if (1) { + int socket_connected = 1; + vnf_t *vnf = (vnf_t *)(config); + // 1. Peek the message header + // 2. If the message is larger than the stack buffer then create a dynamic buffer + // 3. Read the buffer + // 4. Handle the p5 message + + uint32_t header_buffer_size = NFAPI_NR_P5_HEADER_LENGTH; + uint8_t header_buffer[header_buffer_size]; + + uint32_t stack_buffer_size = 32; // should it be the size of then sctp_notificatoin structure + uint8_t stack_buffer[stack_buffer_size]; + + uint8_t *dynamic_buffer = 0; + + uint8_t *read_buffer = &stack_buffer[0]; + uint32_t message_size = 0; + + struct sockaddr_in addr; + socklen_t addr_len = sizeof(addr); + + struct sctp_sndrcvinfo sndrcvinfo; + (void)memset(&sndrcvinfo, 0, sizeof(struct sctp_sndrcvinfo)); + + { + int flags = MSG_PEEK; + if (vnf->sctp) { + message_size = + sctp_recvmsg(pnf->p5_sock, header_buffer, header_buffer_size, (struct sockaddr *)&addr, &addr_len, &sndrcvinfo, &flags); + } else { + message_size = recv(pnf->p5_sock, header_buffer, header_buffer_size, flags); + } + + if (message_size == -1) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Failed to peek sctp message size errno:%d\n", errno); + return 0; + } + NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Peeked message with length :0x%02x\n", message_size); + + for (int i = 0; i < message_size; i++) { + printf("%02x ", header_buffer[i]); + } + printf("\n"); + + nfapi_nr_p4_p5_message_header_t header; + const bool result = config->hdr_unpack_func(header_buffer, header_buffer_size, &header, sizeof(header), 0); + if (!result) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Failed to decode message header\n"); + return 0; + } + message_size = header.message_length + header_buffer_size; + + // now have the size of the mesage + NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF After header unpacking msg size is :0x%02x\n", message_size); + } + + if (message_size > stack_buffer_size) { + dynamic_buffer = (uint8_t *)malloc(message_size); + + if (dynamic_buffer == NULL) { + // todo : add error mesage + NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Failed to allocate dynamic buffer for sctp_recvmsg size:%d\n", message_size); + return -1; + } + + read_buffer = dynamic_buffer; + } + + { + int flags = 0; + (void)memset(&sndrcvinfo, 0, sizeof(struct sctp_sndrcvinfo)); + + ssize_t recvmsg_result = 0; + if (vnf->sctp) { + recvmsg_result = + sctp_recvmsg(pnf->p5_sock, read_buffer, message_size, (struct sockaddr *)&addr, &addr_len, &sndrcvinfo, &flags); + } else { + recvmsg_result = recv(pnf->p5_sock, read_buffer, message_size, 0); + } + + if (recvmsg_result == -1) { + int tmp = errno; + NFAPI_TRACE(NFAPI_TRACE_INFO, "Failed to read sctp message size error %s errno:%d\n", strerror(tmp), tmp); + } else { + NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF after recv flags are :0x%02x\n", flags); + + if (flags & MSG_NOTIFICATION) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "Notification received from %s:%u\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); + + // todo - handle the events + } else { + NFAPI_TRACE(NFAPI_TRACE_INFO, + "Received message fd:%d from %s:%u assoc:%d on stream %d, PPID %d, length %d, flags 0x%x\n", + pnf->p5_sock, + inet_ntoa(addr.sin_addr), + ntohs(addr.sin_port), + sndrcvinfo.sinfo_assoc_id, + sndrcvinfo.sinfo_stream, + ntohl(sndrcvinfo.sinfo_ppid), + message_size, + flags); + + // handle now if complete message in one or more segments + if ((flags & 0x80) == 0x80 || !vnf->sctp) { + vnf_nr_handle_p4_p5_message(read_buffer, message_size, pnf->p5_idx, config); + } else { + int tmp = errno; + NFAPI_TRACE(NFAPI_TRACE_WARN, + "sctp_recvmsg: unhandled mode with flags 0x%x and error %s errno:%d\n", + flags, + strerror(tmp), + tmp); + // assume socket disconnected + NFAPI_TRACE(NFAPI_TRACE_WARN, "Disconnected socket\n"); + socket_connected = 0; + } + } + } + } + + if (dynamic_buffer) { + free(dynamic_buffer); + } + + return socket_connected; + } +} + +static int nfapi_nr_vnf_p5_start(nfapi_vnf_config_t *config) +{ + // Verify that config is not null + if (config == 0) + return -1; + + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s()\n", __FUNCTION__); + + int p5ListenSock, p5Sock; + + struct sockaddr_in addr = {0}; + socklen_t addrSize; + + struct sockaddr_in6 addr6 = {0}; + + struct sctp_event_subscribe events = {0}; + struct sctp_initmsg initMsg = {0}; + int noDelay; + + vnf_t *vnf = (vnf_t *)(config); + + NFAPI_TRACE(NFAPI_TRACE_INFO, "Starting P5 VNF connection on port %u\n", config->vnf_p5_port); + + { + int protocol; + int domain; + + if (vnf->sctp) + protocol = IPPROTO_SCTP; + else + protocol = IPPROTO_IP; + + if (config->vnf_ipv6) { + domain = PF_INET6; + } else { + domain = AF_INET; + } + + // open the SCTP socket + if ((p5ListenSock = socket(domain, SOCK_STREAM, protocol)) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After P5 socket errno: %d\n", errno); + return 0; + } + NFAPI_TRACE(NFAPI_TRACE_INFO, "P5 socket created... %d\n", p5ListenSock); + } + + if (vnf->sctp) { + // configure for MSG_NOTIFICATION + if (setsockopt(p5ListenSock, IPPROTO_SCTP, SCTP_EVENTS, &events, sizeof(struct sctp_event_subscribe)) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt (SCTP_EVENTS) errno: %d\n", errno); + close(p5ListenSock); + return 0; + } + NFAPI_TRACE(NFAPI_TRACE_NOTE, "VNF Setting the SCTP_INITMSG\n"); + // configure the SCTP socket options + initMsg.sinit_num_ostreams = 5; // MAX_SCTP_STREAMS; // number of output streams can be greater + initMsg.sinit_max_instreams = 5; // MAX_SCTP_STREAMS; // number of output streams can be greater + if (setsockopt(p5ListenSock, IPPROTO_SCTP, SCTP_INITMSG, &initMsg, sizeof(initMsg)) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt (SCTP_INITMSG) errno: %d\n", errno); + close(p5ListenSock); + return 0; + } + noDelay = 1; + if (setsockopt(p5ListenSock, IPPROTO_SCTP, SCTP_NODELAY, &noDelay, sizeof(noDelay)) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt (STCP_NODELAY) errno: %d\n", errno); + close(p5ListenSock); + return 0; + } + struct sctp_event_subscribe events; + memset((void *)&events, 0, sizeof(events)); + events.sctp_data_io_event = 1; + + if (setsockopt(p5ListenSock, SOL_SCTP, SCTP_EVENTS, (const void *)&events, sizeof(events)) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt errno: %d\n", errno); + close(p5ListenSock); + return -1; + } + } else { + int error; + socklen_t len = sizeof(error); + + if (getsockopt(p5ListenSock, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After getsockopt errno: %d\n", errno); + close(p5ListenSock); + return -1; + } + } + + if (config->vnf_ipv6) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "IPV6 binding to port %d %d\n", config->vnf_p5_port, p5ListenSock); + addr6.sin6_family = AF_INET6; + addr6.sin6_port = htons(config->vnf_p5_port); + addr6.sin6_addr = in6addr_any; + + // bind to the configured address and port + if (bind(p5ListenSock, (struct sockaddr *)&addr6, sizeof(struct sockaddr_in6)) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After bind errno: %d\n", errno); + close(p5ListenSock); + return 0; + } + } else if (config->vnf_ipv4) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "IPV4 binding to port %d\n", config->vnf_p5_port); + addr.sin_family = AF_INET; + addr.sin_port = htons(config->vnf_p5_port); + addr.sin_addr.s_addr = INADDR_ANY; + + // bind to the configured address and port + if (bind(p5ListenSock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After bind errno: %d\n", errno); + close(p5ListenSock); + AssertFatal(1 == 0, "Failed to bind socket with errno: %d\n", errno); + return 0; + } + } + + NFAPI_TRACE(NFAPI_TRACE_INFO, "bind succeeded..%d.\n", p5ListenSock); + + // put the socket into listen mode + if (listen(p5ListenSock, 2) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After listen errno: %d\n", errno); + close(p5ListenSock); + return 0; + } + + NFAPI_TRACE(NFAPI_TRACE_INFO, "listen succeeded...\n"); + + struct timeval tv; + fd_set read_fd_set; + + int p5_idx = 0; + while (vnf->terminate == 0) { + FD_ZERO(&read_fd_set); + + FD_SET(p5ListenSock, &read_fd_set); + int max_fd = p5ListenSock; + + tv.tv_sec = 5; + tv.tv_usec = 0; + + nfapi_vnf_pnf_info_t *pnf = config->pnf_list; + while (pnf != 0) { + if (pnf->connected) { + FD_SET(pnf->p5_sock, &read_fd_set); + if (pnf->p5_sock > max_fd) { + max_fd = pnf->p5_sock; + } + } + + pnf = pnf->next; + } + + int select_result = select(max_fd + 1, &read_fd_set, 0, 0, &tv); + + if (select_result == -1) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "select result %d errno %d\n", select_result, errno); + close(p5ListenSock); + return 0; + } else if (select_result) { + if (FD_ISSET(p5ListenSock, &read_fd_set)) { + addrSize = sizeof(struct sockaddr_in); + NFAPI_TRACE(NFAPI_TRACE_INFO, "Accepting connection from PNF...\n"); + + p5Sock = accept(p5ListenSock, (struct sockaddr *)&addr, &addrSize); + + if (p5Sock < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failed to accept PNF connection reason:%d\n", errno); + } else { + NFAPI_TRACE(NFAPI_TRACE_INFO, + "PNF connection (fd:%d) accepted from %s:%d \n", + p5Sock, + inet_ntoa(addr.sin_addr), + ntohs(addr.sin_port)); + nfapi_vnf_pnf_info_t *pnf = (nfapi_vnf_pnf_info_t *)malloc(sizeof(nfapi_vnf_pnf_info_t)); + NFAPI_TRACE(NFAPI_TRACE_INFO, "MALLOC nfapi_vnf_pnf_info_t for pnf_list pnf:%p\n", pnf); + memset(pnf, 0, sizeof(nfapi_vnf_pnf_info_t)); + pnf->p5_sock = p5Sock; + pnf->p5_idx = p5_idx++; + pnf->p5_pnf_sockaddr = addr; + pnf->connected = 1; + + nfapi_vnf_pnf_list_add(config, pnf); + + // Inform mac that a pnf connection has been established + // todo : allow mac to 'accept' the connection. i.e. to + // reject it. + if (config->pnf_nr_connection_indication != 0) { + (config->pnf_nr_connection_indication)(config, pnf->p5_idx); + } + + // check the connection status + if (vnf->sctp) { + struct sctp_status status; + (void)memset(&status, 0, sizeof(struct sctp_status)); + socklen_t optLen = (socklen_t)sizeof(struct sctp_status); + if (getsockopt(p5Sock, IPPROTO_SCTP, SCTP_STATUS, &status, &optLen) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After getsockopt errno: %d\n", errno); + return -1; + } else { + NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Association ID = %d\n", status.sstat_assoc_id); + NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Receiver window size = %d\n", status.sstat_rwnd); + NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF In Streams = %d\n", status.sstat_instrms); + NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Out Streams = %d\n", status.sstat_outstrms); + } + } + } + } else { + uint8_t delete_pnfs = 0; + + nfapi_vnf_pnf_info_t *pnf = config->pnf_list; + while (pnf != 0) { + if (FD_ISSET(pnf->p5_sock, &read_fd_set)) { + if (vnf_nr_read_dispatch_message(config, pnf) == 0) { + if (config->pnf_disconnect_indication != 0) { + (config->pnf_disconnect_indication)(config, pnf->p5_idx); + } + + close(pnf->p5_sock); + + pnf->to_delete = 1; + delete_pnfs = 1; + } + } + + pnf = pnf->next; + } + + if (delete_pnfs) { + nfapi_vnf_pnf_info_t *pnf = config->pnf_list; + nfapi_vnf_pnf_info_t *prev = 0; + while (pnf != 0) { + nfapi_vnf_pnf_info_t *curr = pnf; + + if (pnf->to_delete == 1) { + if (prev == 0) { + config->pnf_list = pnf->next; + } else { + prev->next = pnf->next; + } + + pnf = pnf->next; + + free(curr); + } else { + prev = pnf; + pnf = pnf->next; + } + } + } + } + + continue; + } else { + // timeout + + // Should we test for socket closure here every second? + + continue; + } + } + + NFAPI_TRACE(NFAPI_TRACE_INFO, "Closing p5Sock socket's\n"); + { + nfapi_vnf_pnf_info_t *curr = config->pnf_list; + while (curr != NULL) { + if (config->pnf_disconnect_indication) { + (config->pnf_disconnect_indication)(config, curr->p5_idx); + } + + close(curr->p5_sock); + curr = curr->next; + } + } + + NFAPI_TRACE(NFAPI_TRACE_INFO, "Closing p5Listen socket\n"); + close(p5ListenSock); + + return 0; +} + +void vnf_start_p5_thread(void *ptr) +{ + NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] VNF NFAPI thread - nfapi_vnf_start()%s\n", __FUNCTION__); + pthread_setname_np(pthread_self(), "VNF"); + nfapi_nr_vnf_p5_start((nfapi_vnf_config_t *)ptr); +} + +void vnf_nr_reassemble_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t *vnf_p7) +{ + nfapi_nr_p7_message_header_t messageHeader; + + // validate the input params + if (pRecvMsg == NULL || recvMsgLen < 4 || vnf_p7 == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "vnf_handle_p7_message: invalid input params (%p %d %p)\n", pRecvMsg, recvMsgLen, vnf_p7); + return; + } + + // unpack the message header + const bool result = + vnf_p7->_public.hdr_unpack_func(pRecvMsg, recvMsgLen, &messageHeader, sizeof(messageHeader), &vnf_p7->_public.codec_config); + if (!result) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n"); + return; + } + + if (vnf_p7->_public.checksum_enabled) { + uint32_t checksum = nfapi_nr_p7_calculate_checksum(pRecvMsg, recvMsgLen); + if (checksum != messageHeader.checksum) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, + "Checksum verification failed %d %d msg:%d len:%d\n", + checksum, + messageHeader.checksum, + messageHeader.message_id, + recvMsgLen); + return; + } + } + + uint8_t m = NFAPI_P7_GET_MORE(messageHeader.m_segment_sequence); + uint8_t segment_num = NFAPI_P7_GET_SEGMENT(messageHeader.m_segment_sequence); + uint8_t sequence_num = NFAPI_P7_GET_SEQUENCE(messageHeader.m_segment_sequence); + + if (m == 0 && segment_num == 0) { + // we have a complete message + // ensure the message is sensible + if (recvMsgLen < 8 || pRecvMsg == NULL) { + NFAPI_TRACE(NFAPI_TRACE_WARN, "Invalid message size: %d, ignoring\n", recvMsgLen); + return; + } + + // vnf_dispatch_p7_message(&messageHeader, pRecvMsg, recvMsgLen, vnf_p7); + vnf_nr_handle_p7_message(pRecvMsg, recvMsgLen, vnf_p7); + } else { + nfapi_vnf_p7_connection_info_t *phy = vnf_p7_connection_info_list_find(vnf_p7, messageHeader.phy_id); + + if (phy) { + vnf_p7_rx_message_t *rx_msg = vnf_p7_rx_reassembly_queue_add_segment(vnf_p7, + &(phy->reassembly_queue), + sequence_num, + segment_num, + m, + pRecvMsg, + recvMsgLen); + + if (rx_msg->num_segments_received == rx_msg->num_segments_expected) { + // send the buffer on + uint16_t i = 0; + uint16_t length = 0; + for (i = 0; i < rx_msg->num_segments_expected; ++i) { + length += rx_msg->segments[i].length - (i > 0 ? NFAPI_NR_P7_HEADER_LENGTH : 0); + } + + if (phy->reassembly_buffer_size < length) { + vnf_p7_free(vnf_p7, phy->reassembly_buffer); + phy->reassembly_buffer = 0; + } + + if (phy->reassembly_buffer == 0) { + NFAPI_TRACE(NFAPI_TRACE_NOTE, "Resizing VNF_P7 Reassembly buffer %d->%d\n", phy->reassembly_buffer_size, length); + phy->reassembly_buffer = (uint8_t *)vnf_p7_malloc(vnf_p7, length); + + if (phy->reassembly_buffer == 0) { + NFAPI_TRACE(NFAPI_TRACE_NOTE, "Failed to allocate VNF_P7 reassemby buffer len:%d\n", length); + return; + } + memset(phy->reassembly_buffer, 0, length); + phy->reassembly_buffer_size = length; + } + + uint16_t offset = 0; + for (i = 0; i < rx_msg->num_segments_expected; ++i) { + if (i == 0) { + memcpy(phy->reassembly_buffer, rx_msg->segments[i].buffer, rx_msg->segments[i].length); + offset += rx_msg->segments[i].length; + } else { + memcpy(phy->reassembly_buffer + offset, + rx_msg->segments[i].buffer + NFAPI_NR_P7_HEADER_LENGTH, + rx_msg->segments[i].length - NFAPI_NR_P7_HEADER_LENGTH); + offset += rx_msg->segments[i].length - NFAPI_NR_P7_HEADER_LENGTH; + } + } + + vnf_nr_handle_p7_message(phy->reassembly_buffer, length, vnf_p7); + + // delete the structure + vnf_p7_rx_reassembly_queue_remove_msg(vnf_p7, &(phy->reassembly_queue), rx_msg); + } + + // see corresponding comment in pnf_nr_handle_p7_message() [same commit] + vnf_p7_rx_reassembly_queue_remove_old_msgs(vnf_p7, &(phy->reassembly_queue), 10000); + } else { + NFAPI_TRACE(NFAPI_TRACE_INFO, "Unknown phy id %d\n", messageHeader.phy_id); + } + } +} + +int vnf_nr_p7_read_dispatch_message(vnf_p7_t *vnf_p7) +{ + int recvfrom_result = 0; + struct sockaddr_in remote_addr; + socklen_t remote_addr_size = sizeof(remote_addr); + + do { + // peek the header + uint8_t header_buffer[NFAPI_NR_P7_HEADER_LENGTH]; + recvfrom_result = recvfrom(vnf_p7->socket, + header_buffer, + NFAPI_NR_P7_HEADER_LENGTH, + MSG_DONTWAIT | MSG_PEEK, + (struct sockaddr *)&remote_addr, + &remote_addr_size); + + if (recvfrom_result > 0) { + // get the segment size + nfapi_nr_p7_message_header_t header; + const bool result = vnf_p7->_public.hdr_unpack_func(header_buffer, NFAPI_NR_P7_HEADER_LENGTH, &header, sizeof(header), 0); + if (!result) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n"); + return -1; + } + + // resize the buffer if we have a large segment + if (header.message_length > vnf_p7->rx_message_buffer_size) { + NFAPI_TRACE(NFAPI_TRACE_NOTE, "reallocing rx buffer %d\n", header.message_length); + vnf_p7->rx_message_buffer = realloc(vnf_p7->rx_message_buffer, header.message_length); + vnf_p7->rx_message_buffer_size = header.message_length; + } + + // read the segment + recvfrom_result = recvfrom(vnf_p7->socket, + vnf_p7->rx_message_buffer, + header.message_length, + MSG_WAITALL | MSG_TRUNC, + (struct sockaddr *)&remote_addr, + &remote_addr_size); + NFAPI_TRACE(NFAPI_TRACE_DEBUG, "recvfrom_result = %d from %s():%d\n", recvfrom_result, __FUNCTION__, __LINE__); + + // todo : how to handle incomplete readfroms, need some sort of buffer/select + + if (recvfrom_result > 0) { + if (recvfrom_result != header.message_length) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, + "(%d) Received unexpected number of bytes. %d != %d", + __LINE__, + recvfrom_result, + header.message_length); + break; + } + NFAPI_TRACE(NFAPI_TRACE_DEBUG, "Calling vnf_nr_reassemble_p7_message from %d\n", __LINE__); + vnf_nr_reassemble_p7_message(vnf_p7->rx_message_buffer, recvfrom_result, vnf_p7); + return 0; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "recvfrom failed %d %d\n", recvfrom_result, errno); + } + } + + if (recvfrom_result == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) { + // return to the select + } else { + NFAPI_TRACE(NFAPI_TRACE_WARN, "%s recvfrom failed errno:%d\n", __FUNCTION__, errno); + } + } + } while (recvfrom_result > 0); + + return 0; +} + +static int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t *config) +{ + if (config == 0) + return -1; + + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s()\n", __FUNCTION__); + + vnf_p7_t *vnf_p7 = (vnf_p7_t *)config; + + // Create p7 receive udp port + // todo : this needs updating for Ipv6 + + NFAPI_TRACE(NFAPI_TRACE_INFO, "Initialising VNF P7 port:%u\n", config->port); + + // open the UDP socket + if ((vnf_p7->socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After P7 socket errno: %d\n", errno); + return -1; + } + + NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF P7 socket created...\n"); + + // configure the UDP socket options + int iptos_value = 0; + if (setsockopt(vnf_p7->socket, IPPROTO_IP, IP_TOS, &iptos_value, sizeof(iptos_value)) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt (IP_TOS) errno: %d\n", errno); + return -1; + } + + NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF P7 setsockopt succeeded...\n"); + + // Create the address structure + struct sockaddr_in addr; + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(config->port); + addr.sin_addr.s_addr = INADDR_ANY; + + // bind to the configured port + NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF P7 binding too %s:%d\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); + if (bind(vnf_p7->socket, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) + // if (sctp_bindx(config->socket, (struct sockaddr *)&addr, sizeof(struct sockaddr_in), 0) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After bind errno: %d\n", errno); + return -1; + } + + NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF P7 bind succeeded...\n"); + + // struct timespec original_pselect_timeout; + struct timespec pselect_timeout; + pselect_timeout.tv_sec = 100; + pselect_timeout.tv_nsec = 0; + + struct timespec ref_time; + clock_gettime(CLOCK_MONOTONIC, &ref_time); + while (vnf_p7->terminate == 0) { + fd_set rfds; + int maxSock = 0; + FD_ZERO(&rfds); + int selectRetval = 0; + + // Add the p7 socket + FD_SET(vnf_p7->socket, &rfds); + maxSock = vnf_p7->socket; + + selectRetval = pselect(maxSock + 1, &rfds, NULL, NULL, &pselect_timeout, NULL); + + if (selectRetval == 0) { + // pselect timed out, continue + } else if (selectRetval > 0) { + // have a p7 message + if (FD_ISSET(vnf_p7->socket, &rfds)) { + vnf_nr_p7_read_dispatch_message(vnf_p7); + } + } else { + // pselect error + if (selectRetval == -1 && errno == EINTR) { + // a sigal was received. + } else { + // should we exit now? + if (selectRetval == -1 && errno == 22) // invalid argument??? not sure about timeout duration + { + usleep(100000); + } + } + } + } + NFAPI_TRACE(NFAPI_TRACE_INFO, "Closing p7 socket\n"); + close(vnf_p7->socket); + + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() returning\n", __FUNCTION__); + + return 0; +} + +void *vnf_nr_start_p7_thread(void *ptr) +{ + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s()\n", __FUNCTION__); + pthread_setname_np(pthread_self(), "VNF_P7"); + nfapi_vnf_p7_config_t *config = (nfapi_vnf_p7_config_t *)ptr; + nfapi_nr_vnf_p7_start(config); + return config; +} diff --git a/nfapi/open-nFAPI/vnf/inc/vnf.h b/nfapi/open-nFAPI/vnf/inc/vnf.h index 006bb2014c..39769314f4 100644 --- a/nfapi/open-nFAPI/vnf/inc/vnf.h +++ b/nfapi/open-nFAPI/vnf/inc/vnf.h @@ -35,16 +35,18 @@ struct vnf_t int vnf_pack_and_send_p5_message(vnf_t* vnf, uint16_t p5_idx, nfapi_p4_p5_message_header_t* msg, uint16_t msg_len); -bool vnf_nr_send_p5_message(vnf_t* vnf, uint16_t p5_idx, nfapi_nr_p4_p5_message_header_t* msg, uint32_t msg_len); int vnf_pack_and_send_p4_message(vnf_t* vnf, uint16_t p5_idx, nfapi_p4_p5_message_header_t* msg, uint16_t msg_len); int vnf_read_dispatch_message(nfapi_vnf_config_t* config, nfapi_vnf_pnf_info_t* pnf); -int vnf_nr_read_dispatch_message(nfapi_vnf_config_t* config, nfapi_vnf_pnf_info_t* pnf); + void nfapi_vnf_phy_info_list_add(nfapi_vnf_config_t* config, nfapi_vnf_phy_info_t* info); nfapi_vnf_phy_info_t* nfapi_vnf_phy_info_list_find(nfapi_vnf_config_t* config, uint16_t phy_id); void nfapi_vnf_pnf_list_add(nfapi_vnf_config_t* config, nfapi_vnf_pnf_info_t* node); nfapi_vnf_pnf_info_t* nfapi_vnf_pnf_list_find(nfapi_vnf_config_t* config, int p5_idx); + +void vnf_nr_handle_p4_p5_message(void *pRecvMsg, int recvMsgLen, int p5_idx, nfapi_vnf_config_t* config); + #endif // _VNF_H_ diff --git a/nfapi/open-nFAPI/vnf/inc/vnf_p7.h b/nfapi/open-nFAPI/vnf/inc/vnf_p7.h index d368c0fa83..7e04d69b49 100644 --- a/nfapi/open-nFAPI/vnf/inc/vnf_p7.h +++ b/nfapi/open-nFAPI/vnf/inc/vnf_p7.h @@ -19,7 +19,6 @@ #define _VNF_P7_H_ #include "nfapi_vnf_interface.h" - #define TIMEHR_SEC(_time_hr) ((uint32_t)(_time_hr) >> 20) #define TIMEHR_USEC(_time_hr) ((uint32_t)(_time_hr) & 0xFFFFF) #define TIME2TIMEHR(_time) (((uint32_t)(_time.tv_sec) & 0xFFF) << 20 | ((uint32_t)(_time.tv_usec) & 0xFFFFF)) @@ -132,15 +131,20 @@ int vnf_nr_sync(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t* p7_info); int send_mac_subframe_indications(vnf_p7_t* config); int send_mac_slot_indications(vnf_p7_t* config); int vnf_p7_read_dispatch_message(vnf_p7_t* vnf_p7 ); -int vnf_nr_p7_read_dispatch_message(vnf_p7_t* vnf_p7 ); +void vnf_nr_handle_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7); +vnf_p7_rx_message_t* vnf_p7_rx_reassembly_queue_add_segment(vnf_p7_t* vnf_p7, vnf_p7_rx_reassembly_queue_t* queue, uint16_t sequence_number, uint16_t segment_number, uint8_t m, uint8_t* data, uint16_t data_len); +void* vnf_p7_malloc(vnf_p7_t* vnf_p7, size_t size); +void vnf_p7_free(vnf_p7_t* vnf_p7, void* ptr); +void vnf_p7_rx_reassembly_queue_remove_msg(vnf_p7_t* vnf_p7, vnf_p7_rx_reassembly_queue_t* queue, vnf_p7_rx_message_t* msg); +void vnf_p7_rx_reassembly_queue_remove_old_msgs(vnf_p7_t* vnf_p7, vnf_p7_rx_reassembly_queue_t* queue, uint32_t delta); +uint32_t calculate_transmit_timestamp(int mu, uint16_t sfn, uint16_t slot, uint32_t slot_start_time_hr); + void vnf_p7_connection_info_list_add(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t* node); nfapi_vnf_p7_connection_info_t* vnf_p7_connection_info_list_find(vnf_p7_t* vnf_p7, uint16_t phy_id); nfapi_vnf_p7_connection_info_t* vnf_p7_connection_info_list_delete(vnf_p7_t* vnf_p7, uint16_t phy_id); int vnf_p7_pack_and_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_p7_message_header_t* header); -bool vnf_nr_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_nr_p7_message_header_t* header); - void vnf_p7_release_msg(vnf_p7_t* vnf_p7, nfapi_p7_message_header_t* header); void vnf_p7_release_pdu(vnf_p7_t* vnf_p7, void* pdu); diff --git a/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h b/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h index c791ff7028..54754fce05 100644 --- a/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h +++ b/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h @@ -529,7 +529,6 @@ void nfapi_vnf_config_destory(nfapi_vnf_config_t* config); * * This function will not return untill nfapi_vnf_stop is called */ -int nfapi_nr_vnf_start(nfapi_vnf_config_t* config); int nfapi_vnf_start(nfapi_vnf_config_t* config); @@ -1000,7 +999,7 @@ void nfapi_vnf_p7_config_destory(nfapi_vnf_p7_config_t* config); * function is called. */ int nfapi_vnf_p7_start(nfapi_vnf_p7_config_t* config); -int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config); + /*! Stop the VNF P7 library. diff --git a/nfapi/open-nFAPI/vnf/src/vnf.c b/nfapi/open-nFAPI/vnf/src/vnf.c index 757a4e7d68..5ac6be4882 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf.c +++ b/nfapi/open-nFAPI/vnf/src/vnf.c @@ -1267,146 +1267,6 @@ void vnf_handle_p4_p5_message(void *pRecvMsg, int recvMsgLen, int p5_idx, nfapi_ } } -int vnf_nr_read_dispatch_message(nfapi_vnf_config_t* config, nfapi_vnf_pnf_info_t* pnf) -{ - if (1) { - int socket_connected = 1; - vnf_t *vnf = (vnf_t *)(config); - // 1. Peek the message header - // 2. If the message is larger than the stack buffer then create a dynamic buffer - // 3. Read the buffer - // 4. Handle the p5 message - - uint32_t header_buffer_size = NFAPI_NR_P5_HEADER_LENGTH; - uint8_t header_buffer[header_buffer_size]; - - uint32_t stack_buffer_size = 32; // should it be the size of then sctp_notificatoin structure - uint8_t stack_buffer[stack_buffer_size]; - - uint8_t* dynamic_buffer = 0; - - uint8_t* read_buffer = &stack_buffer[0]; - uint32_t message_size = 0; - - struct sockaddr_in addr; - socklen_t addr_len = sizeof(addr); - - struct sctp_sndrcvinfo sndrcvinfo; - (void)memset(&sndrcvinfo, 0, sizeof(struct sctp_sndrcvinfo)); - - { - int flags = MSG_PEEK; - if (vnf->sctp) { - message_size = - sctp_recvmsg(pnf->p5_sock, - header_buffer, - header_buffer_size, - (struct sockaddr *)&addr, - &addr_len, - &sndrcvinfo, - &flags); - } else { - message_size = recv(pnf->p5_sock, - header_buffer, - header_buffer_size, - flags); - } - - if (message_size == -1) { - NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Failed to peek sctp message size errno:%d\n", errno); - return 0; - } - - nfapi_nr_p4_p5_message_header_t header; - const bool result = config->hdr_unpack_func(header_buffer, header_buffer_size, &header, sizeof(header), 0); - if (!result) { - NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Failed to decode message header\n"); - return 0; - } - message_size = header.message_length + header_buffer_size; - - // now have the size of the mesage - } - - if (message_size > stack_buffer_size) { - dynamic_buffer = (uint8_t*)malloc(message_size); - - if (dynamic_buffer == NULL) { - // todo : add error mesage - NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Failed to allocate dynamic buffer for sctp_recvmsg size:%d\n", message_size); - return -1; - } - - read_buffer = dynamic_buffer; - } - - { - int flags = 0; - (void)memset(&sndrcvinfo, 0, sizeof(struct sctp_sndrcvinfo)); - - ssize_t recvmsg_result = 0; - if (vnf->sctp) { - recvmsg_result = sctp_recvmsg(pnf->p5_sock, - read_buffer, - message_size, - (struct sockaddr *)&addr, - &addr_len, - &sndrcvinfo, - &flags); - } else { - recvmsg_result = recv(pnf->p5_sock, - read_buffer, - message_size, - 0); - } - - if (recvmsg_result == -1) { - NFAPI_TRACE(NFAPI_TRACE_INFO, "Failed to read sctp message size errno:%d\n", errno); - } else { - if (flags & MSG_NOTIFICATION) { - NFAPI_TRACE(NFAPI_TRACE_INFO, "Notification received from %s:%u\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); - - // todo - handle the events - } else { - /* - NFAPI_TRACE(NFAPI_TRACE_INFO, "Received message fd:%d from %s:%u assoc:%d on stream %d, PPID %d, length %d, flags 0x%x\n", - pnf->p5_sock, - inet_ntoa(addr.sin_addr), - ntohs(addr.sin_port), - sndrcvinfo.sinfo_assoc_id, - sndrcvinfo.sinfo_stream, - ntohl(sndrcvinfo.sinfo_ppid), - message_size, - flags); - */ - - // handle now if complete message in one or more segments - if ((flags & 0x80) == 0x80 || !vnf->sctp) { - // printf("\nVNF RECEIVES:\n"); - // for(int i=0; ip5_idx, config); - } else { - NFAPI_TRACE(NFAPI_TRACE_WARN, "sctp_recvmsg: unhandled mode with flags 0x%x\n", flags); - - // assume socket disconnected - NFAPI_TRACE(NFAPI_TRACE_WARN, "Disconnected socket\n"); - socket_connected = 0; - } - } - } - } - - if (dynamic_buffer) { - free(dynamic_buffer); - } - - return socket_connected; - } -} int vnf_read_dispatch_message(nfapi_vnf_config_t* config, nfapi_vnf_pnf_info_t* pnf) { @@ -1581,53 +1441,6 @@ static int vnf_send_p5_msg(vnf_t *vnf, nfapi_vnf_pnf_info_t *pnf, const void *ms return 0; } -bool vnf_nr_send_p5_message(vnf_t* vnf, uint16_t p5_idx, nfapi_nr_p4_p5_message_header_t* msg, uint32_t msg_len) -{ - nfapi_vnf_pnf_info_t* pnf = nfapi_vnf_pnf_list_find(&(vnf->_public), p5_idx); - - if(pnf) - { - // pack the message for transmission - int packedMessageLength = 0; - if (NFAPI_MODE == NFAPI_MODE_AERIAL) { -#ifdef ENABLE_AERIAL - // In case it is a FAPI message, create 2 messages, one with nFAPI header for OAI PNF and one with no nFAPI header for Aerial - // L1 - // create FAPI tx_buffer - uint8_t tx_messagebufferFAPI[sizeof(vnf->tx_message_buffer)]; - int packedMessageLengthFAPI = -1; - packedMessageLengthFAPI = - fapi_nr_p5_message_pack(msg, msg_len, tx_messagebufferFAPI, sizeof(tx_messagebufferFAPI), &vnf->_public.codec_config); - return aerial_send_P5_msg(tx_messagebufferFAPI, packedMessageLengthFAPI, msg) == 0; -#else - return true; -#endif - } else { - packedMessageLength = nfapi_nr_p5_message_pack(msg, - msg_len, - vnf->tx_message_buffer, - sizeof(vnf->tx_message_buffer), - &vnf->_public.codec_config); - - if (packedMessageLength < 0) { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi_nr_p5_message_pack failed with return %d\n", packedMessageLength); - return false; - } - // printf("msg id = 0x%02x, entire message length: %d\n", msg->message_id, packedMessageLength); - // for (int i = 0; i < packedMessageLength; i++) { - // printf(" msg->msg_buf[%d] = 0x%02x\n", i, ((uint8_t *) vnf->tx_message_buffer)[i]); - // } - - return vnf_send_p5_msg(vnf, pnf, vnf->tx_message_buffer, packedMessageLength, 0); - } - } else { - NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() cannot find pnf info for p5_idx:%d\n", __FUNCTION__, p5_idx); - return false; - } - -} - - int vnf_pack_and_send_p5_message(vnf_t* vnf, uint16_t p5_idx, nfapi_p4_p5_message_header_t* msg, uint16_t msg_len) { nfapi_vnf_pnf_info_t* pnf = nfapi_vnf_pnf_list_find(&(vnf->_public), p5_idx); diff --git a/nfapi/open-nFAPI/vnf/src/vnf_interface.c b/nfapi/open-nFAPI/vnf/src/vnf_interface.c index 9eccb45acb..431ac6066e 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_interface.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_interface.c @@ -65,422 +65,6 @@ void nfapi_vnf_config_destory(nfapi_vnf_config_t* config) free(config); } -int nfapi_nr_vnf_start(nfapi_vnf_config_t* config) -{ - // Verify that config is not null - if(config == 0) - return -1; - - NFAPI_TRACE(NFAPI_TRACE_INFO, "%s()\n", __FUNCTION__); - - int p5ListenSock, p5Sock; - - struct sockaddr_in addr; - socklen_t addrSize; - - struct sockaddr_in6 addr6; - - struct sctp_event_subscribe events; - struct sctp_initmsg initMsg; - int noDelay; - - (void)memset(&addr, 0, sizeof(struct sockaddr_in)); - (void)memset(&addr6, 0, sizeof(struct sockaddr_in6)); - (void)memset(&events, 0, sizeof(struct sctp_event_subscribe)); - (void)memset(&initMsg, 0, sizeof(struct sctp_initmsg)); - - vnf_t* vnf = (vnf_t*)(config); - - NFAPI_TRACE(NFAPI_TRACE_INFO, "Starting P5 VNF connection on port %u\n", config->vnf_p5_port); - - /* - char * host = 0; - char * port = "4242"; - struct addrinfo hints; - bzero(&hints, sizeof(struct addrinfo)); - //hints.ai_flags=AI_PASSIVE; - //hints.ai_flags=AI_DEFAULT; - hints.ai_family=AF_UNSPEC; - //hints.ai_family=AF_INET6; - hints.ai_socktype=SOCK_STREAM; - //hints.ai_protocol=IPPROTO_SCTP - - struct addrinfo *aiHead = 0; - - - - int result = getaddrinfo(host, port, &hints, &aiHead); - NFAPI_TRACE(NFAPI_TRACE_INFO, "getaddrinfo return %d %d\n", result, errno); - - while(aiHead->ai_next != NULL) - { - NFAPI_TRACE(NFAPI_TRACE_INFO, "addr info %d (IP %d UDP %d SCTP %d)\n %d (%d)\n", - aiHead->ai_protocol, IPPROTO_IP, IPPROTO_UDP, IPPROTO_SCTP, - aiHead->ai_flags, AI_PASSIVE); - - char hostBfr[ NI_MAXHOST ]; - char servBfr[ NI_MAXSERV ]; - - getnameinfo(aiHead->ai_addr, - aiHead->ai_addrlen, - hostBfr, - sizeof( hostBfr ), - servBfr, - sizeof( servBfr ), - NI_NUMERICHOST | NI_NUMERICSERV ); - - switch(aiHead->ai_family) - { - case PF_INET: - { - struct sockaddr_in *pSadrIn = (struct sockaddr_in*) aiHead->ai_addr; - printf( - " ai_addr = sin_family: %d (AF_INET = %d, " - "AF_INET6 = %d)\n" - " sin_addr: %s\n" - " sin_port: %s\n", - pSadrIn->sin_family, - AF_INET, - AF_INET6, - hostBfr, - servBfr ); - } - break; - case PF_INET6: - { - struct sockaddr_in6 *pSadrIn6 = (struct sockaddr_in6*) aiHead->ai_addr; - fprintf( stderr, - " ai_addr = sin6_family: %d (AF_INET = %d, " - "AF_INET6 = %d) \n" - " sin6_addr: %s\n" - " sin6_port: %s\n" - " sin6_flowinfo: %d\n" - " sin6_scope_id: %d\n", - pSadrIn6->sin6_family, - AF_INET, - AF_INET6, - hostBfr, - servBfr, - pSadrIn6->sin6_flowinfo, - pSadrIn6->sin6_scope_id); - } - break; - default: - NFAPI_TRACE(NFAPI_TRACE_INFO, "Not ment to be here\n"); - break; - } - - aiHead = aiHead->ai_next; - } - */ - - { - int protocol; - int domain; - - if (vnf->sctp) - protocol = IPPROTO_SCTP; - else - protocol = IPPROTO_IP; - - if(config->vnf_ipv6) - { - domain = PF_INET6; - } - else - { - domain = AF_INET; - } - - // open the SCTP socket - if ((p5ListenSock = socket(domain, SOCK_STREAM, protocol)) < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "After P5 socket errno: %d\n", errno); - return 0; - } - NFAPI_TRACE(NFAPI_TRACE_INFO, "P5 socket created... %d\n", p5ListenSock); - } - - if (vnf->sctp) - { - // configure for MSG_NOTIFICATION - if (setsockopt(p5ListenSock, IPPROTO_SCTP, SCTP_EVENTS, &events, sizeof(struct sctp_event_subscribe)) < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt (SCTP_EVENTS) errno: %d\n", errno); - close(p5ListenSock); - return 0; - } - NFAPI_TRACE(NFAPI_TRACE_NOTE, "VNF Setting the SCTP_INITMSG\n"); - // configure the SCTP socket options - initMsg.sinit_num_ostreams = 5; //MAX_SCTP_STREAMS; // number of output streams can be greater - initMsg.sinit_max_instreams = 5; //MAX_SCTP_STREAMS; // number of output streams can be greater - if (setsockopt(p5ListenSock, IPPROTO_SCTP, SCTP_INITMSG, &initMsg, sizeof(initMsg)) < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt (SCTP_INITMSG) errno: %d\n", errno); - close(p5ListenSock); - return 0; - } - noDelay = 1; - if (setsockopt(p5ListenSock, IPPROTO_SCTP, SCTP_NODELAY, &noDelay, sizeof(noDelay)) < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt (STCP_NODELAY) errno: %d\n", errno); - close(p5ListenSock); - return 0; - } - struct sctp_event_subscribe events; - memset( (void *)&events, 0, sizeof(events) ); - events.sctp_data_io_event = 1; - - if(setsockopt(p5ListenSock, SOL_SCTP, SCTP_EVENTS, (const void *)&events, sizeof(events)) < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt errno: %d\n", errno); - close(p5ListenSock); - return -1; - } - } else { - int error; - socklen_t len = sizeof(error); - - if (getsockopt(p5ListenSock, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "After getsockopt errno: %d\n", errno); - close(p5ListenSock); - return -1; - } - } - - - if(config->vnf_ipv6) - { - NFAPI_TRACE(NFAPI_TRACE_INFO, "IPV6 binding to port %d %d\n", config->vnf_p5_port, p5ListenSock); - addr6.sin6_family = AF_INET6; - addr6.sin6_port = htons(config->vnf_p5_port); - addr6.sin6_addr = in6addr_any; - - // bind to the configured address and port - if (bind(p5ListenSock, (struct sockaddr *)&addr6, sizeof(struct sockaddr_in6)) < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "After bind errno: %d\n", errno); - close(p5ListenSock); - return 0; - } - } - else if(config->vnf_ipv4) - { - NFAPI_TRACE(NFAPI_TRACE_INFO, "IPV4 binding to port %d\n", config->vnf_p5_port); - addr.sin_family = AF_INET; - addr.sin_port = htons(config->vnf_p5_port); - addr.sin_addr.s_addr = INADDR_ANY; - - // bind to the configured address and port - if (bind(p5ListenSock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) - //if (sctp_bindx(p5ListenSock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in), SCTP_BINDX_ADD_ADDR) < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "After bind errno: %d\n", errno); - close(p5ListenSock); - return 0; - } - } - - NFAPI_TRACE(NFAPI_TRACE_INFO, "bind succeeded..%d.\n", p5ListenSock); - - // put the socket into listen mode - if (listen(p5ListenSock, 2) < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "After listen errno: %d\n", errno); - close(p5ListenSock); - return 0; - } - - NFAPI_TRACE(NFAPI_TRACE_INFO, "listen succeeded...\n"); - - struct timeval tv; - fd_set read_fd_set; - - - int p5_idx = 0; - while(vnf->terminate == 0) - { - FD_ZERO(&read_fd_set); - - FD_SET(p5ListenSock, &read_fd_set); - int max_fd = p5ListenSock; - - tv.tv_sec = 5; - tv.tv_usec = 0; - - nfapi_vnf_pnf_info_t* pnf = config->pnf_list; - while(pnf != 0) - { - if(pnf->connected) - { - FD_SET(pnf->p5_sock, &read_fd_set); - if (pnf->p5_sock > max_fd) - { - max_fd = pnf->p5_sock; - } - } - - pnf = pnf->next; - } - - int select_result = select(max_fd + 1, &read_fd_set, 0, 0, &tv); - - if(select_result == -1) - { - NFAPI_TRACE(NFAPI_TRACE_INFO, "select result %d errno %d\n", select_result, errno); - close(p5ListenSock); - return 0; - } - else if(select_result) - { - if(FD_ISSET(p5ListenSock, &read_fd_set)) - { - addrSize = sizeof(struct sockaddr_in); - NFAPI_TRACE(NFAPI_TRACE_INFO, "Accepting connection from PNF...\n"); - - p5Sock = accept(p5ListenSock, (struct sockaddr *)&addr, &addrSize); - - if (p5Sock < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failed to accept PNF connection reason:%d\n", errno); - } - else - { - NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF connection (fd:%d) accepted from %s:%d \n", p5Sock, inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); - nfapi_vnf_pnf_info_t* pnf = (nfapi_vnf_pnf_info_t*)malloc(sizeof(nfapi_vnf_pnf_info_t)); - NFAPI_TRACE(NFAPI_TRACE_INFO, "MALLOC nfapi_vnf_pnf_info_t for pnf_list pnf:%p\n", pnf); - memset(pnf, 0, sizeof(nfapi_vnf_pnf_info_t)); - pnf->p5_sock = p5Sock; - pnf->p5_idx = p5_idx++; - pnf->p5_pnf_sockaddr = addr; - pnf->connected = 1; - - nfapi_vnf_pnf_list_add(config, pnf); - - // Inform mac that a pnf connection has been established - // todo : allow mac to 'accept' the connection. i.e. to - // reject it. - if(config->pnf_nr_connection_indication != 0) - { - (config->pnf_nr_connection_indication)(config, pnf->p5_idx); - } - - - // check the connection status - if (vnf->sctp) - { - struct sctp_status status; - (void)memset(&status, 0, sizeof(struct sctp_status)); - socklen_t optLen = (socklen_t) sizeof(struct sctp_status); - if (getsockopt(p5Sock, IPPROTO_SCTP, SCTP_STATUS, &status, &optLen) < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "After getsockopt errno: %d\n", errno); - return -1; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Association ID = %d\n", status.sstat_assoc_id); - NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Receiver window size = %d\n", status.sstat_rwnd); - NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF In Streams = %d\n", status.sstat_instrms); - NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Out Streams = %d\n", status.sstat_outstrms); - - } - } - } - } - else - { - uint8_t delete_pnfs = 0; - - nfapi_vnf_pnf_info_t* pnf = config->pnf_list; - while(pnf != 0) - { - if(FD_ISSET(pnf->p5_sock, &read_fd_set)) - { - if(vnf_nr_read_dispatch_message(config, pnf) == 0) - { - if(config->pnf_disconnect_indication != 0) - { - (config->pnf_disconnect_indication)(config, pnf->p5_idx); - } - - close(pnf->p5_sock); - - pnf->to_delete = 1; - delete_pnfs = 1; - } - } - - pnf = pnf->next; - } - - if(delete_pnfs) - { - nfapi_vnf_pnf_info_t* pnf = config->pnf_list; - nfapi_vnf_pnf_info_t* prev = 0; - while(pnf != 0) - { - nfapi_vnf_pnf_info_t* curr = pnf; - - if(pnf->to_delete == 1) - { - if(prev == 0) - { - config->pnf_list = pnf->next; - } - else - { - prev->next = pnf->next; - } - - pnf = pnf->next; - - free(curr); - } - else - { - prev = pnf; - pnf = pnf->next; - } - - } - - } - } - - continue; - } - else - { - // timeout - - // Should we test for socket closure here every second? - - continue; - } - } - - NFAPI_TRACE(NFAPI_TRACE_INFO, "Closing p5Sock socket's\n"); - { - nfapi_vnf_pnf_info_t* curr = config->pnf_list; - while(curr != NULL) - { - if(config->pnf_disconnect_indication) - { - (config->pnf_disconnect_indication)(config, curr->p5_idx); - } - - close(curr->p5_sock); - curr = curr->next; - } - } - - NFAPI_TRACE(NFAPI_TRACE_INFO, "Closing p5Listen socket\n"); - close(p5ListenSock); - - return 0; - -} int nfapi_vnf_start(nfapi_vnf_config_t* config) { diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7.c b/nfapi/open-nFAPI/vnf/src/vnf_p7.c index d1c4105997..b82be32226 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7.c @@ -473,101 +473,6 @@ int vnf_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t* p7_info, u return 0; } -bool vnf_nr_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_nr_p7_message_header_t* header) -{ - nfapi_vnf_p7_connection_info_t* p7_connection = vnf_p7_connection_info_list_find(vnf_p7, header->phy_id); - if(p7_connection) - { - int send_result = 0; - uint8_t buffer[1024*1024*3]; - - header->m_segment_sequence = NFAPI_P7_SET_MSS(0, 0, p7_connection->sequence_number); - - int len = nfapi_nr_p7_message_pack(header, buffer, sizeof(buffer), &vnf_p7->_public.codec_config); - - //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() phy_id:%d nfapi_p7_message_pack()=len=%d vnf_p7->_public.segment_size:%u\n", __FUNCTION__, header->phy_id, len, vnf_p7->_public.segment_size); - - if(len < 0) - { - NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() failed to pack p7 message phy_id:%d\n", __FUNCTION__, header->phy_id); - return false; - } - - if(len > vnf_p7->_public.segment_size) - { - // todo : consider replacing with the sendmmsg call - // todo : worry about blocking writes? - - // segmenting the transmit - int msg_body_len = len - NFAPI_NR_P7_HEADER_LENGTH ; - uint32_t seg_body_len = vnf_p7->_public.segment_size - NFAPI_NR_P7_HEADER_LENGTH ; - int segment_count = (msg_body_len / (seg_body_len)) + ((msg_body_len % seg_body_len) ? 1 : 0); - - int segment = 0; - int offset = NFAPI_NR_P7_HEADER_LENGTH; - uint8_t tx_buffer[vnf_p7->_public.segment_size]; - NFAPI_TRACE(NFAPI_TRACE_DEBUG, "%s() MORE THAN ONE SEGMENT phy_id:%d nfapi_p7_message_pack()=len=%d vnf_p7->_public.segment_size:%u\n", __FUNCTION__, header->phy_id, len, vnf_p7->_public.segment_size); - for(segment = 0; segment < segment_count; ++segment) - { - uint8_t last = 0; - uint32_t size = vnf_p7->_public.segment_size - NFAPI_NR_P7_HEADER_LENGTH; - if(segment + 1 == segment_count) - { - last = 1; - size = (msg_body_len) - (seg_body_len * segment); - } - - uint32_t segment_size = size + NFAPI_NR_P7_HEADER_LENGTH; - - // Update the header with the m and segement - memcpy(&tx_buffer[0], buffer, NFAPI_NR_P7_HEADER_LENGTH); - - // set the segment length - tx_buffer[4] = (segment_size & 0xFF000000) >> 24; - tx_buffer[5] = (segment_size & 0xFF0000) >> 16; - tx_buffer[6] = (segment_size & 0xFF00) >> 8; - tx_buffer[7] = (segment_size & 0xFF); - - // set the m & segment number - tx_buffer[8] = ((!last) << 7) + segment; - - memcpy(&tx_buffer[NFAPI_NR_P7_HEADER_LENGTH], &buffer[0] + offset, size); - offset += size; - - if(vnf_p7->_public.checksum_enabled) - { - nfapi_nr_p7_update_checksum(tx_buffer, segment_size); - } - - nfapi_nr_p7_update_transmit_timestamp(buffer, calculate_transmit_timestamp(p7_connection->mu, p7_connection->sfn, p7_connection->slot, vnf_p7->slot_start_time_hr)); - - send_result = vnf_send_p7_msg(vnf_p7, p7_connection, &tx_buffer[0], segment_size); - - } - } - else - { - if(vnf_p7->_public.checksum_enabled) - { - nfapi_nr_p7_update_checksum(buffer, len); - } - - nfapi_nr_p7_update_transmit_timestamp(buffer, calculate_transmit_timestamp(p7_connection->mu, p7_connection->sfn, p7_connection->slot, vnf_p7->slot_start_time_hr)); - - // simple case that the message fits in a single segement - send_result = vnf_send_p7_msg(vnf_p7, p7_connection, &buffer[0], len); - } - - p7_connection->sequence_number++; - return send_result == 0; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() cannot find p7 connection info for phy_id:%d\n", __FUNCTION__, header->phy_id); - return false; - } -} - int vnf_p7_pack_and_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_p7_message_header_t* header) { @@ -2220,7 +2125,7 @@ void vnf_dispatch_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) } } -void vnf_nr_dispatch_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) +void vnf_nr_handle_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) { nfapi_nr_p7_message_header_t header; @@ -2418,198 +2323,6 @@ void vnf_handle_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) } } -void vnf_nr_handle_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) -{ - nfapi_nr_p7_message_header_t messageHeader; - - // validate the input params - if(pRecvMsg == NULL || recvMsgLen < 4 || vnf_p7 == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "vnf_handle_p7_message: invalid input params (%p %d %p)\n", pRecvMsg, recvMsgLen, vnf_p7); - return; - } - - // unpack the message header - const bool result = vnf_p7->_public.hdr_unpack_func(pRecvMsg, recvMsgLen, &messageHeader, sizeof(nfapi_nr_p7_message_header_t), &vnf_p7->_public.codec_config); - if (!result) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n"); - return; - } - - if(vnf_p7->_public.checksum_enabled) - { - uint32_t checksum = nfapi_nr_p7_calculate_checksum(pRecvMsg, recvMsgLen); - if(checksum != messageHeader.checksum) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Checksum verification failed %d %d msg:%d len:%d\n", checksum, messageHeader.checksum, messageHeader.message_id, recvMsgLen); - return; - } - } - - uint8_t m = NFAPI_P7_GET_MORE(messageHeader.m_segment_sequence); - uint8_t segment_num = NFAPI_P7_GET_SEGMENT(messageHeader.m_segment_sequence); - uint8_t sequence_num = NFAPI_P7_GET_SEQUENCE(messageHeader.m_segment_sequence); - - - if(m == 0 && segment_num == 0) - { - // we have a complete message - // ensure the message is sensible - if (recvMsgLen < 8 || pRecvMsg == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_WARN, "Invalid message size: %d, ignoring\n", recvMsgLen); - return; - } - - //vnf_dispatch_p7_message(&messageHeader, pRecvMsg, recvMsgLen, vnf_p7); - vnf_nr_dispatch_p7_message(pRecvMsg, recvMsgLen, vnf_p7); - } - else - { - nfapi_vnf_p7_connection_info_t* phy = vnf_p7_connection_info_list_find(vnf_p7, messageHeader.phy_id); - - if(phy) - { - vnf_p7_rx_message_t* rx_msg = vnf_p7_rx_reassembly_queue_add_segment(vnf_p7, &(phy->reassembly_queue), sequence_num, segment_num, m, pRecvMsg, recvMsgLen); - - if(rx_msg->num_segments_received == rx_msg->num_segments_expected) - { - // send the buffer on - uint16_t i = 0; - uint16_t length = 0; - for(i = 0; i < rx_msg->num_segments_expected; ++i) - { - length += rx_msg->segments[i].length - (i > 0 ? NFAPI_NR_P7_HEADER_LENGTH : 0); - } - - if(phy->reassembly_buffer_size < length) - { - vnf_p7_free(vnf_p7, phy->reassembly_buffer); - phy->reassembly_buffer = 0; - } - - if(phy->reassembly_buffer == 0) - { - NFAPI_TRACE(NFAPI_TRACE_NOTE, "Resizing VNF_P7 Reassembly buffer %d->%d\n", phy->reassembly_buffer_size, length); - phy->reassembly_buffer = (uint8_t*)vnf_p7_malloc(vnf_p7, length); - - if(phy->reassembly_buffer == 0) - { - NFAPI_TRACE(NFAPI_TRACE_NOTE, "Failed to allocate VNF_P7 reassemby buffer len:%d\n", length); - return; - } - memset(phy->reassembly_buffer, 0, length); - phy->reassembly_buffer_size = length; - } - - uint16_t offset = 0; - for(i = 0; i < rx_msg->num_segments_expected; ++i) - { - if(i == 0) - { - memcpy(phy->reassembly_buffer, rx_msg->segments[i].buffer, rx_msg->segments[i].length); - offset += rx_msg->segments[i].length; - } - else - { - memcpy(phy->reassembly_buffer + offset, rx_msg->segments[i].buffer + NFAPI_NR_P7_HEADER_LENGTH, rx_msg->segments[i].length - NFAPI_NR_P7_HEADER_LENGTH); - offset += rx_msg->segments[i].length - NFAPI_NR_P7_HEADER_LENGTH; - } - } - - - //pnf_dispatch_p7_message(pnf_p7->reassemby_buffer, length, pnf_p7, rx_msg->rx_hr_time); - vnf_nr_dispatch_p7_message(phy->reassembly_buffer, length , vnf_p7); - - - // delete the structure - vnf_p7_rx_reassembly_queue_remove_msg(vnf_p7, &(phy->reassembly_queue), rx_msg); - } - - // see corresponding comment in pnf_nr_handle_p7_message() [same commit] - vnf_p7_rx_reassembly_queue_remove_old_msgs(vnf_p7, &(phy->reassembly_queue), 10000); - } - else - { - - NFAPI_TRACE(NFAPI_TRACE_INFO, "Unknown phy id %d\n", messageHeader.phy_id); - } - } -} - -int vnf_nr_p7_read_dispatch_message(vnf_p7_t* vnf_p7) -{ - int recvfrom_result = 0; - struct sockaddr_in remote_addr; - socklen_t remote_addr_size = sizeof(remote_addr); - - do - { - // peek the header - uint8_t header_buffer[NFAPI_NR_P7_HEADER_LENGTH]; - recvfrom_result = recvfrom(vnf_p7->socket, header_buffer, NFAPI_NR_P7_HEADER_LENGTH, MSG_DONTWAIT | MSG_PEEK, (struct sockaddr*)&remote_addr, &remote_addr_size); - - if(recvfrom_result > 0) - { - // get the segment size - nfapi_nr_p7_message_header_t header; - const bool result = vnf_p7->_public.hdr_unpack_func(header_buffer, NFAPI_NR_P7_HEADER_LENGTH, &header, sizeof(header), 0); - if(!result) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n"); - return -1; - } - - // resize the buffer if we have a large segment - if(header.message_length > vnf_p7->rx_message_buffer_size) - { - NFAPI_TRACE(NFAPI_TRACE_NOTE, "reallocing rx buffer %d\n", header.message_length); - vnf_p7->rx_message_buffer = realloc(vnf_p7->rx_message_buffer, header.message_length); - vnf_p7->rx_message_buffer_size = header.message_length; - } - - // read the segment - recvfrom_result = recvfrom(vnf_p7->socket, vnf_p7->rx_message_buffer, header.message_length, MSG_WAITALL | MSG_TRUNC, (struct sockaddr*)&remote_addr, &remote_addr_size); - NFAPI_TRACE(NFAPI_TRACE_DEBUG, "recvfrom_result = %d from %s():%d\n", recvfrom_result, __FUNCTION__, __LINE__); - - // todo : how to handle incomplete readfroms, need some sort of buffer/select - - if (recvfrom_result > 0) - { - if (recvfrom_result != header.message_length) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "(%d) Received unexpected number of bytes. %d != %d", - __LINE__, recvfrom_result, header.message_length); - break; - } - NFAPI_TRACE(NFAPI_TRACE_DEBUG, "Calling vnf_nr_handle_p7_message from %d\n", __LINE__); - vnf_nr_handle_p7_message(vnf_p7->rx_message_buffer, recvfrom_result, vnf_p7); - return 0; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "recvfrom failed %d %d\n", recvfrom_result, errno); - } - } - - if(recvfrom_result == -1) - { - if(errno == EAGAIN || errno == EWOULDBLOCK) - { - // return to the select - //NFAPI_TRACE(NFAPI_TRACE_WARN, "%s recvfrom would block :%d\n", __FUNCTION__, errno); - } - else - { - NFAPI_TRACE(NFAPI_TRACE_WARN, "%s recvfrom failed errno:%d\n", __FUNCTION__, errno); - } - } - } - while(recvfrom_result > 0); - - return 0; -} int vnf_p7_read_dispatch_message(vnf_p7_t* vnf_p7) { @@ -2655,7 +2368,7 @@ int vnf_p7_read_dispatch_message(vnf_p7_t* vnf_p7) __LINE__, recvfrom_result, header.message_length); break; } - NFAPI_TRACE(NFAPI_TRACE_INFO, "Calling vnf_nr_handle_p7_message from %d\n", __LINE__); + NFAPI_TRACE(NFAPI_TRACE_INFO, "Calling vnf_nr_reassemble_p7_message from %d\n", __LINE__); vnf_handle_p7_message(vnf_p7->rx_message_buffer, recvfrom_result, vnf_p7); return 0; } diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c index c536995e91..6f16e7c4d2 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c @@ -30,7 +30,7 @@ #include "common/ran_context.h" #include "openair1/PHY/defs_gNB.h" -#define FAPI2_IP_DSCP 0 + extern RAN_CONTEXT_t RC; @@ -96,115 +96,6 @@ struct timespec timespec_sub(struct timespec lhs, struct timespec rhs) // monitor the p7 endpoints and the timing loop and // send indications to mac -int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config) -{ - if(config == 0) - return -1; - - NFAPI_TRACE(NFAPI_TRACE_INFO, "%s()\n", __FUNCTION__); - - vnf_p7_t* vnf_p7 = (vnf_p7_t*)config; - - // Create p7 receive udp port - // todo : this needs updating for Ipv6 - - NFAPI_TRACE(NFAPI_TRACE_INFO, "Initialising VNF P7 port:%u\n", config->port); - - // open the UDP socket - if ((vnf_p7->socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "After P7 socket errno: %d\n", errno); - return -1; - } - - NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF P7 socket created...\n"); - - // configure the UDP socket options - int iptos_value = FAPI2_IP_DSCP << 2; - if (setsockopt(vnf_p7->socket, IPPROTO_IP, IP_TOS, &iptos_value, sizeof(iptos_value)) < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt (IP_TOS) errno: %d\n", errno); - return -1; - } - - NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF P7 setsockopt succeeded...\n"); - - // Create the address structure - struct sockaddr_in addr; - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_port = htons(config->port); - addr.sin_addr.s_addr = INADDR_ANY; - - // bind to the configured port - NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF P7 binding too %s:%d\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); - if (bind(vnf_p7->socket, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) - //if (sctp_bindx(config->socket, (struct sockaddr *)&addr, sizeof(struct sockaddr_in), 0) < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "After bind errno: %d\n", errno); - return -1; - } - - NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF P7 bind succeeded...\n"); - - - //struct timespec original_pselect_timeout; - struct timespec pselect_timeout; - pselect_timeout.tv_sec = 100; - pselect_timeout.tv_nsec = 0; - - struct timespec ref_time; - clock_gettime(CLOCK_MONOTONIC, &ref_time); - while(vnf_p7->terminate == 0) - { - fd_set rfds; - int maxSock = 0; - FD_ZERO(&rfds); - int selectRetval = 0; - - // Add the p7 socket - FD_SET(vnf_p7->socket, &rfds); - maxSock = vnf_p7->socket; - - selectRetval = pselect(maxSock+1, &rfds, NULL, NULL, &pselect_timeout, NULL); - - if(selectRetval == 0) - { - // pselect timed out, continue - } - else if(selectRetval > 0) - { - // have a p7 message - if(FD_ISSET(vnf_p7->socket, &rfds)) - { - vnf_nr_p7_read_dispatch_message(vnf_p7); - } - } - else - { - // pselect error - if(selectRetval == -1 && errno == EINTR) - { - // a sigal was received. - } - else - { - //NFAPI_TRACE(NFAPI_TRACE_INFO, "P7 select failed result %d errno %d timeout:%d.%d orginal:%d.%d last_ms:%ld ms:%ld\n", selectRetval, errno, pselect_timeout.tv_sec, pselect_timeout.tv_nsec, pselect_timeout.tv_sec, pselect_timeout.tv_nsec, last_millisecond, millisecond); - // should we exit now? - if (selectRetval == -1 && errno == 22) // invalid argument??? not sure about timeout duration - { - usleep(100000); - } - } - } - } - NFAPI_TRACE(NFAPI_TRACE_INFO, "Closing p7 socket\n"); - close(vnf_p7->socket); - - NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() returning\n", __FUNCTION__); - - return 0; -} int nfapi_vnf_p7_start(nfapi_vnf_p7_config_t* config) @@ -231,7 +122,7 @@ int nfapi_vnf_p7_start(nfapi_vnf_p7_config_t* config) NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF P7 socket created...\n"); // configure the UDP socket options - int iptos_value = FAPI2_IP_DSCP << 2; + int iptos_value = 0; if (setsockopt(vnf_p7->socket, IPPROTO_IP, IP_TOS, &iptos_value, sizeof(iptos_value)) < 0) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt (IP_TOS) errno: %d\n", errno); From 3e3d87226802db439e3114b1849b2b03c97f55aa Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 26 May 2025 17:53:51 +0200 Subject: [PATCH 190/964] Avoid use of xran_get_slot_idx_from_tti() and use public API xran_get_slot_idx_from_tti() has been introduced to access data information from xran. However, it makes no sense, as the used macros to calculate frame, slot, subframe, are already in the public API. Hence, use these macros directly. It would be possible to remove xran_get_slot_idx_from_tti(), but doing so we would need to update the patch ID, causing trouble to users. --- radio/fhi_72/oaioran.c | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/radio/fhi_72/oaioran.c b/radio/fhi_72/oaioran.c index 7ac4998e40..755a07dee1 100644 --- a/radio/fhi_72/oaioran.c +++ b/radio/fhi_72/oaioran.c @@ -67,12 +67,6 @@ volatile oran_sync_info_t oran_sync_info = {0}; void oai_xran_fh_rx_callback(void *pCallbackTag, xran_status_t status) { struct xran_cb_tag *callback_tag = (struct xran_cb_tag *)pCallbackTag; - uint64_t second; - uint32_t tti; - uint32_t frame; - uint32_t subframe; - uint32_t slot, slot2; - uint32_t rx_sym; static int32_t last_slot = -1; static int32_t last_frame = -1; @@ -87,21 +81,17 @@ void oai_xran_fh_rx_callback(void *pCallbackTag, xran_status_t status) const int slots_per_subframe = 1 << xran_ctx->fh_cfg.frame_conf.nNumerology; static int rx_RU[XRAN_PORTS_NUM][160] = {0}; - uint32_t rx_tti = callback_tag->slotiId; + uint32_t tti = callback_tag->slotiId; + uint32_t slotnum = SLOTNUM_PER_SUBFRAME(xran_ctx->interval_us_local); + uint32_t frame = XranGetFrameNum(tti, 0, SUBFRAMES_PER_SYSTEMFRAME, slotnum); + uint32_t subframe = XranGetSubFrameNum(tti, slotnum, SUBFRAMES_PER_SYSTEMFRAME); + uint32_t slot = XranGetSlotNum(tti, slotnum); - tti = xran_get_slot_idx_from_tti(rx_tti, &frame, &subframe, &slot, &second); - - rx_sym = callback_tag->symbol & 0xFF; + uint32_t rx_sym = callback_tag->symbol & 0xFF; uint32_t ru_id = callback_tag->oXuId; - LOG_D(HW, - "rx_callback frame %d, subframe %d, slot %d, second %lld, rx_sym %d ru_id %d\n", - frame, - subframe, - slot, - (unsigned long long)second, - rx_sym, - ru_id); + LOG_D(HW, "rx_callback at %4d.%3d (subframe %d), rx_sym %d ru_id %d\n", frame, slot, subframe, rx_sym, ru_id); + if (rx_sym == 7) { // in F release this value is defined as XRAN_FULL_CB_SYM (full slot (offset + 7)) #ifdef F_RELEASE for (int ru_idx = 0; ru_idx < num_ports; ru_idx++) { @@ -127,7 +117,7 @@ void oai_xran_fh_rx_callback(void *pCallbackTag, xran_status_t status) // would see periodic output with only "0" in stats counters if (!first_call_set) return; - slot2 = slot + (subframe * slots_per_subframe); + uint32_t slot2 = slot + (subframe * slots_per_subframe); rx_RU[ru_id][slot2] = 1; if (last_frame > 0 && frame > 0 && ((slot2 > 0 && last_frame != frame) || (slot2 == 0 && last_frame != ((1024 + frame - 1) & 1023)))) From 8dcdee85f70f06349944def311cd6f2a2346c2d6 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 27 May 2025 09:21:17 +0200 Subject: [PATCH 191/964] Use buffers as set up by driver The buffers are set up by the OAI xran driver, so instead of peaking into xran internal data, access the buffers through the driver directly. The buffers get set up through the following xran calls In xran_5g_fronthault_config(): - src => sFrontHaulTxBbuIoBufCtrl - srccp => sFrontHaulTxPrbMapBbuIoBufCtrl - dst => sFrontHaulRxBbuIoBufCtrl - dstcp => sFrontHaulRxPrbMapBbuIoBufCtrl In xran_5g_prach_req() - prach(dst) => sFHPrachRxBbuIoBufCtrl - prach(dst)decomp => sFHPrachRxBbuIoBufCtrlDecomp Note that in all cases: - the xran buffer array is [XRAN_N_FE_BUF_LEN][XRAN_MAX_SECTOR_NR][XRAN_MAX_ANTENNA_NR] (of [internal] type BbuIoBufCtrlStruct, but we give an sBufferList) - the driver buffer array is [XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN] Hence, we switch the order of indexing, leave out the sector, and omit the sBufferList member. --- radio/fhi_72/oaioran.c | 28 ++++++++++++---------------- radio/fhi_72/oran-init.c | 5 +++++ radio/fhi_72/oran-init.h | 2 ++ 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/radio/fhi_72/oaioran.c b/radio/fhi_72/oaioran.c index 755a07dee1..8be878f8ca 100644 --- a/radio/fhi_72/oaioran.c +++ b/radio/fhi_72/oaioran.c @@ -97,9 +97,10 @@ void oai_xran_fh_rx_callback(void *pCallbackTag, xran_status_t status) for (int ru_idx = 0; ru_idx < num_ports; ru_idx++) { struct xran_device_ctx *xran_ctx_per_ru = xran_dev_get_ctx_by_id(ru_idx); struct xran_fh_config *fh_config = &xran_ctx_per_ru->fh_cfg; + oran_buf_list_t *bufs = get_xran_buffers(ru_idx); for (uint16_t cc_id = 0; cc_id < 1 /* fh_config->nCC */; cc_id++) { // OAI does not support multiple CC yet. for(uint32_t ant_id = 0; ant_id < fh_config->neAxc; ant_id++) { - struct xran_prb_map *pRbMap = (struct xran_prb_map *)xran_ctx_per_ru->sFrontHaulRxPrbMapBbuIoBufCtrl[tti % XRAN_N_FE_BUF_LEN][cc_id][ant_id].sBufferList.pBuffers->pData; + struct xran_prb_map *pRbMap = (struct xran_prb_map *)bufs->dstcp[ant_id][tti % XRAN_N_FE_BUF_LEN].pBuffers->pData; AssertFatal(pRbMap != NULL, "(%d:%d:%d)pRbMap == NULL. Aborting.\n", cc_id, tti % XRAN_N_FE_BUF_LEN, ant_id); for (uint32_t sym_id = 0; sym_id < XRAN_NUM_OF_SYMBOL_PER_SLOT; sym_id++) { @@ -188,12 +189,9 @@ static int read_prach_data(ru_info_t *ru, int frame, int slot) for (int aa = 0; aa < ru->nb_rx; aa++) { int16_t *dst, *src; int idx = 0; - xran_ctx = xran_dev_get_ctx_by_id(aa / nb_rx_per_ru); + oran_buf_list_t *bufs = get_xran_buffers(aa / nb_rx_per_ru); dst = ru->prach_buf[aa]; // + (sym_idx*576)); - src = (int16_t *)((uint8_t *)xran_ctx->sFHPrachRxBbuIoBufCtrlDecomp[tti % XRAN_N_FE_BUF_LEN][0][aa % nb_rx_per_ru] - .sBufferList.pBuffers[sym_idx] - .pData); - + src = (int16_t *)bufs->prachdstdecomp[aa % nb_rx_per_ru][tti % XRAN_N_FE_BUF_LEN].pBuffers[sym_idx].pData; /* convert Network order to host order */ if (ru_conf->compMeth_PRACH == XRAN_COMPMETHOD_NONE) { if (sym_idx == 0) { @@ -351,8 +349,8 @@ int xran_fh_rx_read_slot(ru_info_t *ru, int *frame, int *slot) continue; uint8_t *pData; - uint8_t *pPrbMapData = xran_ctx->sFrontHaulRxPrbMapBbuIoBufCtrl[tti % XRAN_N_FE_BUF_LEN][cc_id][ant_id % nb_rx_per_ru] - .sBufferList.pBuffers->pData; + oran_buf_list_t *bufs = get_xran_buffers(ant_id / nb_rx_per_ru); + uint8_t *pPrbMapData = bufs->dstcp[ant_id % nb_rx_per_ru][tti % XRAN_N_FE_BUF_LEN].pBuffers->pData; struct xran_prb_map *pPrbMap = (struct xran_prb_map *)pPrbMapData; struct xran_prb_elm *pRbElm = &pPrbMap->prbMap[0]; @@ -364,8 +362,8 @@ int xran_fh_rx_read_slot(ru_info_t *ru, int *frame, int *slot) uint32_t one_rb_size = (((pRbElm->iqWidth == 0) || (pRbElm->iqWidth == 16)) ? (N_SC_PER_PRB * 2 * 2) : (3 * pRbElm->iqWidth + 1)); if (fh_init->mtu < pRbElm->nRBSize * one_rb_size) - pData = xran_ctx->sFrontHaulRxBbuIoBufCtrl[tti % XRAN_N_FE_BUF_LEN][cc_id][ant_id % nb_rx_per_ru] - .sBufferList.pBuffers[sym_idx % XRAN_NUM_OF_SYMBOL_PER_SLOT] + pData = bufs->dst[ant_id % nb_rx_per_ru][tti % XRAN_N_FE_BUF_LEN] + .pBuffers[sym_idx % XRAN_NUM_OF_SYMBOL_PER_SLOT] .pData; else pData = p_sec_desc->pData; @@ -491,14 +489,12 @@ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp) for (uint16_t cc_id = 0; cc_id < 1 /*nSectorNum*/; cc_id++) { // OAI does not support multiple CC yet. for (uint8_t ant_id = 0; ant_id < ru->nb_tx; ant_id++) { - xran_ctx = xran_dev_get_ctx_by_id(ant_id / nb_tx_per_ru); + oran_buf_list_t *bufs = get_xran_buffers(ant_id / nb_tx_per_ru); // This loop would better be more inner to avoid confusion and maybe also errors. for (int32_t sym_idx = 0; sym_idx < XRAN_NUM_OF_SYMBOL_PER_SLOT; sym_idx++) { - uint8_t *pData = xran_ctx->sFrontHaulTxBbuIoBufCtrl[tti % XRAN_N_FE_BUF_LEN][cc_id][ant_id % nb_tx_per_ru] - .sBufferList.pBuffers[sym_idx % XRAN_NUM_OF_SYMBOL_PER_SLOT] - .pData; - uint8_t *pPrbMapData = xran_ctx->sFrontHaulTxPrbMapBbuIoBufCtrl[tti % XRAN_N_FE_BUF_LEN][cc_id][ant_id % nb_tx_per_ru] - .sBufferList.pBuffers->pData; + uint8_t *pData = + bufs->src[ant_id % nb_tx_per_ru][tti % XRAN_N_FE_BUF_LEN].pBuffers[sym_idx % XRAN_NUM_OF_SYMBOL_PER_SLOT].pData; + uint8_t *pPrbMapData = bufs->srccp[ant_id % nb_tx_per_ru][tti % XRAN_N_FE_BUF_LEN].pBuffers->pData; struct xran_prb_map *pPrbMap = (struct xran_prb_map *)pPrbMapData; ptr = pData; pos = &ru->txdataF_BF[ant_id][sym_idx * fftsize]; diff --git a/radio/fhi_72/oran-init.c b/radio/fhi_72/oran-init.c index 38e766805a..410df0166a 100644 --- a/radio/fhi_72/oran-init.c +++ b/radio/fhi_72/oran-init.c @@ -464,3 +464,8 @@ int *oai_oran_initialize(struct xran_fh_init *xran_fh_init, struct xran_fh_confi return (void *)gxran_handle; } + +oran_buf_list_t *get_xran_buffers(uint32_t port_id) +{ + return gPortInst[port_id][0].buf_list; +} diff --git a/radio/fhi_72/oran-init.h b/radio/fhi_72/oran-init.h index b9f31d9889..e12fa90858 100644 --- a/radio/fhi_72/oran-init.h +++ b/radio/fhi_72/oran-init.h @@ -59,4 +59,6 @@ extern void *gxran_handle; int *oai_oran_initialize(struct xran_fh_init *fh_init, struct xran_fh_config *fh_config); +oran_buf_list_t *get_xran_buffers(uint32_t port_id); + #endif /* ORAN_INIT_H */ From 42b5df351d0fefbb591bd421cd52398c6c5bb693 Mon Sep 17 00:00:00 2001 From: Romain Beurdouche Date: Wed, 9 Jul 2025 14:49:03 +0200 Subject: [PATCH 192/964] Split out PRACH-specific functions into separate header Split out type and function definitions for a cleaner separation for some consumers of these functions. Concretely, nr_mac_common.h includes various ASN.1 NR RRC headers, but not all consumers of these APIs might need these headers. For instance, the next commit will use these functions in the driver for 7.2 (it needs to compute PRACH length), but the driver itself does not depend on nor does it need the ASN.1 NR RRC headers. Defining a new header avoids the problem. --- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h | 21 +----- .../LAYER2/NR_MAC_COMMON/nr_prach_config.h | 75 +++++++++++++++++++ 2 files changed, 76 insertions(+), 20 deletions(-) create mode 100644 openair2/LAYER2/NR_MAC_COMMON/nr_prach_config.h diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h index 84284f0c48..3770d2c6ec 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h @@ -35,6 +35,7 @@ #include "NR_CellGroupConfig.h" #include "NR_UE-NR-Capability.h" #include "nr_mac.h" +#include "nr_prach_config.h" #include "common/utils/nr/nr_common.h" #define NB_SRS_PERIOD (18) @@ -52,20 +53,6 @@ typedef enum { pusch_len2 = 2 } pusch_maxLength_t; -typedef struct { - uint32_t format; - uint32_t start_symbol; - uint32_t N_t_slot; - uint32_t N_dur; - uint32_t N_RA_slot; - uint32_t N_RA_sfn; - uint32_t max_association_period; - int x; - int y; - int y2; - uint64_t s_map; -} nr_prach_info_t; - typedef struct { uint16_t bwpStart; uint16_t bwpSize; @@ -161,8 +148,6 @@ void find_aggregation_candidates(uint8_t *aggregation_level, const NR_SearchSpace_t *ss, int maxL); -uint16_t get_nr_prach_format_from_index(uint8_t index, uint32_t pointa, uint8_t unpaired); - bool get_nr_prach_sched_from_info(nr_prach_info_t info, int config_index, int frame, @@ -172,8 +157,6 @@ bool get_nr_prach_sched_from_info(nr_prach_info_t info, uint16_t *RA_sfn_index, uint8_t unpaired); -nr_prach_info_t get_nr_prach_occasion_info_from_index(uint8_t index, frequency_range_t freq_range, uint8_t unpaired); - uint8_t get_pusch_mcs_table(long *mcs_Table, int is_tp, int dci_format, @@ -190,8 +173,6 @@ int ul_ant_bits(NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig, long transformPrec uint8_t get_pdsch_mcs_table(long *mcs_Table, int dci_format, int rnti_type, int ss_type); -int get_format0(uint8_t index, uint8_t unpaired, frequency_range_t frequency_range); - uint16_t get_NCS(uint8_t index, uint16_t format, uint8_t restricted_set_config); int compute_pucch_crc_size(int O_uci); uint8_t get_l0_ul(uint8_t mapping_type, uint8_t dmrs_typeA_position); diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_prach_config.h b/openair2/LAYER2/NR_MAC_COMMON/nr_prach_config.h new file mode 100644 index 0000000000..1b6aa0bfb7 --- /dev/null +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_prach_config.h @@ -0,0 +1,75 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file openair2/LAYER2/NR_MAC_COMMON/nr_prach_config.h +* \brief Tools to query the PRACH configuration tables +* \author Romain beurdouche +* \date Jul. 2025 +* \version 0.1 +* \company Eurecom +* \email romain.beurdouche@eurecom.fr +* \note The PRACH configuration tables are used in the MAC layer for scheduling and beyond. +* For example the PRACH duration is requested in the O-RAN 7.2 FrontHaul Interface +*/ + +/** + * @brief Fetch PRACH format (format only) from PRACH configuration tables + * + * @param index PRACH configuration index + * @param unpaired Duplex mode TDD or FDD + * @param freq_range Frequency range FR1 or FR2 + * @return PRACH format (format only) + */ +int get_format0(uint8_t index, uint8_t unpaired, frequency_range_t frequency_range); + +typedef struct { + uint32_t format; + uint32_t start_symbol; + uint32_t N_t_slot; + uint32_t N_dur; + uint32_t N_RA_slot; + uint32_t N_RA_sfn; + uint32_t max_association_period; + int x; + int y; + int y2; + uint64_t s_map; +} nr_prach_info_t; + +/** + * @brief Fetch PRACH occasion info from PRACH configuration tables + * + * @param index PRACH configuration index + * @param freq_range Frequency range FR1 or FR2 + * @param unpaired Duplex mode TDD or FDD + * @return PRACH occasion information + */ +nr_prach_info_t get_nr_prach_occasion_info_from_index(uint8_t index, frequency_range_t freq_range, uint8_t unpaired); + +/** + * @brief Fetch PRACH format (format concatenated with format2) from PRACH configuration tables + * + * @param index PRACH configuration index + * @param pointa Point A ARFCN to determine the Frequency range FR1 or FR2 + * @param unpaired Duplex mode TDD or FDD + * @return PRACH format (format concatenated with format2) + */ +uint16_t get_nr_prach_format_from_index(uint8_t index, uint32_t pointa, uint8_t unpaired); From cc076eb54704968bd20859a8627ea195ef09b378 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 9 Jul 2025 14:54:52 +0200 Subject: [PATCH 193/964] Use locally available data instead of peaking into xran internals Look up xran_fh_init/xran_fh_config through driver instead of peaking into xran internals. Note that xran writes values back into these structs during initialization, and hence it is important to store them _after initialization_. Some remarks regarding less obvious changes: - slotnum is replaced by slots_in_sf: SLOTNUM_PER_SUBFRAME uses the time duration of a slot (=interval_us_local) to calculate the numbers of slots in a subframe, which can be done with a simple shift instead - The prach duration should be queried from the PRACH configuration table. The function to query the occasion info is part of the MAC layer code while this information can be used outside of this layer. Use header `nr_prach_config.h` to not duplicate functionality. Co-authored-by: Romain Beurdouche --- radio/fhi_72/oaioran.c | 59 ++++++++++++++++++++-------------------- radio/fhi_72/oran-init.c | 41 ++++++++++++++++++++++++++++ radio/fhi_72/oran-init.h | 3 ++ 3 files changed, 73 insertions(+), 30 deletions(-) diff --git a/radio/fhi_72/oaioran.c b/radio/fhi_72/oaioran.c index 8be878f8ca..ee213f4301 100644 --- a/radio/fhi_72/oaioran.c +++ b/radio/fhi_72/oaioran.c @@ -43,6 +43,8 @@ #include "common/utils/threadPool/notified_fifo.h" +#define N_SC_PER_PRB 12 + #if OAI_FHI72_USE_POLLING #define USE_POLLING #endif @@ -71,21 +73,19 @@ void oai_xran_fh_rx_callback(void *pCallbackTag, xran_status_t status) static int32_t last_slot = -1; static int32_t last_frame = -1; - /* xran context contains the same xran_fh_init struct info, - but xran_fh_config struct info is RU specific only */ - struct xran_device_ctx *xran_ctx = xran_dev_get_ctx(); - const struct xran_fh_init *fh_init = &xran_ctx->fh_init; + const struct xran_fh_init *fh_init = get_xran_fh_init(); int num_ports = fh_init->xran_ports; /* assuming all RUs have the same numerology */ - const int slots_per_subframe = 1 << xran_ctx->fh_cfg.frame_conf.nNumerology; + const struct xran_fh_config *fh_cfg = get_xran_fh_config(0); + const int slots_in_sf = 1 << fh_cfg->frame_conf.nNumerology; + const int sf_in_frame = 10; static int rx_RU[XRAN_PORTS_NUM][160] = {0}; uint32_t tti = callback_tag->slotiId; - uint32_t slotnum = SLOTNUM_PER_SUBFRAME(xran_ctx->interval_us_local); - uint32_t frame = XranGetFrameNum(tti, 0, SUBFRAMES_PER_SYSTEMFRAME, slotnum); - uint32_t subframe = XranGetSubFrameNum(tti, slotnum, SUBFRAMES_PER_SYSTEMFRAME); - uint32_t slot = XranGetSlotNum(tti, slotnum); + uint32_t frame = XranGetFrameNum(tti, 0, sf_in_frame, slots_in_sf); + uint32_t subframe = XranGetSubFrameNum(tti, slots_in_sf, sf_in_frame); + uint32_t slot = XranGetSlotNum(tti, slots_in_sf); uint32_t rx_sym = callback_tag->symbol & 0xFF; uint32_t ru_id = callback_tag->oXuId; @@ -95,8 +95,7 @@ void oai_xran_fh_rx_callback(void *pCallbackTag, xran_status_t status) if (rx_sym == 7) { // in F release this value is defined as XRAN_FULL_CB_SYM (full slot (offset + 7)) #ifdef F_RELEASE for (int ru_idx = 0; ru_idx < num_ports; ru_idx++) { - struct xran_device_ctx *xran_ctx_per_ru = xran_dev_get_ctx_by_id(ru_idx); - struct xran_fh_config *fh_config = &xran_ctx_per_ru->fh_cfg; + struct xran_fh_config *fh_config = get_xran_fh_config(ru_idx); oran_buf_list_t *bufs = get_xran_buffers(ru_idx); for (uint16_t cc_id = 0; cc_id < 1 /* fh_config->nCC */; cc_id++) { // OAI does not support multiple CC yet. for(uint32_t ant_id = 0; ant_id < fh_config->neAxc; ant_id++) { @@ -118,7 +117,7 @@ void oai_xran_fh_rx_callback(void *pCallbackTag, xran_status_t status) // would see periodic output with only "0" in stats counters if (!first_call_set) return; - uint32_t slot2 = slot + (subframe * slots_per_subframe); + uint32_t slot2 = slot + (subframe * slots_in_sf); rx_RU[ru_id][slot2] = 1; if (last_frame > 0 && frame > 0 && ((slot2 > 0 && last_frame != frame) || (slot2 == 0 && last_frame != ((1024 + frame - 1) & 1023)))) @@ -172,20 +171,21 @@ static int read_prach_data(ru_info_t *ru, int frame, int slot) /* calculate tti and subframe_id from frame, slot num */ int sym_idx = 0; - struct xran_device_ctx *xran_ctx = xran_dev_get_ctx(); - struct xran_prach_cp_config *pPrachCPConfig = &(xran_ctx->PrachCPConfig); - struct xran_ru_config *ru_conf = &(xran_ctx->fh_cfg.ru_conf); - int slots_per_frame = 10 << xran_ctx->fh_cfg.frame_conf.nNumerology; - int slots_per_subframe = 1 << xran_ctx->fh_cfg.frame_conf.nNumerology; + struct xran_fh_init *fh_init = get_xran_fh_init(); + struct xran_fh_config *fh_cfg = get_xran_fh_config(0); + int prach_sym = get_prach_conf_duration(0); + struct xran_ru_config *ru_conf = &fh_cfg->ru_conf; + int slots_per_frame = 10 << fh_cfg->frame_conf.nNumerology; + int slots_per_subframe = 1 << fh_cfg->frame_conf.nNumerology; int tti = slots_per_frame * (frame) + (slot); uint32_t subframe = slot / slots_per_subframe; uint32_t is_prach_slot = xran_is_prach_slot(0, subframe, (slot % slots_per_subframe)); - int nb_rx_per_ru = ru->nb_rx / xran_ctx->fh_init.xran_ports; + int nb_rx_per_ru = ru->nb_rx / fh_init->xran_ports; /* If it is PRACH slot, copy prach IQ from XRAN PRACH buffer to OAI PRACH buffer */ if (is_prach_slot) { - for (sym_idx = 0; sym_idx < pPrachCPConfig->numSymbol; sym_idx++) { + for (sym_idx = 0; sym_idx < prach_sym; sym_idx++) { for (int aa = 0; aa < ru->nb_rx; aa++) { int16_t *dst, *src; int idx = 0; @@ -316,16 +316,16 @@ int xran_fh_rx_read_slot(ru_info_t *ru, int *frame, int *slot) #endif // return(0); - struct xran_device_ctx *xran_ctx = xran_dev_get_ctx(); - int slots_per_frame = 10 << xran_ctx->fh_cfg.frame_conf.nNumerology; + struct xran_fh_config *fh_cfg = get_xran_fh_config(0); + int slots_per_frame = 10 << fh_cfg->frame_conf.nNumerology; int tti = slots_per_frame * (*frame) + (*slot); read_prach_data(ru, *frame, *slot); - const struct xran_fh_init *fh_init = &xran_ctx->fh_init; - int nPRBs = xran_ctx->fh_cfg.nULRBs; - int fftsize = 1 << xran_ctx->fh_cfg.ru_conf.fftSize; + const struct xran_fh_init *fh_init = get_xran_fh_init(); + int nPRBs = fh_cfg->nULRBs; + int fftsize = 1 << fh_cfg->ru_conf.fftSize; int slot_offset_rxdata = 3 & (*slot); uint32_t slot_size = 4 * 14 * fftsize; @@ -336,8 +336,7 @@ int xran_fh_rx_read_slot(ru_info_t *ru, int *frame, int *slot) for (uint8_t ant_id = 0; ant_id < ru->nb_rx; ant_id++) { rx_data = (uint8_t *)ru->rxdataF[ant_id]; start_ptr = rx_data + (slot_size * slot_offset_rxdata); - xran_ctx = xran_dev_get_ctx_by_id(ant_id / nb_rx_per_ru); - const struct xran_frame_config *frame_conf = &xran_ctx->fh_cfg.frame_conf; + const struct xran_frame_config *frame_conf = &get_xran_fh_config(ant_id / nb_rx_per_ru)->frame_conf; // skip processing this slot is TX (no RX in this slot) if (is_tdd_dl_guard_slot(frame_conf, *slot)) continue; @@ -481,10 +480,10 @@ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp) int32_t *pos = NULL; int idx = 0; - struct xran_device_ctx *xran_ctx = xran_dev_get_ctx(); - const struct xran_fh_init *fh_init = &xran_ctx->fh_init; - int nPRBs = xran_ctx->fh_cfg.nDLRBs; - int fftsize = 1 << xran_ctx->fh_cfg.ru_conf.fftSize; + const struct xran_fh_init *fh_init = get_xran_fh_init(); + const struct xran_fh_config *fh_cfg = get_xran_fh_config(0); + int nPRBs = fh_cfg->nDLRBs; + int fftsize = 1 << fh_cfg->ru_conf.fftSize; int nb_tx_per_ru = ru->nb_tx / fh_init->xran_ports; for (uint16_t cc_id = 0; cc_id < 1 /*nSectorNum*/; cc_id++) { // OAI does not support multiple CC yet. diff --git a/radio/fhi_72/oran-init.c b/radio/fhi_72/oran-init.c index 410df0166a..07517dcf18 100644 --- a/radio/fhi_72/oran-init.c +++ b/radio/fhi_72/oran-init.c @@ -30,7 +30,9 @@ #include "common/utils/assertions.h" #include "common/utils/LOG/log.h" +#include "common/utils/nr/nr_common.h" #include "common_lib.h" +#include "openair2/LAYER2/NR_MAC_COMMON/nr_prach_config.h" /* PRACH data samples are 32 bits wide (16bits for I/Q). Each packet contains * 840 samples for long sequence or 144 for short sequence. The payload length @@ -46,6 +48,10 @@ static oran_port_instance_t gPortInst[XRAN_PORTS_NUM][XRAN_MAX_SECTOR_NR]; void *gxran_handle; +static struct xran_fh_init g_fh_init = {0}; +static struct xran_fh_config g_fh_config[XRAN_PORTS_NUM] = {0}; +static uint32_t g_prach_conf_duration[XRAN_PORTS_NUM] = {0}; + static uint32_t get_nSW_ToFpga_FTH_TxBufferLen(int mu, int sections) { uint32_t xran_max_sections_per_slot = RTE_MAX(sections, XRAN_MIN_SECTIONS_PER_SLOT); @@ -460,12 +466,47 @@ int *oai_oran_initialize(struct xran_fh_init *xran_fh_init, struct xran_fh_confi printf("xran_reg_physide_cb failed %d\n", xret); exit(-1); } + + // retrieve and store prach duration + uint8_t idx = xran_fh_config[o_xu_id].prach_conf.nPrachConfIdx; + const struct xran_frame_config *fc = &xran_fh_config[o_xu_id].frame_conf; + g_prach_conf_duration[o_xu_id] = + get_nr_prach_occasion_info_from_index(idx, + fc->nNumerology > 2 ? FR2 : FR1, + fc->nFrameDuplexType == XRAN_FDD ? duplex_mode_FDD : duplex_mode_TDD) + .N_dur; } + // store config after xran initialization -- xran makes modifications to + // these structs during initialization + memcpy(&g_fh_init, xran_fh_init, sizeof(*xran_fh_init)); + memcpy(&g_fh_config, xran_fh_config, sizeof(*xran_fh_config) * xran_fh_init->xran_ports); + return (void *)gxran_handle; } oran_buf_list_t *get_xran_buffers(uint32_t port_id) { + struct xran_fh_init *fh_init = get_xran_fh_init(); + DevAssert(port_id < fh_init->xran_ports); return gPortInst[port_id][0].buf_list; } + +struct xran_fh_init *get_xran_fh_init(void) +{ + return &g_fh_init; +} + +struct xran_fh_config *get_xran_fh_config(uint32_t port_id) +{ + struct xran_fh_init *fh_init = get_xran_fh_init(); + DevAssert(port_id < fh_init->xran_ports); + return &g_fh_config[port_id]; +} + +uint32_t get_prach_conf_duration(uint32_t port_id) +{ + struct xran_fh_init *fh_init = get_xran_fh_init(); + DevAssert(port_id < fh_init->xran_ports); + return g_prach_conf_duration[port_id]; +} diff --git a/radio/fhi_72/oran-init.h b/radio/fhi_72/oran-init.h index e12fa90858..e56b683a9f 100644 --- a/radio/fhi_72/oran-init.h +++ b/radio/fhi_72/oran-init.h @@ -60,5 +60,8 @@ extern void *gxran_handle; int *oai_oran_initialize(struct xran_fh_init *fh_init, struct xran_fh_config *fh_config); oran_buf_list_t *get_xran_buffers(uint32_t port_id); +struct xran_fh_init *get_xran_fh_init(void); +struct xran_fh_config *get_xran_fh_config(uint32_t port_id); +uint32_t get_prach_conf_duration(uint32_t port_id); #endif /* ORAN_INIT_H */ From b7a6b1b7d68c0be6067ebc57e7201181154eb436 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 27 May 2025 09:19:19 +0200 Subject: [PATCH 194/964] Do not include xran internal data: not needed --- cmake_targets/tools/MODULES/Findxran.cmake | 5 +---- radio/fhi_72/oaioran.c | 1 - 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/cmake_targets/tools/MODULES/Findxran.cmake b/cmake_targets/tools/MODULES/Findxran.cmake index 1ade3ac522..369f04753f 100644 --- a/cmake_targets/tools/MODULES/Findxran.cmake +++ b/cmake_targets/tools/MODULES/Findxran.cmake @@ -126,12 +126,9 @@ find_package_handle_standard_args(xran VERSION_VAR xran_VERSION ) -# in proper usage of cmake, include directory should only contain "api", but not header files under "src" directory; -# however, we use xran_dev_get_ctx() and xran_dev_get_ctx_by_id() functions which are defined in xran_common.h; -# since xran_common.h is under "src" directory, we have to include it in ${xran_INCLUDE_DIRS} if(xran_FOUND) set(xran_LIBRARIES ${xran_LIBRARY}) - set(xran_INCLUDE_DIRS ${xran_INCLUDE_DIR} ${xran_INCLUDE_DIR}/../src) + set(xran_INCLUDE_DIRS ${xran_INCLUDE_DIR}) endif() if(xran_FOUND AND NOT TARGET xran::xran) diff --git a/radio/fhi_72/oaioran.c b/radio/fhi_72/oaioran.c index ee213f4301..fc9f58a492 100644 --- a/radio/fhi_72/oaioran.c +++ b/radio/fhi_72/oaioran.c @@ -35,7 +35,6 @@ #include "xran_sync_api.h" #include "oran_isolate.h" #include "oran-init.h" -#include "xran_common.h" #include "oaioran.h" #include From 02bc14d8c176b77698220b77d6a84eb74311c7b8 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 27 May 2025 09:18:34 +0200 Subject: [PATCH 195/964] get xran stats Get xran stats in the trx_oran_get_stats function and use trx_oran_get_stats upon stopping and ending RF. Co-authored-by: Romain Beurdouche --- executables/main_ru.c | 16 ++++++++++++++++ executables/nr-ru.c | 3 +++ executables/nr-softmodem.c | 14 ++++++++++++++ executables/nr-uesoftmodem.c | 8 +++++++- radio/fhi_72/oran_isolate.c | 5 +++++ 5 files changed, 45 insertions(+), 1 deletion(-) diff --git a/executables/main_ru.c b/executables/main_ru.c index 86a26f9ac3..3579c26f7a 100644 --- a/executables/main_ru.c +++ b/executables/main_ru.c @@ -97,11 +97,19 @@ void exit_function(const char *file, const char *function, const int line, const oai_exit = 1; if (ru_m.rfdevice.trx_end_func) { + if (ru_m.rfdevice.trx_get_stats_func) { + ru_m.rfdevice.trx_get_stats_func(&ru_m.rfdevice); + ru_m.rfdevice.trx_get_stats_func = NULL; + } ru_m.rfdevice.trx_end_func(&ru_m.rfdevice); ru_m.rfdevice.trx_end_func = NULL; } if (ru_m.ifdevice.trx_end_func) { + if (ru_m.ifdevice.trx_get_stats_func) { + ru_m.ifdevice.trx_get_stats_func(&ru_m.ifdevice); + ru_m.ifdevice.trx_get_stats_func = NULL; + } ru_m.ifdevice.trx_end_func(&ru_m.ifdevice); ru_m.ifdevice.trx_end_func = NULL; } @@ -363,11 +371,19 @@ int main ( int argc, char **argv ) end_configmodule(uniqCfg); if (ru->rfdevice.trx_end_func) { + if (ru->rfdevice.trx_get_stats_func) { + ru->rfdevice.trx_get_stats_func(&ru->rfdevice); + ru->rfdevice.trx_get_stats_func = NULL; + } ru->rfdevice.trx_end_func(&ru->rfdevice); ru->rfdevice.trx_end_func = NULL; } if (ru->ifdevice.trx_end_func) { + if (ru->ifdevice.trx_get_stats_func) { + ru->ifdevice.trx_get_stats_func(&ru->ifdevice); + ru->ifdevice.trx_get_stats_func = NULL; + } ru->ifdevice.trx_end_func(&ru->ifdevice); ru->ifdevice.trx_end_func = NULL; } diff --git a/executables/nr-ru.c b/executables/nr-ru.c index 411caf9a63..8f29ce4749 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -1371,6 +1371,9 @@ int start_rf(RU_t *ru) { } int stop_rf(RU_t *ru) { + if (ru->rfdevice.trx_get_stats_func) { + ru->rfdevice.trx_get_stats_func(&ru->rfdevice); + } ru->rfdevice.trx_end_func(&ru->rfdevice); return 0; } diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c index 332e06e7af..602606039a 100644 --- a/executables/nr-softmodem.c +++ b/executables/nr-softmodem.c @@ -207,11 +207,19 @@ void exit_function(const char *file, const char *function, const int line, const for (ru_id=0; ru_idrfdevice.trx_end_func) { + if (RC.ru[ru_id]->rfdevice.trx_get_stats_func) { + RC.ru[ru_id]->rfdevice.trx_get_stats_func(&RC.ru[ru_id]->rfdevice); + RC.ru[ru_id]->rfdevice.trx_get_stats_func = NULL; + } RC.ru[ru_id]->rfdevice.trx_end_func(&RC.ru[ru_id]->rfdevice); RC.ru[ru_id]->rfdevice.trx_end_func = NULL; } if (RC.ru[ru_id] && RC.ru[ru_id]->ifdevice.trx_end_func) { + if (RC.ru[ru_id]->ifdevice.trx_get_stats_func) { + RC.ru[ru_id]->ifdevice.trx_get_stats_func(&RC.ru[ru_id]->ifdevice); + RC.ru[ru_id]->ifdevice.trx_get_stats_func = NULL; + } RC.ru[ru_id]->ifdevice.trx_end_func(&RC.ru[ru_id]->ifdevice); RC.ru[ru_id]->ifdevice.trx_end_func = NULL; } @@ -423,11 +431,17 @@ int stop_L1(module_id_t gnb_id) stop_RU(RC.nb_RU); /* stop trx devices, multiple carrier currently not supported by RU */ + if (ru->rfdevice.trx_get_stats_func) { + ru->rfdevice.trx_get_stats_func(&ru->rfdevice); + } if (ru->rfdevice.trx_stop_func) { ru->rfdevice.trx_stop_func(&ru->rfdevice); LOG_I(GNB_APP, "turned off RU rfdevice\n"); } + if (ru->ifdevice.trx_get_stats_func) { + ru->ifdevice.trx_get_stats_func(&ru->rfdevice); + } if (ru->ifdevice.trx_stop_func) { ru->ifdevice.trx_stop_func(&ru->ifdevice); LOG_I(GNB_APP, "turned off RU ifdevice\n"); diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index f1e94e9e55..fad251b060 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -170,8 +170,12 @@ void exit_function(const char *file, const char *function, const int line, const if (PHY_vars_UE_g && PHY_vars_UE_g[0]) { for(CC_id=0; CC_idrfdevice.trx_end_func) + if (PHY_vars_UE_g[0][CC_id] && PHY_vars_UE_g[0][CC_id]->rfdevice.trx_end_func) { + if (PHY_vars_UE_g[0][CC_id]->rfdevice.trx_get_stats_func) { + PHY_vars_UE_g[0][CC_id]->rfdevice.trx_get_stats_func(&PHY_vars_UE_g[0][CC_id]->rfdevice); + } PHY_vars_UE_g[0][CC_id]->rfdevice.trx_end_func(&PHY_vars_UE_g[0][CC_id]->rfdevice); + } } } @@ -591,6 +595,8 @@ int main(int argc, char **argv) ret = pthread_join(phy_vars->stat_thread, NULL); AssertFatal(ret == 0, "pthread_join error %d, errno %d (%s)\n", ret, errno, strerror(errno)); } + if (phy_vars->rfdevice.trx_get_stats_func) + phy_vars->rfdevice.trx_get_stats_func(&phy_vars->rfdevice); if (phy_vars->rfdevice.trx_end_func) phy_vars->rfdevice.trx_end_func(&phy_vars->rfdevice); } diff --git a/radio/fhi_72/oran_isolate.c b/radio/fhi_72/oran_isolate.c index 7ceec513c6..4a141275d7 100644 --- a/radio/fhi_72/oran_isolate.c +++ b/radio/fhi_72/oran_isolate.c @@ -103,6 +103,11 @@ int trx_oran_set_gains(openair0_device *device, openair0_config_t *openair0_cfg) int trx_oran_get_stats(openair0_device *device) { + uint64_t total_time, used_time; + uint32_t num_core_used, core_used[64]; + uint32_t ret = xran_get_time_stats(&total_time, &used_time, &num_core_used, &core_used[0], 0); + if (ret == 0) + LOG_I(HW, "xran_get_time_stats(): total thread time %ld, total time essential tasks %ld, num cores used %d\n", total_time, used_time, num_core_used); printf("ORAN: %s\n", __FUNCTION__); return (0); } From d3283c4819e885a6165e5b893b62dad358c362dc Mon Sep 17 00:00:00 2001 From: Romain Beurdouche Date: Wed, 25 Jun 2025 13:45:07 +0000 Subject: [PATCH 196/964] feat(oran_fhlib_5g): F release works with DPDK21+ Modify xran F release patch to make it compile and run with DPDK 21+ (tested with DPDK 22.11) --- .../F/oaioran_F.patch | 315 +++++++++++++++++- 1 file changed, 307 insertions(+), 8 deletions(-) diff --git a/cmake_targets/tools/oran_fhi_integration_patches/F/oaioran_F.patch b/cmake_targets/tools/oran_fhi_integration_patches/F/oaioran_F.patch index b8d09cf862..8157172d85 100644 --- a/cmake_targets/tools/oran_fhi_integration_patches/F/oaioran_F.patch +++ b/cmake_targets/tools/oran_fhi_integration_patches/F/oaioran_F.patch @@ -259,7 +259,7 @@ index 46e0e1d..409ef4b 100644 int xran_prepare_iq_symbol_portion( struct rte_mbuf *mbuf, diff --git a/fhi_lib/lib/ethernet/ethdi.c b/fhi_lib/lib/ethernet/ethdi.c -index f5b2fd6..144a65e 100644 +index f5b2fd6..2eccc6e 100644 --- a/fhi_lib/lib/ethernet/ethdi.c +++ b/fhi_lib/lib/ethernet/ethdi.c @@ -37,7 +37,10 @@ @@ -273,7 +273,33 @@ index f5b2fd6..144a65e 100644 #include #include #include -@@ -325,8 +328,8 @@ xran_ethdi_init_dpdk_io(char *name, const struct xran_io_cfg *io_cfg, +@@ -185,14 +188,24 @@ static void check_port_link_status(uint8_t portid) + printf("Port %d Link Up - speed %u " + "Mbps - %s\n", (uint8_t)portid, + (unsigned)link.link_speed, ++#if (RTE_VER_YEAR >= 21) ++ (link.link_duplex == RTE_ETH_LINK_FULL_DUPLEX) ? ++ ("full-duplex") : ("half-duplex\n") ++#else + (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? +- ("full-duplex") : ("half-duplex\n")); ++ ("full-duplex") : ("half-duplex\n") ++#endif ++ ); + else + printf("Port %d Link Down\n", + (uint8_t)portid); + } + /* clear all_ports_up flag if any link down */ ++#if (RTE_VER_YEAR >= 21) ++ if (link.link_status == RTE_ETH_LINK_DOWN) { ++#else + if (link.link_status == ETH_LINK_DOWN) { ++#endif + all_ports_up = 0; + break; + } +@@ -325,8 +338,8 @@ xran_ethdi_init_dpdk_io(char *name, const struct xran_io_cfg *io_cfg, char bbdev_wdev[32] = ""; char bbdev_vdev[32] = ""; char iova_mode[32] = "--iova-mode=pa"; @@ -284,7 +310,7 @@ index f5b2fd6..144a65e 100644 char ring_name[32] = ""; int32_t xran_port = -1; queueid_t qi = 0; -@@ -336,7 +339,7 @@ xran_ethdi_init_dpdk_io(char *name, const struct xran_io_cfg *io_cfg, +@@ -336,7 +349,7 @@ xran_ethdi_init_dpdk_io(char *name, const struct xran_io_cfg *io_cfg, cpu = sched_getcpu(); node = numa_node_of_cpu(cpu); @@ -293,7 +319,7 @@ index f5b2fd6..144a65e 100644 "--file-prefix", name, "-a0000:00:00.0", bbdev_wdev, bbdev_vdev}; if (io_cfg == NULL) -@@ -481,11 +484,13 @@ xran_ethdi_init_dpdk_io(char *name, const struct xran_io_cfg *io_cfg, +@@ -481,11 +494,13 @@ xran_ethdi_init_dpdk_io(char *name, const struct xran_io_cfg *io_cfg, ctx->tx_ring[i] = rte_ring_create(ring_name, NUM_MBUFS_RING_TRX, rte_lcore_to_socket_id(*lcore_id), RING_F_SC_DEQ); PANIC_ON(ctx->tx_ring[i] == NULL, "failed to allocate rx ring"); @@ -307,7 +333,7 @@ index f5b2fd6..144a65e 100644 } } } else { -@@ -555,7 +560,7 @@ xran_ethdi_init_dpdk_io(char *name, const struct xran_io_cfg *io_cfg, +@@ -555,7 +570,7 @@ xran_ethdi_init_dpdk_io(char *name, const struct xran_io_cfg *io_cfg, ctx->up_dl_pkt_gen_ring[i] = rte_ring_create(ring_name, NUM_MBUFS_RING, rte_lcore_to_socket_id(*lcore_id), /*RING_F_SC_DEQ*/0); PANIC_ON(ctx->up_dl_pkt_gen_ring[i] == NULL, "failed to allocate dl gen ring"); @@ -317,7 +343,7 @@ index f5b2fd6..144a65e 100644 return 1; diff --git a/fhi_lib/lib/ethernet/ethernet.c b/fhi_lib/lib/ethernet/ethernet.c -index edda598..791256c 100644 +index edda598..77e5ca7 100644 --- a/fhi_lib/lib/ethernet/ethernet.c +++ b/fhi_lib/lib/ethernet/ethernet.c @@ -37,7 +37,10 @@ @@ -331,6 +357,78 @@ index edda598..791256c 100644 #include #include #include +@@ -149,13 +152,22 @@ void xran_init_port(int p_id, uint16_t num_rxq, uint32_t mtu) + static uint16_t nb_txd = BURST_SIZE; + struct rte_ether_addr addr; + struct rte_eth_rxmode rxmode = { ++#if (RTE_VER_YEAR >= 21) ++ .mtu = MAX_RX_LEN, ++#else + .split_hdr_size = 0, + .max_rx_pkt_len = MAX_RX_LEN, + .offloads = DEV_RX_OFFLOAD_JUMBO_FRAME ++#endif + }; + struct rte_eth_txmode txmode = { ++#if (RTE_VER_YEAR >= 21) ++ .mq_mode = RTE_ETH_MQ_TX_NONE, ++ .offloads = RTE_ETH_TX_OFFLOAD_MULTI_SEGS ++#else + .mq_mode = ETH_MQ_TX_NONE, + .offloads = DEV_TX_OFFLOAD_MULTI_SEGS ++#endif + }; + struct rte_eth_conf port_conf = { + .rxmode = rxmode, +@@ -174,8 +186,13 @@ void xran_init_port(int p_id, uint16_t num_rxq, uint32_t mtu) + uint32_t num_mbufs = 0; + + if (mtu <= 1500) { ++#if (RTE_VER_YEAR >= 21) ++ rxmode.offloads &= ~RTE_ETH_TX_OFFLOAD_IPIP_TNL_TSO; ++ rxmode.mtu = RTE_ETHER_MAX_LEN; ++#else + rxmode.offloads &= ~DEV_RX_OFFLOAD_JUMBO_FRAME; + rxmode.max_rx_pkt_len = RTE_ETHER_MAX_LEN; ++#endif + data_room_size = MBUF_POOL_ELM_SMALL; + } + +@@ -184,10 +201,19 @@ void xran_init_port(int p_id, uint16_t num_rxq, uint32_t mtu) + drv_name = dev_info.driver_name; + printf("initializing port %d for TX, drv=%s\n", p_id, drv_name); + +- if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE){ ++#if (RTE_VER_YEAR >= 21) ++ if (dev_info.tx_offload_capa & RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE) ++#else ++ if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) ++#endif ++ { + printf("set DEV_TX_OFFLOAD_MBUF_FAST_FREE\n"); + port_conf.txmode.offloads |= ++#if (RTE_VER_YEAR >= 21) ++ RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE; ++#else + DEV_TX_OFFLOAD_MBUF_FAST_FREE; ++#endif + } + + rte_eth_macaddr_get(p_id, &addr); +@@ -293,8 +319,13 @@ void xran_add_eth_hdr_vlan(struct rte_ether_addr *dst, uint16_t ethertype, struc + PANIC_ON(h == NULL, "mbuf prepend of ether_hdr failed"); + + /* Fill in the ethernet header. */ ++#if (RTE_VER_YEAR >= 21) ++ rte_eth_macaddr_get(mb->port, &h->src_addr); /* set source addr */ ++ h->dst_addr = *dst; /* set dst addr */ ++#else + rte_eth_macaddr_get(mb->port, &h->s_addr); /* set source addr */ + h->d_addr = *dst; /* set dst addr */ ++#endif + h->ether_type = rte_cpu_to_be_16(ethertype); /* ethertype too */ + #if 0 + struct rte_ether_addr *s = &h->s_addr; diff --git a/fhi_lib/lib/src/xran_bfp_ref.cpp b/fhi_lib/lib/src/xran_bfp_ref.cpp index e6d3067..8e0abee 100644 --- a/fhi_lib/lib/src/xran_bfp_ref.cpp @@ -565,7 +663,7 @@ index 789c6fd..a768efb 100644 #include #include diff --git a/fhi_lib/lib/src/xran_delay_measurement.c b/fhi_lib/lib/src/xran_delay_measurement.c -index 4c943c8..d9e7983 100644 +index 4c943c8..7db51a8 100644 --- a/fhi_lib/lib/src/xran_delay_measurement.c +++ b/fhi_lib/lib/src/xran_delay_measurement.c @@ -23,7 +23,10 @@ @@ -579,6 +677,155 @@ index 4c943c8..d9e7983 100644 #include #include #include +@@ -572,16 +575,28 @@ int xran_generate_delay_meas(uint16_t port_id, void* handle, uint8_t actionType, + PANIC_ON(h == NULL, "mbuf prepend of ether_hdr failed"); + + /* Fill in the ethernet header. */ ++#if (RTE_VER_YEAR >= 21) ++ rte_eth_macaddr_get(port_id, &h->src_addr); /* set source addr */ ++#else + rte_eth_macaddr_get(port_id, &h->s_addr); /* set source addr */ ++#endif + + if (p_xran_dev_ctx->fh_init.io_cfg.id) + { + // rte_ether_addr_copy( (struct rte_ether_addr *)p_xran_dev_ctx->fh_init.p_o_du_addr[port_id],&h->d_addr); ++#if (RTE_VER_YEAR >= 21) ++ h->dst_addr = ctx->entities[port_id][ID_O_DU]; /* set dst addr */ ++#else + h->d_addr = ctx->entities[port_id][ID_O_DU]; /* set dst addr */ ++#endif + } + else + { ++#if (RTE_VER_YEAR >= 21) ++ h->dst_addr = ctx->entities[port_id][ID_O_RU]; /* set dst addr */ ++#else + h->d_addr = ctx->entities[port_id][ID_O_RU]; /* set dst addr */ ++#endif + // rte_ether_addr_copy( (struct rte_ether_addr *)p_xran_dev_ctx->fh_init.p_o_ru_addr[port_id],&h->d_addr); + } + +@@ -752,7 +767,11 @@ int xran_generate_delay_meas(uint16_t port_id, void* handle, uint8_t actionType, + int8_t *pa = &p_xran_dev_ctx->fh_init.p_o_du_addr[0]; + printf("DST_MAC: %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8"\n", pa[0],pa[1],pa[2],pa[3],pa[4],pa[5]); + #endif ++#if (RTE_VER_YEAR >= 21) ++ rte_ether_addr_copy((struct rte_ether_addr *)&p_xran_dev_ctx->fh_init.p_o_du_addr[0], (struct rte_ether_addr *)&h->dst_addr.addr_bytes[0]); ++#else + rte_ether_addr_copy((struct rte_ether_addr *)&p_xran_dev_ctx->fh_init.p_o_du_addr[0], (struct rte_ether_addr *)&h->d_addr.addr_bytes[0]); ++#endif + + } + else +@@ -761,13 +780,25 @@ int xran_generate_delay_meas(uint16_t port_id, void* handle, uint8_t actionType, + int8_t *pb = &p_xran_dev_ctx->fh_init.p_o_ru_addr[0]; + printf("DST_MAC: %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8"\n", pb[0],pb[1],pb[2],pb[3],pb[4],pb[5]); + #endif ++#if (RTE_VER_YEAR >= 21) ++ rte_ether_addr_copy((struct rte_ether_addr *)&p_xran_dev_ctx->fh_init.p_o_ru_addr[0], (struct rte_ether_addr *)&h->dst_addr.addr_bytes[0]); ++#else + rte_ether_addr_copy((struct rte_ether_addr *)&p_xran_dev_ctx->fh_init.p_o_ru_addr[0], (struct rte_ether_addr *)&h->d_addr.addr_bytes[0]); ++#endif + + } + #ifdef XRAN_OWD_DEBUG_PKTS ++#if (RTE_VER_YEAR >= 21) ++ uint8_t *pc = &h->src_addr.addr_bytes[0]; ++#else + uint8_t *pc = &h->s_addr.addr_bytes[0]; ++#endif + printf(" Src MAC from packet: %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8"\n", pc[0],pc[1],pc[2],pc[3],pc[4],pc[5]); ++#if (RTE_VER_YEAR >= 21) ++ uint8_t *pd = &h->dst_addr.addr_bytes[0]; ++#else + uint8_t *pd = &h->d_addr.addr_bytes[0]; ++#endif + printf(" Dst MAC from packet: %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8"\n", pd[0],pd[1],pd[2],pd[3],pd[4],pd[5]); + #endif + // Copy dest address from above +@@ -862,9 +893,15 @@ int xran_process_delmeas_request(struct rte_mbuf *pkt, void* handle, struct xran + // 11) Fill the ethernet header properly by swapping src and dest addressed from the copied frame + eth_hdr = rte_pktmbuf_mtod(pkt1, struct rte_ether_hdr *); + /* Swap dest and src mac addresses. */ ++#if (RTE_VER_YEAR >= 21) ++ rte_ether_addr_copy(ð_hdr->dst_addr, &addr); ++ rte_ether_addr_copy(ð_hdr->src_addr, ð_hdr->dst_addr); ++ rte_ether_addr_copy(&addr, ð_hdr->src_addr); ++#else + rte_ether_addr_copy(ð_hdr->d_addr, &addr); + rte_ether_addr_copy(ð_hdr->s_addr, ð_hdr->d_addr); + rte_ether_addr_copy(&addr, ð_hdr->s_addr); ++#endif + // Still need to check ol_flags state and update if necessary + // Compute the delay td12 and save + // Still need to define the DB to save the info and run averages +@@ -872,9 +909,17 @@ int xran_process_delmeas_request(struct rte_mbuf *pkt, void* handle, struct xran + // 12) Send the response right away + #ifdef XRAN_OWD_DEBUG_PKTS + struct rte_ether_hdr *h = (struct rte_ether_hdr *)rte_pktmbuf_mtod(pkt1, struct rte_ether_hdr*); ++#if (RTE_VER_YEAR >= 21) ++ uint8_t *pc = &h->src_addr.addr_bytes[0]; ++#else + uint8_t *pc = &h->s_addr.addr_bytes[0]; ++#endif + printf(" Src MAC from packet: %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8"\n", pc[0],pc[1],pc[2],pc[3],pc[4],pc[5]); ++#if (RTE_VER_YEAR >= 21) ++ uint8_t *pd = &h->dst_addr.addr_bytes[0]; ++#else + uint8_t *pd = &h->d_addr.addr_bytes[0]; ++#endif + printf(" Dst MAC from packet: %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8"\n", pd[0],pd[1],pd[2],pd[3],pd[4],pd[5]); + // printf("EtherType: %04"PRIx16" \n",&h->ether_type); + #endif +@@ -1100,9 +1145,15 @@ int xran_process_delmeas_rem_request(struct rte_mbuf *pkt, void* handle, struct + // 9) Fill the ethernet header properly by swapping src and dest addressed from the copied frame + eth_hdr = rte_pktmbuf_mtod(pkt1, struct rte_ether_hdr *); + /* Swap dest and src mac addresses. */ ++#if (RTE_VER_YEAR >= 21) ++ rte_ether_addr_copy(ð_hdr->dst_addr, &addr); ++ rte_ether_addr_copy(ð_hdr->src_addr, ð_hdr->dst_addr); ++ rte_ether_addr_copy(&addr, ð_hdr->src_addr); ++#else + rte_ether_addr_copy(ð_hdr->d_addr, &addr); + rte_ether_addr_copy(ð_hdr->s_addr, ð_hdr->d_addr); + rte_ether_addr_copy(&addr, ð_hdr->s_addr); ++#endif + // 10) Send the response right away + pdm = (struct xran_ecpri_del_meas_pkt*)rte_pktmbuf_mtod_offset(pkt1, struct xran_ecpri_del_meas_pkt *, sizeof(struct rte_ether_hdr) ); + pdm->cmnhdr.bits.ecpri_payl_size = 10 + powdc->owdm_PlLength; // 10 correponds to the xran_ecpri_delay_meas_pl minus the dummy_bytes field which now allows the user to select the length for this field to be sent +@@ -1177,9 +1228,15 @@ int xran_process_delmeas_rem_request_w_fup(struct rte_mbuf* pkt, void* handle, s + // 7) Fill the ethernet header properly by swapping src and dest addressed from the copied frame + eth_hdr = rte_pktmbuf_mtod(pkt1, struct rte_ether_hdr *); + /* Swap dest and src mac addresses. */ ++#if (RTE_VER_YEAR >= 21) ++ rte_ether_addr_copy(ð_hdr->dst_addr, &addr); ++ rte_ether_addr_copy(ð_hdr->src_addr, ð_hdr->dst_addr); ++ rte_ether_addr_copy(&addr, ð_hdr->src_addr); ++#else + rte_ether_addr_copy(ð_hdr->d_addr, &addr); + rte_ether_addr_copy(ð_hdr->s_addr, ð_hdr->d_addr); + rte_ether_addr_copy(&addr, ð_hdr->s_addr); ++#endif + // 8) Duplicate packet to be used for the follow up packet + pkt2 = rte_pktmbuf_copy(pkt1, _eth_mbuf_pool, 0, UINT32_MAX); + // 9) Record the current timestamp when the request with follow up is being sent +@@ -1283,9 +1340,15 @@ int xran_process_delmeas_follow_up(struct rte_mbuf *pkt, void* handle, struct xr + // 9) Fill the ethernet header properly by swapping src and dest addressed from the copied frame + eth_hdr = rte_pktmbuf_mtod(pkt1, struct rte_ether_hdr *); + /* Swap dest and src mac addresses. */ ++#if (RTE_VER_YEAR >= 21) ++ rte_ether_addr_copy(ð_hdr->dst_addr, &addr); ++ rte_ether_addr_copy(ð_hdr->src_addr, ð_hdr->dst_addr); ++ rte_ether_addr_copy(&addr, ð_hdr->src_addr); ++#else + rte_ether_addr_copy(ð_hdr->d_addr, &addr); + rte_ether_addr_copy(ð_hdr->s_addr, ð_hdr->d_addr); + rte_ether_addr_copy(&addr, ð_hdr->s_addr); ++#endif + pdm = (struct xran_ecpri_del_meas_pkt*)rte_pktmbuf_mtod_offset(pkt1, struct xran_ecpri_del_meas_pkt *, sizeof(struct rte_ether_hdr) ); + pdm->cmnhdr.bits.ecpri_payl_size = 10 + powdc->owdm_PlLength; // 10 correponds to the xran_ecpri_delay_meas_pl minus the dummy_bytes field which now allows the user to select the length for this field to be sent + pdm->cmnhdr.bits.ecpri_payl_size = rte_cpu_to_be_16(pdm->cmnhdr.bits.ecpri_payl_size); diff --git a/fhi_lib/lib/src/xran_dev.c b/fhi_lib/lib/src/xran_dev.c index 4acade1..c939edc 100644 --- a/fhi_lib/lib/src/xran_dev.c @@ -1377,7 +1624,7 @@ index 72249bc..6b30084 100644 #include diff --git a/fhi_lib/lib/src/xran_tx_proc.c b/fhi_lib/lib/src/xran_tx_proc.c -index 45a17a8..28c5568 100644 +index 45a17a8..85ce6fa 100644 --- a/fhi_lib/lib/src/xran_tx_proc.c +++ b/fhi_lib/lib/src/xran_tx_proc.c @@ -35,7 +35,11 @@ @@ -1392,6 +1639,58 @@ index 45a17a8..28c5568 100644 #include #include +@@ -1514,7 +1518,11 @@ xran_process_tx_sym_cp_on_opt(void* pHandle, uint8_t ctx_id, uint32_t tti, int32 + mb_oran_hdr_ext->buf_addr = ext_buff; + mb_oran_hdr_ext->buf_iova = ((struct rte_mempool_objhdr*)RTE_PTR_SUB(mb_base, rte_mempool_objhdr_size))->iova + RTE_PTR_DIFF(ext_buff, mb_base); + mb_oran_hdr_ext->buf_len = ext_buff_len; ++#if (RTE_VER_YEAR >= 21) ++ mb_oran_hdr_ext->ol_flags |= RTE_MBUF_F_EXTERNAL; ++#else + mb_oran_hdr_ext->ol_flags |= EXT_ATTACHED_MBUF; ++#endif + mb_oran_hdr_ext->shinfo = p_share_data; + mb_oran_hdr_ext->data_off = (uint16_t)RTE_MIN((uint16_t)RTE_PKTMBUF_HEADROOM, (uint16_t)mb_oran_hdr_ext->buf_len) - rte_ether_hdr_size; + mb_oran_hdr_ext->data_len = (uint16_t)(mb_oran_hdr_ext->data_len + rte_ether_hdr_size); +@@ -1532,8 +1540,13 @@ xran_process_tx_sym_cp_on_opt(void* pHandle, uint8_t ctx_id, uint32_t tti, int32 + + /* Fill in the ethernet header. */ + #ifndef TRANSMIT_BURST ++#if (RTE_VER_YEAR >= 21) ++ rte_eth_macaddr_get(mb_oran_hdr_ext->port, &((struct rte_ether_hdr*)pStart)->src_addr); /* set source addr */ ++ ((struct rte_ether_hdr*)pStart)->dst_addr = eth_ctx->entities[vf_id][ID_O_RU]; /* set dst addr */ ++#else + rte_eth_macaddr_get(mb_oran_hdr_ext->port, &((struct rte_ether_hdr*)pStart)->s_addr); /* set source addr */ + ((struct rte_ether_hdr*)pStart)->d_addr = eth_ctx->entities[vf_id][ID_O_RU]; /* set dst addr */ ++#endif + ((struct rte_ether_hdr*)pStart)->ether_type = ETHER_TYPE_ECPRI_BE; /* ethertype */ + #endif + nPktSize = sizeof(struct rte_ether_hdr) +@@ -1878,7 +1891,11 @@ xran_process_tx_srs_cp_on(void* pHandle, uint8_t ctx_id, uint32_t tti, int32_t s + mb_oran_hdr_ext->buf_addr = ext_buff; + mb_oran_hdr_ext->buf_iova = ((struct rte_mempool_objhdr*)RTE_PTR_SUB(mb_base, rte_mempool_objhdr_size))->iova + RTE_PTR_DIFF(ext_buff, mb_base); + mb_oran_hdr_ext->buf_len = ext_buff_len; ++#if (RTE_VER_YEAR >= 21) ++ mb_oran_hdr_ext->ol_flags |= RTE_MBUF_F_EXTERNAL; ++#else + mb_oran_hdr_ext->ol_flags |= EXT_ATTACHED_MBUF; ++#endif + mb_oran_hdr_ext->shinfo = p_share_data; + mb_oran_hdr_ext->data_off = (uint16_t)RTE_MIN((uint16_t)RTE_PKTMBUF_HEADROOM, (uint16_t)mb_oran_hdr_ext->buf_len) - rte_ether_hdr_size; + mb_oran_hdr_ext->data_len = (uint16_t)(mb_oran_hdr_ext->data_len + rte_ether_hdr_size); +@@ -1887,8 +1904,13 @@ xran_process_tx_srs_cp_on(void* pHandle, uint8_t ctx_id, uint32_t tti, int32_t s + pStart = (char*)((char*)mb_oran_hdr_ext->buf_addr + mb_oran_hdr_ext->data_off); + + /* Fill in the ethernet header. */ ++#if (RTE_VER_YEAR >= 21) ++ rte_eth_macaddr_get(mb_oran_hdr_ext->port, &((struct rte_ether_hdr*)pStart)->src_addr); /* set source addr */ ++ ((struct rte_ether_hdr*)pStart)->dst_addr = eth_ctx->entities[vf_id][ID_O_RU]; /* set dst addr */ ++#else + rte_eth_macaddr_get(mb_oran_hdr_ext->port, &((struct rte_ether_hdr*)pStart)->s_addr); /* set source addr */ + ((struct rte_ether_hdr*)pStart)->d_addr = eth_ctx->entities[vf_id][ID_O_RU]; /* set dst addr */ ++#endif + ((struct rte_ether_hdr*)pStart)->ether_type = ETHER_TYPE_ECPRI_BE; /* ethertype */ + + nPktSize = sizeof(struct rte_ether_hdr) diff --git a/fhi_lib/lib/src/xran_up_api.c b/fhi_lib/lib/src/xran_up_api.c index fe22a1f..3fd369b 100644 --- a/fhi_lib/lib/src/xran_up_api.c From 486726233de97a1ee5de53bb9bd6da1802d9b1ee Mon Sep 17 00:00:00 2001 From: Romain Beurdouche Date: Fri, 27 Jun 2025 16:18:27 +0000 Subject: [PATCH 197/964] feat(oran_fhlib_5g): Enable to include a BBDEV device while initializing EAL In order to be usable in parallel of FHI 7.2, BBDEV devices should be included in the EAL initialization that is prformed by xran. This commit adds a way of adding the BBDEV device from OAI. Also fixes an issue with pkgconfig in xran. --- .../F/oaioran_F.patch | 66 +++++++++++++++---- radio/fhi_72/CMakeLists.txt | 2 +- radio/fhi_72/oran-config.c | 41 ++++++++++++ 3 files changed, 95 insertions(+), 14 deletions(-) diff --git a/cmake_targets/tools/oran_fhi_integration_patches/F/oaioran_F.patch b/cmake_targets/tools/oran_fhi_integration_patches/F/oaioran_F.patch index 8157172d85..bec423b95e 100644 --- a/cmake_targets/tools/oran_fhi_integration_patches/F/oaioran_F.patch +++ b/cmake_targets/tools/oran_fhi_integration_patches/F/oaioran_F.patch @@ -1,5 +1,5 @@ diff --git a/fhi_lib/app/src/common.h b/fhi_lib/app/src/common.h -index ac5f471..9ebbcab 100644 +index ac5f471..5efcce3 100644 --- a/fhi_lib/app/src/common.h +++ b/fhi_lib/app/src/common.h @@ -28,7 +28,7 @@ @@ -7,12 +7,12 @@ index ac5f471..9ebbcab 100644 #include -#define VERSIONX "oran_f_release_v1.0" -+#define VERSIONX "oran_f_release_v1.3" ++#define VERSIONX "oran_f_release_v1.4" #define APP_O_DU 0 #define APP_O_RU 1 diff --git a/fhi_lib/lib/Makefile b/fhi_lib/lib/Makefile -index eccc4ae..b1b8f4b 100644 +index eccc4ae..a97fdc6 100644 --- a/fhi_lib/lib/Makefile +++ b/fhi_lib/lib/Makefile @@ -23,24 +23,46 @@ MYCUSTOMSPACE1='------------------------------------------------------------' @@ -83,9 +83,9 @@ index eccc4ae..b1b8f4b 100644 RTE_TARGET ?= x86_64-native-linux-icc -RTE_INC := $(shell PKG_CONFIG_PATH=/usr/lib64/pkgconfig:$(RTE_SDK)/build/meson-uninstalled pkgconf --cflags-only-I libdpdk) +ifeq ($(TARGET), x86) -+RTE_INC := $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH):/usr/lib64/pkgconfig:$(RTE_SDK)/build/meson-uninstalled pkgconf --cflags-only-I libdpdk) ++RTE_INC := $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH):/usr/lib64/pkgconfig:$(RTE_SDK)/build/meson-uninstalled pkg-config --cflags-only-I libdpdk) +else ifeq ($(TARGET), armv8) -+RTE_INC := $(pkgconf --cflags-only-I libdpdk) ++RTE_INC := $(shell pkg-config --cflags-only-I libdpdk) +endif API_DIR := $(PROJECT_DIR)/api @@ -147,6 +147,15 @@ index eccc4ae..b1b8f4b 100644 ifeq ($(WIRELESS_SDK_TOOLCHAIN),icc) CPP_FLAGS += -fp-model fast=2 -no-prec-div -no-prec-sqrt -fast-transcendentals -restrict +@@ -150,7 +187,7 @@ CPP_FLAGS += -fp-model fast -march=icelake-server -mintrinsic-promote -Wno-unus + endif + + +-INC := -I$(API_DIR) -I$(ETH_DIR) -I$(SRC_DIR) -I$(RTE_INC) ++INC := -I$(API_DIR) -I$(ETH_DIR) -I$(SRC_DIR) $(RTE_INC) + DEF := + ifeq ($(MLOG),1) + INC += -I$(MLOG_DIR)/source @@ -186,8 +223,13 @@ CPP_SNC_OBJTARGETS := $(addprefix $(PROJECT_OBJ_DIR)/,$(CPP_OBJS_SNC)) AS_OBJTARGETS := $(addprefix $(PROJECT_OBJ_DIR)/,$(AS_OBJS)) @@ -164,7 +173,7 @@ index eccc4ae..b1b8f4b 100644 CPP_FLAGS_FULL := $(CPP_FLAGS) $(CPP_COMP) $(INC) $(DEF) CPP_FLAGS_FULL_SNC := $(CPP_FLAGS) $(CPP_COMP_SNC) $(INC) $(DEF) diff --git a/fhi_lib/lib/api/xran_fh_o_du.h b/fhi_lib/lib/api/xran_fh_o_du.h -index bacf597..8bd7c66 100644 +index bacf597..1dd6d66 100644 --- a/fhi_lib/lib/api/xran_fh_o_du.h +++ b/fhi_lib/lib/api/xran_fh_o_du.h @@ -141,7 +141,7 @@ extern "C" { @@ -176,7 +185,15 @@ index bacf597..8bd7c66 100644 #define XRAN_MAX_SET_BFWS (64) /**< Assumed 64Ant, BFP 9bit with 9K jumbo frame */ #define XRAN_MAX_PKT_BURST (448+4) /**< 4x14x8 symbols per ms */ -@@ -1193,6 +1193,31 @@ int32_t xran_reg_physide_cb_by_dev_id(void *pHandle, xran_fh_tti_callback_fn Cb, +@@ -419,6 +419,7 @@ struct xran_io_cfg { + uint16_t num_rxq; /**< number of RX queues per VF */ + char *dpdk_dev[XRAN_VF_MAX]; /**< VFs devices */ + char *bbdev_dev[1]; /**< BBDev dev name */ ++ char *bbdev_vfio_vf_token[1]; /**< BBDev dev token */ + int32_t bbdev_mode; /**< DPDK for BBDev */ + uint32_t dpdkIoVaMode; /**< IOVA Mode */ + uint32_t dpdkMemorySize; /**< DPDK max memory allocation */ +@@ -1193,6 +1194,31 @@ int32_t xran_reg_physide_cb_by_dev_id(void *pHandle, xran_fh_tti_callback_fn Cb, */ int32_t xran_get_slot_idx (uint32_t PortId, uint32_t *nFrameIdx, uint32_t *nSubframeIdx, uint32_t *nSlotIdx, uint64_t *nSecond); @@ -259,7 +276,7 @@ index 46e0e1d..409ef4b 100644 int xran_prepare_iq_symbol_portion( struct rte_mbuf *mbuf, diff --git a/fhi_lib/lib/ethernet/ethdi.c b/fhi_lib/lib/ethernet/ethdi.c -index f5b2fd6..2eccc6e 100644 +index f5b2fd6..8fb0ec2 100644 --- a/fhi_lib/lib/ethernet/ethdi.c +++ b/fhi_lib/lib/ethernet/ethdi.c @@ -37,7 +37,10 @@ @@ -299,8 +316,11 @@ index f5b2fd6..2eccc6e 100644 all_ports_up = 0; break; } -@@ -325,8 +338,8 @@ xran_ethdi_init_dpdk_io(char *name, const struct xran_io_cfg *io_cfg, +@@ -323,10 +336,11 @@ xran_ethdi_init_dpdk_io(char *name, const struct xran_io_cfg *io_cfg, + uint64_t nWorkerCore = 1; + uint32_t coreNum = sysconf(_SC_NPROCESSORS_CONF); char bbdev_wdev[32] = ""; ++ char bbdev_vfio_vf_token[64] = ""; char bbdev_vdev[32] = ""; char iova_mode[32] = "--iova-mode=pa"; - char socket_mem[32] = "--socket-mem=8192"; @@ -310,16 +330,36 @@ index f5b2fd6..2eccc6e 100644 char ring_name[32] = ""; int32_t xran_port = -1; queueid_t qi = 0; -@@ -336,7 +349,7 @@ xran_ethdi_init_dpdk_io(char *name, const struct xran_io_cfg *io_cfg, +@@ -336,8 +350,8 @@ xran_ethdi_init_dpdk_io(char *name, const struct xran_io_cfg *io_cfg, cpu = sched_getcpu(); node = numa_node_of_cpu(cpu); - char *argv[] = { name, core_mask, "-n2", iova_mode, socket_mem, socket_limit, "--proc-type=auto", +- "--file-prefix", name, "-a0000:00:00.0", bbdev_wdev, bbdev_vdev}; + char *argv[] = { name, core_mask, "-n2", iova_mode, socket_mem, socket_limit, "--proc-type=auto", "--no-telemetry", - "--file-prefix", name, "-a0000:00:00.0", bbdev_wdev, bbdev_vdev}; ++ "--file-prefix", name, "-a0000:00:00.0", bbdev_wdev, bbdev_vdev, bbdev_vfio_vf_token}; if (io_cfg == NULL) -@@ -481,11 +494,13 @@ xran_ethdi_init_dpdk_io(char *name, const struct xran_io_cfg *io_cfg, + return 0; +@@ -347,11 +361,17 @@ xran_ethdi_init_dpdk_io(char *name, const struct xran_io_cfg *io_cfg, + // hw-accelerated bbdev + printf("hw-accelerated bbdev %s\n", io_cfg->bbdev_dev[0]); + snprintf(bbdev_wdev, RTE_DIM(bbdev_wdev), "-a%s", io_cfg->bbdev_dev[0]); ++ if (io_cfg->bbdev_vfio_vf_token[0] != NULL) { ++ snprintf(bbdev_vfio_vf_token, RTE_DIM(bbdev_vfio_vf_token), "--vfio-vf-token=%s", io_cfg->bbdev_vfio_vf_token[0]); ++ } + } else if (io_cfg->bbdev_mode == XRAN_BBDEV_MODE_HW_OFF){ + snprintf(bbdev_wdev, RTE_DIM(bbdev_wdev), "%s", "--vdev=baseband_turbo_sw"); + } else if (io_cfg->bbdev_mode == XRAN_BBDEV_MODE_HW_SW){ + printf("software and hw-accelerated bbdev %s\n", io_cfg->bbdev_dev[0]); + snprintf(bbdev_wdev, RTE_DIM(bbdev_wdev), "-a%s", io_cfg->bbdev_dev[0]); ++ if (io_cfg->bbdev_vfio_vf_token[0] != NULL) { ++ snprintf(bbdev_vfio_vf_token, RTE_DIM(bbdev_vfio_vf_token), "--vfio-vf-token=%s", io_cfg->bbdev_vfio_vf_token[0]); ++ } + snprintf(bbdev_vdev, RTE_DIM(bbdev_vdev), "%s", "--vdev=baseband_turbo_sw"); + } else { + rte_panic("Cannot init DPDK incorrect [bbdev_mode %d]\n", io_cfg->bbdev_mode); +@@ -481,11 +501,13 @@ xran_ethdi_init_dpdk_io(char *name, const struct xran_io_cfg *io_cfg, ctx->tx_ring[i] = rte_ring_create(ring_name, NUM_MBUFS_RING_TRX, rte_lcore_to_socket_id(*lcore_id), RING_F_SC_DEQ); PANIC_ON(ctx->tx_ring[i] == NULL, "failed to allocate rx ring"); @@ -333,7 +373,7 @@ index f5b2fd6..2eccc6e 100644 } } } else { -@@ -555,7 +570,7 @@ xran_ethdi_init_dpdk_io(char *name, const struct xran_io_cfg *io_cfg, +@@ -555,7 +577,7 @@ xran_ethdi_init_dpdk_io(char *name, const struct xran_io_cfg *io_cfg, ctx->up_dl_pkt_gen_ring[i] = rte_ring_create(ring_name, NUM_MBUFS_RING, rte_lcore_to_socket_id(*lcore_id), /*RING_F_SC_DEQ*/0); PANIC_ON(ctx->up_dl_pkt_gen_ring[i] == NULL, "failed to allocate dl gen ring"); diff --git a/radio/fhi_72/CMakeLists.txt b/radio/fhi_72/CMakeLists.txt index a874d4cc01..a49f38adee 100644 --- a/radio/fhi_72/CMakeLists.txt +++ b/radio/fhi_72/CMakeLists.txt @@ -17,7 +17,7 @@ add_library(oran_fhlib_5g MODULE ) set(E_VERSION 5.1.5) -set(F_VERSION 6.1.3) +set(F_VERSION 6.1.4) find_package(xran REQUIRED) if(xran_VERSION VERSION_EQUAL E_VERSION) diff --git a/radio/fhi_72/oran-config.c b/radio/fhi_72/oran-config.c index 891634dbfc..ed8f37f857 100644 --- a/radio/fhi_72/oran-config.c +++ b/radio/fhi_72/oran-config.c @@ -461,6 +461,11 @@ static uint64_t get_u64_mask(const paramdef_t *pd) return mask; } +#ifdef F_RELEASE +char bbdev_dev[32] = ""; +char bbdev_vfio_vf_token[64] = ""; +#endif + static bool set_fh_io_cfg(struct xran_io_cfg *io_cfg, const paramdef_t *fhip, int nump, const int num_rus) { DevAssert(fhip != NULL); @@ -474,8 +479,44 @@ static bool set_fh_io_cfg(struct xran_io_cfg *io_cfg, const paramdef_t *fhip, in for (int i = 0; i < num_dev; ++i) { io_cfg->dpdk_dev[i] = strdup(gpd(fhip, nump, ORAN_CONFIG_DPDK_DEVICES)->strlistptr[i]); // VFs devices } +#ifdef F_RELEASE + io_cfg->bbdev_dev[0] = NULL; // BBDev dev name; max devices = 1 + io_cfg->bbdev_vfio_vf_token[0] = NULL; // BBDev dev token; max devices = 1 + char *shlibversion = NULL; // version of the LDPC coding library + paramdef_t LoaderParams_shlibversion[] = {{"shlibversion", NULL, 0, .strptr = &shlibversion, .defstrval = NULL, TYPE_STRING, 0, NULL}}; + config_get(config_get_if(), LoaderParams_shlibversion, sizeofArray(LoaderParams_shlibversion), "loader.ldpc"); + if (shlibversion != NULL && strncmp(shlibversion, "_t2", 3) == 0) { + uint32_t eal_init_bbdev = 0; // If not 0 then include the BBDEV device in the EAL init for FHI + char *dpdk_dev = NULL; // PCI address of the card + char *vfio_vf_token = NULL; // vfio token for the bbdev card + paramdef_t LoaderParams[] = { + {"eal_init_bbdev", NULL, 0, .uptr = &eal_init_bbdev, .defuintval = 0, TYPE_UINT, 0, NULL}, + {"dpdk_dev", NULL, 0, .strptr = &dpdk_dev, .defstrval = NULL, TYPE_STRING, 0, NULL}, + {"vfio_vf_token", NULL, 0, .strptr = &vfio_vf_token, .defstrval = NULL, TYPE_STRING, 0, NULL} + }; + config_get(config_get_if(), LoaderParams, sizeofArray(LoaderParams), "nrLDPC_coding_t2"); + + if (eal_init_bbdev != 0) { + AssertFatal(dpdk_dev!=NULL, "nrLDPC_coding_t2.dpdk_dev was not provided"); + snprintf(&bbdev_dev[0], sizeof(bbdev_dev), "%s", dpdk_dev); + io_cfg->bbdev_dev[0] = &bbdev_dev[0]; // BBDev dev name; max devices = 1 + if(vfio_vf_token != NULL) { + snprintf(&bbdev_vfio_vf_token[0], sizeof(bbdev_vfio_vf_token), "%s", vfio_vf_token); + io_cfg->bbdev_vfio_vf_token[0] = &bbdev_vfio_vf_token[0]; // BBDev dev token; max devices = 1 + } else { + io_cfg->bbdev_vfio_vf_token[0] = NULL; // BBDev dev token; max devices = 1 + } + io_cfg->bbdev_mode = XRAN_BBDEV_MODE_HW_ON; // DPDK for BBDev + } else { + io_cfg->bbdev_mode = XRAN_BBDEV_NOT_USED; // DPDK for BBDev + } + } else { + io_cfg->bbdev_mode = XRAN_BBDEV_NOT_USED; // DPDK for BBDev + } +#elif defined(E_RELEASE) io_cfg->bbdev_dev[0] = NULL; // BBDev dev name; max devices = 1 io_cfg->bbdev_mode = XRAN_BBDEV_NOT_USED; // DPDK for BBDev +#endif int dpdk_iova_mode_idx = config_paramidx_fromname((paramdef_t *)fhip, nump, ORAN_CONFIG_DPDK_IOVA_MODE); AssertFatal(dpdk_iova_mode_idx >= 0,"Index for dpdk_iova_mode config option not found!"); io_cfg->dpdkIoVaMode = config_get_processedint(config_get_if(), (paramdef_t *)&fhip[dpdk_iova_mode_idx]); // IOVA mode From 8e33727c370bd7cd01561ffbb8d6b408e9495899 Mon Sep 17 00:00:00 2001 From: Romain Beurdouche Date: Mon, 30 Jun 2025 14:01:08 +0000 Subject: [PATCH 198/964] feat(oran_fhlib_5g): pkgconfig fix for E release E release had the same issue of not using pkgconfig properly as F release. This issue was fixed in F release when enabling its compatibility with DPDK 21+. This commit brings this fix to E release. --- .../E/oaioran_E.patch | 17 ++++++++++------- radio/fhi_72/CMakeLists.txt | 2 +- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/cmake_targets/tools/oran_fhi_integration_patches/E/oaioran_E.patch b/cmake_targets/tools/oran_fhi_integration_patches/E/oaioran_E.patch index baa5378673..8d0610892a 100644 --- a/cmake_targets/tools/oran_fhi_integration_patches/E/oaioran_E.patch +++ b/cmake_targets/tools/oran_fhi_integration_patches/E/oaioran_E.patch @@ -1,5 +1,5 @@ diff --git a/fhi_lib/app/src/common.h b/fhi_lib/app/src/common.h -index 7508117..ce17ebd 100644 +index 7508117..318508b 100644 --- a/fhi_lib/app/src/common.h +++ b/fhi_lib/app/src/common.h @@ -28,7 +28,7 @@ @@ -7,12 +7,12 @@ index 7508117..ce17ebd 100644 #include -#define VERSIONX "oran_e_maintenance_release_v1.0" -+#define VERSIONX "oran_e_maintenance_release_v1.5" ++#define VERSIONX "oran_e_maintenance_release_v1.6" #define APP_O_DU 0 #define APP_O_RU 1 diff --git a/fhi_lib/lib/Makefile b/fhi_lib/lib/Makefile -index de141bf..fa2923f 100644 +index de141bf..c2a448d 100644 --- a/fhi_lib/lib/Makefile +++ b/fhi_lib/lib/Makefile @@ -23,12 +23,25 @@ MYCUSTOMSPACE1='------------------------------------------------------------' @@ -50,9 +50,9 @@ index de141bf..fa2923f 100644 -RTE_INC := $(shell PKG_CONFIG_PATH=/usr/lib64/pkgconfig:$(RTE_SDK)/build/meson-uninstalled pkgconf --cflags-only-I libdpdk) +ifeq ($(TARGET), x86) -+RTE_INC := $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH):/usr/lib64/pkgconfig:$(RTE_SDK)/build/meson-uninstalled pkgconf --cflags-only-I libdpdk) ++RTE_INC := $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH):/usr/lib64/pkgconfig:$(RTE_SDK)/build/meson-uninstalled pkg-config --cflags-only-I libdpdk) +else ifeq ($(TARGET), armv8) -+RTE_INC := $(pkgconf --cflags-only-I libdpdk) ++RTE_INC := $(shell pkg-config --cflags-only-I libdpdk) +endif API_DIR := $(PROJECT_DIR)/api SRC_DIR := $(PROJECT_DIR)/src @@ -85,7 +85,7 @@ index de141bf..fa2923f 100644 CC_FLAGS += -std=gnu11 -Wall -Wno-deprecated-declarations \ -fdata-sections \ -@@ -112,12 +132,21 @@ CC_FLAGS += -std=gnu11 -Wall -Wno-deprecated-declarations \ +@@ -112,14 +132,23 @@ CC_FLAGS += -std=gnu11 -Wall -Wno-deprecated-declarations \ -fPIC \ -Wall \ -Wimplicit-function-declaration \ @@ -110,8 +110,11 @@ index de141bf..fa2923f 100644 + -Werror -Wno-unused-variable -std=c++14 +endif - INC := -I$(API_DIR) -I$(ETH_DIR) -I$(SRC_DIR) -I$(RTE_INC) +-INC := -I$(API_DIR) -I$(ETH_DIR) -I$(SRC_DIR) -I$(RTE_INC) ++INC := -I$(API_DIR) -I$(ETH_DIR) -I$(SRC_DIR) $(RTE_INC) DEF := + ifeq ($(MLOG),1) + INC += -I$(MLOG_DIR)/source @@ -150,8 +179,13 @@ CPP_SNC_OBJTARGETS := $(addprefix $(PROJECT_OBJ_DIR)/,$(CPP_OBJS_SNC)) AS_OBJTARGETS := $(addprefix $(PROJECT_OBJ_DIR)/,$(AS_OBJS)) diff --git a/radio/fhi_72/CMakeLists.txt b/radio/fhi_72/CMakeLists.txt index a49f38adee..3b0f16d2a4 100644 --- a/radio/fhi_72/CMakeLists.txt +++ b/radio/fhi_72/CMakeLists.txt @@ -16,7 +16,7 @@ add_library(oran_fhlib_5g MODULE oran-init.c ) -set(E_VERSION 5.1.5) +set(E_VERSION 5.1.6) set(F_VERSION 6.1.4) find_package(xran REQUIRED) From abe25a52b3a3397276f5d9de755a9c8752f27b77 Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Fri, 9 May 2025 01:40:27 -0400 Subject: [PATCH 199/964] Fix alignment of LLR buffer in UE --- openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c index d266d443e9..ebe4c946be 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c @@ -693,7 +693,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, return -1; } - int16_t layer_llr[dlsch[0].Nl][rx_llr_layer_size]; + __attribute__((aligned(32))) int16_t layer_llr[dlsch[0].Nl][rx_llr_layer_size]; for(int i = startSymbIdx; i < startSymbIdx + nbSymb; i++) { /* Calculate LLR's for each symbol */ start_meas_nr_ue_phy(ue, DLSCH_LLR_STATS); From 7feaea00c27b46f46e20786be6a1e243cb3cffc5 Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Thu, 10 Jul 2025 20:40:46 -0400 Subject: [PATCH 200/964] Fix counting error bits in nr_dlsim Recently f buffer was changed to hold packed bits and the correspoinding change in dlsim was not done so the number of error bits before decoding was incorrectly reported. This commit fixes it. --- openair1/SIMULATION/NR_PHY/dlsim.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index f1fa7885a4..36f69041cc 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -1253,9 +1253,8 @@ printf("%d\n", slot); } for (i = 0; i < available_bits; i++) { - if(((gNB_dlsch->harq_process.f[i] == 0) && (UE_llr[i] <= 0)) || - ((gNB_dlsch->harq_process.f[i] == 1) && (UE_llr[i] >= 0))) - { + const uint8_t current_bit = (gNB_dlsch->harq_process.f[i / 8] & (1 << (i & 7))) >> (i & 7); + if (((current_bit == 0) && (UE_llr[i] <= 0)) || ((current_bit == 1) && (UE_llr[i] >= 0))) { if (errors_scrambling[round] == 0) { LOG_D(PHY,"First bit in error in unscrambling = %d\n",i); } From 6a2997ec9b8c579d9b5dab232cb92117fbefc77d Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Thu, 19 Jun 2025 16:41:02 +0200 Subject: [PATCH 201/964] T hacks: add ant0 utility to dump IQ data as float complex Or as int16. --- common/utils/T/tracer/hacks/Makefile | 12 +- common/utils/T/tracer/hacks/ant0.c | 259 +++++++++++++++++++++++++++ 2 files changed, 269 insertions(+), 2 deletions(-) create mode 100644 common/utils/T/tracer/hacks/ant0.c diff --git a/common/utils/T/tracer/hacks/Makefile b/common/utils/T/tracer/hacks/Makefile index 7157406796..f693094fb6 100644 --- a/common/utils/T/tracer/hacks/Makefile +++ b/common/utils/T/tracer/hacks/Makefile @@ -3,7 +3,7 @@ CFLAGS=-Wall -g -pthread -DT_TRACER -I. -I.. LIBS=-lX11 -lm -lpng -lXft -all: dump_nack_signal time_meas timeplot multi-rru-clean +all: dump_nack_signal time_meas timeplot multi-rru-clean ant0 dump_nack_signal: ../utils.o ../database.o ../configuration.o ../event.o \ dump_nack_signal.o @@ -19,10 +19,18 @@ timplot: timeplot.o multi-rru-clean: ../utils.o ../database.o ../event.o ../configuration.o multi-rru-clean.o $(CC) $(CFLAGS) -o $@ $^ $(LIBS) +ant0: ant0.o ../utils.o ../database.o ../configuration.o ../event.o + $(CC) $(CFLAGS) -o $@ $^ -lm + +#ant0 needs good compilation, conversion to float is heavy +ant0.o: ant0.c + $(CC) $(CFLAGS) -c -o $@ $< -march=native -ffast-math -O3 + .PHONY: all %.o: %.c $(CC) $(CFLAGS) -c -o $@ $< clean: - rm -f *.o core dump_nack_signal time_meas timeplot multi-rru-clean + rm -f *.o core dump_nack_signal time_meas timeplot multi-rru-clean \ + ant0 diff --git a/common/utils/T/tracer/hacks/ant0.c b/common/utils/T/tracer/hacks/ant0.c new file mode 100644 index 0000000000..3de4dac325 --- /dev/null +++ b/common/utils/T/tracer/hacks/ant0.c @@ -0,0 +1,259 @@ +#include +#include +#include +#include +#include +#include "database.h" +//#include "utils.h" +#include "configuration.h" +#include "event.h" + +void usage(void) +{ + fprintf(stderr, +"options:\n" +" -d this option is mandatory\n" +" -o this option is mandatory (use - to dump to stdout)\n" +" -ip connect to given IP address (default %s)\n" +" -p connect to given port (default %d)\n" +" -n save maximum 'max' IQ points (may be a bit more)\n" +" -nosig don't intercept ctrl+c, ctrl+z (it may mess up when piping to another tool)\n" +" -e trace given event (default 'USRP_TX_ANT0')\n" +" -b trace given buffer (default 'data')\n" +" -no-timestamp don't use 'timestamp' to fill missing transmission\n" +" -scale divide 16bits input by given value for float output (default 32768.)\n" +" -s16 output short instead of float\n", + DEFAULT_REMOTE_IP, + DEFAULT_REMOTE_PORT + ); + exit(1); +} + +volatile int run = 1; + +static int socket = -1; + +void force_stop(int x) +{ + fprintf(stderr, "\ngently quit...\n"); + close(socket); + socket = -1; + run = 0; +} + +int main(int n, char **v) +{ + char *database_filename = NULL; + char *output_filename = NULL; + FILE *out; + void *database; + char *ip = DEFAULT_REMOTE_IP; + int port = DEFAULT_REMOTE_PORT; + int *is_on; + int number_of_events; + int i; + char mt; + long max = -1; + long dumped = 0; + int nosig = 0; + char *event_name = "USRP_TX_ANT0"; + char *buffer_name = "data"; + int no_timestamp = 0; + float scale = 32768; + int do_float = 1; + + /* write on a socket fails if the other end is closed and we get SIGPIPE */ + if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) abort(); + + for (i = 1; i < n; i++) { + if (!strcmp(v[i], "-h") || !strcmp(v[i], "--help")) usage(); + if (!strcmp(v[i], "-d")) { if (i > n-2) usage(); database_filename = v[++i]; continue; } + if (!strcmp(v[i], "-o")) { if (i > n-2) usage(); output_filename = v[++i]; continue; } + if (!strcmp(v[i], "-ip")) { if (i > n-2) usage(); ip = v[++i]; continue; } + if (!strcmp(v[i], "-p")) { if (i > n-2) usage(); port = atoi(v[++i]); continue; } + if (!strcmp(v[i], "-n")) { if (i > n-2) usage(); max = atol(v[++i]); continue; } + if (!strcmp(v[i], "-nosig")) { nosig = 1; continue; } + if (!strcmp(v[i], "-e")) { if (i > n-2) usage(); event_name = v[++i]; continue; } + if (!strcmp(v[i], "-b")) { if (i > n-2) usage(); buffer_name = v[++i]; continue; } + if (!strcmp(v[i], "-no-timestamp")) { no_timestamp = 1; continue; } + if (!strcmp(v[i], "-scale")) { if (i > n-2) usage(); scale = atof(v[++i]); continue; } + if (!strcmp(v[i], "-s16")) { do_float = 0; continue; } + usage(); + } + + if (database_filename == NULL) { + fprintf(stderr, "ERROR: provide a database file (-d)\n"); + exit(1); + } + if (output_filename == NULL) { + fprintf(stderr, "ERROR: provide an output file (-o)\n"); + exit(1); + } + + database = parse_database(database_filename); + load_config_file(database_filename); + + /* get the event and fields from database */ + int tx_ant0_id = event_id_from_name(database, event_name); + database_event_format f = get_format(database, tx_ant0_id); + +#define G(var_name, var_type, var) \ + if (!strcmp(f.name[i], var_name)) { \ + if (strcmp(f.type[i], var_type)) abort(); \ + var = i; \ + continue; \ + } + + int timestamp_id = -1; + int data_id = -1; + for (i = 0; i < f.count; i++) { + /* there is a typo in T_messages.txt, "timestap" instead of "timestamp" */ + if (!no_timestamp) + G("timestap", "int", timestamp_id); + G(buffer_name, "buffer", data_id); + } + if ((!no_timestamp && timestamp_id == -1) || data_id == -1) { + if (data_id == -1) + fprintf(stderr, "fatal: field '%s' of event '%s' does not exist\n", + buffer_name, event_name); + if (!no_timestamp && timestamp_id == -1) + fprintf(stderr, "fatal: field 'timestamp' of event '%s' does not exist\n", + event_name); + exit(1); + } + + number_of_events = number_of_ids(database); + is_on = calloc(number_of_events, sizeof(int)); + if (is_on == NULL) abort(); + + on_off(database, event_name, is_on, 1); + + /* connect to tracee */ + socket = connect_to(ip, port); + + /* activate trace */ + mt = 1; + if (socket_send(socket, &mt, 1) == -1 || + socket_send(socket, &number_of_events, sizeof(int)) == -1 || + socket_send(socket, is_on, number_of_events * sizeof(int)) == -1) + abort(); + + /* - means to output to stdout */ + if (!strcmp(output_filename, "-")) { + out = stdout; + } else { + out = fopen(output_filename, "w"); + if (out == NULL) { + perror(output_filename); + exit(1); + } + } + + if (!nosig) { + /* exit on ctrl+c and ctrl+z */ + if (signal(SIGQUIT, force_stop) == SIG_ERR) abort(); + if (signal(SIGINT, force_stop) == SIG_ERR) abort(); + if (signal(SIGTSTP, force_stop) == SIG_ERR) abort(); + } + + OBUF ebuf = {.osize = 0, .omaxsize = 0, .obuf = NULL}; + + /* read messages */ + unsigned int last_timestamp = 0; + int last_count = 0; + int first = 1; + + /* stop if max reached */ + while ((max == -1 || dumped < max) && run) { + event e; + e = get_event(socket, &ebuf, database); + + if (e.type == -1) break; + if (e.type != tx_ant0_id) continue; + + unsigned int timestamp = 0; + if (!no_timestamp) + timestamp = e.e[timestamp_id].i; + int count = e.e[data_id].bsize / 4; + +#if 0 + fprintf(stderr, "timestamp %u buffer %p count %d not transmitted %d delta %d\n", + timestamp, + e.e[data_id].b, + count, + timestamp - (last_timestamp + last_count), + timestamp - last_timestamp); +#endif + + /* rfsimulator may send 1 sample with old time when a new client connects + * let's reject this packet + */ + if (!first && timestamp < last_timestamp + last_count) { + /* more than 1 sample is not accepted */ + if (count != 1) { + fprintf(stderr, "fatal: past transmission detected (%d samples)\n", count); + abort(); + } + fprintf(stderr, "past transmission detected (%d samples), ignore\n", count); + continue; + } + + /* insert missing samples */ + if (!no_timestamp && !first) { + int missing = timestamp - (last_timestamp + last_count); + if (missing < 0) abort(); + while (missing) { + /* limit size of array miss[], it's allocated on the stack */ + int count = missing > 65536 ? 65536 : missing; + float miss[count * 2]; + memset(miss, 0, count * 2 * sizeof(float)); + + if (fwrite(miss, count * 2 * sizeof(float), 1, out) != 1) { + fprintf(stderr, "error writing to %s\n", output_filename); + if (strcmp(output_filename, "-")) + fclose(out); + close(socket); + exit(1); + } + dumped += count; + missing -= count; + } + } + + first = 0; + + if (do_float) { + /* transform to float */ + float iq[count * 2]; + short *iq_short = (short *)e.e[data_id].b; + for (int i = 0; i < count * 2; i++) + iq[i] = iq_short[i] / scale; + + /* save */ + if (fwrite(iq, count * 2 * sizeof(float), 1, out) != 1) { + fprintf(stderr, "error writing to %s\n", output_filename); + if (strcmp(output_filename, "-")) + fclose(out); + exit(1); + } + } else { + /* save directly as short */ + if (fwrite(e.e[data_id].b, count * 2 * 2, 1, out) != 1) { + fprintf(stderr, "error writing to %s\n", output_filename); + if (strcmp(output_filename, "-")) + fclose(out); + exit(1); + } + } + dumped += count; + + last_timestamp = timestamp; + last_count = count; + } + + if (strcmp(output_filename, "-")) + fclose(out); + close(socket); + + return 0; +} From 4a0d8ce637e12c57c80a27c0968dcc67d0cac7d3 Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Thu, 19 Jun 2025 16:43:19 +0200 Subject: [PATCH 202/964] rfsim: add a T trace to dump IQ data Only for one antenna. --- radio/rfsimulator/simulator.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/radio/rfsimulator/simulator.c b/radio/rfsimulator/simulator.c index 32648758c8..3a2a0ae2d5 100644 --- a/radio/rfsimulator/simulator.c +++ b/radio/rfsimulator/simulator.c @@ -738,6 +738,10 @@ static int rfsimulator_write_internal(rfsimulator_state_t *t, openair0_timestamp timestamp, timestamp + nsamps, signal_energy(samplesVoid[0], nsamps)); + + /* trace only first antenna */ + T(T_USRP_TX_ANT0, T_INT(timestamp), T_BUFFER(samplesVoid[0], sampleToByte(nsamps, 1))); + return nsamps; } From 17b59413677f714cccc9a1c0d774c359c6fbfc82 Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Thu, 19 Jun 2025 16:44:13 +0200 Subject: [PATCH 203/964] T: dump logs to stderr, not stdout This is a problem with the new tool ant0 when we dump IQ to stdout. The logs will mess up the recording. --- common/utils/T/tracer/utils.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/common/utils/T/tracer/utils.c b/common/utils/T/tracer/utils.c index 78b01a2516..66dd2a0b48 100644 --- a/common/utils/T/tracer/utils.c +++ b/common/utils/T/tracer/utils.c @@ -159,7 +159,7 @@ int socket_send(int socket, void *buffer, int size) { int get_connection(char *addr, int port) { int s, t; - printf("waiting for connection on %s:%d\n", addr, port); + fprintf(stderr, "waiting for connection on %s:%d\n", addr, port); s = create_listen_socket(addr, port); t = socket_accept(s); @@ -169,7 +169,7 @@ int get_connection(char *addr, int port) { } close(s); - printf("connected\n"); + fprintf(stderr, "connected\n"); return t; } @@ -216,12 +216,12 @@ int try_connect_to(char *addr, int port) { int connect_to(char *addr, int port) { int s; - printf("connecting to %s:%d\n", addr, port); + fprintf(stderr, "connecting to %s:%d\n", addr, port); again: s = try_connect_to(addr, port); if (s == -1) { - printf("trying again in 1s\n"); + fprintf(stderr, "trying again in 1s\n"); sleep(1); goto again; } From a10420e015e93826e83c9e11906631b8e508b4c5 Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Sun, 22 Jun 2025 18:59:38 +0200 Subject: [PATCH 204/964] T hacks: add ofdm-plot Used to... surprise... plot OFDM data as output (or input) by gnb! Limitation: only one antenna. --- common/utils/T/tracer/hacks/Makefile | 11 +- common/utils/T/tracer/hacks/plot-ofdm.c | 351 ++++++++++++++++++++++++ 2 files changed, 360 insertions(+), 2 deletions(-) create mode 100644 common/utils/T/tracer/hacks/plot-ofdm.c diff --git a/common/utils/T/tracer/hacks/Makefile b/common/utils/T/tracer/hacks/Makefile index f693094fb6..2c96e67823 100644 --- a/common/utils/T/tracer/hacks/Makefile +++ b/common/utils/T/tracer/hacks/Makefile @@ -3,7 +3,7 @@ CFLAGS=-Wall -g -pthread -DT_TRACER -I. -I.. LIBS=-lX11 -lm -lpng -lXft -all: dump_nack_signal time_meas timeplot multi-rru-clean ant0 +all: dump_nack_signal time_meas timeplot multi-rru-clean ant0 plot-ofdm dump_nack_signal: ../utils.o ../database.o ../configuration.o ../event.o \ dump_nack_signal.o @@ -26,6 +26,13 @@ ant0: ant0.o ../utils.o ../database.o ../configuration.o ../event.o ant0.o: ant0.c $(CC) $(CFLAGS) -c -o $@ $< -march=native -ffast-math -O3 +plot-ofdm: plot-ofdm.o ../utils.o + $(CC) $(CFLAGS) -o $@ $^ $(LIBS) -lfftw3f + +#plot-ofdm needs good compilation +plot-ofdm.o: plot-ofdm.c + $(CC) $(CFLAGS) -c -o $@ $< -march=native -ffast-math -O3 + .PHONY: all %.o: %.c @@ -33,4 +40,4 @@ ant0.o: ant0.c clean: rm -f *.o core dump_nack_signal time_meas timeplot multi-rru-clean \ - ant0 + ant0 plot-ofdm diff --git a/common/utils/T/tracer/hacks/plot-ofdm.c b/common/utils/T/tracer/hacks/plot-ofdm.c new file mode 100644 index 0000000000..3f6e0b9dce --- /dev/null +++ b/common/utils/T/tracer/hacks/plot-ofdm.c @@ -0,0 +1,351 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "utils.h" + +const int width = 14 * 20 * 4; +int height; + +/* when vzoom = 1 each pixel represents 1 RE + * when 2, it is max of 2 vertical REs + * useful if height of plot is to big + * (with 106 RB we already reach 106*12 = 1272 pixels, so with even bigger + * bandwidths...) + */ +int vzoom = 1; +/* when hzoom = 1 each pixel represents 1 RE + * when 2, it is max of 2 horizontal REs + * useful to slow down display + */ +int hzoom = 1; +/* intensity is to scale the input + * normally, as float, cabs(input) is in [0..1] + * to get pixel color we *255 + * but maybe it's too intense, or not enough, + * so let's have a control the user can set at will + */ +float intensity = 255; + +pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; + +void lock(void) +{ + pthread_mutex_lock(&m); +} + +void unlock(void) +{ + pthread_mutex_unlock(&m); +} + +typedef struct { + Display *d; + Window w; + XImage *img; + unsigned char *img_data; + int img_pos; +} gui_t; + +/* delay management begin */ + +long double frame_time; + +void time_start(void) +{ + struct timespec l; + if (clock_gettime(CLOCK_REALTIME, &l)) abort(); + frame_time = l.tv_sec * 1000000000. + l.tv_nsec; +} + +void delay(int fps) +{ + struct timespec t; + struct timespec delay; + long double cur_time; + + frame_time += 1000000000. / fps; + + if (clock_gettime(CLOCK_REALTIME, &t)) abort(); + + cur_time = t.tv_sec * 1000000000. + t.tv_nsec; + + if (frame_time < cur_time) { fprintf(stderr, "ERROR: we late\n"); return; } + + delay.tv_nsec = ((uint64_t)(frame_time-cur_time)) % 1000000000; + delay.tv_sec = ((uint64_t)(frame_time-cur_time)) / 1000000000; + + if (pselect(0, NULL, NULL, NULL, &delay, NULL)) { fprintf(stderr, "ERROR: pselect fails\n"); exit(1); } +} + +/* delay management end */ + +static void *gui_thread(void *_g) +{ + time_start(); + + gui_t *g = _g; + while (1) { + XEvent e; while (XPending(g->d)) XNextEvent(g->d, &e); + lock(); + XPutImage(g->d, g->w, DefaultGC(g->d, DefaultScreen(g->d)), g->img, 0, 0, 0, 0, + width, height/vzoom); + unlock(); + delay(10); + } + return 0; +} + +unsigned char re_to_pixel(float re) +{ + float v = fminf(255, re * intensity); + return v; +} + +unsigned char mix(unsigned char a, unsigned char b) +{ + return a > b ? a : b; +} + +void usage(void) +{ + printf("options:\n"); + printf(" -f input is float, not s16\n"); + printf(" -srate set sampling rate (default 61440000)\n"); + printf(" -prb set number of PRBs (default 106)\n"); + printf(" -mu set mu (default 1, 0 is for 15KHz, 1 for 30KHz, etc.)\n"); + printf(" -no-fft don't do fft, input is in frequency domain\n"); + printf(" -vzoom add some sort of vertical zoom, default 1, passing 2 divides height by 2, etc.\n"); + printf(" -hzoom add some sort of speed control, default 1, passing 2 means 2 REs per pixel, etc.\n"); + printf(" -delay delay 'delay' microseconds between processing of each symbol\n"); + printf(" -intensity set intensity of data pixel (default 255.)\n"); + printf(" -skip skip 'count' samples at beginning\n"); + exit(0); +} + +int main(int n, char **v) +{ + int input_is_float = 0; + int no_fft = 0; + int delay = 0; + int skip = 0; + int symbols_per_subframe; + long sampling_rate = 61440000; + int mu = 1; + int prb = 106; + + /* parse command line arguments */ + for (int i = 1; i < n; i++) { + if (!strcmp(v[i], "-f")) { input_is_float = 1; continue; } + if (!strcmp(v[i], "-no-fft")) { no_fft = 1; continue; } + if (!strcmp(v[i], "-vzoom")) { if (i>n-2) usage(); vzoom = atoi(v[++i]); continue; } + if (!strcmp(v[i], "-hzoom")) { if (i>n-2) usage(); hzoom = atoi(v[++i]); continue; } + if (!strcmp(v[i], "-delay")) { if (i>n-2) usage(); delay = atoi(v[++i]); continue; } + if (!strcmp(v[i], "-intensity")) { if (i>n-2) usage(); intensity = atof(v[++i]); continue; } + if (!strcmp(v[i], "-srate")) { if (i>n-2) usage(); sampling_rate = atol(v[++i]); continue; } + if (!strcmp(v[i], "-prb")) { if (i>n-2) usage(); prb = atoi(v[++i]); continue; } + if (!strcmp(v[i], "-mu")) { if (i>n-2) usage(); mu = atoi(v[++i]); continue; } + if (!strcmp(v[i], "-skip")) { if (i>n-2) usage(); skip = atoi(v[++i]); continue; } + usage(); + } + + symbols_per_subframe = 14 * (1 << mu); + + /* compute durations from sampling rate and mu (scs) */ + /* this is 38.211 5.3.1, a bit simplified/reordered */ + int ofdm_duration = sampling_rate / 15000 / (1 << mu); + int l0_cycle_prefix = sampling_rate / 480000 * (144*64 / (1 << mu) + 16*64) / 4096; + int cycle_prefix = sampling_rate / 480000 * (144*64 / (1 << mu)) / 4096; + + /* small sanity check */ + if (prb * 12 > ofdm_duration) { + printf("fatal: too many PRBs for this sampling rate / mu\n"); + exit(1); + } + + height = prb * 12; + + if (height % vzoom) { fprintf(stderr, "bad vzoom for this height, try 1, 2, 4, ...\n"); return 1; } + + gui_t g = { 0 }; + + /* open X11 display */ + g.d = XOpenDisplay(0); + if (!g.d) { + fprintf(stderr, "could not open display\n"); + return 1; + } + + /* create window */ + g.w = XCreateSimpleWindow(g.d, DefaultRootWindow(g.d), 0, 0, + width, height / vzoom, 0, WhitePixel(g.d, DefaultScreen(g.d)), + WhitePixel(g.d, DefaultScreen(g.d))); + XStoreName(g.d, g.w, "IQ"); + /* enable backing store */ + { + XSetWindowAttributes att; + att.backing_store = Always; + XChangeWindowAttributes(g.d, g.w, CWBackingStore, &att); + } + XSelectInput(g.d, g.w, + KeyPressMask | + ButtonPressMask | + ButtonReleaseMask | + PointerMotionMask | + ExposureMask | + StructureNotifyMask); + XMapWindow(g.d, g.w); + + g.img_data = calloc(1, width * height/vzoom * 4); if (!g.img_data) abort(); + g.img = XCreateImage(g.d, DefaultVisual(g.d, DefaultScreen(g.d)), 24 /*depth*/, + ZPixmap, 0 /*offset*/, (char*)g.img_data, width, height/vzoom, 8, 0); + + new_thread(gui_thread, &g); + + /* fft data */ + int fft_size = ofdm_duration; + float complex *in = fftwf_malloc(sizeof(float complex) * fft_size); + float complex *out = fftwf_malloc(sizeof(float complex) * fft_size); + fftwf_plan p_fft = fftwf_plan_dft_1d(fft_size, in, out, + FFTW_FORWARD, FFTW_ESTIMATE); + memset(in, 0, sizeof(float complex) * fft_size); + fftwf_execute(p_fft); + + int symbol = 0; + int back_color = 0; + int hpixel = 0; + + if (skip) { + if (input_is_float) { + float intime[skip * 2]; + if (fread(intime, skip * 8, 1, stdin) != 1) abort(); + } else { + short intime[skip * 2]; + if (fread(intime, skip * 4, 1, stdin) != 1) abort(); + } + } + + while (1) { + int cur_cycle_prefix; + if (symbol == 0 || symbol == 7 * (1 << mu)) + cur_cycle_prefix = l0_cycle_prefix; + else + cur_cycle_prefix = cycle_prefix; + + if (no_fft) goto without_fft; + + /* input signal is in time domain, timing aligned, do FFT */ + + /* read time domain data */ + if (input_is_float) { + float intime[(ofdm_duration + cur_cycle_prefix) * 2]; + if (fread(intime, (ofdm_duration + cur_cycle_prefix) * 8, 1, stdin) != 1) break; + + for (int i = 0; i < fft_size; i++) + /* skip cycle prefix */ + in[i] = intime[(cur_cycle_prefix + i) * 2] + I * intime[(cur_cycle_prefix + i) * 2 + 1]; + } else { + short intime[(ofdm_duration + cur_cycle_prefix) * 2]; + if (fread(intime, (ofdm_duration + cur_cycle_prefix) * 4, 1, stdin) != 1) break; + + for (int i = 0; i < fft_size; i++) + /* skip cycle prefix */ + in[i] = intime[(cur_cycle_prefix + i) * 2] / 2048. + I * intime[(cur_cycle_prefix + i) * 2 + 1] / 2048.; + } + + /* go to freq domain */ + fftwf_execute(p_fft); + + goto after_fft; + +without_fft: + /* input data is symbols, each containing full FFT data */ + if (input_is_float) { + float infreq[fft_size * 2]; + if (fread(infreq, fft_size * 2 * 4, 1, stdin) != 1) break; + + for (int i = 0; i < fft_size; i++) + out[i] = infreq[i * 2] + I * infreq[i * 2 + 1]; + } else { + short infreq[ofdm_duration * 2]; + if (fread(infreq, fft_size * 2 * 2, 1, stdin) != 1) break; + + for (int i = 0; i < fft_size; i++) + out[i] = infreq[i * 2] / 2048. + I * infreq[i * 2 + 1] / 2048.; + } + +after_fft: + lock(); + + /* extract data of this ofdm symbol */ + unsigned char *p = g.img_data + g.img_pos * 4; + int front_pos = (g.img_pos + 8) % width; + unsigned char *pfront = g.img_data + front_pos * 4; + for (int i = prb * 12 - 1; i >= 0; i -= vzoom) { + /* take the max */ + float out_val = 0; + for (int j = 0; j < vzoom; j++) { + int start = - prb * 12 / 2; + int pos = start + i + j; + /* neg freq are at the end of fft data array */ + int pos_in_fft = pos >= 0 + ? pos + : pos + fft_size; + float v = cabs(out[pos_in_fft]); + if (v > out_val) out_val = v; + } + int color = re_to_pixel(out_val); + /* grey level image mixed with some background changing every slot */ + unsigned char back_col[2][3] = { + { 100, 90, 90 }, + { 100, 60, 60, } + }; + if (hpixel == 0) { + p[0] = p[1] = p[2] = color; + } else { + p[0] = mix(p[0], color); + p[1] = mix(p[1], color); + p[2] = mix(p[2], color); + } + if (hpixel == hzoom - 1) { + p[0] = mix(p[0], back_col[back_color][0]); + p[1] = mix(p[1], back_col[back_color][1]); + p[2] = mix(p[2], back_col[back_color][2]); + } + p[3] = 255; + p += width * 4; + pfront[0] = 255; + pfront[1] = 128; + pfront[2] = 128; + pfront[3] = 255; + pfront += width * 4; + } + + unlock(); + + hpixel++; + if (hpixel == hzoom) { + hpixel = 0; + g.img_pos++; + if (g.img_pos == width) g.img_pos = 0; + } + + symbol++; + if (symbol == symbols_per_subframe) symbol = 0; + + /* switch back color every slot */ + if (symbol % 14 == 0) + back_color = 1 - back_color; + + if (delay) usleep(delay); + } + + return 0; +} From c607413eac6578a1570db34624138b75abc23cc3 Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Sun, 22 Jun 2025 19:08:35 +0200 Subject: [PATCH 205/964] rfsim: add a T trace to dump RX IQ data Only for one antenna. --- radio/rfsimulator/simulator.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/radio/rfsimulator/simulator.c b/radio/rfsimulator/simulator.c index 3a2a0ae2d5..fca1b8a2e0 100644 --- a/radio/rfsimulator/simulator.c +++ b/radio/rfsimulator/simulator.c @@ -1077,6 +1077,10 @@ static int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimest *ptimestamp, t->nextRxTstamp, signal_energy(samplesVoid[0], nsamps)); + + /* trace only first antenna */ + T(T_USRP_RX_ANT0, T_INT(t->nextRxTstamp), T_BUFFER(samplesVoid[0], sampleToByte(nsamps, 1))); + return nsamps; } From 3d3491762687388eac969bc60c3a4d3537f497d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Soares=20Silva?= Date: Tue, 4 Jun 2024 13:33:33 +0100 Subject: [PATCH 206/964] Implementation of PNF using WLS as message transport The common library exposes functions for the PNF to return the received blocks to the VNF for it to call WLS_Enqueue on them. This is done in order to ensure the Blocks are returned after processing, also preventing the Dequeueing of blocks that are still being used, i.e. the internal value is not -1 All saved blocks are to be enqueued at the reception of a SLOT.indication by the VNF Additionally, the definition of NFAPI_MAX_PACKED_MESSAGE_SIZE was moved to nfapi_interface.h and removed from the other headers, this is done to allow to set the maximum message size when using WLS by only changing the value in one place Fixup fapi_nr_message_header_unpack call in nfapi_hex_parser --- CMakeLists.txt | 23 +- cmake_targets/build_oai | 5 +- nfapi/CMakeLists.txt | 7 +- nfapi/oai_integration/nfapi_pnf.c | 29 +- .../wls_integration/CMakeLists.txt | 21 ++ .../wls_integration/include/wls_common.h | 108 +++++++ .../wls_integration/include/wls_pnf.h | 33 ++ .../wls_integration/wls_common.c | 118 +++++++ .../oai_integration/wls_integration/wls_pnf.c | 290 ++++++++++++++++++ nfapi/open-nFAPI/fapi/CMakeLists.txt | 6 +- nfapi/open-nFAPI/fapi/inc/nr_fapi.h | 26 +- nfapi/open-nFAPI/fapi/inc/nr_fapi_p5.h | 2 +- nfapi/open-nFAPI/fapi/inc/nr_fapi_p5_utils.h | 2 +- nfapi/open-nFAPI/fapi/inc/nr_fapi_p7.h | 2 +- nfapi/open-nFAPI/fapi/inc/nr_fapi_p7_utils.h | 2 +- nfapi/open-nFAPI/fapi/src/nr_fapi.c | 9 +- nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c | 13 +- nfapi/open-nFAPI/fapi/src/nr_fapi_p7.c | 12 +- .../nfapi/public_inc/nfapi_interface.h | 5 +- nfapi/open-nFAPI/nfapi/src/nfapi_p7.c | 4 + nfapi/open-nFAPI/pnf/inc/pnf.h | 11 +- nfapi/open-nFAPI/pnf/inc/pnf_p7.h | 1 - nfapi/open-nFAPI/pnf/src/pnf.c | 4 +- nfapi/open-nFAPI/utils/nfapi_hex_parser.c | 3 +- .../vnf/public_inc/nfapi_vnf_interface.h | 1 - 25 files changed, 698 insertions(+), 39 deletions(-) create mode 100644 nfapi/oai_integration/wls_integration/CMakeLists.txt create mode 100644 nfapi/oai_integration/wls_integration/include/wls_common.h create mode 100644 nfapi/oai_integration/wls_integration/include/wls_pnf.h create mode 100644 nfapi/oai_integration/wls_integration/wls_common.c create mode 100644 nfapi/oai_integration/wls_integration/wls_pnf.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 4dc8c9ce7a..123d08c3bc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -715,7 +715,11 @@ add_library(NFAPI_LIB ${NFAPI_SRC}) target_link_libraries(NFAPI_LIB PUBLIC nfapi_common) target_link_libraries(NFAPI_LIB PUBLIC nr_fapi_p5 nr_fapi_p7) -target_compile_definitions(NFAPI_LIB PRIVATE ENABLE_SOCKET) +if(OAI_WLS) + target_compile_definitions(NFAPI_LIB PRIVATE ENABLE_WLS) +else() + target_compile_definitions(NFAPI_LIB PRIVATE ENABLE_SOCKET) +endif() include_directories(${NFAPI_DIR}/nfapi/public_inc) include_directories(${NFAPI_DIR}/nfapi/inc) @@ -729,6 +733,9 @@ add_library(NFAPI_PNF_LIB ${NFAPI_PNF_SRC}) target_link_libraries(NFAPI_PNF_LIB PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs) target_link_libraries(NFAPI_PNF_LIB PUBLIC nr_fapi_p7) +if(OAI_WLS) + target_compile_definitions(NFAPI_PNF_LIB PRIVATE ENABLE_WLS) +endif() include_directories(${NFAPI_DIR}/pnf/public_inc) include_directories(${NFAPI_DIR}/pnf/inc) @@ -756,7 +763,11 @@ set(NFAPI_USER_SRC ${NFAPI_USER_DIR}/gnb_ind_vars.c ) add_library(NFAPI_USER_LIB ${NFAPI_USER_SRC}) -target_compile_definitions(NFAPI_USER_LIB PRIVATE ENABLE_SOCKET) +if(OAI_WLS) + target_compile_definitions(NFAPI_USER_LIB PRIVATE ENABLE_WLS) +else() + target_compile_definitions(NFAPI_USER_LIB PRIVATE ENABLE_SOCKET) +endif() target_link_libraries(NFAPI_USER_LIB PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs UTIL) target_link_libraries(NFAPI_USER_LIB PRIVATE nr_fapi_p7) if(OAI_AERIAL) @@ -1841,8 +1852,12 @@ target_link_libraries(nr-softmodem PRIVATE pthread m CONFIG_LIB rt sctp) target_link_libraries(nr-softmodem PRIVATE ${T_LIB}) target_link_libraries(nr-softmodem PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) target_link_libraries(nr-softmodem PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) - -target_link_libraries(nr-softmodem PUBLIC nfapi_socket_lib) +add_boolean_option(OAI_WLS OFF "Activate OAI's WLS driver" OFF) +if (OAI_WLS) + target_link_libraries(nr-softmodem PUBLIC wls_integration_lib) +else() + target_link_libraries(nr-softmodem PUBLIC nfapi_socket_lib) +endif() add_boolean_option(OAI_AERIAL OFF "Activate OAI's AERIAL driver" OFF) if (OAI_AERIAL) target_compile_definitions(nr-softmodem PUBLIC ENABLE_AERIAL) diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index 5e9bfaf444..cbe197c973 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -99,7 +99,7 @@ Options: USRP, BLADERF, LMSSDR, IRIS, SIMU, AW2SORI, AERIAL, None (Default) Adds this RF board support (in external packages installation and in compilation) -t | --transport - Selects the transport protocol type, options: None, Ethernet, benetel4g, benetel5g, oran_fhlib_5g, oran_fhlib_5g_mplane + Selects the transport protocol type, options: None, Ethernet, benetel4g, benetel5g, oran_fhlib_5g, oran_fhlib_5g_mplane, WLS -P | --phy_simulators Makes the unitary tests Layer 1 simulators -s | --check @@ -308,6 +308,9 @@ function main() { TARGET_LIST="$TARGET_LIST $2" CMAKE_CMD="$CMAKE_CMD -DOAI_FHI72=ON -DOAI_FHI72_MPLANE=ON" ;; + "WLS"|"Wls"|"wls") + CMAKE_CMD="$CMAKE_CMD -DOAI_WLS=ON" + ;; "None") ;; *) diff --git a/nfapi/CMakeLists.txt b/nfapi/CMakeLists.txt index e79905b07c..6b9c75b5a8 100644 --- a/nfapi/CMakeLists.txt +++ b/nfapi/CMakeLists.txt @@ -1,4 +1,9 @@ add_subdirectory(oai_integration/aerial) -add_subdirectory(oai_integration/socket) +if (OAI_WLS) + add_subdirectory(oai_integration/wls_integration) +else () # Not WLS, means its SOCKET-based comms, maybe add a flag specific for UDP + message(STATUS "No Support for WLS") + add_subdirectory(oai_integration/socket) +endif () add_subdirectory(open-nFAPI) add_subdirectory(tests) diff --git a/nfapi/oai_integration/nfapi_pnf.c b/nfapi/oai_integration/nfapi_pnf.c index 88b82ad480..24d7d0fbfa 100644 --- a/nfapi/oai_integration/nfapi_pnf.c +++ b/nfapi/oai_integration/nfapi_pnf.c @@ -63,6 +63,12 @@ #include "executables/lte-softmodem.h" #include "nfapi/open-nFAPI/pnf/inc/pnf_p7.h" +#ifdef ENABLE_WLS +#include +#include +#include "nfapi/oai_integration/wls_integration/include/wls_pnf.h" +#endif + #ifdef ENABLE_SOCKET #include #endif @@ -1752,6 +1758,15 @@ int nr_start_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nf p7_config->codec_config.unpack_vendor_extension_tlv = &pnf_nr_phy_unpack_vendor_extension_tlv; p7_config->codec_config.pack_vendor_extension_tlv = &pnf_nr_phy_pack_vendor_extention_tlv; +#ifdef ENABLE_WLS + p7_config->unpack_func = &fapi_nr_p7_message_unpack; + p7_config->hdr_unpack_func = &fapi_nr_p7_message_header_unpack; + p7_config->pack_func = &fapi_nr_p7_message_pack; + p7_config->send_p7_msg = &wls_pnf_nr_send_p7_message; + // pass p7_config to WLS handler + wls_pnf_set_p7_config(p7_config); +#endif + #ifdef ENABLE_SOCKET p7_config->unpack_func = &nfapi_nr_p7_message_unpack; p7_config->hdr_unpack_func = &nfapi_nr_p7_message_header_unpack; @@ -1806,10 +1821,11 @@ int nr_start_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nf usleep(50000); printf("[PNF] waiting for OAI to be started\n"); } - +#ifndef ENABLE_WLS printf("[PNF] Sending PNF_START_RESP\n"); nfapi_nr_send_pnf_start_resp(config, p7_config->phy_id); printf("[PNF] Sending first P7 slot indication\n"); +#endif #if 1 nfapi_pnf_p7_slot_ind(p7_config, p7_config->phy_id, 0, 0); printf("[PNF] Sent first P7 slot ind\n"); @@ -2192,6 +2208,17 @@ void configure_nr_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_add config->codec_config.unpack_p4_p5_vendor_extension = &pnf_nr_sim_unpack_p4_p5_vendor_extension; config->codec_config.pack_p4_p5_vendor_extension = &pnf_nr_sim_pack_p4_p5_vendor_extension; +#ifdef ENABLE_WLS + printf("WLS MODE PNF\n"); + NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] Creating WLS PNF NFAPI start thread %s\n", __FUNCTION__); + // Assume it's the FAPI handler, change from within the PNF if it's not the case + config->unpack_func = &fapi_nr_p5_message_unpack; + config->hdr_unpack_func = &fapi_nr_message_header_unpack; + config->pack_func = &fapi_nr_p5_message_pack; + config->send_p5_msg = &wls_pnf_nr_send_p5_message; + //wls_fapi_pnf_nr_start_thread(config); + threadCreate(&pnf_p5_init_and_receive_pthread, wls_fapi_pnf_nr_start_thread, config, "NFAPI_WLS_PNF", -1, OAI_PRIORITY_RT_MAX); +#endif #ifdef ENABLE_SOCKET NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] Creating PNF NFAPI start thread %s\n", __FUNCTION__); diff --git a/nfapi/oai_integration/wls_integration/CMakeLists.txt b/nfapi/oai_integration/wls_integration/CMakeLists.txt new file mode 100644 index 0000000000..0a217dd5b6 --- /dev/null +++ b/nfapi/oai_integration/wls_integration/CMakeLists.txt @@ -0,0 +1,21 @@ +message(STATUS "Building with support for WLS") +add_library(wls_integration_lib + wls_pnf.c + wls_common.c +) + +find_library(WLS_LIB wls REQUIRED) +message(STATUS " wls library found in ${WLS_LIB}") + +find_library(hugetlbfs_LIB hugetlbfs REQUIRED) +message(STATUS " hugetlbfs library found in ${hugetlbfs_LIB}") + +pkg_check_modules(dpdk REQUIRED libdpdk=20.11.3) +target_link_libraries(wls_integration_lib PRIVATE ${dpdk_LINK_LIBRARIES}) +target_include_directories(wls_integration_lib PRIVATE ${dpdk_INCLUDE_DIRS}) +target_include_directories(wls_integration_lib PRIVATE include/) + +target_compile_definitions(wls_integration_lib PUBLIC ENABLE_WLS) +target_link_libraries(wls_integration_lib PRIVATE NFAPI_LIB NFAPI_USER_LIB) +target_link_libraries(wls_integration_lib PRIVATE nr_fapi_p5 nr_fapi_p7) +target_link_libraries(wls_integration_lib PRIVATE "${WLS_LIB}" "${hugetlbfs_LIB}") diff --git a/nfapi/oai_integration/wls_integration/include/wls_common.h b/nfapi/oai_integration/wls_integration/include/wls_common.h new file mode 100644 index 0000000000..1b6a8e4cdf --- /dev/null +++ b/nfapi/oai_integration/wls_integration/include/wls_common.h @@ -0,0 +1,108 @@ +/* +* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef OPENAIRINTERFACE_WLS_COMMON_H +#define OPENAIRINTERFACE_WLS_COMMON_H + +#include +#include +#include +#include "wls_lib.h" +#include "nfapi/open-nFAPI/fapi/inc/nr_fapi_p5_utils.h" +#include "nfapi/open-nFAPI/fapi/inc/nr_fapi_p7_utils.h" + +#define WLS_DEV_NAME "wls" +#define WLS_MAC_MEMORY_SIZE 0x7F000000 +#define WLS_PHY_MEMORY_SIZE 0x7F000000 + +#define MAX_NUM_LOCATIONS (508) + +#define MIN_DL_BUF_LOCATIONS (0) /* Used for stats collection 0-49 */ +#define MIN_UL_BUF_LOCATIONS (MIN_DL_BUF_LOCATIONS + MAX_NUM_LOCATIONS) /* Used for stats collection 50-99 */ + +#define MAX_DL_BUF_LOCATIONS (MIN_DL_BUF_LOCATIONS + MAX_NUM_LOCATIONS) /* Used for stats collection 0-49 */ +#define MAX_UL_BUF_LOCATIONS (MIN_UL_BUF_LOCATIONS + MAX_NUM_LOCATIONS) /* Used for stats collection 50-99 */ + +#define ALLOC_TRACK_SIZE ( 16384 ) + +typedef struct { + uint64_t *values; + uint16_t values_size; + uint16_t values_count; +}pa_store_t; + +/* ----- WLS Operation --- */ +#define FAPI_VENDOR_MSG_HEADER_IND 0x1A +// Linked list header present at the top of all messages +typedef struct _fapi_api_queue_elem { + struct _fapi_api_queue_elem *p_next; + // p_tx_data_elm_list used for TX_DATA.request processing + struct _fapi_api_queue_elem *p_tx_data_elm_list; + uint8_t msg_type; + uint8_t num_message_in_block; + uint32_t msg_len; + uint32_t align_offset; + uint64_t time_stamp; +} fapi_api_queue_elem_t, + *p_fapi_api_queue_elem_t; + + +typedef struct wls_mac_mem_array +{ + void **ppFreeBlock; + void *pStorage; + void *pEndOfStorage; + uint32_t nBlockSize; + uint32_t nBlockCount; +} WLS_MAC_MEM_SRUCT, *PWLS_MAC_MEM_SRUCT; + +typedef struct wls_mac_ctx +{ + void *hWls; + void *pWlsMemBase; + void *pWlsMemBaseUsable; + WLS_MAC_MEM_SRUCT sWlsStruct; + + uint64_t nTotalMemorySize; + uint64_t nTotalMemorySizeUsable; + uint32_t nBlockSize; + uint32_t nTotalBlocks; + uint32_t nAllocBlocks; + uint32_t nTotalAllocCnt; + uint32_t nTotalFreeCnt; + uint32_t nTotalUlBufAllocCnt; + uint32_t nTotalUlBufFreeCnt; + uint32_t nTotalDlBufAllocCnt; + uint32_t nTotalDlBufFreeCnt; + // Support for FAPI Translator + uint32_t nPartitionMemSize; + void *pPartitionMemBase; + + volatile pthread_mutex_t lock; + volatile pthread_mutex_t lock_alloc; +} WLS_MAC_CTX, *PWLS_MAC_CTX; + +void fill_fapi_list_elem(p_fapi_api_queue_elem_t currElem, p_fapi_api_queue_elem_t nextElem, const uint8_t msgType, const uint8_t numMsgInBlock, const uint32_t alignOffset); +uint64_t dequeueBlock(PWLS_MAC_CTX pWls); +void wls_return_msg_to_master(PWLS_MAC_CTX pWls, const uint64_t msg_PA); +uint8_t wls_send_fapi_msg(PWLS_MAC_CTX pWls, const uint16_t message_id, const int packed_len, const uint8_t *message ); +uint8_t wls_msg_send(PWLS_MAC_CTX pWls, p_fapi_api_queue_elem_t currMsg); +#endif //OPENAIRINTERFACE_WLS_COMMON_H diff --git a/nfapi/oai_integration/wls_integration/include/wls_pnf.h b/nfapi/oai_integration/wls_integration/include/wls_pnf.h new file mode 100644 index 0000000000..c678345967 --- /dev/null +++ b/nfapi/oai_integration/wls_integration/include/wls_pnf.h @@ -0,0 +1,33 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef OPENAIRINTERFACE_WLS_PNF_H +#define OPENAIRINTERFACE_WLS_PNF_H +#include "nfapi_pnf_interface.h" +#include "pnf.h" +#include "wls_common.h" + +bool wls_pnf_nr_send_p5_message(pnf_t *pnf, nfapi_nr_p4_p5_message_header_t* msg, uint32_t msg_len); +bool wls_pnf_nr_send_p7_message(pnf_p7_t* pnf_p7,nfapi_nr_p7_message_header_t *msg, uint32_t msg_len); +void *wls_fapi_pnf_nr_start_thread(void *ptr); +int wls_fapi_nr_pnf_start(); +void wls_pnf_set_p7_config(void *p7_config); +#endif // OPENAIRINTERFACE_WLS_PNF_H diff --git a/nfapi/oai_integration/wls_integration/wls_common.c b/nfapi/oai_integration/wls_integration/wls_common.c new file mode 100644 index 0000000000..fe4112eba8 --- /dev/null +++ b/nfapi/oai_integration/wls_integration/wls_common.c @@ -0,0 +1,118 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include "wls_common.h" + +void fill_fapi_list_elem(p_fapi_api_queue_elem_t currElem, p_fapi_api_queue_elem_t nextElem, const uint8_t msgType, const uint8_t numMsgInBlock, const uint32_t alignOffset) +{ + currElem->msg_type = msgType; + currElem->num_message_in_block = numMsgInBlock; + currElem->align_offset = alignOffset; + currElem->msg_len = numMsgInBlock * alignOffset; + currElem->p_next = nextElem; + currElem->p_tx_data_elm_list = NULL; + currElem->time_stamp = 0; +} + +uint64_t dequeueBlock(PWLS_MAC_CTX pWls) +{ + uint64_t pa = WLS_DequeueBlock(pWls->hWls); + AssertFatal(pa, "WLS_DequeueBlock failed for pa_hdr\n"); + unsigned long* va = WLS_PA2VA(pWls->hWls, pa); + AssertFatal(va, "WLS_PA2VA failed for headerElem\n"); + while (*va != -1) { + pa = WLS_DequeueBlock(pWls->hWls); + AssertFatal(pa, "WLS_DequeueBlock failed for pa_hdr\n"); + va = WLS_PA2VA(pWls->hWls, pa); + } + return pa; +} + +uint8_t wls_msg_send(PWLS_MAC_CTX pWls, p_fapi_api_queue_elem_t currMsg) +{ + uint32_t msgLen = 0; + + AssertFatal(currMsg, "currMsg can't be NULL"); + AssertFatal(currMsg->p_next, "There needs to be at least 2 blocks to send!"); + msgLen = currMsg->msg_len + sizeof(fapi_api_queue_elem_t); + // Send the first block + if (WLS_Put(pWls, WLS_VA2PA(pWls, currMsg), msgLen, currMsg->msg_type, WLS_SG_FIRST) != 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failure in sending the header block\n"); + return false; + } + // Iterate over the linked list, until a NULL block or a block set to 0xFFFFFFFFFFFFFFFF ( invalid ) + while (((currMsg = currMsg->p_next)) && (uint64_t)(currMsg) != -1) { + msgLen = currMsg->msg_len + sizeof(fapi_api_queue_elem_t); + /* Send the block with appropriate flags, either WLS_SG_NEXT or WLS_SG_LAST */ + const unsigned short flags = currMsg->p_next != NULL ? WLS_SG_NEXT : WLS_SG_LAST; + if (WLS_Put(pWls, WLS_VA2PA(pWls, currMsg), msgLen, currMsg->msg_type, flags) != 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failure in sending the message block\n"); + return false; + } + } + return true; +} + +void wls_return_msg_to_master(PWLS_MAC_CTX pWls,const uint64_t msg_PA) +{ + p_fapi_api_queue_elem_t fapiMsgElem = WLS_PA2VA(pWls->hWls, msg_PA); + AssertFatal(fapiMsgElem, "WLS_PA2VA failed for fapiMsgElem\n"); + const uint8_t wls_header[] = {1, 0}; // num_messages , opaque_handle + // No need to return the message contents, just the block + fill_fapi_list_elem(fapiMsgElem, NULL, FAPI_VENDOR_MSG_HEADER_IND, 1, 2); + memcpy((uint8_t *)(fapiMsgElem + 1), wls_header, 2); + const uint32_t msgLen = fapiMsgElem->msg_len + sizeof(fapi_api_queue_elem_t); + /* Send the block with appropriate only WLS_SG_FIRST flag, since we send only 1 block*/ + if (WLS_Put(pWls->hWls, msg_PA, msgLen, FAPI_VENDOR_MSG_HEADER_IND, WLS_SG_FIRST) != 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR,"Failure in sending block back to master\n"); + } +} + +uint8_t wls_send_fapi_msg(PWLS_MAC_CTX pWls, const uint16_t message_id, const int packed_len, const uint8_t *message) +{ + int num_avail_blocks = WLS_NumBlocks(pWls->hWls); + NFAPI_TRACE(NFAPI_TRACE_DEBUG,"num_avail_blocks is %d\n", num_avail_blocks); + while (num_avail_blocks < 2) { + num_avail_blocks = WLS_NumBlocks(pWls->hWls); + NFAPI_TRACE(NFAPI_TRACE_DEBUG,"num_avail_blocks is %d\n", num_avail_blocks); + } + /* get PA blocks for header and msg */ + uint64_t pa_hdr = dequeueBlock(pWls); + AssertFatal(pa_hdr, "WLS_DequeueBlock failed for pa_hdr\n"); + uint64_t pa_msg = dequeueBlock(pWls); + AssertFatal(pa_msg, "WLS_DequeueBlock failed for pa_msg\n"); + p_fapi_api_queue_elem_t headerElem = WLS_PA2VA(pWls->hWls, pa_hdr); + AssertFatal(headerElem, "WLS_PA2VA failed for headerElem\n"); + p_fapi_api_queue_elem_t fapiMsgElem = WLS_PA2VA(pWls->hWls, pa_msg); + AssertFatal(fapiMsgElem, "WLS_PA2VA failed for fapiMsgElem\n"); + fill_fapi_list_elem(fapiMsgElem, NULL, message_id, 1, packed_len + NFAPI_HEADER_LENGTH); + memcpy((uint8_t *)(fapiMsgElem + 1), message, packed_len + NFAPI_HEADER_LENGTH); + uint8_t wls_header[] = {1, 0}; // num_messages , opaque_handle + if (NFAPI_MODE == NFAPI_MODE_VNF) { + // Use the opaque handle to signal to our PNF to not progress the FAPI PNF state machine + wls_header[1] = 0xff; + } + fill_fapi_list_elem(headerElem, fapiMsgElem, FAPI_VENDOR_MSG_HEADER_IND, 1, 2); + memcpy((uint8_t *)(headerElem + 1), wls_header, 2); + uint8_t retval = wls_msg_send(pWls->hWls, headerElem); + return retval; +} + diff --git a/nfapi/oai_integration/wls_integration/wls_pnf.c b/nfapi/oai_integration/wls_integration/wls_pnf.c new file mode 100644 index 0000000000..e02cef30a4 --- /dev/null +++ b/nfapi/oai_integration/wls_integration/wls_pnf.c @@ -0,0 +1,290 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include "wls_pnf.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "pnf.h" +#include "nr_nfapi_p7.h" +#include "nr_fapi_p5.h" + +// A copy of the PNF P7 config is needed for the message processing thread, in other transport mechanisms where P7 is handled in a +// different thread, the config is passed to it upon the thread creation +nfapi_pnf_p7_config_t *wls_pnf_p7_config = NULL; + +void wls_pnf_set_p7_config(void *p7_config) +{ + wls_pnf_p7_config = (nfapi_pnf_p7_config_t *)p7_config; +} + +static WLS_MAC_CTX g_phy_wls; +uint8_t phy_dpdk_init(void); +uint8_t phy_wls_init(const char *dev_name, uint64_t nWlsMacMemSize, uint64_t nWlsPhyMemSize); +void phy_mac_recv(); +void wls_mac_print_stats(void); + +pnf_t *_this = NULL; + +static PWLS_MAC_CTX wls_mac_get_ctx(void) +{ + return &g_phy_wls; +} + +static nfapi_pnf_config_t *cfg; + +void *wls_fapi_pnf_nr_start_thread(void *ptr) +{ + NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] IN WLS PNF NFAPI start thread %s\n", __FUNCTION__); + cfg = (nfapi_pnf_config_t *)ptr; + wls_fapi_nr_pnf_start(); + return (void *)0; +} + +int wls_fapi_nr_pnf_start() +{ + int64_t ret; + // Verify that config is not null + if (cfg == 0) + return -1; + + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__); + + _this = (pnf_t *)(cfg); + _this->terminate = 0; + // Init PNF config + nfapi_pnf_phy_config_t *phy = (nfapi_pnf_phy_config_t *)malloc(sizeof(nfapi_pnf_phy_config_t)); + memset(phy, 0, sizeof(nfapi_pnf_phy_config_t)); + + phy->state = NFAPI_PNF_PHY_IDLE; + phy->phy_id = 0; + phy->next = (_this->_public).phys; + (_this->_public).phys = phy; + _this->_public.state = NFAPI_PNF_RUNNING; + + // DPDK init + ret = phy_dpdk_init(); + if (!ret) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "[PNF] DPDK Init - Failed\n"); + return false; + } + NFAPI_TRACE(NFAPI_TRACE_INFO, "\n[PHY] DPDK Init - Done\n"); + + // WLS init + ret = phy_wls_init(WLS_DEV_NAME, WLS_MAC_MEMORY_SIZE, WLS_PHY_MEMORY_SIZE); + if (!ret) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "[PNF] WLS Init - Failed\n"); + return false; + } + NFAPI_TRACE(NFAPI_TRACE_INFO, "\n[PHY] WLS Init - Done\n"); + + // Start Receiving loop from the VNF + NFAPI_TRACE(NFAPI_TRACE_INFO, "Start Receiving loop from the VNF\n"); + phy_mac_recv(); + // Should never get here, to be removed, align with present implementation of PNF loop + NFAPI_TRACE(NFAPI_TRACE_INFO, "\n[PHY] Exiting...\n"); + + return true; +} + +uint8_t phy_dpdk_init(void) +{ + unsigned long i; + char *argv[] = {"OAI_PNF", "--proc-type=primary", "--file-prefix", WLS_DEV_NAME, "--iova-mode=pa", "--no-pci"}; + int argc = RTE_DIM(argv); + /* initialize EAL first */ + NFAPI_TRACE(NFAPI_TRACE_INFO, "\n[PHY] Calling rte_eal_init: "); + + for (i = 0; i < RTE_DIM(argv); i++) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s ", argv[i]); + } + + NFAPI_TRACE(NFAPI_TRACE_INFO, "\n"); + + if (rte_eal_init(argc, argv) < 0) + rte_panic("Cannot init EAL\n"); + + return true; +} + +uint8_t phy_wls_init(const char *dev_name, uint64_t nWlsMacMemSize, uint64_t nWlsPhyMemSize) +// uint8_t phy_wls_init(const char *dev_name, uint64_t nBlockSize) +{ + PWLS_MAC_CTX pWls = wls_mac_get_ctx(); + pWls->nTotalAllocCnt = 0; + pWls->nTotalFreeCnt = 0; + pWls->nTotalUlBufAllocCnt = 0; + pWls->nTotalUlBufFreeCnt = 0; + pWls->nTotalDlBufAllocCnt = 0; + pWls->nTotalDlBufFreeCnt = 0; + + pWls->hWls = WLS_Open(dev_name, WLS_SLAVE_CLIENT, &nWlsMacMemSize, &nWlsPhyMemSize); + if (pWls->hWls) { + /* allocate chuck of memory */ + if (WLS_Alloc(pWls->hWls, nWlsMacMemSize + nWlsPhyMemSize) != NULL) { + NFAPI_TRACE(NFAPI_TRACE_DEBUG, "WLS Memory allocated successfully\n"); + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unable to alloc WLS Memory\n"); + return false; + } + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "can't open WLS instance"); + return false; + } + return true; +} + +bool wls_pnf_nr_send_p5_message(pnf_t *pnf, nfapi_nr_p4_p5_message_header_t *msg, uint32_t msg_len) +{ + int packed_len = cfg->pack_func(msg, msg_len, pnf->tx_message_buffer, sizeof(pnf->tx_message_buffer), &pnf->_public.codec_config); + + if (packed_len < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi_p5_message_pack failed (%d)\n", packed_len); + return false; + } + + NFAPI_TRACE(NFAPI_TRACE_DEBUG, "fapi_nr_p5_message_pack succeeded having packed %d bytes\n", packed_len); + NFAPI_TRACE(NFAPI_TRACE_DEBUG, "in msg, msg_len is %d\n", msg->message_length); + PWLS_MAC_CTX pWls = wls_mac_get_ctx(); + + + return wls_send_fapi_msg(pWls, msg->message_id, packed_len, pnf->tx_message_buffer); +} + +bool wls_pnf_nr_send_p7_message(pnf_p7_t *pnf_p7, nfapi_nr_p7_message_header_t *msg, uint32_t msg_len) +{ + UNUSED_VARIABLE(msg_len); + + if (!isFAPIMessageIDValid(msg->message_id)) { + return false; + } + + // if it's an nFAPI message, ignore + if ((msg->message_id == NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC || msg->message_id == NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC + || msg->message_id == NFAPI_NR_PHY_MSG_TYPE_TIMING_INFO)) { + return false; + } + + PWLS_MAC_CTX pWls = wls_mac_get_ctx(); + int num_avail_blocks = WLS_NumBlocks(pWls->hWls); + NFAPI_TRACE(NFAPI_TRACE_DEBUG, "num_avail_blocks is %d\n", num_avail_blocks); + while (num_avail_blocks < 2) { + num_avail_blocks = WLS_NumBlocks(pWls->hWls); + NFAPI_TRACE(NFAPI_TRACE_DEBUG, "num_avail_blocks is %d\n", num_avail_blocks); + } + /* get PA blocks for header and msg */ + const uint64_t pa_hdr = dequeueBlock(pWls); + AssertFatal(pa_hdr, "WLS_DequeueBlock failed for pa_hdr\n"); + const uint64_t pa_msg = dequeueBlock(pWls); + AssertFatal(pa_msg, "WLS_DequeueBlock failed for pa_msg\n"); + p_fapi_api_queue_elem_t headerElem = WLS_PA2VA(pWls->hWls, pa_hdr); + AssertFatal(headerElem, "WLS_PA2VA failed for headerElem\n"); + p_fapi_api_queue_elem_t fapiMsgElem = WLS_PA2VA(pWls->hWls, pa_msg); + AssertFatal(fapiMsgElem, "WLS_PA2VA failed for fapiMsgElem\n"); + const uint8_t wls_header[] = {1, 0}; // num_messages , opaque_handle + fill_fapi_list_elem(headerElem, fapiMsgElem, FAPI_VENDOR_MSG_HEADER_IND, 1, 2); + memcpy((uint8_t *)(headerElem + 1), wls_header, 2); + + const int packed_len = ((nfapi_pnf_p7_config_t *)pnf_p7)->pack_func(msg, (fapiMsgElem + 1), NFAPI_MAX_PACKED_MESSAGE_SIZE, NULL); + + if (packed_len < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi_p7_message_pack failed (%d)\n", packed_len); + return false; + } + fill_fapi_list_elem(fapiMsgElem, NULL, msg->message_id, 1, packed_len + NFAPI_HEADER_LENGTH); + const uint8_t retval = wls_msg_send(pWls->hWls, headerElem); + return retval; +} + +static void procPhyMessages(uint32_t msg_size, void *msg_buf, uint16_t msg_id) +{ + + NFAPI_TRACE(NFAPI_TRACE_DEBUG, "[PHY] Received Msg ID 0x%02x Length %d\n", msg_id, msg_size); + if (msg_buf == NULL || _this == NULL) { + AssertFatal(msg_buf != NULL && _this != NULL, "%s: NULL parameters\n", __FUNCTION__); + } + // Add the size of the header to the message_size, because the size in the header does not include the header length + msg_size += NFAPI_NR_P5_HEADER_LENGTH; + switch (msg_id) { + case NFAPI_NR_PHY_MSG_TYPE_PARAM_REQUEST ... NFAPI_NR_PHY_MSG_TYPE_STOP_REQUEST: + pnf_nr_handle_p5_message(_this, msg_buf, msg_size); + break; + case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST ... NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: { + pnf_nr_handle_p7_message(msg_buf, msg_size, (pnf_p7_t *)wls_pnf_p7_config, 0); + break; + } + default: + printf("\n Unknown Msg ID 0x%02x\n", msg_id); + break; + } +} + +void phy_mac_recv() +{ + /* Number of Memory blocks to get */ + uint32_t msgSize; + uint16_t msgType; + uint16_t flags; + PWLS_MAC_CTX pWls = wls_mac_get_ctx(); + // This flag is used to determine whether to return the received blocks to the PNF + bool to_return = false; + while (_this->terminate == 0) { + int numMsgToGet = WLS_Wait(pWls->hWls); + if (numMsgToGet == 0) { + continue; + } + uint64_t PAs[numMsgToGet]; + uint8_t pa_idx = 0; + while (numMsgToGet--) { + PAs[pa_idx] = WLS_Get(pWls->hWls, &msgSize, &msgType, &flags); + pa_idx++; + } + for (int i = 0; i < pa_idx; i++) { + p_fapi_api_queue_elem_t msg = WLS_PA2VA(pWls->hWls, PAs[i]); + if (msg->msg_type != FAPI_VENDOR_MSG_HEADER_IND) { + uint8_t *msgt = (uint8_t *)(msg + 1); + uint32_t len = msgt[7] | (msgt[6] << 8) | (msgt[5] << 16) | (msgt[4] << 24); + procPhyMessages(len, (void *)(msg + 1), msg->msg_type); + } else { + // We check the header block to determine if it's the OAI VNF, if so, we're required to return the pages for enqueueing + if (!to_return) { + uint8_t *msgt = (uint8_t *)(msg + 1); + if (msgt[1] == 0xff) { + to_return = true; + } + } + } + } + if (to_return) { + // We only return the pages to be enqueued in case we're using the OAI VNF, + // The Radisys O-DU handles enqueueing the blocks differently, and also doesn't handle receiving a single block + for (int i = 0; i < pa_idx; i++) { + wls_return_msg_to_master(pWls, PAs[i]); + } + } + } +} diff --git a/nfapi/open-nFAPI/fapi/CMakeLists.txt b/nfapi/open-nFAPI/fapi/CMakeLists.txt index a97f5f6e6f..cf7f85052f 100644 --- a/nfapi/open-nFAPI/fapi/CMakeLists.txt +++ b/nfapi/open-nFAPI/fapi/CMakeLists.txt @@ -23,4 +23,8 @@ if (OAI_AERIAL) target_compile_definitions(nr_fapi_p7 PRIVATE ENABLE_AERIAL) endif () -target_compile_definitions(nr_fapi_common PRIVATE ENABLE_SOCKET) +if(OAI_WLS) + target_compile_definitions(nr_fapi_common PRIVATE ENABLE_WLS) +else() + target_compile_definitions(nr_fapi_common PRIVATE ENABLE_SOCKET) +endif() diff --git a/nfapi/open-nFAPI/fapi/inc/nr_fapi.h b/nfapi/open-nFAPI/fapi/inc/nr_fapi.h index fcf4b97973..e71e1bae5c 100644 --- a/nfapi/open-nFAPI/fapi/inc/nr_fapi.h +++ b/nfapi/open-nFAPI/fapi/inc/nr_fapi.h @@ -77,12 +77,34 @@ bool isFAPIMessageIDValid(uint16_t id); int check_nr_fapi_unpack_length(nfapi_nr_phy_msg_type_e msgId, uint32_t unpackedBufLen); -int fapi_nr_message_header_unpack(void *pMessageBuf, +/*! \brief Decodes a FAPI P5 message header + * \param pMessageBuf A pointer to an encoded P5 message header + * \param messageBufLen The size of the encoded P5 message header + * \param pUnpackedBuf A pointer to the fapi_message_header + * \param unpackedBufLen The size of fapi_message_header structure. + * \param config A pointer to the nfapi configuration structure + * \return true on success, false on failure. + * + * The function will decode a byte stream pointed to by pMessageBuf into a FAPI p5 header structure pointed to by pUnpackedBuf + */ +bool fapi_nr_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t *config); -int fapi_nr_p7_message_header_unpack(void *pMessageBuf, + +/*! \brief Decodes a FAPI P7 message header + * \param pMessageBuf A pointer to an encoded P5 message header + * \param messageBufLen The size of the encoded P5 message header + * \param pUnpackedBuf A pointer to the fapi_message_header + * \param unpackedBufLen The size of fapi_message_header structure. + * \param config A pointer to the nfapi configuration structure + * \return true on success, false on failure. + * + * This function is a dummy function that points to fapi_nr_message_header_unpack, + * since in FAPI there's no difference in the structure of the message headers for P5 and P7 + */ +bool fapi_nr_p7_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, diff --git a/nfapi/open-nFAPI/fapi/inc/nr_fapi_p5.h b/nfapi/open-nFAPI/fapi/inc/nr_fapi_p5.h index 307b5bad27..d47f0ec929 100644 --- a/nfapi/open-nFAPI/fapi/inc/nr_fapi_p5.h +++ b/nfapi/open-nFAPI/fapi/inc/nr_fapi_p5.h @@ -30,7 +30,7 @@ int fapi_nr_p5_message_pack(void *pMessageBuf, uint32_t packedBufLen, nfapi_p4_p5_codec_config_t *config); -int fapi_nr_p5_message_unpack(void *pMessageBuf, +bool fapi_nr_p5_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, diff --git a/nfapi/open-nFAPI/fapi/inc/nr_fapi_p5_utils.h b/nfapi/open-nFAPI/fapi/inc/nr_fapi_p5_utils.h index 77ed67e2ef..8ef5fbade2 100644 --- a/nfapi/open-nFAPI/fapi/inc/nr_fapi_p5_utils.h +++ b/nfapi/open-nFAPI/fapi/inc/nr_fapi_p5_utils.h @@ -23,7 +23,7 @@ #define OPENAIRINTERFACE_NR_FAPI_P5_UTILS_H #include "stdio.h" #include "stdint.h" -#include "nr_fapi.h" +#include "nfapi/open-nFAPI/fapi/inc/nr_fapi.h" #include "nfapi/oai_integration/vendor_ext.h" bool eq_param_request(const nfapi_nr_param_request_scf_t *unpacked_req, const nfapi_nr_param_request_scf_t *req); diff --git a/nfapi/open-nFAPI/fapi/inc/nr_fapi_p7.h b/nfapi/open-nFAPI/fapi/inc/nr_fapi_p7.h index c2701acb5f..80b39f7386 100644 --- a/nfapi/open-nFAPI/fapi/inc/nr_fapi_p7.h +++ b/nfapi/open-nFAPI/fapi/inc/nr_fapi_p7.h @@ -23,7 +23,7 @@ int fapi_nr_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen, nfapi_p7_codec_config_t *config); -int fapi_nr_p7_message_unpack(void *pMessageBuf, +bool fapi_nr_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, diff --git a/nfapi/open-nFAPI/fapi/inc/nr_fapi_p7_utils.h b/nfapi/open-nFAPI/fapi/inc/nr_fapi_p7_utils.h index f915548783..5c1df2dcef 100644 --- a/nfapi/open-nFAPI/fapi/inc/nr_fapi_p7_utils.h +++ b/nfapi/open-nFAPI/fapi/inc/nr_fapi_p7_utils.h @@ -33,7 +33,7 @@ #define OPENAIRINTERFACE_NR_FAPI_P7_UTILS_H #include "stdio.h" #include "stdint.h" -#include "nr_fapi.h" +#include "nfapi/open-nFAPI/fapi/inc/nr_fapi.h" bool eq_dl_tti_request(const nfapi_nr_dl_tti_request_t *a, const nfapi_nr_dl_tti_request_t *b); bool eq_ul_tti_request(const nfapi_nr_ul_tti_request_t *a, const nfapi_nr_ul_tti_request_t *b); diff --git a/nfapi/open-nFAPI/fapi/src/nr_fapi.c b/nfapi/open-nFAPI/fapi/src/nr_fapi.c index 475b6c07dd..4da483db17 100644 --- a/nfapi/open-nFAPI/fapi/src/nr_fapi.c +++ b/nfapi/open-nFAPI/fapi/src/nr_fapi.c @@ -54,7 +54,6 @@ bool isFAPIMessageIDValid(const uint16_t id) int check_nr_fapi_unpack_length(nfapi_nr_phy_msg_type_e msgId, uint32_t unpackedBufLen) { int retLen = 0; - // check for size of nFAPI struct without the nFAPI specific parameters switch (msgId) { case NFAPI_NR_PHY_MSG_TYPE_PARAM_REQUEST: @@ -165,7 +164,7 @@ int check_nr_fapi_unpack_length(nfapi_nr_phy_msg_type_e msgId, uint32_t unpacked return retLen; } -int fapi_nr_p7_message_header_unpack(void *pMessageBuf, +bool fapi_nr_p7_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, @@ -178,7 +177,7 @@ int fapi_nr_p7_message_header_unpack(void *pMessageBuf, NULL); } -int fapi_nr_message_header_unpack(void *pMessageBuf, +bool fapi_nr_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, @@ -190,12 +189,12 @@ int fapi_nr_message_header_unpack(void *pMessageBuf, if (pMessageBuf == NULL || pUnpackedBuf == NULL || messageBufLen < NFAPI_HEADER_LENGTH || unpackedBufLen < sizeof(fapi_message_header_t)) { - return -1; + return false; } uint8_t *end = pMessageBuf + messageBufLen; // process the header int result = (pull8(&pReadPackedMessage, &fapi_msg.num_msg, end) && pull8(&pReadPackedMessage, &fapi_msg.opaque_handle, end) && pull16(&pReadPackedMessage, &header->message_id, end) && pull32(&pReadPackedMessage, &header->message_length, end)); - return (result); + return result != 0; } diff --git a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c index 554898cbd4..9339a666a3 100644 --- a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c +++ b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c @@ -128,7 +128,7 @@ int fapi_nr_p5_message_pack(void *pMessageBuf, return packedMsgLen; } -int fapi_nr_p5_message_unpack(void *pMessageBuf, +bool fapi_nr_p5_message_unpack(void *pMessageBuf, const uint32_t messageBufLen, void *pUnpackedBuf, const uint32_t unpackedBufLen, @@ -143,10 +143,9 @@ int fapi_nr_p5_message_unpack(void *pMessageBuf, unpackedBufLen); // clean the supplied buffer for - tag value blanking (void)memset(pUnpackedBuf, 0, unpackedBufLen); - if (fapi_nr_message_header_unpack(pMessageBuf, NFAPI_HEADER_LENGTH, pMessageHeader, sizeof(fapi_message_header_t), 0) - < 0) { + if (!fapi_nr_message_header_unpack(pMessageBuf, NFAPI_HEADER_LENGTH, pMessageHeader, sizeof(fapi_message_header_t), 0)) { // failed to read the header - return -1; + return false; } uint8_t *pReadPackedMessage = pMessageBuf + NFAPI_HEADER_LENGTH; uint8_t *end = (uint8_t *)pMessageBuf + messageBufLen; @@ -154,14 +153,14 @@ int fapi_nr_p5_message_unpack(void *pMessageBuf, if (check_nr_fapi_unpack_length(pMessageHeader->message_id, unpackedBufLen) == 0) { // the unpack buffer is not big enough for the struct - return -1; + return false; } // look for the specific message switch (pMessageHeader->message_id) { case NFAPI_NR_PHY_MSG_TYPE_PARAM_REQUEST: // PARAM request has no body; - result = 0; + result = 1; break; case NFAPI_NR_PHY_MSG_TYPE_PARAM_RESPONSE: @@ -209,7 +208,7 @@ int fapi_nr_p5_message_unpack(void *pMessageBuf, break; } - return result; + return result != 0; } uint8_t pack_nr_param_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) diff --git a/nfapi/open-nFAPI/fapi/src/nr_fapi_p7.c b/nfapi/open-nFAPI/fapi/src/nr_fapi_p7.c index 4f73e4596c..4945e6da45 100644 --- a/nfapi/open-nFAPI/fapi/src/nr_fapi_p7.c +++ b/nfapi/open-nFAPI/fapi/src/nr_fapi_p7.c @@ -134,7 +134,7 @@ int fapi_nr_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packed return packedMsgLen; } -int fapi_nr_p7_message_unpack(void *pMessageBuf, +bool fapi_nr_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, @@ -150,9 +150,9 @@ int fapi_nr_p7_message_unpack(void *pMessageBuf, messageBufLen, unpackedBufLen); - if (fapi_nr_message_header_unpack(pMessageBuf, NFAPI_HEADER_LENGTH, &fapi_hdr, sizeof(fapi_message_header_t), 0) < 0) { + if (!fapi_nr_message_header_unpack(pMessageBuf, NFAPI_HEADER_LENGTH, &fapi_hdr, sizeof(fapi_message_header_t), 0)) { // failed to read the header - return -1; + return false; } uint8_t *pReadPackedMessage = pMessageBuf + NFAPI_HEADER_LENGTH; uint8_t *end = (uint8_t *)pMessageBuf + messageBufLen; @@ -160,7 +160,7 @@ int fapi_nr_p7_message_unpack(void *pMessageBuf, pMessageHeader->message_id = fapi_hdr.message_id; if ((uint8_t *)(pMessageBuf + pMessageHeader->message_length) > end) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack message length is greater than the message buffer \n"); - return -1; + return false; } // look for the specific message @@ -231,9 +231,9 @@ int fapi_nr_p7_message_unpack(void *pMessageBuf, if (result == 0) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Unpack failed to unpack message\n"); - return -1; + return false; } - return 0; + return true; } static uint8_t pack_nr_tx_beamforming_pdu(const nfapi_nr_tx_precoding_and_beamforming_t *beamforming_pdu, diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h index 3cfd0591fc..d146408abf 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h @@ -28,8 +28,11 @@ #define NFAPI_PNF_PARAM_GENERAL_OUI_LENGTH 3 #define NFAPI_MAX_NUM_RF_BANDS 16 +#ifdef ENABLE_WLS +#define NFAPI_MAX_PACKED_MESSAGE_SIZE 1024*1024*2 +#else #define NFAPI_MAX_PACKED_MESSAGE_SIZE 32768 - +#endif // The following definition control the size of arrays used in the interface. // These may be changed if desired. They are used in the encoder to make sure // that the user has not specified a 'count' larger than the max array, and also diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c index f7c55cd2e0..e75e418500 100644 --- a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c @@ -6206,6 +6206,10 @@ bool peek_nr_nfapi_p7_sfn_slot(void *pMessageBuf, uint32_t messageBufLen, uint16 #ifdef ENABLE_SOCKET // Socket transport will always use nFAPI encoding uint8_t *pReadPackedMessage = &((uint8_t *)pMessageBuf)[NFAPI_NR_P7_HEADER_LENGTH]; +#endif +#ifdef ENABLE_WLS + // WLS transport will always use FAPI encoding + uint8_t *pReadPackedMessage = &((uint8_t *)pMessageBuf)[NFAPI_HEADER_LENGTH]; #endif uint8_t *end = (uint8_t*)pMessageBuf + messageBufLen; if(!(pull16(&pReadPackedMessage, SFN, end) && pull16(&pReadPackedMessage, Slot, end))) { diff --git a/nfapi/open-nFAPI/pnf/inc/pnf.h b/nfapi/open-nFAPI/pnf/inc/pnf.h index 968359dfee..2dc2ce9de6 100644 --- a/nfapi/open-nFAPI/pnf/inc/pnf.h +++ b/nfapi/open-nFAPI/pnf/inc/pnf.h @@ -20,7 +20,6 @@ #include "nfapi_pnf_interface.h" -#define NFAPI_MAX_PACKED_MESSAGE_SIZE 32768 struct pnf_t { @@ -46,5 +45,15 @@ int pnf_send_message(pnf_t* pnf, uint8_t* msg, uint32_t msg_len, uint16_t stream nfapi_pnf_phy_config_t* nfapi_pnf_phy_config_find(nfapi_pnf_config_t* config, uint16_t phy_id); +void pnf_nr_handle_pnf_param_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen); +void pnf_nr_handle_pnf_config_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen); +void pnf_nr_handle_pnf_start_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen); +void pnf_handle_pnf_stop_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen); +void pnf_nr_handle_param_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen); +void pnf_nr_handle_config_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen); +void pnf_nr_handle_start_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen); +void pnf_nr_handle_stop_request(pnf_t* pnf, void* pRecvMsg, int recvMsgLen); + + #endif // _PNF_H_ diff --git a/nfapi/open-nFAPI/pnf/inc/pnf_p7.h b/nfapi/open-nFAPI/pnf/inc/pnf_p7.h index 49868bde8d..5805e07445 100644 --- a/nfapi/open-nFAPI/pnf/inc/pnf_p7.h +++ b/nfapi/open-nFAPI/pnf/inc/pnf_p7.h @@ -25,7 +25,6 @@ #include "nfapi_pnf_interface.h" -#define NFAPI_MAX_PACKED_MESSAGE_SIZE 32768 typedef struct { uint16_t dl_conf_ontime; diff --git a/nfapi/open-nFAPI/pnf/src/pnf.c b/nfapi/open-nFAPI/pnf/src/pnf.c index fd572cf77f..1c851ce277 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf.c +++ b/nfapi/open-nFAPI/pnf/src/pnf.c @@ -49,7 +49,9 @@ #include "NR_MIB.h" #include "openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h" - +#ifdef ENABLE_WLS +#include "wls_integration/include/wls_pnf.h" +#endif #endif #define MAX_SCTP_STREAMS 16 diff --git a/nfapi/open-nFAPI/utils/nfapi_hex_parser.c b/nfapi/open-nFAPI/utils/nfapi_hex_parser.c index 342492ba92..a037f1221e 100644 --- a/nfapi/open-nFAPI/utils/nfapi_hex_parser.c +++ b/nfapi/open-nFAPI/utils/nfapi_hex_parser.c @@ -281,10 +281,9 @@ int main(int argc, char *argv[]) printf("\n"); AssertFatal(byte_count >= sizeof(fapi_message_header_t), "Read byte amount not enough to encode the header. Should have a minimum of %lu bytes, aborting...", sizeof(fapi_message_header_t)); uint8_t *ptr = hex_values; // Points to the first element of the array - uint8_t **msg_ptr = &ptr; // Pointer to the pointer fapi_message_header_t hdr = {.num_msg = 0, .opaque_handle = 0, .message_id = 0, .message_length = 0}; - fapi_nr_message_header_unpack(msg_ptr, NFAPI_HEADER_LENGTH, &hdr, sizeof(fapi_message_header_t), 0); + fapi_nr_message_header_unpack(ptr, NFAPI_HEADER_LENGTH, &hdr, sizeof(fapi_message_header_t), 0); printf("Decoded message %s message length 0x%02x\n", message_id_to_str(hdr.message_id), hdr.message_length); // Unpack the message diff --git a/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h b/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h index 54754fce05..b98a91e2ac 100644 --- a/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h +++ b/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h @@ -33,7 +33,6 @@ extern "C" { typedef struct vnf_t vnf_t; typedef struct vnf_p7_t vnf_p7_t; -#define NFAPI_MAX_PACKED_MESSAGE_SIZE 32768 /*! The nfapi VNF phy configuration information */ From 6d05d279b029acc6d1327e24b2e02efc3fc37779 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Soares=20Silva?= Date: Wed, 30 Oct 2024 09:12:51 +0000 Subject: [PATCH 207/964] Implementation of VNF using WLS as message transport Add check to vnf_nr_handle_param_response for when phy_info is not found The WLS VNF is in charge of Enqueueing the used blocks after usage for transport, this is done by keeping track of all blocks used, and calling WLS_Enqueue for all of them upon receiving a SLOT.indication --- CMakeLists.txt | 3 + nfapi/oai_integration/nfapi_vnf.c | 29 +- .../wls_integration/CMakeLists.txt | 1 + .../wls_integration/include/wls_vnf.h | 33 ++ .../oai_integration/wls_integration/wls_vnf.c | 418 ++++++++++++++++++ nfapi/open-nFAPI/vnf/src/vnf.c | 55 +-- nfapi/open-nFAPI/vnf/src/vnf_interface.c | 3 +- nfapi/open-nFAPI/vnf/src/vnf_p7.c | 3 + 8 files changed, 514 insertions(+), 31 deletions(-) create mode 100644 nfapi/oai_integration/wls_integration/include/wls_vnf.h create mode 100644 nfapi/oai_integration/wls_integration/wls_vnf.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 123d08c3bc..bfe13b9351 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -754,6 +754,9 @@ endif() include_directories(${NFAPI_DIR}/vnf/public_inc) include_directories(${NFAPI_DIR}/vnf/inc) +if(OAI_WLS) + target_compile_definitions(NFAPI_VNF_LIB PRIVATE ENABLE_WLS) +endif() # nFAPI user defined code ############################# set(NFAPI_USER_SRC diff --git a/nfapi/oai_integration/nfapi_vnf.c b/nfapi/oai_integration/nfapi_vnf.c index 571fe7d55d..582c7b374a 100644 --- a/nfapi/oai_integration/nfapi_vnf.c +++ b/nfapi/oai_integration/nfapi_vnf.c @@ -36,12 +36,15 @@ #include "nfapi_vnf.h" #include #include +#ifdef ENABLE_WLS +#include +#include "nr_fapi_p5.h" +#include "nr_fapi_p7.h" +#endif #ifdef ENABLE_SOCKET #include #endif -#include -#include #include "nfapi.h" #include "vendor_ext.h" @@ -1450,6 +1453,13 @@ void *configure_nr_p7_vnf(void *ptr) p7_vnf->config->unpack_func = &nfapi_nr_p7_message_unpack; p7_vnf->config->hdr_unpack_func = &nfapi_nr_p7_message_header_unpack; p7_vnf->config->pack_func = &nfapi_nr_p7_message_pack; +#ifdef ENABLE_WLS + p7_vnf->config->unpack_func = &fapi_nr_p7_message_unpack; + p7_vnf->config->hdr_unpack_func = &fapi_nr_p7_message_header_unpack; + p7_vnf->config->pack_func = &fapi_nr_p7_message_pack; + p7_vnf->config->send_p7_msg = &wls_vnf_nr_send_p7_message; + wls_vnf_set_p7_config(p7_vnf->config); +#endif #ifdef ENABLE_SOCKET p7_vnf->config->unpack_func = &nfapi_nr_p7_message_unpack; @@ -1516,7 +1526,9 @@ int pnf_nr_start_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_nr_pnf_st NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Sending NFAPI_VNF_PARAM_REQUEST phy_id:%d\n", pnf->phys[0].id); memset(&req, 0, sizeof(req)); req.header.message_id = NFAPI_NR_PHY_MSG_TYPE_PARAM_REQUEST; - +#ifdef ENABLE_WLS + req.header.phy_id = 0; +#endif #ifdef ENABLE_SOCKET req.header.phy_id = pnf->phys[0].id; #endif @@ -1867,6 +1879,17 @@ void configure_nr_nfapi_vnf(char *vnf_addr, int vnf_p5_port, char *pnf_ip_addr, config->codec_config.deallocate = &vnf_nr_deallocate; memset(&UL_RCC_INFO, 0, sizeof(UL_RCC_IND_t)); +#ifdef ENABLE_WLS + config->unpack_func = &fapi_nr_p5_message_unpack; + config->hdr_unpack_func = &fapi_nr_message_header_unpack; + config->pack_func = &fapi_nr_p5_message_pack; + config->send_p5_msg = &wls_vnf_nr_send_p5_message; + printf("WLS MODE PNF\n"); + NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] Creating WLS VNF NFAPI start thread %s\n", __FUNCTION__); + //wls_fapi_pnf_nr_start_thread(config); + threadCreate(&vnf_p5_init_and_receive_pthread, wls_fapi_vnf_nr_start_thread, config, "NFAPI_WLS_VNF", -1, OAI_PRIORITY_RT_MAX); +#endif + #ifdef ENABLE_SOCKET config->unpack_func = &nfapi_nr_p5_message_unpack; config->hdr_unpack_func = &nfapi_nr_p5_message_header_unpack; diff --git a/nfapi/oai_integration/wls_integration/CMakeLists.txt b/nfapi/oai_integration/wls_integration/CMakeLists.txt index 0a217dd5b6..6d225f18b8 100644 --- a/nfapi/oai_integration/wls_integration/CMakeLists.txt +++ b/nfapi/oai_integration/wls_integration/CMakeLists.txt @@ -1,6 +1,7 @@ message(STATUS "Building with support for WLS") add_library(wls_integration_lib wls_pnf.c + wls_vnf.c wls_common.c ) diff --git a/nfapi/oai_integration/wls_integration/include/wls_vnf.h b/nfapi/oai_integration/wls_integration/include/wls_vnf.h new file mode 100644 index 0000000000..645b24d056 --- /dev/null +++ b/nfapi/oai_integration/wls_integration/include/wls_vnf.h @@ -0,0 +1,33 @@ +/* +* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef OPENAIRINTERFACE_WLS_VNF_H +#define OPENAIRINTERFACE_WLS_VNF_H +#include "nfapi_vnf_interface.h" +#include "vnf.h" +#include "wls_common.h" + +void *wls_fapi_vnf_nr_start_thread(void *ptr); +int wls_fapi_nr_vnf_start(); +void wls_vnf_set_p7_config(void *p7_config); +bool wls_vnf_nr_send_p5_message(vnf_t *vnf,uint16_t p5_idx, nfapi_nr_p4_p5_message_header_t* msg, uint32_t msg_len); +bool wls_vnf_nr_send_p7_message(vnf_p7_t* vnf_p7,nfapi_nr_p7_message_header_t* msg); +#endif //OPENAIRINTERFACE_WLS_VNF_H diff --git a/nfapi/oai_integration/wls_integration/wls_vnf.c b/nfapi/oai_integration/wls_integration/wls_vnf.c new file mode 100644 index 0000000000..ccc68b4905 --- /dev/null +++ b/nfapi/oai_integration/wls_integration/wls_vnf.c @@ -0,0 +1,418 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ +#include "wls_vnf.h" + +#include "vnf_p7.h" + +#include +#include +#include +#include +#include +#include +#include + +static nfapi_vnf_config_t *config; +static WLS_MAC_CTX wls_mac_iface; +vnf_t *_vnf = NULL; +// A copy of the VNF P7 config is needed for the message processing thread, in other transport mechanisms where P7 is handled in a +// different thread, the config is passed to it upon the thread creation +nfapi_vnf_p7_config_t *wls_vnf_p7_config = NULL; + +void wls_vnf_set_p7_config(void *p7_config) +{ + wls_vnf_p7_config = (nfapi_vnf_p7_config_t *)p7_config; +} + +static PWLS_MAC_CTX wls_mac_get_ctx(void) +{ + return &wls_mac_iface; +} + +static uint8_t alloc_track[ALLOC_TRACK_SIZE]; +//------------------------------------------------------------------------------------------- +/** @ingroup group_testmac + * + * @param[in] pMemArray Pointer to WLS Memory management structure + * @param[in] pMemArrayMemory Pointer to flat buffer that was allocated + * @param[in] totalSize Total Size of flat buffer allocated + * @param[in] nBlockSize Size of each block that needs to be partitioned by memory manager + * + * @return 0 if SUCCESS + * + * @description + * This function creates memory blocks from a flat buffer which will be used for communciation + * between MAC and PHY + * + **/ +//------------------------------------------------------------------------------------------- +static bool wls_mac_create_mem_array(PWLS_MAC_MEM_SRUCT pMemArray, void *pMemArrayMemory, uint32_t totalSize, uint32_t nBlockSize) +{ + const uint32_t numBlocks = totalSize / nBlockSize; + + printf("wls_mac_create_mem_array: pMemArray[%p] pMemArrayMemory[%p] totalSize[%d] nBlockSize[%d] numBlocks[%d]\n", + pMemArray, + pMemArrayMemory, + totalSize, + nBlockSize, + numBlocks); + AssertFatal(nBlockSize >= sizeof(void *), "WLS nBlockSize too small"); + AssertFatal(totalSize > sizeof(void *), "WLS Can't allocate less than 1 block"); + pMemArray->ppFreeBlock = (void **)pMemArrayMemory; + pMemArray->pStorage = pMemArrayMemory; + pMemArray->pEndOfStorage = ((unsigned long *)pMemArrayMemory) + numBlocks * nBlockSize / sizeof(unsigned long); + pMemArray->nBlockSize = nBlockSize; + pMemArray->nBlockCount = numBlocks; + + // Initialize single-linked list of free blocks; + void **ptr = (void **)pMemArrayMemory; + for (uint32_t i = 0; i < pMemArray->nBlockCount; i++) { + if (i == pMemArray->nBlockCount - 1) { + *ptr = NULL; // End of list + } else { + // Points to the next block + *ptr = (void **)(((uint8_t *)ptr) + nBlockSize); + ptr += nBlockSize / sizeof(unsigned long); + } + } + + memset(alloc_track, 0, sizeof(uint8_t) * ALLOC_TRACK_SIZE); + + return true; +} + +void mac_dpdk_init() +{ + char *my_argv[] = {"OAI_VNF", "-c3", "--proc-type=auto", "--file-prefix", WLS_DEV_NAME, "--iova-mode=pa"}; + printf("\nCalling rte_eal_init: "); + for (unsigned long i = 0; i < RTE_DIM(my_argv); i++) { + printf("%s ", my_argv[i]); + } + printf("\n"); + + if (rte_eal_init(RTE_DIM(my_argv), my_argv) < 0) + rte_panic("\nCannot init EAL\n"); +} + +static uint32_t wls_mac_alloc_mem_array(PWLS_MAC_MEM_SRUCT pMemArray, void **ppBlock) +{ + int idx; + + if (pMemArray->ppFreeBlock == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "wls_mac_alloc_mem_array pMemArray->ppFreeBlock = NULL\n"); + return 1; + } + + // FIXME: Remove after debugging + if (((void *)pMemArray->ppFreeBlock < pMemArray->pStorage) || ((void *)pMemArray->ppFreeBlock >= pMemArray->pEndOfStorage)) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, + "wls_mac_alloc_mem_array ERROR: Corrupted MemArray;Arr=%p,Stor=%p,Free=%p\n", + pMemArray, + pMemArray->pStorage, + pMemArray->ppFreeBlock); + return 1; + } + + pMemArray->ppFreeBlock = (void **)((unsigned long)pMemArray->ppFreeBlock & 0xFFFFFFFFFFFFFFF0); + *pMemArray->ppFreeBlock = (void **)((unsigned long)*pMemArray->ppFreeBlock & 0xFFFFFFFFFFFFFFF0); + + if ((*pMemArray->ppFreeBlock != NULL) + && (((*pMemArray->ppFreeBlock) < pMemArray->pStorage) || ((*pMemArray->ppFreeBlock) >= pMemArray->pEndOfStorage))) { + fprintf(stderr, + "ERROR: Corrupted MemArray;Arr=%p,Stor=%p,Free=%p,Curr=%p\n", + pMemArray, + pMemArray->pStorage, + pMemArray->ppFreeBlock, + *pMemArray->ppFreeBlock); + return 1; + } + + *ppBlock = (void *)pMemArray->ppFreeBlock; + pMemArray->ppFreeBlock = (void **)(*pMemArray->ppFreeBlock); + + idx = (((uint64_t)*ppBlock - (uint64_t)pMemArray->pStorage)) / pMemArray->nBlockSize; + if (alloc_track[idx]) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, + "wls_mac_alloc_mem_array Double alloc Arr=%p,Stor=%p,Free=%p,Curr=%p\n", + pMemArray, + pMemArray->pStorage, + pMemArray->ppFreeBlock, + *pMemArray->ppFreeBlock); + } else { + alloc_track[idx] = 1; + } + + return 0; +} + +void wls_mac_print_stats(void) +{ + PWLS_MAC_CTX pWls = wls_mac_get_ctx(); + + NFAPI_TRACE(NFAPI_TRACE_DEBUG, "wls_mac_free_list_all:\n"); + NFAPI_TRACE(NFAPI_TRACE_DEBUG, + " nTotalBlocks[%d] nAllocBlocks[%d] nFreeBlocks[%d]\n", + pWls->nTotalBlocks, + pWls->nAllocBlocks, + (pWls->nTotalBlocks - pWls->nAllocBlocks)); + NFAPI_TRACE(NFAPI_TRACE_DEBUG, + " nTotalAllocCnt[%d] nTotalFreeCnt[%d] Diff[%d]\n", + pWls->nTotalAllocCnt, + pWls->nTotalFreeCnt, + (pWls->nTotalAllocCnt - pWls->nTotalFreeCnt)); + NFAPI_TRACE(NFAPI_TRACE_DEBUG, + " nDlBufAllocCnt[%d] nDlBufFreeCnt[%d] Diff[%d]\n", + pWls->nTotalDlBufAllocCnt, + pWls->nTotalDlBufFreeCnt, + (pWls->nTotalDlBufAllocCnt - pWls->nTotalDlBufFreeCnt)); + NFAPI_TRACE(NFAPI_TRACE_DEBUG, + " nUlBufAllocCnt[%d] nUlBufFreeCnt[%d] Diff[%d]\n\n", + pWls->nTotalUlBufAllocCnt, + pWls->nTotalUlBufFreeCnt, + (pWls->nTotalUlBufAllocCnt - pWls->nTotalUlBufFreeCnt)); +} + +static void *wls_mac_alloc_buffer(PWLS_MAC_CTX pWls, uint32_t size, uint32_t loc) +{ + void *pBlock = NULL; + pthread_mutex_lock((pthread_mutex_t *)&pWls->lock_alloc); + if (wls_mac_alloc_mem_array(&pWls->sWlsStruct, &pBlock) != 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "wls_mac_alloc_buffer alloc error size[%d] loc[%d]\n", size, loc); + wls_mac_print_stats(); + pthread_mutex_unlock((pthread_mutex_t *)&pWls->lock_alloc); + return NULL; + } + pWls->nAllocBlocks++; + pWls->nTotalAllocCnt++; + if (loc < MAX_DL_BUF_LOCATIONS) + pWls->nTotalDlBufAllocCnt++; + else if (loc < MAX_UL_BUF_LOCATIONS) + pWls->nTotalUlBufAllocCnt++; + + pthread_mutex_unlock((pthread_mutex_t *)&pWls->lock_alloc); + + return pBlock; +} + +static bool mac_wls_init() +{ + uint64_t nWlsMacMemorySize = 0; + uint64_t nWlsPhyMemorySize = 0; + PWLS_MAC_CTX pWls = wls_mac_get_ctx(); + + pthread_mutex_init((pthread_mutex_t *)&pWls->lock, NULL); + pthread_mutex_init((pthread_mutex_t *)&pWls->lock_alloc, NULL); + + pWls->nTotalAllocCnt = 0; + pWls->nTotalFreeCnt = 0; + pWls->nTotalUlBufAllocCnt = 0; + pWls->nTotalUlBufFreeCnt = 0; + pWls->nTotalDlBufAllocCnt = 0; + pWls->nTotalDlBufFreeCnt = 0; + + /* Start by opening the WLS instance with WLS_MASTER_CLIENT */ + if ((pWls->hWls = WLS_Open(WLS_DEV_NAME, WLS_MASTER_CLIENT, &nWlsMacMemorySize, &nWlsPhyMemorySize)) == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "\nCould not open WLS Interface \n"); + return false; + } + + /* WLS_Open was successful, we can allocate memory */ + if ((pWls->pWlsMemBase = WLS_Alloc(pWls->hWls, nWlsMacMemorySize + nWlsPhyMemorySize)) == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "\nCould not allocate WLS Memory \n"); + return false; + } + /* Set the total memory that MAC has access to */ + pWls->nTotalMemorySize = nWlsMacMemorySize; + + /* Partition the WLS memory */ + memset(pWls->pWlsMemBase, 0xCC, pWls->nTotalMemorySize); + pWls->pPartitionMemBase = pWls->pWlsMemBase; + pWls->nPartitionMemSize = pWls->nTotalMemorySize; + pWls->nTotalBlocks = pWls->nTotalMemorySize / (NFAPI_MAX_PACKED_MESSAGE_SIZE); + /* Create the memory array */ + if (!wls_mac_create_mem_array(&pWls->sWlsStruct, pWls->pPartitionMemBase, pWls->nPartitionMemSize, NFAPI_MAX_PACKED_MESSAGE_SIZE)) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "\nCould not create WLS Memory Array \n"); + return false; + } + NFAPI_TRACE(NFAPI_TRACE_INFO, "\nTotalBlocks is %d \n", pWls->nTotalBlocks); +int nBlocks = 0; +for(int i = 0 ; i< pWls->nTotalBlocks; i++){ + void* pMsg = wls_mac_alloc_buffer(pWls, 0, i); + /* Enqueue all blocks */ + nBlocks += WLS_EnqueueBlock(pWls->hWls, WLS_VA2PA(pWls->hWls, pMsg)); +} + NFAPI_TRACE(NFAPI_TRACE_INFO, "\nAllocated %d Blocks \n", nBlocks); + return true; +} + +static int vnf_wls_init() +{ + mac_dpdk_init(); + + if (!mac_wls_init()) { + return 0; + } + + return 1; +} + +void *wls_fapi_vnf_nr_start_thread(void *ptr) +{ + NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] IN WLS PNF NFAPI start thread %s\n", __FUNCTION__); + wls_fapi_nr_vnf_start((nfapi_vnf_config_t *)ptr); + return (void *)0; +} + +static void procPhyMessages(uint32_t msg_size, void *msg_buf, uint16_t msg_id) +{ + NFAPI_TRACE(NFAPI_TRACE_DEBUG, "[VNF] Received Msg ID 0x%02x\n", msg_id); + if (msg_buf == NULL || _vnf == NULL) { + AssertFatal(msg_buf != NULL && _vnf != NULL, "%s: NULL parameters\n", __FUNCTION__); + } + // Add the size of the header to the message_size, because the size in the header does not include the header length + msg_size += NFAPI_NR_P5_HEADER_LENGTH; + switch (msg_id) { + case NFAPI_NR_PHY_MSG_TYPE_PARAM_RESPONSE: + case NFAPI_NR_PHY_MSG_TYPE_CONFIG_RESPONSE: + case NFAPI_NR_PHY_MSG_TYPE_START_RESPONSE: + case NFAPI_NR_PHY_MSG_TYPE_STOP_INDICATION: + vnf_nr_handle_p4_p5_message(msg_buf, msg_size, 0, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST ... NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: { + vnf_nr_handle_p7_message(msg_buf, msg_size + NFAPI_NR_P7_HEADER_LENGTH, (vnf_p7_t *)wls_vnf_p7_config); + break; + } + default: + break; + } +} + +int wls_fapi_nr_vnf_start(nfapi_vnf_config_t *cfg) +{ + config = cfg; + + if (config == 0) { + return -1; + } + _vnf = (vnf_t *)(config); + + // init WLS connection + if (vnf_wls_init() == 0) { + return -1; + } + _vnf->terminate = 0; + + // Connect to the PNF + if (config->pnf_nr_start_resp != 0) { + (config->pnf_nr_start_resp)(config, 0, NULL); + } + /* VNF receive loop */ + /* Number of Memory blocks to get */ + uint32_t msgSize; + uint16_t msgType; + uint16_t flags; + PWLS_MAC_CTX pWls = wls_mac_get_ctx(); + while (_vnf->terminate == 0) { + int numMsgToGet = WLS_Wait(pWls->hWls); + if (numMsgToGet == 0) { + continue; + } + + uint64_t PAs[numMsgToGet]; + uint8_t pa_idx = 0; + while (numMsgToGet--) { + PAs[pa_idx] = WLS_Get(pWls->hWls, &msgSize, &msgType, &flags); + pa_idx++; + } + for (int i = 0; i < pa_idx; i++) { + p_fapi_api_queue_elem_t msg = WLS_PA2VA(pWls->hWls, PAs[i]); + if (msg->msg_type != FAPI_VENDOR_MSG_HEADER_IND) { + uint8_t *msgt = (uint8_t *)(msg + 1); + uint32_t len = msgt[7] | (msgt[6] << 8) | (msgt[5] << 16) | (msgt[4] << 24); + procPhyMessages(len, (void *)(msg + 1), msg->msg_type); + } + } + for (int i = 0; i < pa_idx; i++) { + if (WLS_EnqueueBlock(pWls->hWls, PAs[i]) == -1) { + NFAPI_TRACE(NFAPI_TRACE_DEBUG, "Error in WLS_EnqueueBlock for block %lu\n", PAs[i]); + } + } + } + return 1; +} + +bool wls_vnf_nr_send_p5_message(vnf_t *vnf, uint16_t p5_idx, nfapi_nr_p4_p5_message_header_t *msg, uint32_t msg_len) +{ + UNUSED_VARIABLE(p5_idx); + int packed_len = + vnf->_public.pack_func(msg, msg_len, vnf->tx_message_buffer, sizeof(vnf->tx_message_buffer), &vnf->_public.codec_config); + + if (packed_len < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi_p5_message_pack failed (%d)\n", packed_len); + return false; + } + + // printf("fapi_nr_p5_message_pack succeeded having packed %d bytes\n", packed_len); + // printf("in msg, msg_len is %d\n", msg->message_length); + PWLS_MAC_CTX pWls = wls_mac_get_ctx(); + + int retval = wls_send_fapi_msg(pWls, msg->message_id, packed_len, vnf->tx_message_buffer); + if (retval) { + NFAPI_TRACE(NFAPI_TRACE_DEBUG, "wls_send_fapi_msg success\n"); + } + return retval; +} + +bool wls_vnf_nr_send_p7_message(vnf_p7_t *vnf_p7, nfapi_nr_p7_message_header_t *msg) +{ + uint32_t message_id = msg->message_id; + PWLS_MAC_CTX pWls = wls_mac_get_ctx(); + int num_avail_blocks = WLS_NumBlocks(pWls->hWls); + NFAPI_TRACE(NFAPI_TRACE_DEBUG,"num_avail_blocks is %d\n", num_avail_blocks); + while (num_avail_blocks < 2) { + num_avail_blocks = WLS_NumBlocks(pWls->hWls); + NFAPI_TRACE(NFAPI_TRACE_DEBUG,"num_avail_blocks is %d\n", num_avail_blocks); + } + /* get PA blocks for header and msg */ + uint64_t pa_hdr = dequeueBlock(pWls); + AssertFatal(pa_hdr, "WLS_DequeueBlock failed for pa_hdr\n"); + uint64_t pa_msg = dequeueBlock(pWls); + AssertFatal(pa_msg, "WLS_DequeueBlock failed for pa_msg\n"); + p_fapi_api_queue_elem_t headerElem = WLS_PA2VA(pWls->hWls, pa_hdr); + AssertFatal(headerElem, "WLS_PA2VA failed for headerElem\n"); + p_fapi_api_queue_elem_t fapiMsgElem = WLS_PA2VA(pWls->hWls, pa_msg); + AssertFatal(fapiMsgElem, "WLS_PA2VA failed for fapiMsgElem\n"); + //memcpy((uint8_t *)(fapiMsgElem + 1), message, packed_len + NFAPI_HEADER_LENGTH); + const uint8_t wls_header[] = {1, 0}; // num_messages , opaque_handle + + fill_fapi_list_elem(headerElem, fapiMsgElem, FAPI_VENDOR_MSG_HEADER_IND, 1, 2); + memcpy((uint8_t *)(headerElem + 1), wls_header, 2); + int packed_len = ((nfapi_vnf_p7_config_t *)vnf_p7)->pack_func(msg, (fapiMsgElem + 1), NFAPI_MAX_PACKED_MESSAGE_SIZE, NULL); + if (packed_len < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "fapi_p7_message_pack failed (%d)\n", packed_len); + return false; + } + fill_fapi_list_elem(fapiMsgElem, NULL, message_id, 1, packed_len + NFAPI_HEADER_LENGTH); + uint8_t retval = wls_msg_send(pWls->hWls, headerElem); + return retval; + //return wls_send_fapi_msg(pWls, msg->message_id, packed_len, _vnf->tx_message_buffer); +} diff --git a/nfapi/open-nFAPI/vnf/src/vnf.c b/nfapi/open-nFAPI/vnf/src/vnf.c index 5ac6be4882..345dada3ec 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf.c +++ b/nfapi/open-nFAPI/vnf/src/vnf.c @@ -32,6 +32,9 @@ #include "nfapi/oai_integration/aerial/fapi_vnf_p5.h" #include "nr_fapi_p5.h" #endif +#ifdef ENABLE_WLS +#include +#endif // ENABLE_WLS #include @@ -437,38 +440,36 @@ void vnf_nr_handle_param_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_conf const bool result = config->unpack_func(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config); if (result) { + if (msg.error_code == NFAPI_NR_PARAM_MSG_OK) { + nfapi_vnf_phy_info_t *phy_info = nfapi_vnf_phy_info_list_find(config, msg.header.phy_id); + if (phy_info) { + if (msg.nfapi_config.p7_pnf_address_ipv4.tl.tag) { + struct sockaddr_in sockAddr; - if (msg.error_code == NFAPI_NR_PARAM_MSG_OK) - { - nfapi_vnf_phy_info_t* phy_info = nfapi_vnf_phy_info_list_find(config, msg.header.phy_id); + (void)memcpy(&sockAddr.sin_addr.s_addr, msg.nfapi_config.p7_pnf_address_ipv4.address, NFAPI_IPV4_ADDRESS_LENGTH); + NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF P7 IPv4 address: %s\n", inet_ntoa(sockAddr.sin_addr)); - if(msg.nfapi_config.p7_pnf_address_ipv4.tl.tag) - { - struct sockaddr_in sockAddr; + // store address + phy_info->p7_pnf_address.sin_addr = sockAddr.sin_addr; + } - (void)memcpy(&sockAddr.sin_addr.s_addr, msg.nfapi_config.p7_pnf_address_ipv4.address, NFAPI_IPV4_ADDRESS_LENGTH); - NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF P7 IPv4 address: %s\n", inet_ntoa(sockAddr.sin_addr)); + if (msg.nfapi_config.p7_pnf_address_ipv6.tl.tag) { + struct sockaddr_in6 sockAddr6; + char addr6[64]; + (void)memcpy(&sockAddr6.sin6_addr, msg.nfapi_config.p7_pnf_address_ipv6.address, NFAPI_IPV6_ADDRESS_LENGTH); + NFAPI_TRACE(NFAPI_TRACE_INFO, + "PNF P7 IPv6 address: %s\n", + inet_ntop(AF_INET6, &sockAddr6.sin6_addr, addr6, sizeof(addr6))); + } - // store address - phy_info->p7_pnf_address.sin_addr = sockAddr.sin_addr; - } + if (msg.nfapi_config.p7_pnf_port.tl.tag) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF P7 Port: %d\n", msg.nfapi_config.p7_pnf_port.value); - if(msg.nfapi_config.p7_pnf_address_ipv6.tl.tag) - { - struct sockaddr_in6 sockAddr6; - char addr6[64]; - (void)memcpy(&sockAddr6.sin6_addr, msg.nfapi_config.p7_pnf_address_ipv6.address, NFAPI_IPV6_ADDRESS_LENGTH); - NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF P7 IPv6 address: %s\n", inet_ntop(AF_INET6, &sockAddr6.sin6_addr, addr6, sizeof(addr6))); - } - - if (msg.nfapi_config.p7_pnf_port.tl.tag) - { - NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF P7 Port: %d\n", msg.nfapi_config.p7_pnf_port.value); - - // store port - phy_info->p7_pnf_address.sin_port = htons(msg.nfapi_config.p7_pnf_port.value); - } - } + // store port + phy_info->p7_pnf_address.sin_port = htons(msg.nfapi_config.p7_pnf_port.value); + } + } + } if(config->nr_param_resp) { diff --git a/nfapi/open-nFAPI/vnf/src/vnf_interface.c b/nfapi/open-nFAPI/vnf/src/vnf_interface.c index 431ac6066e..33db1130a3 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_interface.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_interface.c @@ -579,6 +579,7 @@ int nfapi_nr_vnf_config_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_con return -1; AssertFatal(config->send_p5_msg, "Function pointer must be configured\n"); vnf_t* _this = (vnf_t*)(config); +#ifndef ENABLE_WLS nfapi_vnf_phy_info_t* phy = nfapi_vnf_phy_info_list_find(config, req->header.phy_id); @@ -600,7 +601,7 @@ int nfapi_nr_vnf_config_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_con req->nfapi_config.timing_info_period.tl.tag = NFAPI_NR_NFAPI_TIMING_INFO_PERIOD_TAG; req->nfapi_config.timing_info_period.value = phy->timing_info_period; req->num_tlv++; - +#endif return config->send_p5_msg(_this, p5_idx, &req->header, sizeof(nfapi_nr_config_request_scf_t)); } diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7.c b/nfapi/open-nFAPI/vnf/src/vnf_p7.c index b82be32226..82c5ae7d1c 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7.c @@ -29,6 +29,9 @@ #include "nfapi/oai_integration/aerial/fapi_nvIPC.h" #endif #include "vnf_p7.h" +#ifdef ENABLE_WLS +#include +#endif #include "nr_fapi_p7_utils.h" #ifdef NDEBUG From a340d08bd2a7d2025aea94b63e849028ba56cec9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Soares=20Silva?= Date: Mon, 17 Mar 2025 16:40:33 +0000 Subject: [PATCH 208/964] Initial refactoring for P5 messages in Aerial VNF --- CMakeLists.txt | 5 +- nfapi/oai_integration/aerial/fapi_nvIPC.c | 29 +++++-- nfapi/oai_integration/aerial/fapi_nvIPC.h | 3 +- nfapi/oai_integration/nfapi_vnf.c | 86 ++++++++++++++++--- nfapi/oai_integration/nfapi_vnf.h | 3 +- nfapi/open-nFAPI/vnf/src/vnf_interface.c | 3 +- nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c | 4 +- .../SIMULATION/NR_PHY/nr_unitary_common.c | 2 +- openair2/GNB_APP/gnb_config.c | 6 +- 9 files changed, 110 insertions(+), 31 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bfe13b9351..99c537dc22 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -768,14 +768,13 @@ set(NFAPI_USER_SRC add_library(NFAPI_USER_LIB ${NFAPI_USER_SRC}) if(OAI_WLS) target_compile_definitions(NFAPI_USER_LIB PRIVATE ENABLE_WLS) +elseif (OAI_AERIAL) + target_compile_definitions(NFAPI_USER_LIB PRIVATE ENABLE_AERIAL) else() target_compile_definitions(NFAPI_USER_LIB PRIVATE ENABLE_SOCKET) endif() target_link_libraries(NFAPI_USER_LIB PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs UTIL) target_link_libraries(NFAPI_USER_LIB PRIVATE nr_fapi_p7) -if(OAI_AERIAL) - target_compile_definitions(NFAPI_USER_LIB PRIVATE ENABLE_AERIAL) -endif() include_directories(${NFAPI_USER_DIR}) # Layer 1 diff --git a/nfapi/oai_integration/aerial/fapi_nvIPC.c b/nfapi/oai_integration/aerial/fapi_nvIPC.c index ed087204b0..2011b8b68e 100644 --- a/nfapi/oai_integration/aerial/fapi_nvIPC.c +++ b/nfapi/oai_integration/aerial/fapi_nvIPC.c @@ -293,10 +293,26 @@ int8_t buf[1024]; nv_ipc_config_t nv_ipc_config; -int aerial_send_P5_msg(void *packedBuf, uint32_t packedMsgLength, nfapi_nr_p4_p5_message_header_t *header) +bool aerial_nr_send_p5_message(vnf_t *vnf, uint16_t p5_idx, nfapi_nr_p4_p5_message_header_t *msg, uint32_t msg_len) +{ + nfapi_vnf_pnf_info_t *pnf = nfapi_vnf_pnf_list_find(&(vnf->_public), p5_idx); + + if (pnf) { + uint8_t tx_messagebufferFAPI[sizeof(vnf->tx_message_buffer)]; + int packedMessageLengthFAPI = -1; + packedMessageLengthFAPI = + vnf->_public.pack_func(msg, msg_len, tx_messagebufferFAPI, sizeof(tx_messagebufferFAPI), &vnf->_public.codec_config); + return aerial_send_P5_msg(tx_messagebufferFAPI, packedMessageLengthFAPI, msg) == 0; + } else { + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() cannot find pnf info for p5_idx:%d\n", __FUNCTION__, p5_idx); + return false; + } +} + +bool aerial_send_P5_msg(void *packedBuf, uint32_t packedMsgLength, nfapi_nr_p4_p5_message_header_t *header) { if (ipc == NULL) { - return -1; + return false; } nv_ipc_msg_t send_msg = {0}; // look for the specific message @@ -334,7 +350,7 @@ int aerial_send_P5_msg(void *packedBuf, uint32_t packedMsgLength, nfapi_nr_p4_p5 if (alloc_retval != 0) { LOG_E(NFAPI_VNF, "%s error: allocate TX buffer failed Error: %d\n", __FUNCTION__, alloc_retval); ipc->tx_release(ipc, &send_msg); - return alloc_retval; + return false; } memcpy(send_msg.msg_buf, packedBuf, send_msg.msg_len); @@ -350,11 +366,11 @@ int aerial_send_P5_msg(void *packedBuf, uint32_t packedMsgLength, nfapi_nr_p4_p5 if (send_retval < 0) { LOG_E(NFAPI_VNF, "%s error: send TX message failed Error: %d\n", __FUNCTION__, send_retval); ipc->tx_release(ipc, &send_msg); - return send_retval; + return false; } ipc->notify(ipc, 1); // notify that there's 1 message in queue - return 0; + return true; } int aerial_send_P7_msg(void *packedBuf, uint32_t packedMsgLength, nfapi_nr_p7_message_header_t *header) @@ -656,6 +672,7 @@ int nvIPC_Init(nvipc_params_t nvipc_params_s) sleep(1); create_recv_thread(nvipc_params_s.nvipc_poll_core); while(!recv_task_running){usleep(100000);} - aerial_pnf_nr_connection_indication_cb(vnf_config, 1); + nfapi_nr_param_response_scf_t resp_msg; + vnf_config->nr_param_resp(vnf_config, 1, &resp_msg); return 0; } diff --git a/nfapi/oai_integration/aerial/fapi_nvIPC.h b/nfapi/oai_integration/aerial/fapi_nvIPC.h index 5b8b995964..ed67e8c846 100644 --- a/nfapi/oai_integration/aerial/fapi_nvIPC.h +++ b/nfapi/oai_integration/aerial/fapi_nvIPC.h @@ -47,7 +47,8 @@ typedef struct { uint32_t message_length; } fapi_phy_api_msg; -int aerial_send_P5_msg(void *packedBuf, uint32_t packedMsgLength, nfapi_nr_p4_p5_message_header_t *header); +bool aerial_nr_send_p5_message(vnf_t *vnf, uint16_t p5_idx, nfapi_nr_p4_p5_message_header_t *msg, uint32_t msg_len); +bool aerial_send_P5_msg(void *packedBuf, uint32_t packedMsgLength, nfapi_nr_p4_p5_message_header_t *header); int aerial_send_P7_msg(void *packedBuf, uint32_t packedMsgLength, nfapi_nr_p7_message_header_t *header); int aerial_send_P7_msg_with_data(void *packedBuf, uint32_t packedMsgLength, diff --git a/nfapi/oai_integration/nfapi_vnf.c b/nfapi/oai_integration/nfapi_vnf.c index 582c7b374a..be0270e28a 100644 --- a/nfapi/oai_integration/nfapi_vnf.c +++ b/nfapi/oai_integration/nfapi_vnf.c @@ -64,6 +64,7 @@ #ifdef ENABLE_AERIAL #include "aerial/fapi_vnf_p5.h" +#include "nr_fapi_p5.h" #endif #define TEST @@ -719,7 +720,7 @@ int phy_rach_indication(struct nfapi_vnf_p7_config *config, nfapi_rach_indicatio int phy_nr_rach_indication(nfapi_nr_rach_indication_t *ind) { - if (NFAPI_MODE == NFAPI_MODE_VNF) { + if (NFAPI_MODE == NFAPI_MODE_VNF || NFAPI_MODE == NFAPI_MODE_AERIAL) { nfapi_nr_rach_indication_t *rach_ind = CALLOC(1, sizeof(*rach_ind)); copy_rach_indication(ind, rach_ind); if (!put_queue(&gnb_rach_ind_queue, rach_ind)) { @@ -736,7 +737,7 @@ int phy_nr_rach_indication(nfapi_nr_rach_indication_t *ind) int phy_nr_uci_indication(nfapi_nr_uci_indication_t *ind) { LOG_D(NR_MAC, "In %s() NFAPI SFN/SF: %d/%d number_of_pdus :%u\n", __FUNCTION__, ind->sfn, ind->slot, ind->num_ucis); - if (NFAPI_MODE == NFAPI_MODE_VNF) { + if (NFAPI_MODE == NFAPI_MODE_VNF || NFAPI_MODE == NFAPI_MODE_AERIAL) { nfapi_nr_uci_indication_t *uci_ind = CALLOC(1, sizeof(*uci_ind)); AssertFatal(uci_ind, "Memory not allocated for uci_ind in phy_nr_uci_indication."); copy_uci_indication(ind, uci_ind); @@ -841,7 +842,7 @@ int phy_nr_crc_indication(nfapi_nr_crc_indication_t *ind) { LOG_D(NR_MAC, "In %s() NFAPI SFN/SF: %d/%d number_of_pdus :%u\n", __FUNCTION__, ind->sfn, ind->slot, ind->number_crcs); - if (NFAPI_MODE == NFAPI_MODE_VNF) { + if (NFAPI_MODE == NFAPI_MODE_VNF || NFAPI_MODE == NFAPI_MODE_AERIAL) { nfapi_nr_crc_indication_t *crc_ind = CALLOC(1, sizeof(*crc_ind)); copy_crc_indication(ind, crc_ind); if (!put_queue(&gnb_crc_ind_queue, crc_ind)) { @@ -942,7 +943,7 @@ int phy_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind) ind->number_of_pdus, ind->pdu_list[0].pdu); - if (NFAPI_MODE == NFAPI_MODE_VNF) { + if (NFAPI_MODE == NFAPI_MODE_VNF || NFAPI_MODE == NFAPI_MODE_AERIAL) { nfapi_nr_rx_data_indication_t *rx_ind = CALLOC(1, sizeof(*rx_ind)); copy_rx_data_indication(ind, rx_ind); if (!put_queue(&gnb_rx_ind_queue, rx_ind)) { @@ -1422,19 +1423,23 @@ void *configure_nr_p7_vnf(void *ptr) vnf_p7_info *p7_vnf = (vnf_p7_info *)ptr; p7_vnf->config->port = p7_vnf->local_port; +#ifndef ENABLE_AERIAL p7_vnf->config->sync_indication = &phy_sync_indication; p7_vnf->config->slot_indication = &phy_slot_indication; p7_vnf->config->harq_indication = &phy_harq_indication; +#endif p7_vnf->config->nr_crc_indication = &phy_nr_crc_indication; p7_vnf->config->nr_rx_data_indication = &phy_nr_rx_data_indication; p7_vnf->config->nr_rach_indication = &phy_nr_rach_indication; p7_vnf->config->nr_uci_indication = &phy_nr_uci_indication; +#ifndef ENABLE_AERIAL p7_vnf->config->srs_indication = &phy_srs_indication; p7_vnf->config->sr_indication = &phy_sr_indication; p7_vnf->config->cqi_indication = &phy_cqi_indication; p7_vnf->config->lbt_dl_indication = &phy_lbt_dl_indication; p7_vnf->config->nb_harq_indication = &phy_nb_harq_indication; p7_vnf->config->nrach_indication = &phy_nrach_indication; +#endif p7_vnf->config->nr_slot_indication = &phy_nr_slot_indication; p7_vnf->config->nr_srs_indication = &phy_nr_srs_indication; p7_vnf->config->malloc = &vnf_allocate; @@ -1468,6 +1473,10 @@ void *configure_nr_p7_vnf(void *ptr) p7_vnf->config->send_p7_msg = &vnf_nr_send_p7_msg; NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Creating VNF NFAPI P7 start thread %s\n", __FUNCTION__); threadCreate(&vnf_p7_start_pthread, &vnf_nr_start_p7_thread, p7_vnf->config, "vnf_p7_thread", -1, OAI_PRIORITY_RT); +#endif + +#ifdef ENABLE_AERIAL + #endif return 0; } @@ -1569,8 +1578,9 @@ int nr_param_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_nr_param_resp vnf_p7_info *p7_vnf = vnf->p7_vnfs; pnf_info *pnf = vnf->pnfs; phy_info *phy = pnf->phys; - struct sockaddr_in pnf_p7_sockaddr; nfapi_nr_config_request_scf_t *req = &RC.nrmac[0]->config[0]; // check +#ifndef ENABLE_AERIAL + struct sockaddr_in pnf_p7_sockaddr; phy->remote_port = resp->nfapi_config.p7_pnf_port.value; //phy->remote_port = 32123;//resp->nfapi_config.p7_pnf_port.value; memcpy(&pnf_p7_sockaddr.sin_addr.s_addr, &(resp->nfapi_config.p7_pnf_address_ipv4.address[0]), 4); @@ -1578,6 +1588,7 @@ int nr_param_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_nr_param_resp // for now just 1 NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] %d.%d pnf p7 %s:%d timing %u %u %u %u\n", p5_idx, phy->id, phy->remote_addr, phy->remote_port, p7_vnf->timing_window, p7_vnf->periodic_timing_period, p7_vnf->aperiodic_timing_enabled, p7_vnf->periodic_timing_period); +#endif // Hack? the VNF might need the subcarrier spacing for some calculations // (that we actually don't use as of now...). We therefore need to save the // mu, for the current PNF connection (together with where we have frame/slot @@ -1593,7 +1604,7 @@ int nr_param_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_nr_param_resp req->header.phy_id = phy->id; NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Send NFAPI_CONFIG_REQUEST\n"); //NFAPI_TRACE(NFAPI_TRACE_INFO, "\n NR bandP =%d\n",req->nfapi_config.rf_bands.rf_band[0]); - +#ifndef ENABLE_AERIAL req->nfapi_config.p7_vnf_port.tl.tag = NFAPI_NR_NFAPI_P7_VNF_PORT_TAG; req->nfapi_config.p7_vnf_port.value = p7_vnf->local_port; req->num_tlv++; @@ -1631,6 +1642,7 @@ req->nfapi_config.tx_data_timing_offset.tl.tag = NFAPI_NR_NFAPI_TX_DATA_TIMING_O ve2.tl.tag = VENDOR_EXT_TLV_2_TAG; ve2.dummy = 2016; req->vendor_extension = &ve2.tl; +#endif nfapi_nr_vnf_config_req(config, p5_idx, req); printf("[VNF] Sent NFAPI_VNF_CONFIG_REQ num_tlv:%u\n",req->num_tlv); return 0; @@ -1829,9 +1841,11 @@ void vnf_start_thread(void *ptr) { static vnf_info vnf; -void configure_nr_nfapi_vnf(char *vnf_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port) +void configure_nr_nfapi_vnf(eth_params_t params) { +#ifndef ENABLE_AERIAL nfapi_setmode(NFAPI_MODE_VNF); +#endif memset(&vnf, 0, sizeof(vnf)); memset(vnf.p7_vnfs, 0, sizeof(vnf.p7_vnfs)); vnf.p7_vnfs[0].timing_window = 30; @@ -1839,19 +1853,21 @@ void configure_nr_nfapi_vnf(char *vnf_addr, int vnf_p5_port, char *pnf_ip_addr, vnf.p7_vnfs[0].aperiodic_timing_enabled = 0; vnf.p7_vnfs[0].periodic_timing_period = 1; vnf.p7_vnfs[0].config = nfapi_vnf_p7_config_create(); +#ifndef ENABLE_AERIAL NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] %s() vnf.p7_vnfs[0].config:%p VNF ADDRESS:%s:%d\n", __FUNCTION__, vnf.p7_vnfs[0].config, - vnf_addr, - vnf_p5_port); - strcpy(vnf.p7_vnfs[0].local_addr, vnf_addr); - vnf.p7_vnfs[0].local_port = vnf_p7_port; + params.my_addr, + params.my_portc); + strcpy(vnf.p7_vnfs[0].local_addr, params.my_addr); + vnf.p7_vnfs[0].local_port = params.my_portd; +#endif vnf.p7_vnfs[0].mac = (mac_t *)malloc(sizeof(mac_t)); nfapi_vnf_config_t *config = nfapi_vnf_config_create(); config->malloc = malloc; config->free = free; - config->vnf_p5_port = vnf_p5_port; + config->vnf_p5_port = params.my_portc; config->vnf_ipv4 = 1; config->vnf_ipv6 = 0; config->pnf_list = 0; @@ -1899,6 +1915,52 @@ void configure_nr_nfapi_vnf(char *vnf_addr, int vnf_p5_port, char *pnf_ip_addr, pthread_create(&vnf_p5_init_and_receive_pthread, NULL, (void *)&vnf_start_p5_thread, config); NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Created VNF NFAPI start thread %s\n", __FUNCTION__); #endif +#ifdef ENABLE_AERIAL + config->unpack_func = &fapi_nr_p5_message_unpack; + config->hdr_unpack_func = &fapi_nr_message_header_unpack; + config->pack_func = &fapi_nr_p5_message_pack; + config->send_p5_msg = &aerial_nr_send_p5_message; + set_config(config); + NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Created VNF NFAPI start thread %s\n", __FUNCTION__); + nfapi_vnf_pnf_info_t *pnf = (nfapi_vnf_pnf_info_t *)malloc(sizeof(nfapi_vnf_pnf_info_t)); + NFAPI_TRACE(NFAPI_TRACE_INFO, "MALLOC nfapi_vnf_pnf_info_t for pnf_list pnf:%p\n", pnf); + memset(pnf, 0, sizeof(nfapi_vnf_pnf_info_t)); + pnf->p5_idx = 1; + pnf->connected = 1; + // Add needed parameters + + vnf_info *vnf = (vnf_info *)(config->user_data); + pnf_info *pnf_info = vnf->pnfs; + + for (int i = 0; i < 1; ++i) { + phy_info phy; + memset(&phy, 0, sizeof(phy)); + phy.index = 0; + NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] (PHY:%d) phy_config_idx:%d\n", i, 0); + nfapi_vnf_allocate_phy(config, 1, &(phy.id)); + + for (int j = 0; j < 1; ++j) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] (PHY:%d) (RF%d) %d\n", i, j, 0); + phy.rfs[0] = 0; + } + + pnf_info->phys[0] = phy; + } + + + nfapi_vnf_pnf_list_add(config, pnf); + + vnf_p7_info *p7_vnf = vnf->p7_vnfs; + + NFAPI_TRACE(NFAPI_TRACE_INFO, + "[VNF] pnf start response idx:%d config:%p user_data:%p p7_vnf[config:%p thread_started:%d]\n", + 1, + config, + config->user_data, + vnf->p7_vnfs[0].config, + vnf->p7_vnfs[0].thread_started); + configure_nr_p7_vnf(p7_vnf); +#endif } diff --git a/nfapi/oai_integration/nfapi_vnf.h b/nfapi/oai_integration/nfapi_vnf.h index 71cc50c2f7..1a8228f0a3 100644 --- a/nfapi/oai_integration/nfapi_vnf.h +++ b/nfapi/oai_integration/nfapi_vnf.h @@ -21,8 +21,9 @@ #ifndef NFAPI_VNF_H_ #define NFAPI_VNF_H_ +#include void configure_nfapi_vnf(char *vnf_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port); -void configure_nr_nfapi_vnf(char *vnf_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port); +void configure_nr_nfapi_vnf(eth_params_t params); #endif /* NFAPI_VNF_H_ */ diff --git a/nfapi/open-nFAPI/vnf/src/vnf_interface.c b/nfapi/open-nFAPI/vnf/src/vnf_interface.c index 33db1130a3..111d88e8dc 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_interface.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_interface.c @@ -579,8 +579,7 @@ int nfapi_nr_vnf_config_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_con return -1; AssertFatal(config->send_p5_msg, "Function pointer must be configured\n"); vnf_t* _this = (vnf_t*)(config); -#ifndef ENABLE_WLS - +#if !defined(ENABLE_WLS) && !defined(ENABLE_AERIAL) nfapi_vnf_phy_info_t* phy = nfapi_vnf_phy_info_list_find(config, req->header.phy_id); if(phy == NULL) diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c index 6f16e7c4d2..225b0b7d8c 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c @@ -450,12 +450,12 @@ int nfapi_vnf_p7_add_pnf(nfapi_vnf_p7_config_t* config, const char* pnf_p7_addr, node->slot = 0; node->min_sync_cycle_count = 8; node->mu = mu; - +#ifndef ENABLE_AERIAL // save the remote endpoint information node->remote_addr.sin_family = AF_INET; node->remote_addr.sin_port = pnf_p7_port;//htons(pnf_p7_port); node->remote_addr.sin_addr.s_addr = inet_addr(pnf_p7_addr); - +#endif vnf_p7_connection_info_list_add(vnf_p7, node); return 0; diff --git a/openair1/SIMULATION/NR_PHY/nr_unitary_common.c b/openair1/SIMULATION/NR_PHY/nr_unitary_common.c index 8a682b02f1..7aca911b7f 100644 --- a/openair1/SIMULATION/NR_PHY/nr_unitary_common.c +++ b/openair1/SIMULATION/NR_PHY/nr_unitary_common.c @@ -112,7 +112,7 @@ int32_t get_uldl_offset(int nr_bandP) void configure_nr_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port) { } -void configure_nr_nfapi_vnf(char *vnf_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port) +void configure_nr_nfapi_vnf(eth_params_t params) { } int nfapi_nr_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen, nfapi_p7_codec_config_t *config) diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 36ac8b6b1f..ebda616dfc 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -1752,15 +1752,15 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg) RC.nrmac[j]->eth_params_s.remote_portd = *(MacRLC_ParamList.paramarray[j][MACRLC_REMOTE_S_PORTD_IDX].iptr); RC.nrmac[j]->eth_params_s.transp_preference = ETH_UDP_MODE; - configure_nr_nfapi_vnf( - RC.nrmac[j]->eth_params_s.my_addr, RC.nrmac[j]->eth_params_s.my_portc, RC.nrmac[j]->eth_params_s.remote_addr, RC.nrmac[j]->eth_params_s.remote_portd, RC.nrmac[j]->eth_params_s.my_portd); + configure_nr_nfapi_vnf(RC.nrmac[j]->eth_params_s); } else if(strcmp(*(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_S_PREFERENCE_IDX].strptr), "aerial") == 0){ #ifdef ENABLE_AERIAL RC.nrmac[j]->nvipc_params_s.nvipc_shm_prefix = strdup(*(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_S_SHM_PREFIX].strptr)); RC.nrmac[j]->nvipc_params_s.nvipc_poll_core = *(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_S_POLL_CORE].i8ptr); LOG_I(GNB_APP, "Configuring VNF for Aerial connection with prefix %s\n", RC.nrmac[j]->eth_params_s.local_if_name); - aerial_configure_nr_fapi_vnf(); + configure_nr_nfapi_vnf(RC.nrmac[j]->eth_params_s); + #endif } else { // other midhaul AssertFatal(1 == 0, "MACRLC %d: %s unknown southbound midhaul\n", j, *(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_S_PREFERENCE_IDX].strptr)); From 0c21807df9db165428536bc811338689bcb05c78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Soares=20Silva?= Date: Thu, 20 Mar 2025 13:47:12 +0000 Subject: [PATCH 209/964] Change Aerial VNF to use existing functions to process P5 messages Remove fapi_vnf_p5.c and .h files as they're now unused Move scheduler functions to fapi_nvIPC.c --- nfapi/oai_integration/aerial/CMakeLists.txt | 1 - nfapi/oai_integration/aerial/fapi_nvIPC.c | 135 +++-- nfapi/oai_integration/aerial/fapi_nvIPC.h | 6 +- nfapi/oai_integration/aerial/fapi_vnf_p5.c | 610 -------------------- nfapi/oai_integration/aerial/fapi_vnf_p5.h | 72 --- nfapi/oai_integration/nfapi_vnf.c | 2 +- nfapi/open-nFAPI/vnf/src/vnf.c | 1 - openair1/SCHED_NR/fapi_nr_l1.c | 3 - openair2/GNB_APP/gnb_config.c | 4 +- 9 files changed, 89 insertions(+), 745 deletions(-) delete mode 100644 nfapi/oai_integration/aerial/fapi_vnf_p5.c delete mode 100644 nfapi/oai_integration/aerial/fapi_vnf_p5.h diff --git a/nfapi/oai_integration/aerial/CMakeLists.txt b/nfapi/oai_integration/aerial/CMakeLists.txt index 74b1ad9fbf..2df4eb7ee0 100644 --- a/nfapi/oai_integration/aerial/CMakeLists.txt +++ b/nfapi/oai_integration/aerial/CMakeLists.txt @@ -3,7 +3,6 @@ if (OAI_AERIAL) add_library(aerial_lib fapi_nvIPC.c fapi_vnf_p7.c - fapi_vnf_p5.c ) find_library(NVIPC_LIB nvipc REQUIRED) diff --git a/nfapi/oai_integration/aerial/fapi_nvIPC.c b/nfapi/oai_integration/aerial/fapi_nvIPC.c index 2011b8b68e..0259eda06a 100644 --- a/nfapi/oai_integration/aerial/fapi_nvIPC.c +++ b/nfapi/oai_integration/aerial/fapi_nvIPC.c @@ -53,7 +53,6 @@ #include "nfapi_nr_interface_scf.h" #include "nfapi/open-nFAPI/vnf/inc/vnf_p7.h" -#include "fapi_vnf_p5.h" #include "fapi_vnf_p7.h" #define MAX_EVENTS 10 @@ -94,59 +93,9 @@ static int ipc_handle_rx_msg(nv_ipc_t *ipc, nv_ipc_msg_t *msg) } switch (fapi_msg.message_id) { - case NFAPI_NR_PHY_MSG_TYPE_PARAM_RESPONSE: - - if (vnf_config->nr_param_resp) { - nfapi_nr_param_response_scf_t msg_param_resp; - aerial_unpack_nr_param_response(&pReadPackedMessage, end, &msg_param_resp, &vnf_config->codec_config); - (vnf_config->nr_param_resp)(vnf_config, vnf_config->pnf_list->p5_idx, &msg_param_resp); - } + case NFAPI_NR_PHY_MSG_TYPE_PARAM_RESPONSE ... NFAPI_NR_PHY_MSG_TYPE_ERROR_INDICATION: + vnf_nr_handle_p4_p5_message(msg->msg_buf, msg->msg_len, 1, vnf_config); break; - - case NFAPI_NR_PHY_MSG_TYPE_CONFIG_RESPONSE: { - // unpack message - nfapi_nr_config_response_scf_t msg_config_response; - aerial_unpack_nr_config_response(&pReadPackedMessage, end, &msg_config_response, &vnf_config->codec_config); - // Check the error code - if (msg_config_response.error_code == NFAPI_NR_CONFIG_MSG_OK) { - // Invoke the call back - if (vnf_config->nr_config_resp) { - (vnf_config->nr_config_resp)(vnf_config, vnf_config->pnf_list->p5_idx, &msg_config_response); - } - } else { - // Error code not OK (MSG_INVALID_CONFIG) - /* MSG_INVALID_CONFIG.response structure - * Error code uint8_t - * Number of invalid or unsupported TLVs uint8_t - * Number of invalid TLVs that can only be configured in IDLE state uint8_t - * Number of invalid TLVs that can only be configured in RUNNING state uint8_t - * Number of missing TLVs uint8_t - * List of invalid or unsupported TLVs - * List of invalid TLVs that can only be configured in IDLE state - * List of invalid TLVs that can only be configured in RUNNING state - * List of missing TLVs - * */ - } - break; - } - - case NFAPI_NR_PHY_MSG_TYPE_STOP_INDICATION: { - // TODO : ADD Support for NFAPI_NR_PHY_MSG_TYPE_STOP_INDICATION (0x06) - LOG_D(NFAPI_VNF,"Received NFAPI_NR_PHY_MSG_TYPE_STOP_INDICATION\n"); - break; - } - - case NFAPI_NR_PHY_MSG_TYPE_ERROR_INDICATION: { - // TODO: Add Support for NFAPI_NR_PHY_MSG_TYPE_ERROR_INDICATION (0x07) - LOG_D(NFAPI_VNF,"Received NFAPI_NR_PHY_MSG_TYPE_ERROR_INDICATION\n"); - //for (int i = 0; i < msg->msg_len; i++) { - // printf(" msg->msg_buf[%d] = 0x%02x\n", i, ((uint8_t *) msg->msg_buf)[i]); - //} - LOG_D(NFAPI_VNF,"old sfn %u\n", old_sfn); - LOG_D(NFAPI_VNF,"old slot %u\n", old_slot); - - break; - } // P7 Messages // P7 Message Handlers -> ((vnf_info *)vnf_config->user_data)->p7_vnfs->config-> case NFAPI_NR_PHY_MSG_TYPE_SLOT_INDICATION: { @@ -676,3 +625,83 @@ int nvIPC_Init(nvipc_params_t nvipc_params_s) vnf_config->nr_param_resp(vnf_config, 1, &resp_msg); return 0; } + +int oai_fapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req) +{ + nfapi_vnf_p7_config_t *p7_config = (((vnf_info *)vnf_config->user_data)->p7_vnfs[0].config); + + ul_tti_req->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! + ul_tti_req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST; + + // int retval = nfapi_vnf_p7_ul_tti_req(p7_config, ul_tti_req); + int retval = fapi_nr_pack_and_send_p7_message((vnf_p7_t *)p7_config, &ul_tti_req->header); + + if (retval != 0) { + LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval); + } else { + // Reset number of PDUs so that it is not resent + ul_tti_req->n_pdus = 0; + ul_tti_req->n_group = 0; + ul_tti_req->n_ulcch = 0; + ul_tti_req->n_ulsch = 0; + } + return retval; +} + +int oai_fapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req) +{ + nfapi_vnf_p7_config_t *p7_config = (((vnf_info *)vnf_config->user_data)->p7_vnfs[0].config); + ul_dci_req->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! + ul_dci_req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST; + // int retval = nfapi_vnf_p7_ul_dci_req(p7_config, ul_dci_req); + int retval = fapi_nr_pack_and_send_p7_message((vnf_p7_t *)p7_config, &ul_dci_req->header); + if (retval != 0) { + LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval); + } else { + ul_dci_req->numPdus = 0; + } + return retval; +} + +int oai_fapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req) +{ + nfapi_vnf_p7_config_t *p7_config = (((vnf_info *)vnf_config->user_data)->p7_vnfs[0].config); + tx_data_req->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! + tx_data_req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST; + // LOG_D(PHY, "[VNF] %s() TX_REQ sfn_sf:%d number_of_pdus:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(tx_data_req->SFN), + // tx_data_req->Number_of_PDUs); int retval = nfapi_vnf_p7_tx_data_req(p7_config, tx_data_req); + int retval = fapi_nr_pack_and_send_p7_message((vnf_p7_t *)p7_config, &tx_data_req->header); + if (retval != 0) { + LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval); + } else { + tx_data_req->Number_of_PDUs = 0; + } + + return retval; +} + +int oai_fapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req) +{ + nfapi_vnf_p7_config_t *p7_config = (((vnf_info *)vnf_config->user_data)->p7_vnfs[0].config); + dl_config_req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST; + dl_config_req->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! + int retval = fapi_nr_pack_and_send_p7_message((vnf_p7_t *)p7_config, &dl_config_req->header); + dl_config_req->dl_tti_request_body.nPDUs = 0; + dl_config_req->dl_tti_request_body.nGroup = 0; + + if (retval != 0) { + LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval); + } + return retval; +} + +int oai_fapi_send_end_request(int cell, uint32_t frame, uint32_t slot){ + nfapi_vnf_p7_config_t *p7_config = (((vnf_info *)vnf_config->user_data)->p7_vnfs[0].config); + nfapi_nr_slot_indication_scf_t nr_slot_resp = {.header.message_id = 0x8F, .sfn = frame, .slot = slot}; + int retval = fapi_nr_pack_and_send_p7_message((vnf_p7_t *)p7_config, &nr_slot_resp.header); + if (retval != 0) { + LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval); + } + return retval; +} + diff --git a/nfapi/oai_integration/aerial/fapi_nvIPC.h b/nfapi/oai_integration/aerial/fapi_nvIPC.h index ed67e8c846..242c2c5822 100644 --- a/nfapi/oai_integration/aerial/fapi_nvIPC.h +++ b/nfapi/oai_integration/aerial/fapi_nvIPC.h @@ -57,5 +57,9 @@ int aerial_send_P7_msg_with_data(void *packedBuf, nfapi_nr_p7_message_header_t *header); void set_config(nfapi_vnf_config_t *conf); int nvIPC_Init(nvipc_params_t nvipc_params_s); - +int oai_fapi_send_end_request(int cell_id, uint32_t frame, uint32_t slot); +int oai_fapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req); +int oai_fapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req); +int oai_fapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req); +int oai_fapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req); #endif // OPENAIRINTERFACE_FAPI_NVIPC_H diff --git a/nfapi/oai_integration/aerial/fapi_vnf_p5.c b/nfapi/oai_integration/aerial/fapi_vnf_p5.c deleted file mode 100644 index 1b01fd6c09..0000000000 --- a/nfapi/oai_integration/aerial/fapi_vnf_p5.c +++ /dev/null @@ -1,610 +0,0 @@ -/* -* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more -* contributor license agreements. See the NOTICE file distributed with -* this work for additional information regarding copyright ownership. -* The OpenAirInterface Software Alliance licenses this file to You under -* the OAI Public License, Version 1.1 (the "License"); you may not use this file -* except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.openairinterface.org/?page_id=698 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*------------------------------------------------------------------------------- -* For more information about the OpenAirInterface (OAI) Software Alliance: -* contact@openairinterface.org - */ - -/*! \file fapi/oai-integration/fapi_vnf_p5.c -* \brief OAI FAPI VNF P5 message handler procedures -* \author Ruben S. Silva -* \date 2023 -* \version 0.1 -* \company OpenAirInterface Software Alliance -* \email: contact@openairinterface.org, rsilva@allbesmart.pt -* \note -* \warning - */ - -#include "fapi_vnf_p5.h" -#include "fapi_vnf_p7.h" -#include "nfapi/open-nFAPI/vnf/inc/vnf_p7.h" -#include "nr_fapi.h" -#include "nr_fapi_p5.h" - -extern RAN_CONTEXT_t RC; -extern UL_RCC_IND_t UL_RCC_INFO; -extern int sf_ahead; -extern int slot_ahead; - -void *aerial_vnf_nr_p7_config_init(void *ptr) -{ - vnf_p7_info *p7_vnf = (vnf_p7_info *)ptr; - - init_queue(&gnb_rach_ind_queue); - init_queue(&gnb_rx_ind_queue); - init_queue(&gnb_crc_ind_queue); - init_queue(&gnb_uci_ind_queue); - - p7_vnf->config->port = p7_vnf->local_port; - p7_vnf->config->sync_indication = NULL; - p7_vnf->config->slot_indication = NULL; - p7_vnf->config->harq_indication = NULL; - p7_vnf->config->nr_crc_indication = &aerial_phy_nr_crc_indication; - p7_vnf->config->nr_rx_data_indication = &aerial_phy_nr_rx_data_indication; - p7_vnf->config->nr_rach_indication = &aerial_phy_nr_rach_indication; - p7_vnf->config->nr_uci_indication = &aerial_phy_nr_uci_indication; - p7_vnf->config->srs_indication = NULL; - p7_vnf->config->sr_indication = NULL; - p7_vnf->config->cqi_indication = NULL; - p7_vnf->config->lbt_dl_indication = NULL; - p7_vnf->config->nb_harq_indication = NULL; - p7_vnf->config->nrach_indication = NULL; - p7_vnf->config->nr_slot_indication = &aerial_phy_nr_slot_indication; - p7_vnf->config->nr_srs_indication = &aerial_phy_nr_srs_indication; - p7_vnf->config->malloc = &aerial_vnf_allocate; - p7_vnf->config->free = &aerial_vnf_deallocate; - p7_vnf->config->vendor_ext = &aerial_phy_vendor_ext; - p7_vnf->config->user_data = p7_vnf; - p7_vnf->mac->user_data = p7_vnf; - p7_vnf->config->codec_config.unpack_p7_vendor_extension = &aerial_phy_unpack_p7_vendor_extension; - p7_vnf->config->codec_config.pack_p7_vendor_extension = &aerial_phy_pack_p7_vendor_extension; - p7_vnf->config->codec_config.unpack_vendor_extension_tlv = &aerial_phy_unpack_vendor_extension_tlv; - p7_vnf->config->codec_config.pack_vendor_extension_tlv = &aerial_phy_pack_vendor_extension_tlv; - p7_vnf->config->codec_config.allocate = &aerial_vnf_allocate; - p7_vnf->config->codec_config.deallocate = &aerial_vnf_deallocate; - p7_vnf->config->allocate_p7_vendor_ext = &aerial_phy_allocate_p7_vendor_ext; - p7_vnf->config->deallocate_p7_vendor_ext = &aerial_phy_deallocate_p7_vendor_ext; - - return 0; -} - - -int aerial_pnf_nr_connection_indication_cb(nfapi_vnf_config_t *config, int p5_idx) -{ - printf("[VNF] pnf connection indication idx:%d\n", p5_idx); - // in aerial, send first CONFIG.request, not PARAM.request - nfapi_nr_config_request_scf_t conf_req; - memset(&conf_req, 0, sizeof(conf_req)); - conf_req.header.message_id = NFAPI_NR_PHY_MSG_TYPE_CONFIG_REQUEST; - printf("Try to send first CONFIG.request\n"); - aerial_nr_send_config_request(config, p5_idx); - return 0; -} - -int aerial_pnf_disconnection_indication_cb(nfapi_vnf_config_t *config, int p5_idx) -{ - NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] pnf disconnection indication idx:%d\n", p5_idx); - vnf_info *vnf = (vnf_info *)(config->user_data); - pnf_info *pnf = vnf->pnfs; - phy_info *phy = pnf->phys; - vnf_p7_info *p7_vnf = vnf->p7_vnfs; - nfapi_vnf_p7_del_pnf((p7_vnf->config), phy->id); - return 0; -} - -int aerial_pnf_nr_param_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_nr_pnf_param_response_t *resp) -{ - NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] pnf param response idx:%d error:%d\n", p5_idx, resp->error_code); - vnf_info *vnf = (vnf_info *)(config->user_data); - pnf_info *pnf = vnf->pnfs; - - for (int i = 0; i < resp->pnf_phy.number_of_phys; ++i) { - phy_info phy; - memset(&phy, 0, sizeof(phy)); - phy.index = resp->pnf_phy.phy[i].phy_config_index; - NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] (PHY:%d) phy_config_idx:%d\n", i, resp->pnf_phy.phy[i].phy_config_index); - nfapi_vnf_allocate_phy(config, p5_idx, &(phy.id)); - - for (int j = 0; j < resp->pnf_phy.phy[i].number_of_rfs; ++j) { - NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] (PHY:%d) (RF%d) %d\n", i, j, resp->pnf_phy.phy[i].rf_config[j].rf_config_index); - phy.rfs[0] = resp->pnf_phy.phy[i].rf_config[j].rf_config_index; - } - - pnf->phys[0] = phy; - } - nfapi_nr_pnf_config_request_t req; - memset(&req, 0, sizeof(req)); - req.header.message_id = NFAPI_PNF_CONFIG_REQUEST; - req.pnf_phy_rf_config.tl.tag = NFAPI_PNF_PHY_RF_TAG; - req.pnf_phy_rf_config.number_phy_rf_config_info = 2; // DJP pnf.phys.size(); - NFAPI_TRACE(NFAPI_TRACE_INFO, "DJP:Hard coded num phy rf to 2\n"); - - for (unsigned i = 0; i < 2; ++i) { - req.pnf_phy_rf_config.phy_rf_config[i].phy_id = pnf->phys[i].id; - req.pnf_phy_rf_config.phy_rf_config[i].phy_config_index = pnf->phys[i].index; - req.pnf_phy_rf_config.phy_rf_config[i].rf_config_index = pnf->phys[i].rfs[0]; - } - - nfapi_nr_vnf_pnf_config_req(config, p5_idx, &req); - return 0; -} - -int aerial_pnf_nr_config_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_nr_pnf_config_response_t *resp) -{ - NFAPI_TRACE(NFAPI_TRACE_INFO, - "[VNF] pnf config response idx:%d resp[header[phy_id:%u message_id:%02x message_length:%u]]\n", - p5_idx, - resp->header.phy_id, - resp->header.message_id, - resp->header.message_length); - - if (1) { - nfapi_nr_pnf_start_request_t req; - memset(&req, 0, sizeof(req)); - req.header.phy_id = resp->header.phy_id; - req.header.message_id = NFAPI_PNF_START_REQUEST; - nfapi_nr_vnf_pnf_start_req(config, p5_idx, &req); - } else { - // Rather than send the pnf_start_request we will demonstrate - // sending a vendor extention message. The start request will be - // send when the vendor extension response is received - // vnf_info* vnf = (vnf_info*)(config->user_data); - vendor_ext_p5_req req; - memset(&req, 0, sizeof(req)); - req.header.message_id = P5_VENDOR_EXT_REQ; - req.dummy1 = 45; - req.dummy2 = 1977; - nfapi_vnf_vendor_extension(config, p5_idx, &req.header); - } - - return 0; -} - -int aerial_pnf_nr_start_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_nr_pnf_start_response_t *resp) -{ - vnf_info *vnf = (vnf_info *)(config->user_data); - vnf_p7_info *p7_vnf = vnf->p7_vnfs; - pnf_info *pnf = vnf->pnfs; - nfapi_nr_param_request_scf_t req; - NFAPI_TRACE(NFAPI_TRACE_INFO, - "[VNF] pnf start response idx:%d config:%p user_data:%p p7_vnf[config:%p thread_started:%d]\n", - p5_idx, - config, - config->user_data, - vnf->p7_vnfs[0].config, - vnf->p7_vnfs[0].thread_started); - - aerial_vnf_nr_p7_config_init(p7_vnf); - - // start all the phys in the pnf. - NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Sending NFAPI_VNF_PARAM_REQUEST phy_id:%d\n", pnf->phys[0].id); - memset(&req, 0, sizeof(req)); - req.header.message_id = NFAPI_NR_PHY_MSG_TYPE_PARAM_REQUEST; - req.header.phy_id = pnf->phys[0].id; - nfapi_nr_vnf_param_req(config, p5_idx, &req); - return 0; -} - -int aerial_nr_param_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_nr_param_response_scf_t *resp) -{ - NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Received NFAPI_PARAM_RESP idx:%d phy_id:%d\n", p5_idx, resp->header.phy_id); - vnf_info *vnf = (vnf_info *)(config->user_data); - vnf_p7_info *p7_vnf = vnf->p7_vnfs; - pnf_info *pnf = vnf->pnfs; - phy_info *phy = pnf->phys; - struct sockaddr_in pnf_p7_sockaddr; - nfapi_nr_config_request_scf_t *req = &RC.nrmac[0]->config[0]; // check - phy->remote_port = resp->nfapi_config.p7_pnf_port.value; - // phy->remote_port = 32123;//resp->nfapi_config.p7_pnf_port.value; - memcpy(&pnf_p7_sockaddr.sin_addr.s_addr, &(resp->nfapi_config.p7_pnf_address_ipv4.address[0]), 4); - phy->remote_addr = inet_ntoa(pnf_p7_sockaddr.sin_addr); - // for now just 1 - NFAPI_TRACE(NFAPI_TRACE_INFO, - "[VNF] %d.%d pnf p7 %s:%d timing %u %u %u %u\n", - p5_idx, - phy->id, - phy->remote_addr, - phy->remote_port, - p7_vnf->timing_window, - p7_vnf->periodic_timing_period, - p7_vnf->aperiodic_timing_enabled, - p7_vnf->periodic_timing_period); - req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_CONFIG_REQUEST; - req->header.phy_id = phy->id; - NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Send NFAPI_CONFIG_REQUEST\n"); - // NFAPI_TRACE(NFAPI_TRACE_INFO, "\n NR bandP =%d\n",req->nfapi_config.rf_bands.rf_band[0]); - - req->nfapi_config.p7_vnf_port.tl.tag = NFAPI_NR_NFAPI_P7_VNF_PORT_TAG; - req->nfapi_config.p7_vnf_port.value = p7_vnf->local_port; - req->num_tlv++; - NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] DJP local_port:%d\n", ntohs(p7_vnf->local_port)); - req->nfapi_config.p7_vnf_address_ipv4.tl.tag = NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV4_TAG; - struct sockaddr_in vnf_p7_sockaddr; - vnf_p7_sockaddr.sin_addr.s_addr = inet_addr(p7_vnf->local_addr); - memcpy(&(req->nfapi_config.p7_vnf_address_ipv4.address[0]), &vnf_p7_sockaddr.sin_addr.s_addr, 4); - req->num_tlv++; - NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] DJP local_addr:%s\n", p7_vnf->local_addr); - req->nfapi_config.timing_window.tl.tag = NFAPI_NR_NFAPI_TIMING_WINDOW_TAG; - req->nfapi_config.timing_window.value = p7_vnf->timing_window; - NFAPI_TRACE(NFAPI_TRACE_INFO, - "\n[VNF]Timing window tag : %d Timing window:%u\n", - NFAPI_NR_NFAPI_TIMING_WINDOW_TAG, - p7_vnf->timing_window); - req->num_tlv++; - - if (p7_vnf->periodic_timing_enabled || p7_vnf->aperiodic_timing_enabled) { - req->nfapi_config.timing_info_mode.tl.tag = NFAPI_NR_NFAPI_TIMING_INFO_MODE_TAG; - req->nfapi_config.timing_info_mode.value = (p7_vnf->aperiodic_timing_enabled << 1) | (p7_vnf->periodic_timing_enabled); - req->num_tlv++; - - if (p7_vnf->periodic_timing_enabled) { - req->nfapi_config.timing_info_period.tl.tag = NFAPI_NR_NFAPI_TIMING_INFO_PERIOD_TAG; - req->nfapi_config.timing_info_period.value = p7_vnf->periodic_timing_period; - req->num_tlv++; - } - } - // TODO: Assign tag and value for P7 message offsets - req->nfapi_config.dl_tti_timing_offset.tl.tag = NFAPI_NR_NFAPI_DL_TTI_TIMING_OFFSET; - req->nfapi_config.ul_tti_timing_offset.tl.tag = NFAPI_NR_NFAPI_UL_TTI_TIMING_OFFSET; - req->nfapi_config.ul_dci_timing_offset.tl.tag = NFAPI_NR_NFAPI_UL_DCI_TIMING_OFFSET; - req->nfapi_config.tx_data_timing_offset.tl.tag = NFAPI_NR_NFAPI_TX_DATA_TIMING_OFFSET; - - vendor_ext_tlv_2 ve2; - memset(&ve2, 0, sizeof(ve2)); - ve2.tl.tag = VENDOR_EXT_TLV_2_TAG; - ve2.dummy = 2016; - req->vendor_extension = &ve2.tl; - nfapi_nr_vnf_config_req(config, p5_idx, req); - printf("[VNF] Sent NFAPI_VNF_CONFIG_REQ num_tlv:%u\n", req->num_tlv); - return 0; -} - -int aerial_nr_send_config_request(nfapi_vnf_config_t *config, int p5_idx) -{ - vnf_info *vnf = (vnf_info *)(config->user_data); - vnf_p7_info *p7_vnf = vnf->p7_vnfs; - pnf_info *pnf = vnf->pnfs; - phy_info *phy = pnf->phys; - - nfapi_nr_config_request_scf_t *req = &RC.nrmac[0]->config[0]; - - NFAPI_TRACE(NFAPI_TRACE_INFO, - "[VNF] %d.%d pnf p7 %s:%d timing %u %u %u %u\n", - p5_idx, - phy->id, - phy->remote_addr, - phy->remote_port, - p7_vnf->timing_window, - p7_vnf->periodic_timing_period, - p7_vnf->aperiodic_timing_enabled, - p7_vnf->periodic_timing_period); - req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_CONFIG_REQUEST; - req->header.phy_id = phy->id; - NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Send NFAPI_CONFIG_REQUEST\n"); - - vnf_t *_this = (vnf_t *)(config); - - nfapi_vnf_phy_info_t *vnf_phy = nfapi_vnf_phy_info_list_find(config, req->header.phy_id); - - if (vnf_phy == NULL) { - printf("%s failed to find phy information phy_id:%d\n", __FUNCTION__, req->header.phy_id); - return -1; - } - - nfapi_nr_p4_p5_message_header_t *msg = &req->header; - uint16_t msg_len = sizeof(nfapi_nr_config_request_scf_t); - uint8_t tx_messagebufferFAPI[sizeof(_this->tx_message_buffer)]; - int packedMessageLengthFAPI = -1; - packedMessageLengthFAPI = - fapi_nr_p5_message_pack(msg, msg_len, tx_messagebufferFAPI, sizeof(tx_messagebufferFAPI), &_this->_public.codec_config); - - aerial_send_P5_msg(tx_messagebufferFAPI, packedMessageLengthFAPI, msg); - - return 0; -} - -int aerial_nr_config_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_nr_config_response_scf_t *resp) -{ - nfapi_nr_start_request_scf_t req; - NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Received NFAPI_CONFIG_RESP idx:%d phy_id:%d\n", p5_idx, resp->header.phy_id); - LOG_I(NFAPI_VNF, "Received CONFIG.response, gNB is ready! \n"); - - memset(&req, 0, sizeof(req)); - req.header.message_id = NFAPI_NR_PHY_MSG_TYPE_START_REQUEST; - req.header.phy_id = resp->header.phy_id; - nfapi_nr_vnf_start_req(config, p5_idx, &req); - return 0; -} - -int aerial_nr_start_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_nr_start_response_scf_t *resp) -{ - NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Received NFAPI_START_RESP idx:%d phy_id:%d\n", p5_idx, resp->header.phy_id); - return 0; -} - -int aerial_vendor_ext_cb(nfapi_vnf_config_t *config, int p5_idx, void *msg) -{ - NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] %s\n", __FUNCTION__); - - switch (((nfapi_nr_p4_p5_message_header_t *)msg)->message_id) { - case P5_VENDOR_EXT_RSP: { - vendor_ext_p5_rsp *rsp = (vendor_ext_p5_rsp *)msg; - NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] P5_VENDOR_EXT_RSP error_code:%d\n", rsp->error_code); - // send the start request - nfapi_nr_pnf_start_request_t req; - memset(&req, 0, sizeof(req)); - req.header.message_id = NFAPI_PNF_START_REQUEST; - nfapi_nr_vnf_pnf_start_req(config, p5_idx, &req); - } break; - } - - return 0; -} - -int aerial_vnf_unpack_vendor_extension_tlv(nfapi_tl_t *tl, - uint8_t **ppReadPackedMessage, - uint8_t *end, - void **ve, - nfapi_p4_p5_codec_config_t *codec) -{ - return -1; -} - -int aerial_vnf_pack_vendor_extension_tlv(void *vext, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *codec) -{ - nfapi_tl_t *tlv = (nfapi_tl_t *)vext; - - switch (tlv->tag) { - case VENDOR_EXT_TLV_2_TAG: { - vendor_ext_tlv_2 *ve = (vendor_ext_tlv_2 *)tlv; - - if (!push32(ve->dummy, ppWritePackedMsg, end)) - return 0; - - return 1; - } break; - } - - return -1; -} - -int aerial_vnf_unpack_p4_p5_vendor_extension(void *header, - uint8_t **ppReadPackedMessage, - uint8_t *end, - nfapi_p4_p5_codec_config_t *codec) -{ - if (((nfapi_nr_p4_p5_message_header_t *)header)->message_id == P5_VENDOR_EXT_RSP) { - vendor_ext_p5_rsp *req = (vendor_ext_p5_rsp *)(header); - return (!pull16(ppReadPackedMessage, &req->error_code, end)); - } - - return 0; -} - -int aerial_vnf_pack_p4_p5_vendor_extension(void *header, - uint8_t **ppWritePackedMsg, - uint8_t *end, - nfapi_p4_p5_codec_config_t *codec) -{ - if (((nfapi_nr_p4_p5_message_header_t *)header)->message_id == P5_VENDOR_EXT_REQ) { - vendor_ext_p5_req *req = (vendor_ext_p5_req *)(header); - return (!(push16(req->dummy1, ppWritePackedMsg, end) && push16(req->dummy2, ppWritePackedMsg, end))); - } - - return 0; -} - -void *aerial_vnf_allocate_p4_p5_vendor_ext(uint16_t message_id, uint16_t *msg_size) -{ - if (message_id == P5_VENDOR_EXT_RSP) { - *msg_size = sizeof(vendor_ext_p5_rsp); - return malloc(sizeof(vendor_ext_p5_rsp)); - } - - return 0; -} - -void aerial_vnf_deallocate_p4_p5_vendor_ext(void *header) -{ - free(header); -} - -void *aerial_vnf_p5_allocate(size_t size) -{ - // return (void*)memory_pool::allocate(size); - return (void *)malloc(size); -} - -void aerial_vnf_p5_deallocate(void *ptr) -{ - // memory_pool::deallocate((uint8_t*)ptr); - free(ptr); -} - -static vnf_info aerial_vnf; -void aerial_configure_nr_fapi_vnf() -{ - // TODO: Implement for FAPI - // nfapi_setmode(NFAPI_MODE_VNF); - memset(&aerial_vnf, 0, sizeof(aerial_vnf)); - memset(aerial_vnf.p7_vnfs, 0, sizeof(aerial_vnf.p7_vnfs)); - aerial_vnf.p7_vnfs[0].timing_window = 30; - aerial_vnf.p7_vnfs[0].periodic_timing_enabled = 0; - aerial_vnf.p7_vnfs[0].aperiodic_timing_enabled = 0; - aerial_vnf.p7_vnfs[0].periodic_timing_period = 10; - aerial_vnf.p7_vnfs[0].config = nfapi_vnf_p7_config_create(); - aerial_vnf.p7_vnfs[0].mac = (mac_t *)malloc(sizeof(mac_t)); - nfapi_vnf_config_t *config = nfapi_vnf_config_create(); - config->malloc = malloc; - config->free = free; - config->vnf_ipv4 = 1; - config->vnf_ipv6 = 0; - config->pnf_list = 0; - config->phy_list = 0; - - config->pnf_nr_connection_indication = &aerial_pnf_nr_connection_indication_cb; - config->pnf_disconnect_indication = &aerial_pnf_disconnection_indication_cb; - - config->pnf_nr_param_resp = &aerial_pnf_nr_param_resp_cb; - config->pnf_nr_config_resp = &aerial_pnf_nr_config_resp_cb; - config->pnf_nr_start_resp = &aerial_pnf_nr_start_resp_cb; - config->nr_param_resp = &aerial_nr_param_resp_cb; - config->nr_config_resp = &aerial_nr_config_resp_cb; - config->nr_start_resp = &aerial_nr_start_resp_cb; - config->vendor_ext = &aerial_vendor_ext_cb; - config->user_data = &aerial_vnf; - // To allow custom vendor extentions to be added to nfapi - config->codec_config.unpack_vendor_extension_tlv = &aerial_vnf_unpack_vendor_extension_tlv; - config->codec_config.pack_vendor_extension_tlv = &aerial_vnf_pack_vendor_extension_tlv; - config->codec_config.unpack_p4_p5_vendor_extension = &aerial_vnf_unpack_p4_p5_vendor_extension; - config->codec_config.pack_p4_p5_vendor_extension = &aerial_vnf_pack_p4_p5_vendor_extension; - config->allocate_p4_p5_vendor_ext = &aerial_vnf_allocate_p4_p5_vendor_ext; - config->deallocate_p4_p5_vendor_ext = &aerial_vnf_deallocate_p4_p5_vendor_ext; - config->codec_config.allocate = &aerial_vnf_allocate; - config->codec_config.deallocate = &aerial_vnf_deallocate; - memset(&UL_RCC_INFO, 0, sizeof(UL_RCC_IND_t)); - NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Creating VNF NFAPI start thread %s\n", __FUNCTION__); - set_config(config); - NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Created VNF NFAPI start thread %s\n", __FUNCTION__); - nfapi_vnf_pnf_info_t *pnf = (nfapi_vnf_pnf_info_t *)malloc(sizeof(nfapi_vnf_pnf_info_t)); - NFAPI_TRACE(NFAPI_TRACE_INFO, "MALLOC nfapi_vnf_pnf_info_t for pnf_list pnf:%p\n", pnf); - memset(pnf, 0, sizeof(nfapi_vnf_pnf_info_t)); - pnf->p5_idx = 1; - pnf->connected = 1; - // Add needed parameters - - vnf_info *vnf = (vnf_info *)(config->user_data); - pnf_info *pnf_info = vnf->pnfs; - - for (int i = 0; i < 1; ++i) { - phy_info phy; - memset(&phy, 0, sizeof(phy)); - phy.index = 0; - NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] (PHY:%d) phy_config_idx:%d\n", i, 0); - nfapi_vnf_allocate_phy(config, 1, &(phy.id)); - - for (int j = 0; j < 1; ++j) { - NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] (PHY:%d) (RF%d) %d\n", i, j, 0); - phy.rfs[0] = 0; - } - - pnf_info->phys[0] = phy; - } - - - nfapi_vnf_pnf_list_add(config, pnf); - - vnf_p7_info *p7_vnf = vnf->p7_vnfs; - - NFAPI_TRACE(NFAPI_TRACE_INFO, - "[VNF] pnf start response idx:%d config:%p user_data:%p p7_vnf[config:%p thread_started:%d]\n", - 1, - config, - config->user_data, - vnf->p7_vnfs[0].config, - vnf->p7_vnfs[0].thread_started); - - aerial_vnf_nr_p7_config_init(p7_vnf); -} -uint8_t aerial_unpack_nr_param_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) -{ - return unpack_nr_param_response(ppReadPackedMsg, end, msg, config); -} -uint8_t aerial_unpack_nr_config_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) -{ - return unpack_nr_config_response(ppReadPackedMsg, end, msg, config); -} - -int oai_fapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req) -{ - nfapi_vnf_p7_config_t *p7_config = aerial_vnf.p7_vnfs[0].config; - - ul_tti_req->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! - ul_tti_req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST; - - // int retval = nfapi_vnf_p7_ul_tti_req(p7_config, ul_tti_req); - int retval = fapi_nr_pack_and_send_p7_message((vnf_p7_t *)p7_config, &ul_tti_req->header); - - if (retval != 0) { - LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval); - } else { - // Reset number of PDUs so that it is not resent - ul_tti_req->n_pdus = 0; - ul_tti_req->n_group = 0; - ul_tti_req->n_ulcch = 0; - ul_tti_req->n_ulsch = 0; - } - return retval; -} - -int oai_fapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req) -{ - nfapi_vnf_p7_config_t *p7_config = aerial_vnf.p7_vnfs[0].config; - ul_dci_req->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! - ul_dci_req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST; - // int retval = nfapi_vnf_p7_ul_dci_req(p7_config, ul_dci_req); - int retval = fapi_nr_pack_and_send_p7_message((vnf_p7_t *)p7_config, &ul_dci_req->header); - if (retval != 0) { - LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval); - } else { - ul_dci_req->numPdus = 0; - } - return retval; -} - -int oai_fapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req) -{ - nfapi_vnf_p7_config_t *p7_config = aerial_vnf.p7_vnfs[0].config; - tx_data_req->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! - tx_data_req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST; - // LOG_D(PHY, "[VNF] %s() TX_REQ sfn_sf:%d number_of_pdus:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(tx_data_req->SFN), - // tx_data_req->Number_of_PDUs); int retval = nfapi_vnf_p7_tx_data_req(p7_config, tx_data_req); - int retval = fapi_nr_pack_and_send_p7_message((vnf_p7_t *)p7_config, &tx_data_req->header); - if (retval != 0) { - LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval); - } else { - tx_data_req->Number_of_PDUs = 0; - } - - return retval; -} - -int oai_fapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req) -{ - nfapi_vnf_p7_config_t *p7_config = aerial_vnf.p7_vnfs[0].config; - dl_config_req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST; - dl_config_req->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! - int retval = fapi_nr_pack_and_send_p7_message((vnf_p7_t *)p7_config, &dl_config_req->header); - dl_config_req->dl_tti_request_body.nPDUs = 0; - dl_config_req->dl_tti_request_body.nGroup = 0; - - if (retval != 0) { - LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval); - } - return retval; -} - -int oai_fapi_send_end_request(int cell, uint32_t frame, uint32_t slot){ - nfapi_vnf_p7_config_t *p7_config = aerial_vnf.p7_vnfs[0].config; - nfapi_nr_slot_indication_scf_t nr_slot_resp = {.header.message_id = 0x8F, .sfn = frame, .slot = slot}; - int retval = fapi_nr_pack_and_send_p7_message((vnf_p7_t *)p7_config, &nr_slot_resp.header); - if (retval != 0) { - LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval); - } - return retval; -} diff --git a/nfapi/oai_integration/aerial/fapi_vnf_p5.h b/nfapi/oai_integration/aerial/fapi_vnf_p5.h deleted file mode 100644 index 84fb3ec2f8..0000000000 --- a/nfapi/oai_integration/aerial/fapi_vnf_p5.h +++ /dev/null @@ -1,72 +0,0 @@ -/* -* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more -* contributor license agreements. See the NOTICE file distributed with -* this work for additional information regarding copyright ownership. -* The OpenAirInterface Software Alliance licenses this file to You under -* the OAI Public License, Version 1.1 (the "License"); you may not use this file -* except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.openairinterface.org/?page_id=698 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*------------------------------------------------------------------------------- -* For more information about the OpenAirInterface (OAI) Software Alliance: -* contact@openairinterface.org - */ - -/*! \file fapi/oai-integration/fapi_vnf_p5.h -* \brief Header file for fapi_vnf_p5.c -* \author Ruben S. Silva -* \date 2023 -* \version 0.1 -* \company OpenAirInterface Software Alliance -* \email: contact@openairinterface.org, rsilva@allbesmart.pt -* \note -* \warning - */ - -#ifndef OPENAIRINTERFACE_FAPI_VNF_P5_H -#define OPENAIRINTERFACE_FAPI_VNF_P5_H -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "nfapi_nr_interface_scf.h" -#include "nfapi_vnf_interface.h" -#include "nfapi_vnf.h" -#include "nfapi.h" -#include "nfapi/oai_integration/vendor_ext.h" -#include "fapi_nvIPC.h" - -#include "PHY/defs_eNB.h" -#include "PHY/LTE_TRANSPORT/transport_proto.h" - -#include "common/ran_context.h" -#include "openair2/PHY_INTERFACE/queue_t.h" -#include "gnb_ind_vars.h" -#include "nfapi/open-nFAPI/vnf/inc/vnf.h" - -void aerial_configure_nr_fapi_vnf(); -int aerial_nr_send_config_request(nfapi_vnf_config_t *config, int p5_idx); -int oai_fapi_send_end_request(int cell_id, uint32_t frame, uint32_t slot); -uint8_t aerial_unpack_nr_param_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config); -uint8_t aerial_unpack_nr_config_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config); -int aerial_pnf_nr_connection_indication_cb(nfapi_vnf_config_t *config, int p5_idx); - -int oai_fapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req); -int oai_fapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req); -int oai_fapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req); -int oai_fapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req); -#endif //OPENAIRINTERFACE_FAPI_VNF_P5_H diff --git a/nfapi/oai_integration/nfapi_vnf.c b/nfapi/oai_integration/nfapi_vnf.c index be0270e28a..a2f3d579e3 100644 --- a/nfapi/oai_integration/nfapi_vnf.c +++ b/nfapi/oai_integration/nfapi_vnf.c @@ -63,7 +63,7 @@ #include #ifdef ENABLE_AERIAL -#include "aerial/fapi_vnf_p5.h" +#include "aerial/fapi_nvIPC.h" #include "nr_fapi_p5.h" #endif diff --git a/nfapi/open-nFAPI/vnf/src/vnf.c b/nfapi/open-nFAPI/vnf/src/vnf.c index 345dada3ec..d669573168 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf.c +++ b/nfapi/open-nFAPI/vnf/src/vnf.c @@ -29,7 +29,6 @@ #include "nfapi_nr_interface_scf.h" #ifdef ENABLE_AERIAL #include "nfapi/oai_integration/aerial/fapi_nvIPC.h" -#include "nfapi/oai_integration/aerial/fapi_vnf_p5.h" #include "nr_fapi_p5.h" #endif #ifdef ENABLE_WLS diff --git a/openair1/SCHED_NR/fapi_nr_l1.c b/openair1/SCHED_NR/fapi_nr_l1.c index 6b671abcfe..74a2178982 100644 --- a/openair1/SCHED_NR/fapi_nr_l1.c +++ b/openair1/SCHED_NR/fapi_nr_l1.c @@ -29,9 +29,6 @@ * \note * \warning */ -#ifdef ENABLE_AERIAL -#include "nfapi/oai_integration/aerial/fapi_vnf_p5.h" -#endif #include "fapi_nr_l1.h" #include "common/ran_context.h" #include "PHY/NR_TRANSPORT/nr_transport_proto.h" diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index ebda616dfc..cc38dd060c 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -78,9 +78,7 @@ #include "uper_encoder.h" #include "utils.h" #include "x2ap_messages_types.h" -#ifdef ENABLE_AERIAL -#include "nfapi/oai_integration/aerial/fapi_vnf_p5.h" -#endif + static int DEFBANDS[] = {7}; static int DEFENBS[] = {0}; From b8a176e38f098220a1e996b9c206bd717e9e26e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Soares=20Silva?= Date: Thu, 20 Mar 2025 17:07:10 +0000 Subject: [PATCH 210/964] Use existing VNF functions for P7 messages Remove duplicated functions in fapi_vnf_p7.c, leaving only functions for messages that require usage of the secondaty data_buf for unpacking Move vnf_info struct declaration to nfapi_vnf.h to be available in fapi_nvIPC.c --- nfapi/oai_integration/aerial/fapi_nvIPC.c | 164 +++++--------- nfapi/oai_integration/aerial/fapi_nvIPC.h | 5 +- nfapi/oai_integration/aerial/fapi_vnf_p7.c | 249 ++------------------- nfapi/oai_integration/aerial/fapi_vnf_p7.h | 170 +------------- nfapi/oai_integration/nfapi_vnf.c | 134 +---------- nfapi/oai_integration/nfapi_vnf.h | 123 ++++++++++ nfapi/oai_integration/socket/socket_vnf.c | 22 +- 7 files changed, 214 insertions(+), 653 deletions(-) diff --git a/nfapi/oai_integration/aerial/fapi_nvIPC.c b/nfapi/oai_integration/aerial/fapi_nvIPC.c index 0259eda06a..b1bfae5415 100644 --- a/nfapi/oai_integration/aerial/fapi_nvIPC.c +++ b/nfapi/oai_integration/aerial/fapi_nvIPC.c @@ -48,11 +48,13 @@ #include #include #include "fapi_nvIPC.h" +#include +#include #include "nfapi_interface.h" #include "nfapi.h" #include "nfapi_nr_interface_scf.h" #include "nfapi/open-nFAPI/vnf/inc/vnf_p7.h" - +#include "system.h" #include "fapi_vnf_p7.h" #define MAX_EVENTS 10 @@ -92,40 +94,12 @@ static int ipc_handle_rx_msg(nv_ipc_t *ipc, nv_ipc_msg_t *msg) return -1; } + vnf_p7_t *vnf_p7_config = (vnf_p7_t *)((vnf_info *)vnf_config->user_data)->p7_vnfs->config; switch (fapi_msg.message_id) { case NFAPI_NR_PHY_MSG_TYPE_PARAM_RESPONSE ... NFAPI_NR_PHY_MSG_TYPE_ERROR_INDICATION: vnf_nr_handle_p4_p5_message(msg->msg_buf, msg->msg_len, 1, vnf_config); break; // P7 Messages - // P7 Message Handlers -> ((vnf_info *)vnf_config->user_data)->p7_vnfs->config-> - case NFAPI_NR_PHY_MSG_TYPE_SLOT_INDICATION: { - nfapi_nr_slot_indication_scf_t ind; - aerial_unpack_nr_slot_indication(&pReadPackedMessage, - end, - &ind, - &((vnf_p7_t *)((vnf_info *)vnf_config->user_data)->p7_vnfs->config)->_public.codec_config); - // check if the sfn/slot unpacked come wrong at any time, should be old + 1 (slot 0 -- 19, sfn 0 -- 1023) - // add 1 to current sfn number - uint16_t old_slot_plus = ((old_slot + 1) % 20); - uint16_t old_sfn_plus = old_slot_plus == 0 ? ((old_sfn + 1) % 1024) : old_sfn; - if (old_slot_plus != ind.slot || old_sfn_plus != ind.sfn) { - LOG_E(NFAPI_VNF, - "\n============================================================================\n" - "sfn slot doesn't match unpacked one! L2->L1 %d.%d vs L1->L2 %d.%d \n" - "============================================================================\n", - old_sfn, - old_slot, - ind.sfn, - ind.slot); - } - old_sfn = ind.sfn; - old_slot = ind.slot; - if (((vnf_info *)vnf_config->user_data)->p7_vnfs->config->nr_slot_indication) { - (((vnf_info *)vnf_config->user_data)->p7_vnfs->config->nr_slot_indication)(&ind); - } - break; - } - case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION: { uint8_t *pReadData = msg->data_buf; int dataBufLen = msg->data_len; @@ -139,10 +113,10 @@ static int ipc_handle_rx_msg(nv_ipc_t *ipc, nv_ipc_msg_t *msg) &pReadData, data_end, &ind, - &((vnf_p7_t *)((vnf_info *)vnf_config->user_data)->p7_vnfs->config)->_public.codec_config); + &vnf_p7_config->_public.codec_config); NFAPI_TRACE(NFAPI_TRACE_INFO, "%s: Handling RX Indication\n", __FUNCTION__); - if (((vnf_info *)vnf_config->user_data)->p7_vnfs->config->nr_rx_data_indication) { - (((vnf_info *)vnf_config->user_data)->p7_vnfs->config->nr_rx_data_indication)(&ind); + if (vnf_p7_config->_public.nr_rx_data_indication) { + (vnf_p7_config->_public.nr_rx_data_indication)(&ind); for (int i = 0; i < ind.number_of_pdus; ++i) { free(ind.pdu_list[i].pdu); } @@ -151,53 +125,6 @@ static int ipc_handle_rx_msg(nv_ipc_t *ipc, nv_ipc_msg_t *msg) break; } - case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION: { - nfapi_nr_crc_indication_t crc_ind; - crc_ind.header.message_id = fapi_msg.message_id; - crc_ind.header.message_length = fapi_msg.message_length; - aerial_unpack_nr_crc_indication(&pReadPackedMessage, - end, - &crc_ind, - &((vnf_p7_t *)((vnf_info *)vnf_config->user_data)->p7_vnfs->config)->_public.codec_config); - if (((vnf_info *)vnf_config->user_data)->p7_vnfs->config->nr_crc_indication) { - (((vnf_info *)vnf_config->user_data)->p7_vnfs->config->nr_crc_indication)(&crc_ind); - free(crc_ind.crc_list); - } - break; - } - - case NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION: { - nfapi_nr_uci_indication_t ind; - aerial_unpack_nr_uci_indication(&pReadPackedMessage, - end, - &ind, - &((vnf_p7_t *)((vnf_info *)vnf_config->user_data)->p7_vnfs->config)->_public.codec_config); - - if (((vnf_info *)vnf_config->user_data)->p7_vnfs->config->nr_uci_indication) { - (((vnf_info *)vnf_config->user_data)->p7_vnfs->config->nr_uci_indication)(&ind); - for (int i = 0; i < ind.num_ucis; i++) { - if (ind.uci_list[i].pdu_type == NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE) { - if (ind.uci_list[i].pucch_pdu_format_2_3_4.sr.sr_payload) { - free(ind.uci_list[i].pucch_pdu_format_2_3_4.sr.sr_payload); - } - if(ind.uci_list[i].pucch_pdu_format_2_3_4.harq.harq_payload){ - free(ind.uci_list[i].pucch_pdu_format_2_3_4.harq.harq_payload); - } - if(ind.uci_list[i].pucch_pdu_format_2_3_4.csi_part1.csi_part1_payload){ - free(ind.uci_list[i].pucch_pdu_format_2_3_4.csi_part1.csi_part1_payload); - } - if(ind.uci_list[i].pucch_pdu_format_2_3_4.csi_part2.csi_part2_payload){ - free(ind.uci_list[i].pucch_pdu_format_2_3_4.csi_part2.csi_part2_payload); - } - } - } - free(ind.uci_list); - ind.uci_list = NULL; - } - - break; - } - case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION: { uint8_t *pReadData = msg->data_buf; int dataBufLen = msg->data_len; @@ -208,26 +135,47 @@ static int ipc_handle_rx_msg(nv_ipc_t *ipc, nv_ipc_msg_t *msg) &pReadData, data_end, &ind, - &((vnf_p7_t *)((vnf_info *)vnf_config->user_data)->p7_vnfs->config)->_public.codec_config); - if (((vnf_info *)vnf_config->user_data)->p7_vnfs->config->nr_srs_indication) { - (((vnf_info *)vnf_config->user_data)->p7_vnfs->config->nr_srs_indication)(&ind); + &vnf_p7_config->_public.codec_config); + if (vnf_p7_config->_public.nr_srs_indication) { + (vnf_p7_config->_public.nr_srs_indication)(&ind); } break; } + case NFAPI_NR_PHY_MSG_TYPE_SLOT_INDICATION: { + nfapi_nr_slot_indication_scf_t ind; + if (!vnf_p7_config->_public.unpack_func(msg->msg_buf, msg->msg_len, &ind, sizeof(ind), &vnf_p7_config->_public.codec_config)) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); + } else { + NFAPI_TRACE(NFAPI_TRACE_DEBUG, "%s: Handling NR SLOT Indication\n", __FUNCTION__); + // check if the sfn/slot unpacked come wrong at any time, should be old + 1 (slot 0 -- 19, sfn 0 -- 1023) + // add 1 to current sfn number + uint16_t old_slot_plus = ((old_slot + 1) % 20); + uint16_t old_sfn_plus = old_slot_plus == 0 ? ((old_sfn + 1) % 1024) : old_sfn; + if (old_slot_plus != ind.slot || old_sfn_plus != ind.sfn) { + LOG_E(NFAPI_VNF, + "\n============================================================================\n" + "sfn slot doesn't match unpacked one! L2->L1 %d.%d vs L1->L2 %d.%d \n" + "============================================================================\n", + old_sfn, + old_slot, + ind.sfn, + ind.slot); + } + old_sfn = ind.sfn; + old_slot = ind.slot; + if (vnf_p7_config->_public.nr_slot_indication) { + (vnf_p7_config->_public.nr_slot_indication)(&ind); + } + } + break; + } + case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION: + case NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION: case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: { - nfapi_nr_rach_indication_t ind; - aerial_unpack_nr_rach_indication(&pReadPackedMessage, - end, - &ind, - &((vnf_p7_t *)((vnf_info *)vnf_config->user_data)->p7_vnfs->config)->_public.codec_config); - if (((vnf_info *)vnf_config->user_data)->p7_vnfs->config->nr_rach_indication) { - (((vnf_info *)vnf_config->user_data)->p7_vnfs->config->nr_rach_indication)(&ind); - free(ind.pdu_list); - } + vnf_nr_handle_p7_message(msg->msg_buf, msg->msg_len, vnf_p7_config); break; } - default: { NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s P5 Unknown message ID %d\n", __FUNCTION__, fapi_msg.message_id); @@ -322,10 +270,10 @@ bool aerial_send_P5_msg(void *packedBuf, uint32_t packedMsgLength, nfapi_nr_p4_p return true; } -int aerial_send_P7_msg(void *packedBuf, uint32_t packedMsgLength, nfapi_nr_p7_message_header_t *header) +bool aerial_send_P7_msg(void *packedBuf, uint32_t packedMsgLength, nfapi_nr_p7_message_header_t *header) { if (ipc == NULL) { - return -1; + return false; } nv_ipc_msg_t send_msg; uint8_t *pPacketBodyField = &((uint8_t *)packedBuf)[8]; @@ -386,7 +334,7 @@ int aerial_send_P7_msg(void *packedBuf, uint32_t packedMsgLength, nfapi_nr_p7_me if (alloc_retval != 0) { LOG_E(NFAPI_VNF, "%s error: allocate TX buffer failed Error: %d\n", __FUNCTION__, alloc_retval); ipc->tx_release(ipc, &send_msg); - return alloc_retval; + return false; } memcpy(send_msg.msg_buf, packedBuf, send_msg.msg_len); @@ -402,21 +350,21 @@ int aerial_send_P7_msg(void *packedBuf, uint32_t packedMsgLength, nfapi_nr_p7_me if (send_retval < 0) { LOG_E(NFAPI_VNF, "%s error: send TX message failed Error: %d\n", __FUNCTION__, send_retval); ipc->tx_release(ipc, &send_msg); - return send_retval; + return false; } ipc->notify(ipc, 1); // notify that there's 1 message in queue - return 0; + return true; } -int aerial_send_P7_msg_with_data(void *packedBuf, +bool aerial_send_P7_msg_with_data(void *packedBuf, uint32_t packedMsgLength, void *dataBuf, uint32_t dataLength, nfapi_nr_p7_message_header_t *header) { if (ipc == NULL) { - return -1; + return false; } nv_ipc_msg_t send_msg; uint8_t *pPacketBodyField = &((uint8_t *)packedBuf)[8]; @@ -475,7 +423,7 @@ int aerial_send_P7_msg_with_data(void *packedBuf, if (alloc_retval != 0) { LOG_E(NFAPI_VNF, "%s error: allocate TX buffer failed Error: %d\n", __FUNCTION__, alloc_retval); ipc->tx_release(ipc, &send_msg); - return alloc_retval; + return false; } memcpy(send_msg.msg_buf, packedBuf, send_msg.msg_len); @@ -492,11 +440,11 @@ int aerial_send_P7_msg_with_data(void *packedBuf, if (send_retval != 0) { LOG_E(NFAPI_VNF, "%s error: send TX message failed Error: %d\n", __FUNCTION__, send_retval); ipc->tx_release(ipc, &send_msg); - return send_retval; + return false; } ipc->notify(ipc, 1); // notify that there's 1 message in queue - return 0; + return true; } // Always allocate message buffer, but allocate data buffer only when data_len > 0 @@ -634,7 +582,7 @@ int oai_fapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req) ul_tti_req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST; // int retval = nfapi_vnf_p7_ul_tti_req(p7_config, ul_tti_req); - int retval = fapi_nr_pack_and_send_p7_message((vnf_p7_t *)p7_config, &ul_tti_req->header); + int retval = p7_config->send_p7_msg((vnf_p7_t *)p7_config, &ul_tti_req->header); if (retval != 0) { LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval); @@ -654,7 +602,7 @@ int oai_fapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req) ul_dci_req->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! ul_dci_req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST; // int retval = nfapi_vnf_p7_ul_dci_req(p7_config, ul_dci_req); - int retval = fapi_nr_pack_and_send_p7_message((vnf_p7_t *)p7_config, &ul_dci_req->header); + int retval = p7_config->send_p7_msg((vnf_p7_t *)p7_config, &ul_dci_req->header); if (retval != 0) { LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval); } else { @@ -670,7 +618,7 @@ int oai_fapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req) tx_data_req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST; // LOG_D(PHY, "[VNF] %s() TX_REQ sfn_sf:%d number_of_pdus:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(tx_data_req->SFN), // tx_data_req->Number_of_PDUs); int retval = nfapi_vnf_p7_tx_data_req(p7_config, tx_data_req); - int retval = fapi_nr_pack_and_send_p7_message((vnf_p7_t *)p7_config, &tx_data_req->header); + int retval = p7_config->send_p7_msg((vnf_p7_t *)p7_config, &tx_data_req->header); if (retval != 0) { LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval); } else { @@ -685,7 +633,7 @@ int oai_fapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req) nfapi_vnf_p7_config_t *p7_config = (((vnf_info *)vnf_config->user_data)->p7_vnfs[0].config); dl_config_req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST; dl_config_req->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! - int retval = fapi_nr_pack_and_send_p7_message((vnf_p7_t *)p7_config, &dl_config_req->header); + int retval = p7_config->send_p7_msg((vnf_p7_t *)p7_config, &dl_config_req->header); dl_config_req->dl_tti_request_body.nPDUs = 0; dl_config_req->dl_tti_request_body.nGroup = 0; @@ -698,7 +646,7 @@ int oai_fapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req) int oai_fapi_send_end_request(int cell, uint32_t frame, uint32_t slot){ nfapi_vnf_p7_config_t *p7_config = (((vnf_info *)vnf_config->user_data)->p7_vnfs[0].config); nfapi_nr_slot_indication_scf_t nr_slot_resp = {.header.message_id = 0x8F, .sfn = frame, .slot = slot}; - int retval = fapi_nr_pack_and_send_p7_message((vnf_p7_t *)p7_config, &nr_slot_resp.header); + int retval = p7_config->send_p7_msg((vnf_p7_t *)p7_config, &nr_slot_resp.header); if (retval != 0) { LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval); } diff --git a/nfapi/oai_integration/aerial/fapi_nvIPC.h b/nfapi/oai_integration/aerial/fapi_nvIPC.h index 242c2c5822..482d8103f0 100644 --- a/nfapi/oai_integration/aerial/fapi_nvIPC.h +++ b/nfapi/oai_integration/aerial/fapi_nvIPC.h @@ -36,6 +36,7 @@ #include "nv_ipc_utils.h" #include "nvlog.h" #include "nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h" +#include "vnf.h" #include "debug.h" #include "openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h" @@ -49,8 +50,8 @@ typedef struct { bool aerial_nr_send_p5_message(vnf_t *vnf, uint16_t p5_idx, nfapi_nr_p4_p5_message_header_t *msg, uint32_t msg_len); bool aerial_send_P5_msg(void *packedBuf, uint32_t packedMsgLength, nfapi_nr_p4_p5_message_header_t *header); -int aerial_send_P7_msg(void *packedBuf, uint32_t packedMsgLength, nfapi_nr_p7_message_header_t *header); -int aerial_send_P7_msg_with_data(void *packedBuf, +bool aerial_send_P7_msg(void *packedBuf, uint32_t packedMsgLength, nfapi_nr_p7_message_header_t *header); +bool aerial_send_P7_msg_with_data(void *packedBuf, uint32_t packedMsgLength, void *dataBuf, uint32_t dataLength, diff --git a/nfapi/oai_integration/aerial/fapi_vnf_p7.c b/nfapi/oai_integration/aerial/fapi_vnf_p7.c index cb8fa4550f..d9e3e0027b 100644 --- a/nfapi/oai_integration/aerial/fapi_vnf_p7.c +++ b/nfapi/oai_integration/aerial/fapi_vnf_p7.c @@ -35,200 +35,6 @@ #include "nr_fapi_p7.h" #include "nr_fapi_p7_utils.h" -#include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h" // for handle_nr_srs_measurements() - -extern pthread_cond_t nfapi_sync_cond; -extern pthread_mutex_t nfapi_sync_mutex; -extern int nfapi_sync_var; - -int aerial_phy_nr_crc_indication(nfapi_nr_crc_indication_t *ind) -{ - nfapi_nr_crc_indication_t *crc_ind = CALLOC(1, sizeof(*crc_ind)); - copy_crc_indication(ind, crc_ind); - if (!put_queue(&gnb_crc_ind_queue, crc_ind)) { - LOG_E(NR_MAC, "Put_queue failed for crc_ind\n"); - free_crc_indication(crc_ind); - free(crc_ind); - } - return 1; -} - -int aerial_phy_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind) -{ - nfapi_nr_rx_data_indication_t *rx_ind = CALLOC(1, sizeof(*rx_ind)); - copy_rx_data_indication(ind, rx_ind); - if (!put_queue(&gnb_rx_ind_queue, rx_ind)) { - LOG_E(NR_MAC, "Put_queue failed for rx_ind\n"); - free_rx_data_indication(rx_ind); - free(rx_ind); - } - return 1; -} - -int aerial_phy_nr_rach_indication(nfapi_nr_rach_indication_t *ind) -{ - nfapi_nr_rach_indication_t *rach_ind = CALLOC(1, sizeof(*rach_ind)); - copy_rach_indication(ind, rach_ind); - if (!put_queue(&gnb_rach_ind_queue, rach_ind)) { - LOG_E(NR_MAC, "Put_queue failed for rach_ind\n"); - free_rach_indication(rach_ind); - free(rach_ind); - } else { - LOG_I(NR_MAC, "RACH.indication put_queue successfull\n"); - } - return 1; -} - -int aerial_phy_nr_uci_indication(nfapi_nr_uci_indication_t *ind) -{ - nfapi_nr_uci_indication_t *uci_ind = CALLOC(1, sizeof(*uci_ind)); - AssertFatal(uci_ind, "Memory not allocated for uci_ind in phy_nr_uci_indication."); - copy_uci_indication(ind, uci_ind); - if (!put_queue(&gnb_uci_ind_queue, uci_ind)) { - LOG_E(NR_MAC, "Put_queue failed for uci_ind\n"); - free_uci_indication(uci_ind); - free(uci_ind); - uci_ind = NULL; - } - return 1; -} - -void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frame, slot_t slot, NR_Sched_Rsp_t* sched_info); -int oai_fapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req); -int oai_fapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req); -int oai_fapi_tx_data_req(nfapi_nr_tx_data_request_t* tx_data_req); -int oai_fapi_ul_dci_req(nfapi_nr_ul_dci_request_t* ul_dci_req); -int oai_fapi_send_end_request(int cell, uint32_t frame, uint32_t slot); -extern int trigger_scheduler(nfapi_nr_slot_indication_scf_t *slot_ind); - -int aerial_phy_nr_slot_indication(nfapi_nr_slot_indication_scf_t *ind) -{ - LOG_D(MAC, "VNF SFN/Slot %d.%d \n", ind->sfn, ind->slot); - trigger_scheduler(ind); - - return 1; -} - -int aerial_phy_nr_srs_indication(nfapi_nr_srs_indication_t *ind) -{ - // or queue to decouple, but I think it should be fast (in all likelihood, - // the VNF has nothing to do) - for (int i = 0; i < ind->number_of_pdus; ++i) - handle_nr_srs_measurements(0, ind->sfn, ind->slot, &ind->pdu_list[i]); - return 1; -} - -void *aerial_vnf_allocate(size_t size) -{ - // return (void*)memory_pool::allocate(size); - return (void *)malloc(size); -} - -void aerial_vnf_deallocate(void *ptr) -{ - // memory_pool::deallocate((uint8_t*)ptr); - free(ptr); -} - -int aerial_phy_vendor_ext(struct nfapi_vnf_p7_config *config, void *msg) -{ - if (((nfapi_nr_p7_message_header_t *)msg)->message_id == P7_VENDOR_EXT_IND) { - // vendor_ext_p7_ind* ind = (vendor_ext_p7_ind*)msg; - // NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] vendor_ext (error_code:%d)\n", ind->error_code); - } else { - NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] unknown %02x\n", ((nfapi_nr_p7_message_header_t *)msg)->message_id); - } - - return 0; -} - -int aerial_phy_unpack_p7_vendor_extension(void *header, - uint8_t **ppReadPackedMessage, - uint8_t *end, - nfapi_p7_codec_config_t *config) -{ - // NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__); - if (((nfapi_nr_p7_message_header_t *)header)->message_id == P7_VENDOR_EXT_IND) { - vendor_ext_p7_ind *req = (vendor_ext_p7_ind *)(header); - - if (!pull16(ppReadPackedMessage, &req->error_code, end)) - return 0; - } - - return 1; -} - -int aerial_phy_pack_p7_vendor_extension(void *header, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) -{ - // NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__); - if (((nfapi_nr_p7_message_header_t *)header)->message_id == P7_VENDOR_EXT_REQ) { - // NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__); - vendor_ext_p7_req *req = (vendor_ext_p7_req *)(header); - - if (!(push16(req->dummy1, ppWritePackedMsg, end) && push16(req->dummy2, ppWritePackedMsg, end))) - return 0; - } - - return 1; -} - -int aerial_phy_unpack_vendor_extension_tlv(nfapi_tl_t *tl, - uint8_t **ppReadPackedMessage, - uint8_t *end, - void **ve, - nfapi_p7_codec_config_t *codec) -{ - (void)tl; - (void)ppReadPackedMessage; - (void)ve; - return -1; -} - -int aerial_phy_pack_vendor_extension_tlv(void *ve, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *codec) -{ - // NFAPI_TRACE(NFAPI_TRACE_INFO, "phy_pack_vendor_extension_tlv\n"); - nfapi_tl_t *tlv = (nfapi_tl_t *)ve; - - switch (tlv->tag) { - case VENDOR_EXT_TLV_1_TAG: { - // NFAPI_TRACE(NFAPI_TRACE_INFO, "Packing VENDOR_EXT_TLV_1\n"); - vendor_ext_tlv_1 *ve = (vendor_ext_tlv_1 *)tlv; - - if (!push32(ve->dummy, ppWritePackedMsg, end)) - return 0; - - return 1; - } break; - - default: - return -1; - break; - } -} - -void *aerial_phy_allocate_p7_vendor_ext(uint16_t message_id, uint16_t *msg_size) -{ - if (message_id == P7_VENDOR_EXT_IND) { - *msg_size = sizeof(vendor_ext_p7_ind); - return (nfapi_nr_p7_message_header_t *)malloc(sizeof(vendor_ext_p7_ind)); - } - - return 0; -} - -void aerial_phy_deallocate_p7_vendor_ext(void *header) -{ - free(header); -} - -uint8_t aerial_unpack_nr_slot_indication(uint8_t **ppReadPackedMsg, - uint8_t *end, - nfapi_nr_slot_indication_scf_t *msg, - nfapi_p7_codec_config_t *config) -{ - return unpack_nr_slot_indication(ppReadPackedMsg, end, msg, config); -} - static uint8_t aerial_unpack_nr_rx_data_indication_body(nfapi_nr_rx_data_pdu_t *value, uint8_t **ppReadPackedMsg, uint8_t *end, @@ -247,6 +53,7 @@ static uint8_t aerial_unpack_nr_rx_data_indication_body(nfapi_nr_rx_data_pdu_t * return 1; } + uint8_t aerial_unpack_nr_rx_data_indication(uint8_t **ppReadPackedMsg, uint8_t *end, uint8_t **pDataMsg, @@ -273,11 +80,11 @@ uint8_t aerial_unpack_nr_rx_data_indication(uint8_t **ppReadPackedMsg, } // After unpacking the PDU headers, unpack the PDU data from the separate buffer for (int i = 0; i < pNfapiMsg->number_of_pdus; i++) { - if(!pullarray8(pDataMsg, - pNfapiMsg->pdu_list[i].pdu, - pNfapiMsg->pdu_list[i].pdu_length, - pNfapiMsg->pdu_list[i].pdu_length, - data_end)){ + if (!pullarray8(pDataMsg, + pNfapiMsg->pdu_list[i].pdu, + pNfapiMsg->pdu_list[i].pdu_length, + pNfapiMsg->pdu_list[i].pdu_length, + data_end)) { return 0; } } @@ -285,19 +92,6 @@ uint8_t aerial_unpack_nr_rx_data_indication(uint8_t **ppReadPackedMsg, return 1; } -uint8_t aerial_unpack_nr_crc_indication(uint8_t **ppReadPackedMsg, - uint8_t *end, - nfapi_nr_crc_indication_t *msg, - nfapi_p7_codec_config_t *config) -{ - return unpack_nr_crc_indication(ppReadPackedMsg, end, msg, config); -} - -uint8_t aerial_unpack_nr_uci_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) -{ - return unpack_nr_uci_indication(ppReadPackedMsg, end, msg, config); -} - uint8_t aerial_unpack_nr_srs_indication(uint8_t **ppReadPackedMsg, uint8_t *end, uint8_t **pDataMsg, @@ -316,20 +110,13 @@ uint8_t aerial_unpack_nr_srs_indication(uint8_t **ppReadPackedMsg, return retval; } -uint8_t aerial_unpack_nr_rach_indication(uint8_t **ppReadPackedMsg, - uint8_t *end, - nfapi_nr_rach_indication_t *msg, - nfapi_p7_codec_config_t *config) -{ - return unpack_nr_rach_indication(ppReadPackedMsg, end, msg, config); -} - static int32_t aerial_pack_tx_data_request(void *pMessageBuf, void *pPackedBuf, void *pDataBuf, uint32_t packedBufLen, uint32_t dataBufLen, nfapi_p7_codec_config_t *config, + nfapi_vnf_p7_config_t *p7_config, uint32_t *data_len) { if (pMessageBuf == NULL || pPackedBuf == NULL) { @@ -386,16 +173,15 @@ static int32_t aerial_pack_tx_data_request(void *pMessageBuf, uintptr_t dataEnd = (uintptr_t)pPackedDataField; data_len[0] = dataEnd - dataHead; - - if (!fapi_nr_p7_message_pack(pMessageBuf, pPackedBuf, packedBufLen, config)) { - return -1; - } + if (!p7_config->pack_func(pMessageBuf, pPackedBuf, packedBufLen, config)) { + return -1; + } return (int32_t)(pMessageHeader->message_length); } -int fapi_nr_pack_and_send_p7_message(vnf_p7_t *vnf_p7, nfapi_nr_p7_message_header_t *header) +bool aerial_nr_send_p7_message(vnf_p7_t *vnf_p7, nfapi_nr_p7_message_header_t *header) { uint8_t FAPI_buffer[1024 * 64]; // Check if TX_DATA request, if true, need to pack to data_buf @@ -414,17 +200,20 @@ int fapi_nr_pack_and_send_p7_message(vnf_p7_t *vnf_p7, nfapi_nr_p7_message_heade sizeof(FAPI_buffer), sizeof(FAPI_data_buffer), &vnf_p7->_public.codec_config, + ((nfapi_vnf_p7_config_t *)vnf_p7), &data_len); if (len_FAPI <= 0) { LOG_E(NFAPI_VNF, "Problem packing TX_DATA_request\n"); - return len_FAPI; + return false; } else { - int retval = aerial_send_P7_msg_with_data(FAPI_buffer, len_FAPI, FAPI_data_buffer, data_len, header); - return retval; + return aerial_send_P7_msg_with_data(FAPI_buffer, len_FAPI, FAPI_data_buffer, data_len, header) == 0; } } else { // Create and send FAPI P7 message - int len_FAPI = fapi_nr_p7_message_pack(header, FAPI_buffer, sizeof(FAPI_buffer), &vnf_p7->_public.codec_config); - return aerial_send_P7_msg(FAPI_buffer, len_FAPI, header); + int len_FAPI = ((nfapi_vnf_p7_config_t *)vnf_p7)->pack_func(header, + FAPI_buffer, + sizeof(FAPI_buffer), + &vnf_p7->_public.codec_config); + return aerial_send_P7_msg(FAPI_buffer, len_FAPI, header) == 0; } } diff --git a/nfapi/oai_integration/aerial/fapi_vnf_p7.h b/nfapi/oai_integration/aerial/fapi_vnf_p7.h index ca75b02276..3722411578 100644 --- a/nfapi/oai_integration/aerial/fapi_vnf_p7.h +++ b/nfapi/oai_integration/aerial/fapi_vnf_p7.h @@ -47,187 +47,21 @@ #include "nfapi_interface.h" #include "nfapi_nr_interface_scf.h" #include "nfapi_vnf_interface.h" -#include "nfapi_vnf.h" -#include "nfapi.h" -#include "nfapi/oai_integration/vendor_ext.h" #include "fapi_nvIPC.h" - -#include "PHY/defs_eNB.h" -#include "PHY/LTE_TRANSPORT/transport_proto.h" -#include "openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h" -#include "lte-softmodem.h" - -#include "common/ran_context.h" #include "openair2/PHY_INTERFACE/queue_t.h" -#include "gnb_ind_vars.h" -#include "nfapi/open-nFAPI/vnf/inc/vnf.h" #include "nfapi/open-nFAPI/vnf/inc/vnf_p7.h" -typedef struct { - uint8_t enabled; - uint32_t rx_port; - uint32_t tx_port; - char tx_addr[80]; -} udp_data; - -typedef struct { - uint16_t index; - uint16_t id; - uint8_t rfs[2]; - uint8_t excluded_rfs[2]; - - udp_data udp; - - char local_addr[80]; - int local_port; - - char *remote_addr; - int remote_port; - - uint8_t duplex_mode; - uint16_t dl_channel_bw_support; - uint16_t ul_channel_bw_support; - uint8_t num_dl_layers_supported; - uint8_t num_ul_layers_supported; - uint16_t release_supported; - uint8_t nmm_modes_supported; - - uint8_t dl_ues_per_subframe; - uint8_t ul_ues_per_subframe; - - uint8_t first_subframe_ind; - - // timing information recevied from the vnf - uint8_t timing_window; - uint8_t timing_info_mode; - uint8_t timing_info_period; - -} phy_info; - -typedef struct { - uint16_t index; - uint16_t band; - int16_t max_transmit_power; - int16_t min_transmit_power; - uint8_t num_antennas_supported; - uint32_t min_downlink_frequency; - uint32_t max_downlink_frequency; - uint32_t max_uplink_frequency; - uint32_t min_uplink_frequency; -} rf_info; - -typedef struct { - int release; - phy_info phys[2]; - rf_info rfs[2]; - - uint8_t sync_mode; - uint8_t location_mode; - uint8_t location_coordinates[6]; - uint32_t dl_config_timing; - uint32_t ul_config_timing; - uint32_t tx_timing; - uint32_t hi_dci0_timing; - - uint16_t max_phys; - uint16_t max_total_bw; - uint16_t max_total_dl_layers; - uint16_t max_total_ul_layers; - uint8_t shared_bands; - uint8_t shared_pa; - int16_t max_total_power; - uint8_t oui; - - uint8_t wireshark_test_mode; - -} pnf_info; - -typedef struct mac mac_t; -typedef struct mac { - void *user_data; - - void (*dl_config_req)(mac_t *mac, nfapi_dl_config_request_t *req); - void (*ul_config_req)(mac_t *mac, nfapi_ul_config_request_t *req); - void (*hi_dci0_req)(mac_t *mac, nfapi_hi_dci0_request_t *req); - void (*tx_req)(mac_t *mac, nfapi_tx_request_t *req); -} mac_t; - -typedef struct { - int local_port; - char local_addr[80]; - - unsigned timing_window; - unsigned periodic_timing_enabled; - unsigned aperiodic_timing_enabled; - unsigned periodic_timing_period; - - // This is not really the right place if we have multiple PHY, - // should be part of the phy struct - udp_data udp; - - uint8_t thread_started; - - nfapi_vnf_p7_config_t *config; - - mac_t *mac; - -} vnf_p7_info; - -typedef struct { - uint8_t wireshark_test_mode; - pnf_info pnfs[2]; - vnf_p7_info p7_vnfs[2]; - -} vnf_info; - -int aerial_phy_nr_crc_indication(nfapi_nr_crc_indication_t *ind); -int aerial_phy_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind); -int aerial_phy_nr_rach_indication(nfapi_nr_rach_indication_t *ind); -int aerial_phy_nr_uci_indication(nfapi_nr_uci_indication_t *ind); -int aerial_phy_nr_slot_indication(nfapi_nr_slot_indication_scf_t *ind); -int aerial_phy_nr_srs_indication(nfapi_nr_srs_indication_t *ind); -void *aerial_vnf_allocate(size_t size); -void aerial_vnf_deallocate(void *ptr); -int aerial_phy_vendor_ext(struct nfapi_vnf_p7_config *config, void *msg); -int aerial_phy_unpack_p7_vendor_extension(void *header, - uint8_t **ppReadPackedMessage, - uint8_t *end, - nfapi_p7_codec_config_t *config); -int aerial_phy_pack_p7_vendor_extension(void *header, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config); -int aerial_phy_unpack_vendor_extension_tlv(nfapi_tl_t *tl, - uint8_t **ppReadPackedMessage, - uint8_t *end, - void **ve, - nfapi_p7_codec_config_t *codec); -int aerial_phy_pack_vendor_extension_tlv(void *ve, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *codec); -void *aerial_phy_allocate_p7_vendor_ext(uint16_t message_id, uint16_t *msg_size); -void aerial_phy_deallocate_p7_vendor_ext(void *header); - -uint8_t aerial_unpack_nr_slot_indication(uint8_t **ppReadPackedMsg, - uint8_t *end, - nfapi_nr_slot_indication_scf_t *msg, - nfapi_p7_codec_config_t *config); uint8_t aerial_unpack_nr_rx_data_indication(uint8_t **ppReadPackedMsg, uint8_t *end, uint8_t **pDataMsg, uint8_t *data_end, nfapi_nr_rx_data_indication_t *msg, nfapi_p7_codec_config_t *config); -uint8_t aerial_unpack_nr_crc_indication(uint8_t **ppReadPackedMsg, - uint8_t *end, - nfapi_nr_crc_indication_t *msg, - nfapi_p7_codec_config_t *config); -uint8_t aerial_unpack_nr_uci_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config); + uint8_t aerial_unpack_nr_srs_indication(uint8_t **ppReadPackedMsg, uint8_t *end, uint8_t **pDataMsg, uint8_t *data_end, void *msg, nfapi_p7_codec_config_t *config); -uint8_t aerial_unpack_nr_rach_indication(uint8_t **ppReadPackedMsg, - uint8_t *end, - nfapi_nr_rach_indication_t *msg, - nfapi_p7_codec_config_t *config); - -// int fapi_nr_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen, nfapi_p7_codec_config_t* config); -int fapi_nr_pack_and_send_p7_message(vnf_p7_t *vnf_p7, nfapi_nr_p7_message_header_t *header); +bool aerial_nr_send_p7_message(vnf_p7_t *vnf_p7, nfapi_nr_p7_message_header_t *header); #endif // OPENAIRINTERFACE_FAPI_VNF_P7_H diff --git a/nfapi/oai_integration/nfapi_vnf.c b/nfapi/oai_integration/nfapi_vnf.c index a2f3d579e3..8c30843807 100644 --- a/nfapi/oai_integration/nfapi_vnf.c +++ b/nfapi/oai_integration/nfapi_vnf.c @@ -32,7 +32,6 @@ #include #include "nfapi_nr_interface_scf.h" -#include "nfapi_vnf_interface.h" #include "nfapi_vnf.h" #include #include @@ -64,7 +63,9 @@ #ifdef ENABLE_AERIAL #include "aerial/fapi_nvIPC.h" +#include "aerial/fapi_vnf_p7.h" #include "nr_fapi_p5.h" +#include "nr_fapi_p7.h" #endif #define TEST @@ -72,128 +73,6 @@ extern RAN_CONTEXT_t RC; extern UL_RCC_IND_t UL_RCC_INFO; -typedef struct { - uint8_t enabled; - uint32_t rx_port; - uint32_t tx_port; - char tx_addr[80]; -} udp_data; - -typedef struct { - uint16_t index; - uint16_t id; - uint8_t rfs[2]; - uint8_t excluded_rfs[2]; - - udp_data udp; - - char local_addr[80]; - int local_port; - - char *remote_addr; - int remote_port; - - uint8_t duplex_mode; - uint16_t dl_channel_bw_support; - uint16_t ul_channel_bw_support; - uint8_t num_dl_layers_supported; - uint8_t num_ul_layers_supported; - uint16_t release_supported; - uint8_t nmm_modes_supported; - - uint8_t dl_ues_per_subframe; - uint8_t ul_ues_per_subframe; - - uint8_t first_subframe_ind; - - // timing information recevied from the vnf - uint8_t timing_window; - uint8_t timing_info_mode; - uint8_t timing_info_period; - -} phy_info; - -typedef struct { - uint16_t index; - uint16_t band; - int16_t max_transmit_power; - int16_t min_transmit_power; - uint8_t num_antennas_supported; - uint32_t min_downlink_frequency; - uint32_t max_downlink_frequency; - uint32_t max_uplink_frequency; - uint32_t min_uplink_frequency; -} rf_info; - -typedef struct { - - int release; - phy_info phys[2]; - rf_info rfs[2]; - - uint8_t sync_mode; - uint8_t location_mode; - uint8_t location_coordinates[6]; - uint32_t dl_config_timing; - uint32_t ul_config_timing; - uint32_t tx_timing; - uint32_t hi_dci0_timing; - - uint16_t max_phys; - uint16_t max_total_bw; - uint16_t max_total_dl_layers; - uint16_t max_total_ul_layers; - uint8_t shared_bands; - uint8_t shared_pa; - int16_t max_total_power; - uint8_t oui; - - uint8_t wireshark_test_mode; - -} pnf_info; - -typedef struct mac mac_t; - -typedef struct mac { - - void *user_data; - - void (*dl_config_req)(mac_t *mac, nfapi_dl_config_request_t *req); - void (*ul_config_req)(mac_t *mac, nfapi_ul_config_request_t *req); - void (*hi_dci0_req)(mac_t *mac, nfapi_hi_dci0_request_t *req); - void (*tx_req)(mac_t *mac, nfapi_tx_request_t *req); -} mac_t; - -typedef struct { - - int local_port; - char local_addr[80]; - - unsigned timing_window; - unsigned periodic_timing_enabled; - unsigned aperiodic_timing_enabled; - unsigned periodic_timing_period; - - // This is not really the right place if we have multiple PHY, - // should be part of the phy struct - udp_data udp; - - uint8_t thread_started; - - nfapi_vnf_p7_config_t *config; - - mac_t *mac; - -} vnf_p7_info; - -typedef struct { - - uint8_t wireshark_test_mode; - pnf_info pnfs[2]; - vnf_p7_info p7_vnfs[2]; - -} vnf_info; - int vnf_pack_vendor_extension_tlv(void *ve, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *codec) { //NFAPI_TRACE(NFAPI_TRACE_INFO, "vnf_pack_vendor_extension_tlv\n"); nfapi_tl_t *tlv = (nfapi_tl_t *)ve; @@ -1455,9 +1334,7 @@ void *configure_nr_p7_vnf(void *ptr) p7_vnf->config->codec_config.deallocate = &vnf_deallocate; p7_vnf->config->allocate_p7_vendor_ext = &phy_nr_allocate_p7_vendor_ext; p7_vnf->config->deallocate_p7_vendor_ext = &phy_nr_deallocate_p7_vendor_ext; - p7_vnf->config->unpack_func = &nfapi_nr_p7_message_unpack; - p7_vnf->config->hdr_unpack_func = &nfapi_nr_p7_message_header_unpack; - p7_vnf->config->pack_func = &nfapi_nr_p7_message_pack; + #ifdef ENABLE_WLS p7_vnf->config->unpack_func = &fapi_nr_p7_message_unpack; p7_vnf->config->hdr_unpack_func = &fapi_nr_p7_message_header_unpack; @@ -1476,7 +1353,10 @@ void *configure_nr_p7_vnf(void *ptr) #endif #ifdef ENABLE_AERIAL - + p7_vnf->config->unpack_func = &fapi_nr_p7_message_unpack; + p7_vnf->config->hdr_unpack_func = &fapi_nr_p7_message_header_unpack; + p7_vnf->config->pack_func = &fapi_nr_p7_message_pack; + p7_vnf->config->send_p7_msg = &aerial_nr_send_p7_message; #endif return 0; } diff --git a/nfapi/oai_integration/nfapi_vnf.h b/nfapi/oai_integration/nfapi_vnf.h index 1a8228f0a3..104cff44f4 100644 --- a/nfapi/oai_integration/nfapi_vnf.h +++ b/nfapi/oai_integration/nfapi_vnf.h @@ -23,6 +23,129 @@ #define NFAPI_VNF_H_ #include +#include "nfapi_vnf_interface.h" +typedef struct { + uint8_t enabled; + uint32_t rx_port; + uint32_t tx_port; + char tx_addr[80]; +} udp_data; + +typedef struct { + uint16_t index; + uint16_t id; + uint8_t rfs[2]; + uint8_t excluded_rfs[2]; + + udp_data udp; + + char local_addr[80]; + int local_port; + + char *remote_addr; + int remote_port; + + uint8_t duplex_mode; + uint16_t dl_channel_bw_support; + uint16_t ul_channel_bw_support; + uint8_t num_dl_layers_supported; + uint8_t num_ul_layers_supported; + uint16_t release_supported; + uint8_t nmm_modes_supported; + + uint8_t dl_ues_per_subframe; + uint8_t ul_ues_per_subframe; + + uint8_t first_subframe_ind; + + // timing information recevied from the vnf + uint8_t timing_window; + uint8_t timing_info_mode; + uint8_t timing_info_period; + +} phy_info; + +typedef struct { + uint16_t index; + uint16_t band; + int16_t max_transmit_power; + int16_t min_transmit_power; + uint8_t num_antennas_supported; + uint32_t min_downlink_frequency; + uint32_t max_downlink_frequency; + uint32_t max_uplink_frequency; + uint32_t min_uplink_frequency; +} rf_info; + +typedef struct { + + int release; + phy_info phys[2]; + rf_info rfs[2]; + + uint8_t sync_mode; + uint8_t location_mode; + uint8_t location_coordinates[6]; + uint32_t dl_config_timing; + uint32_t ul_config_timing; + uint32_t tx_timing; + uint32_t hi_dci0_timing; + + uint16_t max_phys; + uint16_t max_total_bw; + uint16_t max_total_dl_layers; + uint16_t max_total_ul_layers; + uint8_t shared_bands; + uint8_t shared_pa; + int16_t max_total_power; + uint8_t oui; + + uint8_t wireshark_test_mode; + +} pnf_info; + +typedef struct mac mac_t; + +typedef struct mac { + + void *user_data; + + void (*dl_config_req)(mac_t *mac, nfapi_dl_config_request_t *req); + void (*ul_config_req)(mac_t *mac, nfapi_ul_config_request_t *req); + void (*hi_dci0_req)(mac_t *mac, nfapi_hi_dci0_request_t *req); + void (*tx_req)(mac_t *mac, nfapi_tx_request_t *req); +} mac_t; + +typedef struct { + + int local_port; + char local_addr[80]; + + unsigned timing_window; + unsigned periodic_timing_enabled; + unsigned aperiodic_timing_enabled; + unsigned periodic_timing_period; + + // This is not really the right place if we have multiple PHY, + // should be part of the phy struct + udp_data udp; + + uint8_t thread_started; + + nfapi_vnf_p7_config_t *config; + + mac_t *mac; + +} vnf_p7_info; + +typedef struct { + + uint8_t wireshark_test_mode; + pnf_info pnfs[2]; + vnf_p7_info p7_vnfs[2]; + +} vnf_info; + void configure_nfapi_vnf(char *vnf_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port); void configure_nr_nfapi_vnf(eth_params_t params); diff --git a/nfapi/oai_integration/socket/socket_vnf.c b/nfapi/oai_integration/socket/socket_vnf.c index d5f26a25df..6440109ed6 100644 --- a/nfapi/oai_integration/socket/socket_vnf.c +++ b/nfapi/oai_integration/socket/socket_vnf.c @@ -45,30 +45,16 @@ bool vnf_nr_send_p5_msg(vnf_t *vnf, uint16_t p5_idx, nfapi_nr_p4_p5_message_head if (pnf) { // pack the message for transmission int packedMessageLength = 0; - if (NFAPI_MODE == NFAPI_MODE_AERIAL) { -#ifdef ENABLE_AERIAL // TODO: Remove this into the aerial VNF transport module - // In case it is a FAPI message, create 2 messages, one with nFAPI header for OAI PNF and one with no nFAPI header for Aerial - // L1 - // create FAPI tx_buffer - uint8_t tx_messagebufferFAPI[sizeof(vnf->tx_message_buffer)]; - int packedMessageLengthFAPI = -1; - packedMessageLengthFAPI = - fapi_nr_p5_message_pack(msg, msg_len, tx_messagebufferFAPI, sizeof(tx_messagebufferFAPI), &vnf->_public.codec_config); - return aerial_send_P5_msg(tx_messagebufferFAPI, packedMessageLengthFAPI, msg); -#else - return 0; -#endif - } else { - packedMessageLength = - vnf->_public.pack_func(msg, msg_len, vnf->tx_message_buffer, sizeof(vnf->tx_message_buffer), &vnf->_public.codec_config); + + packedMessageLength = + vnf->_public.pack_func(msg, msg_len, vnf->tx_message_buffer, sizeof(vnf->tx_message_buffer), &vnf->_public.codec_config); if (packedMessageLength < 0) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi_nr_p5_message_pack failed with return %d\n", packedMessageLength); return false; } - return send_p5_msg(vnf, pnf, vnf->tx_message_buffer, packedMessageLength, 0); - } + return send_p5_msg(vnf, pnf, vnf->tx_message_buffer, packedMessageLength, 0); } else { NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() cannot find pnf info for p5_idx:%d\n", __FUNCTION__, p5_idx); return false; From 1026b8121fa1fa60cdd53a5f862b7f3d481e0f22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Soares=20Silva?= Date: Fri, 21 Mar 2025 11:11:55 +0000 Subject: [PATCH 211/964] Add VNF callback for ERROR.indication Created a function nr_error_ind_cb for the VNF that takes a received ERROR.indication and shows some details regarding the reported error from the PNF, since up until now it was not handled and treated as an unknown message. Proper error handling procedure not created, only shows that the error occurred. --- nfapi/oai_integration/nfapi_vnf.c | 17 ++++++++ nfapi/open-nFAPI/fapi/inc/nr_fapi_p5_utils.h | 1 + nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c | 28 +++---------- .../nfapi/public_inc/nfapi_nr_interface_scf.h | 24 +++++++----- .../vnf/public_inc/nfapi_vnf_interface.h | 20 +++++++++- nfapi/open-nFAPI/vnf/src/vnf.c | 39 ++++++++++++++++++- 6 files changed, 96 insertions(+), 33 deletions(-) diff --git a/nfapi/oai_integration/nfapi_vnf.c b/nfapi/oai_integration/nfapi_vnf.c index 8c30843807..5ea99de7ea 100644 --- a/nfapi/oai_integration/nfapi_vnf.c +++ b/nfapi/oai_integration/nfapi_vnf.c @@ -59,6 +59,7 @@ #include "openair2/PHY_INTERFACE/queue_t.h" #include "gnb_ind_vars.h" #include "nr_fapi_p7_utils.h" +#include "nr_fapi_p5_utils.h" #include #ifdef ENABLE_AERIAL @@ -1622,6 +1623,21 @@ int nr_start_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_nr_start_resp return 0; } +int nr_error_ind_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_nr_error_indication_scf_t *resp) +{ + NFAPI_TRACE(NFAPI_TRACE_WARN, + "[VNF] Received NFAPI_NR_PHY_MSG_TYPE_ERROR_INDICATION idx:%d phy_id:%d\n", + p5_idx, + resp->header.phy_id); + NFAPI_TRACE(NFAPI_TRACE_WARN, "[VNF] Previous message 0x%02x resulted in an error on the PNF \n", resp->message_id); + NFAPI_TRACE(NFAPI_TRACE_WARN, + "[VNF] Received error code 0x%02x (%s)\n", + resp->error_code, + error_ind_code_to_str(resp->error_code)); + // TODO: add error handling to the VNF instead of only reporting the received error + return 0; +} + int vendor_ext_cb(nfapi_vnf_config_t *config, int p5_idx, void *msg) { NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] %s\n", __FUNCTION__); @@ -1762,6 +1778,7 @@ void configure_nr_nfapi_vnf(eth_params_t params) config->nr_param_resp = &nr_param_resp_cb; config->nr_config_resp = &nr_config_resp_cb; config->nr_start_resp = &nr_start_resp_cb; + config->nr_error_ind = &nr_error_ind_cb; config->vendor_ext = &vendor_nr_ext_cb; config->user_data = &vnf; // To allow custom vendor extentions to be added to nfapi diff --git a/nfapi/open-nFAPI/fapi/inc/nr_fapi_p5_utils.h b/nfapi/open-nFAPI/fapi/inc/nr_fapi_p5_utils.h index 8ef5fbade2..9d96a3be36 100644 --- a/nfapi/open-nFAPI/fapi/inc/nr_fapi_p5_utils.h +++ b/nfapi/open-nFAPI/fapi/inc/nr_fapi_p5_utils.h @@ -64,6 +64,7 @@ void dump_start_request(const nfapi_nr_start_request_scf_t *msg); void dump_start_response(const nfapi_nr_start_response_scf_t *msg); void dump_stop_request(const nfapi_nr_stop_request_scf_t *msg); void dump_stop_indication(const nfapi_nr_stop_indication_scf_t *msg); +char* error_ind_code_to_str(nfapi_nr_phy_notifications_errors_e error_code); void dump_error_indication(const nfapi_nr_error_indication_scf_t *msg); 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 4c3f32ef27..a810b199ff 100644 --- a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c +++ b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c @@ -1469,29 +1469,13 @@ void dump_stop_indication(const nfapi_nr_stop_indication_scf_t *msg) dump_p5_message_header(&msg->header,depth); } -static char *error_code_to_str(uint8_t error_code) +char* error_ind_code_to_str(nfapi_nr_phy_notifications_errors_e error_code) { switch (error_code) { - case NFAPI_NR_PHY_API_MSG_OK: - return "NFAPI_NR_PHY_API_MSG_OK"; - case NFAPI_NR_PHY_API_MSG_INVALID_STATE: - return "NFAPI_NR_PHY_API_MSG_INVALID_STATE"; - case NFAPI_NR_PHY_API_MSG_INVALID_CONFIG: - return "NFAPI_NR_PHY_API_MSG_INVALID_CONFIG"; - case NFAPI_NR_PHY_API_SFN_OUT_OF_SYNC: - return "NFAPI_NR_PHY_API_SFN_OUT_OF_SYNC"; - case NFAPI_NR_PHY_API_MSG_SLOR_ERR: - return "NFAPI_NR_PHY_API_MSG_SLOR_ERR"; - case NFAPI_NR_PHY_API_MSG_BCH_MISSING: - return "NFAPI_NR_PHY_API_MSG_BCH_MISSING"; - case NFAPI_NR_PHY_API_MSG_INVALID_SFN: - return "NFAPI_NR_PHY_API_MSG_INVALID_SFN"; - case NFAPI_NR_PHY_API_MSG_UL_DCI_ERR: - return "NFAPI_NR_PHY_API_MSG_UL_DCI_ERR"; - case NFAPI_NR_PHY_API_MSG_TX_ERR: - return "NFAPI_NR_PHY_API_MSG_TX_ERR"; - default: - return "Unknown Error code"; +#define X(name, value) case name: return #name; + NFAPI_PHY_ERROR_LIST +#undef X + default: return "UNKNOWN_ERROR"; } } @@ -1503,6 +1487,6 @@ void dump_error_indication(const nfapi_nr_error_indication_scf_t *msg) INDENTED_PRINTF("SFN = 0x%02x (%d)\n", msg->sfn, msg->sfn); INDENTED_PRINTF("Slot = 0x%02x (%d)\n", msg->slot, msg->slot); INDENTED_PRINTF("Message ID = 0x%02x\n", msg->message_id); - INDENTED_PRINTF("Error Code = 0x%02x (%s) \n", msg->error_code, error_code_to_str(msg->error_code)); + INDENTED_PRINTF("Error Code = 0x%02x (%s) \n", msg->error_code, error_ind_code_to_str(msg->error_code)); depth--; } 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 f213868328..e19dab108c 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 @@ -701,16 +701,22 @@ typedef enum { } nfapi_nr_stop_errors_e; //3.3.5 PHY Notifications + +#define NFAPI_PHY_ERROR_LIST \ +X(NFAPI_NR_PHY_API_MSG_OK ,0x0)\ +X(NFAPI_NR_PHY_API_MSG_INVALID_STATE ,0x1)\ +X(NFAPI_NR_PHY_API_MSG_INVALID_CONFIG ,0x2)\ +X(NFAPI_NR_PHY_API_SFN_OUT_OF_SYNC ,0X3)\ +X(NFAPI_NR_PHY_API_MSG_SLOR_ERR ,0X4)\ +X(NFAPI_NR_PHY_API_MSG_BCH_MISSING ,0X5)\ +X(NFAPI_NR_PHY_API_MSG_INVALID_SFN ,0X6)\ +X(NFAPI_NR_PHY_API_MSG_UL_DCI_ERR ,0X7)\ +X(NFAPI_NR_PHY_API_MSG_TX_ERR ,0X8) + typedef enum { - NFAPI_NR_PHY_API_MSG_OK =0x0, - NFAPI_NR_PHY_API_MSG_INVALID_STATE =0x1, - NFAPI_NR_PHY_API_MSG_INVALID_CONFIG =0x2, - NFAPI_NR_PHY_API_SFN_OUT_OF_SYNC =0X3, - NFAPI_NR_PHY_API_MSG_SLOR_ERR =0X4, - NFAPI_NR_PHY_API_MSG_BCH_MISSING =0X5, - NFAPI_NR_PHY_API_MSG_INVALID_SFN =0X6, - NFAPI_NR_PHY_API_MSG_UL_DCI_ERR =0X7, - NFAPI_NR_PHY_API_MSG_TX_ERR =0X8 +#define X(name, value) name = value, + NFAPI_PHY_ERROR_LIST +#undef X } nfapi_nr_phy_notifications_errors_e; typedef struct { diff --git a/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h b/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h index b98a91e2ac..db303b8b4a 100644 --- a/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h +++ b/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h @@ -294,7 +294,25 @@ typedef struct nfapi_vnf_config */ int (*start_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_start_response_t* resp); int (*nr_start_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_start_response_scf_t* resp); - + + /*! A callback for the ERROR.indication + * \param config A pointer to the vnf configuration + * \param p5_idx The p5 index used to indicate a particular pnf p5 connection + * \param ind A data structure for the decoded ERROR.indication This will + * have been allocated on the stack. + * \return not currently used. + * + * The ERROR.indication contains a reported error from the PNF, often signifying that a message has been sent too late + * + * + * The ind may contain pointers to dynamically allocated sub structures + * such as the vendor_extension. The dynamically allocated structure will + * be deallocated on return. If the client wishes to 'keep' the structures + * then the substructure pointers should be set to 0 and then the client should + * use the codec_config.deallocate function to release it at a future point + */ + int (*nr_error_ind)(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_error_indication_scf_t* ind); + /*! A callback for the STOP.resp * \param config A pointer to the vnf configuration * \param p5_idx The p5 index used to indicate a particular pnf p5 connection diff --git a/nfapi/open-nFAPI/vnf/src/vnf.c b/nfapi/open-nFAPI/vnf/src/vnf.c index d669573168..b61d5f26ae 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf.c +++ b/nfapi/open-nFAPI/vnf/src/vnf.c @@ -633,6 +633,39 @@ void vnf_nr_handle_start_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_conf } } +void vnf_nr_handle_error_indication(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx) +{ + + // ensure it's valid + if (pRecvMsg == NULL || config == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } + else + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "Received ERROR.indication\n"); + + nfapi_nr_error_indication_scf_t msg; + + // unpack the message + if (config->unpack_func(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config)) + { + if (config->nr_error_ind){ + (config->nr_error_ind)(config, p5_idx, &msg); + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__); + } + + // make sure to release any dynamic part of the message + if(msg.vendor_extension) + config->codec_config.deallocate(msg.vendor_extension); + } +} + + void vnf_handle_stop_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx) { @@ -1125,7 +1158,11 @@ void vnf_nr_handle_p4_p5_message(void *pRecvMsg, int recvMsgLen, int p5_idx, nfa case NFAPI_NR_PHY_MSG_TYPE_CONFIG_RESPONSE: vnf_nr_handle_config_response(pRecvMsg, recvMsgLen, config, p5_idx); - break; + break; + + case NFAPI_NR_PHY_MSG_TYPE_ERROR_INDICATION: + vnf_nr_handle_error_indication(pRecvMsg, recvMsgLen, config, p5_idx); + break; case NFAPI_NR_PHY_MSG_TYPE_START_RESPONSE: vnf_nr_handle_start_response(pRecvMsg, recvMsgLen, config, p5_idx); From 43c733dc8934f060490f77dd756169d2387f415f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Soares=20Silva?= Date: Fri, 21 Mar 2025 17:52:53 +0000 Subject: [PATCH 212/964] Prevent pulling TLV tag and length over end of the buffer. Checks whether there are at least 4 bytes available to pull tag and length values. On tlv_list unpack, if the size is sent as 0, immediately exit the function --- nfapi/open-nFAPI/common/src/nfapi.c | 4 ++-- nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/nfapi/open-nFAPI/common/src/nfapi.c b/nfapi/open-nFAPI/common/src/nfapi.c index 716387ae7d..f997552c1e 100644 --- a/nfapi/open-nFAPI/common/src/nfapi.c +++ b/nfapi/open-nFAPI/common/src/nfapi.c @@ -889,8 +889,8 @@ int unpack_nr_tlv_list(unpack_tlv_t unpack_fns[], nfapi_tl_t generic_tl; uint8_t numBadTags = 0; uint16_t idx = 0; - - while ((uint8_t *)(*ppReadPackedMsg) < end) { + if (size == 0) { return 1; } + while ((uint8_t *)(*ppReadPackedMsg) + 4 < end) { // unpack the tl and process the values accordingly if (unpack_tl(ppReadPackedMsg, &generic_tl, end) == 0) return 0; diff --git a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c index 9339a666a3..6936d8b8fa 100644 --- a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c +++ b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c @@ -1347,7 +1347,7 @@ uint8_t unpack_nr_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void * nfapi_tl_t generic_tl; uint8_t numBadTags = 0; unsigned long idx = 0; - while ((uint8_t *)(*ppReadPackedMsg) < end) { + while ((uint8_t *)(*ppReadPackedMsg) + 4 < end) { // unpack the tl and process the values accordingly if (unpack_tl(ppReadPackedMsg, &generic_tl, end) == 0) return 0; From 625c8cfd51a2a4cc257670a63a9054dd575fe2ec Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Thu, 26 Jun 2025 09:22:43 +0200 Subject: [PATCH 213/964] CI: move RFSim 5G to acamas --- .../xml_files/container_5g_e1_rfsim.xml | 6 +-- .../xml_files/container_5g_f1_rfsim.xml | 38 +++++++++--------- .../xml_files/container_5g_fdd_rfsim.xml | 18 ++++----- ci-scripts/xml_files/container_5g_rfsim.xml | 40 +++++++++---------- .../xml_files/container_5g_rfsim_24prb.xml | 22 +++++----- .../xml_files/container_5g_rfsim_2x2.xml | 18 ++++----- .../container_5g_rfsim_fdd_phytest.xml | 18 ++++----- .../container_5g_rfsim_fr2_32prb.xml | 10 ++--- .../xml_files/container_5g_rfsim_ntn_geo.xml | 18 ++++----- .../xml_files/container_5g_rfsim_ntn_leo.xml | 10 ++--- .../xml_files/container_5g_rfsim_sidelink.xml | 2 +- .../xml_files/container_5g_rfsim_tdd_dora.xml | 10 ++--- .../xml_files/container_5g_rfsim_u0_25prb.xml | 18 ++++----- 13 files changed, 114 insertions(+), 114 deletions(-) diff --git a/ci-scripts/xml_files/container_5g_e1_rfsim.xml b/ci-scripts/xml_files/container_5g_e1_rfsim.xml index 95ae2f7b0a..51f0270b19 100644 --- a/ci-scripts/xml_files/container_5g_e1_rfsim.xml +++ b/ci-scripts/xml_files/container_5g_e1_rfsim.xml @@ -80,16 +80,16 @@ Attach_UE Attach OAI UE (Wait for IP) rfsim5g_ue rfsim5g_ue2 rfsim5g_ue3 - cacofonix cacofonix cacofonix + acamas acamas acamas Ping Ping ext-dn from all NR-UEs rfsim5g_ue rfsim5g_ue2 rfsim5g_ue3 - cacofonix cacofonix cacofonix + acamas acamas acamas rfsim5g_5gc_fixed_ip - cacofonix + acamas -c 20 -i0.25 5 diff --git a/ci-scripts/xml_files/container_5g_f1_rfsim.xml b/ci-scripts/xml_files/container_5g_f1_rfsim.xml index 3b783a9215..9909e84876 100644 --- a/ci-scripts/xml_files/container_5g_f1_rfsim.xml +++ b/ci-scripts/xml_files/container_5g_f1_rfsim.xml @@ -106,7 +106,7 @@ Attach_UE Attach OAI UE (Wait for IP) rfsim5g_ue - cacofonix + acamas @@ -122,9 +122,9 @@ Ping Ping ext-dn from all NR-UEs rfsim5g_ue - cacofonix + acamas rfsim5g_ext_dn - cacofonix + acamas -c 20 -i0.25 5 @@ -132,7 +132,7 @@ Custom_Command Simulate a DL radio channel with noise (3 dB) - cacofonix + acamas echo channelmod modify 0 noise_power_dB 3 | nc --send-only 192.168.71.181 8091 @@ -141,9 +141,9 @@ Iperf (DL/5Mbps/UDP)(30 sec) -u -b 5M -t 20 -R rfsim5g_ue - cacofonix + acamas rfsim5g_ext_dn - cacofonix + acamas 5 90 @@ -153,9 +153,9 @@ Iperf (UL/3Mbps/UDP)(30 sec) -u -b 3M -t 20 rfsim5g_ue - cacofonix + acamas rfsim5g_ext_dn - cacofonix + acamas 5 90 @@ -163,7 +163,7 @@ Custom_Command Trigger Reestablishment - cacofonix + acamas 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' @@ -171,9 +171,9 @@ Ping Ping ext-dn from NR-UE rfsim5g_ue - cacofonix + acamas rfsim5g_ext_dn - cacofonix + acamas -c 20 -i0.5 -w25 80 @@ -181,56 +181,56 @@ Custom_Command Verify Reestablishment - cacofonix + acamas echo ci get_reestab_count | nc 192.168.71.150 9090 | grep -E 'UE RNTI [0-9a-f]{4} reestab 1' Custom_Command Simulate a disruption of DL radio channel (ploss 55) - cacofonix + acamas echo channelmod modify 0 ploss 55 | nc 192.168.71.181 8091 Custom_Command Get UE sync state (UE ID 0) - cacofonix + acamas echo ciUE sync_state 0 | nc 192.168.71.181 8091 | grep -E UE_NOT_SYNC Custom_Command Restoration of the original DL channel conditions (ploss 20) - cacofonix + acamas echo channelmod modify 0 ploss 20 | nc 192.168.71.181 8091 Custom_Command Get UE sync state (UE ID 0) - cacofonix + acamas echo ciUE sync_state 0 | nc 192.168.71.181 8091 | grep -E UE_CONNECTED Custom_Command Trigger Handover - cacofonix + acamas echo ci trigger_f1_ho | nc 192.168.71.150 9090 Custom_Command UE (1) connected to DU-PCI 0? - cacofonix + acamas echo ci fetch_du_by_ue_id 1 | nc 192.168.71.150 9090 | grep "3584" Custom_Command UE (1) connected to DU-PCI 1? - cacofonix + acamas echo ci fetch_du_by_ue_id 1 | nc 192.168.71.150 9090 | grep "3585" diff --git a/ci-scripts/xml_files/container_5g_fdd_rfsim.xml b/ci-scripts/xml_files/container_5g_fdd_rfsim.xml index 2c9fd04544..1fd3de1ad5 100644 --- a/ci-scripts/xml_files/container_5g_fdd_rfsim.xml +++ b/ci-scripts/xml_files/container_5g_fdd_rfsim.xml @@ -73,16 +73,16 @@ Attach_UE Attach OAI UE (Wait for IP) rfsim5g_ue - cacofonix + acamas Ping Ping ext-dn from NR-UE rfsim5g_ue - cacofonix + acamas rfsim5g_ext_dn - cacofonix + acamas -c 20 -i 0.25 5 @@ -91,9 +91,9 @@ Ping Ping NR-UE from ext-dn rfsim5g_ext_dn - cacofonix + acamas rfsim5g_ue - cacofonix + acamas -c 20 -i 0.25 5 @@ -103,9 +103,9 @@ Iperf (DL/3Mbps/UDP)(30 sec) -u -b 3M -t 30 -R rfsim5g_ue - cacofonix + acamas rfsim5g_ext_dn - cacofonix + acamas 5 90 @@ -115,9 +115,9 @@ Iperf (UL/3Mbps/UDP)(30 sec) -u -b 3M -t 30 rfsim5g_ue - cacofonix + acamas rfsim5g_ext_dn - cacofonix + acamas 5 90 diff --git a/ci-scripts/xml_files/container_5g_rfsim.xml b/ci-scripts/xml_files/container_5g_rfsim.xml index 80e4d189ff..910a2dcbb5 100644 --- a/ci-scripts/xml_files/container_5g_rfsim.xml +++ b/ci-scripts/xml_files/container_5g_rfsim.xml @@ -133,16 +133,16 @@ Attach_UE Attach OAI UE (Wait for IP) rfsim5g_ue rfsim5g_ue2 rfsim5g_ue3 rfsim5g_ue4 rfsim5g_ue5 rfsim5g_ue6 rfsim5g_ue7 rfsim5g_ue8 rfsim5g_ue9 rfsim5g_ue10 - cacofonix cacofonix cacofonix cacofonix cacofonix cacofonix cacofonix cacofonix cacofonix cacofonix + acamas acamas acamas acamas acamas acamas acamas acamas acamas acamas Ping Ping ext-dn from NR-UE rfsim5g_ue - cacofonix + acamas rfsim5g_ext_dn - cacofonix + acamas -c 20 -i 0.25 5 @@ -151,9 +151,9 @@ Ping Ping NR-UE from ext-dn rfsim5g_ext_dn - cacofonix + acamas rfsim5g_ue - cacofonix + acamas -c 20 -i 0.25 5 @@ -162,9 +162,9 @@ Ping Ping ext-dn from Second NR-UE rfsim5g_ue2 - cacofonix + acamas rfsim5g_ext_dn - cacofonix + acamas -c 20 -i 0.25 5 @@ -173,9 +173,9 @@ Ping Ping Second NR-UE from ext-dn rfsim5g_ext_dn - cacofonix + acamas rfsim5g_ue2 - cacofonix + acamas -c 20 -i 0.25 5 @@ -184,9 +184,9 @@ Ping Ping ext-dn from both UEs rfsim5g_ue rfsim5g_ue2 - cacofonix cacofonix + acamas acamas rfsim5g_ext_dn - cacofonix + acamas -c 20 -i 0.25 5 @@ -195,9 +195,9 @@ Ping Ping ext-dn from all UEs rfsim5g_ue rfsim5g_ue2 rfsim5g_ue3 rfsim5g_ue4 rfsim5g_ue5 rfsim5g_ue6 rfsim5g_ue7 rfsim5g_ue8 rfsim5g_ue9 rfsim5g_ue10 - cacofonix cacofonix cacofonix cacofonix cacofonix cacofonix cacofonix cacofonix cacofonix cacofonix + acamas acamas acamas acamas acamas acamas acamas acamas acamas acamas rfsim5g_ext_dn - cacofonix + acamas -c 20 -i 0.25 -s 1016 5 @@ -207,9 +207,9 @@ Iperf (DL/3Mbps/UDP)(30 sec) -u -b 3M -t 20 -R rfsim5g_ue - cacofonix + acamas rfsim5g_ext_dn - cacofonix + acamas 5 90 @@ -219,9 +219,9 @@ Iperf (UL/1Mbps/UDP)(30 sec) -u -b 1M -t 20 rfsim5g_ue - cacofonix + acamas rfsim5g_ext_dn - cacofonix + acamas 5 90 @@ -230,21 +230,21 @@ Attach_UE Attach OAI UE 1 and 2 rfsim5g_ue rfsim5g_ue2 - cacofonix cacofonix + acamas acamas Detach_UE Detach OAI UE 1 and 2 rfsim5g_ue rfsim5g_ue2 - cacofonix cacofonix + acamas acamas Detach_UE 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 + acamas acamas acamas acamas acamas acamas acamas acamas diff --git a/ci-scripts/xml_files/container_5g_rfsim_24prb.xml b/ci-scripts/xml_files/container_5g_rfsim_24prb.xml index 91275a5f10..752252fc11 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_24prb.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_24prb.xml @@ -91,7 +91,7 @@ Attach_UE Attach OAI UE (Wait for IP) rfsim5g_ue - cacofonix + acamas @@ -104,9 +104,9 @@ Ping Ping ext-dn from NR-UE rfsim5g_ue - cacofonix + acamas rfsim5g_ext_dn - cacofonix + acamas -c 20 -i0.5 80 @@ -115,9 +115,9 @@ Ping Ping NR-UE from ext-dn rfsim5g_ext_dn - cacofonix + acamas rfsim5g_ue - cacofonix + acamas -c 20 -i0.2 5 @@ -127,9 +127,9 @@ Iperf (DL/3Mbps/UDP)(30 sec) -u -b 3M -t 20 -R rfsim5g_ue - cacofonix + acamas rfsim5g_ext_dn - cacofonix + acamas 5 90 @@ -139,9 +139,9 @@ Iperf (UL/1Mbps/UDP)(30 sec) -u -b 1M -t 20 rfsim5g_ue - cacofonix + acamas rfsim5g_ext_dn - cacofonix + acamas 5 90 @@ -149,14 +149,14 @@ Custom_Command Force Msg3 C-RNTI RA - cacofonix + acamas echo ciUE force_crnti_ra | nc 192.168.71.150 8091 Custom_Command Force RRC_IDLE (UE ID 0) - cacofonix + acamas echo ciUE force_RRC_IDLE | nc 192.168.71.150 8091 diff --git a/ci-scripts/xml_files/container_5g_rfsim_2x2.xml b/ci-scripts/xml_files/container_5g_rfsim_2x2.xml index 77d39a3c55..779a453749 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_2x2.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_2x2.xml @@ -73,16 +73,16 @@ Attach_UE Attach OAI UE (Wait for IP) rfsim5g_ue - cacofonix + acamas Ping Ping ext-dn from NR-UE rfsim5g_ue - cacofonix + acamas rfsim5g_ext_dn - cacofonix + acamas -c 20 -i 0.25 5 @@ -91,9 +91,9 @@ Ping Ping NR-UE from ext-dn rfsim5g_ext_dn - cacofonix + acamas rfsim5g_ue - cacofonix + acamas -c 20 -i 0.25 5 @@ -103,9 +103,9 @@ Iperf (DL/10Mbps/UDP)(30 sec) -u -b 10M -t 20 -R rfsim5g_ue - cacofonix + acamas rfsim5g_ext_dn - cacofonix + acamas 5 90 @@ -115,9 +115,9 @@ Iperf (UL/4Mbps/UDP)(30 sec) -u -b 4M -t 20 rfsim5g_ue - cacofonix + acamas rfsim5g_ext_dn - cacofonix + acamas 5 90 diff --git a/ci-scripts/xml_files/container_5g_rfsim_fdd_phytest.xml b/ci-scripts/xml_files/container_5g_rfsim_fdd_phytest.xml index cd908d0d82..58ff14102b 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_fdd_phytest.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_fdd_phytest.xml @@ -49,7 +49,7 @@ Custom_Command Clean-Up any residual volume - cacofonix + acamas docker volume rm 5g_rfsimulator_fdd_phytest_rrc.config -f @@ -80,9 +80,9 @@ Ping Ping gNB from NR-UE rfsim5g_ue - cacofonix + acamas rfsim5g_gnb_nos1 - cacofonix + acamas -c20 -i0.2 0 @@ -91,9 +91,9 @@ Ping Ping NR-UE from gNB rfsim5g_gnb_nos1 - cacofonix + acamas rfsim5g_ue - cacofonix + acamas -c20 -i0.2 0 @@ -103,9 +103,9 @@ Iperf (DL/30kbps/UDP)(30 sec) -u -b 0.03M -t 20 -R -c 10.0.1.1 rfsim5g_ue - cacofonix + acamas rfsim5g_gnb_nos1 - cacofonix + acamas 5 90 @@ -115,9 +115,9 @@ Iperf (UL/30kbps/UDP)(30 sec) -u -b 0.03M -t 20 -c 10.0.1.1 rfsim5g_ue - cacofonix + acamas rfsim5g_gnb_nos1 - cacofonix + acamas 5 90 diff --git a/ci-scripts/xml_files/container_5g_rfsim_fr2_32prb.xml b/ci-scripts/xml_files/container_5g_rfsim_fr2_32prb.xml index 1965f95aa0..3aa9a395b3 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_fr2_32prb.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_fr2_32prb.xml @@ -73,16 +73,16 @@ Attach_UE Attach OAI UE (Wait for IP) rfsim5g_ue - cacofonix + acamas Ping Ping ext-dn from NR-UE rfsim5g_ue - cacofonix + acamas rfsim5g_ext_dn - cacofonix + acamas -c 20 -i0.2 0 @@ -91,9 +91,9 @@ Ping Ping NR-UE from ext-dn rfsim5g_ext_dn - cacofonix + acamas rfsim5g_ue - cacofonix + acamas -c 20 -i0.2 0 diff --git a/ci-scripts/xml_files/container_5g_rfsim_ntn_geo.xml b/ci-scripts/xml_files/container_5g_rfsim_ntn_geo.xml index 32cc3b1f58..9893f805eb 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_ntn_geo.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_ntn_geo.xml @@ -78,16 +78,16 @@ Attach_UE Attach OAI UE (Wait for IP) rfsim5g_ue - cacofonix + acamas Ping Ping ext-dn from NR-UE rfsim5g_ue - cacofonix + acamas rfsim5g_ext_dn - cacofonix + acamas -c 20 -i 0.25 5 @@ -96,9 +96,9 @@ Ping Ping NR-UE from ext-dn rfsim5g_ext_dn - cacofonix + acamas rfsim5g_ue - cacofonix + acamas -c 20 -i 0.25 5 @@ -106,7 +106,7 @@ Custom_Command Trigger Reestablishment - cacofonix + acamas echo ci force_reestab | nc 192.168.71.140 9090 | grep -E 'Reset RLC counters of UE RNTI [0-9a-f]{4} to trigger reestablishment' yes @@ -115,9 +115,9 @@ Ping Ping ext-dn from NR-UE rfsim5g_ue - cacofonix + acamas rfsim5g_ext_dn - cacofonix + acamas -c 20 -i0.5 -w25 80 @@ -125,7 +125,7 @@ Custom_Command Verify Reestablishment - cacofonix + acamas echo ci get_reestab_count | nc 192.168.71.140 9090 | grep -E 'UE RNTI [0-9a-f]{4} reestab 1' yes diff --git a/ci-scripts/xml_files/container_5g_rfsim_ntn_leo.xml b/ci-scripts/xml_files/container_5g_rfsim_ntn_leo.xml index 2846fc016e..61bf4d5e48 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_ntn_leo.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_ntn_leo.xml @@ -73,16 +73,16 @@ Attach_UE Attach OAI UE (Wait for IP) rfsim5g_ue - cacofonix + acamas Ping Ping ext-dn from NR-UE rfsim5g_ue - cacofonix + acamas rfsim5g_ext_dn - cacofonix + acamas -c 20 -i 0.25 5 @@ -91,9 +91,9 @@ Ping Ping NR-UE from ext-dn rfsim5g_ext_dn - cacofonix + acamas rfsim5g_ue - cacofonix + acamas -c 20 -i 0.25 5 diff --git a/ci-scripts/xml_files/container_5g_rfsim_sidelink.xml b/ci-scripts/xml_files/container_5g_rfsim_sidelink.xml index ac7e28f003..1e11870b88 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_sidelink.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_sidelink.xml @@ -77,7 +77,7 @@ Custom_Command Check that UE synched - cacofonix + acamas docker logs rfsim5g-oai-nr-ue-2 | grep -m 1 "PSBCH RX:OK" 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 34d46cc87d..e4875418b9 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_tdd_dora.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_tdd_dora.xml @@ -48,7 +48,7 @@ Custom_Command Clean-Up any residual volume - cacofonix + acamas docker volume rm 5g_rfsimulator_tdd_dora_rrc.config -f @@ -79,9 +79,9 @@ Ping Ping gNB from NR-UE rfsim5g_ue - cacofonix + acamas rfsim5g_gnb_nos1 - cacofonix + acamas -c20 -i0.2 0 @@ -90,9 +90,9 @@ Ping Ping NR-UE from gNB rfsim5g_gnb_nos1 - cacofonix + acamas rfsim5g_ue - cacofonix + acamas -c20 -i0.2 0 diff --git a/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml b/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml index bedb40799e..82011e3cc2 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml @@ -73,16 +73,16 @@ Attach_UE Attach OAI UE (Wait for IP) rfsim5g_ue - cacofonix + acamas Ping Ping ext-dn from NR-UE rfsim5g_ue - cacofonix + acamas rfsim5g_ext_dn - cacofonix + acamas -c 20 -i 0.25 5 @@ -91,9 +91,9 @@ Ping Ping NR-UE from ext-dn rfsim5g_ext_dn - cacofonix + acamas rfsim5g_ue - cacofonix + acamas -c 20 -i 0.25 5 @@ -103,9 +103,9 @@ Iperf (DL/3Mbps/UDP)(30 sec) -u -b 3M -t 20 -R rfsim5g_ue - cacofonix + acamas rfsim5g_ext_dn - cacofonix + acamas 5 90 @@ -115,9 +115,9 @@ Iperf (UL/1Mbps/UDP)(30 sec) -u -b 1M -t 20 rfsim5g_ue - cacofonix + acamas rfsim5g_ext_dn - cacofonix + acamas 5 90 From 621aa3c12ea2921b6c4d9aae701471c82b610a04 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 10 Jul 2025 08:37:29 +0200 Subject: [PATCH 214/964] Cleanup possible transmission interrupt states --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c | 1 + openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 36cb53b8f2..13dc711b77 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -3283,6 +3283,7 @@ void nr_mac_update_timers(module_id_t module_id, frame_t frame, slot_t slot) nr_timer_stop(&sched_ctrl->transm_interrupt); if (UE->interrupt_action == FOLLOW_OUTOFSYNC) nr_mac_trigger_ul_failure(sched_ctrl, UE->current_DL_BWP.scs); + /* else: default FOLLOW_INSYNC: nothing to do (UE is now active again) */ } } } diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index ea2cc617bd..704488f062 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -733,7 +733,7 @@ typedef struct nr_mac_rrc_ul_if_s { initial_ul_rrc_message_transfer_func_t initial_ul_rrc_message_transfer; } nr_mac_rrc_ul_if_t; -typedef enum interrupt_followup_action { FOLLOW_INSYNC, FOLLOW_INSYNC_RECONFIG, FOLLOW_OUTOFSYNC } interrupt_followup_action_t; +typedef enum interrupt_followup_action { FOLLOW_INSYNC, FOLLOW_OUTOFSYNC } interrupt_followup_action_t; /*! \brief UE list used by gNB to order UEs/CC for scheduling*/ typedef struct { From a13a8f01af31f5d30f531523d191a64aa6973614 Mon Sep 17 00:00:00 2001 From: rmagueta Date: Wed, 6 Nov 2024 12:07:44 +0000 Subject: [PATCH 215/964] Add F1AP procedures related to measurementTimingConfiguration --- openair2/COMMON/f1ap_messages_types.h | 1 + openair2/F1AP/lib/f1ap_ue_context.c | 25 ++++++++++++++++++- openair2/F1AP/tests/f1ap_lib_test.c | 2 ++ .../LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c | 1 - openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c | 1 - 5 files changed, 27 insertions(+), 3 deletions(-) diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h index 89826e7ff5..e44e1dccb4 100644 --- a/openair2/COMMON/f1ap_messages_types.h +++ b/openair2/COMMON/f1ap_messages_types.h @@ -381,6 +381,7 @@ typedef struct f1ap_cu_to_du_rrc_info_s { byte_array_t *cg_configinfo; byte_array_t *ue_cap; byte_array_t *meas_config; + byte_array_t *meas_timing_config; byte_array_t *ho_prep_info; } f1ap_cu_to_du_rrc_info_t; diff --git a/openair2/F1AP/lib/f1ap_ue_context.c b/openair2/F1AP/lib/f1ap_ue_context.c index a1b5531c2b..9d8cbfe15f 100644 --- a/openair2/F1AP/lib/f1ap_ue_context.c +++ b/openair2/F1AP/lib/f1ap_ue_context.c @@ -57,8 +57,9 @@ static F1AP_CUtoDURRCInformation_t encode_cu_to_du_rrc_info(const f1ap_cu_to_du_ } /* optional: HandoverPreparationInformation */ + F1AP_ProtocolExtensionContainer_10696P60_t *p = NULL; if (cu2du->ho_prep_info) { - F1AP_ProtocolExtensionContainer_10696P60_t *p = calloc_or_fail(1, sizeof(*p)); + p = calloc_or_fail(1, sizeof(*p)); enc.iE_Extensions = (struct F1AP_ProtocolExtensionContainer *)p; asn1cSequenceAdd(p->list, F1AP_CUtoDURRCInformation_ExtIEs_t, ie_ext); ie_ext->id = F1AP_ProtocolIE_ID_id_HandoverPreparationInformation; @@ -68,6 +69,20 @@ static F1AP_CUtoDURRCInformation_t encode_cu_to_du_rrc_info(const f1ap_cu_to_du_ F1AP_HandoverPreparationInformation_t *hpi = &ie_ext->extensionValue.choice.HandoverPreparationInformation; OCTET_STRING_fromBuf(hpi, (const char *)ba->buf, ba->len); } + + /* optional: iE_Extensions */ + if (cu2du->meas_timing_config) { + if (!p) + p = calloc_or_fail(1, sizeof(*p)); + enc.iE_Extensions = (struct F1AP_ProtocolExtensionContainer *)p; + asn1cSequenceAdd(p->list, F1AP_CUtoDURRCInformation_ExtIEs_t, ie_ext); + ie_ext->id = F1AP_ProtocolIE_ID_id_MeasurementTimingConfiguration; + ie_ext->criticality = F1AP_Criticality_ignore; + ie_ext->extensionValue.present = F1AP_CUtoDURRCInformation_ExtIEs__extensionValue_PR_MeasurementTimingConfiguration; + const byte_array_t *ba = cu2du->meas_timing_config; + F1AP_MeasurementTimingConfiguration_t *mtc = &ie_ext->extensionValue.choice.MeasurementTimingConfiguration; + OCTET_STRING_fromBuf(mtc, (const char *)ba->buf, ba->len); + } return enc; } @@ -98,6 +113,11 @@ static bool decode_cu_to_du_rrc_info(f1ap_cu_to_du_rrc_info_t *dec, const F1AP_C const F1AP_HandoverPreparationInformation_t *hopi = &cu2du_info_ext->extensionValue.choice.HandoverPreparationInformation; *dec->ho_prep_info = create_byte_array(hopi->size, (uint8_t*) hopi->buf); break; + case F1AP_ProtocolIE_ID_id_MeasurementTimingConfiguration: + dec->meas_timing_config = calloc_or_fail(1, sizeof(*dec->meas_timing_config)); + const F1AP_MeasurementTimingConfiguration_t *mtc = &cu2du_info_ext->extensionValue.choice.MeasurementTimingConfiguration; + *dec->meas_timing_config = create_byte_array(mtc->size, (uint8_t *)mtc->buf); + break; default: PRINT_ERROR("received unsupported F1AP CUtoDURRCInfo extension container %ld\n", cu2du_info_ext->id); } @@ -112,6 +132,7 @@ static f1ap_cu_to_du_rrc_info_t cp_cu_to_du_rrc_info(const f1ap_cu_to_du_rrc_inf CP_OPT_BYTE_ARRAY(dst.cg_configinfo, src->cg_configinfo); CP_OPT_BYTE_ARRAY(dst.ue_cap, src->ue_cap); CP_OPT_BYTE_ARRAY(dst.meas_config, src->meas_config); + CP_OPT_BYTE_ARRAY(dst.meas_timing_config, src->meas_timing_config); CP_OPT_BYTE_ARRAY(dst.ho_prep_info, src->ho_prep_info); return dst; } @@ -126,6 +147,7 @@ static bool eq_cu_to_du_rrc_info(const f1ap_cu_to_du_rrc_info_t *a, const f1ap_c _F1_EQ_CHECK_OPTIONAL_IE(a, b, cg_configinfo, eq_ba); _F1_EQ_CHECK_OPTIONAL_IE(a, b, ue_cap, eq_ba); _F1_EQ_CHECK_OPTIONAL_IE(a, b, meas_config, eq_ba); + _F1_EQ_CHECK_OPTIONAL_IE(a, b, meas_timing_config, eq_ba); _F1_EQ_CHECK_OPTIONAL_IE(a, b, ho_prep_info, eq_ba); return true; } @@ -135,6 +157,7 @@ static void free_cu_to_du_rrc_info(f1ap_cu_to_du_rrc_info_t *cu2du) FREE_OPT_BYTE_ARRAY(cu2du->cg_configinfo); FREE_OPT_BYTE_ARRAY(cu2du->ue_cap); FREE_OPT_BYTE_ARRAY(cu2du->meas_config); + FREE_OPT_BYTE_ARRAY(cu2du->meas_timing_config); FREE_OPT_BYTE_ARRAY(cu2du->ho_prep_info); } diff --git a/openair2/F1AP/tests/f1ap_lib_test.c b/openair2/F1AP/tests/f1ap_lib_test.c index ebf90fc648..72ea809245 100644 --- a/openair2/F1AP/tests/f1ap_lib_test.c +++ b/openair2/F1AP/tests/f1ap_lib_test.c @@ -755,6 +755,7 @@ static void test_f1ap_ue_context_setup_request() orig.cu_to_du_rrc_info.cg_configinfo = get_malloced_test_ba("CG-CONFIGINFO"); orig.cu_to_du_rrc_info.ue_cap = get_malloced_test_ba("UE CAP"); orig.cu_to_du_rrc_info.meas_config = get_malloced_test_ba("UE MEASUREMENT CONFIGURATION"); + orig.cu_to_du_rrc_info.meas_timing_config = get_malloced_test_ba("MEASUREMENT TIMING CONFIGURATION"); orig.cu_to_du_rrc_info.ho_prep_info = get_malloced_test_ba("PREPARATION DATA FOR HANDOVER"); orig.srbs_len = 2; orig.srbs = calloc_or_fail(orig.srbs_len, sizeof(*orig.srbs)); @@ -996,6 +997,7 @@ static void test_f1ap_ue_context_modification_request() .cg_configinfo = get_malloced_test_ba("Modified"), .ue_cap = get_malloced_test_ba("UE forgot to send earlier"), .meas_config = get_malloced_test_ba("with updates from another cell"), + .meas_timing_config = get_malloced_test_ba("measurement timing configuration"), .ho_prep_info = get_malloced_test_ba("prepare to ho soon!"), }; _F1_MALLOC(orig.cu_to_du_rrc_info, cu2du); diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c index cf6c5b2563..deec619e3d 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c @@ -93,7 +93,6 @@ static void ue_context_modification_required_direct(const f1ap_ue_context_modif_ du2cu->cellGroupConfig = malloc(du2cu->cellGroupConfig_length * sizeof(*du2cu->cellGroupConfig)); AssertFatal(du2cu->cellGroupConfig != NULL, "out of memory\n"); memcpy(du2cu->cellGroupConfig, required->du_to_cu_rrc_information->cellGroupConfig, du2cu->cellGroupConfig_length); - AssertFatal(required->du_to_cu_rrc_information->measGapConfig == NULL && required->du_to_cu_rrc_information->measGapConfig_length == 0, "not handled yet\n"); AssertFatal(required->du_to_cu_rrc_information->requestedP_MaxFR1 == NULL && required->du_to_cu_rrc_information->requestedP_MaxFR1_length == 0, "not handled yet\n"); } f1ap_msg->cause = required->cause; diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c index 19bf8039b6..c7e23ed702 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c @@ -117,7 +117,6 @@ static void ue_context_modification_required_f1ap(const f1ap_ue_context_modif_re du2cu->cellGroupConfig = malloc(du2cu->cellGroupConfig_length * sizeof(*du2cu->cellGroupConfig)); AssertFatal(du2cu->cellGroupConfig != NULL, "out of memory\n"); memcpy(du2cu->cellGroupConfig, required->du_to_cu_rrc_information->cellGroupConfig, du2cu->cellGroupConfig_length); - AssertFatal(required->du_to_cu_rrc_information->measGapConfig == NULL && required->du_to_cu_rrc_information->measGapConfig_length == 0, "not handled yet\n"); AssertFatal(required->du_to_cu_rrc_information->requestedP_MaxFR1 == NULL && required->du_to_cu_rrc_information->requestedP_MaxFR1_length == 0, "not handled yet\n"); } f1ap_msg->cause = required->cause; From 7b8427e101f89fd7d018d945ffeefdb09d158c5a Mon Sep 17 00:00:00 2001 From: rmagueta Date: Thu, 10 Jul 2025 09:06:34 +0200 Subject: [PATCH 216/964] UE RRC: Print warning that measurement gaps are not supported --- openair2/RRC/NR_UE/rrc_UE.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index da1b3d8ba0..87cb68303a 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -1871,8 +1871,7 @@ static void nr_rrc_ue_process_measConfig(rrcPerNB_t *rrc, NR_MeasConfig_t *const if (measConfig->measIdToAddModList) handle_measid_addmod(rrc, measConfig->measIdToAddModList, timers); - AssertFatal(!measConfig->measGapConfig, "Measurement gaps not yet supported\n"); - AssertFatal(!measConfig->measGapSharingConfig, "Measurement gaps not yet supported\n"); + LOG_W(NR_RRC, "Measurement gaps not yet supported!\n"); if (measConfig->s_MeasureConfig) { if (measConfig->s_MeasureConfig->present == NR_MeasConfig__s_MeasureConfig_PR_ssb_RSRP) { From c2d9fb358959776397a5dfa719d1200e845aef97 Mon Sep 17 00:00:00 2001 From: rmagueta Date: Thu, 10 Jul 2025 09:06:39 +0200 Subject: [PATCH 217/964] Add MeasGap Configuration in Radio config Add some helper functions that will be used by the MAC handler to fill the right MeasGap configuration based on Measurement Configuration sent by the CU, in the next commit. --- openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 13 ++ openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c | 195 +++++++++++++++++++ openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h | 9 + 3 files changed, 217 insertions(+) diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 704488f062..477b9ce0c0 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -733,6 +733,19 @@ typedef struct nr_mac_rrc_ul_if_s { initial_ul_rrc_message_transfer_func_t initial_ul_rrc_message_transfer; } nr_mac_rrc_ul_if_t; +typedef struct measgap_config { + bool enable; + int mgrp_ms; + long mgrp; + long gapOffset; + long mgta; + int n_slots_mgta; + int n_slots_advance; + float mgl_ms; + long mgl; + int mgl_slots; +} measgap_config_t; + typedef enum interrupt_followup_action { FOLLOW_INSYNC, FOLLOW_OUTOFSYNC } interrupt_followup_action_t; /*! \brief UE list used by gNB to order UEs/CC for scheduling*/ diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c index a64cd61afb..ad22b9dd63 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c @@ -4090,3 +4090,198 @@ NR_ReconfigurationWithSync_t *get_reconfiguration_with_sync(rnti_t rnti, uid_t u return reconfigurationWithSync; } + +static NR_MeasGapConfig_t *get_gap_config_from_smtc(const NR_SSB_MTC_t *ssb_mtc) +{ + NR_MeasGapConfig_t *measGapConfig = calloc_or_fail(1, sizeof(*measGapConfig)); + measGapConfig->ext1 = calloc_or_fail(1, sizeof(*measGapConfig->ext1)); + measGapConfig->ext1->gapUE = calloc_or_fail(1, sizeof(*measGapConfig->ext1->gapUE)); + measGapConfig->ext1->gapUE->present = NR_SetupRelease_GapConfig_PR_setup; + NR_GapConfig_t *gap_config = calloc_or_fail(1, sizeof(*gap_config)); + measGapConfig->ext1->gapUE->choice.setup = gap_config; + + // mgta = Measurement Gap Timing Advance, to provide sufficient time for the UE to re-tune its transceiver + // This allows the Measurement Gap to extend mgta ms either side of the SS/PBCH Measurement Window. + gap_config->mgta = NR_GapConfig__mgta_ms0dot5; + + // mgrp = Measurement Gap Repetition Period + // gapOffset = It defines the start of the Measurement Gaps relative to the start of the radio frame with SFN = 0 + // The Measurement Gaps need to be synchronized with the SS/PBCH transmissions which are to be measured + gap_config->mgrp = NR_GapConfig__mgrp_ms160; + switch (ssb_mtc->periodicityAndOffset.present) { + case NR_SSB_MTC__periodicityAndOffset_PR_sf20: + gap_config->gapOffset = ssb_mtc->periodicityAndOffset.choice.sf20; + break; + case NR_SSB_MTC__periodicityAndOffset_PR_sf40: + gap_config->gapOffset = ssb_mtc->periodicityAndOffset.choice.sf40; + break; + case NR_SSB_MTC__periodicityAndOffset_PR_sf80: + gap_config->gapOffset = ssb_mtc->periodicityAndOffset.choice.sf80; + break; + case NR_SSB_MTC__periodicityAndOffset_PR_sf160: + gap_config->gapOffset = ssb_mtc->periodicityAndOffset.choice.sf160; + break; + default: + LOG_W(NR_RRC, "SMTC periodicity higher than MGRP\n"); + // With this configuration, not all SSBs belong to the Measurement Gap. + if (ssb_mtc->periodicityAndOffset.present == NR_SSB_MTC__periodicityAndOffset_PR_sf5) { + gap_config->gapOffset = ssb_mtc->periodicityAndOffset.choice.sf5; + } else if (ssb_mtc->periodicityAndOffset.present == NR_SSB_MTC__periodicityAndOffset_PR_sf10) { + gap_config->gapOffset = ssb_mtc->periodicityAndOffset.choice.sf10; + } + } + + // mgl = Measurement Gap Length + // FIXME: At least the duration of the SMTC plus 2 times the mgta should be enough, + // however, at the moment it only works by setting the maximum value + gap_config->mgl = NR_GapConfig__mgl_ms6; + + return measGapConfig; +} + +NR_MeasurementTimingConfiguration_t *get_nr_mtc(uint8_t *buf, uint32_t len) +{ + if (buf == NULL || len == 0) + return NULL; + + NR_MeasurementTimingConfiguration_t *mtc = NULL; + asn_dec_rval_t dec_rval = uper_decode(NULL, &asn_DEF_NR_MeasurementTimingConfiguration, (void **)&mtc, buf, len, 0, 0); + if (dec_rval.code != RC_OK) { + LOG_E(NR_MAC, "cannot decode NR MeasurementTimingConfiguration, ignoring\n"); + ASN_STRUCT_FREE(asn_DEF_NR_MeasurementTimingConfiguration, mtc); + return NULL; + } + return mtc; +} + +/** @brief return Measurement Gap Repetition Period from ASN.1 config */ +static int get_mgrp(long mgrp) +{ + switch (mgrp) { + case NR_GapConfig__mgrp_ms20: + return 20; + case NR_GapConfig__mgrp_ms40: + return 40; + case NR_GapConfig__mgrp_ms80: + return 80; + case NR_GapConfig__mgrp_ms160: + return 160; + default: + LOG_E(NR_MAC, "Invalid MGRP %ld\n", mgrp); + return -1; + } +} + +/** @brief Return Measurement Gap Length from ASN.1 config */ +static float get_mgl(long mgl) +{ + switch (mgl) { + case NR_GapConfig__mgl_ms1dot5: + return 1.5; + case NR_GapConfig__mgl_ms3: + return 3.0; + case NR_GapConfig__mgl_ms3dot5: + return 3.5; + case NR_GapConfig__mgl_ms4: + return 4; + case NR_GapConfig__mgl_ms5dot5: + return 5.5; + case NR_GapConfig__mgl_ms6: + return 6; + default: + LOG_E(NR_MAC, "Invalid MGL %ld\n", mgl); + return -1; + } +} + +/** @brief Return Measurement Gap Timing Advance, from ASN.1 config */ +static float get_mgta(long mgta) +{ + switch (mgta) { + case NR_GapConfig__mgta_ms0: + return 0.0; + case NR_GapConfig__mgta_ms0dot25: + return 0.25; + case NR_GapConfig__mgta_ms0dot5: + return 0.5; + default: + LOG_E(NR_MAC, "Invalid MGTA %ld\n", mgta); + return -1; + } +} + +/** @brief Return Measurement Gap Configuration, from ASN.1 config */ +const NR_GapConfig_t *get_gap_config(const NR_MeasGapConfig_t *mgc) +{ + if (mgc->gapFR2 && mgc->gapFR2->present == NR_SetupRelease_GapConfig_PR_setup) + return mgc->gapFR2->choice.setup; + + // FR1 case + if (!mgc->ext1) + return NULL; + + const NR_SetupRelease_GapConfig_t *gapUE = mgc->ext1->gapUE; + if (gapUE && gapUE->present == NR_SetupRelease_GapConfig_PR_setup) + return gapUE->choice.setup; + + const NR_SetupRelease_GapConfig_t *gapFR1 = mgc->ext1->gapFR1; + if (gapFR1 && gapFR1->present == NR_SetupRelease_GapConfig_PR_setup) + return gapFR1->choice.setup; + + return NULL; +} + +measgap_config_t create_measgap_config(const NR_MeasurementTimingConfiguration_t *mtc, int scs, int min_rxtxtime) +{ + measgap_config_t mgc = {0}; + const NR_MeasTimingList_t *mtlist = mtc->criticalExtensions.choice.c1->choice.measTimingConf->measTiming; + const NR_MeasTiming_t *mt = mtlist->list.array[0]; + DevAssert(mt != NULL && mt->frequencyAndTiming != NULL); + const struct NR_MeasTiming__frequencyAndTiming *ft = mt->frequencyAndTiming; + const NR_SSB_MTC_t *ssb_mtc = &ft->ssb_MeasurementTimingConfiguration; + NR_MeasGapConfig_t *measGapConfig = get_gap_config_from_smtc(ssb_mtc); + const NR_GapConfig_t *gap_config = get_gap_config(measGapConfig); + if (!gap_config) + return mgc; + + mgc.mgrp_ms = get_mgrp(gap_config->mgrp); + DevAssert(mgc.mgrp_ms != -1); + mgc.mgrp = gap_config->mgrp; + + mgc.gapOffset = gap_config->gapOffset; + mgc.mgta = gap_config->mgta; + mgc.n_slots_mgta = ((int)(10 * get_mgta(gap_config->mgta)) << scs) / 10; + + // We start the timer K2 slots earlier to avoid scheduling feedback PUCCHs inside measGap + // or depending on the current min_rxtxtime earlier + // TS 38.214 - Table 6.1.2.1.1.2 + const int max_k2 = max(3, min_rxtxtime); + + mgc.n_slots_advance = mgc.n_slots_mgta + max_k2; + + mgc.mgl_ms = get_mgl(gap_config->mgl); + DevAssert(mgc.mgl_ms != -1); + mgc.mgl = gap_config->mgl; + mgc.mgl_slots = ((int)(10 * (mgc.mgl_ms + max_k2)) << scs) / 10; + + mgc.enable = true; + return mgc; +} + +int encode_measgap_config(const measgap_config_t *c, uint8_t *buf) +{ + NR_MeasGapConfig_t *measGapConfig = calloc_or_fail(1, sizeof(*measGapConfig)); + measGapConfig->ext1 = calloc_or_fail(1, sizeof(*measGapConfig->ext1)); + measGapConfig->ext1->gapUE = calloc_or_fail(1, sizeof(*measGapConfig->ext1->gapUE)); + measGapConfig->ext1->gapUE->present = NR_SetupRelease_GapConfig_PR_setup; + NR_GapConfig_t *gap_config = calloc_or_fail(1, sizeof(*gap_config)); + measGapConfig->ext1->gapUE->choice.setup = gap_config; + gap_config->mgta = c->mgta; + gap_config->mgrp = c->mgrp; + gap_config->gapOffset = c->gapOffset; + gap_config->mgl = c->mgl; + asn_enc_rval_t enc_rval_mgc = uper_encode_to_buffer(&asn_DEF_NR_MeasGapConfig, NULL, measGapConfig, buf, 1024); + AssertFatal(enc_rval_mgc.encoded > 0, "Could not encode CellGroup, failed element %s\n", enc_rval_mgc.failed_type->name); + ASN_STRUCT_FREE(asn_DEF_NR_MeasGapConfig, measGapConfig); + return (int)((enc_rval_mgc.encoded + 7) >> 3); +} diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h index bdf56a3310..51c30c38b6 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h @@ -28,6 +28,8 @@ #include "NR_BCCH-DL-SCH-Message.h" #include "NR_CellGroupConfig.h" #include "NR_UE-NR-Capability.h" +#include "NR_MeasConfig.h" +#include "NR_MeasurementTimingConfiguration.h" #include "NR_UL-CCCH-Message.h" #include "f1ap_messages_types.h" #include "common/platform_types.h" @@ -42,6 +44,9 @@ typedef struct nr_mac_config_t nr_mac_config_t; struct nr_mac_timers; typedef struct nr_mac_timers nr_mac_timers_t; +struct measgap_config; +typedef struct measgap_config measgap_config_t; + void nr_rrc_config_dl_tda(struct NR_PDSCH_TimeDomainResourceAllocationList *pdsch_TimeDomainAllocationList, frame_type_t frame_type, NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon, @@ -119,4 +124,8 @@ NR_RLC_BearerConfig_t *get_DRB_RLC_BearerConfig(long lcChannelId, long priority, const nr_rlc_configuration_t *default_rlc_config); +NR_MeasurementTimingConfiguration_t *get_nr_mtc(uint8_t *buf, uint32_t len); +measgap_config_t create_measgap_config(const NR_MeasurementTimingConfiguration_t *mtc, int scs, int min_rxtxtime); +int encode_measgap_config(const measgap_config_t *c, uint8_t *buf); + #endif From dfbb6b1509be3ce935383ff5d91c074e3cfee492 Mon Sep 17 00:00:00 2001 From: rmagueta Date: Thu, 10 Jul 2025 08:35:11 +0200 Subject: [PATCH 218/964] Handle Measurement Timing Configuration in DU/MAC handler --- openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c | 15 +++++++++++++-- openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 1 + 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c index 30d3999f75..43b73705e9 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -625,7 +625,9 @@ void ue_context_setup_request(const f1ap_ue_context_setup_req_t *req) } else if (cu2du->ue_cap != NULL) { ue_cap = get_ue_nr_cap(*req->gNB_DU_ue_id, cu2du->ue_cap->buf, cu2du->ue_cap->len); } - AssertFatal(cu2du->meas_config == NULL, "MeasConfig not handled\n"); + NR_MeasurementTimingConfiguration_t *mtc = NULL; + if (cu2du->meas_timing_config != NULL) + mtc = get_nr_mtc(cu2du->meas_timing_config->buf, cu2du->meas_timing_config->len); /* 38.473: "For DC operation, the CG-ConfigInfo IE shall be included in the CU * to DU RRC Information IE at the gNB acting as secondary node" As of now, @@ -696,6 +698,16 @@ void ue_context_setup_request(const f1ap_ue_context_setup_req_t *req) int ss_type = cg_configinfo ? NR_SearchSpace__searchSpaceType_PR_ue_Specific: NR_SearchSpace__searchSpaceType_PR_common; configure_UE_BWP(mac, scc, UE, false, ss_type, -1, -1); + if (mtc) { + /* creates a suitable measGap config to be used in the gNB */ + UE->measgap_config = create_measgap_config(mtc, UE->current_DL_BWP.scs, mac->radio_config.minRXTXTIME); + /* encodes the measGapConfig created, if useful (or not!) */ + byte_array_t *mgc = calloc_or_fail(1, sizeof(*mgc)); + mgc->buf = calloc_or_fail(1, 1024); + mgc->len = encode_measgap_config(&UE->measgap_config, mgc->buf); + resp.du_to_cu_rrc_info.meas_gap_config = mgc; + } + NR_SCHED_UNLOCK(&mac->sched_lock); mac->mac_rrc.ue_context_setup_response(&resp); @@ -720,7 +732,6 @@ void ue_context_modification_request(const f1ap_ue_context_mod_req_t *req) byte_array_t *b = req->cu_to_du_rrc_info->ue_cap; ue_cap = get_ue_nr_cap(req->gNB_DU_ue_id, b->buf, b->len); } - AssertFatal(req->cu_to_du_rrc_info->meas_config == NULL, "MeasConfig not handled\n"); } NR_SCHED_LOCK(&mac->sched_lock); diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 477b9ce0c0..84be6f4b5a 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -766,6 +766,7 @@ typedef struct { NR_SpCellConfig_t *reconfigSpCellConfig; interrupt_followup_action_t interrupt_action; NR_UE_NR_Capability_t *capability; + measgap_config_t measgap_config; // UE selected beam index uint8_t UE_beam_index; float ul_thr_ue; From 932b17766782c6f9bf7820a5986fb16e15f45be4 Mon Sep 17 00:00:00 2001 From: rmagueta Date: Thu, 10 Jul 2025 08:38:52 +0200 Subject: [PATCH 219/964] Add logic for measgap scheduling --- common/utils/nr/nr_common.c | 5 +++ common/utils/nr/nr_common.h | 6 +++ openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c | 1 + .../LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 1 + .../NR_MAC_gNB/gNB_scheduler_primitives.c | 38 ++++++++++++++++++- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 2 + 6 files changed, 51 insertions(+), 2 deletions(-) diff --git a/common/utils/nr/nr_common.c b/common/utils/nr/nr_common.c index 5d98a99bb4..7875fe546a 100644 --- a/common/utils/nr/nr_common.c +++ b/common/utils/nr/nr_common.c @@ -1415,6 +1415,11 @@ uint32_t nr_timer_elapsed_time(const NR_timer_t *timer) return timer->counter; } +uint32_t nr_timer_remaining_time(const NR_timer_t *timer) +{ + return timer->target - timer->counter; +} + void nr_timer_setup(NR_timer_t *timer, const uint32_t target, const uint32_t step) { timer->target = target; diff --git a/common/utils/nr/nr_common.h b/common/utils/nr/nr_common.h index f98ce510a2..05ee80c18a 100644 --- a/common/utils/nr/nr_common.h +++ b/common/utils/nr/nr_common.h @@ -222,6 +222,12 @@ bool nr_timer_is_active(const NR_timer_t *timer); * @return Time passed since start of timer */ uint32_t nr_timer_elapsed_time(const NR_timer_t *timer); +/** + * @brief To return how much time is left until the timer expires + * @param timer Timer to be checked + * @return Time left until the timer expires + */ +uint32_t nr_timer_remaining_time(const NR_timer_t *timer); int set_default_nta_offset(frequency_range_t freq_range, uint32_t samples_per_subframe); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c index 39d75907be..faaa00ea3f 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c @@ -201,6 +201,7 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frame, slot_t slo LOG_I(NR_MAC, "Frame.Slot %d.%d\n%s\n", frame, slot, stats_output); } + nr_measgap_scheduling(gNB, frame, slot); nr_mac_update_timers(module_idP, frame, slot); if (wait_prach_completed || get_softmodem_params()->phy_test) { diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index 9c5a00e12c..dad58f52f0 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -628,6 +628,7 @@ static void pf_dl(module_id_t module_id, NR_sched_pdsch_t *sched_pdsch = &sched_ctrl->sched_pdsch; /* get the PID of a HARQ process awaiting retrnasmission, or -1 otherwise */ sched_pdsch->dl_harq_pid = sched_ctrl->retrans_dl_harq.head; + /* Calculate Throughput */ const float a = 0.01f; const uint32_t b = UE->mac_stats.dl.current_bytes; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 13dc711b77..b40329cd69 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -3158,6 +3158,37 @@ void nr_csirs_scheduling(int Mod_idP, frame_t frame, slot_t slot, nfapi_nr_dl_tt } } +void nr_measgap_scheduling(gNB_MAC_INST *nr_mac, frame_t frame, sub_frame_t slot) +{ + NR_SCHED_ENSURE_LOCKED(&nr_mac->sched_lock); + + NR_UEs_t *UE_info = &nr_mac->UE_info; + UE_iterator(UE_info->connected_ue_list, UE) { + measgap_config_t *mgc = &UE->measgap_config; + if (!mgc->enable) + continue; + + const int slots_frame = nr_mac->frame_structure.numb_slots_frame; + const frame_t f = (frame + (slot + mgc->n_slots_advance) / slots_frame) % 1024; + const slot_t s = (slot + mgc->n_slots_advance) % slots_frame; + + // TS 38 331 - Section 5.5.2.9 Measurement gap configuration + if (!(((f % (mgc->mgrp_ms / 10)) == (mgc->gapOffset / 10)) && (s == mgc->gapOffset % 10))) + continue; + + NR_timer_t *t = &UE->UE_sched_ctrl.transm_interrupt; + interrupt_followup_action_t a = nr_timer_is_active(t) ? UE->interrupt_action : FOLLOW_INSYNC; + // start a timer to stop scheduling UE during MeasGap, or extend timer for + // duration of measGap with existing follow-up action + // TODO: if the timer is running, it might be to stop scheduling of the UE afterwards, but then it does not make sense to stop + // scheduling the UE now, we should maybe just skip it? + if (!nr_timer_is_active(t) || nr_timer_remaining_time(t) < mgc->mgl_slots) { + nr_mac_trigger_ul_failure(&UE->UE_sched_ctrl, UE->current_DL_BWP.scs); /* set the UE to "not active" */ + nr_mac_interrupt_ue_transmission(nr_mac, UE, a, mgc->mgl_slots); + } + } +} + void nr_mac_clean_cellgroup(NR_CellGroupConfig_t *cell_group) { DevAssert(cell_group != NULL); @@ -3281,9 +3312,12 @@ void nr_mac_update_timers(module_id_t module_id, frame_t frame, slot_t slot) if (nr_timer_tick(&sched_ctrl->transm_interrupt)) { /* expired */ nr_timer_stop(&sched_ctrl->transm_interrupt); - if (UE->interrupt_action == FOLLOW_OUTOFSYNC) + if (UE->interrupt_action == FOLLOW_OUTOFSYNC) { nr_mac_trigger_ul_failure(sched_ctrl, UE->current_DL_BWP.scs); - /* else: default FOLLOW_INSYNC: nothing to do (UE is now active again) */ + } else { + DevAssert(UE->interrupt_action == FOLLOW_INSYNC); + nr_mac_reset_ul_failure(sched_ctrl); + } } } } diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index c6f9a2f6f9..ea07fbeea4 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -203,6 +203,8 @@ void nr_csirs_scheduling(int Mod_idP, frame_t frame, slot_t slot, nfapi_nr_dl_tt void nr_csi_meas_reporting(int Mod_idP, frame_t frameP, slot_t slotP); +void nr_measgap_scheduling(gNB_MAC_INST *nr_mac, frame_t frame, sub_frame_t slot); + int nr_acknack_scheduling(gNB_MAC_INST *mac, NR_UE_info_t *UE, frame_t frameP, From 6ce4d78c1908a0640dec9e72bd0a9720ecc8d616 Mon Sep 17 00:00:00 2001 From: rmagueta Date: Thu, 10 Jul 2025 09:58:07 +0200 Subject: [PATCH 220/964] Refactor get_MeasConfig(): create subfunctions --- openair2/RRC/NR/MESSAGES/asn1_msg.c | 78 +++++++++++++++++------------ 1 file changed, 47 insertions(+), 31 deletions(-) diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.c b/openair2/RRC/NR/MESSAGES/asn1_msg.c index 0f7ec6db1a..184b8d5888 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.c +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.c @@ -956,6 +956,42 @@ int do_RRCReestablishmentComplete(uint8_t *buffer, size_t buffer_size, int64_t r return((enc_rval.encoded+7)/8); } +static NR_MeasObjectToAddMod_t *get_MeasObject(const struct NR_MeasTiming__frequencyAndTiming *ft, + int band, + NR_ARFCN_ValueNR_t ssbFrequency, + NR_MeasObjectId_t measObjectId) +{ + const NR_SSB_MTC_t *ssb_mtc = &ft->ssb_MeasurementTimingConfiguration; + NR_MeasObjectToAddMod_t *mo = calloc_or_fail(1, sizeof(*mo)); + mo->measObjectId = measObjectId; + mo->measObject.present = NR_MeasObjectToAddMod__measObject_PR_measObjectNR; + NR_MeasObjectNR_t *monr = calloc_or_fail(1, sizeof(*monr)); + asn1cCallocOne(monr->ssbFrequency, ssbFrequency); + asn1cCallocOne(monr->ssbSubcarrierSpacing, ft->ssbSubcarrierSpacing); + monr->referenceSignalConfig.ssb_ConfigMobility = calloc_or_fail(1, sizeof(*monr->referenceSignalConfig.ssb_ConfigMobility)); + monr->referenceSignalConfig.ssb_ConfigMobility->deriveSSB_IndexFromCell = true; + monr->absThreshSS_BlocksConsolidation = calloc_or_fail(1, sizeof(*monr->absThreshSS_BlocksConsolidation)); + asn1cCallocOne(monr->absThreshSS_BlocksConsolidation->thresholdRSRP, 36); + asn1cCallocOne(monr->nrofSS_BlocksToAverage, 8); + monr->smtc1 = calloc_or_fail(1, sizeof(*monr->smtc1)); + monr->smtc1->periodicityAndOffset = ssb_mtc->periodicityAndOffset; + monr->smtc1->duration = ssb_mtc->duration; + monr->quantityConfigIndex = 1; + monr->ext1 = calloc_or_fail(1, sizeof(*monr->ext1)); + asn1cCallocOne(monr->ext1->freqBandIndicatorNR, band); + mo->measObject.choice.measObjectNR = monr; + return mo; +} + +static NR_MeasIdToAddMod_t *get_MeasId(NR_MeasId_t measId, NR_ReportConfigId_t reportConfigId, NR_MeasObjectId_t measObjectId) +{ + NR_MeasIdToAddMod_t *measid = calloc_or_fail(1, sizeof(NR_MeasIdToAddMod_t)); + measid->measId = measId; + measid->reportConfigId = reportConfigId; + measid->measObjectId = measObjectId; + return measid; +} + NR_MeasConfig_t *get_MeasConfig(const NR_MeasTiming_t *mt, int band, int scs, @@ -964,15 +1000,15 @@ NR_MeasConfig_t *get_MeasConfig(const NR_MeasTiming_t *mt, seq_arr_t *rc_A3_seq, seq_arr_t *pci_seq) { - NR_MeasConfig_t *mc = calloc(1, sizeof(*mc)); - mc->measObjectToAddModList = calloc(1, sizeof(*mc->measObjectToAddModList)); - mc->reportConfigToAddModList = calloc(1, sizeof(*mc->reportConfigToAddModList)); - mc->measIdToAddModList = calloc(1, sizeof(*mc->measIdToAddModList)); + NR_MeasConfig_t *mc = calloc_or_fail(1, sizeof(*mc)); + mc->measObjectToAddModList = calloc_or_fail(1, sizeof(*mc->measObjectToAddModList)); + mc->reportConfigToAddModList = calloc_or_fail(1, sizeof(*mc->reportConfigToAddModList)); + mc->measIdToAddModList = calloc_or_fail(1, sizeof(*mc->measIdToAddModList)); if (rc_PER) asn1cSeqAdd(&mc->reportConfigToAddModList->list, rc_PER); - if (rc_A2) + if (rc_A2) asn1cSeqAdd(&mc->reportConfigToAddModList->list, rc_A2); if (rc_A3_seq) { @@ -984,29 +1020,13 @@ NR_MeasConfig_t *get_MeasConfig(const NR_MeasTiming_t *mt, DevAssert(mt != NULL && mt->frequencyAndTiming != NULL); const struct NR_MeasTiming__frequencyAndTiming *ft = mt->frequencyAndTiming; - const NR_SSB_MTC_t *ssb_mtc = &ft->ssb_MeasurementTimingConfiguration; // Measurement Objects: Specifies what is to be measured. For NR and inter-RAT E-UTRA measurements, this may include // cell-specific offsets, blacklisted cells to be ignored and whitelisted cells to consider for measurements. - NR_MeasObjectToAddMod_t *mo1 = calloc(1, sizeof(*mo1)); - mo1->measObjectId = 1; - mo1->measObject.present = NR_MeasObjectToAddMod__measObject_PR_measObjectNR; - NR_MeasObjectNR_t *monr1 = calloc(1, sizeof(*monr1)); - asn1cCallocOne(monr1->ssbFrequency, ft->carrierFreq); - asn1cCallocOne(monr1->ssbSubcarrierSpacing, ft->ssbSubcarrierSpacing); - monr1->referenceSignalConfig.ssb_ConfigMobility = calloc(1, sizeof(*monr1->referenceSignalConfig.ssb_ConfigMobility)); - monr1->referenceSignalConfig.ssb_ConfigMobility->deriveSSB_IndexFromCell = true; - monr1->absThreshSS_BlocksConsolidation = calloc(1, sizeof(*monr1->absThreshSS_BlocksConsolidation)); - asn1cCallocOne(monr1->absThreshSS_BlocksConsolidation->thresholdRSRP, 36); - asn1cCallocOne(monr1->nrofSS_BlocksToAverage, 8); - monr1->smtc1 = calloc(1, sizeof(*monr1->smtc1)); - monr1->smtc1->periodicityAndOffset = ssb_mtc->periodicityAndOffset; - monr1->smtc1->duration = ssb_mtc->duration; - monr1->quantityConfigIndex = 1; - monr1->ext1 = calloc(1, sizeof(*monr1->ext1)); - asn1cCallocOne(monr1->ext1->freqBandIndicatorNR, band); + NR_MeasObjectToAddMod_t *mo1 = get_MeasObject(ft, band, ft->carrierFreq, 1); if (pci_seq) { + NR_MeasObjectNR_t *monr1 = mo1->measObject.choice.measObjectNR; for (int i = 0; i < pci_seq->size; i++) { if (monr1->cellsToAddModList == NULL) { monr1->cellsToAddModList = calloc(1, sizeof(*monr1->cellsToAddModList)); @@ -1019,22 +1039,18 @@ NR_MeasConfig_t *get_MeasConfig(const NR_MeasTiming_t *mt, } } - mo1->measObject.choice.measObjectNR = monr1; asn1cSeqAdd(&mc->measObjectToAddModList->list, mo1); // Preparation of measId for (uint8_t reportIdx = 0; reportIdx < mc->reportConfigToAddModList->list.count; reportIdx++) { const NR_ReportConfigId_t reportId = mc->reportConfigToAddModList->list.array[reportIdx]->reportConfigId; - NR_MeasIdToAddMod_t *measid = calloc(1, sizeof(NR_MeasIdToAddMod_t)); - measid->measId = reportIdx + 1; - measid->reportConfigId = reportId; - measid->measObjectId = 1; + NR_MeasIdToAddMod_t *measid = get_MeasId(reportIdx + 1, reportId, 1); asn1cSeqAdd(&mc->measIdToAddModList->list, measid); } - mc->quantityConfig = calloc(1, sizeof(*mc->quantityConfig)); - mc->quantityConfig->quantityConfigNR_List = calloc(1, sizeof(*mc->quantityConfig->quantityConfigNR_List)); - NR_QuantityConfigNR_t *qcnr = calloc(1, sizeof(*qcnr)); + mc->quantityConfig = calloc_or_fail(1, sizeof(*mc->quantityConfig)); + mc->quantityConfig->quantityConfigNR_List = calloc_or_fail(1, sizeof(*mc->quantityConfig->quantityConfigNR_List)); + NR_QuantityConfigNR_t *qcnr = calloc_or_fail(1, sizeof(*qcnr)); asn1cCallocOne(qcnr->quantityConfigCell.ssb_FilterConfig.filterCoefficientRSRP, NR_FilterCoefficient_fc6); asn1cCallocOne(qcnr->quantityConfigCell.csi_RS_FilterConfig.filterCoefficientRSRP, NR_FilterCoefficient_fc6); asn1cSeqAdd(&mc->quantityConfig->quantityConfigNR_List->list, qcnr); From 5e0307d8452761082a0ef93b5828e1535c688a05 Mon Sep 17 00:00:00 2001 From: rmagueta Date: Thu, 10 Jul 2025 10:12:34 +0200 Subject: [PATCH 221/964] Refactor code, add inter-freq neighbors, avoid mem leak Previously, we only supported intra-frequency handovers, so the measurements where only for intra-frequency, reusing the same measurement object. Now that we would support inter-frequency handover, also add multiple MeasObjects for each neighbor. --- openair2/RRC/NR/MESSAGES/asn1_msg.c | 40 +++++++++++++++++++---------- openair2/RRC/NR/MESSAGES/asn1_msg.h | 2 +- openair2/RRC/NR/rrc_gNB.c | 8 +----- 3 files changed, 29 insertions(+), 21 deletions(-) diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.c b/openair2/RRC/NR/MESSAGES/asn1_msg.c index 184b8d5888..b3397ad518 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.c +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.c @@ -998,7 +998,7 @@ NR_MeasConfig_t *get_MeasConfig(const NR_MeasTiming_t *mt, NR_ReportConfigToAddMod_t *rc_PER, NR_ReportConfigToAddMod_t *rc_A2, seq_arr_t *rc_A3_seq, - seq_arr_t *pci_seq) + seq_arr_t *neigh_seq) { NR_MeasConfig_t *mc = calloc_or_fail(1, sizeof(*mc)); mc->measObjectToAddModList = calloc_or_fail(1, sizeof(*mc->measObjectToAddModList)); @@ -1024,30 +1024,44 @@ NR_MeasConfig_t *get_MeasConfig(const NR_MeasTiming_t *mt, // Measurement Objects: Specifies what is to be measured. For NR and inter-RAT E-UTRA measurements, this may include // cell-specific offsets, blacklisted cells to be ignored and whitelisted cells to consider for measurements. NR_MeasObjectToAddMod_t *mo1 = get_MeasObject(ft, band, ft->carrierFreq, 1); - - if (pci_seq) { + if (neigh_seq) { NR_MeasObjectNR_t *monr1 = mo1->measObject.choice.measObjectNR; - for (int i = 0; i < pci_seq->size; i++) { - if (monr1->cellsToAddModList == NULL) { - monr1->cellsToAddModList = calloc(1, sizeof(*monr1->cellsToAddModList)); - } - - NR_CellsToAddMod_t *cell = calloc(1, sizeof(*cell)); - int *pci = (int *)seq_arr_at(pci_seq, i); - cell->physCellId = *pci; + if (monr1->cellsToAddModList == NULL) + monr1->cellsToAddModList = calloc_or_fail(1, sizeof(*monr1->cellsToAddModList)); + FOR_EACH_SEQ_ARR(nr_neighbour_cell_t *, n, neigh_seq) { + NR_CellsToAddMod_t *cell = calloc_or_fail(1, sizeof(*cell)); + cell->physCellId = n->physicalCellId; ASN_SEQUENCE_ADD(&monr1->cellsToAddModList->list, cell); } } - asn1cSeqAdd(&mc->measObjectToAddModList->list, mo1); // Preparation of measId - for (uint8_t reportIdx = 0; reportIdx < mc->reportConfigToAddModList->list.count; reportIdx++) { + uint8_t reportIdx = 0; + for (; reportIdx < mc->reportConfigToAddModList->list.count; reportIdx++) { const NR_ReportConfigId_t reportId = mc->reportConfigToAddModList->list.array[reportIdx]->reportConfigId; NR_MeasIdToAddMod_t *measid = get_MeasId(reportIdx + 1, reportId, 1); asn1cSeqAdd(&mc->measIdToAddModList->list, measid); } + // Preparation of measId for neighbour cells for periodic report + if (neigh_seq) { + int mo_id = 2; + FOR_EACH_SEQ_ARR(nr_neighbour_cell_t *, neigh_cell, neigh_seq) { + NR_MeasObjectToAddMod_t *mo_neighbour = get_MeasObject(ft, band, neigh_cell->absoluteFrequencySSB, mo_id); + NR_MeasObjectNR_t *monr = mo_neighbour->measObject.choice.measObjectNR; + monr->cellsToAddModList = calloc_or_fail(1, sizeof(*monr->cellsToAddModList)); + NR_CellsToAddMod_t *cell = calloc_or_fail(1, sizeof(*cell)); + cell->physCellId = neigh_cell->physicalCellId; + ASN_SEQUENCE_ADD(&monr->cellsToAddModList->list, cell); + asn1cSeqAdd(&mc->measObjectToAddModList->list, mo_neighbour); + NR_MeasIdToAddMod_t *measid = get_MeasId(reportIdx + 1, rc_PER->reportConfigId, mo_id); + asn1cSeqAdd(&mc->measIdToAddModList->list, measid); + reportIdx++; + mo_id++; + } + } + mc->quantityConfig = calloc_or_fail(1, sizeof(*mc->quantityConfig)); mc->quantityConfig->quantityConfigNR_List = calloc_or_fail(1, sizeof(*mc->quantityConfig->quantityConfigNR_List)); NR_QuantityConfigNR_t *qcnr = calloc_or_fail(1, sizeof(*qcnr)); diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.h b/openair2/RRC/NR/MESSAGES/asn1_msg.h index 3ac4695eba..8918384090 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.h +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.h @@ -151,7 +151,7 @@ NR_MeasConfig_t *get_MeasConfig(const NR_MeasTiming_t *mt, NR_ReportConfigToAddMod_t *rc_PER, NR_ReportConfigToAddMod_t *rc_A2, seq_arr_t *rc_A3_seq, - seq_arr_t *pci_seq); + seq_arr_t *neigh_seq); void free_MeasConfig(NR_MeasConfig_t *mc); int do_NR_Paging(uint8_t Mod_id, uint8_t *buffer, uint32_t tmsi); diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index a6ba6f8cda..eeb18e8698 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -568,7 +568,6 @@ nr_rrc_reconfig_param_t get_RRCReconfiguration_params(gNB_RRC_INST *rrc, gNB_RRC NR_ReportConfigToAddMod_t *rc_PER = NULL; NR_ReportConfigToAddMod_t *rc_A2 = NULL; seq_arr_t *rc_A3_seq = NULL; - seq_arr_t *pci_seq = NULL; if (du->mtc != NULL) { int scs = get_ssb_scs(cell_info); int band = get_dl_band(cell_info); @@ -587,16 +586,11 @@ nr_rrc_reconfig_param_t get_RRCReconfiguration_params(gNB_RRC_INST *rrc, gNB_RRC If default one added once as a report, no need to add it again && duplication. */ rc_A3_seq = malloc(sizeof(seq_arr_t)); - pci_seq = malloc(sizeof(seq_arr_t)); seq_arr_init(rc_A3_seq, sizeof(NR_ReportConfigToAddMod_t)); - seq_arr_init(pci_seq, sizeof(int)); LOG_D(NR_RRC, "HO LOG: Preparing A3 Event Measurement Configuration!\n"); bool is_default_a3_added = false; for (int i = 0; i < neighbour_cells->size; i++) { nr_neighbour_cell_t *neighbourCell = (nr_neighbour_cell_t *)seq_arr_at(neighbour_cells, i); - if (!neighbourCell->isIntraFrequencyNeighbour) - continue; - seq_arr_push_back(pci_seq, &neighbourCell->physicalCellId, sizeof(int)); const nr_a3_event_t *a3Event = get_a3_configuration(rrc, neighbourCell->physicalCellId); if (!a3Event || is_default_a3_added) continue; @@ -610,7 +604,7 @@ nr_rrc_reconfig_param_t get_RRCReconfiguration_params(gNB_RRC_INST *rrc, gNB_RRC if (rrc->measurementConfiguration.a2_event) rc_A2 = prepare_a2_event_report(rrc->measurementConfiguration.a2_event); - measconfig = get_MeasConfig(mt, band, scs, rc_PER, rc_A2, rc_A3_seq, pci_seq); + measconfig = get_MeasConfig(mt, band, scs, rc_PER, rc_A2, rc_A3_seq, neighbour_cells); } if (UE->measConfig) From dddf34ac9b969b1b1c30f965f7effff16ed8e682 Mon Sep 17 00:00:00 2001 From: alexjiao Date: Wed, 2 Jul 2025 15:17:57 +0800 Subject: [PATCH 222/964] Fix PDSCH overlap with ZP CSI-RS case When PDSCH overlap with ZP CSI-RS, nb_re_pdsch needs to be reduced by number of CSI-RS RE. --- .../NR_UE_TRANSPORT/nr_dlsch_demodulation.c | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c index b1e33054ba..37c8382ec5 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c @@ -488,6 +488,30 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, nb_re_pdsch = (pilots == 1) ? ((config_type == NFAPI_NR_DMRS_TYPE1) ? nb_rb_pdsch * (12 - 6 * dlsch_config->n_dmrs_cdm_groups) : nb_rb_pdsch * (12 - 4 * dlsch_config->n_dmrs_cdm_groups)) : (nb_rb_pdsch * 12); + // Subtract CSI-RS REs from PDSCH RE count + if (csi_res_bitmap != 0) { + uint32_t csi_re_count = 0; + uint32_t csi_res_even = csi_res_bitmap & 0xfff; + uint32_t csi_res_odd = (csi_res_bitmap >> 16) & 0xfff; + + for (int rb = 0; rb < nb_rb_pdsch; rb++) { + uint32_t rb_csi_pattern = (rb % 2 == 0) ? csi_res_even : csi_res_odd; + csi_re_count += __builtin_popcount(rb_csi_pattern); + } + + nb_re_pdsch = (nb_re_pdsch > csi_re_count) ? (nb_re_pdsch - csi_re_count) : 0; + + if (csi_re_count > 0) { + LOG_D(NR_PHY, + "[CSI OVERLAP] Frame/Slot %d.%d Symbol %d: CSI-RS overlapping PDSCH - %d CSI-RS REs skipped, %d data REs extracted\n", + frame, + nr_slot_rx, + symbol, + csi_re_count, + nb_re_pdsch); + } + } + if (scope_req->copy_rxdataF_to_scope) { size_t size = sizeof(c16_t) * nb_re_pdsch; int copy_index = symbol - dlsch_config->start_symbol; From 74a34daf5b37403a84550add3f2d206d996d8f91 Mon Sep 17 00:00:00 2001 From: Rajesh Guttula Date: Mon, 7 Jul 2025 18:49:23 +0530 Subject: [PATCH 223/964] Extnded changes to "Initial support for RedCap" feature in gNB The changes done in this commit are to contribute the supporting changes for the existing "Initial support for RedCap" feature in gNB. In this patch, handle and store the RedCap related IE's present in "NR UE Capability Information" msg which are - 'supportOfRedCap-r17' - 'supportOf16DRB-RedCap-r17' - 'longSN-RedCap-r17' - 'am-WithLongSN-RedCap-r17' use 'longSN-RedCap-r17' and 'am-WithLongSN-RedCap-r17' IEs to set the SN length to either 12 Bit or 18 Bit accordingly. --- .../LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c | 9 +++- openair2/RRC/NR/nr_rrc_defs.h | 8 ++++ openair2/RRC/NR/rrc_gNB.c | 42 +++++++++++++++++++ openair2/RRC/NR/rrc_gNB_radio_bearers.c | 15 +++++-- 4 files changed, 69 insertions(+), 5 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c index 30d3999f75..4af16aa199 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -324,6 +324,12 @@ static int handle_ue_context_drbs_setup(NR_UE_info_t *UE, AssertFatal(drb->qos_choice == F1AP_QOS_CHOICE_NR, "only NR QoS supported\n"); f1ap_drb_setup_t *resp_drb = &(*resp_drbs)[i]; NR_RLC_BearerConfig_t *rlc_BearerConfig = get_bearerconfig_from_drb(drb, rlc_config); + if (UE->capability && UE->capability->rlc_Parameters && UE->capability->rlc_Parameters->ext2 + && UE->capability->rlc_Parameters->ext2->am_WithLongSN_RedCap_r17 == NULL) { + *rlc_BearerConfig->rlc_Config->choice.am->dl_AM_RLC.sn_FieldLength = NR_SN_FieldLengthAM_size12; + *rlc_BearerConfig->rlc_Config->choice.am->ul_AM_RLC.sn_FieldLength = NR_SN_FieldLengthAM_size12; + } + nr_rlc_add_drb(UE->rnti, drb->id, rlc_BearerConfig); nr_lc_config_t c = {.lcid = rlc_BearerConfig->logicalChannelIdentity, .nssai = drb->nr.nssai}; @@ -649,6 +655,8 @@ void ue_context_setup_request(const f1ap_ue_context_setup_req_t *req) resp.gNB_DU_ue_id = UE->rnti; NR_CellGroupConfig_t *new_CellGroup = clone_CellGroupConfig(UE->CellGroup); + // Needed for DRB Setup (e.g., RLC might reduce SN size) + UE->capability = ue_cap; if (req->srbs_len > 0) { resp.srbs_len = handle_ue_context_srbs_setup(UE, req->srbs_len, req->srbs, &resp.srbs, new_CellGroup, &mac->rlc_config); @@ -665,7 +673,6 @@ void ue_context_setup_request(const f1ap_ue_context_setup_req_t *req) } NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon; - UE->capability = ue_cap; if (ue_cap != NULL && cg_configinfo == NULL) { // store the new UE capabilities, and update the cellGroupConfig // only to be done if we did not already update through the cg_configinfo diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index 804657e8ce..68a83c9545 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -169,6 +169,13 @@ typedef enum { RRC_UECAPABILITY_ENQUIRY, } rrc_action_t; +typedef struct nr_redcap_ue_cap { + bool support_of_redcap_r17; + bool support_of_16drb_redcap_r17; + bool pdcp_drb_long_sn_redcap_r17; + bool rlc_am_drb_long_sn_redcap_r17; +} nr_redcap_ue_cap_t; + /* forward declaration */ typedef struct nr_handover_context_s nr_handover_context_t; @@ -253,6 +260,7 @@ typedef struct gNB_RRC_UE_s { int max_delays_pdu_session; bool ongoing_pdusession_setup_request; + nr_redcap_ue_cap_t *redcap_cap; } gNB_RRC_UE_t; typedef struct rrc_gNB_ue_context_s { diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index a6ba6f8cda..ae4d55cae7 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -117,6 +117,34 @@ typedef struct deliver_ue_ctxt_release_data_t { sctp_assoc_t assoc_id; } deliver_ue_ctxt_release_data_t; +const NR_RedCapParameters_r17_t *get_redcapparam_r17(NR_UE_NR_Capability_t *UE_Capability_nr) +{ + if (UE_Capability_nr && UE_Capability_nr->nonCriticalExtension && UE_Capability_nr->nonCriticalExtension->nonCriticalExtension + && UE_Capability_nr->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension + && UE_Capability_nr->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension + && UE_Capability_nr->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension + ->nonCriticalExtension + && UE_Capability_nr->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension + ->nonCriticalExtension->nonCriticalExtension + && UE_Capability_nr->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension + ->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension + && UE_Capability_nr->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension + ->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension + && UE_Capability_nr->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension + ->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension + && UE_Capability_nr->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension + ->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension + ->nonCriticalExtension + && UE_Capability_nr->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension + ->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension + ->nonCriticalExtension->redCapParameters_r17) { + return UE_Capability_nr->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension + ->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension + ->nonCriticalExtension->redCapParameters_r17; + } else + return NULL; +} + static void rrc_deliver_ue_ctxt_release_cmd(void *deliver_pdu_data, ue_id_t ue_id, int srb_id, char *buf, int size, int sdu_id) { DevAssert(deliver_pdu_data != NULL); @@ -1590,6 +1618,18 @@ static void handle_ueCapabilityInformation(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, UE->UE_Capability_nr = 0; } + const NR_RedCapParameters_r17_t *redcap_p = get_redcapparam_r17(UE->UE_Capability_nr); + if (redcap_p) { + UE->redcap_cap = calloc_or_fail(1, sizeof(*UE->redcap_cap)); + UE->redcap_cap->support_of_redcap_r17 = redcap_p->supportOfRedCap_r17 != NULL; + UE->redcap_cap->support_of_16drb_redcap_r17 = redcap_p->supportOf16DRB_RedCap_r17 != NULL; + if (UE->UE_Capability_nr->pdcp_Parameters.ext2) + UE->redcap_cap->pdcp_drb_long_sn_redcap_r17 = UE->UE_Capability_nr->pdcp_Parameters.ext2->longSN_RedCap_r17 != NULL; + if (UE->UE_Capability_nr->rlc_Parameters && UE->UE_Capability_nr->rlc_Parameters->ext2) + UE->redcap_cap->rlc_am_drb_long_sn_redcap_r17 = + UE->UE_Capability_nr->rlc_Parameters->ext2->am_WithLongSN_RedCap_r17 != NULL; + } + UE->UE_Capability_size = ue_cap_container->ue_CapabilityRAT_Container.size; if (eutra_index != -1) { LOG_E(NR_RRC, "fatal: more than 1 eutra capability\n"); @@ -2200,6 +2240,8 @@ static void rrc_delete_ue_data(gNB_RRC_UE_t *UE) ASN_STRUCT_FREE(asn_DEF_NR_MeasResults, UE->measResults); FREE_AND_ZERO_BYTE_ARRAY(UE->ue_cap_buffer); free_MeasConfig(UE->measConfig); + free(UE->redcap_cap); + UE->redcap_cap = NULL; } void rrc_remove_ue(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p) diff --git a/openair2/RRC/NR/rrc_gNB_radio_bearers.c b/openair2/RRC/NR/rrc_gNB_radio_bearers.c index 5112029f87..d91c866cd4 100644 --- a/openair2/RRC/NR/rrc_gNB_radio_bearers.c +++ b/openair2/RRC/NR/rrc_gNB_radio_bearers.c @@ -85,12 +85,19 @@ drb_t *get_drb(gNB_RRC_UE_t *ue, uint8_t drb_id) void set_default_drb_pdcp_config(struct pdcp_config_s *pdcp_config, int do_drb_integrity, int do_drb_ciphering, - const nr_pdcp_configuration_t *default_pdcp_config) + const nr_pdcp_configuration_t *default_pdcp_config, + const nr_redcap_ue_cap_t *redcap_cap) { AssertError(pdcp_config != NULL, return, "Failed to set default PDCP configuration for DRB!\n"); pdcp_config->discardTimer = encode_discard_timer(default_pdcp_config->drb.discard_timer); - pdcp_config->pdcp_SN_SizeDL = encode_sn_size_dl(default_pdcp_config->drb.sn_size); - pdcp_config->pdcp_SN_SizeUL = encode_sn_size_ul(default_pdcp_config->drb.sn_size); + if (redcap_cap && redcap_cap->support_of_redcap_r17 && !redcap_cap->pdcp_drb_long_sn_redcap_r17) { + LOG_I(NR_RRC, "UE is RedCap without long PDCP SN support: overriding PDCP SN size to 12\n"); + pdcp_config->pdcp_SN_SizeDL = NR_PDCP_Config__drb__pdcp_SN_SizeDL_len12bits; + pdcp_config->pdcp_SN_SizeUL = NR_PDCP_Config__drb__pdcp_SN_SizeUL_len12bits; + } else { + pdcp_config->pdcp_SN_SizeDL = encode_sn_size_dl(default_pdcp_config->drb.sn_size); + pdcp_config->pdcp_SN_SizeUL = encode_sn_size_ul(default_pdcp_config->drb.sn_size); + } pdcp_config->t_Reordering = encode_t_reordering(default_pdcp_config->drb.t_reordering); pdcp_config->headerCompression.present = NR_PDCP_Config__drb__headerCompression_PR_notUsed; pdcp_config->headerCompression.NotUsed = 0; @@ -145,7 +152,7 @@ drb_t *generateDRB(gNB_RRC_UE_t *ue, est_drb->status = DRB_ACTIVE; } /* PDCP Configuration */ - set_default_drb_pdcp_config(&est_drb->pdcp_config, do_drb_integrity, do_drb_ciphering, pdcp_config); + set_default_drb_pdcp_config(&est_drb->pdcp_config, do_drb_integrity, do_drb_ciphering, pdcp_config, ue->redcap_cap); drb_t *rrc_drb = get_drb(ue, drb_id); DevAssert(rrc_drb == est_drb); /* to double check that we create the same which we would retrieve */ From 8d7f2a8fbdbe58b9bfa6fa3a5a5f42ca4e4de24f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Soares=20Silva?= Date: Thu, 27 Mar 2025 17:10:26 +0000 Subject: [PATCH 224/964] Add documentation for different VNF/PNF transport Add a section in nfapi.md related to the different transport mechanisms available for VNF/PNF communication Edit NR_NFAPI_archi.md to describe the VNF and PNF processing logic, as well as adding a flowchart for each of the components execution Add the necessary patch to install the WLS library in the system --- cmake_targets/tools/install_wls_lib.patch | 209 ++++++++++++++++ doc/NR_NFAPI_archi.md | 284 +++++++++++++++++----- doc/README.md | 2 +- doc/nfapi.md | 124 +++++++++- 4 files changed, 553 insertions(+), 66 deletions(-) create mode 100644 cmake_targets/tools/install_wls_lib.patch diff --git a/cmake_targets/tools/install_wls_lib.patch b/cmake_targets/tools/install_wls_lib.patch new file mode 100644 index 0000000000..5050b79a4e --- /dev/null +++ b/cmake_targets/tools/install_wls_lib.patch @@ -0,0 +1,209 @@ +diff --git a/wls_lib/Makefile b/wls_lib/Makefile +index 2f8e4b2..e657488 100644 +--- a/wls_lib/Makefile ++++ b/wls_lib/Makefile +@@ -1,20 +1,6 @@ +-############################################################################### +-# +-# Copyright (c) 2021 Intel. +-# +-# Licensed under the Apache License, Version 2.0 (the "License"); +-# you may not use this file except in compliance with the License. +-# You may obtain a copy of the License at +-# +-# http://www.apache.org/licenses/LICENSE-2.0 +-# +-# Unless required by applicable law or agreed to in writing, software +-# distributed under the License is distributed on an "AS IS" BASIS, +-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-# See the License for the specific language governing permissions and +-# limitations under the License. +-# +-############################################################################### ++################################################################ ++# ++################################################################ + + MYCUSTOMTAB=' ' + MYCUSTOMSPACE='============================================================================================' +@@ -24,11 +10,17 @@ MYCUSTOMSPACE1='------------------------------------------------------------' + # Tools configuration + ############################################################## + ifeq ($(WIRELESS_SDK_TOOLCHAIN),icc) +-CC := icc ++ CC := icc + CPP := icpc +-AS := as +-AR := ar +-LD := icc ++ AS := as ++ AR := ar ++ LD := icc ++else ifeq ($(WIRELESS_SDK_TOOLCHAIN),gcc) ++ CC := gcc ++ CPP := g++ ++ AS := as ++ AR := ar ++ LD := gcc + else ifeq ($(WIRELESS_SDK_TOOLCHAIN),icx) + CC := icx + CPP := icx +@@ -44,9 +36,9 @@ ifeq ($(WIRELESS_SDK_TARGET_ISA),sse) + else ifeq ($(WIRELESS_SDK_TARGET_ISA),avx2) + TARGET_PROCESSOR := -xCORE-AVX2 + else ifeq ($(WIRELESS_SDK_TARGET_ISA),avx512) +- TARGET_PROCESSOR := -xCORE-AVX512 ++ TARGET_PROCESSOR := -march=skylake-avx512 + else ifeq ($(WIRELESS_SDK_TARGET_ISA),snc) +- TARGET_PROCESSOR := -xicelake-server ++ TARGET_PROCESSOR := -march=icelake-server + else ifeq ($(WIRELESS_SDK_TARGET_ISA),spr) + TARGET_PROCESSOR := -march=sapphirerapids + endif +@@ -66,15 +58,38 @@ PROJECT_DIR := ./ + BUILDDIR := make + PROJECT_BINARY := $(PROJECT_NAME).so + ++PKGCONF ?= pkg-config ++LIBDPDK_VERSION=20.11.3 ++ ++ifeq ($(shell $(PKGCONF) --modversion "libdpdk = '$(LIBDPDK_VERSION)'"),$(LIBDPDK_VERSION)) ++ DPDK_INSTALLED=1 ++else ++ DPDK_INSTALLED=0 ++endif ++ + ifeq ($(RTE_SDK),) +-$(error "Please define RTE_SDK environment variable") ++ifeq ($(DPDK_INSTALLED),0) ++$(error "Please define RTE_SDK environment variable OR install DPDK version $(LIBDPDK_VERSION)") ++endif + endif + +-RTE_INC := $(shell PKG_CONFIG_PATH=/usr/lib64/pkgconfig:$(RTE_SDK)/build/meson-uninstalled pkgconf --cflags-only-I libdpdk) ++# At least one of the options is defined ++ ++ifneq ($(RTE_SDK),) ++ RTE_INC := $(shell PKG_CONFIG_PATH=/usr/lib64/pkgconfig:$(RTE_SDK)/build/meson-uninstalled pkgconf --cflags-only-I libdpdk) ++else ifeq ($(DPDK_INSTALLED),1) ++ RTE_INC := $(shell PKG_CONFIG_PATH=/usr/lib64/pkgconfig $(PKGCONF) --cflags-only-I libdpdk) ++endif + + CC_SRC = wls_lib_dpdk.c \ + syslib.c + ++CC_HDR = syslib.h \ ++ ttypes.h \ ++ wls.h \ ++ wls_debug.h \ ++ wls_lib.h ++ + CC_FLAGS += -std=gnu11 -Wall -Wno-deprecated-declarations \ + -fdata-sections \ + -ffunction-sections \ +@@ -84,18 +99,19 @@ CC_FLAGS += -std=gnu11 -Wall -Wno-deprecated-declarations \ + -Wimplicit-function-declaration \ + -g -O3 -mcmodel=large $(TARGET_PROCESSOR) + +-INC := -I$(RTE_INC) ++INC := -I$(RTE_INC) -I../intel_fapi/ + DEF := + + AS_FLAGS := + AR_FLAGS := rc + + PROJECT_OBJ_DIR := $(BUILDDIR)/obj ++PROJECT_DEP_DIR := $(PROJECT_OBJ_DIR)/$(PROJECT_NAME).dep.d + + CC_OBJS := $(patsubst %.c,%.o,$(CC_SRC)) + AS_OBJS := $(patsubst %.s,%.o,$(AS_SRC)) + OBJS := $(CC_OBJS) $(AS_OBJS) $(LIBS) +-DIRLIST := $(addprefix $(PROJECT_OBJ_DIR)/,$(sort $(dir $(OBJS)))) ++DIRLIST := $(addprefix $(PROJECT_OBJ_DIR)/,$(sort $(dir $(OBJS)))) $(PROJECT_DEP_DIR) + + CC_OBJTARGETS := $(addprefix $(PROJECT_OBJ_DIR)/,$(CC_OBJS)) + +@@ -104,9 +120,7 @@ CC_FLAGS_FULL := $(CC_FLAGS) $(INC) $(DEF) + + AS_FLAGS := $(AS_FLAGS) $(INC) + +-PROJECT_DEP_FILE := $(PROJECT_OBJ_DIR)/$(PROJECT_NAME).dep +- +-ifeq ($(wildcard $(PROJECT_DEP_FILE)),$(PROJECT_DEP_FILE)) ++ifeq ($(wildcard $(PROJECT_DEP_DIR)),$(PROJECT_DEP_DIR)) + GENERATE_DEPS := + else + +@@ -119,11 +133,11 @@ all : welcome_line $(PROJECT_BINARY) + + .PHONY : clear_dep + clear_dep: +- @$(RM) $(PROJECT_DEP_FILE) +- @echo [DEP] $(subst $(PROJECT_OBJ_DIR)/,,$(PROJECT_DEP_FILE)) ++ @echo [DEP] rm $(PROJECT_DEP_DIR)/$(@F).dep ++ @$(RM) $(PROJECT_DEP_DIR)/$(@F).dep + +-$(CC_DEPS) : +- @$(CC) -MM $(subst __up__,../,$(subst __dep__,,$@)) -MT $(PROJECT_OBJ_DIR)/$(patsubst %.c,%.o,$(subst __up__,../,$(subst __dep__,,$@))) $(CC_FLAGS_FULL) >> $(PROJECT_DEP_FILE) ++$(CC_DEPS) : $(PROJECT_DEP_DIR) ++ @$(CC) $(CC_FLAGS_FULL) -MM $(subst __up__,../,$(subst __dep__,,$@)) -MT $(PROJECT_OBJ_DIR)/$(patsubst %.c,%.o,$(subst __up__,../,$(subst __dep__,,$@))) >> $(PROJECT_DEP_DIR)/$(@F).dep + + .PHONY : generate_deps + generate_deps : clear_dep $(CC_DEPS) +@@ -136,17 +150,17 @@ echo_start_build : + $(DIRLIST) : + -@$(MD) $@ + +-$(CC_OBJTARGETS) : ++$(CC_OBJTARGETS) : $(GENERATE_DEPS) + @echo [CC] $(subst $(PROJECT_OBJ_DIR)/,,$@) + @$(CC) -c $(CC_FLAGS_FULL) -o"$@" $(patsubst %.o,%.c,$(subst $(PROJECT_OBJ_DIR)/,,$@)) + +-$(AS_OBJTARGETS) : ++$(AS_OBJTARGETS) : $(CC_OBJTARGETS) $(CPP_OBJTARGETS) + @echo [AS] $(subst $(PROJECT_OBJ_DIR)/,,$@) + @$(AS) $(AS_FLAGS) -o"$@" $(patsubst %.o,%.s,$(subst $(PROJECT_OBJ_DIR)/,,$@)) + +-ifeq ($(wildcard $(PROJECT_DEP_FILE)),$(PROJECT_DEP_FILE)) ++ifeq ($(wildcard $(PROJECT_DEP_DIR)),$(PROJECT_DEP_DIR)) + +-include $(PROJECT_DEP_FILE) ++include $(PROJECT_DEP_DIR)/* + + endif + +@@ -156,7 +170,7 @@ clean: + @$(RM) $(CC_OBJTARGETS) $(AS_OBJTARGETS) + ifneq ($(wildcard $(PROJECT_DIR)/$(PROJECT_MAKE)),) + @echo [CLEAN] : $(PROJECT_NAME) +- @$(RM) $(PROJECT_BINARY) $(PROJECT_BINARY_LIB) $(PROJECT_DEP_FILE) ++ @$(RM) -rf $(PROJECT_BINARY) $(PROJECT_BINARY_LIB) $(PROJECT_DEP_DIR) + endif + + xclean: clean +@@ -172,7 +186,24 @@ welcome_line : + debug : all + release : all + +-$(PROJECT_BINARY) : $(DIRLIST) echo_start_build $(GENERATE_DEPS) $(PRE_BUILD) $(CC_OBJTARGETS) $(AS_OBJTARGETS) ++$(PROJECT_BINARY) : $(DIRLIST) echo_start_build $(GENERATE_DEPS) $(CC_OBJTARGETS) $(AS_OBJTARGETS) + @echo [AR] $(subst $(BUILDDIR)/,,$@) + @$(CC) $(CC_OBJTARGETS) $(AS_OBJTARGETS) -shared -fPIC -o $@ + ++############################################################## ++# Install configuration ++############################################################## ++ ++INSTALL_DIR := /usr/local ++INCLUDE_DIR := $(INSTALL_DIR)/include/ ++ ++.PHONY : install ++install: $(PROJECT_BINARY) install_headers ++ @echo [INSTALL] : $(PROJECT_BINARY) ++ @$(CP) $(PROJECT_BINARY) $(INSTALL_DIR)/lib ++ ++.PHONY : install_headers ++install_headers: $(CC_SRC) ++ @echo [INSTALL] : $(PROJECT_NAME) headers ++ @$(MD) $(INCLUDE_DIR) ++ @$(CP) $(CC_HDR) $(INCLUDE_DIR) diff --git a/doc/NR_NFAPI_archi.md b/doc/NR_NFAPI_archi.md index 59c511fb52..8065ddb4fc 100644 --- a/doc/NR_NFAPI_archi.md +++ b/doc/NR_NFAPI_archi.md @@ -1,53 +1,90 @@ -# global +This document describes the broad way in which the VNF and PNF work internally, +from configuration, to P5 and P7 message exchange and processing. +Their internal processing is broadly independent on which transport mechanism +is responsible for exchanging data between the 2 components. -xnf is pnf or vnf +To read more about the transport mechanisms available, and how to run the split, please refer to +[this file](./nfapi.md). -The xnf starting functions are configure_nfapi_xnf() +[[_TOC_]] -The OAI code that read the configuration parameters call these functions that will create autonomous thread for xnf control part +# VNF/PNF Split -These control threads create a SCTP socket by Linux API call (no use of OpenAir internal architecture with SCTP itti thread). +The gNB is split into VNF(L2+) and PNF(L1) -The main() function of softmodem has to create and start the other threads+loop on event for appropriate work: RF Rx in pnf, NGAP, GTP-U, X2, RLC, PDCP for vnf +These component are configured via the functions: -NFAPI has it's own code directly on Linux+Posix, it doesn't reuse any piece of the OpenAir framework: SCTP thread, thread creation and management, ... +- configure_nr_nfapi_vnf() +- configure_nr_nfapi_pnf() -## signaling (P5) xnf main loop +These functions initialize the configuration appropriate for the transport mechanism selected ( setting the +pack/unpack function pointers, as well as the appropriate send functions ) -nfapi_vnf_start() create the SCTP socket, then do event waiting in a infinite loop while(vnf->terminate == 0). It accepts the pnf connections, then process the messages on reception +After this, a thread is created for the P5 receive loop, which initializes the transport and receive loop -nfapi_pnf_start() initiate connection to vnf until it has a link. Then it enter a similar infinite loop in pnf_message_pump() +This created thread may be only for P5 messages, or P5 and P7, depending on the transport type -After some checks, when a message is obtained, it calls pnf_handle_p5_message() or vnf_handle_p4_p5_message() that have a switch on each p5 message types: the enum nfapi_message_id_e +- When using socket-based communication (which uses nFAPI encoding), the receiving loop for P7 messages is separate from + P5, it starts upon the PNF_START exchange +- In the other transport mechanisms (WLS and nvIPC, which use FAPI encoding), the receiving loop is the same for P5 and + P7 messages, the P7 configuration is done immediately after the P5 configuration. + +Since the first P7 messages is only sent/received after the START exchange, we can logically treat the loops as separate +, we won't receive P7 messages before finishing the P5 ones ( except for the STOP exchange ) + +## P5 interface main loop + +After the P5 configuration, both the VNF and PNF have a thread waiting to "consume" (n)FAPI messages exchanged between +them + +Upon the reception of a message (whether in its entirety or segmented in the case of nFAPI), the messages are sent to +the appropriate handler: + +- pnf_nr_handle_p5_message +- vnf_nr_handle_p4_p5_message + +In each of these functions, there's a switch calling the appropriate handler according to the message ID, for example: -Each message type has it's own processing function in the switch, like ``` -case NFAPI_START_RESPONSE: - vnf_handle_start_response(pRecvMsg, recvMsgLen, config, p5_idx); - break; +case NFAPI_NR_PHY_MSG_TYPE_START_RESPONSE: + vnf_nr_handle_start_response(pRecvMsg, recvMsgLen, config, p5_idx); + break; ``` These loops are autonomous in their thread waiting incoming message. -## P7 xnf main loop +## P7 interface main loop -When the p5 interface receives appropriate message, it starts the p7 interface by launching a thread (see the calls to pthread_create() in nfapi/oai_integration/nfapi_xnf.c) +- Note: As explained before, the P7 reception loop is the same as the P5 messages when not using socket-based + communication -The p7 main loops starting is a bit simpler, thanks to UDP non connected protocol. The xnf_dispatch_p7_message() do p7 fragments re-assembly, then -calls xnf_dispatch_p7_message() that have the big switch on message type (as in p5 above description) +In this case, when the P5 interface receives appropriate message, it starts the p7 interface by launching a thread -So, we have the logic for UL reception in vnf, and DL reception in pnf +- On the PNF, this is done in the START.request handler ( nr_start_request(...) ) +- On the VNF, this is done in ( configure_nr_p7_vnf(...) ) + +Much in the same way as when processing P5 messages, the following functions are called to unpack and process them: + +- pnf_nr_handle_p7_message +- vnf_nr_handle_p7_message + +``` +case NFAPI_NR_PHY_MSG_TYPE_SLOT_INDICATION: + vnf_handle_nr_slot_indication(pRecvMsg, recvMsgLen, vnf_p7); + break; +``` ## P7 UL transmission by PNF -RF samples are received, and decoding is done by the PNF using control data transmitted by the VNF to the PNF through downlink p7 messages (UL_TTI_req and UL_DCI_req). +RF samples are received, and decoding is done by the PNF using control data transmitted by the VNF to the PNF through +downlink p7 messages (UL_TTI.request and UL_DCI.request). -After decoding, results are accumulated into the xNB->UL_INFO structure at the PNF. +After decoding, results are accumulated into the gNB->UL_INFO structure at the PNF. -The data in the UL_INFO struct is transmitted through a socket in the form of 'uplink indication functions' from the PNF to the VNF. Each uplink indication message is transmitted from their respective handle functions in NR_UL_indication(). For example, +The data in the UL_INFO struct is transmitted through the configured send function pointer (send_p7_msg), which packs +the message into a buffer according to the encoding and sends it to the VNF ``` - void handle_nr_rach(NR_UL_IND_t *UL_info) { if(NFAPI_MODE == NFAPI_MODE_PNF) { if (UL_info->rach_ind.number_of_pdus>0) { @@ -56,67 +93,186 @@ void handle_nr_rach(NR_UL_IND_t *UL_info) { } } -``` +.... -## P7 UL reception at VNF +int oai_nfapi_nr_rach_indication(nfapi_nr_rach_indication_t *ind) { + ind->header.phy_id = 1; // HACK TODO FIXME - need to pass this around!!!! + ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION; + return nfapi_pnf_p7_nr_rach_ind(p7_config_g, ind); +} -Through the infinite loop [while(vnf_p7->terminate == 0)] running in nfapi_nr_vnf_p7_start(), the VNF receives and unpacks the uplink indication message received on its socket. Based on the unpacked messages, UL_INFO struct on the VNF side gets populated. +..... -``` - -// have a p7 message - if(FD_ISSET(vnf_p7->socket, &rfds)) - { - vnf_nr_p7_read_dispatch_message(vnf_p7); - } - -``` - -vnf_nr_dispatch_p7_message() is the function that contains the switch on various message headers so that the appropriate unpack function is called. - -## P7 DL Transmission by VNF - -DL messages are scheduled at the VNF, through NR_UL_indication(). NR_UL_indication() is called when the SFN/slot in the UL_info structure changes (this acts as a trigger for next slot processing, instead of running a separate clock at the VNF). The SFN/slot at the VNF in UL_info is updated using the slot_indication uplink p7 message, which is sent at the beginning of every slot by the PNF. The slot_indication message contains SFN/slot of the TX_thread, so that the scheduler operates slot_ahead slots ahead of the RX thread. This ensures that UL_tti_req is received before RX slot processing at the PNF. - -The function NR_schedule_response calls oai_nfapi_[DL P7 msg]_req(), which contains the routines for packing + transmission of scheduled messages through the socket to the PNF. For example, to send the 'TX_data_req' p7 message - -``` - -if (Sched_INFO->TX_req->Number_of_PDUs > 0) +int nfapi_pnf_p7_nr_rach_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_rach_indication_t* ind) { - oai_nfapi_tx_data_req(Sched_INFO->TX_req); + if(config == NULL || ind == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__); + return -1; + } + + pnf_p7_t* _this = (pnf_p7_t*)(config); + AssertFatal(_this->_public.send_p7_msg, "Function pointer must be configured|"); + return _this->_public.send_p7_msg(_this, (nfapi_nr_p7_message_header_t*)ind, sizeof(nfapi_nr_rach_indication_t)); } ``` +## P7 UL reception at VNF + +Through the P7 reception loop, the VNF receives a buffer containing the messages, which it handles by the following +process: + +- Unpack the header by use of the hdr_unpack_func function pointer +- According to the Message ID in the header, send the buffer to the appropriate handler by use of a switch statement: + +``` + case NFAPI_NR_PHY_MSG_TYPE_SLOT_INDICATION: + vnf_handle_nr_slot_indication(pRecvMsg, recvMsgLen, vnf_p7); + break; + +``` + +- In the handler function, unpack the entire message, by using the unpack_func function pointer. +- If the unpack procedure is successful, call the previously configure callback for that message type: + +``` + nfapi_nr_slot_indication_scf_t ind = {0}; + const bool result = vnf_p7->_public.unpack_func(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config); + if(!result) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); + } + else + { + NFAPI_TRACE(NFAPI_TRACE_DEBUG, "%s: Handling NR SLOT Indication\n", __FUNCTION__); + if(vnf_p7->_public.nr_slot_indication) + { + (vnf_p7->_public.nr_slot_indication)(&ind); + } + free_slot_indication(&ind); + } + +``` + +vnf_nr_dispatch_p7_message() is the function that contains the switch on various message headers so that the appropriate +unpack function is called. + +## P7 DL Transmission by VNF + +DL messages are scheduled at the VNF, through gNB_dlsch_ulsch_scheduler(). gNB_dlsch_ulsch_scheduler() is called when +handling a SLOT.indication message in trigger_scheduler(). + +The function trigger_scheduler(nfapi_nr_slot_indication_scf_t *slot_ind) calls the functions oai_nfapi_[DL P7 msg]_ +req(), calling in turn call the send_p7_msg function pointer, which contain the logic to pack the message into a buffer +and send it to the PNF. +Finally, NR_UL_indication is called to process the other P7 messages received from the PNF that were put in theire +respective queues. +For example, the TX_DATA.request message is sent in the following manner: + +``` + if (g_sched_resp.TX_req.Number_of_PDUs > 0) + oai_nfapi_tx_data_req(&g_sched_resp.TX_req); + +... + +int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req) +{ + LOG_D(NR_PHY, "Entering oai_nfapi_nr_tx_data_req sfn:%d,slot:%d\n", tx_data_req->SFN, tx_data_req->Slot); + nfapi_vnf_p7_config_t *p7_config = vnf.p7_vnfs[0].config; + tx_data_req->header.phy_id = 1; // HACK TODO FIXME - need to pass this around!!!! + tx_data_req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST; + //LOG_D(PHY, "[VNF] %s() TX_REQ sfn_sf:%d number_of_pdus:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(tx_req->sfn_sf), tx_req->tx_request_body.number_of_pdus); + bool retval = nfapi_vnf_p7_tx_data_req(p7_config, tx_data_req); + + if (!retval) { + LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval); + } else { + tx_data_req->Number_of_PDUs = 0; + } + + return retval; +} + +... + +bool nfapi_vnf_p7_tx_data_req(nfapi_vnf_p7_config_t* config, nfapi_nr_tx_data_request_t* req) +{ + if(config == 0 || req == 0) + return -1; + + vnf_p7_t* vnf_p7 = (vnf_p7_t*)config; + AssertFatal(config->send_p7_msg, "Function pointer must be configured|"); + return config->send_p7_msg(vnf_p7, &req->header); +} + +``` + +## VNF functional flowchart + ```mermaid graph TD - pselect[VNF socket pselect] -- timed out : end of slot --> call_sched[Call Scheduler NR_UL_indication] -- oai_nfapi_***_req sends the DL p7 msg--> slot_inc[Increment sfn/slot]; - pselect[VNF socket pselect] -- UL p7 xyz msg recvd --> msg_recvd[Read message vnf_nr_p7_read_dispatch_message] --> header_unpack[Unpack Header] -- switch cases on header --> unpack_msg[Handle Message vnf_handle_nr_xyz] --> fill_ul_info[Fill UL info struct with fn pointer vnf_p7->_public.nr_rx_xyz]; - fill_ul_info -- update pselect_timeout: next_slot_start - time_xyz_msg_recvd-->pselect; - slot_inc -- next slot --> pselect + softmodem_start[nr-softmodem init] --> P5_configuration[configure_nr_nfapi_vnf] --> transport_init[Transport mechanism init] --> send_first_msg[Send first P5 message to PNF] + transport_init[Transport mechanism init] --> P5_recv_loop[P5 receive loop] -- P5 Message processing --> P5_recv_loop[P5 receive loop] + P5_recv_loop[P5 receive loop] -- Start.response callback called --> P7_config[P7 Configuration] --> P7_loop[P7 Loop] --> P7_msg_recv[P7 message received] --> call_vnf_handle_p7[Call vnf_nr_handle_p7_msg] --> hdr_unpack[Unpack header] --> call_specific_p7_handler[Call specific P7 message handler] --> slot_ind[Is a SLOT.indication?] -- Yes --> trig_scheduler[Call trigger_scheduler] --> gNB_ulsch_dlsch_sched[Call gNB_dlsch_ulsch_scheduler] --> send_p7_dl[Process and send P7 messages to PNF] --> call_ul_ind[Call NR_UL_indication] --> proc_p7[Process P7 messages in queue] --> P7_loop[P7 Loop] + slot_ind[Is a SLOT.indication?] -- No --> put_queue[Put message in queue] --> P7_loop[P7 Loop]; + ``` -Note that since DL P7 message reception and TX/RX processing are done on separate threads, there is the issue of the L1 processing threads trying to do their job before the required P7 message is received. In the case of RX processing, since the scheduler operates slot_ahead slots ahead of the RX thread, the required messages conveniently arrive earlier than they are required. However, in the case of TX processing, this cannot be ensured if the scheduler is exactly in sync with the TX thread. -Therefore, we operate the VNF vnf_slot_ahead (which is currently 2) slots ahead of the PNF. This is to ensure that the DL fapi structures for a particular TX slot are all received before TX processing for that slot. +## P7 DL Reception at PNF -## P7 DL Reception at PNF +Through the infinite loop [while(pnf_p7->terminate == 0)] running in pnf_nr_p7_message_pump(), the PNF receives and +unpacks the downlink P7 message received on its socket. Based on the unpacked message, the appropriate message +structures are filled in the PNF, and these are used further down the pipeline for processing. +Through the P7 reception loop, the PNF receives a buffer containing a P7 message from the VNF, which it processes the +following way: -Through the infinite loop [while(pnf_p7->terminate == 0)] running in pnf_nr_p7_message_pump(), the PNF receives and unpacks the downlink P7 message received on its socket. Based on the unpacked message, the appropriate message structures are filled in the PNF, and these are used further down the pipeline for processing. +- Unpack the header by use of the hdr_unpack_func function pointer +- According to the Message ID in the header, send the buffer to the appropriate handler by use of a switch statement: -While receiving the DL P7 message, we check whether the message was received within a timing window from which it was sent. The duration of the window can be set by the user (set as a parameter for xnf in the p5 messages). Note that the DL information must be received by the PNF within a timing window at least lesser than the duration of slot_ahead variable (timing_window <= slot_ahead * slot_duration). +``` + case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: + pnf_handle_dl_tti_request(pRecvMsg, recvMsgLen, pnf_p7); + break; +``` + +- In the handler function, the SFN and Slot are peeked from the message +- The SFN and slot are checked to determine if the message is inside the appropriate timing window +- If so, the message is unpacked into the P7 Slot buffer: + +``` + pnf_p7->slot_buffer[buffer_index].sfn = frame; + pnf_p7->slot_buffer[buffer_index].slot = slot; + nfapi_nr_dl_tti_request_t *req = &pnf_p7->slot_buffer[buffer_index].dl_tti_req; + pnf_p7->nr_stats.dl_tti.ontime++; + + NFAPI_TRACE(NFAPI_TRACE_DEBUG, + "POPULATE DL_TTI_REQ current tx sfn/slot:%d.%d p7 msg sfn/slot: %d.%d buffer_index:%d\n", + pnf_p7->sfn, + pnf_p7->slot, + frame, + slot, + buffer_index); + const bool result = pnf_p7->_public.unpack_func(pRecvMsg, recvMsgLen, req, sizeof(*req), &(pnf_p7->_public.codec_config)); + + ``` + +- The messages are later processed in the NR_slot_indication function, which is called in the tx_func function ( + L1_tx_thread ) + +## PNF functional flowchart ```mermaid -graph TB - pselect[PNF socket pselect] -- timed out : end of slot --> slot_inc[Increment sfn/slot]; - pselect[PNF socket pselect] -- DL p7 xyz msg recvd --> msg_recvd[Read message pnf_nr_nfapi_p7_read_dispatch_message] --> header_unpack[Unpack Header] -- switch cases on header --> unpack_msg[Unpack Message pnf_handle_nr_xyz] --> fill_pnf_p7[Fill pnf_p7 global structure pnf_handle_nr_xyz] --Data from pnf_p7 struct copied to fapi structures using pnf_phy_***_req. Called every slot from handle_nr_slot_ind-->pselect; - - slot_inc -- next slot --> pselect +graph TD + softmodem_start[nr-softmodem init] --> init_l1_tx_thread[Init L1 TX Thread] --> tx_func[Call tx_func] --> nr_slot_ind[Call NR_slot_indication] --> pnf_slot_ind[Call handle_nr_slot_ind] --> send_slot_ind[Send SLOT.ind to VNF] --> get_from_slot_buffer[Get P7 messages from slot_buffer] --> proc_p7_dl[Process P7 messages from VNF] --> tx_func + softmodem_start[nr-softmodem init] --> init_l1_rx_thread[Init L1 RX Thread] --> rx_func[Call rx_func] --> nr_ul_ind[Call NR_UL_indication] --> send_p7_vnf[Send P7 messages to VNF] --> rx_func + softmodem_start[nr-softmodem init] --> P5_configuration[configure_nr_nfapi_pnf] --> transport_init[Transport mechanism init] --> p5_loop[P5 Loop] -- Process P5 messages --> p5_loop + p5_loop -- START.request callback called --> p7_config[P7 Configuration] --> l1_north_init_gnb[Call l1_north_init_gNB] --> nr_if_module_init[Call NR_IF_Module_Init] --> install_slot_ind_cb[Install NR_slot_indication callback] + p7_config[P7 Configuration] --> p7_loop[P7 Loop] --> p7_recv[Receive P7 message] --> pnf_handle_p7[Call pnf_nr_handle_p7_message] --> hdr_unpack[Unpack header with hdr_unpack] --> p7_handler[Call pnf_handle_] --> peek_sfn[Peek SFN/Slot and check if in timing window] --> p7_unpack[Unpack message into slot_buffer] --> p7_loop ``` -Once the messages are received, they are filled into slot buffers, and are stored until the processing of the slot that they were meant for. diff --git a/doc/README.md b/doc/README.md index 24050666a7..756294fb5d 100644 --- a/doc/README.md +++ b/doc/README.md @@ -57,7 +57,7 @@ There is some general information in the [OpenAirInterface Gitlab Wiki](https:// - [How to use the L2 simulator](./L2NFAPI.md) - [How to use the OAI channel simulator](../openair1/SIMULATION/TOOLS/DOC/channel_simulation.md) - [How to use multiple BWPs](./RUN_NR_multiple_BWPs.md) -- [How to run OAI-VNF and OAI-PNF](./nfapi.md): how to run the nFAPI split, +- [How to run OAI-VNF and OAI-PNF](./nfapi.md): how to run the FAPI/nFAPI split, including some general remarks on FAPI/nFAPI. - [How to use the positioning reference signal (PRS)](./RUN_NR_PRS.md) - [How to use device-to-device communication (D2D, 4G)](./d2d_emulator_setup.txt) diff --git a/doc/nfapi.md b/doc/nfapi.md index 366b5fb4ac..41a3770be4 100644 --- a/doc/nfapi.md +++ b/doc/nfapi.md @@ -1,5 +1,6 @@ This document describes the SmallCellForum (SCF) (n)FAPI split in 5G, i.e., -between the MAC/L2 and PHY/L1. +between the MAC/L2 and PHY/L1. It also describes how to make use of the +multiple transport mechanisms between the 2. The interested reader is recommended to read a copy of the SCF 222.10 specification ("FAPI"). This includes information on what is P5, P7, and how @@ -7,6 +8,8 @@ FAPI works. The currently used version is SCF 222.10.02, with some messages upgraded to SCF 222.10.04 due to bugfixes in the spec. Further information about nFAPI can be found in SCF 225.2.0. +[[_TOC_]] + # Quickstart Compile OAI as normal. Start the CN and make sure that the VNF configuration @@ -108,6 +111,125 @@ can proceed as follows: Note: all L1-specific options have to be passed to the PNF, and remaining options to the VNF. +## Transport mechanisms between VNF and PNF + +Currently, the VNF/PNF split supports three transport mechanisms between each +other: + +1. Socket communication (either regular, or SCTP), this is the default + + The socket type may be changed by editing `nfapi_pnf_config_create()` and + `nfapi_vnf_config_create()`, in both of which `_this->sctp = ;` indicate whether SCTP or regular sockets are to be used. Note: The + value of `_this->sctp` **must** be the same on the VNF and PNF. +2. Intel WLS Lib, which uses DPDK to achieve a shared memory communication between components. +3. nvIPC, which is used exclusively for the NVIDIA Aerial L1. Thus, it is only + applicable for the VNF. + +The change between transport mechanisms is done at compilation time: +- No changes to the `build_oai` call are required in order to select socket communication, as it is the default. +- In order to select WLS as the transport mechanism between VNF and PNF, first install the WLS library, and afterwards use `-t WLS` as a parameter of `build_oai`: + +### How to use nFAPI + +nFAPI is used by default. Compile and configure as indicated above. + +### How to use Aerial + +Refer to [this document](./Aerial_FAPI_Split_Tutorial.md) for more information. + +### How to use WLS lib + +Before the first compilation with WLS support, the [WLS +library](https://docs.o-ran-sc.org/projects/o-ran-sc-o-du-phy/en/latest/wls-lib.html) +must first be compiled and installed to the system. + +The WLS library has a few dependencies: + - [DPDK](https://doc.dpdk.org/guides/prog_guide/build-sdk-meson.html), specifically version [20.11.3](https://fast.dpdk.org/rel/dpdk-20.11.3.tar.xz). + - libelf-dev + - libhugetlbfs-dev + +Additionally, a patch needs to be applied to the WLS lib Makefile in order for +the shared library and headers to be installed into the system, the necessary +patch is available [here](../cmake_targets/tools/install_wls_lib.patch) + +Clone the code and apply the patch + + git clone -b oran_f_release https://gerrit.o-ran-sc.org/r/o-du/phy.git + cd phy/wls_lib/ + git apply ~/openairinterface5g/cmake_targets/tools/install_wls_lib.patch + +Then compile and install the library + + WIRELESS_SDK_TOOLCHAIN=gcc WIRELESS_SDK_TARGET_ISA=avx2 make + sudo WIRELESS_SDK_TOOLCHAIN=gcc WIRELESS_SDK_TARGET_ISA=avx2 make install + +After installing WLS, you can run the build command as shown below: + + ./build_oai -t WLS -w USRP --gNB --nrUE --ninja -C + +#### How to run OAI PNF with OAI VNF + +Refer to the above steps in [Quickstart](.#quickstart), but run the PNF first as it is the WLS "master". + +#### How to run OAI PNF with OSC/Radisys O-DU + +Set up the hugepages for DPDK (1GB page size, 6 pages; this only needs to be +done once): + + sudo nano /etc/default/grub + GRUB_CMDLINE_LINUX_DEFAULT="${GRUB_CMDLINE_LINUX_DEFAULT} default_hugepagesz=1G hugepagesz=1G hugepages=6" + +Then rewrite the bootloader and reboot + + sudo update-grub + sudo reboot + +Install dependencies: + + sudo apt-get install libstdc++-14-dev libnsl-dev libpcap-dev libxml2-dev + +Clone the Radisys repository (We're currently using the `oai_integration` branch): + + git clone https://gerrit.o-ran-sc.org/r/o-du/l2 -b oai-integration + +Build the O-DU + + cd ~/l2/build/odu + make clean_all;make odu PHY=INTEL_L1 MACHINE=BIT64 MODE=TDD;make cu_stub NODE=TEST_STUB MACHINE=BIT64 MODE=TDD;make ric_stub NODE=TEST_STUB MACHINE=BIT64 MODE=TDD + +Setup local interfaces for the cu_stub, ric_stub and o_du + + sudo ifconfig enp7s0:ODU "192.168.130.81" && sudo ifconfig enp7s0:CU_STUB "192.168.130.82" && sudo ifconfig enp7s0:RIC_STUB "192.168.130.80" + +Run cu_stu and ric_stub in separate terminals + + cd ~/l2/bin/ + ./cu_stub/cu_stub + clear && ./ric_stub/ric_stub + +Run the OAI PNF first, as it is the WLS memory master + + sudo NFAPI_TRACE_LEVEL=info ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-pnf.band78.rfsim.2x2.conf --nfapi PNF --rfsim --rfsimulator.serveraddr server + +Run the O-DU over GDB + + sudo -E gdb -ex run --readnever --args ./odu/odu + +Note: If you see the following prompt in GDB + + This GDB supports auto-downloading debuginfo from the following URLs: + + Enable debuginfod for this session? (y or [n]) + +You can run the following command one time before executing gdb to disable it: + + export DEBUGINFOD_URLS= + +Run the OAI-UE + + sudo ./nr-uesoftmodem -r 273 --numerology 1 --band 78 -C 3400140000 --ssb 1518 --uicc0.imsi 001010000000001 --rfsim + # nFAPI logging system nFAPI has its own logging system, independent of OAI's. It can be activated by From d4c46c50734bc177a5c884a19d173d3a41588e23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Soares=20Silva?= Date: Mon, 31 Mar 2025 15:03:29 +0100 Subject: [PATCH 225/964] Fix compilation for simulators and LTE softmodem Add nr_fapi_p5 library to the simulators common library for access to the utility function `copy_config_request` Add dummy VNF/PNF functions to be referenced by lte-softmodem, before LTE and NR implementations of the VNF/PNF are separated --- openair1/SCHED/nfapi_lte_dummy.c | 81 ++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/openair1/SCHED/nfapi_lte_dummy.c b/openair1/SCHED/nfapi_lte_dummy.c index 6856d85806..d61f0d0548 100644 --- a/openair1/SCHED/nfapi_lte_dummy.c +++ b/openair1/SCHED/nfapi_lte_dummy.c @@ -4,6 +4,10 @@ #include "nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h" #include "openair2/NR_PHY_INTERFACE/NR_IF_Module.h" #include "openair1/PHY/LTE_TRANSPORT/transport_common.h" +typedef struct pnf_t pnf_t; +typedef struct pnf_p7_t pnf_p7_t; +typedef struct vnf_t vnf_t; +typedef struct vnf_p7_t vnf_p7_t; void handle_nfapi_nr_pdcch_pdu(PHY_VARS_gNB *gNB, int frame, int slot, @@ -52,3 +56,80 @@ void install_nr_schedule_handlers(NR_IF_Module_t *if_inst){} void nr_dump_frame_parms(NR_DL_FRAME_PARMS *fp){} +bool vnf_nr_send_p5_msg(vnf_t *vnf, uint16_t p5_idx, nfapi_nr_p4_p5_message_header_t *msg, uint32_t msg_len) +{ + return false; +} + +bool vnf_nr_send_p7_msg(vnf_p7_t *vnf_p7, nfapi_nr_p7_message_header_t *header) +{ + return false; +} + +void *vnf_nr_start_p7_thread(void *ptr) +{ + return 0; +} + +bool pnf_nr_send_p5_message(pnf_t *pnf, nfapi_nr_p4_p5_message_header_t *msg, uint32_t msg_len) +{ + return false; +} + +bool pnf_nr_send_p7_message(pnf_p7_t *pnf_p7, nfapi_nr_p7_message_header_t *header, uint32_t msg_len) +{ + return false; +} + +void *pnf_start_p5_thread(void *ptr) +{ + return 0; +} + +void vnf_start_p5_thread(void *ptr) +{ +} + +void *pnf_nr_p7_thread_start(void *ptr) +{ + return 0; +} + +bool wls_vnf_nr_send_p7_message(vnf_p7_t *vnf_p7, nfapi_nr_p7_message_header_t *msg) +{ + return false; +} + +void wls_vnf_set_p7_config(void *p7_config) +{ +} + +bool wls_vnf_nr_send_p5_message(vnf_t *vnf,uint16_t p5_idx, nfapi_nr_p4_p5_message_header_t* msg, uint32_t msg_len) +{ + return false; +} + +void *wls_fapi_vnf_nr_start_thread(void *ptr) +{ + return NULL; +} + +bool wls_pnf_nr_send_p7_message(pnf_p7_t* pnf_p7,nfapi_nr_p7_message_header_t *msg, uint32_t msg_len) +{ + return false; +} + +bool wls_pnf_nr_send_p5_message(pnf_t *pnf, nfapi_nr_p4_p5_message_header_t *msg, uint32_t msg_len) +{ + return false; +} + +void *wls_fapi_pnf_nr_start_thread(void *ptr) +{ + return NULL; +} + +void wls_pnf_set_p7_config(void *p7_config) +{ + +} From d74c620956aebc5ad93a85f9a60d9883b5f36251 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Soares=20Silva?= Date: Mon, 14 Jul 2025 14:34:50 +0100 Subject: [PATCH 226/964] Set PNF slot_ahead to 1 when using WLS as the transport mechanism --- nfapi/oai_integration/nfapi_pnf.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/nfapi/oai_integration/nfapi_pnf.c b/nfapi/oai_integration/nfapi_pnf.c index 24d7d0fbfa..48e31b7264 100644 --- a/nfapi/oai_integration/nfapi_pnf.c +++ b/nfapi/oai_integration/nfapi_pnf.c @@ -2339,7 +2339,11 @@ void handle_nr_slot_ind(uint16_t sfn, uint16_t slot) //send VNF slot indication, which is aligned with TX thread, so that it can call the scheduler //we give four additional slots (2ms) which should be enough time for the VNF to //answer +#ifndef ENABLE_WLS int slot_ahead = 2 << mu; +#else + int slot_ahead = 1; +#endif uint16_t sfn_tx = sfn; uint16_t slot_tx = slot; sfnslot_add_slot(mu, &sfn_tx, &slot_tx, slot_ahead); // modify: do in place From 5c52f6dc23f7e25e9a048e7a240f45c8041d51b2 Mon Sep 17 00:00:00 2001 From: fatich Date: Tue, 15 Jul 2025 15:12:16 +0200 Subject: [PATCH 227/964] fix(RLC): Count dropped DL SDUs by the RLC When a downlink SDU was discarded by the RLC Acknowledged Mode entity due to a full transmit buffer (tx_maxsize), the drop statistics were not being updated. The `txpdu_dd_pkts` and `txpdu_dd_bytes` counters remained at 0. It should be noted that while the statistics are named `txpdu_dd_*`, the drop at this stage occurs at the SDU level. --- openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c b/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c index 4d288b48cb..65a182b3a1 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c @@ -1811,6 +1811,8 @@ void nr_rlc_entity_am_recv_sdu(nr_rlc_entity_t *_entity, if (entity->tx_size + size > entity->tx_maxsize) { entity->sdu_rejected++; + entity->common.stats.txpdu_dd_pkts++; + entity->common.stats.txpdu_dd_bytes += size; return; } From d5b9f81285a7b97a6413391d965e1eba6bef7816 Mon Sep 17 00:00:00 2001 From: rmagueta Date: Thu, 10 Jul 2025 10:12:42 +0200 Subject: [PATCH 228/964] Send MeasConfig to DU, Receive MeasGapConfig from DU --- openair2/RRC/NR/MESSAGES/asn1_msg.c | 14 +++++++ openair2/RRC/NR/MESSAGES/asn1_msg.h | 5 +++ openair2/RRC/NR/rrc_gNB.c | 60 +++++++++++++++++++++-------- 3 files changed, 64 insertions(+), 15 deletions(-) diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.c b/openair2/RRC/NR/MESSAGES/asn1_msg.c index b3397ad518..c016e4c899 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.c +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.c @@ -1152,3 +1152,17 @@ int do_NR_HandoverPreparationInformation(const uint8_t *uecap_buf, int uecap_buf ASN_STRUCT_FREE(asn_DEF_NR_HandoverPreparationInformation, hpi); return (enc_rval.encoded + 7) / 8; } + +int do_NR_MeasConfig(const NR_MeasConfig_t *measconfig, uint8_t *buf, int buf_size) +{ + asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_MeasConfig, NULL, measconfig, buf, buf_size); + AssertFatal(enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", enc_rval.failed_type->name, enc_rval.encoded); + return (enc_rval.encoded + 7) / 8; +} + +int do_NR_MeasurementTimingConfiguration(const NR_MeasurementTimingConfiguration_t *mtc, uint8_t *buf, int buf_size) +{ + asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_MeasurementTimingConfiguration, NULL, mtc, buf, buf_size); + AssertFatal(enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", enc_rval.failed_type->name, enc_rval.encoded); + return (enc_rval.encoded + 7) / 8; +} diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.h b/openair2/RRC/NR/MESSAGES/asn1_msg.h index 8918384090..432db0e5cd 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.h +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.h @@ -50,6 +50,7 @@ #include "NR_ReestablishmentCause.h" #include "NR_SRB-ToAddModList.h" #include "NR_SecurityConfig.h" +#include "NR_MeasurementTimingConfiguration.h" #include "ds/seq_arr.h" #include "ds/byte_array.h" #include "rrc_messages_types.h" @@ -120,6 +121,10 @@ int do_RRCSetupComplete(uint8_t *buffer, int do_NR_HandoverPreparationInformation(const uint8_t *uecap_buf, int uecap_buf_size, uint8_t *buf, int buf_size); +int do_NR_MeasConfig(const NR_MeasConfig_t *measconfig, uint8_t *buf, int buf_size); + +int do_NR_MeasurementTimingConfiguration(const NR_MeasurementTimingConfiguration_t *mtc, uint8_t *buf, int buf_size); + int do_RRCSetupRequest(uint8_t *buffer, size_t buffer_size, uint8_t *rv, uint64_t fiveG_S_TMSI_part1); int do_NR_RRCReconfigurationComplete_for_nsa(uint8_t *buffer, size_t buffer_size, NR_RRC_TransactionIdentifier_t Transaction_id); diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index eeb18e8698..991b19af50 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -557,14 +557,11 @@ void free_RRCReconfiguration_params(nr_rrc_reconfig_param_t params) FREE_AND_ZERO_BYTE_ARRAY(params.dedicated_NAS_msg_list[i]); } -/** @brief Prepare the instance of RRCReconfigurationParams to be pass to RRC encoding */ -nr_rrc_reconfig_param_t get_RRCReconfiguration_params(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, uint8_t srb_reest_bitmap, bool drb_reestablish) +static NR_MeasConfig_t *nr_rrc_get_measconfig(const gNB_RRC_INST *rrc, const gNB_RRC_UE_t *UE) { - uint8_t xid = rrc_gNB_get_next_transaction_identifier(rrc->module_id); - nr_rrc_du_container_t *du = get_du_for_ue(rrc, UE->rrc_ue_id); + nr_rrc_du_container_t *du = get_du_for_ue((gNB_RRC_INST *)rrc, UE->rrc_ue_id); DevAssert(du != NULL); f1ap_served_cell_info_t *cell_info = &du->setup_req->cell[0].info; - NR_MeasConfig_t *measconfig = NULL; NR_ReportConfigToAddMod_t *rc_PER = NULL; NR_ReportConfigToAddMod_t *rc_A2 = NULL; seq_arr_t *rc_A3_seq = NULL; @@ -578,9 +575,7 @@ nr_rrc_reconfig_param_t get_RRCReconfiguration_params(gNB_RRC_INST *rrc, gNB_RRC if (neighbour_config) neighbour_cells = neighbour_config->neighbour_cells; - if (neighbour_cells - && rrc->measurementConfiguration.a3_event_list - && rrc->measurementConfiguration.a3_event_list->size > 0) { + if (neighbour_cells && rrc->measurementConfiguration.a3_event_list && rrc->measurementConfiguration.a3_event_list->size > 0) { /* Loop through neighbours and find related A3 configuration If no related A3 but there is default add the default one. If default one added once as a report, no need to add it again && duplication. @@ -591,7 +586,7 @@ nr_rrc_reconfig_param_t get_RRCReconfiguration_params(gNB_RRC_INST *rrc, gNB_RRC bool is_default_a3_added = false; for (int i = 0; i < neighbour_cells->size; i++) { nr_neighbour_cell_t *neighbourCell = (nr_neighbour_cell_t *)seq_arr_at(neighbour_cells, i); - const nr_a3_event_t *a3Event = get_a3_configuration(rrc, neighbourCell->physicalCellId); + const nr_a3_event_t *a3Event = get_a3_configuration((gNB_RRC_INST *)rrc, neighbourCell->physicalCellId); if (!a3Event || is_default_a3_added) continue; if (a3Event->pci == -1) @@ -603,14 +598,15 @@ nr_rrc_reconfig_param_t get_RRCReconfiguration_params(gNB_RRC_INST *rrc, gNB_RRC rc_PER = prepare_periodic_event_report(rrc->measurementConfiguration.per_event); if (rrc->measurementConfiguration.a2_event) rc_A2 = prepare_a2_event_report(rrc->measurementConfiguration.a2_event); - - measconfig = get_MeasConfig(mt, band, scs, rc_PER, rc_A2, rc_A3_seq, neighbour_cells); + return get_MeasConfig(mt, band, scs, rc_PER, rc_A2, rc_A3_seq, neighbour_cells); } + return NULL; +} - if (UE->measConfig) - free_MeasConfig(UE->measConfig); - - UE->measConfig = measconfig; +/** @brief Prepare the instance of RRCReconfigurationParams to be pass to RRC encoding */ +nr_rrc_reconfig_param_t get_RRCReconfiguration_params(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, uint8_t srb_reest_bitmap, bool drb_reestablish) +{ + uint8_t xid = rrc_gNB_get_next_transaction_identifier(rrc->module_id); // Re-establish PDCP for SRB2 only NR_SRB_ToAddModList_t *SRBs = createSRBlist(UE, srb_reest_bitmap); @@ -1155,6 +1151,7 @@ static void rrc_handle_RRCSetupRequest(gNB_RRC_INST *rrc, UE->nr_cellid = msg->nr_cellid; UE->masterCellGroup = cellGroupConfig; UE->ongoing_reconfiguration = false; + UE->measConfig = nr_rrc_get_measconfig(rrc, UE); activate_srb(UE, 1); rrc_gNB_generate_RRCSetup(0, msg->crnti, ue_context_p, msg->du2cu_rrc_container, msg->du2cu_rrc_container_length); } @@ -2091,6 +2088,17 @@ static void rrc_CU_process_ue_context_setup_response(MessageDef *msg_p, instance uper_decode_complete(NULL, &asn_DEF_NR_CellGroupConfig, (void **)&cellGroupConfig, (uint8_t *)cgc->buf, cgc->len); AssertFatal(dec_rval.code == RC_OK && dec_rval.consumed > 0, "Cell group config decode error\n"); + if (resp->du_to_cu_rrc_info.meas_gap_config) { + NR_MeasGapConfig_t *measGapConfig = NULL; + asn_dec_rval_t dec_rval_mgc = uper_decode_complete(NULL, + &asn_DEF_NR_MeasGapConfig, + (void **)&measGapConfig, + (uint8_t *)resp->du_to_cu_rrc_info.meas_gap_config->buf, + resp->du_to_cu_rrc_info.meas_gap_config->len); + AssertFatal(dec_rval_mgc.code == RC_OK && dec_rval_mgc.consumed > 0, "measGapConfig decode error\n"); + UE->measConfig->measGapConfig = measGapConfig; + } + if (UE->masterCellGroup) { ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->masterCellGroup); LOG_I(RRC, "UE %04x replacing existing CellGroupConfig with new one received from DU\n", UE->rnti); @@ -3039,6 +3047,28 @@ void rrc_gNB_generate_UeContextSetupRequest(const gNB_RRC_INST *rrc, *cu2du.ue_cap = copy_byte_array(ue_p->ue_cap_buffer); } + nr_rrc_du_container_t *du = get_du_for_ue((gNB_RRC_INST *)rrc, ue_p->rrc_ue_id); + byte_array_t *meas_timing_config = NULL; + if (du->mtc && ue_p->measConfig && ue_p->measConfig->measObjectToAddModList) { + NR_MeasObjectToAddModList_t *mo_list = ue_p->measConfig->measObjectToAddModList; + NR_ARFCN_ValueNR_t ssbFrequency0; + for (int i = 0; i < mo_list->list.count; i++) { + NR_MeasObjectToAddMod_t *mo = mo_list->list.array[i]; + if (mo->measObject.present == NR_MeasObjectToAddMod__measObject_PR_measObjectNR) { + NR_MeasObjectNR_t *monr = mo->measObject.choice.measObjectNR; + if (i == 0) { + ssbFrequency0 = *monr->ssbFrequency; + } else if (ssbFrequency0 != *monr->ssbFrequency) { + meas_timing_config = calloc_or_fail(1, sizeof(*meas_timing_config)); + meas_timing_config->buf = calloc_or_fail(1, NR_RRC_BUF_SIZE); + meas_timing_config->len = do_NR_MeasurementTimingConfiguration(du->mtc, meas_timing_config->buf, NR_RRC_BUF_SIZE); + cu2du.meas_timing_config = meas_timing_config; + break; + } + } + } + } + int nb_srb = 1; f1ap_srb_to_setup_t *srbs = calloc_or_fail(nb_srb, sizeof(*srbs)); srbs[0].id = 2; From 779d2bee5255e37d1a2f81e40a9cb8ed897398ce Mon Sep 17 00:00:00 2001 From: rmagueta Date: Mon, 14 Apr 2025 18:35:22 +0100 Subject: [PATCH 229/964] Get new measConfig and measurementTimingConfiguration for target gNB-DU during handover --- openair2/RRC/NR/nr_rrc_proto.h | 2 ++ openair2/RRC/NR/rrc_gNB.c | 6 +++--- openair2/RRC/NR/rrc_gNB_mobility.c | 15 +++++++++++++++ 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h index 094f1791c1..0d675ff525 100644 --- a/openair2/RRC/NR/nr_rrc_proto.h +++ b/openair2/RRC/NR/nr_rrc_proto.h @@ -72,6 +72,8 @@ void rrc_gNB_generate_dedicatedRRCReconfiguration_release(gNB_RRC_INST *rrc, uint32_t nas_length, uint8_t *nas_buffer); +NR_MeasConfig_t *nr_rrc_get_measconfig(const gNB_RRC_INST *rrc, uint64_t nr_cellid); + bool ue_associated_to_cuup(const gNB_RRC_INST *rrc, const gNB_RRC_UE_t *ue); sctp_assoc_t get_existing_cuup_for_ue(const gNB_RRC_INST *rrc, const gNB_RRC_UE_t *ue); sctp_assoc_t get_new_cuup_for_ue(const gNB_RRC_INST *rrc, const gNB_RRC_UE_t *ue, int sst, int sd); diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 991b19af50..8172af28b9 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -557,9 +557,9 @@ void free_RRCReconfiguration_params(nr_rrc_reconfig_param_t params) FREE_AND_ZERO_BYTE_ARRAY(params.dedicated_NAS_msg_list[i]); } -static NR_MeasConfig_t *nr_rrc_get_measconfig(const gNB_RRC_INST *rrc, const gNB_RRC_UE_t *UE) +NR_MeasConfig_t *nr_rrc_get_measconfig(const gNB_RRC_INST *rrc, uint64_t nr_cellid) { - nr_rrc_du_container_t *du = get_du_for_ue((gNB_RRC_INST *)rrc, UE->rrc_ue_id); + nr_rrc_du_container_t *du = get_du_by_cell_id((gNB_RRC_INST *)rrc, nr_cellid); DevAssert(du != NULL); f1ap_served_cell_info_t *cell_info = &du->setup_req->cell[0].info; NR_ReportConfigToAddMod_t *rc_PER = NULL; @@ -1151,7 +1151,7 @@ static void rrc_handle_RRCSetupRequest(gNB_RRC_INST *rrc, UE->nr_cellid = msg->nr_cellid; UE->masterCellGroup = cellGroupConfig; UE->ongoing_reconfiguration = false; - UE->measConfig = nr_rrc_get_measconfig(rrc, UE); + UE->measConfig = nr_rrc_get_measconfig(rrc, UE->nr_cellid); activate_srb(UE, 1); rrc_gNB_generate_RRCSetup(0, msg->crnti, ue_context_p, msg->du2cu_rrc_container, msg->du2cu_rrc_container_length); } diff --git a/openair2/RRC/NR/rrc_gNB_mobility.c b/openair2/RRC/NR/rrc_gNB_mobility.c index 85c9597371..fe3214da2d 100644 --- a/openair2/RRC/NR/rrc_gNB_mobility.c +++ b/openair2/RRC/NR/rrc_gNB_mobility.c @@ -181,6 +181,19 @@ static void nr_initiate_handover(const gNB_RRC_INST *rrc, srbs[0].id = 1; srbs[1].id = 2; + free_MeasConfig(ue->measConfig); + ue->measConfig = nr_rrc_get_measconfig(rrc, target_du->setup_req->cell[0].info.nr_cellid); + byte_array_t *meas_config = calloc_or_fail(1, sizeof(*meas_config)); + meas_config->buf = calloc_or_fail(1, NR_RRC_BUF_SIZE); + meas_config->len = do_NR_MeasConfig(ue->measConfig, meas_config->buf, NR_RRC_BUF_SIZE); + + byte_array_t *meas_timing_config = NULL; + if (target_du->mtc) { + meas_timing_config = calloc_or_fail(1, sizeof(*meas_timing_config)); + meas_timing_config->buf = calloc_or_fail(1, NR_RRC_BUF_SIZE); + meas_timing_config->len = do_NR_MeasurementTimingConfiguration(target_du->mtc, meas_timing_config->buf, NR_RRC_BUF_SIZE); + } + byte_array_t *hpi = malloc_or_fail(sizeof(*hpi)); *hpi = copy_byte_array(*ho_prep_info); @@ -201,6 +214,8 @@ static void nr_initiate_handover(const gNB_RRC_INST *rrc, .drbs_len = nb_drb, .drbs = drbs, .cu_to_du_rrc_info.ho_prep_info = hpi, + .cu_to_du_rrc_info.meas_config = meas_config, + .cu_to_du_rrc_info.meas_timing_config = meas_timing_config, .gnb_du_ue_agg_mbr_ul = ue_agg_mbr, }; rrc->mac_rrc.ue_context_setup_request(target_du->assoc_id, &ue_context_setup_req); From b443ec4c52993c95a740752edd83d5df4427897d Mon Sep 17 00:00:00 2001 From: rmagueta Date: Wed, 16 Apr 2025 12:53:17 +0100 Subject: [PATCH 230/964] Get measurement of neighboring cells and measurement gaps working after RRCReestablishment --- openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c | 1 + openair2/RRC/NR/rrc_gNB.c | 1 + 2 files changed, 2 insertions(+) diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c index 43b73705e9..fdbd886ad9 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -961,6 +961,7 @@ void dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *dl_rrc) UE->CellGroup = oldUE->CellGroup; oldUE->CellGroup = NULL; UE->mac_stats = oldUE->mac_stats; + UE->measgap_config = oldUE->measgap_config; /* 38.331 5.3.7.2 says that the UE releases the spCellConfig, so we drop it * from the current configuration. It will be reapplied when the * reconfiguration has succeeded (indicated by the CU) */ diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 8172af28b9..81f806a204 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -1032,6 +1032,7 @@ static void rrc_gNB_process_RRCReestablishmentComplete(gNB_RRC_INST *rrc, gNB_RR uint8_t new_xid = rrc_gNB_get_next_transaction_identifier(rrc->module_id); ue_p->xids[new_xid] = RRC_REESTABLISH_COMPLETE; nr_rrc_reconfig_param_t params = {.cell_group_config = cellGroupConfig, + .meas_config = ue_p->measConfig, .drb_config_list = DRBs, .srb_config_list = SRBs, .transaction_id = new_xid}; From c3f243ca829b964b5df45da801b66edf0f5b1df3 Mon Sep 17 00:00:00 2001 From: rmagueta Date: Wed, 25 Jun 2025 15:03:55 +0100 Subject: [PATCH 231/964] Inter-frequency handover documentation update --- doc/FEATURE_SET.md | 4 ++++ doc/RRC/rrc-dev.md | 4 ++-- doc/handover-tutorial.md | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/doc/FEATURE_SET.md b/doc/FEATURE_SET.md index 3c7490d937..9faf2c3d3b 100644 --- a/doc/FEATURE_SET.md +++ b/doc/FEATURE_SET.md @@ -139,6 +139,10 @@ These modes of operation are supported: - evaluation of CQI report - MAC scheduling of SR reception - Intra-frequency handover +- Inter-frequency handover + - Measurement gaps are automatically computed at the DU if the CU has neighbor information and the configured + neighbors include cells operating on different frequencies + - DUs must be synchronized with each other for the measurements to be properly performed - Initial support for RedCap - Scheduling of SIBs (2, 19) diff --git a/doc/RRC/rrc-dev.md b/doc/RRC/rrc-dev.md index d511421b01..e6eb3f97e0 100644 --- a/doc/RRC/rrc-dev.md +++ b/doc/RRC/rrc-dev.md @@ -291,7 +291,7 @@ Note that while 38.331 requires only one RRC transaction to happen at a time, the 5G RRC does not actually ensure this; it only tries to prevent it by chaining of transactions and some checks. For instance, the Security Mode procedure is followed by a UE capability procedure, and some procedures are not -executed if others are ongoing (ex.: handover if there is reconfiguratio). +executed if others are ongoing (ex.: handover if there is reconfiguration). However, it might be possible to trigger a procedure while another is ongoing. As of now, no queueing mechanims exists to ensure only one operation is @@ -303,7 +303,7 @@ Handover-related data is stored in a per-UE structure of type `nr_handover_context_t`. It is a pointer and only set during handover operation. This data structure has in turn two pointers, one to the source CU (`nr_ho_source_cu_t`), and one to the target CU (`nr_ho_target_cu_t`). In F1, -both are present. In N2 and Xn, only one pointer is supposed to be set a the +both are present. In N2 and Xn, only one pointer is supposed to be set at the corresponding CU. `nr_ho_source_cu_t` contains notably a function pointer `ho_cancel` for diff --git a/doc/handover-tutorial.md b/doc/handover-tutorial.md index 5fe08be665..87a45ed1e5 100644 --- a/doc/handover-tutorial.md +++ b/doc/handover-tutorial.md @@ -123,7 +123,7 @@ You can do handover across DUs with a COTS UE. Note that these DUs should be separated by at least multiple meters to ensure that the UE will receive different signal strengths when moving between cells. -We only support intra-frequency handovers yet. We have verified with USRPs +We support both intra-frequency and inter-frequency handovers. We have verified with USRPs only, although other radios should work as well. For UEs, we verified Quectel modules and iPhones. Note, though, that not all From 7682c407e1ff72e0413cf118b4ef273a01c61078 Mon Sep 17 00:00:00 2001 From: Bartosz Podrygajlo Date: Wed, 18 Jun 2025 11:19:25 +0200 Subject: [PATCH 232/964] Fix a wraparound bug with equal priority remaining buffer size in MAC --- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 25ddd20b1d..009cbc0ccf 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -2514,7 +2514,10 @@ static long get_num_bytes_to_reqlc(NR_UE_MAC_INST_t *mac, } } AssertFatal(num_remaining_bytes >= 0 && num_bytes_requested <= buflen_remain, - "the total number of bytes allocated until target length is greater than expected\n"); + "the total number of bytes allocated until target length is greater than expected: num_bytes_requested %ld, " + "buflen_remain %d\n", + num_bytes_requested, + buflen_remain); LOG_D(NR_MAC, "number of bytes requested for lcid %d is %li\n", lc_num, num_bytes_requested); return num_bytes_requested; @@ -2780,11 +2783,9 @@ static uint8_t nr_ue_get_sdu(NR_UE_MAC_INST_t *mac, remain); if (num_lcids_same_priority == count_same_priority_lcids) { - buflen_ep = (remain - (count_same_priority_lcids * sizeof(NR_MAC_SUBHEADER_LONG))) / count_same_priority_lcids; - /* after serving equal priority LCIDs in the first round, buflen_remain could be > 0 and < (count_same_priority_lcids * sh_size) - if above division yeilds a remainder. hence the following sets buflen_ep to 0 if there is not enough buffer left for subsequent rounds - */ - buflen_ep = buflen_ep < 0 ? 0 : buflen_ep; + buflen_ep = remain < count_same_priority_lcids * sizeof(NR_MAC_SUBHEADER_LONG) + ? 0 + : (remain - (count_same_priority_lcids * sizeof(NR_MAC_SUBHEADER_LONG))) / count_same_priority_lcids; } while (mac_ce_info.end_for_tailer - mac_ce_info.cur_ptr > 0) { From 5d7c4fe14d5b2ac1174d6d44b75a237ca25bd46c Mon Sep 17 00:00:00 2001 From: Bartosz Podrygajlo Date: Wed, 18 Jun 2025 11:21:29 +0200 Subject: [PATCH 233/964] NR UE: Enable additional PDU session Add new command line / config parameter --extra-pdu-id which when configured creates an extra PDU session. Rename --default_pdu_id to --default-pdu-id --- executables/nr-uesoftmodem.c | 6 +++++- executables/nr-uesoftmodem.h | 3 +++ executables/softmodem-common.h | 3 ++- openair3/NAS/NR_UE/CMakeLists.txt | 1 + openair3/NAS/NR_UE/nr_nas_msg.c | 10 +++++++--- 5 files changed, 18 insertions(+), 5 deletions(-) diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index fad251b060..6ed407a507 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -201,11 +201,15 @@ nrUE_params_t *get_nrUE_params(void) { } static void get_options(configmodule_interface_t *cfg) { - paramdef_t cmdline_params[] =CMDLINE_NRUEPARAMS_DESC ; + paramdef_t cmdline_params[] = CMDLINE_NRUEPARAMS_DESC; int numparams = sizeofArray(cmdline_params); config_get(cfg, cmdline_params, numparams, NULL); if (nrUE_params.vcdflag > 0) ouput_vcd = 1; + AssertFatal(nrUE_params.extra_pdu_id != get_softmodem_params()->default_pdu_session_id, + "Default PDU ID (%d) and Extra PDU ID (%d) must be different!\n", + get_softmodem_params()->default_pdu_session_id, + nrUE_params.extra_pdu_id); } // set PHY vars from command line diff --git a/executables/nr-uesoftmodem.h b/executables/nr-uesoftmodem.h index 2eb9138e78..e5f2eb6571 100644 --- a/executables/nr-uesoftmodem.h +++ b/executables/nr-uesoftmodem.h @@ -24,6 +24,7 @@ extern uint16_t ue_id_g; #define CONFIG_HLP_AGC "Rx Gain control used for UE\n" #define CONFIG_HLP_NUM_UL_ACTORS "Number of UL actors to use. Set to 0 to disable UL actor framework and do processing inline\n" #define CONFIG_HLP_NUM_DL_ACTORS "Number of DL actors to use. Set to 0 to disable DL actor framework and do processing inline\n" +#define CONFIG_HLP_EXTRA_PDU_ID "ID of an additional PDU session to configure alongside default PDU session\n" /***************************************************************************************************************************************/ /* command line options definitions, CMDLINE_XXXX_DESC macros are used to initialize paramdef_t arrays which are then used as argument @@ -81,6 +82,7 @@ extern uint16_t ue_id_g; {"agc", CONFIG_HLP_AGC, PARAMFLAG_BOOL, .iptr=&(nrUE_params.agc), .defintval=0, TYPE_INT, 0}, \ {"num-ul-actors", CONFIG_HLP_NUM_UL_ACTORS, 0, .iptr=&nrUE_params.num_ul_actors, .defintval=2, TYPE_INT, 0}, \ {"num-dl-actors", CONFIG_HLP_NUM_DL_ACTORS, 0, .iptr=&nrUE_params.num_dl_actors, .defintval=4, TYPE_INT, 0}, \ + {"extra-pdu-id", CONFIG_HLP_EXTRA_PDU_ID, 0, .iptr=&nrUE_params.extra_pdu_id, .defintval=-1, TYPE_INT, 0}, \ } // clang-format on @@ -122,6 +124,7 @@ typedef struct { int tx_max_power; int num_ul_actors; int num_dl_actors; + int extra_pdu_id; } nrUE_params_t; extern uint64_t get_nrUE_optmask(void); extern uint64_t set_nrUE_optmask(uint64_t bitmask); diff --git a/executables/softmodem-common.h b/executables/softmodem-common.h index 8bd3558ff1..005677a9de 100644 --- a/executables/softmodem-common.h +++ b/executables/softmodem-common.h @@ -189,7 +189,7 @@ extern int usrp_tx_thread; {"E" , CONFIG_HLP_TQFS, PARAMFLAG_BOOL, .iptr=&softmodem_params.threequarter_fs, .defintval=0, TYPE_INT, 0}, \ {"imscope" , CONFIG_HLP_IMSCOPE, PARAMFLAG_BOOL, .uptr=&enable_imscope, .defintval=0, TYPE_UINT, 0}, \ {"imscope-record" , CONFIG_HLP_IMSCOPE_RECORD,PARAMFLAG_BOOL, .uptr=&enable_imscope_record, .defintval=0, TYPE_UINT, 0}, \ - {"default_pdu_id", NULL, 0, .iptr=&DEFAULT_PDU_ID, .defintval=10, TYPE_INT, 0}, \ + {"default-pdu-id", NULL, 0, .iptr=&DEFAULT_PDU_ID, .defintval=10, TYPE_INT, 0}, \ } // clang-format on @@ -347,6 +347,7 @@ typedef struct { int no_itti; int threequarter_fs; int default_pdu_session_id; + int extra_pdu_session_id; } softmodem_params_t; #define IS_SA_MODE(sM_params) (!(sM_params)->phy_test && !(sM_params)->do_ra && !(sM_params)->nsa) diff --git a/openair3/NAS/NR_UE/CMakeLists.txt b/openair3/NAS/NR_UE/CMakeLists.txt index ec391092e5..edc596fa5f 100644 --- a/openair3/NAS/NR_UE/CMakeLists.txt +++ b/openair3/NAS/NR_UE/CMakeLists.txt @@ -11,6 +11,7 @@ target_link_libraries(nr_nas PUBLIC nas_common_ies_lib nas_utils ds + UTIL ) target_include_directories(nr_nas PUBLIC . 5GS/) diff --git a/openair3/NAS/NR_UE/nr_nas_msg.c b/openair3/NAS/NR_UE/nr_nas_msg.c index f2d87e5606..615cc5a4f1 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg.c +++ b/openair3/NAS/NR_UE/nr_nas_msg.c @@ -74,6 +74,7 @@ #include "fgmm_authentication_reject.h" #include "ds/byte_array.h" #include "key_nas_deriver.h" +#include "nr-uesoftmodem.h" #define MAX_NAS_UE 4 @@ -1773,10 +1774,10 @@ static void send_nas_5gmm_ind(instance_t instance, const Guti5GSMobileIdentity_t itti_send_msg_to_task(TASK_RRC_NRUE, instance, msg); } -static void request_default_pdusession(nr_ue_nas_t *nas) +static void request_pdusession(nr_ue_nas_t *nas, int pdusession_id) { MessageDef *message_p = itti_alloc_new_message(TASK_NAS_NRUE, nas->UE_id, NAS_PDU_SESSION_REQ); - NAS_PDU_SESSION_REQ(message_p).pdusession_id = get_softmodem_params()->default_pdu_session_id; + NAS_PDU_SESSION_REQ(message_p).pdusession_id = pdusession_id; NAS_PDU_SESSION_REQ(message_p).pdusession_type = 0x91; // 0x91 = IPv4, 0x92 = IPv6, 0x93 = IPv4v6 NAS_PDU_SESSION_REQ(message_p).sst = nas->uicc->nssai_sst; NAS_PDU_SESSION_REQ(message_p).sd = nas->uicc->nssai_sd; @@ -1868,7 +1869,10 @@ static void handle_registration_accept(nr_ue_nas_t *nas, const uint8_t *pdu_buff if (get_user_nssai_idx(msg.nas_allowed_nssai, nas) < 0) { LOG_E(NAS, "NSSAI parameters not match with allowed NSSAI. Couldn't request PDU session.\n"); } else { - request_default_pdusession(nas); + request_pdusession(nas, get_softmodem_params()->default_pdu_session_id); + if (get_nrUE_params()->extra_pdu_id != -1) { + request_pdusession(nas, get_nrUE_params()->extra_pdu_id); + } } // Free local message after processing free_fgmm_registration_accept(&msg); From 3d270cf627bf305544e864c313d3b4ab32b28c88 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Tue, 1 Jul 2025 16:47:24 +0200 Subject: [PATCH 234/964] CI: replace nc by ncat When migrating from RHEL (on cacofonix) to Ubuntu 22.04 (on acamas), the `nc` command needs to be replaced by `ncat`. The version of `nc` available on Ubuntu is the OpenBSD variant, which lacks support for some options used in our scripts. `ncat` from the Nmap is used instead. --- .../xml_files/container_5g_f1_rfsim.xml | 20 +++++++++---------- .../xml_files/container_5g_rfsim_24prb.xml | 4 ++-- .../xml_files/container_5g_rfsim_ntn_geo.xml | 4 ++-- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/ci-scripts/xml_files/container_5g_f1_rfsim.xml b/ci-scripts/xml_files/container_5g_f1_rfsim.xml index 9909e84876..bc8cf586ed 100644 --- a/ci-scripts/xml_files/container_5g_f1_rfsim.xml +++ b/ci-scripts/xml_files/container_5g_f1_rfsim.xml @@ -133,7 +133,7 @@ Custom_Command Simulate a DL radio channel with noise (3 dB) acamas - echo channelmod modify 0 noise_power_dB 3 | nc --send-only 192.168.71.181 8091 + echo channelmod modify 0 noise_power_dB 3 | ncat --send-only 192.168.71.181 8091 @@ -164,7 +164,7 @@ Custom_Command Trigger Reestablishment acamas - 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' + echo ci force_reestab | ncat 192.168.71.171 9090 | grep -E 'Reset RLC counters of UE RNTI [0-9a-f]{4} to trigger reestablishment' @@ -182,56 +182,56 @@ Custom_Command Verify Reestablishment acamas - echo ci get_reestab_count | nc 192.168.71.150 9090 | grep -E 'UE RNTI [0-9a-f]{4} reestab 1' + echo ci get_reestab_count | ncat 192.168.71.150 9090 | grep -E 'UE RNTI [0-9a-f]{4} reestab 1' Custom_Command Simulate a disruption of DL radio channel (ploss 55) acamas - echo channelmod modify 0 ploss 55 | nc 192.168.71.181 8091 + echo channelmod modify 0 ploss 55 | ncat 192.168.71.181 8091 Custom_Command Get UE sync state (UE ID 0) acamas - echo ciUE sync_state 0 | nc 192.168.71.181 8091 | grep -E UE_NOT_SYNC + echo ciUE sync_state 0 | ncat 192.168.71.181 8091 | grep -E UE_NOT_SYNC Custom_Command Restoration of the original DL channel conditions (ploss 20) acamas - echo channelmod modify 0 ploss 20 | nc 192.168.71.181 8091 + echo channelmod modify 0 ploss 20 | ncat 192.168.71.181 8091 Custom_Command Get UE sync state (UE ID 0) acamas - echo ciUE sync_state 0 | nc 192.168.71.181 8091 | grep -E UE_CONNECTED + echo ciUE sync_state 0 | ncat 192.168.71.181 8091 | grep -E UE_CONNECTED Custom_Command Trigger Handover acamas - echo ci trigger_f1_ho | nc 192.168.71.150 9090 + echo ci trigger_f1_ho | ncat 192.168.71.150 9090 Custom_Command UE (1) connected to DU-PCI 0? acamas - echo ci fetch_du_by_ue_id 1 | nc 192.168.71.150 9090 | grep "3584" + echo ci fetch_du_by_ue_id 1 | ncat 192.168.71.150 9090 | grep "3584" Custom_Command UE (1) connected to DU-PCI 1? acamas - echo ci fetch_du_by_ue_id 1 | nc 192.168.71.150 9090 | grep "3585" + echo ci fetch_du_by_ue_id 1 | ncat 192.168.71.150 9090 | grep "3585" diff --git a/ci-scripts/xml_files/container_5g_rfsim_24prb.xml b/ci-scripts/xml_files/container_5g_rfsim_24prb.xml index 752252fc11..60bb0011fc 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_24prb.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_24prb.xml @@ -150,14 +150,14 @@ Custom_Command Force Msg3 C-RNTI RA acamas - echo ciUE force_crnti_ra | nc 192.168.71.150 8091 + echo ciUE force_crnti_ra | ncat 192.168.71.150 8091 Custom_Command Force RRC_IDLE (UE ID 0) acamas - echo ciUE force_RRC_IDLE | nc 192.168.71.150 8091 + echo ciUE force_RRC_IDLE | ncat 192.168.71.150 8091 diff --git a/ci-scripts/xml_files/container_5g_rfsim_ntn_geo.xml b/ci-scripts/xml_files/container_5g_rfsim_ntn_geo.xml index 9893f805eb..2cefc32722 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_ntn_geo.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_ntn_geo.xml @@ -107,7 +107,7 @@ Custom_Command Trigger Reestablishment acamas - echo ci force_reestab | nc 192.168.71.140 9090 | grep -E 'Reset RLC counters of UE RNTI [0-9a-f]{4} to trigger reestablishment' + echo ci force_reestab | ncat 192.168.71.140 9090 | grep -E 'Reset RLC counters of UE RNTI [0-9a-f]{4} to trigger reestablishment' yes @@ -126,7 +126,7 @@ Custom_Command Verify Reestablishment acamas - echo ci get_reestab_count | nc 192.168.71.140 9090 | grep -E 'UE RNTI [0-9a-f]{4} reestab 1' + echo ci get_reestab_count | ncat 192.168.71.140 9090 | grep -E 'UE RNTI [0-9a-f]{4} reestab 1' yes From cde021e1d9491ed7631e3a20350b4e9557c80c04 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Fri, 4 Jul 2025 14:43:22 +0200 Subject: [PATCH 235/964] CI: add SYS_NICE capability in some RFSim5G tests Add SYS_NICE capability to enable setting thread priority and affinity in rfsim5g tests. This improves execution speed in test cases with heavier processing workloads. --- .../yaml_files/5g_f1_rfsimulator/docker-compose.yaml | 7 +++++++ .../yaml_files/5g_rfsimulator/docker-compose.yaml | 12 ++++++++++++ .../5g_rfsimulator_2x2/docker-compose.yaml | 3 +++ 3 files changed, 22 insertions(+) diff --git a/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml b/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml index 5c3bdc7a18..90a1a4531d 100644 --- a/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml @@ -96,6 +96,8 @@ services: container_name: rfsim5g-oai-cu cap_drop: - ALL + cap_add: + - SYS_NICE environment: USE_ADDITIONAL_OPTIONS: --log_config.global_log_options level,nocolor,time --rfsimulator.options chanmod @@ -123,6 +125,8 @@ services: container_name: rfsim5g-oai-du-pci0 cap_drop: - ALL + cap_add: + - SYS_NICE environment: USE_ADDITIONAL_OPTIONS: --rfsim --log_config.global_log_options level,nocolor,time @@ -152,6 +156,8 @@ services: container_name: rfsim5g-oai-du-pci1 cap_drop: - ALL + cap_add: + - SYS_NICE environment: USE_ADDITIONAL_OPTIONS: --rfsim --log_config.global_log_options level,nocolor,time @@ -188,6 +194,7 @@ services: cap_add: - NET_ADMIN # for interface bringup - NET_RAW # for ping + - SYS_NICE environment: USE_ADDITIONAL_OPTIONS: --rfsim --log_config.global_log_options level,nocolor,time -r 106 --numerology 1 -C 3619200000 diff --git a/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml index cdce17520a..d531b15270 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml @@ -92,6 +92,8 @@ services: oai-gnb: image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop} container_name: rfsim5g-oai-gnb + cap_add: + - SYS_NICE cap_drop: - ALL environment: @@ -119,6 +121,7 @@ services: cap_add: - NET_ADMIN # for interface bringup - NET_RAW # for ping + - SYS_NICE environment: USE_ADDITIONAL_OPTIONS: -E --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001100 -C 3319680000 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time depends_on: @@ -145,6 +148,7 @@ services: cap_add: - NET_ADMIN # for interface bringup - NET_RAW # for ping + - SYS_NICE environment: USE_ADDITIONAL_OPTIONS: -E --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001101 -C 3319680000 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time depends_on: @@ -171,6 +175,7 @@ services: cap_add: - NET_ADMIN # for interface bringup - NET_RAW # for ping + - SYS_NICE environment: USE_ADDITIONAL_OPTIONS: -E --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001102 -C 3319680000 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time depends_on: @@ -197,6 +202,7 @@ services: cap_add: - NET_ADMIN # for interface bringup - NET_RAW # for ping + - SYS_NICE environment: USE_ADDITIONAL_OPTIONS: -E --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001103 -C 3319680000 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time depends_on: @@ -223,6 +229,7 @@ services: cap_add: - NET_ADMIN # for interface bringup - NET_RAW # for ping + - SYS_NICE environment: USE_ADDITIONAL_OPTIONS: -E --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001104 -C 3319680000 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time depends_on: @@ -249,6 +256,7 @@ services: cap_add: - NET_ADMIN # for interface bringup - NET_RAW # for ping + - SYS_NICE environment: USE_ADDITIONAL_OPTIONS: -E --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001105 -C 3319680000 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time depends_on: @@ -275,6 +283,7 @@ services: cap_add: - NET_ADMIN # for interface bringup - NET_RAW # for ping + - SYS_NICE environment: USE_ADDITIONAL_OPTIONS: -E --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001106 -C 3319680000 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time depends_on: @@ -301,6 +310,7 @@ services: cap_add: - NET_ADMIN # for interface bringup - NET_RAW # for ping + - SYS_NICE environment: USE_ADDITIONAL_OPTIONS: -E --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001107 -C 3319680000 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time depends_on: @@ -327,6 +337,7 @@ services: cap_add: - NET_ADMIN # for interface bringup - NET_RAW # for ping + - SYS_NICE environment: USE_ADDITIONAL_OPTIONS: -E --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001108 -C 3319680000 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time depends_on: @@ -353,6 +364,7 @@ services: cap_add: - NET_ADMIN # for interface bringup - NET_RAW # for ping + - SYS_NICE environment: USE_ADDITIONAL_OPTIONS: -E --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001109 -C 3319680000 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time depends_on: diff --git a/ci-scripts/yaml_files/5g_rfsimulator_2x2/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_2x2/docker-compose.yaml index 5d4970459a..ba7b9a86f4 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_2x2/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_2x2/docker-compose.yaml @@ -94,6 +94,8 @@ services: container_name: rfsim5g-oai-gnb cap_drop: - ALL + cap_add: + - SYS_NICE environment: USE_ADDITIONAL_OPTIONS: --rfsim --log_config.global_log_options level,nocolor,time ASAN_OPTIONS: detect_leaks=0 @@ -120,6 +122,7 @@ services: cap_add: - NET_ADMIN # for interface bringup - NET_RAW # for ping + - SYS_NICE environment: USE_ADDITIONAL_OPTIONS: --rfsim -r 273 --numerology 1 --band 78 -C 3450720000 --ssb 1518 --ue-nb-ant-tx 2 --uicc0.imsi 208990100001100 --ue-nb-ant-rx 2 --uecap_file /opt/oai-nr-ue/etc/uecap.xml --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time depends_on: From 456d7f1aabe5ff03971a38dda7f9d0fb7540d3a0 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Fri, 11 Jul 2025 06:07:47 +0000 Subject: [PATCH 236/964] CI: Increase sleep time in RFSim5G Based on observations from testing on acamas, the interval between DL disruption and the UE synch check needs to be increased - the UE takes longer to go out of sync . A sleep of 15 seconds has proven to be a reliable value to ensure constant results. --- ci-scripts/xml_files/container_5g_f1_rfsim.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci-scripts/xml_files/container_5g_f1_rfsim.xml b/ci-scripts/xml_files/container_5g_f1_rfsim.xml index bc8cf586ed..17f52daeb7 100644 --- a/ci-scripts/xml_files/container_5g_f1_rfsim.xml +++ b/ci-scripts/xml_files/container_5g_f1_rfsim.xml @@ -93,7 +93,7 @@ IdleSleep Sleep - 5 + 15 From 7ba7017fb78abc4901bd0f174694cacf4681af04 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Fri, 11 Jul 2025 06:12:42 +0000 Subject: [PATCH 237/964] CI: add sleep after UE deployment in TDD dora test Give more time to the gNB-UE to establish the connection before ping test is triggered. --- ci-scripts/xml_files/container_5g_rfsim_tdd_dora.xml | 7 +++++++ 1 file changed, 7 insertions(+) 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 e4875418b9..5efa8d3401 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_tdd_dora.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_tdd_dora.xml @@ -30,6 +30,7 @@ 004000 000000 000001 + 000030 020001 020002 100001 @@ -75,6 +76,12 @@ 0 + + IdleSleep + Sleep + 5 + + Ping Ping gNB from NR-UE From fb6640f0e16b84766afbb06b1de17e145b584ec3 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Tue, 15 Jul 2025 15:08:11 +0000 Subject: [PATCH 238/964] CI: adjust UL throughput target for 2x2 RFSim5G test on acamas MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit reduces the UL throughput target in the 2x2 test to align with the host’s performance capabilities. The adjustment ensures more reliable and consistent CI results. --- ci-scripts/xml_files/container_5g_rfsim_2x2.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ci-scripts/xml_files/container_5g_rfsim_2x2.xml b/ci-scripts/xml_files/container_5g_rfsim_2x2.xml index 779a453749..5efb2e708b 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_2x2.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_2x2.xml @@ -112,8 +112,8 @@ Iperf - Iperf (UL/4Mbps/UDP)(30 sec) - -u -b 4M -t 20 + Iperf (UL/3Mbps/UDP)(30 sec) + -u -b 3M -t 20 rfsim5g_ue acamas rfsim5g_ext_dn From fdd29779c65321121a53151a628ce681932286b0 Mon Sep 17 00:00:00 2001 From: Reem Bahsoun Date: Tue, 15 Jul 2025 17:04:16 +0200 Subject: [PATCH 239/964] Change frequency to match the WNC RU range of frequencies --- .../gnb-vnf.sa.band78.273prb.aerial.conf | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/ci-scripts/conf_files/gnb-vnf.sa.band78.273prb.aerial.conf b/ci-scripts/conf_files/gnb-vnf.sa.band78.273prb.aerial.conf index be2e0404e3..37223d712c 100644 --- a/ci-scripts/conf_files/gnb-vnf.sa.band78.273prb.aerial.conf +++ b/ci-scripts/conf_files/gnb-vnf.sa.band78.273prb.aerial.conf @@ -43,19 +43,12 @@ gNBs = # downlinkConfigCommon #frequencyInfoDL - # this is 3300.24 + 134*12*30e3 = 3348.48 MHz (5G NR GSCN: 7741) - absoluteFrequencySSB = 649920; - #652860; #should be 649920 -#647520; -#647540; -#649920; -#650208; -#647540; + # center frequency = 3350.01 MHz + # selected SSB frequency = 3349.92 MHz + absoluteFrequencySSB = 623328; dl_frequencyBand = 78; - # this is 3300.24 MHz - dl_absoluteFrequencyPointA = 646724; -#649104; -#646724; + # frequency point A = 3300.87 MHz + dl_absoluteFrequencyPointA = 620058; #scs-SpecificCarrierList dl_offstToCarrier = 0; # subcarrierSpacing From 27b86205a2ddafb6e233dfaeea861d2b1d53e5e3 Mon Sep 17 00:00:00 2001 From: Reem Bahsoun Date: Tue, 15 Jul 2025 17:25:30 +0200 Subject: [PATCH 240/964] Add high throuput testing on CI --- .../xml_files/container_sa_aerial_quectel.xml | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/ci-scripts/xml_files/container_sa_aerial_quectel.xml b/ci-scripts/xml_files/container_sa_aerial_quectel.xml index 8f524550da..89db1ac2bb 100644 --- a/ci-scripts/xml_files/container_sa_aerial_quectel.xml +++ b/ci-scripts/xml_files/container_sa_aerial_quectel.xml @@ -35,6 +35,8 @@ 000011 000022 000033 + 200022 + 300033 000222 222222 333333 @@ -115,6 +117,28 @@ 80 + + Iperf + Optional iperf (DL/UDP/1000M)(30 sec)(single-ue profile) + true + -u -b 1000M -t 30 -R + oc-cn5g-20897-aerial + up2-aerial + 25 + 80 + + + + Iperf + Optional iperf (UL/UDP/90M)(30 sec)(single-ue profile) + true + -u -b 90M -t 30 -l 1428 + oc-cn5g-20897-aerial + up2-aerial + 25 + 80 + + Detach_UE true From fc72ce87533942b1e783ebd1f7ebe6dc8dba17da Mon Sep 17 00:00:00 2001 From: Reem Bahsoun Date: Wed, 16 Jul 2025 09:58:41 +0200 Subject: [PATCH 241/964] Add WNC RU in Aerial doc + update cuBB iamge name and number of cores used (related to MR 3477) --- doc/Aerial_FAPI_Split_Tutorial.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/doc/Aerial_FAPI_Split_Tutorial.md b/doc/Aerial_FAPI_Split_Tutorial.md index 8d4ea54c3d..1d8132e38d 100644 --- a/doc/Aerial_FAPI_Split_Tutorial.md +++ b/doc/Aerial_FAPI_Split_Tutorial.md @@ -41,12 +41,12 @@ PTP enabled switches and grandmaster clock we have tested with: These are the radio units we've used for testing: -| Vendor | Software Version | -|-------------|------------------| -| Foxconn RPQN-7801E RU | 2.6.9r254 | -| Foxconn RPQN-7801E RU | 3.1.15_0p4 | -| Foxconn RPQN-7801E RU | v3.2.0q.551.12.E.rc2.srs-AIO | - +| Vendor | Software Version | +|-----------------------|-----------------------------| +| Foxconn RPQN-7801E RU | 2.6.9r254 | +| Foxconn RPQN-7801E RU | 3.1.15_0p4 | +| Foxconn RPQN-7801E RU | 3.2.0q.551.12.E.rc2.srs-AIO | +| WNC R1220-078LE | 1.9.0 | The UEs that have been tested and confirmed working with Aerial are the following: @@ -80,7 +80,7 @@ To set up the L1 and install the components manually refer to this [instructions | Applicative Threads | Allocated CPUs | |------------------------|----------------| | PTP & PHC2SYS Services | 41 | -| OAI `nr-softmodem` | 13-20 | +| OAI `nr-softmodem` | 13-14 | ## PTP configuration @@ -230,10 +230,10 @@ After preparing the L1 software, the container needs to be committed to create a In this file the RU MAC address needs to be specified before commiting the image. ```bash -~$ docker commit nv-cubb cubb-build:24-3 +~$ docker commit nv-cubb cubb-build:25-1 ~$ docker image ls .. -cubb-build 24-3 824156e0334c 2 weeks ago 23.9GB +cubb-build 25-1 824156e0334c 2 weeks ago 23.9GB -.. ``` From 4490571e0395ce8f6997f7b9a5b60e6e81b21a64 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 16 Jul 2025 11:10:35 +0200 Subject: [PATCH 242/964] CI 5G RFsim nFAPI u0/25PRB: Add Ping test on second PDU session --- ci-scripts/ci_infra.yaml | 6 ++++++ ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml | 12 ++++++++++++ .../5g_rfsimulator_u0_25prb/docker-compose.yaml | 2 +- 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/ci-scripts/ci_infra.yaml b/ci-scripts/ci_infra.yaml index cda6258244..6e750d75b2 100644 --- a/ci-scripts/ci_infra.yaml +++ b/ci-scripts/ci_infra.yaml @@ -301,6 +301,12 @@ rfsim5g_ue: AttachScript: docker start rfsim5g-oai-nr-ue DetachScript: docker stop rfsim5g-oai-nr-ue MTU: 1500 +# for tests with second PDU session ID 2, needs to match requested PDU session name +rfsim5g_ue_pdu_2: + Host: "%%current_host%%" + NetworkScript: docker exec rfsim5g-oai-nr-ue ip a show dev oaitun_ue1p2 + CmdPrefix: docker exec rfsim5g-oai-nr-ue + IF: oaitun_ue1p2 rfsim5g_ue2: Host: "%%current_host%%" diff --git a/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml b/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml index 82011e3cc2..6a81c53e69 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml @@ -32,6 +32,7 @@ 000003 020001 020002 + 020003 030001 030002 100001 @@ -98,6 +99,17 @@ 5 + + Ping + Ping ext-dn from NR-UE on PDU session ID 2 + rfsim5g_ue_pdu_2 + acamas + rfsim5g_ext_dn + acamas + -c 20 -i 0.25 + 5 + + Iperf Iperf (DL/3Mbps/UDP)(30 sec) diff --git a/ci-scripts/yaml_files/5g_rfsimulator_u0_25prb/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_u0_25prb/docker-compose.yaml index 24a9edd8d7..a1b873eb96 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_u0_25prb/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_u0_25prb/docker-compose.yaml @@ -147,7 +147,7 @@ services: - NET_ADMIN # for interface bringup - NET_RAW # for ping environment: - USE_ADDITIONAL_OPTIONS: --rfsim -r 25 --numerology 0 --uicc0.imsi 208990100001100 --band 66 -C 2152680000 --CO -400000000 --ssb 48 --rfsimulator.serveraddr 192.168.71.141 --log_config.global_log_options level,nocolor,time + USE_ADDITIONAL_OPTIONS: --rfsim -r 25 --numerology 0 --uicc0.imsi 208990100001100 --band 66 -C 2152680000 --CO -400000000 --ssb 48 --rfsimulator.serveraddr 192.168.71.141 --extra-pdu-id 2 --log_config.global_log_options level,nocolor,time depends_on: - oai-pnf networks: From 47d857c9199982747e1bc32d72023a9a3576410c Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Tue, 24 Jun 2025 11:15:13 +0200 Subject: [PATCH 243/964] CI: test T2 with DPDK 22.11 Build and run OAI physims with DPDK version 22.11 for testing with the latest T2 firmware release. Environment variables PKG_CONFIG_PATH and LD_LIBRARY_PATH are set to point to the custom installation path of DPDK v22.11. --- ci-scripts/cls_native.py | 5 ++-- .../xml_files/t2_offload_dec_nr_ulsim.xml | 18 +++++++------- .../xml_files/t2_offload_enc_nr_dlsim.xml | 24 +++++++++---------- 3 files changed, 24 insertions(+), 23 deletions(-) diff --git a/ci-scripts/cls_native.py b/ci-scripts/cls_native.py index 8f4d90ea84..fe508b84e3 100644 --- a/ci-scripts/cls_native.py +++ b/ci-scripts/cls_native.py @@ -30,6 +30,7 @@ import cls_analysis import constants as CONST LOG_PATH_PHYSIM = 'phy_sim_logs' +DPDK_PATH = '/opt/dpdk-t2-22.11.0' class Native(): @@ -39,7 +40,7 @@ class Native(): with cls_cmd.getConnection(host) as ssh: base = f"{directory}/cmake_targets" - ret = ssh.run(f"{base}/build_oai {options} > {base}/log/build_oai.log", timeout=900) + ret = ssh.run(f"C_INCLUDE_PATH={DPDK_PATH}/include/ PKG_CONFIG_PATH={DPDK_PATH}/lib64/pkgconfig/ {base}/build_oai {options} > {base}/log/build_oai.log", timeout=900) success = ret.returncode == 0 logs = ssh.run(f"cat {base}/log/build_oai.log", silent=True) logging.debug(f"build finished with code {ret.returncode}, output:\n{logs.stdout}") @@ -73,7 +74,7 @@ class Native(): os.system(f'mkdir -p ./{LOG_PATH_PHYSIM}') runLogFile=f'physim_{HTML.testCase_id}.log' with cls_cmd.getConnection(host) as cmd: - cmd.run(f'sudo {workSpacePath}/ran_build/build/{physim_test} {options} >> {workSpacePath}/{runLogFile}') + cmd.run(f'sudo LD_LIBRARY_PATH=.:{DPDK_PATH}/lib64/ {workSpacePath}/ran_build/build/{physim_test} {options} >> {workSpacePath}/{runLogFile}') cmd.copyin(src=f'{workSpacePath}/{runLogFile}', tgt=f'{LOG_PATH_PHYSIM}/{runLogFile}') success, msg = cls_analysis.Analysis.analyze_physim(f'{LOG_PATH_PHYSIM}/{runLogFile}', physim_test, options, threshold) if success: diff --git a/ci-scripts/xml_files/t2_offload_dec_nr_ulsim.xml b/ci-scripts/xml_files/t2_offload_dec_nr_ulsim.xml index c959d99e1b..15b8921a5a 100644 --- a/ci-scripts/xml_files/t2_offload_dec_nr_ulsim.xml +++ b/ci-scripts/xml_files/t2_offload_dec_nr_ulsim.xml @@ -62,7 +62,7 @@ true nr_ulsim 100 - -n1000 -s30 -S30.2 -m5 -r106 -R106 -C10 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev d8:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -m5 -r106 -R106 -C10 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 @@ -80,7 +80,7 @@ true nr_ulsim 150 - -n1000 -s30 -S30.2 -m15 -r106 -R106 -C10 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev d8:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -m15 -r106 -R106 -C10 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 @@ -98,7 +98,7 @@ true nr_ulsim 250 - -n1000 -s30 -S30.2 -m25 -r106 -R106 -C10 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev d8:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -m25 -r106 -R106 -C10 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 @@ -116,7 +116,7 @@ true nr_ulsim 150 - -n1000 -s30 -S30.2 -m5 -r273 -R273 -C10 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev d8:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -m5 -r273 -R273 -C10 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 @@ -134,7 +134,7 @@ true nr_ulsim 350 - -n1000 -s30 -S30.2 -m15 -r273 -R273 -C10 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev d8:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -m15 -r273 -R273 -C10 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 @@ -152,7 +152,7 @@ true nr_ulsim 550 - -n1000 -s30 -S30.2 -m25 -r273 -R273 -C10 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev d8:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -m25 -r273 -R273 -C10 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 @@ -170,7 +170,7 @@ true nr_ulsim 250 - -n1000 -s30 -S30.2 -m5 -r273 -R273 -C10 -W2 -z2 -y2 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev d8:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -m5 -r273 -R273 -C10 -W2 -z2 -y2 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 @@ -188,7 +188,7 @@ true nr_ulsim 650 - -n1000 -s30 -S30.2 -m15 -r273 -R273 -C10 -W2 -z2 -y2 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev d8:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -m15 -r273 -R273 -C10 -W2 -z2 -y2 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 @@ -206,7 +206,7 @@ true nr_ulsim 1100 - -n1000 -s30 -S30.2 -m25 -r273 -R273 -C10 -W2 -z2 -y2 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev d8:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -m25 -r273 -R273 -C10 -W2 -z2 -y2 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 diff --git a/ci-scripts/xml_files/t2_offload_enc_nr_dlsim.xml b/ci-scripts/xml_files/t2_offload_enc_nr_dlsim.xml index 400399d3a1..7feb93741a 100644 --- a/ci-scripts/xml_files/t2_offload_enc_nr_dlsim.xml +++ b/ci-scripts/xml_files/t2_offload_enc_nr_dlsim.xml @@ -63,7 +63,7 @@ true nr_dlsim 100 - -n1000 -s30 -S30.2 -e5 -b106 -R106 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev d8:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -e5 -b106 -R106 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 @@ -81,7 +81,7 @@ true nr_dlsim 100 - -n1000 -s30 -S30.2 -e15 -b106 -R106 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev d8:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -e15 -b106 -R106 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 @@ -99,7 +99,7 @@ true nr_dlsim 200 - -n1000 -s30 -S30.2 -e25 -b106 -R106 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev d8:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -e25 -b106 -R106 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 @@ -117,7 +117,7 @@ true nr_dlsim 150 - -n1000 -s30 -S30.2 -e5 -b273 -R273 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev d8:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -e5 -b273 -R273 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 @@ -135,7 +135,7 @@ true nr_dlsim 250 - -n1000 -s30 -S30.2 -e15 -b273 -R273 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev d8:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -e15 -b273 -R273 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 @@ -153,7 +153,7 @@ true nr_dlsim 400 - -n1000 -s30 -S30.2 -e25 -b273 -R273 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev d8:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -e25 -b273 -R273 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 @@ -171,7 +171,7 @@ true nr_dlsim 200 - -n1000 -s30 -S30.2 -e5 -b273 -R273 -X4,5,6,7,8,9 -x2 -z2 -y2 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev d8:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -e5 -b273 -R273 -X4,5,6,7,8,9 -x2 -z2 -y2 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 @@ -189,7 +189,7 @@ true nr_dlsim 500 - -n1000 -s30 -S30.2 -e15 -b273 -R273 -X4,5,6,7,8,9 -x2 -z2 -y2 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev d8:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -e15 -b273 -R273 -X4,5,6,7,8,9 -x2 -z2 -y2 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 @@ -207,7 +207,7 @@ true nr_dlsim 500 - -n1000 -s30 -S30.2 -e25 -b273 -R273 -X4,5,6,7,8,9 -x2 -z2 -y2 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev d8:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -e25 -b273 -R273 -X4,5,6,7,8,9 -x2 -z2 -y2 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 @@ -225,7 +225,7 @@ true nr_dlsim 200 - -n1000 -s30 -S30.2 -e5 -b273 -R273 -X4,5,6,7,8,9 -x2 -z4 -y4 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev d8:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -e5 -b273 -R273 -X4,5,6,7,8,9 -x2 -z4 -y4 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 @@ -243,7 +243,7 @@ true nr_dlsim 300 - -n1000 -s30 -S30.2 -e15 -b273 -R273 -X4,5,6,7,8,9 -x2 -z4 -y4 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev d8:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -e15 -b273 -R273 -X4,5,6,7,8,9 -x2 -z4 -y4 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 @@ -261,6 +261,6 @@ true nr_dlsim 450 - -n1000 -s30 -S30.2 -e25 -b273 -R273 -X4,5,6,7,8,9 -x2 -z4 -y4 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev d8:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -e25 -b273 -R273 -X4,5,6,7,8,9 -x2 -z4 -y4 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 From c9aa985e233ac97eeae6ca6a861d7f280c26a5a7 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 17 Jul 2025 14:36:18 +0200 Subject: [PATCH 244/964] Verify 2nd PDU session is up --- ci-scripts/ci_infra.yaml | 3 +++ ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml | 8 ++++++++ 2 files changed, 11 insertions(+) diff --git a/ci-scripts/ci_infra.yaml b/ci-scripts/ci_infra.yaml index 6e750d75b2..266f0db7cc 100644 --- a/ci-scripts/ci_infra.yaml +++ b/ci-scripts/ci_infra.yaml @@ -307,6 +307,9 @@ rfsim5g_ue_pdu_2: NetworkScript: docker exec rfsim5g-oai-nr-ue ip a show dev oaitun_ue1p2 CmdPrefix: docker exec rfsim5g-oai-nr-ue IF: oaitun_ue1p2 + AttachScript: docker start rfsim5g-oai-nr-ue + DetachScript: docker stop rfsim5g-oai-nr-ue + MTU: 1500 rfsim5g_ue2: Host: "%%current_host%%" diff --git a/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml b/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml index 6a81c53e69..40f3ad4607 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml @@ -32,6 +32,7 @@ 000003 020001 020002 + 000004 020003 030001 030002 @@ -99,6 +100,13 @@ 5 + + Attach_UE + Verify 2nd PDU session is up + rfsim5g_ue_pdu_2 + acamas + + Ping Ping ext-dn from NR-UE on PDU session ID 2 From 0079c4613e4301994e9688ca192a92a2219d5f2d Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Fri, 18 Jul 2025 12:02:10 +0200 Subject: [PATCH 245/964] CI: change frequency for phytests with USRP N310 --- ... => gnb.band79.106prb.usrpn300.phytest-dora.conf} | 12 ++++++------ ... => gnb.band79.162prb.usrpn300.phytest-dora.conf} | 12 ++++++------ ... => gnb.band79.273prb.usrpn300.phytest-dora.conf} | 12 ++++++------ ci-scripts/xml_files/gnb_phytest_usrp_run.xml | 2 +- .../xml_files/gnb_phytest_usrp_run_100_2x2.xml | 2 +- ci-scripts/xml_files/gnb_phytest_usrp_run_60.xml | 2 +- ci-scripts/xml_files/gnb_phytest_usrp_run_60_2x2.xml | 2 +- 7 files changed, 22 insertions(+), 22 deletions(-) rename ci-scripts/conf_files/{gnb.band78.106prb.usrpn300.phytest-dora.conf => gnb.band79.106prb.usrpn300.phytest-dora.conf} (98%) rename ci-scripts/conf_files/{gnb.band78.162prb.usrpn300.phytest-dora.conf => gnb.band79.162prb.usrpn300.phytest-dora.conf} (98%) rename ci-scripts/conf_files/{gnb.band78.273prb.usrpn300.phytest-dora.conf => gnb.band79.273prb.usrpn300.phytest-dora.conf} (98%) diff --git a/ci-scripts/conf_files/gnb.band78.106prb.usrpn300.phytest-dora.conf b/ci-scripts/conf_files/gnb.band79.106prb.usrpn300.phytest-dora.conf similarity index 98% rename from ci-scripts/conf_files/gnb.band78.106prb.usrpn300.phytest-dora.conf rename to ci-scripts/conf_files/gnb.band79.106prb.usrpn300.phytest-dora.conf index bcb3b8e8d8..691fb86393 100644 --- a/ci-scripts/conf_files/gnb.band78.106prb.usrpn300.phytest-dora.conf +++ b/ci-scripts/conf_files/gnb.band79.106prb.usrpn300.phytest-dora.conf @@ -31,11 +31,11 @@ gNBs = # downlinkConfigCommon #frequencyInfoDL - # this is 3319.68 MHz - absoluteFrequencySSB = 621312; - dl_frequencyBand = 78; - # this is 3300.6 MHz - dl_absoluteFrequencyPointA = 620040; + # this is 4412.64 MHz + absoluteFrequencySSB = 694176; + dl_frequencyBand = 79; + # this is 4400.94 MHz + dl_absoluteFrequencyPointA = 693396; #scs-SpecificCarrierList dl_offstToCarrier = 0; # subcarrierSpacing @@ -55,7 +55,7 @@ gNBs = #uplinkConfigCommon #frequencyInfoUL - ul_frequencyBand = 78; + ul_frequencyBand = 79; #scs-SpecificCarrierList ul_offstToCarrier = 0; # subcarrierSpacing diff --git a/ci-scripts/conf_files/gnb.band78.162prb.usrpn300.phytest-dora.conf b/ci-scripts/conf_files/gnb.band79.162prb.usrpn300.phytest-dora.conf similarity index 98% rename from ci-scripts/conf_files/gnb.band78.162prb.usrpn300.phytest-dora.conf rename to ci-scripts/conf_files/gnb.band79.162prb.usrpn300.phytest-dora.conf index 79e9fb5402..bb0388f113 100644 --- a/ci-scripts/conf_files/gnb.band78.162prb.usrpn300.phytest-dora.conf +++ b/ci-scripts/conf_files/gnb.band79.162prb.usrpn300.phytest-dora.conf @@ -31,11 +31,11 @@ gNBs = # downlinkConfigCommon #frequencyInfoDL - # this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP) - absoluteFrequencySSB = 621312; - dl_frequencyBand = 78; - # this is 3600 MHz - dl_absoluteFrequencyPointA = 620040; + # this is 4435.68 MHz + absoluteFrequencySSB = 695712; + dl_frequencyBand = 79; + # this is 4400.94 MHz + dl_absoluteFrequencyPointA = 693396; #scs-SpecificCarrierList dl_offstToCarrier = 0; # subcarrierSpacing @@ -55,7 +55,7 @@ gNBs = #uplinkConfigCommon #frequencyInfoUL - ul_frequencyBand = 78; + ul_frequencyBand = 79; #scs-SpecificCarrierList ul_offstToCarrier = 0; # subcarrierSpacing diff --git a/ci-scripts/conf_files/gnb.band78.273prb.usrpn300.phytest-dora.conf b/ci-scripts/conf_files/gnb.band79.273prb.usrpn300.phytest-dora.conf similarity index 98% rename from ci-scripts/conf_files/gnb.band78.273prb.usrpn300.phytest-dora.conf rename to ci-scripts/conf_files/gnb.band79.273prb.usrpn300.phytest-dora.conf index e0c7b78247..67f1272563 100644 --- a/ci-scripts/conf_files/gnb.band78.273prb.usrpn300.phytest-dora.conf +++ b/ci-scripts/conf_files/gnb.band79.273prb.usrpn300.phytest-dora.conf @@ -33,11 +33,11 @@ gNBs = # downlinkConfigCommon #frequencyInfoDL - # this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP) - absoluteFrequencySSB = 621312; - dl_frequencyBand = 78; - # this is 3600 MHz - dl_absoluteFrequencyPointA = 620040; + # this is 4458.72 MHz + absoluteFrequencySSB = 697248; + dl_frequencyBand = 79; + # this is 4400.94 MHz + dl_absoluteFrequencyPointA = 693396; #scs-SpecificCarrierList dl_offstToCarrier = 0; # subcarrierSpacing @@ -57,7 +57,7 @@ gNBs = #uplinkConfigCommon #frequencyInfoUL - ul_frequencyBand = 78; + ul_frequencyBand = 79; #scs-SpecificCarrierList ul_offstToCarrier = 0; # subcarrierSpacing diff --git a/ci-scripts/xml_files/gnb_phytest_usrp_run.xml b/ci-scripts/xml_files/gnb_phytest_usrp_run.xml index 7a66ea6c34..658d0b8c70 100644 --- a/ci-scripts/xml_files/gnb_phytest_usrp_run.xml +++ b/ci-scripts/xml_files/gnb_phytest_usrp_run.xml @@ -45,7 +45,7 @@ Initialize_eNB Initialize gNB USRP - -O ci-scripts/conf_files/gnb.band78.106prb.usrpn300.phytest-dora.conf --phy-test -q -U 768 -T 106 -t 23 -D 127 -m 28 -M 106 --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time + -O ci-scripts/conf_files/gnb.band79.106prb.usrpn300.phytest-dora.conf --phy-test -q -U 768 -T 106 -t 23 -D 127 -m 28 -M 106 --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time datalog_rt_stats.default.yaml NR 192.168.20.2 diff --git a/ci-scripts/xml_files/gnb_phytest_usrp_run_100_2x2.xml b/ci-scripts/xml_files/gnb_phytest_usrp_run_100_2x2.xml index 2f94fa986d..3a24805449 100644 --- a/ci-scripts/xml_files/gnb_phytest_usrp_run_100_2x2.xml +++ b/ci-scripts/xml_files/gnb_phytest_usrp_run_100_2x2.xml @@ -45,7 +45,7 @@ Initialize_eNB Initialize gNB USRP - -O ci-scripts/conf_files/gnb.band78.273prb.usrpn300.phytest-dora.conf --phy-test -q -U 768 -T 273 -t 23 -D 127 -m 23 -M 273 -l 2 --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time + -O ci-scripts/conf_files/gnb.band79.273prb.usrpn300.phytest-dora.conf --phy-test -q -U 768 -T 273 -t 23 -D 127 -m 23 -M 273 -l 2 --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time datalog_rt_stats.100.2x2.yaml NR 192.168.20.2 diff --git a/ci-scripts/xml_files/gnb_phytest_usrp_run_60.xml b/ci-scripts/xml_files/gnb_phytest_usrp_run_60.xml index 77e47c66b4..bececb210f 100644 --- a/ci-scripts/xml_files/gnb_phytest_usrp_run_60.xml +++ b/ci-scripts/xml_files/gnb_phytest_usrp_run_60.xml @@ -45,7 +45,7 @@ Initialize_eNB Initialize gNB USRP - -O ci-scripts/conf_files/gnb.band78.162prb.usrpn300.phytest-dora.conf --phy-test -q -U 768 -T 162 -t 23 -D 127 -m 23 -M 162 --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time + -O ci-scripts/conf_files/gnb.band79.162prb.usrpn300.phytest-dora.conf --phy-test -q -U 768 -T 162 -t 23 -D 127 -m 23 -M 162 --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time datalog_rt_stats.1x1.60.yaml NR 192.168.20.2 diff --git a/ci-scripts/xml_files/gnb_phytest_usrp_run_60_2x2.xml b/ci-scripts/xml_files/gnb_phytest_usrp_run_60_2x2.xml index 67e2316ea3..503f0880a5 100644 --- a/ci-scripts/xml_files/gnb_phytest_usrp_run_60_2x2.xml +++ b/ci-scripts/xml_files/gnb_phytest_usrp_run_60_2x2.xml @@ -45,7 +45,7 @@ Initialize_eNB Initialize gNB USRP - -O ci-scripts/conf_files/gnb.band78.162prb.usrpn300.phytest-dora.conf --phy-test --gNBs.[0].pdsch_AntennaPorts_XP 2 --RUs.[0].nb_tx 2 --RUs.[0].nb_rx 2 -q -U 768 -T 162 -t 23 -D 127 -m 23 -M 162 -l 2 --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time + -O ci-scripts/conf_files/gnb.band79.162prb.usrpn300.phytest-dora.conf --phy-test --gNBs.[0].pdsch_AntennaPorts_XP 2 --RUs.[0].nb_tx 2 --RUs.[0].nb_rx 2 -q -U 768 -T 162 -t 23 -D 127 -m 23 -M 162 -l 2 --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time datalog_rt_stats.60.2x2.yaml NR 192.168.20.2 From 10112332cc4c402a1df8b238630fccf30d8f4f46 Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 1 Jul 2025 13:55:00 +0200 Subject: [PATCH 246/964] function to count bits with a mask for start and stop --- common/utils/nr/nr_common.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/common/utils/nr/nr_common.h b/common/utils/nr/nr_common.h index f98ce510a2..8a24f6d6dd 100644 --- a/common/utils/nr/nr_common.h +++ b/common/utils/nr/nr_common.h @@ -246,6 +246,12 @@ static __attribute__((always_inline)) inline int count_bits64(uint64_t v) return __builtin_popcountll(v); } +static __attribute__((always_inline)) inline int count_bits64_with_mask(uint64_t v, int start, int num) +{ + uint64_t mask = ((1LL << num) - 1) << start; + return count_bits64(v & mask); +} + uint64_t reverse_bits(uint64_t in, int n_bits); void reverse_bits_u8(uint8_t const* in, size_t sz, uint8_t* out); From 1a2a8bb04f9bd0127b59610adc5a99d96c3c94ef Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 1 Jul 2025 14:01:26 +0200 Subject: [PATCH 247/964] replace get_dmrs_symbols_in_slot with new function (does exactly the same) --- openair1/PHY/NR_REFSIG/dmrs_nr.c | 12 +----------- openair1/PHY/NR_REFSIG/dmrs_nr.h | 1 - openair1/SIMULATION/NR_PHY/ulsim.c | 6 ++---- 3 files changed, 3 insertions(+), 16 deletions(-) diff --git a/openair1/PHY/NR_REFSIG/dmrs_nr.c b/openair1/PHY/NR_REFSIG/dmrs_nr.c index 4d5ed0fe63..a5a55d685a 100644 --- a/openair1/PHY/NR_REFSIG/dmrs_nr.c +++ b/openair1/PHY/NR_REFSIG/dmrs_nr.c @@ -307,16 +307,6 @@ int8_t get_next_dmrs_symbol_in_slot(uint16_t ul_dmrs_symb_pos, uint8_t counter, } -/* return the total number of dmrs symbol in a slot */ -uint8_t get_dmrs_symbols_in_slot(uint16_t l_prime_mask, uint16_t nb_symb, uint8_t start) -{ - uint8_t tmp = 0; - for (int i = start; i < start + nb_symb; i++) { - tmp += (l_prime_mask >> i) & 0x01; - } - return tmp; -} - /* return the position of valid dmrs symbol in a slot for channel compensation */ int8_t get_valid_dmrs_idx_for_channel_est(uint16_t dmrs_symb_pos, uint8_t counter) { @@ -351,7 +341,7 @@ void nr_chest_time_domain_avg(NR_DL_FRAME_PARMS *frame_parms, simde__m128i *ul_ch128_1; int16_t *ul_ch16_0; int total_symbols = start_symbol + num_symbols; - int num_dmrs_symb = get_dmrs_symbols_in_slot(dmrs_bitmap, total_symbols, start_symbol); + int num_dmrs_symb = count_bits64_with_mask(dmrs_bitmap, start_symbol, total_symbols); int first_dmrs_symb = get_next_dmrs_symbol_in_slot(dmrs_bitmap, start_symbol, total_symbols); AssertFatal(first_dmrs_symb > -1, "No DMRS symbol present in this slot\n"); for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { diff --git a/openair1/PHY/NR_REFSIG/dmrs_nr.h b/openair1/PHY/NR_REFSIG/dmrs_nr.h index 001aae4150..97d61993ce 100644 --- a/openair1/PHY/NR_REFSIG/dmrs_nr.h +++ b/openair1/PHY/NR_REFSIG/dmrs_nr.h @@ -63,7 +63,6 @@ uint8_t allowed_xlsch_re_in_dmrs_symbol(uint16_t k, void nr_gen_ref_conj_symbols(const uint32_t *in, uint32_t length, int16_t *output, int mod_order); int8_t get_next_dmrs_symbol_in_slot(uint16_t ul_dmrs_symb_pos, uint8_t counter, uint8_t end_symbol); -uint8_t get_dmrs_symbols_in_slot(uint16_t l_prime_mask, uint16_t nb_symb, uint8_t start); int8_t get_valid_dmrs_idx_for_channel_est(uint16_t dmrs_symb_pos, uint8_t counter); void nr_chest_time_domain_avg(NR_DL_FRAME_PARMS *frame_parms, int32_t **ch_estimates, diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index 4e127fe0b7..3c30ad9546 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -847,14 +847,12 @@ int main(int argc, char *argv[]) uint8_t length_dmrs = pusch_len1; uint16_t l_prime_mask = get_l_prime(nb_symb_sch, mapping_type, add_pos, length_dmrs, start_symbol, NR_MIB__dmrs_TypeA_Position_pos2); - uint16_t number_dmrs_symbols = get_dmrs_symbols_in_slot(l_prime_mask, nb_symb_sch, start_symbol); + int number_dmrs_symbols = count_bits64_with_mask(l_prime_mask, start_symbol, nb_symb_sch); uint8_t nb_re_dmrs = (dmrs_config_type == pusch_dmrs_type1) ? 6 : 4; uint32_t tbslbrm = 0; if (ilbrm) - tbslbrm = nr_compute_tbslbrm(mcs_table, - N_RB_UL, - precod_nbr_layers); + tbslbrm = nr_compute_tbslbrm(mcs_table, N_RB_UL, precod_nbr_layers); if ((UE->frame_parms.nb_antennas_tx==4)&&(precod_nbr_layers==4)) num_dmrs_cdm_grps_no_data = 2; From f33e5cbf131313acf45810b3c202a5d01665b9a1 Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 1 Jul 2025 14:24:01 +0200 Subject: [PATCH 248/964] use function to count number of dmrs symbols --- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 7 ++----- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 7 +------ openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 12 +++--------- .../LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c | 5 +---- 4 files changed, 7 insertions(+), 24 deletions(-) diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 8da471f4c1..091741deb9 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -821,10 +821,8 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N AssertFatal(ulsch_harq != NULL, "harq_pid %d is not allocated\n", ulsch->harq_pid); if ((ulsch->active == true) && (ulsch->frame == frame_rx) && (ulsch->slot == slot_rx) && (ulsch->handled == 0)) { LOG_D(PHY, "PUSCH ID %d with RNTI %x detection started in frame %d slot %d\n", ULSCH_id, ulsch->rnti, frame_rx, slot_rx); - - int num_dmrs = 0; - for (int s = 0; s < NR_NUMBER_OF_SYMBOLS_PER_SLOT; s++) - num_dmrs += (ulsch_harq->ulsch_pdu.ul_dmrs_symb_pos >> s) & 1; + nfapi_nr_pusch_pdu_t *pdu = &ulsch_harq->ulsch_pdu; + int num_dmrs = count_bits64_with_mask(pdu->ul_dmrs_symb_pos, 0, NR_NUMBER_OF_SYMBOLS_PER_SLOT); #ifdef DEBUG_RXDATA NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; @@ -832,7 +830,6 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N int slot_offset = frame_parms->get_samples_slot_timestamp(slot_rx, frame_parms, 0); slot_offset -= ru->N_TA_offset; int32_t sample_offset = gNB->common_vars.debugBuff_sample_offset; - nfapi_nr_pusch_pdu_t *pdu = &ulsch_harq->ulsch_pdu; int16_t *buf = (int16_t *)&gNB->common_vars.debugBuff[offset]; buf[0] = (int16_t)ulsch->rnti; buf[1] = (int16_t)pdu->rb_size; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 2c37b21f5b..1a5b245566 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -797,12 +797,7 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, int start_symbol = pusch_config_pdu->start_symbol_index; int number_of_symbols = pusch_config_pdu->nr_of_symbols; - int number_dmrs_symbols = 0; - for (int i = start_symbol; i < start_symbol + number_of_symbols; i++) { - if ((pusch_config_pdu->ul_dmrs_symb_pos >> i) & 0x01) - number_dmrs_symbols += 1; - } - + int number_dmrs_symbols = count_bits64_with_mask(pusch_config_pdu->ul_dmrs_symb_pos, start_symbol, number_of_symbols); int nb_dmrs_re_per_rb = ((pusch_config_pdu->dmrs_config_type == pusch_dmrs_type1) ? 6 : 4) * pusch_config_pdu->num_dmrs_cdm_grps_no_data; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 4a723263dc..78fb84029a 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -293,9 +293,7 @@ static void schedule_nr_MsgA_pusch(NR_UplinkConfigCommon_t *uplinkConfigCommon, pusch_pdu->mcs_index = msgA_PUSCH_Resource->msgA_MCS_r16; pusch_pdu->qam_mod_order = nr_get_Qm_dl(pusch_pdu->mcs_index, pusch_pdu->mcs_table); - int num_dmrs_symb = 0; - for (int i = 10; i < 10 + 3; i++) - num_dmrs_symb += (pusch_pdu->ul_dmrs_symb_pos >> i) & 1; + int num_dmrs_symb = count_bits64_with_mask(pusch_pdu->ul_dmrs_symb_pos, 10, 3); AssertFatal(pusch_pdu->mcs_index <= 28, "Exceeding MCS limit for MsgA PUSCH\n"); int R = nr_get_code_rate_ul(pusch_pdu->mcs_index, pusch_pdu->mcs_table); pusch_pdu->target_code_rate = R; @@ -825,9 +823,7 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP, uint16_t *vrb_map_UL = &nr_mac->common_channels[CC_id].vrb_map_UL[beam_ul.idx][buffer_index * MAX_BWP_SIZE]; NR_pusch_dmrs_t dmrs_info = get_ul_dmrs_params(scc, ul_bwp, &tda_info, 1); - int num_dmrs_symb = 0; - for(int i = tda_info.startSymbolIndex; i < tda_info.startSymbolIndex + tda_info.nrOfSymbols; i++) - num_dmrs_symb += (dmrs_info.ul_dmrs_symb_pos >> i) & 1; + int num_dmrs_symb = count_bits64_with_mask(dmrs_info.ul_dmrs_symb_pos, tda_info.startSymbolIndex, tda_info.nrOfSymbols); int TBS = 0, mcsindex = 0, R = 0, Qm = 0; while(TBS < 7) { // TBS for msg3 is 7 bytes (except for RRCResumeRequest1 currently not implemented) mcsindex++; @@ -1162,9 +1158,7 @@ static void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, slot_ NR_tda_info_t tda_info = get_ul_tda_info(ul_bwp, 0, NR_SearchSpace__searchSpaceType_PR_common, TYPE_TC_RNTI_, ra->Msg3_tda_id); NR_pusch_dmrs_t dmrs_info = get_ul_dmrs_params(scc, ul_bwp, &tda_info, 1); - int num_dmrs_symb = 0; - for(int i = tda_info.startSymbolIndex; i < tda_info.startSymbolIndex + tda_info.nrOfSymbols; i++) - num_dmrs_symb += (dmrs_info.ul_dmrs_symb_pos >> i) & 1; + int num_dmrs_symb = count_bits64_with_mask(dmrs_info.ul_dmrs_symb_pos, tda_info.startSymbolIndex, tda_info.nrOfSymbols); int TBS = 0, mcsindex = 0, R = 0, Qm = 0; while(TBS < 7) { // TBS for msg3 is 7 bytes (except for RRCResumeRequest1 currently not implemented) mcsindex++; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index b894587854..341440607a 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -762,10 +762,7 @@ NR_pusch_dmrs_t get_ul_dmrs_params(const NR_ServingCellConfigCommon_t *scc, tda_info->startSymbolIndex, scc->dmrs_TypeA_Position); - uint8_t num_dmrs_symb = 0; - for(int i = tda_info->startSymbolIndex; i < tda_info->startSymbolIndex + tda_info->nrOfSymbols; i++) - num_dmrs_symb += (dmrs.ul_dmrs_symb_pos >> i) & 1; - dmrs.num_dmrs_symb = num_dmrs_symb; + dmrs.num_dmrs_symb = count_bits64_with_mask(dmrs.ul_dmrs_symb_pos, tda_info->startSymbolIndex, tda_info->nrOfSymbols); dmrs.N_PRB_DMRS = dmrs.num_dmrs_cdm_grps_no_data * (dmrs.dmrs_config_type == 0 ? 6 : 4); return dmrs; } From b0a099cc1514549384aa41b6405ee4e42a8d7920 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 21 Jul 2025 12:17:59 +0200 Subject: [PATCH 249/964] RAN-Container-Parent: Auto-generate artifact in failure case RAN-Container-Parent uses Jenkinsfile-GitLab-Container, which only triggers sub pipelines, then collects their results. However, if a sub pipeline did not generate an artifact, the result was skipped. It would also not show it in the automatically generated result page, when it should. Remedy this by automatically generating a file with a link to the pipeline if the artifact could not be retrieved, which 1. Will give a link, which is easier for developers to follow to the pipeline than manually clicking through Jenkins, 2. Makes the failed pipeline appear in the list of failed pipelines. --- ci-scripts/Jenkinsfile-GitLab-Container | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/ci-scripts/Jenkinsfile-GitLab-Container b/ci-scripts/Jenkinsfile-GitLab-Container index 62ab0266b1..f2a84fbd91 100644 --- a/ci-scripts/Jenkinsfile-GitLab-Container +++ b/ci-scripts/Jenkinsfile-GitLab-Container @@ -835,11 +835,13 @@ def finalizeSlaveJob(jobName) { selector: lastCompleted()) if (fileExists(fileName)) { sh "sed -i -e 's#TEMPLATE_BUILD_TIME#${JOB_TIMESTAMP}#' ${fileName}" - archiveArtifacts artifacts: fileName - // BUILD_URL is like http://server:port/jenkins/job/foo/15/ - // no need to add a prefixed '/' - artifactUrl += 'artifact/' + fileName + } else { + sh "echo \"could not copy results from ${jobName}, please check pipeline ${BUILD_URL}\" > ${fileName}" } + archiveArtifacts artifacts: fileName + // BUILD_URL is like http://server:port/jenkins/job/foo/15/ + // no need to add a prefixed '/' + artifactUrl += 'artifact/' + fileName } artifactUrl = "\n * [${jobName}](${artifactUrl})" return artifactUrl From b732c6082ff76c5bf7e73b38f9add80219cd7b7c Mon Sep 17 00:00:00 2001 From: Abdo-Gaber Date: Mon, 10 Mar 2025 10:39:51 +0100 Subject: [PATCH 250/964] T_tracer Extension to Support up to 35 Parameters in the T() macro --- common/utils/T/T.h | 657 +++++++++++++++++++++++++++++++++- common/utils/T/tracer/event.h | 2 +- 2 files changed, 652 insertions(+), 7 deletions(-) diff --git a/common/utils/T/T.h b/common/utils/T/T.h index 746607cc6e..c78b99632a 100644 --- a/common/utils/T/T.h +++ b/common/utils/T/T.h @@ -100,12 +100,14 @@ struct T_header; /* T macro tricks */ extern int T_stdout; -#define TN(...) TN_N(__VA_ARGS__,39,38,37,36,35,34,33,32,31,30,29,28,27,26, \ - 25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7, \ - 6,5,4,3,2,1,0)(__VA_ARGS__) -#define TN_N(n0,n1,n2,n3,n4,n5,n6,n7,n8,n9,n10,n11,n12,n13,n14,n15,n16,n17, \ - n18,n19,n20,n21,n22,n23,n24,n25,n26,n27,n28,n29,n30,n31,n32, \ - n33,n34,n35,n36,n37,n38,n,...) T##n +#define TN(...) TN_N(__VA_ARGS__,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,\ + 56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,\ + 37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,\ + 18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)(__VA_ARGS__) +#define TN_N(n0,n1,n2,n3,n4,n5,n6,n7,n8,n9,n10,n11,n12,n13,n14,n15,n16,n17,n18,n19,n20,\ + n21,n22,n23,n24,n25,n26,n27,n28,n29,n30,n31,n32,n33,n34,n35,n36,n37,n38,\ + n39,n40,n41,n42,n43,n44,n45,n46,n47,n48,n49,n50,n51,n52,n53,n54,n55,n56,\ + n57,n58,n59,n60,n61,n62,n63,n64,n65,n66,n67,n68,n69,n70,n,...) T##n #define T(...) do { if (T_stdout == 0 || T_stdout == 2) TN(__VA_ARGS__); } while (0) /* type used to send arbitrary buffer data */ @@ -620,6 +622,633 @@ extern int *T_active; } \ } while (0) + +#define T41(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6,t7,x7,t8,x8,t9,x9,\ + t10,x10,t11,x11,t12,x12,t13,x13,t14,x14,t15,x15,t16,x16,t17,x17,\ + t18,x18,t19,x19) \ + do { \ + if (T_ACTIVE(t)) { \ + T_LOCAL_DATA \ + T_HEADER(t); \ + T_PUT_##t0(2, x0); \ + T_PUT_##t1(3, x1); \ + T_PUT_##t2(4, x2); \ + T_PUT_##t3(5, x3); \ + T_PUT_##t4(6, x4); \ + T_PUT_##t5(7, x5); \ + T_PUT_##t6(8, x6); \ + T_PUT_##t7(9, x7); \ + T_PUT_##t8(10, x8); \ + T_PUT_##t9(11, x9); \ + T_PUT_##t10(12, x10); \ + T_PUT_##t11(13, x11); \ + T_PUT_##t12(14, x12); \ + T_PUT_##t13(15, x13); \ + T_PUT_##t14(16, x14); \ + T_PUT_##t15(17, x15); \ + T_PUT_##t16(18, x16); \ + T_PUT_##t17(19, x17); \ + T_PUT_##t18(20, x18); \ + T_PUT_##t19(21, x19); \ + T_COMMIT(); \ + } \ + } while (0) + +#define T43(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6,t7,x7,t8,x8,t9,x9,\ + t10,x10,t11,x11,t12,x12,t13,x13,t14,x14,t15,x15,t16,x16,t17,x17,\ + t18,x18,t19,x19,t20,x20) \ + do { \ + if (T_ACTIVE(t)) { \ + T_LOCAL_DATA \ + T_HEADER(t); \ + T_PUT_##t0(2, x0); \ + T_PUT_##t1(3, x1); \ + T_PUT_##t2(4, x2); \ + T_PUT_##t3(5, x3); \ + T_PUT_##t4(6, x4); \ + T_PUT_##t5(7, x5); \ + T_PUT_##t6(8, x6); \ + T_PUT_##t7(9, x7); \ + T_PUT_##t8(10, x8); \ + T_PUT_##t9(11, x9); \ + T_PUT_##t10(12, x10); \ + T_PUT_##t11(13, x11); \ + T_PUT_##t12(14, x12); \ + T_PUT_##t13(15, x13); \ + T_PUT_##t14(16, x14); \ + T_PUT_##t15(17, x15); \ + T_PUT_##t16(18, x16); \ + T_PUT_##t17(19, x17); \ + T_PUT_##t18(20, x18); \ + T_PUT_##t19(21, x19); \ + T_PUT_##t20(22, x20); \ + T_COMMIT(); \ + } \ + } while (0) + +#define T45(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6,t7,x7,t8,x8,t9,x9,\ + t10,x10,t11,x11,t12,x12,t13,x13,t14,x14,t15,x15,t16,x16,t17,x17,\ + t18,x18,t19,x19,t20,x20,t21,x21) \ + do { \ + if (T_ACTIVE(t)) { \ + T_LOCAL_DATA \ + T_HEADER(t); \ + T_PUT_##t0(2, x0); \ + T_PUT_##t1(3, x1); \ + T_PUT_##t2(4, x2); \ + T_PUT_##t3(5, x3); \ + T_PUT_##t4(6, x4); \ + T_PUT_##t5(7, x5); \ + T_PUT_##t6(8, x6); \ + T_PUT_##t7(9, x7); \ + T_PUT_##t8(10, x8); \ + T_PUT_##t9(11, x9); \ + T_PUT_##t10(12, x10); \ + T_PUT_##t11(13, x11); \ + T_PUT_##t12(14, x12); \ + T_PUT_##t13(15, x13); \ + T_PUT_##t14(16, x14); \ + T_PUT_##t15(17, x15); \ + T_PUT_##t16(18, x16); \ + T_PUT_##t17(19, x17); \ + T_PUT_##t18(20, x18); \ + T_PUT_##t19(21, x19); \ + T_PUT_##t20(22, x20); \ + T_PUT_##t21(23, x21); \ + T_COMMIT(); \ + } \ + } while (0) + +#define T47(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6,t7,x7,t8,x8,t9,x9,\ + t10,x10,t11,x11,t12,x12,t13,x13,t14,x14,t15,x15,t16,x16,t17,x17,\ + t18,x18,t19,x19,t20,x20,t21,x21,t22,x22) \ + do { \ + if (T_ACTIVE(t)) { \ + T_LOCAL_DATA \ + T_HEADER(t); \ + T_PUT_##t0(2, x0); \ + T_PUT_##t1(3, x1); \ + T_PUT_##t2(4, x2); \ + T_PUT_##t3(5, x3); \ + T_PUT_##t4(6, x4); \ + T_PUT_##t5(7, x5); \ + T_PUT_##t6(8, x6); \ + T_PUT_##t7(9, x7); \ + T_PUT_##t8(10, x8); \ + T_PUT_##t9(11, x9); \ + T_PUT_##t10(12, x10); \ + T_PUT_##t11(13, x11); \ + T_PUT_##t12(14, x12); \ + T_PUT_##t13(15, x13); \ + T_PUT_##t14(16, x14); \ + T_PUT_##t15(17, x15); \ + T_PUT_##t16(18, x16); \ + T_PUT_##t17(19, x17); \ + T_PUT_##t18(20, x18); \ + T_PUT_##t19(21, x19); \ + T_PUT_##t20(22, x20); \ + T_PUT_##t21(23, x21); \ + T_PUT_##t22(24, x22); \ + T_COMMIT(); \ + } \ + } while (0) + +#define T49(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6,t7,x7,t8,x8,t9,x9,\ + t10,x10,t11,x11,t12,x12,t13,x13,t14,x14,t15,x15,t16,x16,t17,x17,\ + t18,x18,t19,x19,t20,x20,t21,x21,t22,x22,t23,x23) \ + do { \ + if (T_ACTIVE(t)) { \ + T_LOCAL_DATA \ + T_HEADER(t); \ + T_PUT_##t0(2, x0); \ + T_PUT_##t1(3, x1); \ + T_PUT_##t2(4, x2); \ + T_PUT_##t3(5, x3); \ + T_PUT_##t4(6, x4); \ + T_PUT_##t5(7, x5); \ + T_PUT_##t6(8, x6); \ + T_PUT_##t7(9, x7); \ + T_PUT_##t8(10, x8); \ + T_PUT_##t9(11, x9); \ + T_PUT_##t10(12, x10); \ + T_PUT_##t11(13, x11); \ + T_PUT_##t12(14, x12); \ + T_PUT_##t13(15, x13); \ + T_PUT_##t14(16, x14); \ + T_PUT_##t15(17, x15); \ + T_PUT_##t16(18, x16); \ + T_PUT_##t17(19, x17); \ + T_PUT_##t18(20, x18); \ + T_PUT_##t19(21, x19); \ + T_PUT_##t20(22, x20); \ + T_PUT_##t21(23, x21); \ + T_PUT_##t22(24, x22); \ + T_PUT_##t23(25, x23); \ + T_COMMIT(); \ + } \ + } while (0) + +#define T51(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6,t7,x7,t8,x8,t9,x9,\ + t10,x10,t11,x11,t12,x12,t13,x13,t14,x14,t15,x15,t16,x16,t17,x17,\ + t18,x18,t19,x19,t20,x20,t21,x21,t22,x22,t23,x23,t24,x24) \ + do { \ + if (T_ACTIVE(t)) { \ + T_LOCAL_DATA \ + T_HEADER(t); \ + T_PUT_##t0(2, x0); \ + T_PUT_##t1(3, x1); \ + T_PUT_##t2(4, x2); \ + T_PUT_##t3(5, x3); \ + T_PUT_##t4(6, x4); \ + T_PUT_##t5(7, x5); \ + T_PUT_##t6(8, x6); \ + T_PUT_##t7(9, x7); \ + T_PUT_##t8(10, x8); \ + T_PUT_##t9(11, x9); \ + T_PUT_##t10(12, x10); \ + T_PUT_##t11(13, x11); \ + T_PUT_##t12(14, x12); \ + T_PUT_##t13(15, x13); \ + T_PUT_##t14(16, x14); \ + T_PUT_##t15(17, x15); \ + T_PUT_##t16(18, x16); \ + T_PUT_##t17(19, x17); \ + T_PUT_##t18(20, x18); \ + T_PUT_##t19(21, x19); \ + T_PUT_##t20(22, x20); \ + T_PUT_##t21(23, x21); \ + T_PUT_##t22(24, x22); \ + T_PUT_##t23(25, x23); \ + T_PUT_##t24(26, x24); \ + T_COMMIT(); \ + } \ + } while (0) + +#define T53(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6,t7,x7,t8,x8,t9,x9,\ + t10,x10,t11,x11,t12,x12,t13,x13,t14,x14,t15,x15,t16,x16,t17,x17,\ + t18,x18,t19,x19,t20,x20,t21,x21,t22,x22,t23,x23,t24,x24,t25,x25) \ + do { \ + if (T_ACTIVE(t)) { \ + T_LOCAL_DATA \ + T_HEADER(t); \ + T_PUT_##t0(2, x0); \ + T_PUT_##t1(3, x1); \ + T_PUT_##t2(4, x2); \ + T_PUT_##t3(5, x3); \ + T_PUT_##t4(6, x4); \ + T_PUT_##t5(7, x5); \ + T_PUT_##t6(8, x6); \ + T_PUT_##t7(9, x7); \ + T_PUT_##t8(10, x8); \ + T_PUT_##t9(11, x9); \ + T_PUT_##t10(12, x10); \ + T_PUT_##t11(13, x11); \ + T_PUT_##t12(14, x12); \ + T_PUT_##t13(15, x13); \ + T_PUT_##t14(16, x14); \ + T_PUT_##t15(17, x15); \ + T_PUT_##t16(18, x16); \ + T_PUT_##t17(19, x17); \ + T_PUT_##t18(20, x18); \ + T_PUT_##t19(21, x19); \ + T_PUT_##t20(22, x20); \ + T_PUT_##t21(23, x21); \ + T_PUT_##t22(24, x22); \ + T_PUT_##t23(25, x23); \ + T_PUT_##t24(26, x24); \ + T_PUT_##t25(27, x25); \ + T_COMMIT(); \ + } \ + } while (0) + +#define T55(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6,t7,x7,t8,x8,t9,x9,\ + t10,x10,t11,x11,t12,x12,t13,x13,t14,x14,t15,x15,t16,x16,t17,x17,\ + t18,x18,t19,x19,t20,x20,t21,x21,t22,x22,t23,x23,t24,x24,t25,x25,\ + t26,x26) \ + do { \ + if (T_ACTIVE(t)) { \ + T_LOCAL_DATA \ + T_HEADER(t); \ + T_PUT_##t0(2, x0); \ + T_PUT_##t1(3, x1); \ + T_PUT_##t2(4, x2); \ + T_PUT_##t3(5, x3); \ + T_PUT_##t4(6, x4); \ + T_PUT_##t5(7, x5); \ + T_PUT_##t6(8, x6); \ + T_PUT_##t7(9, x7); \ + T_PUT_##t8(10, x8); \ + T_PUT_##t9(11, x9); \ + T_PUT_##t10(12, x10); \ + T_PUT_##t11(13, x11); \ + T_PUT_##t12(14, x12); \ + T_PUT_##t13(15, x13); \ + T_PUT_##t14(16, x14); \ + T_PUT_##t15(17, x15); \ + T_PUT_##t16(18, x16); \ + T_PUT_##t17(19, x17); \ + T_PUT_##t18(20, x18); \ + T_PUT_##t19(21, x19); \ + T_PUT_##t20(22, x20); \ + T_PUT_##t21(23, x21); \ + T_PUT_##t22(24, x22); \ + T_PUT_##t23(25, x23); \ + T_PUT_##t24(26, x24); \ + T_PUT_##t25(27, x25); \ + T_PUT_##t26(28, x26); \ + T_COMMIT(); \ + } \ + } while (0) + +#define T57(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6,t7,x7,t8,x8,t9,x9,\ + t10,x10,t11,x11,t12,x12,t13,x13,t14,x14,t15,x15,t16,x16,t17,x17,\ + t18,x18,t19,x19,t20,x20,t21,x21,t22,x22,t23,x23,t24,x24,t25,x25,\ + t26,x26,t27,x27) \ + do { \ + if (T_ACTIVE(t)) { \ + T_LOCAL_DATA \ + T_HEADER(t); \ + T_PUT_##t0(2, x0); \ + T_PUT_##t1(3, x1); \ + T_PUT_##t2(4, x2); \ + T_PUT_##t3(5, x3); \ + T_PUT_##t4(6, x4); \ + T_PUT_##t5(7, x5); \ + T_PUT_##t6(8, x6); \ + T_PUT_##t7(9, x7); \ + T_PUT_##t8(10, x8); \ + T_PUT_##t9(11, x9); \ + T_PUT_##t10(12, x10); \ + T_PUT_##t11(13, x11); \ + T_PUT_##t12(14, x12); \ + T_PUT_##t13(15, x13); \ + T_PUT_##t14(16, x14); \ + T_PUT_##t15(17, x15); \ + T_PUT_##t16(18, x16); \ + T_PUT_##t17(19, x17); \ + T_PUT_##t18(20, x18); \ + T_PUT_##t19(21, x19); \ + T_PUT_##t20(22, x20); \ + T_PUT_##t21(23, x21); \ + T_PUT_##t22(24, x22); \ + T_PUT_##t23(25, x23); \ + T_PUT_##t24(26, x24); \ + T_PUT_##t25(27, x25); \ + T_PUT_##t26(28, x26); \ + T_PUT_##t27(29, x27); \ + T_COMMIT(); \ + } \ + } while (0) + +#define T59(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6,t7,x7,t8,x8,t9,x9,\ + t10,x10,t11,x11,t12,x12,t13,x13,t14,x14,t15,x15,t16,x16,t17,x17,\ + t18,x18,t19,x19,t20,x20,t21,x21,t22,x22,t23,x23,t24,x24,t25,x25,\ + t26,x26,t27,x27,t28,x28) \ + do { \ + if (T_ACTIVE(t)) { \ + T_LOCAL_DATA \ + T_HEADER(t); \ + T_PUT_##t0(2, x0); \ + T_PUT_##t1(3, x1); \ + T_PUT_##t2(4, x2); \ + T_PUT_##t3(5, x3); \ + T_PUT_##t4(6, x4); \ + T_PUT_##t5(7, x5); \ + T_PUT_##t6(8, x6); \ + T_PUT_##t7(9, x7); \ + T_PUT_##t8(10, x8); \ + T_PUT_##t9(11, x9); \ + T_PUT_##t10(12, x10); \ + T_PUT_##t11(13, x11); \ + T_PUT_##t12(14, x12); \ + T_PUT_##t13(15, x13); \ + T_PUT_##t14(16, x14); \ + T_PUT_##t15(17, x15); \ + T_PUT_##t16(18, x16); \ + T_PUT_##t17(19, x17); \ + T_PUT_##t18(20, x18); \ + T_PUT_##t19(21, x19); \ + T_PUT_##t20(22, x20); \ + T_PUT_##t21(23, x21); \ + T_PUT_##t22(24, x22); \ + T_PUT_##t23(25, x23); \ + T_PUT_##t24(26, x24); \ + T_PUT_##t25(27, x25); \ + T_PUT_##t26(28, x26); \ + T_PUT_##t27(29, x27); \ + T_PUT_##t28(30, x28); \ + T_COMMIT(); \ + } \ + } while (0) + +#define T61(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6,t7,x7,t8,x8,t9,x9,\ + t10,x10,t11,x11,t12,x12,t13,x13,t14,x14,t15,x15,t16,x16,t17,x17,\ + t18,x18,t19,x19,t20,x20,t21,x21,t22,x22,t23,x23,t24,x24,t25,x25,\ + t26,x26,t27,x27,t28,x28,t29,x29) \ + do { \ + if (T_ACTIVE(t)) { \ + T_LOCAL_DATA \ + T_HEADER(t); \ + T_PUT_##t0(2, x0); \ + T_PUT_##t1(3, x1); \ + T_PUT_##t2(4, x2); \ + T_PUT_##t3(5, x3); \ + T_PUT_##t4(6, x4); \ + T_PUT_##t5(7, x5); \ + T_PUT_##t6(8, x6); \ + T_PUT_##t7(9, x7); \ + T_PUT_##t8(10, x8); \ + T_PUT_##t9(11, x9); \ + T_PUT_##t10(12, x10); \ + T_PUT_##t11(13, x11); \ + T_PUT_##t12(14, x12); \ + T_PUT_##t13(15, x13); \ + T_PUT_##t14(16, x14); \ + T_PUT_##t15(17, x15); \ + T_PUT_##t16(18, x16); \ + T_PUT_##t17(19, x17); \ + T_PUT_##t18(20, x18); \ + T_PUT_##t19(21, x19); \ + T_PUT_##t20(22, x20); \ + T_PUT_##t21(23, x21); \ + T_PUT_##t22(24, x22); \ + T_PUT_##t23(25, x23); \ + T_PUT_##t24(26, x24); \ + T_PUT_##t25(27, x25); \ + T_PUT_##t26(28, x26); \ + T_PUT_##t27(29, x27); \ + T_PUT_##t28(30, x28); \ + T_PUT_##t29(31, x29); \ + T_COMMIT(); \ + } \ + } while (0) + +#define T63(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6,t7,x7,t8,x8,t9,x9,\ + t10,x10,t11,x11,t12,x12,t13,x13,t14,x14,t15,x15,t16,x16,t17,x17,\ + t18,x18,t19,x19,t20,x20,t21,x21,t22,x22,t23,x23,t24,x24,t25,x25,\ + t26,x26,t27,x27,t28,x28,t29,x29,t30,x30) \ + do { \ + if (T_ACTIVE(t)) { \ + T_LOCAL_DATA \ + T_HEADER(t); \ + T_PUT_##t0(2, x0); \ + T_PUT_##t1(3, x1); \ + T_PUT_##t2(4, x2); \ + T_PUT_##t3(5, x3); \ + T_PUT_##t4(6, x4); \ + T_PUT_##t5(7, x5); \ + T_PUT_##t6(8, x6); \ + T_PUT_##t7(9, x7); \ + T_PUT_##t8(10, x8); \ + T_PUT_##t9(11, x9); \ + T_PUT_##t10(12, x10); \ + T_PUT_##t11(13, x11); \ + T_PUT_##t12(14, x12); \ + T_PUT_##t13(15, x13); \ + T_PUT_##t14(16, x14); \ + T_PUT_##t15(17, x15); \ + T_PUT_##t16(18, x16); \ + T_PUT_##t17(19, x17); \ + T_PUT_##t18(20, x18); \ + T_PUT_##t19(21, x19); \ + T_PUT_##t20(22, x20); \ + T_PUT_##t21(23, x21); \ + T_PUT_##t22(24, x22); \ + T_PUT_##t23(25, x23); \ + T_PUT_##t24(26, x24); \ + T_PUT_##t25(27, x25); \ + T_PUT_##t26(28, x26); \ + T_PUT_##t27(29, x27); \ + T_PUT_##t28(30, x28); \ + T_PUT_##t29(31, x29); \ + T_PUT_##t30(32, x30); \ + T_COMMIT(); \ + } \ + } while (0) + +#define T65(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6,t7,x7,t8,x8,t9,x9,\ + t10,x10,t11,x11,t12,x12,t13,x13,t14,x14,t15,x15,t16,x16,t17,x17,\ + t18,x18,t19,x19,t20,x20,t21,x21,t22,x22,t23,x23,t24,x24,t25,x25,\ + t26,x26,t27,x27,t28,x28,t29,x29,t30,x30,t31,x31) \ + do { \ + if (T_ACTIVE(t)) { \ + T_LOCAL_DATA \ + T_HEADER(t); \ + T_PUT_##t0(2, x0); \ + T_PUT_##t1(3, x1); \ + T_PUT_##t2(4, x2); \ + T_PUT_##t3(5, x3); \ + T_PUT_##t4(6, x4); \ + T_PUT_##t5(7, x5); \ + T_PUT_##t6(8, x6); \ + T_PUT_##t7(9, x7); \ + T_PUT_##t8(10, x8); \ + T_PUT_##t9(11, x9); \ + T_PUT_##t10(12, x10); \ + T_PUT_##t11(13, x11); \ + T_PUT_##t12(14, x12); \ + T_PUT_##t13(15, x13); \ + T_PUT_##t14(16, x14); \ + T_PUT_##t15(17, x15); \ + T_PUT_##t16(18, x16); \ + T_PUT_##t17(19, x17); \ + T_PUT_##t18(20, x18); \ + T_PUT_##t19(21, x19); \ + T_PUT_##t20(22, x20); \ + T_PUT_##t21(23, x21); \ + T_PUT_##t22(24, x22); \ + T_PUT_##t23(25, x23); \ + T_PUT_##t24(26, x24); \ + T_PUT_##t25(27, x25); \ + T_PUT_##t26(28, x26); \ + T_PUT_##t27(29, x27); \ + T_PUT_##t28(30, x28); \ + T_PUT_##t29(31, x29); \ + T_PUT_##t30(32, x30); \ + T_PUT_##t31(33, x31); \ + T_COMMIT(); \ + } \ + } while (0) + +#define T67(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6,t7,x7,t8,x8,t9,x9,\ + t10,x10,t11,x11,t12,x12,t13,x13,t14,x14,t15,x15,t16,x16,t17,x17,\ + t18,x18,t19,x19,t20,x20,t21,x21,t22,x22,t23,x23,t24,x24,t25,x25,\ + t26,x26,t27,x27,t28,x28,t29,x29,t30,x30,t31,x31,t32,x32) \ + do { \ + if (T_ACTIVE(t)) { \ + T_LOCAL_DATA \ + T_HEADER(t); \ + T_PUT_##t0(2, x0); \ + T_PUT_##t1(3, x1); \ + T_PUT_##t2(4, x2); \ + T_PUT_##t3(5, x3); \ + T_PUT_##t4(6, x4); \ + T_PUT_##t5(7, x5); \ + T_PUT_##t6(8, x6); \ + T_PUT_##t7(9, x7); \ + T_PUT_##t8(10, x8); \ + T_PUT_##t9(11, x9); \ + T_PUT_##t10(12, x10); \ + T_PUT_##t11(13, x11); \ + T_PUT_##t12(14, x12); \ + T_PUT_##t13(15, x13); \ + T_PUT_##t14(16, x14); \ + T_PUT_##t15(17, x15); \ + T_PUT_##t16(18, x16); \ + T_PUT_##t17(19, x17); \ + T_PUT_##t18(20, x18); \ + T_PUT_##t19(21, x19); \ + T_PUT_##t20(22, x20); \ + T_PUT_##t21(23, x21); \ + T_PUT_##t22(24, x22); \ + T_PUT_##t23(25, x23); \ + T_PUT_##t24(26, x24); \ + T_PUT_##t25(27, x25); \ + T_PUT_##t26(28, x26); \ + T_PUT_##t27(29, x27); \ + T_PUT_##t28(30, x28); \ + T_PUT_##t29(31, x29); \ + T_PUT_##t30(32, x30); \ + T_PUT_##t31(33, x31); \ + T_PUT_##t32(34, x32); \ + T_COMMIT(); \ + } \ + } while (0) + +#define T69(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6,t7,x7,t8,x8,t9,x9,\ + t10,x10,t11,x11,t12,x12,t13,x13,t14,x14,t15,x15,t16,x16,t17,x17,\ + t18,x18,t19,x19,t20,x20,t21,x21,t22,x22,t23,x23,t24,x24,t25,x25,\ + t26,x26,t27,x27,t28,x28,t29,x29,t30,x30,t31,x31,t32,x32,t33,x33) \ + do { \ + if (T_ACTIVE(t)) { \ + T_LOCAL_DATA \ + T_HEADER(t); \ + T_PUT_##t0(2, x0); \ + T_PUT_##t1(3, x1); \ + T_PUT_##t2(4, x2); \ + T_PUT_##t3(5, x3); \ + T_PUT_##t4(6, x4); \ + T_PUT_##t5(7, x5); \ + T_PUT_##t6(8, x6); \ + T_PUT_##t7(9, x7); \ + T_PUT_##t8(10, x8); \ + T_PUT_##t9(11, x9); \ + T_PUT_##t10(12, x10); \ + T_PUT_##t11(13, x11); \ + T_PUT_##t12(14, x12); \ + T_PUT_##t13(15, x13); \ + T_PUT_##t14(16, x14); \ + T_PUT_##t15(17, x15); \ + T_PUT_##t16(18, x16); \ + T_PUT_##t17(19, x17); \ + T_PUT_##t18(20, x18); \ + T_PUT_##t19(21, x19); \ + T_PUT_##t20(22, x20); \ + T_PUT_##t21(23, x21); \ + T_PUT_##t22(24, x22); \ + T_PUT_##t23(25, x23); \ + T_PUT_##t24(26, x24); \ + T_PUT_##t25(27, x25); \ + T_PUT_##t26(28, x26); \ + T_PUT_##t27(29, x27); \ + T_PUT_##t28(30, x28); \ + T_PUT_##t29(31, x29); \ + T_PUT_##t30(32, x30); \ + T_PUT_##t31(33, x31); \ + T_PUT_##t32(34, x32); \ + T_PUT_##t33(35, x33); \ + T_COMMIT(); \ + } \ + } while (0) + +#define T71(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6,t7,x7,t8,x8,t9,x9,\ + t10,x10,t11,x11,t12,x12,t13,x13,t14,x14,t15,x15,t16,x16,t17,x17,\ + t18,x18,t19,x19,t20,x20,t21,x21,t22,x22,t23,x23,t24,x24,t25,x25,\ + t26,x26,t27,x27,t28,x28,t29,x29,t30,x30,t31,x31,t32,x32,t33,x33,t34,x34) \ + do { \ + if (T_ACTIVE(t)) { \ + T_LOCAL_DATA \ + T_HEADER(t); \ + T_PUT_##t0(2, x0); \ + T_PUT_##t1(3, x1); \ + T_PUT_##t2(4, x2); \ + T_PUT_##t3(5, x3); \ + T_PUT_##t4(6, x4); \ + T_PUT_##t5(7, x5); \ + T_PUT_##t6(8, x6); \ + T_PUT_##t7(9, x7); \ + T_PUT_##t8(10, x8); \ + T_PUT_##t9(11, x9); \ + T_PUT_##t10(12, x10); \ + T_PUT_##t11(13, x11); \ + T_PUT_##t12(14, x12); \ + T_PUT_##t13(15, x13); \ + T_PUT_##t14(16, x14); \ + T_PUT_##t15(17, x15); \ + T_PUT_##t16(18, x16); \ + T_PUT_##t17(19, x17); \ + T_PUT_##t18(20, x18); \ + T_PUT_##t19(21, x19); \ + T_PUT_##t20(22, x20); \ + T_PUT_##t21(23, x21); \ + T_PUT_##t22(24, x22); \ + T_PUT_##t23(25, x23); \ + T_PUT_##t24(26, x24); \ + T_PUT_##t25(27, x25); \ + T_PUT_##t26(28, x26); \ + T_PUT_##t27(29, x27); \ + T_PUT_##t28(30, x28); \ + T_PUT_##t29(31, x29); \ + T_PUT_##t30(32, x30); \ + T_PUT_##t31(33, x31); \ + T_PUT_##t32(34, x32); \ + T_PUT_##t33(35, x33); \ + T_PUT_##t34(36, x34); \ + T_COMMIT(); \ + } \ + } while (0) + + #define T_CALL_ERROR \ do { \ printf("%s:%d:%s: error calling T, you have to use T_INT() or T_XX()\n", \ @@ -645,6 +1274,22 @@ extern int *T_active; #define T34(...) T_CALL_ERROR #define T36(...) T_CALL_ERROR #define T38(...) T_CALL_ERROR +#define T40(...) T_CALL_ERROR +#define T42(...) T_CALL_ERROR +#define T44(...) T_CALL_ERROR +#define T46(...) T_CALL_ERROR +#define T48(...) T_CALL_ERROR +#define T50(...) T_CALL_ERROR +#define T52(...) T_CALL_ERROR +#define T54(...) T_CALL_ERROR +#define T56(...) T_CALL_ERROR +#define T58(...) T_CALL_ERROR +#define T60(...) T_CALL_ERROR +#define T62(...) T_CALL_ERROR +#define T64(...) T_CALL_ERROR +#define T66(...) T_CALL_ERROR +#define T68(...) T_CALL_ERROR +#define T70(...) T_CALL_ERROR /* special cases for VCD logs */ diff --git a/common/utils/T/tracer/event.h b/common/utils/T/tracer/event.h index e3d7637bf4..594cf94d09 100644 --- a/common/utils/T/tracer/event.h +++ b/common/utils/T/tracer/event.h @@ -8,7 +8,7 @@ #endif /* maximum number of arguments for the T macro */ -#define T_MAX_ARGS 32 +#define T_MAX_ARGS 72 enum event_arg_type { EVENT_INT, From e85b38c5c582022f84e4ec8d313b2766a15f7cd2 Mon Sep 17 00:00:00 2001 From: Abdo-Gaber Date: Mon, 10 Mar 2025 10:44:18 +0100 Subject: [PATCH 251/964] Add new trace messages on UE and gNB GNB_PHY_UL_FD_PUSCH_IQ, GNB_PHY_UL_FD_DMRS, GNB_PHY_UL_FD_CHAN_EST_DMRS_POS, GNB_PHY_UL_PAYLOAD_RX_BITS, UE_PHY_UL_SCRAMBLED_TX_BITS, UE_PHY_UL_PAYLOAD_TX_BITS --- common/utils/T/T_messages.txt | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/common/utils/T/T_messages.txt b/common/utils/T/T_messages.txt index 0f306501f0..813226ec14 100644 --- a/common/utils/T/T_messages.txt +++ b/common/utils/T/T_messages.txt @@ -111,6 +111,26 @@ ID = GNB_PHY_PUCCH_PUSCH_IQ DESC = gNodeB input data in the frequency domain for a slot where some PUCCH or PUSCH detection was done GROUP = ALL:PHY:GRAPHIC:HEAVY:GNB FORMAT = int,frame : int,slot : buffer,rxdataF +ID = GNB_PHY_UL_FD_PUSCH_IQ + DESC = gNodeB UL PUSCH IQ Data in the frequency domain + GROUP = ALL:PHY:GRAPHIC:HEAVY:GNB + FORMAT = int,frame : int,slot : int,datetime_yyyymmdd : int,datetime_hhmmssmmm : int,frame_type : int,freq_range : int,subcarrier_spacing : int,cyclic_prefix : int,symbols_per_slot : int,Nid_cell : int,rnti : int,rb_size : int,rb_start : int,start_symbol_index : int,nr_of_symbols : int,qam_mod_order : int,mcs_index : int,mcs_table : int,nrOfLayers : int,transform_precoding : int,dmrs_config_type : int,ul_dmrs_symb_pos : int,number_dmrs_symbols : int,dmrs_port : int,dmrs_nscid : int,nb_antennas_rx : int,number_of_bits : buffer,data +ID = GNB_PHY_UL_FD_DMRS + DESC = gNodeB UL DMRS Signal in the frequency domain + GROUP = ALL:PHY:GRAPHIC:HEAVY:GNB + FORMAT = int,frame : int,slot : int,datetime_yyyymmdd : int,datetime_hhmmssmmm : int,frame_type : int,freq_range : int,subcarrier_spacing : int,cyclic_prefix : int,symbols_per_slot : int,Nid_cell : int,rnti : int,rb_size : int,rb_start : int,start_symbol_index : int,nr_of_symbols : int,qam_mod_order : int,mcs_index : int,mcs_table : int,nrOfLayers : int,transform_precoding : int,dmrs_config_type : int,ul_dmrs_symb_pos : int,number_dmrs_symbols : int,dmrs_port : int,dmrs_nscid : int,nb_antennas_rx : int,number_of_bits : buffer,data +ID = GNB_PHY_UL_FD_CHAN_EST_DMRS_POS + DESC = gNodeB channel estimation in the frequency domain based on DMRS and at DMRS pilots location without any further interploation. + GROUP = ALL:PHY:GRAPHIC:HEAVY:GNB + FORMAT = int,frame : int,slot : int,datetime_yyyymmdd : int,datetime_hhmmssmmm : int,frame_type : int,freq_range : int,subcarrier_spacing : int,cyclic_prefix : int,symbols_per_slot : int,Nid_cell : int,rnti : int,rb_size : int,rb_start : int,start_symbol_index : int,nr_of_symbols : int,qam_mod_order : int,mcs_index : int,mcs_table : int,nrOfLayers : int,transform_precoding : int,dmrs_config_type : int,ul_dmrs_symb_pos : int,number_dmrs_symbols : int,dmrs_port : int,dmrs_nscid : int,nb_antennas_rx : int,number_of_bits : buffer,data +ID = GNB_PHY_UL_FD_CHAN_EST_DMRS_INTERPL + DESC = gNodeB channel estimation in the frequency domain based on DMRS and interploation. + GROUP = ALL:PHY:GRAPHIC:HEAVY:GNB + FORMAT = int,frame : int,slot : int,datetime_yyyymmdd : int,datetime_hhmmssmmm : int,frame_type : int,freq_range : int,subcarrier_spacing : int,cyclic_prefix : int,symbols_per_slot : int,Nid_cell : int,rnti : int,rb_size : int,rb_start : int,start_symbol_index : int,nr_of_symbols : int,qam_mod_order : int,mcs_index : int,mcs_table : int,nrOfLayers : int,transform_precoding : int,dmrs_config_type : int,ul_dmrs_symb_pos : int,number_dmrs_symbols : int,dmrs_port : int,dmrs_nscid : int,nb_antennas_rx : int,number_of_bits : buffer,dataI +ID = GNB_PHY_UL_PAYLOAD_RX_BITS + DESC = gNodeB slot payload after decoder + GROUP = ALL:PHY:GRAPHIC:HEAVY:GNB + FORMAT = int,frame : int,slot : int,datetime_yyyymmdd : int,datetime_hhmmssmmm : int,frame_type : int,freq_range : int,subcarrier_spacing : int,cyclic_prefix : int,symbols_per_slot : int,Nid_cell : int,rnti : int,rb_size : int,rb_start : int,start_symbol_index : int,nr_of_symbols : int,qam_mod_order : int,mcs_index : int,mcs_table : int,nrOfLayers : int,transform_precoding : int,dmrs_config_type : int,ul_dmrs_symb_pos : int,number_dmrs_symbols : int,dmrs_port : int,dmrs_nscid : int,nb_antennas_rx : int,number_of_bits : buffer,data ID = GNB_PHY_UL_FREQ_CHANNEL_ESTIMATE DESC = gNodeB channel estimation in the frequency domain GROUP = ALL:PHY:GRAPHIC:HEAVY:GNB @@ -1352,6 +1372,14 @@ ID = UE_PHY_MEAS DESC = UE PHY measurements GROUP = ALL:PHY:GRAPHIC:HEAVY:UE FORMAT = int,eNB_ID : int,frame : int,subframe : int,rsrp : int,rssi : int,snr: int,rx_power: int,noise_power: int,w_cqi: int,freq_offset +ID = UE_PHY_UL_PAYLOAD_TX_BITS + DESC = UE UL Tx bits in one slot before decoder and scrambler + GROUP = ALL:PHY:GRAPHIC:HEAVY:UE + FORMAT = int,frame : int,slot : int,datetime_yyyymmdd : int,datetime_hhmmssmmm : int,frame_type : int,freq_range : int,subcarrier_spacing : int,cyclic_prefix : int,symbols_per_slot : int,Nid_cell : int,rnti : int,rb_size : int,rb_start : int,start_symbol_index : int,nr_of_symbols : int,qam_mod_order : int,mcs_index : int,mcs_table : int,nrOfLayers : int,transform_precoding : int,dmrs_config_type : int,ul_dmrs_symb_pos : int,number_dmrs_symbols : int,dmrs_port : int,dmrs_nscid : int,nb_antennas_tx : int,number_of_bits : buffer,data +ID = UE_PHY_UL_SCRAMBLED_TX_BITS + DESC = UE UL Tx bits in one slot after scrambler + GROUP = ALL:PHY:GRAPHIC:HEAVY:UE + FORMAT = int,frame : int,slot : int,datetime_yyyymmdd : int,datetime_hhmmssmmm : int,frame_type : int,freq_range : int,subcarrier_spacing : int,cyclic_prefix : int,symbols_per_slot : int,Nid_cell : int,rnti : int,rb_size : int,rb_start : int,start_symbol_index : int,nr_of_symbols : int,qam_mod_order : int,mcs_index : int,mcs_table : int,nrOfLayers : int,transform_precoding : int,dmrs_config_type : int,ul_dmrs_symb_pos : int,number_dmrs_symbols : int,dmrs_port : int,dmrs_nscid : int,nb_antennas_tx : int,number_of_bits : buffer,data #for debug/test - not used ID = first From a942e7e5abc66177099876191048363a58889674 Mon Sep 17 00:00:00 2001 From: Abdo-Gaber Date: Mon, 10 Mar 2025 10:50:40 +0100 Subject: [PATCH 252/964] Add log tools to get and process UTC Time during data tracing --- CMakeLists.txt | 1 + openair1/PHY/log_tools.c | 83 ++++++++++++++++++++++++++++++++++++++++ openair1/PHY/log_tools.h | 43 +++++++++++++++++++++ 3 files changed, 127 insertions(+) create mode 100644 openair1/PHY/log_tools.c create mode 100644 openair1/PHY/log_tools.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 99c537dc22..0091626ce4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -848,6 +848,7 @@ set(PHY_SRC_COMMON ${OPENAIR1_DIR}/PHY/TOOLS/sqrt.c ${OPENAIR1_DIR}/PHY/TOOLS/get_sin_cos.c ${OPENAIR1_DIR}/PHY/TOOLS/oai_arith_operations.c + ${OPENAIR1_DIR}/PHY/log_tools.c ) set(PHY_SRC diff --git a/openair1/PHY/log_tools.c b/openair1/PHY/log_tools.c new file mode 100644 index 0000000000..9d75296dc2 --- /dev/null +++ b/openair1/PHY/log_tools.c @@ -0,0 +1,83 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file openair1/PHY/log_tools.c + * \brief log tools used by data recording application (to be merged to existing OAI log tools) + * \author Abdo Gaber + * \date 2024 + * \version 1.0 + * \company Emerson, NI Test and Measurement + * \email: + * \note + * \warning + */ + +#include "log_tools.h" +#include +#include +#include +#include +#include +#include +#include "PHY/TOOLS/tools_defs.h" + +// Get Time Stamp in microseconds in YYYYMMDDHHMMSSmmmuuu format +char* get_time_stamp_usec(char time_stamp_str[]) +{ + // initialization to measure time stamp --This part should be moved to inilization part + time_t my_time; + struct tm* timeinfo; + time(&my_time); + struct timeval tv; + + // get time stamp + timeinfo = localtime(&my_time); + gettimeofday(&tv, NULL); + // Add time stamp: yyyy mm dd hh mm ss msec + uint16_t year = timeinfo->tm_year + 1900; + uint8_t mon = timeinfo->tm_mon + 1; + uint8_t mday = timeinfo->tm_mday; + uint8_t hour = timeinfo->tm_hour; + uint8_t min = timeinfo->tm_min; + uint8_t sec = timeinfo->tm_sec; + uint16_t usec = (tv.tv_usec); + // printf ("Time stamp: %d_%d_%d_%d_%d_%d_%d \n",year,mon,mday,hour,min,sec,usec); + // sprintf(time_stamp_str, "%d_%d_%d_%d_%d_%d_%d",year,mon,mday,hour,min,sec,usec); + sprintf(time_stamp_str, "%04d%02d%02d%02d%02d%02d%06d", year, mon, mday, hour, min, sec, usec); + + return time_stamp_str; +} + +// Function to convert timestamp string to integer +int convert_time_stamp_to_int(const char* timestamp) +{ + return atoi(timestamp); +} + +int split_time_stamp_and_convert_to_int(char time_stamp_str[], int shift, int length) +{ + char time_part[length + 1]; // Buffer to hold the date part YYYYMMDD or HHMMSSmmm + // Copy the first 8 or 9 characters (YYYYMMDD) to HHMMSSmmm + strncpy(time_part, time_stamp_str + shift, length); + time_part[length] = '\0'; // Null-terminate the string + // Convert timestamp string to integer + return convert_time_stamp_to_int(time_part); +} \ No newline at end of file diff --git a/openair1/PHY/log_tools.h b/openair1/PHY/log_tools.h new file mode 100644 index 0000000000..e75ae05233 --- /dev/null +++ b/openair1/PHY/log_tools.h @@ -0,0 +1,43 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file openair1/PHY/log_tools.h + * \brief log tools used by data recording application (to be merged to existing OAI log tools) + * \author Abdo Gaber + * \date 2024 + * \version 1.0 + * \company Emerson, NI Test and Measurement + * \email: + * \note + * \warning + */ + +#ifndef __PHY_LOG_TOOLS_H__ +#define __PHY_LOG_TOOLS_H__ + +#include +#include "PHY/TOOLS/tools_defs.h" + +char* get_time_stamp_usec(char time_stamp_str[]); +int convert_time_stamp_to_int(const char* timestamp); +int split_time_stamp_and_convert_to_int(char time_stamp_str[], int shift, int length); + +#endif /*__PHY_LOG_TOOLS_H__ */ \ No newline at end of file From 693dfb9374e591a1dfff6f13351f42e2ee5ac803 Mon Sep 17 00:00:00 2001 From: Marius Tillner Date: Tue, 22 Jul 2025 15:51:01 +0200 Subject: [PATCH 253/964] bugfix: avoid segmentation fault when Redcap tries to connect to gNB as NR_ServingCellConfig_t scd is NULL when Redcap does RA --- openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c index ad22b9dd63..c7fc724747 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c @@ -3503,7 +3503,8 @@ static bool verify_radio_configuration(int uid, const NR_ServingCellConfigCommon return false; } - int n_dl_bwp = scd->downlinkBWP_ToAddModList ? scd->downlinkBWP_ToAddModList->list.count : 1; + /* for RedCap, scd is NULL */ + int n_dl_bwp = scd && scd->downlinkBWP_ToAddModList ? scd->downlinkBWP_ToAddModList->list.count : 1; int csi_offset = fs->numb_slots_period * n_dl_bwp; // see set_csirs_periodicity if (csi_offset / 320 >= get_full_dl_slots_per_period(fs)) { From 3c03e18c23c687de9f60650d754929a270579d3e Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Mon, 21 Jul 2025 15:40:33 +0200 Subject: [PATCH 254/964] CI: move RFSim 4G to acamas --- .../xml_files/container_4g_rfsim_fdd_05MHz.xml | 18 +++++++++--------- .../container_4g_rfsim_fdd_05MHz_noS1.xml | 16 ++++++++-------- .../xml_files/container_4g_rfsim_fdd_10MHz.xml | 18 +++++++++--------- .../xml_files/container_4g_rfsim_fdd_20MHz.xml | 18 +++++++++--------- .../xml_files/container_4g_rfsim_fembms.xml | 4 ++-- .../xml_files/container_4g_rfsim_mbms.xml | 4 ++-- .../xml_files/container_4g_rfsim_tdd_05MHz.xml | 16 ++++++++-------- doc/TESTBenches.md | 5 +++-- 8 files changed, 50 insertions(+), 49 deletions(-) diff --git a/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz.xml b/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz.xml index aa80d4b5dc..235546928a 100644 --- a/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz.xml +++ b/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz.xml @@ -108,16 +108,16 @@ Attach_UE Attach OAI UE (Wait for IP) rfsim4g_ue - cacofonix + acamas Ping Ping Traffic-Gen from LTE-UE rfsim4g_ue - cacofonix + acamas rfsim4g_ext_dn - cacofonix + acamas -c 20 5 @@ -126,9 +126,9 @@ Ping Ping LTE-UE from Traffic-Gen rfsim4g_ext_dn - cacofonix + acamas rfsim4g_ue - cacofonix + acamas -c 20 5 @@ -141,8 +141,8 @@ -u -t 30 -b 2M -R 25 80 - cacofonix - cacofonix + acamas + acamas @@ -153,8 +153,8 @@ -u -t 30 -b 1M 25 80 - cacofonix - cacofonix + acamas + acamas diff --git a/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz_noS1.xml b/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz_noS1.xml index bfcade47ab..9b27ba1f8c 100644 --- a/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz_noS1.xml +++ b/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz_noS1.xml @@ -86,9 +86,9 @@ Ping Ping Traffic-Gen from LTE-UE rfsim4g_ue - cacofonix + acamas rfsim4g_enb_nos1 - cacofonix + acamas -c 20 5 @@ -97,9 +97,9 @@ Ping Ping LTE-UE from eNB rfsim4g_enb_nos1 - cacofonix + acamas rfsim4g_ue - cacofonix + acamas -c 20 5 @@ -108,9 +108,9 @@ Iperf Iperf UDP DL rfsim4g_ue - cacofonix + acamas rfsim4g_enb_nos1 - cacofonix + acamas -u -t 30 -b 2M -R 25 80 @@ -120,9 +120,9 @@ Iperf Iperf UDP UL rfsim4g_ue - cacofonix + acamas rfsim4g_enb_nos1 - cacofonix + acamas -u -t 30 -b 1M 25 80 diff --git a/ci-scripts/xml_files/container_4g_rfsim_fdd_10MHz.xml b/ci-scripts/xml_files/container_4g_rfsim_fdd_10MHz.xml index 0cf4944a6c..2b8141a71d 100644 --- a/ci-scripts/xml_files/container_4g_rfsim_fdd_10MHz.xml +++ b/ci-scripts/xml_files/container_4g_rfsim_fdd_10MHz.xml @@ -108,16 +108,16 @@ Attach_UE Attach OAI UE (Wait for IP) rfsim4g_ue - cacofonix + acamas Ping Ping Traffic-Gen from LTE-UE rfsim4g_ue - cacofonix + acamas rfsim4g_ext_dn - cacofonix + acamas -c 20 5 @@ -126,9 +126,9 @@ Ping Ping LTE-UE from Traffic-Gen rfsim4g_ext_dn - cacofonix + acamas rfsim4g_ue - cacofonix + acamas -c 20 5 @@ -137,9 +137,9 @@ Iperf Iperf UDP DL rfsim4g_ue - cacofonix + acamas rfsim4g_ext_dn - cacofonix + acamas -u -t 30 -b 2M -R 25 80 @@ -149,9 +149,9 @@ Iperf Iperf UDP UL rfsim4g_ue - cacofonix + acamas rfsim4g_ext_dn - cacofonix + acamas -u -t 30 -b 1M 25 80 diff --git a/ci-scripts/xml_files/container_4g_rfsim_fdd_20MHz.xml b/ci-scripts/xml_files/container_4g_rfsim_fdd_20MHz.xml index 069db0c585..7afcc2f7c1 100644 --- a/ci-scripts/xml_files/container_4g_rfsim_fdd_20MHz.xml +++ b/ci-scripts/xml_files/container_4g_rfsim_fdd_20MHz.xml @@ -108,16 +108,16 @@ Attach_UE Attach OAI UE (Wait for IP) rfsim4g_ue - cacofonix + acamas Ping Ping Traffic-Gen from LTE-UE rfsim4g_ue - cacofonix + acamas rfsim4g_ext_dn - cacofonix + acamas -c 20 5 @@ -126,9 +126,9 @@ Ping Ping LTE-UE from Traffic-Gen rfsim4g_ext_dn - cacofonix + acamas rfsim4g_ue - cacofonix + acamas -c 20 5 @@ -137,9 +137,9 @@ Iperf Iperf UDP DL rfsim4g_ue - cacofonix + acamas rfsim4g_ext_dn - cacofonix + acamas -u -t 30 -b 2M -R 25 80 @@ -149,9 +149,9 @@ Iperf Iperf UDP UL rfsim4g_ue - cacofonix + acamas rfsim4g_ext_dn - cacofonix + acamas -u -t 30 -b 1M 25 80 diff --git a/ci-scripts/xml_files/container_4g_rfsim_fembms.xml b/ci-scripts/xml_files/container_4g_rfsim_fembms.xml index c030fbb4a4..1f869ecdde 100644 --- a/ci-scripts/xml_files/container_4g_rfsim_fembms.xml +++ b/ci-scripts/xml_files/container_4g_rfsim_fembms.xml @@ -83,9 +83,9 @@ Iperf2_Unidir Iperf2 UDP DL rfsim4g_ue_fembms - cacofonix + acamas rfsim4g_enb_fembms - cacofonix + acamas -u -t 30 -b 2M 25 80 diff --git a/ci-scripts/xml_files/container_4g_rfsim_mbms.xml b/ci-scripts/xml_files/container_4g_rfsim_mbms.xml index 34c2fc6c89..4c3691e466 100644 --- a/ci-scripts/xml_files/container_4g_rfsim_mbms.xml +++ b/ci-scripts/xml_files/container_4g_rfsim_mbms.xml @@ -83,9 +83,9 @@ Iperf Iperf UDP DL rfsim4g_ue - cacofonix + acamas rfsim4g_enb_nos1 - cacofonix + acamas -u -t 30 -b 2M -R 25 80 diff --git a/ci-scripts/xml_files/container_4g_rfsim_tdd_05MHz.xml b/ci-scripts/xml_files/container_4g_rfsim_tdd_05MHz.xml index df44214af9..f84269b16e 100644 --- a/ci-scripts/xml_files/container_4g_rfsim_tdd_05MHz.xml +++ b/ci-scripts/xml_files/container_4g_rfsim_tdd_05MHz.xml @@ -108,9 +108,9 @@ Ping Ping Traffic-Gen from LTE-UE rfsim4g_ue - cacofonix + acamas rfsim4g_ext_dn - cacofonix + acamas -c 20 5 @@ -119,9 +119,9 @@ Ping Ping LTE-UE from Traffic-Gen rfsim4g_ext_dn - cacofonix + acamas rfsim4g_ue - cacofonix + acamas -c 20 5 @@ -130,9 +130,9 @@ Iperf Iperf UDP DL rfsim4g_ue - cacofonix + acamas rfsim4g_ext_dn - cacofonix + acamas -u -t 30 -b 2M -R 25 80 @@ -142,9 +142,9 @@ Iperf Iperf UDP UL rfsim4g_ue - cacofonix + acamas rfsim4g_ext_dn - cacofonix + acamas -u -t 30 -b 1M 25 80 diff --git a/doc/TESTBenches.md b/doc/TESTBenches.md index 53d54e45ec..2e0a26b2f9 100644 --- a/doc/TESTBenches.md +++ b/doc/TESTBenches.md @@ -23,6 +23,7 @@ | matix | Matix | gNB (n77) | N310 | | gracehopper1-oai | Gracehopper1 | gNB (n78, PNF/Nvidia CUBB + VNF) | Foxconn RU, _Nvidia Aerial integration_ | | gracehopper3-oai | Gracehopper3 | build | -- | +| acamas | Acamas | 4G and 5G rfsimulator| -- | Note: The available resources, and their current usage, is indicated here: - [Lockable resources of jenkins-oai](https://jenkins-oai.eurecom.fr/lockable-resources/): @@ -178,11 +179,11 @@ information on how the images are built. - see [`./physical-simulators.md`](./physical-simulators.md) for an overview - [RAN-RF-Sim-Test-4G](https://jenkins-oai.eurecom.fr/job/RAN-RF-Sim-Test-4G/) ~4G-LTE - - cacofonix (eNB, lteUE, OAI EPC) + - acamas (eNB, lteUE, OAI EPC) - uses RFsimulator, for FDD 5, 10, 20MHz with core, 5MHz noS1 - [RAN-RF-Sim-Test-5G](https://jenkins-oai.eurecom.fr/job/RAN-RF-Sim-Test-5G/) ~5G-NR ~nrUE - - cacofonix (gNB, nrUE, OAI 5GC) + - acamas (gNB, nrUE, OAI 5GC) - uses RFsimulator, TDD 40MHz, FDD 40MHz, F1 split - [RAN-SA-AW2S-CN5G](https://jenkins-oai.eurecom.fr/job/RAN-SA-AW2S-CN5G/) ~5G-NR From c5bc949a9685bd05d727d969ac646f43deb1e7c0 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Tue, 22 Jul 2025 14:45:12 +0200 Subject: [PATCH 255/964] rfsimulator: fix model name for channel bridge->nb_cnx++ is done before calling snprintf(modelname,... in the function, so we take the model name of the next channel. This commit corrects the issue by using bridge->nb_cnx - 1, ensuring that the model name corresponds to the currently connected client. This bug was introduced by MR !3455. Co-authored-by: Bartosz Podrygajlo Co-authored-by: Laurent THOMAS --- radio/rfsimulator/simulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radio/rfsimulator/simulator.c b/radio/rfsimulator/simulator.c index ca28dd2e79..c60192bc93 100644 --- a/radio/rfsimulator/simulator.c +++ b/radio/rfsimulator/simulator.c @@ -218,7 +218,7 @@ static buffer_t *allocCirBuf(rfsimulator_state_t *bridge, int sock) sizeofArray(modelname), "rfsimu_channel_%s%d", (bridge->role == SIMU_ROLE_SERVER) ? "ue" : "enB", - bridge->nb_cnx); + bridge->nb_cnx - 1); ptr->channel_model = find_channel_desc_fromname(modelname); // path_loss in dB if (!ptr->channel_model) { // Use legacy method to find channel model - this will use the same channel model for all clients From 8caf326134b2f1adcda22e8ed467fbdeadea63d4 Mon Sep 17 00:00:00 2001 From: Abdo-Gaber Date: Mon, 10 Mar 2025 12:24:20 +0100 Subject: [PATCH 256/964] Add traces on gNB PHY UL and related requirement: FD PUSH IQ, FD DMRS, and UL Channel estimates wi/wo interpolation - The required memories have been created and initialized in: openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c - Those memories: memory for DMRS signals, memory for channel estimates based on DMRS positions, memory to store slot grid with channel coefficients based on DMRS positions after interpolation, and memory to store extracted data including PUSCH + DMRS. - The input parameters to nr_pusch_channel_estimation() has been updated to get the pointer to the added memories of pusch_dmrs_slot_mem and pusch_ch_est_dmrs_pos_slot_mem (openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h) - The DMRS grid of NR slot and the estimated channel coefficients at DMRS locations are logged to created memories in: openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c - The function inner_rx in openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c is updated to log the extracted ULSCH PRBs and the interpolated channel coefficients. - The T-macro() has been called in (openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c) to trace added traces: T_GNB_PHY_UL_FD_DMRS, T_GNB_PHY_UL_FD_CHAN_EST_DMRS_POS, T_GNB_PHY_UL_FD_PUSCH_IQ, T_GNB_PHY_UL_FD_CHAN_EST_DMRS_INTERPL --- .../NR_ESTIMATION/nr_ul_channel_estimation.c | 36 ++- openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h | 4 +- .../PHY/NR_TRANSPORT/nr_ulsch_demodulation.c | 253 +++++++++++++++++- 3 files changed, 288 insertions(+), 5 deletions(-) diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c index 728e59e510..383140ba88 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c @@ -64,6 +64,8 @@ typedef struct puschAntennaProc_s { c16_t ***rxdataF; task_ans_t *ans; scopeData_t *scope; + c16_t *pusch_ch_est_dmrs_pos_slot_mem; + int dmrs_symbol_start_idx; } puschAntennaProc_t; __attribute__((always_inline)) inline c16_t c32x16cumulVectVectWithSteps(c16_t *in1, @@ -149,6 +151,9 @@ static void nr_pusch_antenna_processing(void *arg) int re_offset = k0; LOG_D(PHY, "PUSCH estimation DMRS type 1, Freq-domain interpolation"); int pilot_cnt = 0; +#if T_TRACER + int ch_est_cnt = 0; // To trace channel coefficients +#endif for (int n = 0; n < 3 * nb_rb_pusch; n++) { // LS estimation @@ -165,6 +170,17 @@ static void nr_pusch_antenna_processing(void *arg) for (int k = pilot_cnt << 1; k < (pilot_cnt << 1) + 4; k++) { ul_ls_est[k] = ch16; } +//------------------Write channel parameters to Memory for data recording ------------------// +#if T_TRACER + if (T_ACTIVE(T_GNB_PHY_UL_FD_CHAN_EST_DMRS_POS)) { + // Trace channel coefficients + c16_t *pusch_ch_est_dmrs_pos_slot_mem = rdata->pusch_ch_est_dmrs_pos_slot_mem; + int dmrs_symbol_start_idx = rdata->dmrs_symbol_start_idx; + pusch_ch_est_dmrs_pos_slot_mem[dmrs_symbol_start_idx + delta + ch_est_cnt] = ch16; // 0, 2, 4, 6, 8, location of REs + pusch_ch_est_dmrs_pos_slot_mem[dmrs_symbol_start_idx + delta + ch_est_cnt + 2] = ch16; // 0, 2, 4, 6, 8, location of REs + } + ch_est_cnt += 4; +#endif pilot_cnt += 2; } c16_t ch_estimates_time[frame_parms->ofdm_symbol_size] __attribute__((aligned(32))); @@ -459,7 +475,9 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, unsigned short bwp_start_subcarrier, nfapi_nr_pusch_pdu_t *pusch_pdu, int *max_ch, - uint32_t *nvar) + uint32_t *nvar, + c16_t *pusch_dmrs_slot_mem, + c16_t *pusch_ch_est_dmrs_pos_slot_mem) { c16_t pilot[3280] __attribute__((aligned(32))); @@ -519,6 +537,20 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, LOG_I(PHY, "In %s: %d + j*(%d)\n", __FUNCTION__, pilot[i].r, pilot[i].i); } +#endif + + //------------------Write DMRS to Memory for Data Recording ------------------// + int dmrs_symbol_start_idx = symbol * pusch_pdu->nrOfLayers * nb_rb_pusch * NR_NB_SC_PER_RB + nl * nb_rb_pusch * NR_NB_SC_PER_RB; +#if T_TRACER + if (T_ACTIVE(T_GNB_PHY_UL_FD_DMRS)) { + // used by T-Tracer to trace DMRS slot grid + int dmrs_delta = 0; // intialize it to zero currently, derive it later from above functions + for (int i = 0; i < (6 * nb_rb_pusch); i++) { + // the generated DMRs is a complex conjugate of mod table, so flip the sign of imag. part + pusch_dmrs_slot_mem[dmrs_symbol_start_idx + dmrs_delta + i * 2].r = pilot[i].r; // 0, 2, 4, 6, 8, location of REs + pusch_dmrs_slot_mem[dmrs_symbol_start_idx + dmrs_delta + i * 2].i = -pilot[i].i; // 0, 2, 4, 6, 8, location of REs + } + } #endif int nest_count = 0; @@ -573,6 +605,8 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, rdata->rxdataF = gNB->common_vars.rxdataF; rdata->scope = gNB->scopeData; rdata->ans = &ans; + rdata->pusch_ch_est_dmrs_pos_slot_mem = pusch_ch_est_dmrs_pos_slot_mem; + rdata->dmrs_symbol_start_idx = dmrs_symbol_start_idx; // Call the nr_pusch_antenna_processing function if (job_id == num_jobs - 1) { // Run the last job inline diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h index 483e1ea090..cde3e9c89d 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h @@ -51,7 +51,9 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, unsigned short bwp_start_subcarrier, nfapi_nr_pusch_pdu_t *pusch_pdu, int *max_ch, - uint32_t *nvar); + uint32_t *nvar, + c16_t *pusch_dmrs_slot_mem, + c16_t *pusch_ch_est_dmrs_pos_slot_mem); void dump_nr_I0_stats(FILE *fd,PHY_VARS_gNB *gNB); diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c index 1729c8c8c4..c834c3a014 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c @@ -10,9 +10,19 @@ #include "common/utils/nr/nr_common.h" #include #include "PHY/sse_intrin.h" +#include "T.h" +#include +#include "PHY/log_tools.h" #define INVALID_VALUE 255 +#if T_TRACER +static void copy_c16_data_to_slot_memory(c16_t *src, c16_t *dst_slot, int nb_re_pusch, int symbol) +{ + memcpy(&dst_slot[nb_re_pusch * symbol], src, nb_re_pusch * sizeof(c16_t)); +} +#endif + void nr_idft(int32_t *z, uint32_t Msc_PUSCH) { @@ -928,7 +938,9 @@ static void inner_rx(PHY_VARS_gNB *gNB, int length, int symbol, int output_shift, - uint32_t nvar) + uint32_t nvar, + c16_t *rxFext_slot, + c16_t *chFext_slot) { int nb_layer = rel15_ul->nrOfLayers; int nb_rx_ant = frame_parms->nb_antennas_rx; @@ -959,6 +971,16 @@ static void inner_rx(PHY_VARS_gNB *gNB, dmrs_symbol_flag, rel15_ul, frame_parms); +#if T_TRACER + int nb_re_pusch = NR_NB_SC_PER_RB * rel15_ul->rb_size; + // Assume assume Tx and Rx = 1 + if (T_ACTIVE(T_GNB_PHY_UL_FD_PUSCH_IQ)) { + copy_c16_data_to_slot_memory(rxFext[aarx], rxFext_slot, nb_re_pusch, symbol); + } + if (T_ACTIVE(T_GNB_PHY_UL_FD_CHAN_EST_DMRS_INTERPL)) { + copy_c16_data_to_slot_memory(chFext[aatx][aarx], chFext_slot, nb_re_pusch, symbol); + } +#endif } } c16_t rho[nb_layer][nb_layer][buffer_length] __attribute__((aligned(32))); @@ -1067,6 +1089,8 @@ typedef struct puschSymbolProc_s { uint32_t nvar; int beam_nb; task_ans_t *ans; + c16_t *pusch_ch_est_dmrs_interpl_slot_mem; + c16_t *rxFext_slot_mem; } puschSymbolProc_t; static void nr_pusch_symbol_processing(void *arg) @@ -1102,7 +1126,9 @@ static void nr_pusch_symbol_processing(void *arg) gNB->pusch_vars[ulsch_id].ul_valid_re_per_slot[symbol], symbol, gNB->pusch_vars[ulsch_id].log2_maxh, - rdata->nvar); + rdata->nvar, + rdata->rxFext_slot_mem, + rdata->pusch_ch_est_dmrs_interpl_slot_mem); int nb_re_pusch = gNB->pusch_vars[ulsch_id].ul_valid_re_per_slot[symbol]; // layer de-mapping @@ -1165,6 +1191,38 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, LOG_D(PHY,"pusch %d.%d : bwp_start_subcarrier %d, rb_start %d, first_carrier_offset %d\n", frame,slot,bwp_start_subcarrier, rel15_ul->rb_start, frame_parms->first_carrier_offset); LOG_D(PHY,"pusch %d.%d : ul_dmrs_symb_pos %x\n",frame,slot,rel15_ul->ul_dmrs_symb_pos); + // Memories to store data for data recording + int buffer_length_slot = rel15_ul->rb_size * NR_NB_SC_PER_RB * 14; // 14 OFDM Symbols per slot + int nb_rx_ant = frame_parms->nb_antennas_rx; + int nb_layer = rel15_ul->nrOfLayers; + + // Initialize memory for DMRS signals + c16_t pusch_dmrs_slot_mem[nb_layer * buffer_length_slot] __attribute__((aligned(32))); + // Initialize memory for channel estimates based on DMRS positions + c16_t pusch_ch_est_dmrs_pos_slot_mem[buffer_length_slot * nb_layer * nb_rx_ant] __attribute__((aligned(32))); + // memory to store slot grid with channel coefficients based on DMRS positions after interpolation + c16_t pusch_ch_est_dmrs_interpl_slot_mem[buffer_length_slot * nb_layer * nb_rx_ant] __attribute__((aligned(32))); + // memory to store extracted data including PUSCH + DMRS + c16_t rxFext_slot_mem[nb_rx_ant * buffer_length_slot] __attribute__((aligned(32))); + +#if T_TRACER + // Initialize memory for DMRS signals + if (T_ACTIVE(T_GNB_PHY_UL_FD_DMRS)) + memset(pusch_dmrs_slot_mem, 0, sizeof(c16_t) * nb_layer * buffer_length_slot); + + // Initialize memory for channel estimates based on DMRS positions + if (T_ACTIVE(T_GNB_PHY_UL_FD_CHAN_EST_DMRS_POS)) + memset(pusch_ch_est_dmrs_pos_slot_mem, 0, sizeof(c16_t) * buffer_length_slot * nb_layer * nb_rx_ant); + + // memory to store slot grid with channel coefficients based on DMRS positions after interpolation + if (T_ACTIVE(T_GNB_PHY_UL_FD_CHAN_EST_DMRS_INTERPL)) + memset(pusch_ch_est_dmrs_interpl_slot_mem, 0, sizeof(c16_t) * buffer_length_slot * nb_layer * nb_rx_ant); + + // memory to store extracted data including PUSCH + DMRS + if (T_ACTIVE(T_GNB_PHY_UL_FD_PUSCH_IQ)) + memset(rxFext_slot_mem, 0, sizeof(c16_t) * buffer_length_slot * nb_rx_ant); +#endif + //---------------------------------------------------------- //------------------- Channel estimation ------------------- //---------------------------------------------------------- @@ -1190,7 +1248,9 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, bwp_start_subcarrier, rel15_ul, &max_ch, - &nvar_tmp); + &nvar_tmp, + pusch_dmrs_slot_mem, + pusch_ch_est_dmrs_pos_slot_mem); nvar += nvar_tmp; } // measure the SNR from the channel estimation @@ -1417,6 +1477,8 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, rdata->scramblingSequence = scramblingSequence; rdata->nvar = nvar; rdata->beam_nb = beam_nb; + rdata->rxFext_slot_mem = rxFext_slot_mem; + rdata->pusch_ch_est_dmrs_interpl_slot_mem = pusch_ch_est_dmrs_interpl_slot_mem; if (rel15_ul->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) { nr_pusch_symbol_processing(rdata); @@ -1431,6 +1493,191 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, } } // symbol loop +#if T_TRACER + // Get Time Stamp for T-tracer messages + char trace_time_stamp_str[30]; + get_time_stamp_usec(trace_time_stamp_str); + // trace_time_stamp_str = 8 bytes timestamp = YYYYMMDD + // + 9 bytes timestamp = HHMMSSMMM + // Not Ready for MIMO + int dmrs_port = get_dmrs_port(0, rel15_ul->dmrs_ports); + if (T_ACTIVE(T_GNB_PHY_UL_FD_DMRS)) { + // Log GNB_PHY_UL_FD_DMRS using T-Tracer if activated + // FORMAT = int,frame : int,slot : int,datetime_yyyymmdd : int,datetime_hhmmssmmm : + // int,frame_type : int,freq_range : int,subcarrier_spacing : int,cyclic_prefix : int,symbols_per_slot : + // int,Nid_cell : int,rnti : + // int,rb_size : int,rb_start : int,start_symbol_index : int,nr_of_symbols : + // int,qam_mod_order : int,mcs_index : int,mcs_table : int,nrOfLayers : + // int,transform_precoding : int,dmrs_config_type : int,ul_dmrs_symb_pos : int,number_dmrs_symbols : int,dmrs_port : + // int,dmrs_nscid : int,nb_antennas_rx : int,number_of_bits : buffer,data + T(T_GNB_PHY_UL_FD_DMRS, + T_INT((int)frame), + T_INT((int)slot), + T_INT((int)split_time_stamp_and_convert_to_int(trace_time_stamp_str, 0, 8)), + T_INT((int)split_time_stamp_and_convert_to_int(trace_time_stamp_str, 8, 9)), + T_INT((int)frame_parms->frame_type), // Frame type (0 FDD, 1 TDD) frame_structure + T_INT((int)frame_parms->freq_range), // Frequency range (0 FR1, 1 FR2) + T_INT((int)rel15_ul->subcarrier_spacing), // Subcarrier spacing (0 15kHz, 1 30kHz, 2 60kHz) + T_INT((int)rel15_ul->cyclic_prefix), // Normal or extended prefix (0 normal, 1 extended) + T_INT((int)frame_parms->symbols_per_slot), // Number of symbols per slot + T_INT((int)frame_parms->Nid_cell), + T_INT((int)rel15_ul->rnti), + T_INT((int)rel15_ul->rb_size), + T_INT((int)rel15_ul->rb_start), + T_INT((int)rel15_ul->start_symbol_index), // start_ofdm_symbol + T_INT((int)rel15_ul->nr_of_symbols), // num_ofdm_symbols + T_INT((int)rel15_ul->qam_mod_order), // modulation + T_INT((int)rel15_ul->mcs_index), // mcs + T_INT((int)rel15_ul->mcs_table), // mcs_table_index + T_INT((int)rel15_ul->nrOfLayers), // num_layer + T_INT((int)rel15_ul->transform_precoding), // transformPrecoder_enabled = 0, transformPrecoder_disabled = 1 + T_INT((int)rel15_ul->dmrs_config_type), // dmrs_resource_map_config: pusch_dmrs_type1 = 0, pusch_dmrs_type2 = 1 + T_INT((int)rel15_ul->ul_dmrs_symb_pos), // used to derive the DMRS symbol positions + T_INT((int)number_dmrs_symbols), + // dmrs_start_ofdm_symbol + // dmrs_duration_num_ofdm_symbols + // dmrs_num_add_positions + T_INT((int)dmrs_port), // dmrs_antenna_port + T_INT((int)rel15_ul->scid), // dmrs_nscid + T_INT((int)frame_parms->nb_antennas_rx), // rx antenna + T_INT(0), // number_of_bits + T_BUFFER((c16_t *)(&(pusch_dmrs_slot_mem[0])), rel15_ul->rb_size * NR_NB_SC_PER_RB * rel15_ul->nr_of_symbols * 4)); + } + + if (T_ACTIVE(T_GNB_PHY_UL_FD_CHAN_EST_DMRS_POS)) { + // Log GNB_PHY_UL_FD_CHAN_EST_DMRS_POS using T-Tracer if activated + // FORMAT = int,frame : int,slot : int,datetime_yyyymmdd : int,datetime_hhmmssmmm : + // int,frame_type : int,freq_range : int,subcarrier_spacing : int,cyclic_prefix : int,symbols_per_slot : + // int,Nid_cell : int,rnti : + // int,rb_size : int,rb_start : int,start_symbol_index : int,nr_of_symbols : + // int,qam_mod_order : int,mcs_index : int,mcs_table : int,nrOfLayers : + // int,transform_precoding : int,dmrs_config_type : int,ul_dmrs_symb_pos : int,number_dmrs_symbols : int,dmrs_port : + // int,dmrs_nscid : int,nb_antennas_rx : int,number_of_bits : buffer,data + T(T_GNB_PHY_UL_FD_CHAN_EST_DMRS_POS, + T_INT((int)frame), + T_INT((int)slot), + T_INT((int)split_time_stamp_and_convert_to_int(trace_time_stamp_str, 0, 8)), + T_INT((int)split_time_stamp_and_convert_to_int(trace_time_stamp_str, 8, 9)), + T_INT((int)frame_parms->frame_type), // Frame type (0 FDD, 1 TDD) frame_structure + T_INT((int)frame_parms->freq_range), // Frequency range (0 FR1, 1 FR2) + T_INT((int)rel15_ul->subcarrier_spacing), // Subcarrier spacing (0 15kHz, 1 30kHz, 2 60kHz) + T_INT((int)rel15_ul->cyclic_prefix), // Normal or extended prefix (0 normal, 1 extended) + T_INT((int)frame_parms->symbols_per_slot), // Number of symbols per slot + T_INT((int)frame_parms->Nid_cell), + T_INT((int)rel15_ul->rnti), + T_INT((int)rel15_ul->rb_size), + T_INT((int)rel15_ul->rb_start), + T_INT((int)rel15_ul->start_symbol_index), // start_ofdm_symbol + T_INT((int)rel15_ul->nr_of_symbols), // num_ofdm_symbols + T_INT((int)rel15_ul->qam_mod_order), // modulation + T_INT((int)rel15_ul->mcs_index), // mcs + T_INT((int)rel15_ul->mcs_table), // mcs_table_index + T_INT((int)rel15_ul->nrOfLayers), // num_layer + T_INT((int)rel15_ul->transform_precoding), // transformPrecoder_enabled = 0, transformPrecoder_disabled = 1 + T_INT((int)rel15_ul->dmrs_config_type), // dmrs_resource_map_config: pusch_dmrs_type1 = 0, pusch_dmrs_type2 = 1 + T_INT((int)rel15_ul->ul_dmrs_symb_pos), // used to derive the DMRS symbol positions + T_INT((int)number_dmrs_symbols), + // dmrs_start_ofdm_symbol + // dmrs_duration_num_ofdm_symbols + // dmrs_num_add_positions + T_INT((int)dmrs_port), // dmrs_antenna_port + T_INT((int)rel15_ul->scid), // dmrs_nscid + T_INT((int)frame_parms->nb_antennas_rx), // rx antenna + T_INT(0), // number_of_bits + T_BUFFER((c16_t *)(&(pusch_ch_est_dmrs_pos_slot_mem[0])), rel15_ul->rb_size * NR_NB_SC_PER_RB * rel15_ul->nr_of_symbols * 4)); + } + + if (T_ACTIVE(T_GNB_PHY_UL_FD_PUSCH_IQ)) { + // Log GNB_PHY_UL_FD_PUSCH_IQ using T-Tracer if activated + // FORMAT = int,frame : int,slot : int,datetime_yyyymmdd : int,datetime_hhmmssmmm : + // int,frame_type : int,freq_range : int,subcarrier_spacing : int,cyclic_prefix : int,symbols_per_slot : + // int,Nid_cell : int,rnti : + // int,rb_size : int,rb_start : int,start_symbol_index : int,nr_of_symbols : + // int,qam_mod_order : int,mcs_index : int,mcs_table : int,nrOfLayers : + // int,transform_precoding : int,dmrs_config_type : int,ul_dmrs_symb_pos : int,number_dmrs_symbols : int,dmrs_port : + // int,dmrs_nscid : int,nb_antennas_rx : int,number_of_bits : buffer,data + + T(T_GNB_PHY_UL_FD_PUSCH_IQ, + T_INT((int)frame), + T_INT((int)slot), + T_INT((int)split_time_stamp_and_convert_to_int(trace_time_stamp_str, 0, 8)), + T_INT((int)split_time_stamp_and_convert_to_int(trace_time_stamp_str, 8, 9)), + T_INT((int)frame_parms->frame_type), // Frame type (0 FDD, 1 TDD) frame_structure + T_INT((int)frame_parms->freq_range), // Frequency range (0 FR1, 1 FR2) + T_INT((int)rel15_ul->subcarrier_spacing), // Subcarrier spacing (0 15kHz, 1 30kHz, 2 60kHz) + T_INT((int)rel15_ul->cyclic_prefix), // Normal or extended prefix (0 normal, 1 extended) + T_INT((int)frame_parms->symbols_per_slot), // Number of symbols per slot + T_INT((int)frame_parms->Nid_cell), + T_INT((int)rel15_ul->rnti), + T_INT((int)rel15_ul->rb_size), + T_INT((int)rel15_ul->rb_start), + T_INT((int)rel15_ul->start_symbol_index), // start_ofdm_symbol + T_INT((int)rel15_ul->nr_of_symbols), // num_ofdm_symbols + T_INT((int)rel15_ul->qam_mod_order), // modulation + T_INT((int)rel15_ul->mcs_index), // mcs + T_INT((int)rel15_ul->mcs_table), // mcs_table_index + T_INT((int)rel15_ul->nrOfLayers), // num_layer + T_INT((int)rel15_ul->transform_precoding), // transformPrecoder_enabled = 0, transformPrecoder_disabled = 1 + T_INT((int)rel15_ul->dmrs_config_type), // dmrs_resource_map_config: pusch_dmrs_type1 = 0, pusch_dmrs_type2 = 1 + T_INT((int)rel15_ul->ul_dmrs_symb_pos), // used to derive the DMRS symbol positions + T_INT((int)number_dmrs_symbols), + // dmrs_start_ofdm_symbol + // dmrs_duration_num_ofdm_symbols + // dmrs_num_add_positions + T_INT((int)dmrs_port), // dmrs_antenna_port + T_INT((int)rel15_ul->scid), // dmrs_nscid + T_INT((int)frame_parms->nb_antennas_rx), // rx antenna + T_INT(0), // number_of_bits + T_BUFFER((c16_t *)(&(rxFext_slot_mem[0])), + rel15_ul->rb_size * NR_NB_SC_PER_RB * rel15_ul->nr_of_symbols * frame_parms->nb_antennas_rx * 4)); + } + if (T_ACTIVE(T_GNB_PHY_UL_FD_CHAN_EST_DMRS_INTERPL)) { + // Log pusch_ch_est_dmrs_interpl_slot_mem using T-Tracer if activated + // FORMAT = int,frame : int,slot : int,datetime_yyyymmdd : int,datetime_hhmmssmmm : + // int,frame_type : int,freq_range : int,subcarrier_spacing : int,cyclic_prefix : int,symbols_per_slot : + // int,Nid_cell : int,rnti : + // int,rb_size : int,rb_start : int,start_symbol_index : int,nr_of_symbols : + // int,qam_mod_order : int,mcs_index : int,mcs_table : int,nrOfLayers : + // int,transform_precoding : int,dmrs_config_type : int,ul_dmrs_symb_pos : int,number_dmrs_symbols : int,dmrs_port : + // int,dmrs_nscid : int,nb_antennas_rx : int,number_of_bits : buffer,data + + T(T_GNB_PHY_UL_FD_CHAN_EST_DMRS_INTERPL, + T_INT((int)frame), + T_INT((int)slot), + T_INT((int)split_time_stamp_and_convert_to_int(trace_time_stamp_str, 0, 8)), + T_INT((int)split_time_stamp_and_convert_to_int(trace_time_stamp_str, 8, 9)), + T_INT((int)frame_parms->frame_type), // Frame type (0 FDD, 1 TDD) frame_structure + T_INT((int)frame_parms->freq_range), // Frequency range (0 FR1, 1 FR2) + T_INT((int)rel15_ul->subcarrier_spacing), // Subcarrier spacing (0 15kHz, 1 30kHz, 2 60kHz) + T_INT((int)rel15_ul->cyclic_prefix), // Normal or extended prefix (0 normal, 1 extended) + T_INT((int)frame_parms->symbols_per_slot), // Number of symbols per slot + T_INT((int)frame_parms->Nid_cell), + T_INT((int)rel15_ul->rnti), + T_INT((int)rel15_ul->rb_size), + T_INT((int)rel15_ul->rb_start), + T_INT((int)rel15_ul->start_symbol_index), // start_ofdm_symbol + T_INT((int)rel15_ul->nr_of_symbols), // num_ofdm_symbols + T_INT((int)rel15_ul->qam_mod_order), // modulation + T_INT((int)rel15_ul->mcs_index), // mcs + T_INT((int)rel15_ul->mcs_table), // mcs_table_index + T_INT((int)rel15_ul->nrOfLayers), // num_layer + T_INT((int)rel15_ul->transform_precoding), // transformPrecoder_enabled = 0, transformPrecoder_disabled = 1 + T_INT((int)rel15_ul->dmrs_config_type), // dmrs_resource_map_config: pusch_dmrs_type1 = 0, pusch_dmrs_type2 = 1 + T_INT((int)rel15_ul->ul_dmrs_symb_pos), // used to derive the DMRS symbol positions + T_INT((int)number_dmrs_symbols), + // dmrs_start_ofdm_symbol + // dmrs_duration_num_ofdm_symbols + // dmrs_num_add_positions + T_INT((int)dmrs_port), // dmrs_antenna_port + T_INT((int)rel15_ul->scid), // dmrs_nscid + T_INT((int)frame_parms->nb_antennas_rx), // rx antenna + T_INT(0), // number_of_bits + T_BUFFER( + (c16_t *)pusch_ch_est_dmrs_interpl_slot_mem, + rel15_ul->rb_size * NR_NB_SC_PER_RB * rel15_ul->nr_of_symbols * frame_parms->nb_antennas_rx * rel15_ul->nrOfLayers * 4)); + } +#endif + join_task_ans(&ans); stop_meas(&gNB->rx_pusch_symbol_processing_stats); From e0c5621d6091b96c936d1e501c673f4afec3d3ea Mon Sep 17 00:00:00 2001 From: Abdo-Gaber Date: Mon, 10 Mar 2025 12:41:51 +0100 Subject: [PATCH 257/964] Add traces on UE PHY UL and related requirement: Tx Scrambled bits and Tx payload bits - Update input parameters to nr_ulsch_encoding () in nr_transport_proto_ue.h to get number_dmrs_symbols to be added to meta-data. - In nr_ulsch_coding.c: Trace UE PHY UL Payload TX bits (T_message: T_UE_PHY_UL_PAYLOAD_TX_BITS) including related meta-data and UTC time. - In nr_ulsch_ue.c: Trace UE PHY UL Scrambled TX bits (T_message: T_UE_PHY_UL_SCRAMBLED_TX_BITS) including related meta-data and UTC time. - Fix the input prameters in nr_ulsch_encoding () called in (openair1/SIMULATION/NR_PHY/ulschsim.c) since a new input parameter has been added. --- .../NR_UE_TRANSPORT/nr_transport_proto_ue.h | 3 +- .../PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c | 56 +++++++++++++++++- openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c | 57 ++++++++++++++++++- openair1/SIMULATION/NR_PHY/ulschsim.c | 2 +- 4 files changed, 114 insertions(+), 4 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h index 8e266a57a3..aebb410187 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h @@ -112,7 +112,8 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, const uint8_t slot, unsigned int *G, int nb_ulsch, - uint8_t *ULSCH_ids); + uint8_t *ULSCH_ids, + uint16_t number_dmrs_symbols); /*! \brief Perform PUSCH scrambling. TS 38.211 V15.4.0 subclause 6.3.1.1 @param[in] in Pointer to input bits diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c index 2eeb27d457..b044d06305 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c @@ -32,6 +32,7 @@ #include "PHY/NR_UE_TRANSPORT/nr_transport_ue.h" #include "executables/nr-uesoftmodem.h" #include "common/utils/LOG/vcd_signal_dumper.h" +#include "PHY/log_tools.h" int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, NR_UE_ULSCH_t *ulsch, @@ -39,7 +40,8 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, const uint8_t slot, unsigned int *G, int nb_ulsch, - uint8_t *ULSCH_ids) + uint8_t *ULSCH_ids, + uint16_t number_dmrs_symbols) { start_meas_nr_ue_phy(ue, ULSCH_ENCODING_STATS); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_UE_ULSCH_ENCODING, VCD_FUNCTION_IN); @@ -108,6 +110,58 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, AssertFatal((A / 8) + 3 <= max_payload_bytes, "A %d is too big (A/8+3 = %d > %d)\n", A, (A / 8) + 3, max_payload_bytes); } +#if T_TRACER + if (T_ACTIVE(T_UE_PHY_UL_PAYLOAD_TX_BITS)) { + // Get Time Stamp for T-tracer messages + char trace_tx_payload_time_stamp_str[30]; + get_time_stamp_usec(trace_tx_payload_time_stamp_str); + // trace_time_stamp_str = 8 bytes timestamp = YYYYMMDD + // + 9 bytes timestamp = HHMMSSMMM + // Log UE_PHY_UL_PAYLOAD_TX_BITS using T-Tracer if activated + // FORMAT = int,frame : int,slot : int,datetime_yyyymmdd : int,datetime_hhmmssmmm : + // int,frame_type : int,freq_range : int,subcarrier_spacing : int,cyclic_prefix : int,symbols_per_slot : + // int,Nid_cell : int,rnti : + // int,rb_size : int,rb_start : int,start_symbol_index : int,nr_of_symbols : + // int,qam_mod_order : int,mcs_index : int,mcs_table : int,nrOfLayers : + // int,transform_precoding : int,dmrs_config_type : int,ul_dmrs_symb_pos : int,number_dmrs_symbols : int,dmrs_port : + // int,dmrs_nscid : nb_antennas_tx : int,number_of_bits : buffer,data Define the subcarrier spacing vector + // int subcarrier_spacing_vect[] = {15000, 30000, 60000, 120000}; + NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; + int subcarrier_spacing_index = frame_parms->subcarrier_spacing / 15000 - 1; + T(T_UE_PHY_UL_PAYLOAD_TX_BITS, + T_INT((int)frame), + T_INT((int)slot), + T_INT((int)split_time_stamp_and_convert_to_int(trace_tx_payload_time_stamp_str, 0, 8)), + T_INT((int)split_time_stamp_and_convert_to_int(trace_tx_payload_time_stamp_str, 8, 9)), + T_INT((int)frame_parms->frame_type), // Frame type (0 FDD, 1 TDD) frame_structure + T_INT((int)frame_parms->freq_range), // Frequency range (0 FR1, 1 FR2) + T_INT((int)subcarrier_spacing_index), // Subcarrier spacing (0 15kHz, 1 30kHz, 2 60kHz) + T_INT((int)ulsch->pusch_pdu.cyclic_prefix), // Normal or extended prefix (0 normal, 1 extended) + T_INT((int)frame_parms->symbols_per_slot), // Number of symbols per slot + T_INT((int)frame_parms->Nid_cell), + T_INT((int)ulsch->pusch_pdu.rnti), + T_INT((int)ulsch->pusch_pdu.rb_size), + T_INT((int)ulsch->pusch_pdu.rb_start), + T_INT((int)ulsch->pusch_pdu.start_symbol_index), // start_ofdm_symbol + T_INT((int)ulsch->pusch_pdu.nr_of_symbols), // num_ofdm_symbols + T_INT((int)ulsch->pusch_pdu.qam_mod_order), // modulation + T_INT((int)ulsch->pusch_pdu.mcs_index), // mcs + T_INT((int)ulsch->pusch_pdu.mcs_table), // mcs_table_index + T_INT((int)ulsch->pusch_pdu.nrOfLayers), // num_layer + T_INT((int)ulsch->pusch_pdu.transform_precoding), // transformPrecoder_enabled = 0, transformPrecoder_disabled = 1 + T_INT((int)ulsch->pusch_pdu.dmrs_config_type), // dmrs_resource_map_config: pusch_dmrs_type1 = 0, pusch_dmrs_type2 = 1 + T_INT((int)ulsch->pusch_pdu.ul_dmrs_symb_pos), // used to derive the DMRS symbol positions + T_INT((int)number_dmrs_symbols), + // dmrs_start_ofdm_symbol + // dmrs_duration_num_ofdm_symbols + // dmrs_num_add_positions + T_INT((int)get_dmrs_port(0, ulsch->pusch_pdu.dmrs_ports)), // dmrs_antenna_port + T_INT((int)ulsch->pusch_pdu.scid), // dmrs_nscid + T_INT((int)frame_parms->nb_antennas_tx), // number of tx antennas + T_INT((int)A), // number_of_bits + T_BUFFER((uint8_t *)harq_process->payload_AB, A / 8)); + } +#endif ///////////////////////// b---->| block segmentation |---->c ///////////////////////// harq_process->BG = pusch_pdu->ldpcBaseGraph; diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c index e8217ee5aa..ebfd6f6352 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c @@ -48,6 +48,7 @@ #include "executables/softmodem-common.h" #include "PHY/NR_REFSIG/ul_ref_seq_nr.h" #include +#include "PHY/log_tools.h" //#define DEBUG_PUSCH_MAPPING //#define DEBUG_MAC_PDU @@ -543,7 +544,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, /////////////////////////ULSCH coding///////////////////////// - if (nr_ulsch_encoding(UE, &phy_data->ulsch, frame, slot, G, 1, ULSCH_ids) == -1) { + if (nr_ulsch_encoding(UE, &phy_data->ulsch, frame, slot, G, 1, ULSCH_ids, number_dmrs_symbols) == -1) { stop_meas_nr_ue_phy(UE, PUSCH_PROC_STATS); return; } @@ -602,7 +603,61 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, rnti, false, scrambled_output); +#if T_TRACER + if (T_ACTIVE(T_UE_PHY_UL_SCRAMBLED_TX_BITS)) { + // Get Time Stamp for T-tracer messages + char trace_time_stamp_str[30]; + get_time_stamp_usec(trace_time_stamp_str); + // trace_time_stamp_str = 8 bytes timestamp = YYYYMMDD + // + 9 bytes timestamp = HHMMSSMMM + int dmrs_port = get_dmrs_port(0, pusch_pdu->dmrs_ports); + const uint8_t *in_bytes = (const uint8_t *)scrambled_output; + + // Log UE_PHY_UL_SCRAMBLED_TX_BITS using T-Tracer if activated + // FORMAT = int,frame : int,slot : int,datetime_yyyymmdd : int,datetime_hhmmssmmm : + // int,frame_type : int,freq_range : int,subcarrier_spacing : int,cyclic_prefix : int,symbols_per_slot : + // int,Nid_cell : int,rnti : + // int,rb_size : int,rb_start : int,start_symbol_index : int,nr_of_symbols : + // int,qam_mod_order : int,mcs_index : int,mcs_table : int,nrOfLayers : + // int,transform_precoding : int,dmrs_config_type : int,ul_dmrs_symb_pos : int,number_dmrs_symbols : int,dmrs_port : + // int,dmrs_nscid : nb_antennas_tx : int,number_of_bits : buffer,data Define the subcarrier spacing vector + // int subcarrier_spacing_vect[] = {15000, 30000, 60000, 120000}; + int subcarrier_spacing_index = frame_parms->subcarrier_spacing / 15000 - 1; + T(T_UE_PHY_UL_SCRAMBLED_TX_BITS, + T_INT((int)frame), + T_INT((int)slot), + T_INT((int)split_time_stamp_and_convert_to_int(trace_time_stamp_str, 0, 8)), + T_INT((int)split_time_stamp_and_convert_to_int(trace_time_stamp_str, 8, 9)), + T_INT((int)frame_parms->frame_type), // Frame type (0 FDD, 1 TDD) frame_structure + T_INT((int)frame_parms->freq_range), // Frequency range (0 FR1, 1 FR2) + T_INT((int)subcarrier_spacing_index), // Subcarrier spacing (0 15kHz, 1 30kHz, 2 60kHz) + T_INT((int)pusch_pdu->cyclic_prefix), // Normal or extended prefix (0 normal, 1 extended) + T_INT((int)frame_parms->symbols_per_slot), // Number of symbols per slot + T_INT((int)frame_parms->Nid_cell), + T_INT((int)pusch_pdu->rnti), + T_INT((int)pusch_pdu->rb_size), + T_INT((int)pusch_pdu->rb_start), + T_INT((int)pusch_pdu->start_symbol_index), // start_ofdm_symbol + T_INT((int)pusch_pdu->nr_of_symbols), // num_ofdm_symbols + T_INT((int)pusch_pdu->qam_mod_order), // modulation + T_INT((int)pusch_pdu->mcs_index), // mcs + T_INT((int)pusch_pdu->mcs_table), // mcs_table_index + T_INT((int)pusch_pdu->nrOfLayers), // num_layer + T_INT((int)pusch_pdu->transform_precoding), // transformPrecoder_enabled = 0, transformPrecoder_disabled = 1 + T_INT((int)pusch_pdu->dmrs_config_type), // dmrs_resource_map_config: pusch_dmrs_type1 = 0, pusch_dmrs_type2 = 1 + T_INT((int)pusch_pdu->ul_dmrs_symb_pos), // used to derive the DMRS symbol positions + T_INT((int)number_dmrs_symbols), + // dmrs_start_ofdm_symbol + // dmrs_duration_num_ofdm_symbols + // dmrs_num_add_positions + T_INT((int)dmrs_port), // dmrs_antenna_port + T_INT((int)pusch_pdu->scid), // dmrs_nscid + T_INT((int)frame_parms->nb_antennas_tx), // number of tx antennas + T_INT((int)available_bits), // number_of_bits + T_BUFFER((uint8_t *)in_bytes, available_bits / 8)); + } +#endif /////////////////////////ULSCH modulation///////////////////////// int max_num_re = Nl * number_of_symbols * nb_rb * NR_NB_SC_PER_RB; diff --git a/openair1/SIMULATION/NR_PHY/ulschsim.c b/openair1/SIMULATION/NR_PHY/ulschsim.c index ef6fd34ee4..058a59feb5 100644 --- a/openair1/SIMULATION/NR_PHY/ulschsim.c +++ b/openair1/SIMULATION/NR_PHY/ulschsim.c @@ -513,7 +513,7 @@ int main(int argc, char **argv) if (input_fd == NULL) { uint8_t ULSCH_ids[] = {0}; - nr_ulsch_encoding(UE, ulsch_ue, 0, 0, &G, 1, ULSCH_ids); + nr_ulsch_encoding(UE, ulsch_ue, 0, 0, &G, 1, ULSCH_ids, 0); } printf("\n"); From 1a8a1004442abe08a7a3ba6873570bea46c30f77 Mon Sep 17 00:00:00 2001 From: Abdo-Gaber Date: Mon, 10 Mar 2025 12:28:22 +0100 Subject: [PATCH 258/964] Add Trace RX Payload on gNB (msg: GNB_PHY_UL_PAYLOAD_RX_BITS) including UTC time Log gNB RX Payload for both CRC valid and invalid cases --- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 64 +++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 8da471f4c1..37e7aa1207 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -39,8 +39,10 @@ #include "nfapi/oai_integration/vendor_ext.h" #include "assertions.h" #include +#include #include #include +#include "PHY/log_tools.h" //#define DEBUG_RXDATA //#define SRS_IND_DEBUG @@ -425,6 +427,68 @@ static int nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, boo crc_valid = true; } } +#if T_TRACER + if (T_ACTIVE(T_GNB_PHY_UL_PAYLOAD_RX_BITS)) { + // capture Rx Payload via T-Tracer for both CRC valid and invalid cases + // Get Time Stamp for T-tracer messages + char trace_rx_payload_time_stamp_str[30]; + get_time_stamp_usec(trace_rx_payload_time_stamp_str); + // trace_rx_payload_time_stamp_str = 8 bytes timestamp = YYYYMMDD + // + 9 bytes timestamp = HHMMSSMMM + + // Log GNB_PHY_UL_PAYLOAD_RX_BITS using T-Tracer if activated + // FORMAT = int,frame : int,slot : int,datetime_yyyymmdd : int,datetime_hhmmssmmm : + // int,frame_type : int,freq_range : int,subcarrier_spacing : int,cyclic_prefix : int,symbols_per_slot : + // int,Nid_cell : int,rnti : + // int,rb_size : int,rb_start : int,start_symbol_index : int,nr_of_symbols : + // int,qam_mod_order : int,mcs_index : int,mcs_table : int,nrOfLayers : + // int,transform_precoding : int,dmrs_config_type : int,ul_dmrs_symb_pos : int,number_dmrs_symbols : int,dmrs_port : + // int,dmrs_nscid : int,nb_antennas_rx : int,number_of_bits : buffer,data + + NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; + int dmrs_port = get_dmrs_port(0, pusch_pdu->dmrs_ports); + // int num_bytes = rdata->Kr_bytes - (ulsch_harq->F >> 3) - ((ulsch_harq->C > 1) ? 3 : 0); + // printf("num_bytes %d, len with CRC %d, data len %d\n", num_bytes, lenWithCrc(1, rdata->A), rdata->A); + // calculate the number of dmrs symbols in the slot + int number_dmrs_symbols = 0; + for (int l = pusch_pdu->start_symbol_index; l < pusch_pdu->start_symbol_index + pusch_pdu->nr_of_symbols; l++) + number_dmrs_symbols += ((pusch_pdu->ul_dmrs_symb_pos) >> l) & 0x01; + + // Log GNB_PHY_UL_PAYLOAD_RX_BITS using T-Tracer if activated + T(T_GNB_PHY_UL_PAYLOAD_RX_BITS, + T_INT((int)ulsch->frame), + T_INT((int)ulsch->slot), + T_INT((int)split_time_stamp_and_convert_to_int(trace_rx_payload_time_stamp_str, 0, 8)), + T_INT((int)split_time_stamp_and_convert_to_int(trace_rx_payload_time_stamp_str, 8, 9)), + T_INT((int)frame_parms->frame_type), // Frame type (0 FDD, 1 TDD) frame_structure + T_INT((int)frame_parms->freq_range), // Frequency range (0 FR1, 1 FR2) + T_INT((int)pusch_pdu->subcarrier_spacing), // Subcarrier spacing (0 15kHz, 1 30kHz, 2 60kHz) + T_INT((int)pusch_pdu->cyclic_prefix), // Normal or extended prefix (0 normal, 1 extended) + T_INT((int)frame_parms->symbols_per_slot), // Number of symbols per slot + T_INT((int)frame_parms->Nid_cell), + T_INT((int)pusch_pdu->rnti), + T_INT((int)pusch_pdu->rb_size), + T_INT((int)pusch_pdu->rb_start), + T_INT((int)pusch_pdu->start_symbol_index), // start_ofdm_symbol + T_INT((int)pusch_pdu->nr_of_symbols), // num_ofdm_symbols + T_INT((int)pusch_pdu->qam_mod_order), // modulation + T_INT((int)pusch_pdu->mcs_index), // mcs + T_INT((int)pusch_pdu->mcs_table), // mcs_table_index + T_INT((int)pusch_pdu->nrOfLayers), // num_layer + T_INT((int)pusch_pdu->transform_precoding), // transformPrecoder_enabled = 0, transformPrecoder_disabled = 1 + T_INT((int)pusch_pdu->dmrs_config_type), // dmrs_resource_map_config: pusch_dmrs_type1 = 0, pusch_dmrs_type2 = 1 + T_INT((int)pusch_pdu->ul_dmrs_symb_pos), // used to derive the DMRS symbol positions + T_INT((int)number_dmrs_symbols), + // dmrs_start_ofdm_symbol + // dmrs_duration_num_ofdm_symbols + // dmrs_num_add_positions + T_INT((int)dmrs_port), // dmrs_antenna_port + T_INT((int)pusch_pdu->scid), // dmrs_nscid + T_INT((int)frame_parms->nb_antennas_rx), // rx antenna + T_INT(((ulsch_harq->TBS) << 3)), // number_of_bits + T_BUFFER((uint8_t *)((ulsch_harq->b)), ((ulsch_harq->TBS) << 3) / 8)); // data + } +#endif nfapi_nr_crc_t *crc = &UL_INFO->crc_ind.crc_list[UL_INFO->crc_ind.number_crcs++]; nfapi_nr_rx_data_pdu_t *pdu = &UL_INFO->rx_ind.pdu_list[UL_INFO->rx_ind.number_of_pdus++]; From 9a9c5c97efee2b785dfd816bafd043678292dfb4 Mon Sep 17 00:00:00 2001 From: Abdo-Gaber Date: Mon, 10 Mar 2025 12:49:05 +0100 Subject: [PATCH 259/964] Add Data Collection Services (T-Tracer for gNB and UE) - Add _tracer_app_gnb and t_tracer_app_ue apps to common/utils/T/tracer/Makefile - Add Data collection Service for gNB: common/utils/T/tracer/t_tracer_app_gnb.c - Add Data Collection Service for UE: common/utils/T/tracer/t_tracer_app_ue.c - Add Shared memory configuration (common/utils/T/tracer/shared_memory_config.h), since We will have too much memory consumption on the stack if the T-tracer is not fast enough to process the traces or if we have too much traces. As a result, tracers start to capture data, write data in shared memory, then close the T-Tracer after getting the recording of N slots - Support the operation of : COnfig, Record, and Stop - Poll from Socket and not use get_events to mitigate long-time waiting if there is no data in buffer or the UE is already released or crashed - Add extra offset to improve data sync --- common/utils/T/tracer/Makefile | 12 +- common/utils/T/tracer/shared_memory_config.h | 64 ++ common/utils/T/tracer/t_tracer_app_gnb.c | 973 ++++++++++++++++++ common/utils/T/tracer/t_tracer_app_ue.c | 976 +++++++++++++++++++ 4 files changed, 2023 insertions(+), 2 deletions(-) create mode 100644 common/utils/T/tracer/shared_memory_config.h create mode 100644 common/utils/T/tracer/t_tracer_app_gnb.c create mode 100644 common/utils/T/tracer/t_tracer_app_ue.c diff --git a/common/utils/T/tracer/Makefile b/common/utils/T/tracer/Makefile index 807347f5a4..6777be7152 100644 --- a/common/utils/T/tracer/Makefile +++ b/common/utils/T/tracer/Makefile @@ -8,7 +8,7 @@ XLIBS=-lX11 -lpng -lXft all: record replay extract_config textlog enb ue vcd macpdu2wireshark \ extract_input_subframe extract_output_subframe to_vcd extract multi \ - gnb + gnb t_tracer_app_gnb t_tracer_app_ue record: utils.o record.o database.o configuration.o $(CC) $(CFLAGS) -o record $^ $(LIBS) @@ -65,6 +65,14 @@ gnb: utils.o gnb.o database.o event.o handler.o configuration.o \ filter/filter.a $(CC) $(CFLAGS) -o gnb $^ $(LIBS) $(XLIBS) +t_tracer_app_gnb: utils.o t_tracer_app_gnb.o database.o event.o handler.o configuration.o \ + logger/logger.a filter/filter.a + $(CC) $(CFLAGS) -o t_tracer_app_gnb $^ $(LIBS) $(XLIBS) + +t_tracer_app_ue: utils.o t_tracer_app_ue.o database.o event.o handler.o configuration.o \ + logger/logger.a filter/filter.a + $(CC) $(CFLAGS) -o t_tracer_app_ue $^ $(LIBS) $(XLIBS) + multi.o: ../incgen/T_IDs.h ../incgen/T_IDs.h: ../T_messages.txt @@ -90,7 +98,7 @@ filter/filter.a: clean: rm -f *.o core tracer_remote textlog enb ue vcd record replay rm -f extract_config macpdu2wireshark extract_input_subframe - rm -f extract_output_subframe to_vcd extract multi gnb + rm -f extract_output_subframe to_vcd extract multi gnb t_tracer_app_gnb t_tracer_app_ue cd gui && $(MAKE) clean cd view && $(MAKE) clean cd logger && $(MAKE) clean diff --git a/common/utils/T/tracer/shared_memory_config.h b/common/utils/T/tracer/shared_memory_config.h new file mode 100644 index 0000000000..c126d85801 --- /dev/null +++ b/common/utils/T/tracer/shared_memory_config.h @@ -0,0 +1,64 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file common/utils/T/tracer/shared_memory_config.h + * \brief shared memory to store data captured by T-Tracer services to be processed by data recording application + * \author Abdo Gaber + * \date 2024 + * \version 1.0 + * \company Emerson, NI Test and Measurement + * \email: + * \note + * \warning + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef _SHARED_MEMORY_CONFIG_H_ +#define _SHARED_MEMORY_CONFIG_H_ + +#define SHMSIZE ((122.88e6 / (100 * 20)) * 1000 * 8) // Assume capture in 1000, each I+Q represented by 8 byts +// 122.88e6: 10ms at 100 MHz BW of 5G NR +// 20: 20 slots in 10ms +// subcarrier spacing: 30 KHz + +// for gNB T Tracer App +#define GETKEYDIR1_gNB ("/tmp/gnb_app1") +#define GETKEYDIR2_gNB ("/tmp/gnb_app2") +#define PROJECTID_gNB (2335) + +// for UET Tracer App +#define GETKEYDIR1_UE ("/tmp/ue_app1") +#define GETKEYDIR2_UE ("/tmp/ue_app2") +#define PROJECTID_UE (2336) + +void err_exit(char *buf); +int create_shm(char **addrN, const char *pathname, int projectId); +void del_shm(char *addr, int shm_id); + +#endif /* _SHARED_MEMORY_CONFIG_H_ */ diff --git a/common/utils/T/tracer/t_tracer_app_gnb.c b/common/utils/T/tracer/t_tracer_app_gnb.c new file mode 100644 index 0000000000..3cb0325e39 --- /dev/null +++ b/common/utils/T/tracer/t_tracer_app_gnb.c @@ -0,0 +1,973 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file common/utils/T/tracer/t_tracer_app_gnb.c + * \brief T-Tracer gnb service to capture tracee Messages from gNB, it is used by data recording application + * \author Abdo Gaber + * \date 2025 + * \version 1.0 + * \company Emerson, NI Test and Measurement + * \email: + * \note + * \warning + */ + +#include +#include +#include +#include +#include +#include "database.h" +#include "event.h" +#include "handler.h" +#include "logger/logger.h" +#include "utils.h" +#include "event_selector.h" +#include "configuration.h" +#include "shared_memory_config.h" +#include +#include +#include +#include +#include +#include +#include +#define MAX_FRAME_INDEX 1023 +#define MAX_SLOT_INDEX 19 +#define DEBUG_T_Tracer +#define DEBUG_BUFFER +// Duration to discard recording in milliseconds to mitigate reading data from +// the buffer in the stack from the previous record +#define DISCARD_RECORD_DURATION_MS 10 + +// Combine bytes in - little-endian format +int combine_bytes(const uint8_t *bytes, size_t num_bytes) +{ + int result = 0; + for (size_t i = 0; i < num_bytes; ++i) { + result |= (bytes[i] << (i * 8)); + } + return result; +} + +// Convert an integer to an array of bytes - little-endian format +void int_to_bytes(int num, uint8_t *bytes, size_t num_bytes) +{ + for (size_t i = 0; i < num_bytes; ++i) { + bytes[i] = (num >> (i * 8)) & 0xFF; + } +} + +// Check if the message is in the list of bits messages +bool is_bits_messages(int traces_bits_support_data_Collection_format_idx[], int n_bits_msgs, int msg_id) +{ + for (int i = 0; i < n_bits_msgs; i++) { + if (msg_id == traces_bits_support_data_Collection_format_idx[i]) { + return true; + } + } + return false; +} + +// Get the current time +struct timespec get_current_time() +{ + struct timespec time; + clock_gettime(CLOCK_MONOTONIC, &time); + return time; +} + +// Function to convert timespec to microseconds +long long timespec_to_microseconds(struct timespec time) +{ + return (time.tv_sec * 1000000LL) + (time.tv_nsec / 1000); +} + +// Calculate the time difference in milliseconds +double calculate_time_difference(struct timespec start, struct timespec end) +{ + double start_ms = start.tv_sec * 1000.0 + start.tv_nsec / 1000000.0; + double end_ms = end.tv_sec * 1000.0 + end.tv_nsec / 1000000.0; + return end_ms - start_ms; +} + +// Get Time Stamp in microseconds in YYYYMMDDHHMMSSmmmuuu format +char *get_time_stamp_usec(char time_stamp_str[]) +{ + // initialization to measure time stamp --This part should be moved to inilization part + time_t my_time; + struct tm *timeinfo; + time(&my_time); + struct timeval tv; + + // get time stamp + timeinfo = localtime(&my_time); + gettimeofday(&tv, NULL); + // Add time stamp: yyyy mm dd hh mm ss usec + uint16_t year = timeinfo->tm_year + 1900; + uint8_t mon = timeinfo->tm_mon + 1; + uint8_t mday = timeinfo->tm_mday; + uint8_t hour = timeinfo->tm_hour; + uint8_t min = timeinfo->tm_min; + uint8_t sec = timeinfo->tm_sec; + uint16_t usec = (tv.tv_usec); + // printf ("Time stamp: %d_%d_%d_%d_%d_%d_%d \n",year,mon,mday,hour,min,sec,usec); + // sprintf(time_stamp_str, "%d_%d_%d_%d_%d_%d_%d",year,mon,mday,hour,min,sec,usec); + sprintf(time_stamp_str, "%04d%02d%02d%02d%02d%02d%06d", year, mon, mday, hour, min, sec, usec); + + return time_stamp_str; +} + +// Convert timestamp string to integer +int convert_time_stamp_to_int(const char *timestamp) +{ + return atoi(timestamp); +} + +// Split timestamp string and convert to integer +int split_time_stamp_and_convert_to_int(char time_stamp_str[], int shift, int length) +{ + char time_part[length + 1]; // Buffer to hold the date part YYYYMMDD or HHMMSSmmm + // Copy the first 8 or 9 characters (YYYYMMDD) to HHMMSSmmm + strncpy(time_part, time_stamp_str + shift, length); + time_part[length] = '\0'; // Null-terminate the string + // Convert timestamp string to integer + return convert_time_stamp_to_int(time_part); +} + +void err_exit(char *buf) +{ + fprintf(stderr, "%s\n", buf); + exit(1); +} + +// create shared memory +int create_shm(char **addrN, const char *shm_path, int projectId) +{ + key_t key; + if (-1 != open(shm_path, O_CREAT, 0777)) { + key = ftok(shm_path, projectId); + } else { + err_exit("Error: open shared memory"); + } + + if (key < 0) { + err_exit("Error: ftok error"); + } + + int shm_id; + shm_id = shmget(key, SHMSIZE, IPC_CREAT | IPC_EXCL | 0664); + if (shm_id == -1) { + if (errno == EEXIST) { + printf("Error: shared memeory already exist\n"); + shm_id = shmget(key, 0, 0); + printf("reference shm_id = %d\n", shm_id); + } else { + perror("errno"); + err_exit("shmget error"); + } + } + char *addr; + // address to attach - attach for read & write + if ((addr = shmat(shm_id, 0, 0)) == (void *)-1) { + if (shmctl(shm_id, IPC_RMID, NULL) == -1) + err_exit("Error: shmctl error"); + else { + printf("Attach shared memory failed\n"); + printf("remove shared memory identifier successful\n"); + } + err_exit("shmat error"); + } + *addrN = addr; + return shm_id; +} + +// delete shared memory +void del_shm(char *addr, int shm_id) +{ + if (shmdt(addr) < 0) + err_exit("shmdt error"); + + if (shmctl(shm_id, IPC_RMID, NULL) == -1) + err_exit("shmctl error"); + else { + printf("Remove shared memory identifier successful\n"); + } +} + +/* this function sends the activated traces to the nr-softmodem */ +void activate_traces(int socket, int number_of_events, int *is_on) +{ + char t = 1; + if (socket_send(socket, &t, 1) == -1 || socket_send(socket, &number_of_events, sizeof(int)) == -1 + || socket_send(socket, is_on, number_of_events * sizeof(int)) == -1) + abort(); +} + +void usage(void) +{ + printf( + "options:\n" + " -d this option is mandatory\n" + " -ip connect to given IP address (default %s)\n" + " -p connect to given port (default %d)\n", + DEFAULT_REMOTE_IP, + DEFAULT_REMOTE_PORT); + exit(1); +} + +// class to store the message and the action to enable capture selected data +// 0: do not record message +// 1: record message +struct trace_struct { + char on_off_name[100]; + int on_off_action; +}; + +// struct for trace message based on Data Collection Trace Messages Structure +// you need to define the vararibles of each message +typedef struct { + /* Data Collection Trace Message Structure */ + int frame; + int slot; + int datetime_yyyymmdd; + int datetime_hhmmssmmm; + int frame_type, freq_range, subcarrier_spacing, cyclic_prefix, symbols_per_slot; + int Nid_cell, rnti; + int rb_size, rb_start, start_symbol_index, nr_of_symbols; + int qam_mod_order, mcs_index, mcs_table, nrOfLayers, transform_precoding; + int dmrs_config_type, ul_dmrs_symb_pos, number_dmrs_symbols; + int dmrs_port, dmrs_nscid, nb_antennas_rx, number_of_bits; + int data_size, data; +} event_trace_msg_data; + +void setup_trace_msg_data(event_trace_msg_data *d, void *database) +{ + database_event_format f; + int i; + + /* Data Collection Trace Message Structure */ + // FORMAT = int,frame : int,slot : int,datetime_yyyymmdd : int,datetime_hhmmssmmm : + // int,frame_type : int,freq_range : int,subcarrier_spacing : int,cyclic_prefix : int,symbols_per_slot : + // int,Nid_cell : int,rnti : + // int,rb_size : int,rb_start : int,start_symbol_index : int,nr_of_symbols : + // int,qam_mod_order : int,mcs_index : int,mcs_table : int,nrOfLayers : + // int,transform_precoding : int,dmrs_config_type : int,ul_dmrs_symb_pos : int,number_dmrs_symbols : + // int,dmrs_port : int,dmrs_nscid : + // int,nb_antennas_rx : int,number_of_bits : buffer,data + + // Initialize the data structure + d->frame = -1; + d->slot = -1; + d->datetime_yyyymmdd = -1; + d->datetime_hhmmssmmm = -1; + d->frame_type = -1; + d->freq_range = -1; + d->subcarrier_spacing = -1; + d->cyclic_prefix = -1; + d->symbols_per_slot = -1; + d->Nid_cell = -1; + d->rnti = -1; + d->rb_size = -1; + d->rb_start = -1; + d->start_symbol_index = -1; + d->nr_of_symbols = -1; + d->qam_mod_order = -1; + d->mcs_index = -1; + d->mcs_table = -1; + d->nrOfLayers = -1; + d->transform_precoding = -1; + d->dmrs_config_type = -1; + d->ul_dmrs_symb_pos = -1; + d->number_dmrs_symbols = -1; + d->dmrs_port = -1; + d->dmrs_nscid = -1; + d->nb_antennas_rx = -1; + d->number_of_bits = -1; + d->data = -1; + +/* this macro looks for a particular element and checks its type */ +#define G(var_name, var_type, var) \ + if (!strcmp(f.name[i], var_name)) { \ + if (strcmp(f.type[i], var_type)) { \ + printf("Error: Trace Message has a bad type for %s\n", var_name); \ + exit(1); \ + } \ + var = i; \ + continue; \ + } + + /* ------------------------------*/ + /* Create Macro for Data Collection Trace Message */ + /* ------------------------------*/ + // Data Collection Trace Message Structure + // Example: GNB_PHY_UL_FD_PUSCH_IQ, GNB_PHY_UL_FD_DMRS_ID, + // GNB_PHY_UL_FD_CHAN_EST_DMRS_POS, GNB_PHY_UL_FD_CHAN_EST_DMRS_INTERPL + // GNB_PHY_UL_PAYLOAD_RX_BITS + // UE_PHY_UL_SCRAMBLED_TX_BITS + // UE_PHY_UL_PAYLOAD_TX_BITS + // Get a template of any message based on Data Collection Trace Messages Structure + int Trace_MSG_ID = event_id_from_name(database, "GNB_PHY_UL_FD_PUSCH_IQ"); + f = get_format(database, Trace_MSG_ID); + + /* get the elements of the trace + * the value is an index in the event, see below */ + // FORMAT = int,frame : int,slot : int,datetime_yyyymmdd : int,datetime_hhmmssmmm : + // int,frame_type : int,freq_range : int,subcarrier_spacing : int,cyclic_prefix : int,symbols_per_slot : + // int,Nid_cell : int,rnti : + // int,rb_size : int,rb_start : int,start_symbol_index : int,nr_of_symbols : + // int,qam_mod_order : int,mcs_index : int,mcs_table : int,nrOfLayers : + // int,transform_precoding : int,dmrs_config_type : int,ul_dmrs_symb_pos : int,number_dmrs_symbols : + // int,dmrs_port : int,dmrs_nscid : + // int,nb_antennas_rx : int,number_of_bits : buffer,data + + for (i = 0; i < f.count; i++) { + G("frame", "int", d->frame) + G("slot", "int", d->slot) + G("datetime_yyyymmdd", "int", d->datetime_yyyymmdd) + G("datetime_hhmmssmmm", "int", d->datetime_hhmmssmmm) + G("frame_type", "int", d->frame_type) + G("freq_range", "int", d->freq_range) + G("subcarrier_spacing", "int", d->subcarrier_spacing) + G("cyclic_prefix", "int", d->cyclic_prefix) + G("symbols_per_slot", "int", d->symbols_per_slot) + G("Nid_cell", "int", d->Nid_cell) + G("rnti", "int", d->rnti) + G("rb_size", "int", d->rb_size) + G("rb_start", "int", d->rb_start) + G("start_symbol_index", "int", d->start_symbol_index) + G("nr_of_symbols", "int", d->nr_of_symbols) + G("qam_mod_order", "int", d->qam_mod_order) + G("mcs_index", "int", d->mcs_index) + G("mcs_table", "int", d->mcs_table) + G("nrOfLayers", "int", d->nrOfLayers) + G("transform_precoding", "int", d->transform_precoding) + G("dmrs_config_type", "int", d->dmrs_config_type) + G("ul_dmrs_symb_pos", "int", d->ul_dmrs_symb_pos) + G("number_dmrs_symbols", "int", d->number_dmrs_symbols) + G("dmrs_port", "int", d->dmrs_port) + G("dmrs_nscid", "int", d->dmrs_nscid) + G("nb_antennas_rx", "int", d->nb_antennas_rx) + G("number_of_bits", "int", d->number_of_bits) + G("data", "buffer", d->data) + } + // if (d->frame == -1 || d->slot == -1) goto error; +#undef G + return; +} + +// Function to check if a value is in the array +int isValueInArray(int value, int arr[], int size) +{ + for (int i = 0; i < size; i++) { + if (arr[i] == value) { + return 1; // Value found + } + } + return 0; // Value not found +} + +void reestablish_connection(int *socket, char *ip, int port, int number_of_events, int *is_on) +{ + clear_remote_config(); + if (*socket != -1) + close(*socket); + + /* connect to the nr-softmodem */ + *socket = connect_to(ip, port); + if (*socket == -1) { + printf("\n Failed to connect to nr-softmodem. Retrying...\n"); + return; + } + printf("\n Connected"); + + /* activate the traces in the nr-softmodem */ + activate_traces(*socket, number_of_events, is_on); + printf("\n Activated Traces in nr-softmodem"); +} + +int main(int n, char **v) +{ + // Define and initialize an array of strings to list + // trace_msgs_support_data_Collection_format + // it is used to parse the requested messages if it is based + // on Data Collection Trace Messages Structure and supported tracer messages indices + char *traces_iq_support_data_Collection_format[] = {"GNB_PHY_UL_FD_PUSCH_IQ", + "GNB_PHY_UL_FD_DMRS", + "GNB_PHY_UL_FD_CHAN_EST_DMRS_POS", + "GNB_PHY_UL_FD_CHAN_EST_DMRS_INTERPL"}; + char *traces_bits_support_data_Collection_format[] = {"GNB_PHY_UL_PAYLOAD_RX_BITS", + "UE_PHY_UL_SCRAMBLED_TX_BITS", + "UE_PHY_UL_PAYLOAD_TX_BITS"}; + // extra number of records to simlify Sync between base station and UE synchronization records. + // if you have network delay, you can increase the number of records to capture + int max_sync_offset = 6; // 6 frames ~ 60 ms + // all supported messages + // Calculate the size of the combined array + int n_iq_msgs = sizeof(traces_iq_support_data_Collection_format) / sizeof(traces_iq_support_data_Collection_format[0]); + int n_bits_msgs = sizeof(traces_bits_support_data_Collection_format) / sizeof(traces_bits_support_data_Collection_format[0]); + int n_msgs_based_data_Collection_format = n_iq_msgs + n_bits_msgs; + + // Create the combined array + char *traces_support_data_Collection_format[n_msgs_based_data_Collection_format]; + // Copy IQ messages to the combined array + for (int i = 0; i < n_iq_msgs; i++) { + traces_support_data_Collection_format[i] = traces_iq_support_data_Collection_format[i]; + } + + // Copy Bits messages to the combined array + for (int i = 0; i < n_bits_msgs; i++) { + traces_support_data_Collection_format[i + n_iq_msgs] = traces_bits_support_data_Collection_format[i]; + } + + uint16_t msg_id = 0; + uint16_t start_frame_number = 0; + uint32_t number_records = 0; // number of records to capture, it is number of slots + // array to store the requested tracer messages indices + int req_tracer_msgs_indices[100] = {0}; + // define variables --> to do: add all of them to be class of pointers + char *database_filename = NULL; + void *database; + char *ip = DEFAULT_REMOTE_IP; + char ip_address[16]; // max IP address length is 15 + 1 for null terminator + int port = DEFAULT_REMOTE_PORT; + int *is_on; + int number_of_events; + int i; + int socket = -1; + char trace_time_stamp_str[30]; + + // data structure for the trace messages based on Data Collection Trace Messages Structure + event_trace_msg_data trace_msg_data; + + // initlization variables + unsigned int bufIdx_wr = 0; + unsigned int bufIdx_rd = 0; + uint8_t num_req_tracer_msgs = 0; + + // initilaze shared memory + char *addr_wr, *addr_rd; + printf("\n Data Collection Service: Initializing shared memory ..."); + printf("\n Directory 1: %s, Directory 2: %s", GETKEYDIR1_gNB, GETKEYDIR2_gNB); + printf("\n Project ID: %d\n", PROJECTID_gNB); + int shm_id_wr = create_shm(&addr_wr, GETKEYDIR1_gNB, PROJECTID_gNB); + int shm_id_rd = create_shm(&addr_rd, GETKEYDIR2_gNB, PROJECTID_gNB); + del_shm(addr_wr, shm_id_wr); + del_shm(addr_rd, shm_id_rd); + shm_id_wr = create_shm(&addr_wr, GETKEYDIR1_gNB, PROJECTID_gNB); + shm_id_rd = create_shm(&addr_rd, GETKEYDIR2_gNB, PROJECTID_gNB); + + /* write on a socket fails if the other end is closed and we get SIGPIPE */ + if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) + abort(); + + /* parse command line options */ + // Port number and IP address are given via API and not via command line + for (i = 1; i < n; i++) { + if (!strcmp(v[i], "-h") || !strcmp(v[i], "--help")) + usage(); + if (!strcmp(v[i], "-d")) { + if (i > n - 2) + usage(); + database_filename = v[++i]; + continue; + } + if (!strcmp(v[i], "-ip")) { + if (i > n - 2) + usage(); + ip = v[++i]; + continue; + } + if (!strcmp(v[i], "-p")) { + if (i > n - 2) + usage(); + port = atoi(v[++i]); + continue; + } + usage(); + } + + if (database_filename == NULL) { + printf("ERROR: Provide a database file (-d)\n"); + exit(1); + } + + /* load the database T_messages.txt */ + database = parse_database(database_filename); + load_config_file(database_filename); + + /* an array of int for all the events defined in the database is needed */ + number_of_events = number_of_ids(database); + is_on = calloc(number_of_events, sizeof(int)); + if (is_on == NULL) + abort(); + + // Set first byte of the shared memory to 0 + addr_rd[0] = 0; // important to check if we have new requested messages + + // read requested tracer msg indices from memory + printf("\n Data Collection Service: Waiting for messages request ...\n"); + // 0: Wait + // 1: config + // 2: record + // 3: stop + // Wait for Action Config + while (1) { + if ((uint8_t)(addr_rd[0]) == 0) { + usleep(50); // sleep for 50 us: 0.5 ms slot duration + } + // config state + else if ((uint8_t)(addr_rd[0]) == 1) { + get_time_stamp_usec(trace_time_stamp_str); + printf("\n Received config message. Time Stamp: %s", trace_time_stamp_str); + + // get the IP address length in bytes + bufIdx_rd = 1; + uint8_t ip_address_length = addr_rd[bufIdx_rd]; + bufIdx_rd += 1; // + 1 byte = IP address length + + // read the IP address + for (int i = 0; i < ip_address_length; i++) { + ip_address[i] = addr_rd[bufIdx_rd]; + bufIdx_rd += 1; + } + + ip = ip_address; + + // get the array bytes of the port number : 2 bytes + uint8_t port_number_bytes[2] = {addr_rd[bufIdx_rd], addr_rd[bufIdx_rd + 1]}; + bufIdx_rd += 2; // + 2 bytes = start frame number + + port = combine_bytes(port_number_bytes, 2); + printf("\n Parameters: IP Address length: %d, IP Address: %s, Port Number: %d \n", ip_address_length, ip_address, port); + addr_rd[0] = 0; // reset memory : to wait for record action + break; + } + } + // Establish connection to the nr-softmodem + clear_remote_config(); + if (socket != -1) + close(socket); + + /* connect to the nr-softmodem */ + socket = connect_to(ip, port); + printf("\n Connected to nr-softmodem"); + + // Read Action record or stop + printf("\n Data Collection Service: Waiting for record message ...\n"); + while (1) { + // wait for Action record + if ((uint8_t)(addr_rd[0]) == 0) { + usleep(50); // sleep for 50 us: 0.5 ms slot duration + } + + // quit state + else if ((uint8_t)(addr_rd[0]) == 3) { + printf("\n Received 'stop' command. Exiting..."); + printf("\n "); + // Clean up and exit + break; + } + // record state + else if ((uint8_t)(addr_rd[0]) == 2) { + // clear remote buffer if there is + clear_remote_config(); + get_time_stamp_usec(trace_time_stamp_str); + printf("\n Received record message. Time Stamp: %s", trace_time_stamp_str); + + // read number of requested messages + bufIdx_rd = 1; + num_req_tracer_msgs = addr_rd[bufIdx_rd]; + bufIdx_rd += 1; + printf("\n Number of requested tracer messages: %d,", num_req_tracer_msgs); + // reset memory : action to wait for next record action + addr_rd[0] = 0; + + // read tracer msg IDs - every message ID has been stored in two bytes + for (uint8_t msg_n = 0; msg_n < num_req_tracer_msgs; msg_n++) { + // get the array bytes of the tracer message ID: 2 bytes + uint8_t msg_id_bytes[2] = {addr_rd[bufIdx_rd], addr_rd[bufIdx_rd + 1]}; + bufIdx_rd += 2; // + 2 bytes = message ID + msg_id = combine_bytes(msg_id_bytes, 2); + + req_tracer_msgs_indices[msg_n] = msg_id; + printf(" msg_id: %d, ", msg_id); + } + // get the array bytes of the number of records: 4 bytes + uint8_t number_records_bytes[4] = {addr_rd[bufIdx_rd], + addr_rd[bufIdx_rd + 1], + addr_rd[bufIdx_rd + 2], + addr_rd[bufIdx_rd + 3]}; + bufIdx_rd += 4; // + 4 bytes = number of records + + number_records = combine_bytes(number_records_bytes, 4); + + printf("num_records: %d, ", number_records); + + // get the array bytes of the start frame number : 2 bytes + uint8_t start_frame_number_bytes[2] = {addr_rd[bufIdx_rd], addr_rd[bufIdx_rd + 1]}; + bufIdx_rd += 2; // + 2 bytes = start frame number + + start_frame_number = combine_bytes(start_frame_number_bytes, 2); + + printf("start_frame: %d\n", start_frame_number); + + /* activate the trace in this array */ + printf("\n Activate Tracer messages in on_off array: "); + for (i = 0; i < num_req_tracer_msgs; i++) { + char *on_off_name = event_name_from_id(database, req_tracer_msgs_indices[i]); + on_off(database, on_off_name, is_on, 1); + printf("%d, %s, ", req_tracer_msgs_indices[i], on_off_name); + // on_off(database, "GNB_PHY_DL_OUTPUT_SIGNAL", is_on, 1); + } + + // get the event IDs for the bit messages + int traces_bits_support_data_Collection_format_idx[n_bits_msgs]; + for (int i = 0; i < n_bits_msgs; i++) { + traces_bits_support_data_Collection_format_idx[i] = + event_id_from_name(database, traces_bits_support_data_Collection_format[i]); + } + + // all supported messages + int traces_support_data_Collection_format_idx[n_msgs_based_data_Collection_format]; + for (int i = 0; i < n_msgs_based_data_Collection_format; i++) { + traces_support_data_Collection_format_idx[i] = event_id_from_name(database, traces_support_data_Collection_format[i]); + } + + // setup data for the trace messages + setup_trace_msg_data(&trace_msg_data, database); + printf("\n Setup Trace Data Done"); + + // Get the start time + struct timespec start_time = get_current_time(); + + /* activate the tracee in the nr-softmodem */ + activate_traces(socket, number_of_events, is_on); + printf("\n Activated Traces in nr-softmodem"); + + /* a buffer needed to receive events from the nr-softmodem */ + OBUF ebuf = {osize : 0, omaxsize : 0, obuf : NULL}; + + /* read events */ + int nrecord_idx = 0; + bufIdx_wr = 0; + // logic to be sure that we have a complete slot record + bool start_recording = false; + bool got_ref_frame_slot = false; + int ref_slot = 0; + int ref_frame = 0; + int slot_difference = 0; + int frame_difference = 0; + int current_frame = 0, prev_frame = 0, current_slot = 0, prev_slot = 0; + // offset to sync between base station and UE synchronization records or power measurements + int sync_offset_index = 0; // increase the index only if the index of frame changes after getting all records + // since we will use the frame differece to do extra records, we should be sure that the last slot is recorded completely + printf("\n\n Data Collection Service: Start reading messages ..."); + struct pollfd event_poll_fd; + event_poll_fd.fd = socket; + event_poll_fd.events = POLLIN; + while (1) { + // stop if number of records is done + if ((nrecord_idx >= number_records) && (sync_offset_index >= max_sync_offset)) { + // We added one to the number of records to capture the last record completely if + // we have several messages enabled per slot + break; + } + int poll_ret = poll(&event_poll_fd, 1, 1); // 1 ms timeout for poll + if (poll_ret > 0 && (event_poll_fd.revents & POLLIN)) { + event e = get_event(socket, &ebuf, database); + + if (e.type == -1) { + printf("\n Link broken or unexpected message received. Re-establishing connection...\n"); + reestablish_connection(&socket, ip, port, number_of_events, is_on); + continue; // Skip further processing and retry + } + //------------------------- + // GNB_PHY_UL_FD_PUSCH_IQ, GNB_PHY_UL_FD_DMRS_ID, GNB_PHY_UL_FD_CHAN_EST_DMRS_POS, + // UE_PHY_UL_SCRAMBLED_TX_BITS, GNB_PHY_UL_PAYLOAD_RX_BITS, UE_PHY_UL_PAYLOAD_TX_BITS + //------------------------- + // is it a requested message + if (isValueInArray(e.type, req_tracer_msgs_indices, num_req_tracer_msgs)) { + // is it based on Data Collection Trace Messages Structure + if (isValueInArray(e.type, traces_support_data_Collection_format_idx, n_msgs_based_data_Collection_format)) { + // Start recording from the next slot to mitigate capturing partial data + // check if the current frame and slot are different from the previous frame and slot + // Then, increase the record index + if (start_recording == false) { + if (got_ref_frame_slot == false) { + ref_frame = e.e[trace_msg_data.frame].i; + ref_slot = e.e[trace_msg_data.slot].i; + printf("\nMessage Info: msg_id %s (%d) \n", event_name_from_id(database, e.type), e.type); + got_ref_frame_slot = true; + } + + current_frame = e.e[trace_msg_data.frame].i; + current_slot = e.e[trace_msg_data.slot].i; + frame_difference = (current_frame - ref_frame + MAX_FRAME_INDEX + 1) % (MAX_FRAME_INDEX + 1); + slot_difference = (current_slot - ref_slot + MAX_SLOT_INDEX + 1) % (MAX_SLOT_INDEX + 1); + printf("\n First frame.slot: %d.%d, current frame.slot: %d.%d, diff frame.slot: %d.%d", + ref_frame, + ref_slot, + current_frame, + current_slot, + frame_difference, + slot_difference); + + if ((ref_frame != current_frame) || (ref_slot != current_slot)) { + start_recording = true; + printf("\n Start recording from frame: %d, slot: %d ", e.e[trace_msg_data.frame].i, e.e[trace_msg_data.slot].i); + } + } + // start recording from the next frame to mitigate capturing partial data + if (start_recording == true) { + /* this is how to access the elements of the Data Collection trace messages. + * we use e.e[] and then the correct suffix, here + * it's .i for the integer and .b for the buffer and .bsize for the buffer size + * see in event.h the structure event_arg + */ + unsigned char *buf = e.e[trace_msg_data.data].b; + + printf("\n\nRecord number: %d", nrecord_idx); +#ifdef DEBUG_BUFFER + printf("\nBuffer index in bytes: %d", bufIdx_wr); +#endif + + // add general message header: message ID, + // T-Tracer Message format + // FORMAT = int,frame : int,slot : int,datetime_yyyymmdd : int,datetime_hhmmssmmm : + // int,frame_type : int,freq_range : int,subcarrier_spacing : int,cyclic_prefix : int,symbols_per_slot : + // int,Nid_cell : int,rnti : + // int,rb_size : int,rb_start : int,start_symbol_index : int,nr_of_symbols : + // int,qam_mod_order : int,mcs_index : int,mcs_table : int,nrOfLayers : + // int,transform_precoding : int,dmrs_config_type : int,ul_dmrs_symb_pos : int,number_dmrs_symbols : + // int,dmrs_port : int,dmrs_nscid : + // int,nb_antennas_rx : int,number_of_bits : buffer,data + memcpy(&addr_wr[bufIdx_wr], &e.type, sizeof(uint16_t)); + bufIdx_wr += sizeof(uint16_t); + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.frame].i, sizeof(uint16_t)); + bufIdx_wr += sizeof(uint16_t); + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.slot].i, sizeof(uint8_t)); + bufIdx_wr += sizeof(uint8_t); + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.datetime_yyyymmdd].i, sizeof(uint32_t)); + bufIdx_wr += sizeof(uint32_t); + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.datetime_hhmmssmmm].i, sizeof(uint32_t)); + bufIdx_wr += sizeof(uint32_t); + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.frame_type].i, sizeof(uint8_t)); + bufIdx_wr += sizeof(uint8_t); + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.freq_range].i, sizeof(uint8_t)); + bufIdx_wr += sizeof(uint8_t); + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.subcarrier_spacing].i, sizeof(uint8_t)); + bufIdx_wr += sizeof(uint8_t); + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.cyclic_prefix].i, sizeof(uint8_t)); + bufIdx_wr += sizeof(uint8_t); + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.symbols_per_slot].i, sizeof(uint8_t)); + bufIdx_wr += sizeof(uint8_t); + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.Nid_cell].i, sizeof(uint16_t)); + bufIdx_wr += sizeof(uint16_t); + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.rnti].i, sizeof(uint16_t)); + bufIdx_wr += sizeof(uint16_t); + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.rb_size].i, sizeof(uint16_t)); + bufIdx_wr += sizeof(uint16_t); + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.rb_start].i, sizeof(uint16_t)); + bufIdx_wr += sizeof(uint16_t); + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.start_symbol_index].i, sizeof(uint8_t)); + bufIdx_wr += sizeof(uint8_t); + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.nr_of_symbols].i, sizeof(uint8_t)); + bufIdx_wr += sizeof(uint8_t); + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.qam_mod_order].i, sizeof(uint8_t)); + bufIdx_wr += sizeof(uint8_t); + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.mcs_index].i, sizeof(uint8_t)); + bufIdx_wr += sizeof(uint8_t); + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.mcs_table].i, sizeof(uint8_t)); + bufIdx_wr += sizeof(uint8_t); + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.nrOfLayers].i, sizeof(uint8_t)); + bufIdx_wr += sizeof(uint8_t); + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.transform_precoding].i, sizeof(uint8_t)); + bufIdx_wr += sizeof(uint8_t); + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.dmrs_config_type].i, sizeof(uint8_t)); + bufIdx_wr += sizeof(uint8_t); + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.ul_dmrs_symb_pos].i, sizeof(uint16_t)); + bufIdx_wr += sizeof(uint16_t); + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.number_dmrs_symbols].i, sizeof(uint8_t)); + bufIdx_wr += sizeof(uint8_t); + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.dmrs_port].i, sizeof(uint16_t)); + bufIdx_wr += sizeof(uint16_t); + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.dmrs_nscid].i, sizeof(uint16_t)); + bufIdx_wr += sizeof(uint16_t); + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.nb_antennas_rx].i, sizeof(uint8_t)); + bufIdx_wr += sizeof(uint8_t); + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.number_of_bits].i, sizeof(uint32_t)); + bufIdx_wr += sizeof(uint32_t); + + printf("\nTime Stamp: %d_%d", e.e[trace_msg_data.datetime_yyyymmdd].i, e.e[trace_msg_data.datetime_hhmmssmmm].i); + + // add message body: length in bytes + recorded data + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.data].bsize, sizeof(uint32_t)); + bufIdx_wr += sizeof(uint32_t); + + // read data from buffer and convert from unsigned char * array to int 16 using the right endianness + // T-tracer: Little Endian + // For BITS Messages, example: UE_PHY_UL_SCRAMBLED_TX_BITS: data in bytes + + if (is_bits_messages(traces_bits_support_data_Collection_format_idx, n_bits_msgs, e.type)) { + for (int byte_idx = 0; byte_idx < e.e[trace_msg_data.data].bsize; byte_idx += 1) { + // printf("%d, ", buf[byte_idx]); + memcpy(&addr_wr[bufIdx_wr], &buf[byte_idx], sizeof(uint8_t)); + bufIdx_wr += sizeof(uint8_t); + } + + } else { + for (int byte_idx = 0; byte_idx < e.e[trace_msg_data.data].bsize; byte_idx += 2) { + // For a little-endian system: + memcpy(&addr_wr[bufIdx_wr], &buf[byte_idx], sizeof(uint8_t)); + bufIdx_wr += sizeof(uint8_t); + memcpy(&addr_wr[bufIdx_wr], &buf[byte_idx + 1], sizeof(uint8_t)); + bufIdx_wr += sizeof(uint8_t); + } + } + /* + for (int byte_idx_i = 0; byte_idx_i < e.e[d.nr_ul_fd_dmrs_data].bsize; byte_idx_i+=4) { + int16_t I = buf[byte_idx_i] | (buf[byte_idx_i+1] << 8); + int16_t Q = buf[byte_idx_i+2] | (buf[byte_idx_i+3] << 8); + printf ("idx %d, ", byte_idx_i); + printf ("\n%d", I); + printf ("\n%d", Q); + } + */ + // check if the current frame and slot are different from the previous frame and slot + // Then, increase the record index + current_frame = e.e[trace_msg_data.frame].i; + current_slot = e.e[trace_msg_data.slot].i; + + // increase sync offset index if the current frame is different from the previous frame + if ((current_frame != prev_frame) && nrecord_idx >= number_records) { + sync_offset_index++; + } + + if (current_frame != prev_frame || current_slot != prev_slot) { + nrecord_idx++; + // Update previous frame and slot numbers + prev_frame = current_frame; + prev_slot = current_slot; + } +#ifdef DEBUG_T_Tracer + printf("\nMessage Info: msg_id %s (%d) \n", event_name_from_id(database, e.type), e.type); + printf("frame %d, slot %d, datetime %d_%d\n", + e.e[trace_msg_data.frame].i, + e.e[trace_msg_data.slot].i, + e.e[trace_msg_data.datetime_yyyymmdd].i, + e.e[trace_msg_data.datetime_hhmmssmmm].i); + printf("frame_type %d, freq_range %d, subcarrier_spacing %d, cyclic_prefix %d, symbols_per_slot %d\n", + e.e[trace_msg_data.frame_type].i, + e.e[trace_msg_data.freq_range].i, + e.e[trace_msg_data.subcarrier_spacing].i, + e.e[trace_msg_data.cyclic_prefix].i, + e.e[trace_msg_data.symbols_per_slot].i); + printf("Nid_cell %d, rnti %d, rb_size %d, rb_start %d, start_symbol_index %d, nr_of_symbols %d\n", + e.e[trace_msg_data.Nid_cell].i, + e.e[trace_msg_data.rnti].i, + e.e[trace_msg_data.rb_size].i, + e.e[trace_msg_data.rb_start].i, + e.e[trace_msg_data.start_symbol_index].i, + e.e[trace_msg_data.nr_of_symbols].i); + printf("qam_mod_order %d, mcs_index %d, mcs_table %d, nrOfLayers %d, transform_precoding %d\n", + e.e[trace_msg_data.qam_mod_order].i, + e.e[trace_msg_data.mcs_index].i, + e.e[trace_msg_data.mcs_table].i, + e.e[trace_msg_data.nrOfLayers].i, + e.e[trace_msg_data.transform_precoding].i); + printf("dmrs_config_type %d, ul_dmrs_symb_pos %d, number_dmrs_symbols %d, dmrs_port %d, dmrs_nscid %d\n", + e.e[trace_msg_data.dmrs_config_type].i, + e.e[trace_msg_data.ul_dmrs_symb_pos].i, + e.e[trace_msg_data.number_dmrs_symbols].i, + e.e[trace_msg_data.dmrs_port].i, + e.e[trace_msg_data.dmrs_nscid].i); + printf("nb_antennas_rx %d, number_of_bits %d, data size %d\n", + e.e[trace_msg_data.nb_antennas_rx].i, + e.e[trace_msg_data.number_of_bits].i, + e.e[trace_msg_data.data].bsize); +#endif + } // End of start recording flag + } // end of if statement for the supported messages based on Data Collection Trace Messages Structure + else { + printf("ERROR: Requested Message is not based on Data Collection Trace Messages Structure\n"); + printf("ERROR: Requested Message ID: %d\n", e.type); + } + } // end of if statement for the requested messages + } // end while loop of reading events + else { + // No data, just loop and check time + usleep(100); // optional: avoid busy-waiting + } + } // End of while loop to read events + + // de-activate the tracee in the nr-softmodem + printf("\n De-activated Tracer message:\n"); + for (i = 0; i < num_req_tracer_msgs; i++) { + char *on_off_name = event_name_from_id(database, req_tracer_msgs_indices[i]); + on_off(database, on_off_name, is_on, 0); + // printf("\n %d, %s, ", req_tracer_msgs_indices[i], on_off_name); + // on_off(database, "GNB_PHY_DL_OUTPUT_SIGNAL", is_on, 1); + } + // De-activate the tracee in the nr-softmodem + activate_traces(socket, number_of_events, is_on); + printf("\n De-activated Traces"); + // Get the end time + struct timespec end_time = get_current_time(); + // Calculate the time difference + double time_diff = calculate_time_difference(start_time, end_time); + printf("Total Time difference: %.2f ms\n", time_diff); + printf("Time difference per record: %.2f ms\n", time_diff / (number_records + max_sync_offset)); + + // discard stale or previous record data for the first DISCARD_RECORD_DURATION_MS + struct timespec record_start, record_now; + clock_gettime(CLOCK_MONOTONIC, &record_start); + + while (1) { + clock_gettime(CLOCK_MONOTONIC, &record_now); + double elapsed_ms = calculate_time_difference(record_start, record_now); + if (elapsed_ms >= DISCARD_RECORD_DURATION_MS) { + break; // Stop after 10ms + } + int poll_ret = poll(&event_poll_fd, 1, 1); // 1 ms timeout for poll + if (poll_ret > 0 && (event_poll_fd.revents & POLLIN)) { + event e = get_event(socket, &ebuf, database); + printf("%d", e.type); + if (e.type == -1) { + printf("\n Link broken or unexpected message received. Re-establishing connection...\n"); + reestablish_connection(&socket, ip, port, number_of_events, is_on); + continue; + } + } else { + // No data, just loop and check time + usleep(100); // optional: avoid busy-waiting + } + } // End of while loop to discard stale records + } + } // End a while loop to check for the "stop" command + // de-activate the tracee in the nr-softmodem + + free_database(database); + free(is_on); + close(socket); + + return 0; +} diff --git a/common/utils/T/tracer/t_tracer_app_ue.c b/common/utils/T/tracer/t_tracer_app_ue.c new file mode 100644 index 0000000000..141bbd2385 --- /dev/null +++ b/common/utils/T/tracer/t_tracer_app_ue.c @@ -0,0 +1,976 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file common/utils/T/tracer/t_tracer_app_ue.c + * \brief T-Tracer UE service to capture tracee Messages from UE, it is used by data recording application + * \author Abdo Gaber + * \date 2025 + * \version 1.0 + * \company Emerson, NI Test and Measurement + * \email: + * \note + * \warning + */ + +#include +#include +#include +#include +#include +#include "database.h" +#include "event.h" +#include "handler.h" +#include "logger/logger.h" +#include "utils.h" +#include "event_selector.h" +#include "configuration.h" +#include "shared_memory_config.h" +#include +#include +#include +#include +#include +#include +#include +#define MAX_FRAME_INDEX 1023 +#define MAX_SLOT_INDEX 19 +#define DEBUG_T_Tracer +#define DEBUG_BUFFER +// Duration to discard recording in milliseconds to mitigate stale or previous record data +#define DISCARD_RECORD_DURATION_MS 10 +// #include + +// Combine bytes in little-endian format +int combine_bytes(const uint8_t *bytes, size_t num_bytes) +{ + int result = 0; + for (size_t i = 0; i < num_bytes; ++i) { + result |= (bytes[i] << (i * 8)); + } + return result; +} + +// Convert an integer to an array of bytes in little-endian format +void int_to_bytes(int num, uint8_t *bytes, size_t num_bytes) +{ + for (size_t i = 0; i < num_bytes; ++i) { + bytes[i] = (num >> (i * 8)) & 0xFF; + } +} + +// Check if the message is in the list of bits messages +bool is_bits_messages(int traces_bits_support_data_Collection_format_idx[], int n_bits_msgs, int msg_id) +{ + for (int i = 0; i < n_bits_msgs; i++) { + if (msg_id == traces_bits_support_data_Collection_format_idx[i]) { + return true; + } + } + return false; +} + +// Get the current time +struct timespec get_current_time() +{ + struct timespec time; + clock_gettime(CLOCK_MONOTONIC, &time); + return time; +} + +// Function to convert timespec to microseconds +long long timespec_to_microseconds(struct timespec time) +{ + return (time.tv_sec * 1000000LL) + (time.tv_nsec / 1000); +} + +// Calculate the time difference in milliseconds +double calculate_time_difference(struct timespec start, struct timespec end) +{ + double start_ms = start.tv_sec * 1000.0 + start.tv_nsec / 1000000.0; + double end_ms = end.tv_sec * 1000.0 + end.tv_nsec / 1000000.0; + return end_ms - start_ms; +} + +// Get Time Stamp in microseconds in YYYYMMDDHHMMSSmmmuuu format +char *get_time_stamp_usec(char time_stamp_str[]) +{ + // initialization to measure time stamp --This part should be moved to inilization part + time_t my_time; + struct tm *timeinfo; + time(&my_time); + struct timeval tv; + + // get time stamp + timeinfo = localtime(&my_time); + gettimeofday(&tv, NULL); + // Add time stamp: yyyy mm dd hh mm ss usec + uint16_t year = timeinfo->tm_year + 1900; + uint8_t mon = timeinfo->tm_mon + 1; + uint8_t mday = timeinfo->tm_mday; + uint8_t hour = timeinfo->tm_hour; + uint8_t min = timeinfo->tm_min; + uint8_t sec = timeinfo->tm_sec; + uint16_t usec = (tv.tv_usec); + // printf ("Time stamp: %d_%d_%d_%d_%d_%d_%d \n",year,mon,mday,hour,min,sec,usec); + // sprintf(time_stamp_str, "%d_%d_%d_%d_%d_%d_%d",year,mon,mday,hour,min,sec,usec); + sprintf(time_stamp_str, "%04d%02d%02d%02d%02d%02d%06d", year, mon, mday, hour, min, sec, usec); + + return time_stamp_str; +} + +// Convert timestamp string to integer +int convert_time_stamp_to_int(const char *timestamp) +{ + return atoi(timestamp); +} + +// Split timestamp string and convert to integer +int split_time_stamp_and_convert_to_int(char time_stamp_str[], int shift, int length) +{ + char time_part[length + 1]; // Buffer to hold the date part YYYYMMDD or HHMMSSmmm + // Copy the first 8 or 9 characters (YYYYMMDD) to HHMMSSmmm + strncpy(time_part, time_stamp_str + shift, length); + time_part[length] = '\0'; // Null-terminate the string + // Convert timestamp string to integer + return convert_time_stamp_to_int(time_part); +} + +void err_exit(char *buf) +{ + fprintf(stderr, "%s\n", buf); + exit(1); +} + +// create shared memory +int create_shm(char **addrN, const char *shm_path, int projectId) +{ + key_t key; + if (-1 != open(shm_path, O_CREAT, 0777)) { + key = ftok(shm_path, projectId); + } else { + err_exit("Error: open shared memory"); + } + + if (key < 0) { + err_exit("Error: ftok error"); + } + + int shm_id; + shm_id = shmget(key, SHMSIZE, IPC_CREAT | IPC_EXCL | 0664); + if (shm_id == -1) { + if (errno == EEXIST) { + printf("Error: shared memeory already exist\n"); + shm_id = shmget(key, 0, 0); + printf("reference shm_id = %d\n", shm_id); + } else { + perror("errno"); + err_exit("shmget error"); + } + } + char *addr; + // address to attach - attach for read & write + if ((addr = shmat(shm_id, 0, 0)) == (void *)-1) { + if (shmctl(shm_id, IPC_RMID, NULL) == -1) + err_exit("Error: shmctl error"); + else { + printf("Attach shared memory failed\n"); + printf("remove shared memory identifier successful\n"); + } + err_exit("shmat error"); + } + *addrN = addr; + return shm_id; +} + +// delete shared memory +void del_shm(char *addr, int shm_id) +{ + if (shmdt(addr) < 0) + err_exit("shmdt error"); + + if (shmctl(shm_id, IPC_RMID, NULL) == -1) + err_exit("shmctl error"); + else { + printf("Remove shared memory identifier successful\n"); + } +} + +/* this function sends the activated traces to the nr-softmodem */ +void activate_traces(int socket, int number_of_events, int *is_on) +{ + char t = 1; + if (socket_send(socket, &t, 1) == -1 || socket_send(socket, &number_of_events, sizeof(int)) == -1 + || socket_send(socket, is_on, number_of_events * sizeof(int)) == -1) + abort(); +} + +void usage(void) +{ + printf( + "options:\n" + " -d this option is mandatory\n" + " -ip connect to given IP address (default %s)\n" + " -p connect to given port (default %d)\n", + DEFAULT_REMOTE_IP, + DEFAULT_REMOTE_PORT); + exit(1); +} + +// class to store the message and the action to enable capture selected data +// 0: do not record message +// 1: record message +struct trace_struct { + char on_off_name[100]; + int on_off_action; +}; + +// struct for trace message based on Data Collection Trace Messages Structure +// you need to define the vararibles of each message +typedef struct { + /* Data Collection Trace Message Structure */ + int frame; + int slot; + int datetime_yyyymmdd; + int datetime_hhmmssmmm; + int frame_type, freq_range, subcarrier_spacing, cyclic_prefix, symbols_per_slot; + int Nid_cell, rnti; + int rb_size, rb_start, start_symbol_index, nr_of_symbols; + int qam_mod_order, mcs_index, mcs_table, nrOfLayers, transform_precoding; + int dmrs_config_type, ul_dmrs_symb_pos, number_dmrs_symbols; + int dmrs_port, dmrs_nscid, nb_antennas_tx, number_of_bits; + int data_size, data; +} event_trace_msg_data; + +void setup_trace_msg_data(event_trace_msg_data *d, void *database) +{ + database_event_format f; + int i; + + /* Data Collection Trace Message Structure */ + // FORMAT = int,frame : int,slot : int,datetime_yyyymmdd : int,datetime_hhmmssmmm : + // int,frame_type : int,freq_range : int,subcarrier_spacing : int,cyclic_prefix : int,symbols_per_slot : + // int,Nid_cell : int,rnti : + // int,rb_size : int,rb_start : int,start_symbol_index : int,nr_of_symbols : + // int,qam_mod_order : int,mcs_index : int,mcs_table : int,nrOfLayers : + // int,transform_precoding : int,dmrs_config_type : int,ul_dmrs_symb_pos : int,number_dmrs_symbols : + // int,dmrs_port : int,dmrs_nscid : + // int,nb_antennas_tx : int,number_of_bits : buffer,data + + // Initialize the data structure + d->frame = -1; + d->slot = -1; + d->datetime_yyyymmdd = -1; + d->datetime_hhmmssmmm = -1; + d->frame_type = -1; + d->freq_range = -1; + d->subcarrier_spacing = -1; + d->cyclic_prefix = -1; + d->symbols_per_slot = -1; + d->Nid_cell = -1; + d->rnti = -1; + d->rb_size = -1; + d->rb_start = -1; + d->start_symbol_index = -1; + d->nr_of_symbols = -1; + d->qam_mod_order = -1; + d->mcs_index = -1; + d->mcs_table = -1; + d->nrOfLayers = -1; + d->transform_precoding = -1; + d->dmrs_config_type = -1; + d->ul_dmrs_symb_pos = -1; + d->number_dmrs_symbols = -1; + d->dmrs_port = -1; + d->dmrs_nscid = -1; + d->nb_antennas_tx = -1; + d->number_of_bits = -1; + d->data = -1; + +/* this macro looks for a particular element and checks its type */ +#define G(var_name, var_type, var) \ + if (!strcmp(f.name[i], var_name)) { \ + if (strcmp(f.type[i], var_type)) { \ + printf("Error: Trace Message has a bad type for %s\n", var_name); \ + exit(1); \ + } \ + var = i; \ + continue; \ + } + + /* ------------------------------*/ + /* Create Macro for Data Collection Trace Message */ + /* ------------------------------*/ + // Data Collection Trace Message Structure + // Example: GNB_PHY_UL_FD_PUSCH_IQ, GNB_PHY_UL_FD_DMRS_ID, + // GNB_PHY_UL_FD_CHAN_EST_DMRS_POS, GNB_PHY_UL_FD_CHAN_EST_DMRS_INTERPL + // GNB_PHY_UL_PAYLOAD_RX_BITS + // UE_PHY_UL_SCRAMBLED_TX_BITS + // UE_PHY_UL_PAYLOAD_TX_BITS + // Get a template of any message based on Data Collection Trace Messages Structure + int Trace_MSG_ID = event_id_from_name(database, "GNB_PHY_UL_FD_PUSCH_IQ"); + f = get_format(database, Trace_MSG_ID); + + /* get the elements of the trace + * the value is an index in the event, see below */ + // FORMAT = int,frame : int,slot : int,datetime_yyyymmdd : int,datetime_hhmmssmmm : + // int,frame_type : int,freq_range : int,subcarrier_spacing : int,cyclic_prefix : int,symbols_per_slot : + // int,Nid_cell : int,rnti : + // int,rb_size : int,rb_start : int,start_symbol_index : int,nr_of_symbols : + // int,qam_mod_order : int,mcs_index : int,mcs_table : int,nrOfLayers : + // int,transform_precoding : int,dmrs_config_type : int,ul_dmrs_symb_pos : int,number_dmrs_symbols : + // int,dmrs_port : int,dmrs_nscid : + // int,nb_antennas_tx : int,number_of_bits : buffer,data + + for (i = 0; i < f.count; i++) { + G("frame", "int", d->frame) + G("slot", "int", d->slot) + G("datetime_yyyymmdd", "int", d->datetime_yyyymmdd) + G("datetime_hhmmssmmm", "int", d->datetime_hhmmssmmm) + G("frame_type", "int", d->frame_type) + G("freq_range", "int", d->freq_range) + G("subcarrier_spacing", "int", d->subcarrier_spacing) + G("cyclic_prefix", "int", d->cyclic_prefix) + G("symbols_per_slot", "int", d->symbols_per_slot) + G("Nid_cell", "int", d->Nid_cell) + G("rnti", "int", d->rnti) + G("rb_size", "int", d->rb_size) + G("rb_start", "int", d->rb_start) + G("start_symbol_index", "int", d->start_symbol_index) + G("nr_of_symbols", "int", d->nr_of_symbols) + G("qam_mod_order", "int", d->qam_mod_order) + G("mcs_index", "int", d->mcs_index) + G("mcs_table", "int", d->mcs_table) + G("nrOfLayers", "int", d->nrOfLayers) + G("transform_precoding", "int", d->transform_precoding) + G("dmrs_config_type", "int", d->dmrs_config_type) + G("ul_dmrs_symb_pos", "int", d->ul_dmrs_symb_pos) + G("number_dmrs_symbols", "int", d->number_dmrs_symbols) + G("dmrs_port", "int", d->dmrs_port) + G("dmrs_nscid", "int", d->dmrs_nscid) + // bug in T-Tracer Framework, need to be checked that is why we are getting + // the right tx antennas only if we set to rx "nb_antennas_rx" + G("nb_antennas_rx", "int", d->nb_antennas_tx) + G("number_of_bits", "int", d->number_of_bits) + G("data", "buffer", d->data) + } + // if (d->frame == -1 || d->slot == -1) goto error; +#undef G + return; +} + +// Function to check if a value is in the array +int isValueInArray(int value, int arr[], int size) +{ + for (int i = 0; i < size; i++) { + if (arr[i] == value) { + return 1; // Value found + } + } + return 0; // Value not found +} + +void reestablish_connection(int *socket, char *ip, int port, int number_of_events, int *is_on) +{ + clear_remote_config(); + if (*socket != -1) + close(*socket); + + /* connect to the nr-softmodem */ + *socket = connect_to(ip, port); + if (*socket == -1) { + printf("\n Failed to connect to nr-softmodem. Retrying...\n"); + return; + } + printf("\n Connected"); + + /* activate the traces in the nr-softmodem */ + activate_traces(*socket, number_of_events, is_on); + printf("\n Activated Traces in nr-softmodem"); +} + +int main(int n, char **v) +{ + // Define and initialize an array of strings to list + // trace_msgs_support_data_Collection_format + // it is used to parse the requested messages if it is based + // on Data Collection Trace Messages Structure and supported tracer messages indices + char *traces_iq_support_data_Collection_format[] = {"GNB_PHY_UL_FD_PUSCH_IQ", + "GNB_PHY_UL_FD_DMRS", + "GNB_PHY_UL_FD_CHAN_EST_DMRS_POS", + "GNB_PHY_UL_FD_CHAN_EST_DMRS_INTERPL"}; + char *traces_bits_support_data_Collection_format[] = {"GNB_PHY_UL_PAYLOAD_RX_BITS", + "UE_PHY_UL_SCRAMBLED_TX_BITS", + "UE_PHY_UL_PAYLOAD_TX_BITS"}; + // extra number of records to simlify Sync between base station and UE synchronization records. + // if you have network delay, you can increase the number of records to capture + int max_sync_offset = 6; // 6 frames ~ 60 ms + // all supported messages + // Calculate the size of the combined array + int n_iq_msgs = sizeof(traces_iq_support_data_Collection_format) / sizeof(traces_iq_support_data_Collection_format[0]); + int n_bits_msgs = sizeof(traces_bits_support_data_Collection_format) / sizeof(traces_bits_support_data_Collection_format[0]); + int n_msgs_based_data_Collection_format = n_iq_msgs + n_bits_msgs; + + // Create the combined array + char *traces_support_data_Collection_format[n_msgs_based_data_Collection_format]; + // Copy IQ messages to the combined array + for (int i = 0; i < n_iq_msgs; i++) { + traces_support_data_Collection_format[i] = traces_iq_support_data_Collection_format[i]; + } + + // Copy Bits messages to the combined array + for (int i = 0; i < n_bits_msgs; i++) { + traces_support_data_Collection_format[i + n_iq_msgs] = traces_bits_support_data_Collection_format[i]; + } + + uint16_t msg_id = 0; + uint16_t start_frame_number = 0; + uint32_t number_records = 0; // number of records to capture, it is number of slots + // array to store the requested tracer messages indices + int req_tracer_msgs_indices[100] = {0}; + // define variables --> to do: add all of them to be class of pointers + char *database_filename = NULL; + void *database; + char *ip = DEFAULT_REMOTE_IP; + char ip_address[16]; // max IP address length is 15 + 1 for null terminator + int port = DEFAULT_REMOTE_PORT; + int *is_on; + int number_of_events; + int i; + int socket = -1; + char trace_time_stamp_str[30]; + + // data structure for the trace messages based on Data Collection Trace Messages Structure + event_trace_msg_data trace_msg_data; + + // initlization variables + unsigned int bufIdx_wr = 0; + unsigned int bufIdx_rd = 0; + uint8_t num_req_tracer_msgs = 0; + + // initilaze shared memory + char *addr_wr, *addr_rd; + printf("\n Data Collection Service: Initializing shared memory ..."); + printf("\n Directory 1: %s, Directory 2: %s", GETKEYDIR1_UE, GETKEYDIR2_UE); + printf("\n Project ID: %d\n", PROJECTID_UE); + int shm_id_wr = create_shm(&addr_wr, GETKEYDIR1_UE, PROJECTID_UE); + int shm_id_rd = create_shm(&addr_rd, GETKEYDIR2_UE, PROJECTID_UE); + del_shm(addr_wr, shm_id_wr); + del_shm(addr_rd, shm_id_rd); + shm_id_wr = create_shm(&addr_wr, GETKEYDIR1_UE, PROJECTID_UE); + shm_id_rd = create_shm(&addr_rd, GETKEYDIR2_UE, PROJECTID_UE); + + /* write on a socket fails if the other end is closed and we get SIGPIPE */ + if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) + abort(); + + /* parse command line options */ + // Port number and IP address are given via API and not via command line + for (i = 1; i < n; i++) { + if (!strcmp(v[i], "-h") || !strcmp(v[i], "--help")) + usage(); + if (!strcmp(v[i], "-d")) { + if (i > n - 2) + usage(); + database_filename = v[++i]; + continue; + } + if (!strcmp(v[i], "-ip")) { + if (i > n - 2) + usage(); + ip = v[++i]; + continue; + } + if (!strcmp(v[i], "-p")) { + if (i > n - 2) + usage(); + port = atoi(v[++i]); + continue; + } + usage(); + } + + if (database_filename == NULL) { + printf("ERROR: Provide a database file (-d)\n"); + exit(1); + } + + /* load the database T_messages.txt */ + database = parse_database(database_filename); + load_config_file(database_filename); + + /* an array of int for all the events defined in the database is needed */ + number_of_events = number_of_ids(database); + is_on = calloc(number_of_events, sizeof(int)); + if (is_on == NULL) + abort(); + + // Set first byte of the shared memory to 0 + addr_rd[0] = 0; // important to check if we have new requested messages + + // read requested tracer msg indices from memory + printf("\n Data Collection Service: Waiting for messages request ...\n"); + // 0: Wait + // 1: config + // 2: record + // 3: stop + // Wait for Action Config + while (1) { + if ((uint8_t)(addr_rd[0]) == 0) { + usleep(50); // sleep for 50 us: 0.5 ms slot duration + } + // config state + else if ((uint8_t)(addr_rd[0]) == 1) { + get_time_stamp_usec(trace_time_stamp_str); + printf("\n Received config message. Time Stamp: %s", trace_time_stamp_str); + + // get the IP address length in bytes + bufIdx_rd = 1; + uint8_t ip_address_length = addr_rd[bufIdx_rd]; + bufIdx_rd += 1; // + 1 byte = IP address length + + // read the IP address + for (int i = 0; i < ip_address_length; i++) { + ip_address[i] = addr_rd[bufIdx_rd]; + bufIdx_rd += 1; + } + + ip = ip_address; + + // get the array bytes of the port number : 2 bytes + uint8_t port_number_bytes[2] = {addr_rd[bufIdx_rd], addr_rd[bufIdx_rd + 1]}; + bufIdx_rd += 2; // + 2 bytes = start frame number + + port = combine_bytes(port_number_bytes, 2); + printf("\n Parameters: IP Address length: %d, IP Address: %s, Port Number: %d \n", ip_address_length, ip_address, port); + addr_rd[0] = 0; // reset memory : to wait for record action + break; + } + } + // Establish connection to the nr-softmodem + clear_remote_config(); + if (socket != -1) + close(socket); + + /* connect to the nr-softmodem */ + socket = connect_to(ip, port); + printf("\n Connected to nr-UEsoftmodem"); + + // Read Action record or stop + printf("\n Data Collection Service: Waiting for record message ...\n"); + while (1) { + // wait for Action record + if ((uint8_t)(addr_rd[0]) == 0) { + usleep(50); // sleep for 50 us: 0.5 ms slot duration + } + + // quit state + else if ((uint8_t)(addr_rd[0]) == 3) { + printf("\n Received 'stop' command. Exiting..."); + printf("\n "); + // Clean up and exit + break; + } + // record state + else if ((uint8_t)(addr_rd[0]) == 2) { + // clear remote buffer if there is + clear_remote_config(); + get_time_stamp_usec(trace_time_stamp_str); + printf("\n Received record message. Time Stamp: %s", trace_time_stamp_str); + + // read number of requested messages + bufIdx_rd = 1; + num_req_tracer_msgs = addr_rd[bufIdx_rd]; + bufIdx_rd += 1; + printf("\n Number of requested tracer messages: %d,", num_req_tracer_msgs); + // reset memory : action to wait for next record action + addr_rd[0] = 0; + + // read tracer msg IDs - every message ID has been stored in two bytes + for (uint8_t msg_n = 0; msg_n < num_req_tracer_msgs; msg_n++) { + // get the array bytes of the tracer message ID: 2 bytes + uint8_t msg_id_bytes[2] = {addr_rd[bufIdx_rd], addr_rd[bufIdx_rd + 1]}; + bufIdx_rd += 2; // + 2 bytes = message ID + msg_id = combine_bytes(msg_id_bytes, 2); + + req_tracer_msgs_indices[msg_n] = msg_id; + printf(" msg_id: %d, ", msg_id); + } + // get the array bytes of the number of records: 4 bytes + uint8_t number_records_bytes[4] = {addr_rd[bufIdx_rd], + addr_rd[bufIdx_rd + 1], + addr_rd[bufIdx_rd + 2], + addr_rd[bufIdx_rd + 3]}; + bufIdx_rd += 4; // + 4 bytes = number of records + + number_records = combine_bytes(number_records_bytes, 4); + + printf("num_records: %d, ", number_records); + + // get the array bytes of the start frame number : 2 bytes + uint8_t start_frame_number_bytes[2] = {addr_rd[bufIdx_rd], addr_rd[bufIdx_rd + 1]}; + bufIdx_rd += 2; // + 2 bytes = start frame number + + start_frame_number = combine_bytes(start_frame_number_bytes, 2); + + printf("start_frame: %d\n", start_frame_number); + + /* activate the trace in this array */ + printf("\n Activate Tracer messages in on_off array: \n"); + for (i = 0; i < num_req_tracer_msgs; i++) { + char *on_off_name = event_name_from_id(database, req_tracer_msgs_indices[i]); + on_off(database, on_off_name, is_on, 1); + printf("%d, %s, ", req_tracer_msgs_indices[i], on_off_name); + // on_off(database, "GNB_PHY_DL_OUTPUT_SIGNAL", is_on, 1); + } + + // get the event IDs for the bit messages + int traces_bits_support_data_Collection_format_idx[n_bits_msgs]; + for (int i = 0; i < n_bits_msgs; i++) { + traces_bits_support_data_Collection_format_idx[i] = + event_id_from_name(database, traces_bits_support_data_Collection_format[i]); + } + + // all supported messages + int traces_support_data_Collection_format_idx[n_msgs_based_data_Collection_format]; + for (int i = 0; i < n_msgs_based_data_Collection_format; i++) { + traces_support_data_Collection_format_idx[i] = event_id_from_name(database, traces_support_data_Collection_format[i]); + } + + // setup data for the trace messages + setup_trace_msg_data(&trace_msg_data, database); + printf("\n Setup Trace Data Done"); + + // Get the start time + struct timespec start_time = get_current_time(); + + /* activate the tracee in the nr-softmodem */ + activate_traces(socket, number_of_events, is_on); + printf("\n Activated Traces in nr-UEsoftmodem"); + + /* a buffer needed to receive events from the nr-softmodem */ + OBUF ebuf = {osize : 0, omaxsize : 0, obuf : NULL}; + /* read events */ + int nrecord_idx = 0; + bufIdx_wr = 0; + // logic to be sure that we have a complete slot record + bool start_recording = false; + bool got_ref_frame_slot = false; + int ref_slot = 0; + int ref_frame = 0; + int slot_difference = 0; + int frame_difference = 0; + int current_frame = 0, prev_frame = 0, current_slot = 0, prev_slot = 0; + // offset to sync between base station and UE synchronization records or power measurements + int sync_offset_index = 0; // increase the index only if the index of frame changes after getting all records + // since we will use the frame differece to do extra records, we should be sure that the last slot is recorded completely + printf("\n\n Data Collection Service: Start reading messages ..."); + struct pollfd event_poll_fd; + event_poll_fd.fd = socket; + event_poll_fd.events = POLLIN; + while (1) { + // stop if number of records is done + if ((nrecord_idx >= number_records) && (sync_offset_index >= max_sync_offset)) { + // We added one to the number of records to capture the last record completely + // if we have several messages enabled per slot + break; + } + int poll_ret = poll(&event_poll_fd, 1, 1); // 1 ms timeout for poll + if (poll_ret > 0 && (event_poll_fd.revents & POLLIN)) { + event e = get_event(socket, &ebuf, database); + if (e.type == -1) { + printf("\n Link broken or unexpected message received. Re-establishing connection...\n"); + reestablish_connection(&socket, ip, port, number_of_events, is_on); + continue; // Skip further processing and retry + } + + //------------------------- + // GNB_PHY_UL_FD_PUSCH_IQ, GNB_PHY_UL_FD_DMRS_ID, GNB_PHY_UL_FD_CHAN_EST_DMRS_POS, + // UE_PHY_UL_SCRAMBLED_TX_BITS, GNB_PHY_UL_PAYLOAD_RX_BITS, UE_PHY_UL_PAYLOAD_TX_BITS + //------------------------- + // is it a requested message + if (isValueInArray(e.type, req_tracer_msgs_indices, num_req_tracer_msgs)) { + // is it based on Data Collection Trace Messages Structure + if (isValueInArray(e.type, traces_support_data_Collection_format_idx, n_msgs_based_data_Collection_format)) { + // Start recording from the next slot to mitigate capturing partial data + // check if the current frame and slot are different from the previous frame and slot + // Then, increase the record index + if (start_recording == false) { + if (got_ref_frame_slot == false) { + ref_frame = e.e[trace_msg_data.frame].i; + ref_slot = e.e[trace_msg_data.slot].i; + printf("\nMessage Info: msg_id %s (%d) \n", event_name_from_id(database, e.type), e.type); + got_ref_frame_slot = true; + } + + current_frame = e.e[trace_msg_data.frame].i; + current_slot = e.e[trace_msg_data.slot].i; + frame_difference = (current_frame - ref_frame + MAX_FRAME_INDEX + 1) % (MAX_FRAME_INDEX + 1); + slot_difference = (current_slot - ref_slot + MAX_SLOT_INDEX + 1) % (MAX_SLOT_INDEX + 1); + printf("\n First frame.slot: %d.%d, current frame.slot: %d.%d, diff frame.slot: %d.%d", + ref_frame, + ref_slot, + current_frame, + current_slot, + frame_difference, + slot_difference); + + if ((ref_frame != current_frame) || (ref_slot != current_slot)) { + start_recording = true; + printf("\n Start recording from frame: %d, slot: %d ", e.e[trace_msg_data.frame].i, e.e[trace_msg_data.slot].i); + } + } + // start recording from the next frame to mitigate capturing partial data + if (start_recording == true) { + /* this is how to access the elements of the Data Collection trace messages. + * we use e.e[] and then the correct suffix, here + * it's .i for the integer and .b for the buffer and .bsize for the buffer size + * see in event.h the structure event_arg + */ + unsigned char *buf = e.e[trace_msg_data.data].b; + + printf("\n\nRecord number: %d", nrecord_idx); +#ifdef DEBUG_BUFFER + printf("\nBuffer index in bytes: %d", bufIdx_wr); +#endif + + // add general message header: message ID, + // T-Tracer Message format + // FORMAT = int,frame : int,slot : int,datetime_yyyymmdd : int,datetime_hhmmssmmm : + // int,frame_type : int,freq_range : int,subcarrier_spacing : int,cyclic_prefix : int,symbols_per_slot : + // int,Nid_cell : int,rnti : + // int,rb_size : int,rb_start : int,start_symbol_index : int,nr_of_symbols : + // int,qam_mod_order : int,mcs_index : int,mcs_table : int,nrOfLayers : + // int,transform_precoding : int,dmrs_config_type : int,ul_dmrs_symb_pos : int,number_dmrs_symbols : + // int,dmrs_port : int,dmrs_nscid : + // int,nb_antennas_tx : int,number_of_bits : buffer,data + // printf("\nTX : %d", e.e[trace_msg_data.nb_antennas_tx].i); + memcpy(&addr_wr[bufIdx_wr], &e.type, sizeof(uint16_t)); + bufIdx_wr += sizeof(uint16_t); + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.frame].i, sizeof(uint16_t)); + bufIdx_wr += sizeof(uint16_t); + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.slot].i, sizeof(uint8_t)); + bufIdx_wr += sizeof(uint8_t); + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.datetime_yyyymmdd].i, sizeof(uint32_t)); + bufIdx_wr += sizeof(uint32_t); + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.datetime_hhmmssmmm].i, sizeof(uint32_t)); + bufIdx_wr += sizeof(uint32_t); + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.frame_type].i, sizeof(uint8_t)); + bufIdx_wr += sizeof(uint8_t); + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.freq_range].i, sizeof(uint8_t)); + bufIdx_wr += sizeof(uint8_t); + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.subcarrier_spacing].i, sizeof(uint8_t)); + bufIdx_wr += sizeof(uint8_t); + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.cyclic_prefix].i, sizeof(uint8_t)); + bufIdx_wr += sizeof(uint8_t); + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.symbols_per_slot].i, sizeof(uint8_t)); + bufIdx_wr += sizeof(uint8_t); + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.Nid_cell].i, sizeof(uint16_t)); + bufIdx_wr += sizeof(uint16_t); + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.rnti].i, sizeof(uint16_t)); + bufIdx_wr += sizeof(uint16_t); + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.rb_size].i, sizeof(uint16_t)); + bufIdx_wr += sizeof(uint16_t); + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.rb_start].i, sizeof(uint16_t)); + bufIdx_wr += sizeof(uint16_t); + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.start_symbol_index].i, sizeof(uint8_t)); + bufIdx_wr += sizeof(uint8_t); + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.nr_of_symbols].i, sizeof(uint8_t)); + bufIdx_wr += sizeof(uint8_t); + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.qam_mod_order].i, sizeof(uint8_t)); + bufIdx_wr += sizeof(uint8_t); + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.mcs_index].i, sizeof(uint8_t)); + bufIdx_wr += sizeof(uint8_t); + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.mcs_table].i, sizeof(uint8_t)); + bufIdx_wr += sizeof(uint8_t); + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.nrOfLayers].i, sizeof(uint8_t)); + bufIdx_wr += sizeof(uint8_t); + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.transform_precoding].i, sizeof(uint8_t)); + bufIdx_wr += sizeof(uint8_t); + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.dmrs_config_type].i, sizeof(uint8_t)); + bufIdx_wr += sizeof(uint8_t); + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.ul_dmrs_symb_pos].i, sizeof(uint16_t)); + bufIdx_wr += sizeof(uint16_t); + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.number_dmrs_symbols].i, sizeof(uint8_t)); + bufIdx_wr += sizeof(uint8_t); + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.dmrs_port].i, sizeof(uint16_t)); + bufIdx_wr += sizeof(uint16_t); + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.dmrs_nscid].i, sizeof(uint16_t)); + bufIdx_wr += sizeof(uint16_t); + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.nb_antennas_tx].i, sizeof(uint8_t)); + bufIdx_wr += sizeof(uint8_t); + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.number_of_bits].i, sizeof(uint32_t)); + bufIdx_wr += sizeof(uint32_t); + + printf("\nTime Stamp: %d_%d", e.e[trace_msg_data.datetime_yyyymmdd].i, e.e[trace_msg_data.datetime_hhmmssmmm].i); + + // add message body: length in bytes + recorded data + memcpy(&addr_wr[bufIdx_wr], &e.e[trace_msg_data.data].bsize, sizeof(uint32_t)); + bufIdx_wr += sizeof(uint32_t); + + // read data from buffer and convert from unsigned char * array to int 16 using the right endianness + // T-tracer: Little Endian + // For BITS Messages, example: UE_PHY_UL_SCRAMBLED_TX_BITS: data in bytes + + if (is_bits_messages(traces_bits_support_data_Collection_format_idx, n_bits_msgs, e.type)) { + for (int byte_idx = 0; byte_idx < e.e[trace_msg_data.data].bsize; byte_idx += 1) { + // printf("%d, ", buf[byte_idx]); + memcpy(&addr_wr[bufIdx_wr], &buf[byte_idx], sizeof(uint8_t)); + bufIdx_wr += sizeof(uint8_t); + } + + } else { + for (int byte_idx = 0; byte_idx < e.e[trace_msg_data.data].bsize; byte_idx += 2) { + // For a little-endian system: + memcpy(&addr_wr[bufIdx_wr], &buf[byte_idx], sizeof(uint8_t)); + bufIdx_wr += sizeof(uint8_t); + memcpy(&addr_wr[bufIdx_wr], &buf[byte_idx + 1], sizeof(uint8_t)); + bufIdx_wr += sizeof(uint8_t); + } + } + /* + for (int byte_idx_i = 0; byte_idx_i < e.e[d.nr_ul_fd_dmrs_data].bsize; byte_idx_i+=4) { + int16_t I = buf[byte_idx_i] | (buf[byte_idx_i+1] << 8); + int16_t Q = buf[byte_idx_i+2] | (buf[byte_idx_i+3] << 8); + printf ("idx %d, ", byte_idx_i); + printf ("\n%d", I); + printf ("\n%d", Q); + } + */ + // check if the current frame and slot are different from the previous frame and slot + // Then, increase the record index + current_frame = e.e[trace_msg_data.frame].i; + current_slot = e.e[trace_msg_data.slot].i; + + // increase sync offset index if the current frame is different from the previous frame + if ((current_frame != prev_frame) && nrecord_idx >= number_records) { + sync_offset_index++; + } + + if (current_frame != prev_frame || current_slot != prev_slot) { + nrecord_idx++; + // Update previous frame and slot numbers + prev_frame = current_frame; + prev_slot = current_slot; + } +#ifdef DEBUG_T_Tracer + printf("\nMessage Info: msg_id %s (%d) \n", event_name_from_id(database, e.type), e.type); + printf("frame %d, slot %d, datetime %d_%d\n", + e.e[trace_msg_data.frame].i, + e.e[trace_msg_data.slot].i, + e.e[trace_msg_data.datetime_yyyymmdd].i, + e.e[trace_msg_data.datetime_hhmmssmmm].i); + printf("frame_type %d, freq_range %d, subcarrier_spacing %d, cyclic_prefix %d, symbols_per_slot %d\n", + e.e[trace_msg_data.frame_type].i, + e.e[trace_msg_data.freq_range].i, + e.e[trace_msg_data.subcarrier_spacing].i, + e.e[trace_msg_data.cyclic_prefix].i, + e.e[trace_msg_data.symbols_per_slot].i); + printf("Nid_cell %d, rnti %d, rb_size %d, rb_start %d, start_symbol_index %d, nr_of_symbols %d\n", + e.e[trace_msg_data.Nid_cell].i, + e.e[trace_msg_data.rnti].i, + e.e[trace_msg_data.rb_size].i, + e.e[trace_msg_data.rb_start].i, + e.e[trace_msg_data.start_symbol_index].i, + e.e[trace_msg_data.nr_of_symbols].i); + printf("qam_mod_order %d, mcs_index %d, mcs_table %d, nrOfLayers %d, transform_precoding %d\n", + e.e[trace_msg_data.qam_mod_order].i, + e.e[trace_msg_data.mcs_index].i, + e.e[trace_msg_data.mcs_table].i, + e.e[trace_msg_data.nrOfLayers].i, + e.e[trace_msg_data.transform_precoding].i); + printf("dmrs_config_type %d, ul_dmrs_symb_pos %d, number_dmrs_symbols %d, dmrs_port %d, dmrs_nscid %d\n", + e.e[trace_msg_data.dmrs_config_type].i, + e.e[trace_msg_data.ul_dmrs_symb_pos].i, + e.e[trace_msg_data.number_dmrs_symbols].i, + e.e[trace_msg_data.dmrs_port].i, + e.e[trace_msg_data.dmrs_nscid].i); + printf("nb_antennas_tx %d, number_of_bits %d, data size %d\n", + e.e[trace_msg_data.nb_antennas_tx].i, + e.e[trace_msg_data.number_of_bits].i, + e.e[trace_msg_data.data].bsize); +#endif + } // End of start recording flag + } // end of if statement for the supported messages based on Data Collection Trace Messages Structure + else { + printf("ERROR: Requested Message is not based on Data Collection Trace Messages Structure\n"); + printf("ERROR: Requested Message ID: %d\n", e.type); + } + } // end of if statement for the requested messages + } // end while loop of reading events + else { + // No data, just loop and check time + usleep(100); // optional: avoid busy-waiting + } + } // End of while loop to read messages + + // de-activate the tracee in the nr-softmodem + printf("\n De-activated Tracer message:\n"); + for (i = 0; i < num_req_tracer_msgs; i++) { + char *on_off_name = event_name_from_id(database, req_tracer_msgs_indices[i]); + on_off(database, on_off_name, is_on, 0); + // printf("\n %d, %s, ", req_tracer_msgs_indices[i], on_off_name); + // on_off(database, "GNB_PHY_DL_OUTPUT_SIGNAL", is_on, 1); + } + // De-activate the tracee in the nr-softmodem + activate_traces(socket, number_of_events, is_on); + printf("\n De-activated Traces"); + + // Get the end time + struct timespec end_time = get_current_time(); + // Calculate the time difference + double time_diff = calculate_time_difference(start_time, end_time); + printf("Total Time difference: %.2f ms\n", time_diff); + printf("Time difference per record: %.2f ms\n", time_diff / (number_records + max_sync_offset)); + + // discard stale or previous record data for the first DISCARD_RECORD_DURATION_MS + struct timespec record_start, record_now; + clock_gettime(CLOCK_MONOTONIC, &record_start); + + while (1) { + clock_gettime(CLOCK_MONOTONIC, &record_now); + double elapsed_ms = calculate_time_difference(record_start, record_now); + if (elapsed_ms >= DISCARD_RECORD_DURATION_MS) { + break; // Stop after 10ms + } + int poll_ret = poll(&event_poll_fd, 1, 1); // 1 ms timeout for poll + if (poll_ret > 0 && (event_poll_fd.revents & POLLIN)) { + event e = get_event(socket, &ebuf, database); + printf("%d", e.type); + if (e.type == -1) { + printf("\n Link broken or unexpected message received. Re-establishing connection...\n"); + reestablish_connection(&socket, ip, port, number_of_events, is_on); + continue; + } + } else { + // No data, just loop and check time + usleep(100); // optional: avoid busy-waiting + } + } // End of while loop to discard stale records + } + } // End a while loop to check for the "stop" command + // de-activate the tracee in the nr-softmodem + + // free_database(database); //Do on one app, for example on gNB App + free(is_on); + close(socket); + + return 0; +} From 8c3e14ead9a25d402c64f96bebf9f07f94a47a93 Mon Sep 17 00:00:00 2001 From: Abdo-Gaber Date: Mon, 10 Mar 2025 13:03:52 +0100 Subject: [PATCH 260/964] Add Data Recording Application v1.0 (main app, SigMF Interface, Config files, Sync validation) The data recording App includes the following files: - The main app: data_recording_app_v1.0.py that has the data control service, interact with tracers, and data sync and conversion service - The configuration file: common/utils/data_recording/config/config_data_recording.json - The wireless dictionary file: common/utils/data_recording/config/wireless_link_parameter_map.yaml - The SigMF Interface (common/utils/data_recording/lib/sigmf_interface.py) to store recorded data and meta-data in SigMF format - A simple script (common/utils/data_recording/sync_validation_demo.py) to validate that the recorded bits from gNB and UE are in Sync - For more info look to doc/data_recording.md A squashed commit further updates: - Enhance Data Recording App structure - Support the new state machine of T-Tracers - Add new files for Config Interface, sync Service, def of data recording messages, and common utilties - Make part of logging on Terminal configurable --- .../config/config_data_recording.json | 84 ++ .../config/wireless_link_parameter_map.yaml | 375 ++++++++ .../data_recording/data_recording_app_v1.0.py | 829 ++++++++++++++++++ common/utils/data_recording/lib/__init__.py | 32 + .../utils/data_recording/lib/common_utils.py | 74 ++ .../data_recording/lib/config_interface.py | 150 ++++ .../lib/data_recording_messages_def.py | 107 +++ .../data_recording/lib/sigmf_interface.py | 580 ++++++++++++ .../utils/data_recording/lib/sync_service.py | 150 ++++ common/utils/data_recording/requirements.txt | 5 + .../data_recording/sync_validation_demo.py | 150 ++++ 11 files changed, 2536 insertions(+) create mode 100644 common/utils/data_recording/config/config_data_recording.json create mode 100644 common/utils/data_recording/config/wireless_link_parameter_map.yaml create mode 100644 common/utils/data_recording/data_recording_app_v1.0.py create mode 100644 common/utils/data_recording/lib/__init__.py create mode 100644 common/utils/data_recording/lib/common_utils.py create mode 100644 common/utils/data_recording/lib/config_interface.py create mode 100644 common/utils/data_recording/lib/data_recording_messages_def.py create mode 100644 common/utils/data_recording/lib/sigmf_interface.py create mode 100644 common/utils/data_recording/lib/sync_service.py create mode 100644 common/utils/data_recording/requirements.txt create mode 100644 common/utils/data_recording/sync_validation_demo.py diff --git a/common/utils/data_recording/config/config_data_recording.json b/common/utils/data_recording/config/config_data_recording.json new file mode 100644 index 0000000000..2d4387d664 --- /dev/null +++ b/common/utils/data_recording/config/config_data_recording.json @@ -0,0 +1,84 @@ +{ + "id": 0, + "test_config": { + "test_scenario_id": "", + "test_name": "phy_ul_bler_test", + "test_mode": "rf_real_time", + "dut_type": "trad_rx" + }, + "environment_emulation": { + "target_link_config": { + "ran_config": { + "uplink": { + "ul_used_signal_BW_MHz": 2.16 + } + }, + "wireless_channel": { + "downlink": { + "type": "rf_cable" + }, + "uplink": { + "type": "statistical_var", + "statistical": { + "var_power_delay_profile": "tdl_d", + "speed_mps": 5.0, + "delay_spread_ns": 50.0, + "snr_db": 20.0, + "predef_channel_profile": null + } + }, + "carrierFreqValueList_hz": [ + 3319680000.0 + ], + "ul_used_signal_BW_MHz": 2.16 + } + } + }, + "data_recording_config": { + "data_storage_path": "/home/user/workarea/oai_recorded_data/", + "data_file_format": "SigMF", + "enable_saving_tracer_messages_sigmf": true, + "num_records": 5, + "t_tracer_message_definition_file": "../T/T_messages.txt", + "parameter_map_file": "config/wireless_link_parameter_map.yaml", + "start_frame_number": 5, + "base_station": { + "requested_tracer_messages": [ + "GNB_PHY_UL_FD_PUSCH_IQ", + "GNB_PHY_UL_FD_DMRS", + "GNB_PHY_UL_FD_CHAN_EST_DMRS_POS", + "GNB_PHY_UL_FD_CHAN_EST_DMRS_INTERPL", + "GNB_PHY_UL_PAYLOAD_RX_BITS" + ], + "meta_data":{ + "num_rx_antennas": 1, + "tx_gain": 48.0, + "rx_gain": 30.0, + "hw_type": "USRP X410", + "hw_subtype": "ZBX", + "seid": "328AB35" + } + }, + "user_equipment": { + "requested_tracer_messages": [ + "UE_PHY_UL_SCRAMBLED_TX_BITS", + "UE_PHY_UL_PAYLOAD_TX_BITS" + ], + "meta_data":{ + "num_tx_antennas": 1, + "tx_gain": 48.0, + "rx_gain": 40.0, + "hw_type": "USRP X410", + "hw_subtype": "ZBX", + "seid": "323F75F" + } + }, + "common_meta_data": { + "sample_rate": 61440000.0, + "bandwidth": 40000000.0, + "clock_reference": "external" + }, + "tracer_service_baseStation_address": "127.0.0.1:2021", + "tracer_service_userEquipment_address": "127.0.0.1:2023" + } +} diff --git a/common/utils/data_recording/config/wireless_link_parameter_map.yaml b/common/utils/data_recording/config/wireless_link_parameter_map.yaml new file mode 100644 index 0000000000..deab34434c --- /dev/null +++ b/common/utils/data_recording/config/wireless_link_parameter_map.yaml @@ -0,0 +1,375 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (the "License"); you may not use this file +# * except in compliance with the License. +# * You may obtain a copy of the License at +# * +# * http://www.openairinterface.org/?page_id=698 +# * +# * Unless required by applicable law or agreed to in writing, software +# * distributed under the License is distributed on an "AS IS" BASIS, +# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# * See the License for the specific language governing permissions and +# * limitations under the License. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# file common/utils/data_recording/config/wireless_link_parameter_map.yaml +# brief Wireless Link Parameter Map Dictionary +# author Abdo Gaber +# date 2024 +# version 1.0 +# company Emerson, NI Test and Measurement +# email: +# note +# warning + + +# Wireless Link Parameter Map +# Components: +# Transmitter: list of waveform configuration based on standard +# Parameters pair is given via this parameter map dictionary (Parameter name in Waveform creator vs that in the API ~ SigMF meta-data) +# Having a separate dictionary ease of adoption in case of: +# - Adding new parameters +# - Use different waveform creator that has Different naming scheme +# - Define your own customized standard or new wireless system +# - All changes are limited to parameter map dictionary +# the parameter name of waveform generator has the following style: +# StandardName_WaveformGenerator_parameter, i.e. +# if standard = 5gnr, WaveformGenerator: ni_rfmx_rfws, then the parameter name: 5gnr_ni_rfmx_rfws_parameter +# ===================================================================================== +# ======== list of parameter pairs between waveform config and API ~ SigMF Meta-Data === +# ===================================================================================== + +# List of waveform generators that generate waveforms +# key: +# standard: "name" +# generator: "link or text ... etc" +# key: Used to create parameter names in wireless_link_parameter_map +# Recommended name for each waveform generator to be given as: standard_WaveformGenerator +# Example: 5g NR waveform created using RFmx with RFWS config file: "5gnr_ni_rfmx_rfws" +# Note: The suffix "_parameter" will be added automatically +# standard name: occur in meta-data +# generator: generator description to occur in meta-data + +waveform_generator: + # waveform_source: standard + 5gnr_oai: # Generated using OAI + standard: "5gnr" + generator: "OpenAirInterface: https://www.openairinterface.org/" + 5gnr_ni_rfmx_rfws: # Generated using NI RFmx Tool + standard: "5gnr" + generator: "NI RFmx Waveform Creator: https://www.ni.com/en-ca/shop/wireless-design-test/application-software-for-wireless-design-test-category/what-is-rfmx.html" +transmitter: + # 5G NR subfield + 5gnr: + # frame number + - sigmf_parameter_name: "frame" + description: "5G NR frame number" + 5gnr_oai_parameter: + name: "frame" + # slot number + - sigmf_parameter_name: "slot" + description: "5G NR slot number" + 5gnr_oai_parameter: + name: "slot" + # bandwidth + - sigmf_parameter_name: "bandwidth" + description: "5G NR bandwidth" + 5gnr_ni_rfmx_rfws_parameter: + name: "Bandwidth (Hz)" + 5gnr_oai_parameter: + name: "bandwidth" + # Frame structure + - sigmf_parameter_name: "frame_structure" + description: "5G NR duplexing scheme FDD, TDD, user defined" + 5gnr_ni_rfmx_rfws_parameter: + name: "Duplex Scheme" # not exact, since it depends if the waveform is for UL or DL + 5gnr_oai_parameter: + name: "frame_type" + value_map: # simu value : SigMF value + 0: "fdd" + 1: "tdd" + # Link direction + - sigmf_parameter_name: "link_direction" + description: "Link direction" + 5gnr_ni_rfmx_rfws_parameter: + name: "Link Direction" + # Frequency Range + - sigmf_parameter_name: "frequency_range" + description: "Frequency Range" + 5gnr_ni_rfmx_rfws_parameter: + name: "Frequency Range" + value_map: # simu value : SigMF value + "Range 1": "fr1" + "Range 2": "fr2" + 5gnr_oai_parameter: + name: "freq_range" + value_map: # simu value : SigMF value + 0: "fr1" + 1: "fr2" + # Subcarrier spacing in Hz + - sigmf_parameter_name: "subcarrier_spacing" + description: "Subcarrier spacing in Hz" + 5gnr_ni_rfmx_rfws_parameter: + name: Subcarrier Spacing (Hz) + 5gnr_oai_parameter: + name: subcarrier_spacing + value_map: # simu value : SigMF value + 0: 15000 + 1: 30000 + 2: 60000 + 3: 120000 + # Sampling rate in Hz + - sigmf_parameter_name: "sample_rate" + description: "Sampling rate in Hz" + 5gnr_ni_rfmx_rfws_parameter: + name: "sample_rate_hz" + 5gnr_oai_parameter: + name: "sample_rate" + # Cyclic prefix mode + - sigmf_parameter_name: "cp_mode" + description: "Cyclic prefix mode" + 5gnr_ni_rfmx_rfws_parameter: + name: "Cyclic Prefix Mode" + 5gnr_oai_parameter: + name: "cyclic_prefix" + value_map: # simu value : SigMF value + 0: "normal" + 1: "extended" + # cell ID + - sigmf_parameter_name: "cell_id" + description: "cell ID" + 5gnr_ni_rfmx_rfws_parameter: + name: "Cell ID" + 5gnr_oai_parameter: + name: "Nid_cell" + # rnti + - sigmf_parameter_name: "rnti" + description: "RNTI" + 5gnr_ni_rfmx_rfws_parameter: + name: "rnti" + 5gnr_oai_parameter: + name: "rnti" + # Symbols per slot + - sigmf_parameter_name: "symbols_per_slot" + description: "Symbols per slot" + 5gnr_oai_parameter: + name: "symbols_per_slot" + # PUSCH: content + - sigmf_parameter_name: "pusch:content" + description: "PUSCH: content" + # PUSCH: channel code + - sigmf_parameter_name: "pusch:channel_code" + description: "PUSCH: channel code" + # PUSCH: number of PRBs + - sigmf_parameter_name: "pusch:num_prb" + description: "PUSCH Resource Block Size" + 5gnr_oai_parameter: + name: "rb_size" + # PUSCH RB Start index + - sigmf_parameter_name: "pusch:start_prb" + description: "PUSCH Resource Block Start" + 5gnr_oai_parameter: + name: "rb_start" + # PUSCH MAPPING type + - sigmf_parameter_name: "pusch:mapping_type" + description: "PUSCH Mapping Type" + 5gnr_oai_parameter: + name: "mappingType" + value_map: # simu value : SigMF value + "NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeA": "A" + "NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB": "B" + # PUSCH: OFDM symbol start index within slot + - sigmf_parameter_name: "pusch:start_ofdm_symbol" + description: "PUSCH: OFDM symbol start index within slot" + 5gnr_oai_parameter: + name: "start_symbol_index" + # PUSCH: number of OFDM symbols in one slot + - sigmf_parameter_name: "pusch:num_ofdm_symbols" + description: "PUSCH: number of OFDM symbols in one slot" + 5gnr_oai_parameter: + name: "nr_of_symbols" + # PUSCH: modulation + - sigmf_parameter_name: "pusch:modulation" + description: "PUSCH: modulation" + 5gnr_ni_rfmx_rfws_parameter: + name: "UL Modulation Type" + value_map: # simu value : SigMF value + "8PSK": "8_psk" + "QPSK": "qpsk" + "QAM16": "16_qam" + "QAM64": "64_qam" + "QAM256": "256_qam" + "QAM1024": "1024_qam" + "Standard": "" + 5gnr_oai_parameter: + name: "qam_mod_order" + value_map: # simu value : SigMF value + 2 : "qpsk" + 4 : "16_qam" + 6 : "64_qam" + 8 : "256_qam" + "Standard": "" + # PUSCH MCS Index + - sigmf_parameter_name: "pusch:mcs" + description: "PUSCH MCS Index" + 5gnr_oai_parameter: + name: "mcs_index" + # PUSCH MCS Index Table + - sigmf_parameter_name: "pusch:mcs_table_index" + description: "PUSCH MCS Table Index" + 5gnr_oai_parameter: + name: "mcs_table" + # PUSCH: number of transmission layers + - sigmf_parameter_name: "pusch:num_layer" + description: "PUSCH: number of transmission layers" + 5gnr_oai_parameter: + name: "nrOfLayers" + # Transform Precoding + - sigmf_parameter_name: "pusch:transform_precoding" + description: "PUSCH Transform Precoding" + 5gnr_oai_parameter: + name: "transform_precoding" + value_map: # simu value : SigMF value + 0: "enabled" + 1: "disabled" + # PUSCH DMRS: content + - sigmf_parameter_name: "pusch_dmrs:content" + description: "PUSCH DMRS: content" + #"none": "none" + #"random_qpsk": "random_qpsk" + #"compliant": "compliant" + # PUSCH DMRS: resource map configuration + - sigmf_parameter_name: "pusch_dmrs:resource_map_config" + description: "PUSCH DMRS: resource map configuration" + 5gnr_oai_parameter: + name: "dmrs_config_type" + value_map: + 0: "5g nr type 1" + 1: "5g nr type 2" + # PUSCH DMRS: OFDM symbol start index within slot + - sigmf_parameter_name: "pusch_dmrs:start_ofdm_symbol" + description: "PUSCH DMRS: OFDM symbol start index within slot" + 5gnr_oai_parameter: + # to be derived from this OAI parameter + name: "ul_dmrs_symb_pos" + # PUSCH DMRS: DMRS duration in number of OFDM symbols + - sigmf_parameter_name: "pusch_dmrs:duration_num_ofdm_symbols" + description: "PUSCH DMRS: DMRS duration in number of OFDM symbols" + 5gnr_oai_parameter: + # to be derived from this OAI parameter + name: "ul_dmrs_symb_pos" + # PUSCH DMRS: OFDM symbol indices within resource grid + - sigmf_parameter_name: "pusch_dmrs:ofdm_symbol_idx" + description: "PUSCH DMRS: OFDM symbol indices within resource grid" + 5gnr_oai_parameter: + # to be derived from this OAI parameter + name: "ul_dmrs_symb_pos" + # PUSCH DMRS: number of additional PUSCH DMRS positions + - sigmf_parameter_name: "pusch_dmrs:num_add_positions" + description: "PUSCH DMRS: number of additional PUSCH DMRS positions" + 5gnr_oai_parameter: + # to be derived from this OAI parameter + name: "ul_dmrs_symb_pos" + # PUSCH DMRS: antenna port + - sigmf_parameter_name: "pusch_dmrs:antennna_port" + description: "PUSCH DMRS: antenna port" + 5gnr_oai_parameter: + name: "dmrs_port" + # PUSCH DMRS: scrambler initialization + - sigmf_parameter_name: "pusch_dmrs:nscid" + description: "PUSCH DMRS: scrambler initialization" + 5gnr_oai_parameter: + name: "dmrs_nscid" + # number of rx antennas + - sigmf_parameter_name: "num_rx_antennas" + description: "Number of Rx antennas" + 5gnr_oai_parameter: + name: "nb_antennas_rx" + # number of tx antennas + - sigmf_parameter_name: "num_tx_antennas" + description: "Number of Tx antennas" + 5gnr_oai_parameter: + name: "nb_antennas_tx" + +channel: + # Signal-to-noise ratio (Es/N0) in dB + - sigmf_parameter_name: "snr_esn0_db" + description: "Signal-to-noise ratio (Es/N0) in dB" + # Signal-to-noise ratio (Eb/N0) in dB + - sigmf_parameter_name: "snr_ebn0_db" + description: "Signal-to-noise ratio (Eb/N0) in dB" + # Channel model + - sigmf_parameter_name: "channel_model" + description: "Fading channel model" + # Number of channel taps + - sigmf_parameter_name: "num_channel_taps" + description: "Number of channel taps" + # Channel attenuation level in dB + - sigmf_parameter_name: "channel_attenuation_db" + description: "Channel attenuation level in dB" + # Nominal delay spread in s + - sigmf_parameter_name: "delay_spread" + description: "Nominal delay spread in s" + # UE speed in m/s + - sigmf_parameter_name: "speed" + description: "UE speed in m/s" + # Carrier frequency in Hz + - sigmf_parameter_name: "carrier_frequency" + description: "Carrier frequency in Hz" +receiver: + # Frequency domain interpolation method for channel estimation + - sigmf_parameter_name: "channel_estimation_freq_interpolation" + description: "Frequency domain interpolation method for channel estimation" + # Time domain interpolation method for channel estimation + - sigmf_parameter_name: "channel_estimation_time_interpolation" + description: "Time domain interpolation method for channel estimation" + # Channel equalization method + - sigmf_parameter_name: "channel_equalization_method" + description: "Channel equalization method" + # Symbol demapping method + - sigmf_parameter_name: "symbol_demapping_method" + description: "Symbol demapping method" + # Manufacturer of the hardware used to receive the signal + - sigmf_parameter_name: "manufacturer" + description: "Manufacturer" + # Unique ID of the emitter, USRP serial number --> usrp_mboard_serial + - sigmf_parameter_name: "seid" + description: "Emitter ID (USRP serial number)" + # For USRP, use “daughterboard ID, a string read out from the device shortened by the hex ID e.g. ‘(0x0085)’ + - sigmf_parameter_name: "hw_subtype" + description: "Hardware subtype (for USRP: daughterboard ID)" + # RX sync reference source ("internal", "external", "gpsdo") + - sigmf_parameter_name: "clock_reference" + description: "RX clock reference" + required_field: false + # Estimated SNR in dB + - sigmf_parameter_name: "snr_estimate_db" + description: "SNR estimate in dB" + required_field: false + # Result of coarse PSS-based timing estimation (used for synchronization) + - sigmf_parameter_name: "timing_estimate_coarse" + description: "Coarse timing estimate in samples" + required_field: false" + # Result of coarse PSS-based frequency offset estimation (used for synchronization) + - sigmf_parameter_name: "cfo_estimate_coarse" + description: "Coarse frequency estimate in Hz" + required_field: false + # Result of fine CRS-based frequency offset estimation (used for synchronization) + - sigmf_parameter_name: "cfo_estimate_fine" + description: "Fine frequency estimate in Hz" + required_field: false + # Number of transmitted payload bits + - sigmf_parameter_name: "num_payload_bits" + description: "Number of transmitted payload bits" + required_field: false + # Number of bit errors when applying traditional RX processing + - sigmf_parameter_name: "bit_errors_trad_rx" + description: "Bit errors" + required_field: false \ No newline at end of file diff --git a/common/utils/data_recording/data_recording_app_v1.0.py b/common/utils/data_recording/data_recording_app_v1.0.py new file mode 100644 index 0000000000..53b7555b4b --- /dev/null +++ b/common/utils/data_recording/data_recording_app_v1.0.py @@ -0,0 +1,829 @@ +# /* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (the "License"); you may not use this file +# * except in compliance with the License. +# * You may obtain a copy of the License at +# * +# * http://www.openairinterface.org/?page_id=698 +# * +# * Unless required by applicable law or agreed to in writing, software +# * distributed under the License is distributed on an "AS IS" BASIS, +# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# * See the License for the specific language governing permissions and +# * limitations under the License. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +# --------------------------------------------------------------------- +# file common/utils/data_recording/data_recording_app_v1.0.py +# brief main application of synchronized real-time data recording +# author Abdo Gaber +# date 2025 +# version 1.0 +# company Emerson, NI Test and Measurement +# email: +# note +# warning + +import sysv_ipc as ipc +import struct +import time +from datetime import datetime +from termcolor import colored +import numpy as np +import json +import concurrent.futures +# from concurrent import futures +import threading +# import related functions +from lib import sigmf_interface +# import library functions +from lib import sync_service +from lib import data_recording_messages_def +from lib import common_utils +from lib import config_interface + +DEBUG_WIRELESS_RECORDED_DATA = True +DEBUG_BUFFER_READING = False + +# globally applicable metadata +global_info = { + "author": "Abdo Gaber", + "description": "Synchronized Real-Time Data Recording", + "timestamp": 0, + "collection_file_prefix": "data-collection", # collection file name prefix "deap-rx + str(...)" + "collection_file": "", # Reserved to be created in the code: “data-collection_rec-0_TIME-STAMP” + "datetime_offset": "", # datetime offset between current location and UTC/Zulu timezone + # Example: "+01:00" for Berlin, Germany + "save_config_data_recording_app_json": True, + "waveform_generator": "5gnr_oai", + "extensions": {}, +} + +# Supported OAI Trace messages +# UL receiver messages +# gNB IQ Msgs: "GNB_PHY_UL_FD_PUSCH_IQ", "GNB_PHY_UL_FD_DMRS", "GNB_PHY_UL_FD_CHAN_EST_DMRS_POS", +# "GNB_PHY_UL_FD_CHAN_EST_DMRS_INTERPL" +# gNB BITS Msgs: "GNB_PHY_UL_PAYLOAD_RX_BITS" +# UE BITS Msgs: "UE_PHY_UL_SCRAMBLED_TX_BITS", "UE_PHY_UL_PAYLOAD_TX_BITS" + +supported_oai_tracer_messages = { + # gNB messages + "GNB_PHY_UL_FD_PUSCH_IQ": { + "file_name_prefix": "rx-fd-data", + "scope": "gNB", + "description": "Frequency-domain RX data", + "serialization_scheme": ["subcarriers", "ofdm_symbols"], + }, + "GNB_PHY_UL_FD_DMRS": { + "file_name_prefix": "tx-pilots-fd-data", + "scope": "gNB", + "description": "Frequency-domain TX PUSCH DMRS data", + "serialization_scheme": ["subcarriers", "ofdm_symbols"], + }, + "GNB_PHY_UL_FD_CHAN_EST_DMRS_POS": { + "file_name_prefix": "raw-ce-fd-data", + "scope": "gNB", + "description": "Frequency-domain raw channel estimates (at DMRS positions)", + "serialization_scheme": ["subcarriers", "ofdm_symbols"], + }, + "GNB_PHY_UL_FD_CHAN_EST_DMRS_INTERPL": { + "file_name_prefix": "raw-inter-ce-fd-data", + "scope": "gNB", + "description": "Interpolcated Frequency-domain raw channel estimates", + "serialization_scheme": ["subcarriers", "ofdm_symbols"], + }, + "GNB_PHY_UL_PAYLOAD_RX_BITS": { + "file_name_prefix": "rx-payload-bits", + "scope": "gNB", + "description": "Received PUSCH payload bits", + "serialization_scheme": ["bits", "subcarriers", "ofdm_symbols"], + }, + # UE messages + "UE_PHY_UL_SCRAMBLED_TX_BITS": { + "file_name_prefix": "tx-scrambled-bits", + "scope": "UE", + "description": "Transmitted scrambled PUSCH bits", + "serialization_scheme": ["bits", "subcarriers", "ofdm_symbols"], + }, + "UE_PHY_UL_PAYLOAD_TX_BITS": { + "file_name_prefix": "tx-payload-bits", + "scope": "UE", + "description": "Transmitted PUSCH payload bits", + "serialization_scheme": ["bits", "subcarriers", "ofdm_symbols"], + }, +} +# ------------------------------------------- +# System configuration: gNB +project_id_gnb = 2335 +read_shm_path_gnb = "/tmp/gnb_app1" +write_shm_path_gnb = "/tmp/gnb_app2" + +# System configuration: UE +project_id_ue = 2336 +read_shm_path_ue = "/tmp/ue_app1" +write_shm_path_ue = "/tmp/ue_app2" + + +# initialize shared memory +def attach_shm(shm_path, project_id): + key = ipc.ftok(shm_path, project_id) + shm = ipc.SharedMemory(key, 0, 0) + # I found if we do not attach ourselves + # it will attach as ReadOnly. + shm.attach(0, 0) + return shm + + +def detach_shm(shm): + try: + shm.detach() + print("Shared memory detached successfully.") + except ipc.ExistentialError: + print("Shared memory segment does not exist.") + + +def remove_shm(shm): + try: + shm.remove() + print("Shared memory removed successfully.") + except ipc.ExistentialError: + print("Shared memory segment does not exist.") + + +# check data if avalible in the shared memory +def is_data_available_in_memory(shm, bufIdx, general_message_header_length, timeout=20): + start_time = time.time() + while True: + buf = shm.read(bufIdx + general_message_header_length) + n_bytes = sum(buf) + print("Data Recording App: Waiting for Measurements!") + if n_bytes > 0: + print("There is data in memory, n_bytes: ", n_bytes) + return True + if (time.time() - start_time) > timeout: + break + time.sleep(1) + return False + + +# Read data from Shared memory based Data Conversion Service message structure +def read_data_from_shm(shm, bufIdx, tracer_msgs_identities): + # print buffer index + if DEBUG_BUFFER_READING: + print("Buffer Index: ", bufIdx) + # get general message header list + general_msg_header_list, general_message_header_length = data_recording_messages_def.get_general_msg_header_list() + buf = shm.read(bufIdx + general_message_header_length) + n_bytes = sum(buf) + if n_bytes == 0: + raise Exception('ERROR: No data available in memory') + msg_id = struct.unpack(' timeout_sync: + raise Exception( + "ERROR: Data Recording NO Sync Found, check Tracer Services if they are connected!") + + # Get gNB data based on the sync data + bufIdx = 0 + while True: + time.sleep(0.0035) + gnb_bufIdx = bufIdx + captured_data, bufIdx = read_data_from_shm( + shm_reading_gnb, bufIdx, tracer_msgs_identities) + if (captured_data["frame"] == sync_info["frame"] + and captured_data["slot"] == sync_info["slot"]): + break + + # Read Synchronized data between gNB and UE + while True: # read all records + print("\nRecord number: ", record_idx) + if DEBUG_BUFFER_READING: + print(f"Buffer Index gNB: {gnb_bufIdx}, Buffer Index UE: {ue_bufIdx}") + # wait for the next record + # To do: check if we need to add exta waiting times between different events in case of + # data streaming via network such as on UE side or gNB side + time.sleep(0.0035) # 2.3 ms = latency of T tracer to capture data from the RAN + + collected_metafiles = [] + # Read data from gNB T-tracer Application + for idx in range(gnb_args.num_requested_tracer_msgs): + time.sleep(0.0015) + if DEBUG_WIRELESS_RECORDED_DATA: + print(f"\nRecord number: {record_idx}, Reading MSG data ", idx) + captured_data, gnb_bufIdx = read_data_from_shm( + shm_reading_gnb, gnb_bufIdx, tracer_msgs_identities) + # drive the collection file time stamp from the first message per record + if idx == 0: + # Get time stamp + time_stamp_ms, time_stamp_ms_file_name = ( + sigmf_interface.time_stamp_formating( + captured_data["time_stamp"], global_info["datetime_offset"])) + global_info["collection_file"] = ( + global_info["collection_file_prefix"] + + "-rec-" + + str(record_idx) + + "-" + + str(time_stamp_ms_file_name) + ) + global_info["timestamp"] = time_stamp_ms + + # Write data into files with the given format + if config_meta_data["data_recording_config"]["enable_saving_tracer_messages_sigmf"]: + collected_metafiles.append( + sigmf_interface.write_recorded_data_to_sigmf( + captured_data, config_meta_data, global_info, record_idx)) + + # Read data from UE T-tracer Application + for idx in range(ue_args.num_requested_tracer_msgs): + time.sleep(0.0015) + if DEBUG_WIRELESS_RECORDED_DATA: + print(f"\nRecord number: {record_idx}, Reading MSG data ", idx) + captured_data, ue_bufIdx = read_data_from_shm( + shm_reading_ue, ue_bufIdx, tracer_msgs_identities) + + # Write data into files with the given format + if config_meta_data["data_recording_config"]["enable_saving_tracer_messages_sigmf"]: + collected_metafiles.append( + sigmf_interface.write_recorded_data_to_sigmf( + captured_data, config_meta_data, global_info, record_idx)) + + # generate SigMF collection file + if config_meta_data["data_recording_config"]["enable_saving_tracer_messages_sigmf"]: + data_storage_path = config_meta_data["data_recording_config"][ + "data_storage_path"] + description = global_info["description"] + sigmf_interface.save_sigmf_collection( + collected_metafiles, global_info, description, data_storage_path) + + frame = captured_data["frame"] + slot = captured_data["slot"] + + # Check for changes in frame or slot + if frame != prev_frame or slot != prev_slot: + record_idx += 1 + # We have reached the end of the data. Break the loop + if record_idx >= config_meta_data["data_recording_config"]["num_records"]: + break + # Update previous frame and slot + prev_frame = frame + prev_slot = slot + + +# data conversion service +def data_conversion_service(shm_reading, config_meta_data, args, sync_info, do_sync): + # Initialize variables + record_idx = 0 + prev_frame = -1 + prev_slot = -1 + bufIdx = 0 + # Read data from T-tracer Application + print("Data Conversion Service: Reading data from T-tracer Application") + print("Requested Tracer Messages: ", args.num_requested_tracer_msgs) + if args.num_requested_tracer_msgs > 0: + num_requested_tracer_msgs = args.num_requested_tracer_msgs + else: + raise Exception("ERROR: No requested tracer messages found!") + + tracer_msgs_identities = config_meta_data["data_recording_config"][ + "tracer_msgs_identities"] + global_info = config_meta_data["data_recording_config"]["global_info"] + + if do_sync: + print(" Find Memory Index of NR MSGs based on Sync info") + while True: + time.sleep(0.0035) + station_bufIdx = bufIdx + captured_data, bufIdx = read_data_from_shm( + shm_reading, bufIdx, tracer_msgs_identities) + print("*Sync Status: NR Captured Data (Frame, slot): (", captured_data["frame"], + ", ", captured_data["slot"], "), Sync Info (Frame, slot): (", sync_info["frame"], + ", ", sync_info["slot"]," )") + if (captured_data["frame"] == sync_info["frame"] + and captured_data["slot"] == sync_info["slot"]): + print("*sync Pass") + break + print("*sync Fail") + bufIdx = station_bufIdx + + # Read data from T-tracer Application + while True: # read all records + print("\nRecord number: ", record_idx) + if DEBUG_BUFFER_READING: + print(f"Buffer Index: {bufIdx}") + # wait for the next record + # To do: check if we need to add exta waiting times between different events in case of + # data streaming via network such as on UE side or gNB side + time.sleep(0.0035) # 2.3 ms = latency of T tracer to capture data from the RAN + + collected_metafiles = [] + for idx in range(num_requested_tracer_msgs): + time.sleep(0.0015) + if DEBUG_WIRELESS_RECORDED_DATA: + print(f"\nRecord number: {record_idx}, Reading MSG data ", idx) + captured_data, bufIdx = read_data_from_shm( + shm_reading, bufIdx, tracer_msgs_identities) + # derive the collection file time stamp from the first message per record + if idx == 0: + # Get time stamp + time_stamp_ms, time_stamp_ms_file_name = ( + sigmf_interface.time_stamp_formating( + captured_data["time_stamp"], global_info["datetime_offset"])) + global_info["collection_file"] = ( + global_info["collection_file_prefix"] + + "-rec-" + + str(record_idx) + + "-" + + str(time_stamp_ms_file_name)) + global_info["timestamp"] = time_stamp_ms + # Write data into files with the given format + if config_meta_data["data_recording_config"]["enable_saving_tracer_messages_sigmf"]: + collected_metafiles.append( + sigmf_interface.write_recorded_data_to_sigmf( + captured_data, config_meta_data, global_info, record_idx)) + + frame = captured_data["frame"] + slot = captured_data["slot"] + + # generate SigMF collection file + if config_meta_data["data_recording_config"]["enable_saving_tracer_messages_sigmf"]: + data_storage_path = config_meta_data["data_recording_config"][ + "data_storage_path"] + description = global_info["description"] + sigmf_interface.save_sigmf_collection( + collected_metafiles, global_info, description, data_storage_path) + + # Check for changes in frame or slot + if frame != prev_frame or slot != prev_slot: + record_idx += 1 + # We have reached the end of the data. Break the loop + if record_idx >= config_meta_data["data_recording_config"]["num_records"]: + break + # Update previous frame and slot + prev_frame = frame + prev_slot = slot + + +# Write Tracer Control Message +def write_shm(shm, args): + # Note: Big Endian >, Little Endian < + # Note: unsigned char B, signed char b, short h, int I, long long q + # Note: float f, double d, string s, char c, bool ? + # 1: config + # 2: record + # 3: quit + print("Write Shared Memory: ", args.action) + if args.action == "config": + # Determine the length of the IP address + ip_length = len(args.bytes_IPaddress) + 1 # String terminator + # Construct the format string dynamically + format_string = f"{ip_length}s" + shm.write( + # Config action + struct.pack(" dict: + """ + Reads main config file. + """ + # read general parameter set from yaml config file + with open(main_config_file, "r") as file: + main_config = json.load(file) + + return main_config + + +# Function to read the main configuration file in YAML format +def read_main_config_file(main_config_file: str) -> dict: + """ + Reads main config file. + """ + # read general parameter set from yaml config file + with open(main_config_file, "r") as file: + main_config = yaml.load(file, Loader=yaml.Loader) + + return main_config + + +# Function to parse the OAI T_messages file and get the index of a given string +def parse_message_file(file_path): + with open(file_path, "r") as file: + content = file.readlines() + # Extract lines that start with 'ID' and remove the 'ID = ' prefix + tracer_msgs_identities = [ + line.strip().replace("ID = ", "") + for line in content + if line.strip().startswith("ID") + ] + + return tracer_msgs_identities + + +# Function to get the index of a given string in the list of ID lines +def get_index_of_id(tracer_msgs_identities, message_id): + try: + return tracer_msgs_identities.index(message_id) + except ValueError: + return -1 # Return -1 if the string is not found + + +# Function to get the indices of requested tracer messages +def get_requested_tracer_msgs_indices(requested_tracer_messages, tracer_msgs_identities): + # get requested tracer messages indices + req_tracer_msgs_indices = [] + for idx, value in enumerate(requested_tracer_messages): + msg_index = get_index_of_id(tracer_msgs_identities, value) + req_tracer_msgs_indices.append(msg_index) + print("Requested Traces IDs: ", req_tracer_msgs_indices) + return req_tracer_msgs_indices + + +# Function to get the data recording configuration +def get_data_recording_config(config_meta_data): + parser = argparse.ArgumentParser(description="request messages IDs") + ue_args = parser.parse_args() + gnb_args = parser.parse_args() + + # get Tracer Messages IDs from the T-Tracer Messages file + # MSG list order should be similar to the T-Tracer Messages txt file + # Be sure that you are using the same T_messages file that is used in the OAI project + # OAI Path: .../common/utils/T/T_messages.txt + + # Parse the T_messages file + tracer_msgs_identities = parse_message_file( + config_meta_data["data_recording_config"]["t_tracer_message_definition_file"]) + config_meta_data["data_recording_config"]["tracer_msgs_identities"] = tracer_msgs_identities + + # get requested tracer messages indices for gNB + gnb_args.requested_tracer_messages = \ + config_meta_data["data_recording_config"]["base_station"]["requested_tracer_messages"] + # get requested tracer messages indices for UE + ue_args.requested_tracer_messages = \ + config_meta_data["data_recording_config"]["user_equipment"]["requested_tracer_messages"] + + # check if gnb_requested_tracer_messages is not empty + if gnb_args.requested_tracer_messages: + config_meta_data["data_recording_config"]["base_station"][ + "req_tracer_msgs_indices"] = get_requested_tracer_msgs_indices( + gnb_args.requested_tracer_messages, tracer_msgs_identities) + + # get gNB Trace Messages + gnb_args.num_records = config_meta_data["data_recording_config"]["num_records"] + gnb_args.start_frame_number = config_meta_data["data_recording_config"]["start_frame_number"] + gnb_args.req_tracer_msgs_indices = \ + config_meta_data["data_recording_config"]["base_station"]["req_tracer_msgs_indices"] + gnb_args.num_requested_tracer_msgs = len(gnb_args.req_tracer_msgs_indices) + # Split the string into IP and port + gnb_args.IPaddress, gnb_args.port = config_meta_data["data_recording_config"][ + "tracer_service_baseStation_address"].split(":") + gnb_args.bytes_IPaddress = bytes(gnb_args.IPaddress, "utf-8") + + # check if ue_requested_tracer_messages is not empty + if ue_args.requested_tracer_messages: + config_meta_data["data_recording_config"]["user_equipment"][ + "req_tracer_msgs_indices"] = get_requested_tracer_msgs_indices( + ue_args.requested_tracer_messages, tracer_msgs_identities) + + # get UE Trace Messages + ue_args.num_records = config_meta_data["data_recording_config"]["num_records"] + ue_args.start_frame_number = config_meta_data["data_recording_config"]["start_frame_number"] + ue_args.req_tracer_msgs_indices = \ + config_meta_data["data_recording_config"]["user_equipment"]["req_tracer_msgs_indices"] + ue_args.num_requested_tracer_msgs = len(ue_args.req_tracer_msgs_indices) + ue_args.IPaddress, ue_args.port = config_meta_data["data_recording_config"][ + "tracer_service_userEquipment_address"].split(":") + ue_args.bytes_IPaddress = bytes(ue_args.IPaddress, "utf-8") + + return config_meta_data, gnb_args, ue_args diff --git a/common/utils/data_recording/lib/data_recording_messages_def.py b/common/utils/data_recording/lib/data_recording_messages_def.py new file mode 100644 index 0000000000..a807058f29 --- /dev/null +++ b/common/utils/data_recording/lib/data_recording_messages_def.py @@ -0,0 +1,107 @@ +# /* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (the "License"); you may not use this file +# * except in compliance with the License. +# * You may obtain a copy of the License at +# * +# * http://www.openairinterface.org/?page_id=698 +# * +# * Unless required by applicable law or agreed to in writing, software +# * distributed under the License is distributed on an "AS IS" BASIS, +# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# * See the License for the specific language governing permissions and +# * limitations under the License. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +# --------------------------------------------------------------------- +# file common/utils/data_recording/lib/data_recording_messages_def.py +# brief defination of captured data recording messages +# author Abdo Gaber +# date 2025 +# version 1.0 +# company Emerson, NI Test and Measurement +# email: +# note +# warning + + +# Data Collection Trace Messages - General message structure - number of bytes +def get_general_msg_header_list(): + """ + shared memory layout written from the app: + ================================= + msg_id (uint8) message type ID + frame (uint16) + slot (uint8) + datetime_yyyymmdd (uint32) + datetime_hhmmssmmm (uint32) + frame_type (uint8) + freq_range (uint8) + subcarrier_spacing (uint8) + cyclic_prefix (uint8) + symbols_per_slot (uint8) + Nid_cell (uint16) + rnti (uint16) + rb_size (uint16) + rb_start (uint16) + start_symbol_index (uint8) + nr_of_symbols (uint8) + qam_mod_order (uint8) + mcs_index (uint8) + mcs_table (uint8) + nrOfLayers (uint8) + transform_precoding (uint8) + dmrs_config_type (uint8) + ul_dmrs_symb_pos (uint16) + number_dmrs_symbols (uint8) + dmrs_port (uint16) + dmrs_scid (uint16) + nb_antennas (uint8) + number_of_bits (uint32) + length_bytes (uint32) + For IQ Data: IQ samples: I0, Q0, I1, Q1, ... I_x, Q_x (int16) + For bit data: bits: b0, b1, b2, ... b_x (uint8) + + """ + # Data Collection Trace Messages - General message structure - number of bytes + general_msg_header_list = { + "msg_id": 2, + "frame": 2, + "slot": 1, + "datetime_yyyymmdd": 4, + "datetime_hhmmssmmm": 4, + "frame_type": 1, + "freq_range": 1, + "subcarrier_spacing": 1, + "cyclic_prefix": 1, + "symbols_per_slot": 1, + "Nid_cell": 2, + "rnti": 2, + "rb_size": 2, + "rb_start": 2, + "start_symbol_index": 1, + "nr_of_symbols": 1, + "qam_mod_order": 1, + "mcs_index": 1, + "mcs_table": 1, + "nrOfLayers": 1, + "transform_precoding": 1, + "dmrs_config_type": 1, + "ul_dmrs_symb_pos": 2, + "number_dmrs_symbols": 1, + "dmrs_port": 2, + "dmrs_scid": 2, + "nb_antennas": 1, # for gNB or nb_antennas_tx for UE + "number_of_bits": 4, + "length_bytes": 4, + } + # initial number of bytes to read to get data + general_message_header_length = 0 + for key, value in general_msg_header_list.items(): + general_message_header_length = general_message_header_length + value + return general_msg_header_list, general_message_header_length diff --git a/common/utils/data_recording/lib/sigmf_interface.py b/common/utils/data_recording/lib/sigmf_interface.py new file mode 100644 index 0000000000..74d58a03f8 --- /dev/null +++ b/common/utils/data_recording/lib/sigmf_interface.py @@ -0,0 +1,580 @@ +# /* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (the "License"); you may not use this file +# * except in compliance with the License. +# * You may obtain a copy of the License at +# * +# * http://www.openairinterface.org/?page_id=698 +# * +# * Unless required by applicable law or agreed to in writing, software +# * distributed under the License is distributed on an "AS IS" BASIS, +# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# * See the License for the specific language governing permissions and +# * limitations under the License. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +# --------------------------------------------------------------------- +# file common/utils/data_recording/lib/sigmf_interface.py +# brief SigMF Interface to Write data and meta-data to files in SigMF format +# author Abdo Gaber +# date 2025 +# version 1.0 +# company Emerson, NI Test and Measurement +# email: +# note +# warning + +import os +import sigmf +from sigmf import SigMFFile +# from sigmf.utils import get_data_type_str +import numpy as np +from datetime import datetime +import yaml +from sigmf import SigMFCollection + +""" +SERIALIZATION_SCHEMES = { + # gnb + "rx-fd-data": ["subcarriers", "ofdm_symbols"], + "tx-pilots-fd-data": ["subcarriers", "ofdm_symbols"], + "raw-ce-fd-data": ["subcarriers", "ofdm_symbols"], + "rx-payload-bits": ["bits", "subcarriers", "ofdm_symbols"], + # ue + "tx-scrambled-bits": ["bits", "subcarriers", "ofdm_symbols"], + "tx-payload-bits": ["bits", "subcarriers", "ofdm_symbols"], +} +""" +STANDARDS = {"5gnr_oai": "5gnr"} + + +def time_stamp_formating(time_stamp, datetime_offset): + # Parse the input string into a datetime object + time_stamp_ms_obj = datetime.strptime(time_stamp, "%Y%m%d_%H%M%S%f") + + # Format the datetime object into the desired output format with milliseconds + time_stamp_ms_iso = ( + time_stamp_ms_obj.strftime("%Y_%m_%dT%H:%M:%S.%f")[:-3] + datetime_offset + ) + time_stamp_ms = time_stamp_ms_iso + time_stamp_ms_file_name = time_stamp_ms_iso.replace(":", "_").replace(".", "_") + + return time_stamp_ms, time_stamp_ms_file_name + + +def create_serialization_metadata(serialization_scheme, data_source: str, + link_sim_parameters: dict) -> dict: + """Creates dict that specifies the serialization metadata.""" + + # retrieve parameter from LinkSimulator config + if data_source == "5gnr_oai": + num_ofdm_symbol = link_sim_parameters["nr_of_symbols"] + num_subcarriers = link_sim_parameters["rb_size"] * 12 + num_bits_per_symbol = link_sim_parameters["qam_mod_order"] + else: + raise Exception( + f"Invalid data source string '{data_source}'! Only '5gnr_oai' is valid!" + ) + + # create array with scheme dimensions + if len(serialization_scheme) == 2: + counts = [num_subcarriers, num_ofdm_symbol] + elif len(serialization_scheme) == 3: + counts = [num_bits_per_symbol, num_subcarriers, num_ofdm_symbol] + else: + raise Exception( + f"Invalid number of elements in serialization scheme: {len(serialization_scheme)}") + + # create metadata dict + serialization_dict = { + "serialization:scheme": serialization_scheme, + "serialization:counts": counts, + } + + return serialization_dict + + +def map_metadata_to_sigmf_format(scope, waveform_generator, parameter_map_file, captured_data): + """ + Maps metadata from Waveform creator to API and SigMF format. + The used parameters and the mapping pairs are specified in a separate YAML file + that must be provided as well. + """ + # read waveform parameter map from yaml file + dir_path = os.path.dirname(__file__) + src_path = os.path.split(dir_path)[0] + + with open(os.path.join(src_path, parameter_map_file), "r") as file: + parameter_map_dic = yaml.load(file, Loader=yaml.Loader) + # preallocate target dict + sigmf_metadata_dict = {} + + # get standard and name of generator + standard_key = parameter_map_dic["waveform_generator"][waveform_generator] + generator = standard_key["generator"] + + if scope == "tx": + parameter_map_dic = parameter_map_dic["transmitter"][ + STANDARDS[waveform_generator] + ] + elif scope == "channel": + parameter_map_dic = parameter_map_dic["channel"] + elif scope == "rx": + parameter_map_dic = parameter_map_dic["receiver"] + else: + raise Exception( + f"Invalid mapping scope '{scope}'! Only 'tx', 'channel' and 'rx' are valid!" + ) + + # check if standard key is given + if parameter_map_dic is None: + raise Exception( + "Invalid standard key: " + "Name should be corrected or added to wireless_link_parameter_map.yaml, given: " + f"{waveform_generator}" + ) + + for parameter_pair in parameter_map_dic: + # check if key for chosen simulator even exists + if waveform_generator + "_parameter" in parameter_pair.keys(): + # only continue with mapping from file if direct equivalent exists + if parameter_pair[waveform_generator + "_parameter"]["name"]: + # It is not necessary to get all parameters from wireless_link_parameter_map.yaml + # in captured_data since some parameters related to DL or UL only + if (parameter_pair[waveform_generator + "_parameter"]["name"] in captured_data.keys()): + # extract value from waveform config source + value = captured_data[ + parameter_pair[waveform_generator + "_parameter"]["name"]] + # additional mapping if parameter values should come from a discrete set of values + if ("value_map" in parameter_pair[waveform_generator + "_parameter"].keys()): + value = parameter_pair[waveform_generator + "_parameter"]["value_map"][value] + # write to target dictionary for SigMF + sigmf_metadata_dict[parameter_pair["sigmf_parameter_name"]] = value + else: + raise Exception( + f"Incomplete specification in field '{waveform_generator}_parameter'!") + # else: # fill_non_explicit_fields + # waveform_config[parameter_pair["sigmf_parameter_name"]] = "none" + if not sigmf_metadata_dict: + raise Exception( + """ERROR: Check captured meta-data or provided config and meta data """) + + # check for non-JSON-serializable data types + def isfloat(NumberString): + try: + float(NumberString) + return True + except ValueError: + return False + + for key, value in sigmf_metadata_dict.items(): + if isinstance(value, np.integer): + sigmf_metadata_dict[key] = int(value) + elif isinstance(value, (np.float16, np.float32, np.float64)): + sigmf_metadata_dict[key] = np.format_float_positional(value, trim="-") + elif isinstance(value, int): + sigmf_metadata_dict[key] = int(value) + elif isinstance(value, float): + # store value in decimal and not in scientific notation + sigmf_metadata_dict[key] = float(value) + elif isinstance(value, str) and key != "standard": + # convert string to lower case + sigmf_metadata_dict[key] = value.lower() + if isfloat(value): + if value.isdigit(): + sigmf_metadata_dict[key] = int(float(value)) + elif value.replace(".", "", 1).isdigit() and value.count(".") < 2: + sigmf_metadata_dict[key] = float(value) + + return sigmf_metadata_dict, generator + + +def create_system_components_metadata(waveform_generator, parameter_map_file, captured_data): + """Creates system components (TX, channel, RX) metadata that will reside in the annotations.""" + # map metadata of waveform generator to SigMF format + signal_info, generator = map_metadata_to_sigmf_format( + "tx", waveform_generator, parameter_map_file, captured_data + ) + tx_metadata = { + "signal:detail": { + "standard": STANDARDS[waveform_generator], + "generator": generator, + STANDARDS[waveform_generator]: signal_info, + } + } + + channel_metadata = {} # will be filled later + rx_metadata = {} # will be filled later + + return tx_metadata, channel_metadata, rx_metadata + + +def write_recorded_data_to_sigmf(captured_data, config_meta_data, global_info, idx): + """ + Compiles and saves provided data and metadata into SigMF file format. + """ + # get meta data from config file + base_station_meta_data = config_meta_data["data_recording_config"]["base_station"][ + "meta_data"] + user_equipment_meta_data = config_meta_data["data_recording_config"][ + "user_equipment"]["meta_data"] + + # Check the receive target path is valid, else create folder + data_storage_path = config_meta_data["data_recording_config"]["data_storage_path"] + if not os.path.isdir(data_storage_path): + print("Create new folder for recorded data: " + str(data_storage_path)) + os.makedirs(data_storage_path) + + # Write recorded data to file + # Get time stamp + time_stamp_ms, time_stamp_ms_file_name = time_stamp_formating( + captured_data["time_stamp"], global_info["datetime_offset"]) + # Map OAI Message Name to SigMF Message Name + file_name_prefix = config_meta_data["data_recording_config"][ + "supported_oai_tracer_messages"][captured_data["message_type"]]["file_name_prefix"] + recorded_data_file_name = ( + file_name_prefix + "-rec-" + str(idx) + "-" + time_stamp_ms_file_name) + + dataset_filename = recorded_data_file_name + ".sigmf-data" + dataset_file_path = os.path.join(data_storage_path, dataset_filename) + print(dataset_file_path) + captured_data["recorded_data"].tofile(dataset_file_path) + + # map OAI config data to SigMF metadata + waveform_generator = config_meta_data["data_recording_config"]["global_info"][ + "waveform_generator"] + parameter_map_file = config_meta_data["data_recording_config"]["parameter_map_file"] + tx_metadata, channel_metadata, rx_metadata = create_system_components_metadata( + waveform_generator, parameter_map_file, captured_data) + + # Add other OAI metadata to SigMF metadata + # ---------------------------------------------------- + # Set 1: Parameters needs to be derived from OAI message + # ---------------------------------------------------- + # PUSCH DMRS: OFDM symbol start index within slot + get_pusch_dmrs_start_ofdm_symbol = 0 + tx_metadata["signal:detail"][STANDARDS[waveform_generator]][ + "pusch_dmrs:ofdm_symbol_idx"] = [] + + for symbol in range(captured_data["start_symbol_index"], + captured_data["start_symbol_index"] + captured_data["nr_of_symbols"]): + + dmrs_symbol_flag = (captured_data["ul_dmrs_symb_pos"] >> symbol) & 0x01 + if dmrs_symbol_flag and not get_pusch_dmrs_start_ofdm_symbol: + get_pusch_dmrs_start_ofdm_symbol = 1 + tx_metadata["signal:detail"][STANDARDS[waveform_generator]][ + "pusch_dmrs:start_ofdm_symbol"] = symbol + if dmrs_symbol_flag: + tx_metadata["signal:detail"][STANDARDS[waveform_generator]][ + "pusch_dmrs:ofdm_symbol_idx"].append(symbol) # Append symbol to the list + + tx_metadata["signal:detail"][STANDARDS[waveform_generator]][ + "pusch_dmrs:duration_num_ofdm_symbols"] = 1 + tx_metadata["signal:detail"][STANDARDS[waveform_generator]][ + "pusch_dmrs:num_add_positions"] = (captured_data["number_dmrs_symbols"] - 1) + + # If the message is a BIT message, add number of bits to the signal info + # "UE_PHY_UL_SCRAMBLED_TX_BITS", "GNB_PHY_UL_PAYLOAD_RX_BITS", "UE_PHY_UL_PAYLOAD_TX_BITS" + if "_BITS" in captured_data["message_type"]: + # if "BIT" in captured_data["message_type"]: + tx_metadata["signal:detail"][STANDARDS[waveform_generator]]["num_bits"] = ( + captured_data["number_of_bits"]) + + # If the message is captured from UE, it is UPLink message, + # so number of antennas is num of Tx antennas + # number of antennas on Rx side should be read from global_info given by user + if "UE" in captured_data["message_type"]: + tx_metadata["signal:detail"][STANDARDS[waveform_generator]][ + "num_tx_antennas" + ] = captured_data["nb_antennas"] + rx_metadata.update( + {"num_rx_antennas": base_station_meta_data["num_rx_antennas"]} + ) + # If the message is captured from gNB, it is UPLink message, + # so number of antennas is num of Rx antennas + # number of antennas on Tx side should be read from global_info given by user + else: + tx_metadata["signal:detail"][STANDARDS[waveform_generator]][ + "num_tx_antennas"] = user_equipment_meta_data["num_tx_antennas"] + rx_metadata.update({"num_rx_antennas": captured_data["nb_antennas"]}) + + # Check if the message type contains "UL" + if "UL" in captured_data["message_type"]: + tx_metadata["signal:detail"][STANDARDS[waveform_generator]][ + "link_direction"] = "uplink" + else: + tx_metadata["signal:detail"][STANDARDS[waveform_generator]][ + "link_direction"] = "downlink" + # ---------------------------------------------------- + # Set 2: Parameters that is hardcoded + # ---------------------------------------------------- + tx_metadata["signal:detail"][STANDARDS[waveform_generator]][ + "pusch:content"] = "compliant" + tx_metadata["signal:detail"][STANDARDS[waveform_generator]][ + "pusch:mapping_type"] = "B" + tx_metadata["signal:detail"][STANDARDS[waveform_generator]]["num_slots"] = 1 + if config_meta_data["test_config"]["test_mode"] == "rf_simulation": + tx_metadata["signal:detail"][STANDARDS[waveform_generator]][ + "pusch:payload_bit_pattern"] = "random" + elif config_meta_data["test_config"]["test_mode"] == "rf_real_time": + tx_metadata["signal:detail"][STANDARDS[waveform_generator]][ + "pusch:payload_bit_pattern"] = "zeros" + else: + raise Exception("ERROR: Test mode is not supported in SigMF formatting") + # ---------------------------------------------------- + # Read mean parameters + freq = config_meta_data["environment_emulation"]["target_link_config"][ + "wireless_channel"]["carrierFreqValueList_hz"][0] + bandwidth = config_meta_data["data_recording_config"]["common_meta_data"][ + "bandwidth"] + # used_signal_bandwidth = ( + # pow(10, 6) * config_meta_data["environment_emulation"]["target_link_config"]["ran_config"][ + # "uplink"]["ul_used_signal_BW_MHz"]) + sample_rate = config_meta_data["data_recording_config"]["common_meta_data"][ + "sample_rate"] + + # get signal emitter info + signal_emitter = { + "manufacturer": "NI", + "seid": user_equipment_meta_data["seid"], # Unique ID of the emitter + "hw": user_equipment_meta_data["hw_type"], + "hw_subtype": user_equipment_meta_data["hw_subtype"], + "frequency": freq, + "sample_rate": sample_rate, + "bandwidth": bandwidth, + "gain_tx": user_equipment_meta_data["tx_gain"], + "clock_reference": config_meta_data["data_recording_config"][ + "common_meta_data" + ]["clock_reference"], + } + + # ---------------------------------------------------- + # get channel metadata + # ---------------------------------------------------- + # get downlink channel info + # ch_downlink_config = config_meta_data["environment_emulation"]["target_link_config"]["wireless_channel"]["downlink"] + # ch_downlink ={"channel_model": ch_downlink_config["type"]} + + # ch_downlink_model = {"channel_model": "AWGN"} + # get uplink channel info + ch_uplink_config = config_meta_data["environment_emulation"]["target_link_config"][ + "wireless_channel" + ]["uplink"] + # Real Time RF Emulation + if config_meta_data["test_config"]["test_mode"] == "rf_real_time": + channel_metadata.update({"emulation_mode": "ni rf real time"}) + if ch_uplink_config["type"] == "statistical_predefined": + channel_metadata.update( + { + "channel_model": ch_uplink_config["statistical"]["predef_channel_profile"], + "snr_esn0_db": ch_uplink_config["statistical"]["snr_db"], + } + ) + + elif ch_uplink_config["type"] == "statistical_var": + channel_metadata.update( + { + "channel_model": ch_uplink_config["statistical"]["var_power_delay_profile"], + "snr_esn0_db": ch_uplink_config["statistical"]["snr_db"], + "delay_spread": ch_uplink_config["statistical"]["delay_spread_ns"] * pow(10, -9), + "speed": ch_uplink_config["statistical"]["speed_mps"], + } + ) + else: + raise Exception("ERROR: channel type is not supported in SigMF formatting") + # RF Simulation + elif config_meta_data["test_config"]["test_mode"] == "rf_simulation": + channel_metadata.update({"emulation_mode": "oai rf simulation"}) + channel_metadata.update( + { + "channel_model": ch_uplink_config["statistical"]["predef_channel_profile"], + "snr_esn0_db": ch_uplink_config["statistical"]["snr_db"], + "delay_spread": ch_uplink_config["statistical"]["delay_spread_ns"] + * pow(10, -9), "speed": ch_uplink_config["statistical"]["speed_mps"], + } + ) + else: + raise Exception( + "ERROR: Channel Emulation mode is not supported in SigMF formatting") + + channel_metadata["carrier_frequency"] = config_meta_data["environment_emulation"][ + "target_link_config"]["wireless_channel"]["carrierFreqValueList_hz"][0] + + # ---------------------------------------------------- + # get rx metadata + # ---------------------------------------------------- + rx_metadata.update( + { + "bandwidth": bandwidth, + "gain": base_station_meta_data["rx_gain"], + "manufacturer": "NI", + "seid": base_station_meta_data["seid"], + "hw_subtype": base_station_meta_data["hw_subtype"], + "clock_reference": config_meta_data["data_recording_config"][ + "common_meta_data" + ]["clock_reference"], + "phy_freq_domain_receiver_type": config_meta_data["test_config"][ + "dut_type" + ], + } + ) + # ---------------------------------------------------- + # get test config + # ---------------------------------------------------- + """ + test_config = { + "test_name": config_meta_data["test_config"]["test_name"], + "test_mode": config_meta_data["test_config"]["test_mode"], + "dut_type": config_meta_data["test_config"]["dut_type"], + } + """ + # Create sigmf metadata + # ---------------------- + # Add global parameters to SigMF metadata + # ---------------------- + meta = SigMFFile( + data_file=dataset_file_path, # extension is optional + global_info={ + SigMFFile.DATATYPE_KEY: captured_data[ + "sigmf_data_type" + ], # "cf32_le", # get_data_type_str(rx_data) - 'cf64_le' is not supported yet + SigMFFile.SAMPLE_RATE_KEY: sample_rate, + SigMFFile.NUM_CHANNELS_KEY: 1, + SigMFFile.AUTHOR_KEY: global_info["author"], + SigMFFile.DESCRIPTION_KEY: config_meta_data["data_recording_config"][ + "supported_oai_tracer_messages" + ][captured_data["message_type"]]["description"], + SigMFFile.RECORDER_KEY: "NI Data Recording Application for OAI", + SigMFFile.LICENSE_KEY: "MIT License", + # Since we are focusing on 5G NR UL, the base station is the receiver + SigMFFile.HW_KEY: base_station_meta_data["hw_type"], + # Disable DATASET key to mitigate the warning when read SIGMF data although it is given in the spec. + # It seems SIGMF still has bug here + SigMFFile.DATASET_KEY: dataset_filename, + SigMFFile.VERSION_KEY: sigmf.__version__, + sigmf.SigMFFile.COLLECTION_KEY: global_info["collection_file"], + }, + ) + + # ---------------------- + # Add capture parameters to SigMF metadata + # ---------------------- + serialization_scheme = config_meta_data["data_recording_config"][ + "supported_oai_tracer_messages" + ][captured_data["message_type"]]["serialization_scheme"] + capture_metadata = { + sigmf.SigMFFile.DATETIME_KEY: time_stamp_ms, + SigMFFile.FREQUENCY_KEY: freq, + **create_serialization_metadata( + serialization_scheme, waveform_generator, captured_data + ), + } + meta.add_capture(start_index=0, metadata=capture_metadata) # Sample Start + + # create annotations dict + system_components_dict = { + "system_components:transmitter": [ + { + "transmitter_id": "tx_0", + **tx_metadata, + "signal:emitter": signal_emitter, + } + ] + } + + system_components_dict["system_components:channel"] = [ + {"transmitter_id": "tx_0", **channel_metadata}] + + system_components_dict["system_components:receiver"] = rx_metadata + # ---------------------- + # Add annotation parameters to SigMF metadata + # ---------------------- + meta.add_annotation( + start_index=0, # Sample Start + length=len(captured_data["recorded_data"]), # Sample count + metadata={ + # SigMFFile.FLO_KEY: freq - sample_rate/ 2, # args.freq - args.rate / 2, + # SigMFFile.FHI_KEY: freq + sample_rate/ 2, # args.freq + args.rate / 2, + # SigMFFile.LABEL_KEY: label, + # SigMFFile.COMMENT_KEY: general_config["comment"], + "num_transmitters": 1, + **system_components_dict, + }, + ) + + # Write Meta Data to file + dataset_meta_filename = recorded_data_file_name + ".sigmf-meta" + dataset_meta_file_path = os.path.join(data_storage_path, dataset_meta_filename) + meta.tofile(dataset_meta_file_path) # extension is optional + + print(dataset_meta_file_path) + + return dataset_meta_file_path + + +def save_sigmf_collection(streams: list, global_info: dict, description: str, storage_path: str): + """Save metadata and links to SigMF data/metadata files to SigMF collection file.""" + # construct path + storage_path = os.path.expanduser(storage_path) + collection_filepath = os.path.join(storage_path, global_info["collection_file"]) + # statically configure Collection metadata + collection = SigMFCollection( + streams, + metadata={ + SigMFCollection.COLLECTION_KEY: { + SigMFCollection.VERSION_KEY: sigmf.__version__, + SigMFCollection.DESCRIPTION_KEY: description, + SigMFCollection.AUTHOR_KEY: global_info["author"], + # SigMFCollection.LICENSE_KEY: "License", + # SigMFCollection.EXTENSIONS_KEY: global_info["extensions"], + SigMFCollection.STREAMS_KEY: [], + } + }, + ) + + # save collection file + collection.tofile(collection_filepath) + print("") + print(collection_filepath + ".sigmf-collection") + + +def load_sigmf(filename: str, storage_path: str, scope: str): + """ + Loads metadata and data from SigMF file. + """ + # construct path + storage_path = os.path.expanduser(storage_path) + filepath = os.path.join(storage_path, filename) + # load SigMF file + signal = sigmf.sigmffile.fromfile(filepath) + + # get metadata fields + global_metadata = signal.get_global_info() + annotations_metadata = signal.get_annotations() + + # we only consider single annotations metadata element per SigMF file + annotation_start_idx = annotations_metadata[0][sigmf.SigMFFile.START_INDEX_KEY] + annotation_length = annotations_metadata[0][sigmf.SigMFFile.LENGTH_INDEX_KEY] + + # get capture metadata + capture_metadata = signal.get_capture_info(annotation_start_idx) + + # from source code: sigmffile.py + # "autoscale : bool, default True + # If dataset is in a fixed-point representation, scale samples from (min, max) to (-1.0, 1.0) + # raw_components : bool, default False + # If True read and return the sample components (individual I & Q for complex, samples for real) + # with no conversions or interleaved channels."" + # TODO: problem: raw_components flag is not used at all! changes in source code required! + # TODO: data is always converted to float32 after being read + + # read actual data + data = signal.read_samples( + annotation_start_idx, annotation_length, autoscale=False, raw_components=True) + + return data, global_metadata, annotations_metadata diff --git a/common/utils/data_recording/lib/sync_service.py b/common/utils/data_recording/lib/sync_service.py new file mode 100644 index 0000000000..87538173fd --- /dev/null +++ b/common/utils/data_recording/lib/sync_service.py @@ -0,0 +1,150 @@ + +# /* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (the "License"); you may not use this file +# * except in compliance with the License. +# * You may obtain a copy of the License at +# * +# * http://www.openairinterface.org/?page_id=698 +# * +# * Unless required by applicable law or agreed to in writing, software +# * distributed under the License is distributed on an "AS IS" BASIS, +# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# * See the License for the specific language governing permissions and +# * limitations under the License. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +# --------------------------------------------------------------------- +# file common/utils/data_recording/lib/sync_service.py +# brief Sync service between captured Data from 5GNR gNB and UE +# author Abdo Gaber +# date 2025 +# version 1.0 +# company Emerson, NI Test and Measurement +# email: +# note +# warning + +import struct +from lib import data_recording_messages_def + +DEBUG_POW_MEAS_SYNC = True + + +# check if first frame ahead: +def is_frame_ahead(frame1, frame2, max_frame=1023): + """ + Check if frame1 is ahead of frame2, considering wrap-around from max_frame to 0. + + Args: + frame1 (int): The first frame number. + frame2 (int): The second frame number. + max_frame (int): The maximum frame number before wrap-around. Default is 1023. + + Returns: + bool: True if frame1 is ahead of frame2, False otherwise. + """ + # Calculate the difference considering wrap-around + diff = (frame1 - frame2 + (max_frame + 1)) % (max_frame + 1) + # If the difference is less than half the range, frame1 is ahead + return diff < (max_frame + 1) // 2 + + +# find the frame and slot start +def find_frame_slot_start(dataset1_start, dataset2_start): + """ + Function to find the frame and slot start for data sync + Args: + dataset1_start_info: Dictionary containing the start information of dataset1 + dataset2_start_info: Dictionary containing the start information of dataset2 + Returns: + sync_info: Dictionary containing the sync information + sync_info["frame"] = frame_start + sync_info["slot"] = slot_start + + """ + sync_info = {} + + if dataset1_start["frame"] == dataset2_start["frame"]: + frame_diff = 0 + frame_start = dataset1_start["frame"] + slot_start = max(dataset1_start["slot"], dataset2_start["slot"]) + + elif is_frame_ahead(dataset1_start["frame"], dataset2_start["frame"]): + frame_start = dataset1_start["frame"] + slot_start = dataset1_start["slot"] + frame_diff = (dataset1_start["frame"]- dataset2_start["frame"] + 1024) % 1024 + elif is_frame_ahead(dataset2_start["frame"], dataset1_start["frame"]): + frame_start = dataset2_start["frame"] + slot_start = dataset2_start["slot"] + frame_diff = (dataset2_start["frame"] - dataset1_start["frame"] + 1024) % 1024 + # check first if the delta time between the two datasets is larger than expected offset time. + # So, the sync will not be applied + # check during the calculation of the frame the ramp-around from 1023 to 0 + if abs(frame_diff) > 6: + raise Exception( + f"Frame difference between dataset1 and dataset2 is too large: {frame_diff}. " + "This may indicate a problem with the data collection or synchronization." + ) + + # Determine the starting frame and slot for data sync + sync_info["frame"] = frame_start + sync_info["slot"] = slot_start + return sync_info + + +# Read data from gNB T-tracer Application +def get_frame_slot_start(shm_reading, bufIdx, general_msg_header_list, + general_message_header_length): + buf = shm_reading.read(bufIdx + general_message_header_length) + msg_id = struct.unpack(" Date: Mon, 10 Mar 2025 13:08:22 +0100 Subject: [PATCH 261/964] Add Readme for the Data Recording Application It provides and overview about the Architecture, Requirement Packages, Configuration Files, How to run Data Recording Application, and an Overview on Collected Data Set. --- doc/data_recording.md | 488 ++++++++++++++++++ doc/images/data_recording_arch.svg | 48 ++ ...serialization_tx_scrambled_bit_message.svg | 48 ++ doc/images/sigmf_dataset.svg | 48 ++ 4 files changed, 632 insertions(+) create mode 100644 doc/data_recording.md create mode 100644 doc/images/data_recording_arch.svg create mode 100644 doc/images/data_serialization_tx_scrambled_bit_message.svg create mode 100644 doc/images/sigmf_dataset.svg diff --git a/doc/data_recording.md b/doc/data_recording.md new file mode 100644 index 0000000000..8d4680a4cf --- /dev/null +++ b/doc/data_recording.md @@ -0,0 +1,488 @@ +# Synchronized Real-Time Data Recording Application + +The Data Recording Application runs in parallel to the system components on one of the LINUX servers. It makes use of OAI T-tracer framework. It is able to communicate with the Base station (gNB) and User terminal (UE). +In addition, it synchronizes and combines data traces and control information (metadata) from Base station and User terminal into consistent [Signal Metadata Format (SigMF) format](https://github.com/gnuradio/SigMF) data sets. SigMF is an open-source standard that specifies a way to describe sets of recorded digital signal samples with metadata (data properties and scenario descriptions) provided in [JSON](http://www.json.org/) files. These recorded data sets have a wide range of uses in research and applications. + +## Data Recording Application Architecture + +Data Recording Application designed to have multiple services in different simulation environments: +- Data Control Service (Python) +- Data collection (T-Tracer) Service (C) +- Data Conversion Service (Python) + +Regarding to the APIs between different services, they are such as the following: +- Data Control Service -> Data Collection (T–Tracer) Service: The API is based on a shared memory. +- Data Collection (T–Tracer) Service -> 5G NR Stack: T-Tracer Framework, ethernet connection. +- Data Collection (T–Tracer) Service -> Data Conversion Service: The API is based on a shared memory. + +The following figure shows OAI gNB and UE with the Data Recording App system architecture. + +OAI gNB and UE with the Data Recording App system architectur + +## Required Packages +Install all required system packages with the following commands: +```bash +sudo apt-get update +sudo apt-get install -y python3-sysv-ipc libxft-dev +``` + +Then, install all required python packages with the following commands: +```bash +python3 -m pip install sigmf==1.2.1 termcolor bitarray pandas numpy==1.23 +``` + +User can install all required python packages also using the `requirements.txt` file: +```bash +python3 -m pip install -r common/utils/data_recording/requirements.txt +``` + +## Configuration Files +### Main Data Recording JSON Configuration File +The Data Recording application provides configuration file in [JSON](http://www.json.org/) format. It is stored in [common/utils/data_recording/config/config_data_recording.json](../common/utils/data_recording/config/config_data_recording.json) folder. The main parameters are: +- **data_storage_path**: Path to directory for data storage +- **num_records**: Number of requested data records in slots +- **t_tracer_message_definition_file**: T-Tracer message definition file +- **parameter_map_file**: Parameter mapping dictionary (OAI parameters to standardized metadata). It is located here: [common/utils/data_recording/config/wireless_link_parameter_map.yaml](../common/utils/data_recording/config/wireless_link_parameter_map.yaml) +- **start_frame_number**: It can be used to start the recording from a specific frame, but it is not yet supported. +- **base_station**: + - requested_tracer_messages: Requested base station data traces. The supported messages are: + - GNB_PHY_UL_FD_PUSCH_IQ + - GNB_PHY_UL_FD_DMRS + - GNB_PHY_UL_FD_CHAN_EST_DMRS_POS + - GNB_PHY_UL_FD_CHAN_EST_DMRS_INTERPL + - GNB_PHY_UL_PAYLOAD_RX_BITS + - meta_data: Additional base station metadata (additional fixed base station parameters that cannot be read from the system yet, but shall be included into the SigMF metadata) +- **user_equipment** + - requested_tracer_messages: Requested user equipment data traces. The supported messages are: + - UE_PHY_UL_SCRAMBLED_TX_BITS + - UE_PHY_UL_PAYLOAD_TX_BITS + - meta_data: Additional user equipment metadata (additional fixed UE parameters that are not read from the system yet, but shall be included into the SigMF metadata) +- **common_meta_data**: Common metadata parameters that are not read from the system yet, but shall be included into the SigMF metadata such as the sampling rate, the bandwidth, and the clock reference of USRP. +- **tracer_service_baseStation_address**: The IP address and port number of base station server. If the Data Recording App and the Data Collection (T–Tracer) Service are running on the same server of base station, the IP address and port number are : `127.0.0.1:2021` +- **tracer_service_userEquipment_address**: The IP address and port number of UE server. + +**Notes**: +- The data can be recorded from base station and UE or from base station only or UE only. To disable the recording from any station, make the list of `requested_tracer_messages` empty such as: `requested_tracer_messages:[]` + +The figure below illustrates an example of a JSON Data Recording App configuration file. + +```json +{ +"data_recording_config": { + "data_storage_path": "/home/user/workarea/oai_recorded_data/", + "data_file_format": "SigMF", + "enable_saving_tracer_messages_sigmf": true, + "num_records": 5, + "t_tracer_message_definition_file": "../T/T_messages.txt", + "parameter_map_file": "config/wireless_link_parameter_map.yaml", + "start_frame_number": 5, + "base_station": { + "requested_tracer_messages": [ + "GNB_PHY_UL_FD_PUSCH_IQ", + "GNB_PHY_UL_FD_DMRS", + "GNB_PHY_UL_FD_CHAN_EST_DMRS_POS", + "GNB_PHY_UL_FD_CHAN_EST_DMRS_INTERPL", + "GNB_PHY_UL_PAYLOAD_RX_BITS" + ], + "meta_data":{ + "num_rx_antennas": 1, + "tx_gain": 48.0, + "rx_gain": 30.0, + "hw_type": "USRP X410", + "hw_subtype": "ZBX", + "seid": "328AB35" + } + }, + "user_equipment": { + "requested_tracer_messages": [ + "UE_PHY_UL_SCRAMBLED_TX_BITS", + "UE_PHY_UL_PAYLOAD_TX_BITS" + ], + "meta_data":{ + "num_tx_antennas": 1, + "tx_gain": 48.0, + "rx_gain": 40.0, + "hw_type": "USRP X410", + "hw_subtype": "ZBX", + "seid": "323F75F" + } + }, + "common_meta_data": { + "sample_rate": 61440000.0, + "bandwidth": 40000000.0, + "clock_reference": "external" + }, + "tracer_service_baseStation_address": "127.0.0.1:2021", + "tracer_service_userEquipment_address": "127.0.0.1:2023" + } +} +``` + +### Wireless Link Parameter Map Dictionary +Since every signal recorder has related configuration with different naming scheme, the [common/utils/data_recording/config/wireless_link_parameter_map.yaml](../common/utils/data_recording/config/wireless_link_parameter_map.yaml) is a dictionary to do the parameters pair between the signal configuration and the SigMF metadata (e.g. OAI parameter name vs. SigMF metadata parameter name). It eases of adoption in case of adding new parameters. In case of changing the name of given parameters in OAI and we need to get those parameters in metadata, the required changes need to be done in the parameter map dictionary. + +The following figure shows an example of Wireless Link Parameter Map Dictionary. For example, the frequency range is called in standardized SigMF metadata `frequency_range` while it is called in OAI `freq_range` and it is called in NI 5G NR RFmx `frequency range`. + +```yaml + # Frequency Range + - sigmf_parameter_name: "frequency_range" + description: "Frequency Range" + 5gnr_ni_rfmx_rfws_parameter: + name: "Frequency Range" + value_map: # simu value : SigMF value + "Range 1": "fr1" + "Range 2": "fr2" + 5gnr_oai_parameter: + name: "freq_range" + value_map: # simu value : SigMF value + 0: "fr1" + 1: "fr2" +``` + +### Global Metadata +There are some metadata parameters that the user may need to change only once. Those parameters have been hard coded in the Data Recording App header. +[common/utils/data_recording/data_recording_app_v1.0.py](../common/utils/data_recording/data_recording_app_v1.0.py). Those are: +- The global metadata such as: author, description, sigmf collection file prefix, datetime_offset, enable saving config Data Recording App in json file with recorded data, and name of signal generator (i.e. 5gnr_oai). The name of signal generator is used for parameter mapping dictionary (OAI parameters to standardized metadata). +- The mapping between supported OAI messages and file_name_prefix, scope, and description. + +The following figure shows an example of global metadata. + +```python +# globally applicable metadata +global_info = { + "author": "Abdo Gaber", + "description": "Synchronized Real-Time Data Recording", + "timestamp": 0, + "collection_file_prefix": "data-collection", # collection file name prefix "deap-rx + str(...)" + "collection_file": "", # Reserved to be created in the code: “data-collection_rec-0_TIME-STAMP” + "datetime_offset": "", # datetime offset between current location and UTC/Zulu timezone + # Example: "+01:00" for Berlin, Germany + "save_config_data_recording_app_json": True, + "waveform_generator": "5gnr_oai", + "extensions": {}, +} +``` + +The following figure shows an example of mapping between supported OAI messages by Data recorrding App and file_name_prefix. + +```python +supported_oai_tracer_messages = { + # gNB messages + "GNB_PHY_UL_FD_PUSCH_IQ": { + "file_name_prefix": "rx-fd-data", + "scope": "gNB", + "description": "Frequency-domain RX data", + "serialization_scheme": ["subcarriers", "ofdm_symbols"], + }, + "GNB_PHY_UL_FD_DMRS": { + "file_name_prefix": "tx-pilots-fd-data", + "scope": "gNB", + "description": "Frequency-domain TX PUSCH DMRS data", + "serialization_scheme": ["subcarriers", "ofdm_symbols"], + }, + "GNB_PHY_UL_FD_CHAN_EST_DMRS_POS": { + "file_name_prefix": "raw-ce-fd-data", + "scope": "gNB", + "description": "Frequency-domain raw channel estimates (at DMRS positions)", + "serialization_scheme": ["subcarriers", "ofdm_symbols"], + }, + "GNB_PHY_UL_FD_CHAN_EST_DMRS_INTERPL": { + "file_name_prefix": "raw-inter-ce-fd-data", + "scope": "gNB", + "description": "Interpolcated Frequency-domain raw channel estimates", + "serialization_scheme": ["subcarriers", "ofdm_symbols"], + }, + "GNB_PHY_UL_PAYLOAD_RX_BITS": { + "file_name_prefix": "rx-payload-bits", + "scope": "gNB", + "description": "Received PUSCH payload bits", + "serialization_scheme": ["bits", "subcarriers", "ofdm_symbols"], + }, + # UE messages + "UE_PHY_UL_SCRAMBLED_TX_BITS": { + "file_name_prefix": "tx-scrambled-bits", + "scope": "UE", + "description": "Transmitted scrambled PUSCH bits", + "serialization_scheme": ["bits", "subcarriers", "ofdm_symbols"], + }, + "UE_PHY_UL_PAYLOAD_TX_BITS": { + "file_name_prefix": "tx-payload-bits", + "scope": "UE", + "description": "Transmitted PUSCH payload bits", + "serialization_scheme": ["bits", "subcarriers", "ofdm_symbols"], + }, +} +``` + +## How to run Data Recording Application +The data recording application can be hosted on the gNB Server or in another server (for example the data lake server). The T-Tracer framework is a Network socket-based (TCP) communication between OAI 5G RAN stack and external tracer program. + +### Step1: Run NR gNB Softmodem with enabling T-Tracer Option + +It is worth mentioning that there is no need to set the T-Tracer port number via NR gNB Softmodem command, the default port `2021` is going to be used. If the Data Recording App is running on the same server of gNB, the parameter `tracer_service_baseStation_address` should be `"tracer_service_baseStation_address": "127.0.0.1:2021`. The gNB T-tracer App will read captured data then from port `2021`. +For the test simplicity, user can run the system in PHY-test mode. We will show how to run using PHY-Test mode: + +Run NR gNB Softmodem with USRP: +``` +sudo ./cmake_targets/ran_build/build/nr-softmodem -O ./targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.band78.sa.fr1.106PRB.1x1.usrpx410_3300MHz.conf --gNBs.[0].min_rxtxtime 6 --usrp-tx-thread-config 1 --phy-test -d --T_stdout 2 --T_nowait +``` +Run NR gNB Softmodem in RF Simulation: +``` +sudo ./cmake_targets/ran_build/build/nr-softmodem -O ./targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.band78.sa.fr1.106PRB.1x1.usrpx410_3300MHz.conf --gNBs.[0].min_rxtxtime 6 --rfsim --rfsimulator.serveraddr server --phy-test -d --T_stdout 2 --T_nowait +``` +Note: User needs to change the name of gNB config file to your gNB config file. + +It is worth mentioning that the possible values for T-tracer control options +- --T_stdout option: default 1 + - --T_stdout = 0: Disable output on the terminal and only use the T tracer + - --T_stdout = 1: Disable the T tracer and only output on the terminal + - --T_stdout = 2: Both Eeable the T tracer and output on the terminal +- --T_nowait: Starting gNB without waiting for T-Tracer to be connected +- --T_port [port]: Default port 2021 + +### Step2: Run NR UE Softmodem with enabling T-Tracer Option + +User needs to set the T-Tracer port number via NR UE Softmodem command, assume `2023`. The UE T-tracer App will read captured data then from port `2023`. The IP address and port number are configured in JSON file via the parameter: `"tracer_service_userEquipment_address": "192.168.100.3:2023”`, where the IP address `192.168.100.3` is the IP address of the UE server. +In OAI PHY-test mode, after running the NR gNB softmodem, copy from gNB Server the following two RRC files `reconfig.raw` and `rbconfig.raw` to UE Server (assume to `/home/user/workarea/rrc_files/`): + +Run OAI Soft UE with USRP: +``` +sudo ./cmake_targets/ran_build/build/nr-uesoftmodem --usrp-args "type=x4xx,addr=192.168.10.2,second_addr=192.168.11.2,clock_source=external,time_source=external" --phy-test -O ./targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.conf --reconfig-file /home/user/workarea/rrc_files/reconfig.raw --rbconfig-file /home/user/workarea/rrc_files/rbconfig.raw --ue-rxgain 40 --ue-txgain 12 --T_stdout 2 --T_nowait --T_port 2023 +``` + + +Run OAI Soft UE in RF Simulation, assume the IP address of gNB server is `192.168.100.2`: +``` +sudo ./cmake_targets/ran_build/build/nr-uesoftmodem --rfsim --rfsimulator.serveraddr 192.168.100.2 --phy-test -O ./targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.conf --reconfig-file /home/user/workarea/rrc_files/reconfig.raw --rbconfig-file /home/user/workarea/rrc_files/rbconfig.raw --T_stdout 2 --T_nowait --T_port 2023 +``` + +### Step3: Run Data Recording Application Services +First, compile the Data Collection (T-Tracer) Services: +- Go to: `common/utils/T/tracer` +- Compile gNB and UE Data Collection Services (T-Tracer Apps) +``` +make t_tracer_app_gnb +make t_tracer_app_ue +``` + +Run gNB Data Collection service on one terminal: +``` +./t_tracer_app_gnb -d ../T_messages.txt +``` +Run UE Data Collection service on another terminal: +``` +./t_tracer_app_ue -d ../T_messages.txt +``` + +Second, run main Data Recording Application: +- Go to: `common/utils/data_recording` + +Run the following python script: +``` +python3 data_recording_app_v1.0.py +``` + +The recorded data set will be stored in the configured path, assume `/home/user/workarea/oai_recorded_data/`. +The following figure shows an example of recorded data set. + +Example from SigMF recorded data set + +## Overview on Collected Data Set + +SigMF supports heterogeneous data via SigMF collections. It is used to bundle multiple SigMF files into one recording. +A heterogeneous data set generated for a certain scenario is stored in a SigMF collection which consists of (as it is shown in the figure above) +- One SigMF collection file per each record, e.g. + - data-collection-rec-idx-timestamp.sigmf-collection +- SigMF recordings (.sigmf-meta file + .sigmf-data file). Per each message, there are two files: + - rx-fd-data-rec-idx-timestamp.sigmf-meta + - rx-fd-data-rec-idx-timestamp.sigmf-data + - tx-pilots-fd-data-rec-idx-timestamp.sigmf-meta + - tx-pilots-fd-data-rec-idx-timestamp.sigmf-data + - raw-ce-fd-data-rec-idx-timestamp.sigmf-meta + - raw-ce-fd-data-rec-idx-timestamp.sigmf-data + - tx-scrambled-bits-rec-idx-timestamp.sigmf-meta + - tx-scrambled-bits-rec-idx-timestamp.sigmf-data + +The following figure shows an example of SigMF collection file and how it bundles multiple SigMF files of a single record. + +```json +{ + "collection": { + "core:author": "Abdo Gaber", + "core:description": "Synchronized Real-Time Data Recording", + "core:streams": [ + { + "hash": "0a39edb03eb86fb0d368a0511f17b0e99d3314d09b1d271c8bc893dffbb6b06b8987362bd15a334f8da40091ca83f6201218084fc602b562b5b012933bc4608a", + "name": "/home/user/workarea/oai_recorded_data/tx-pilots-fd-data-rec-0-2025_06_19T11_19_00_037" + }, + { + "hash": "f2062ff3a7020e2569c9d1d3c5a8403dacf83a1e842b126f889262d56a1b2efc818962d198cd5219bf563aba5e0709e80eba40bd973de95787319e8380d339ba", + "name": "/home/user/workarea/oai_recorded_data/raw-ce-fd-data-rec-0-2025_06_19T11_19_00_037" + }, + { + "hash": "283b62908321db17db6a53c77d41a385360e9f11128627934f4f41746b797b77e41dbc18e72d096126673766edb5d4a9408712f5071d064fae0a792644c16bdd", + "name": "/home/user/workarea/oai_recorded_data/rx-fd-data-rec-0-2025_06_19T11_19_00_037" + }, + { + "hash": "e72f2d6ea3e353d666e7635726ea6a5bd096e6fc14c965c7c2803705bcd0cf934ac9dc3a0c12f190171afc2db7d4b3fd7d5acc8e18796c48d5ee6e7bbd0551b7", + "name": "/home/user/workarea/oai_recorded_data/raw-inter-ce-fd-data-rec-0-2025_06_19T11_19_00_037" + }, + { + "hash": "7eddf8eb4564c03a1505e3288052cc583416617158dbff0bad942af7cc2477449c6c7ff2f02a55849449ba6956800b446f5c0880d418d80fffc24fb236038ef3", + "name": "/home/user/workarea/oai_recorded_data/rx-payload-bits-rec-0-2025_06_19T11_19_00_037" + }, + { + "hash": "ec128fd8691975995df84f96db3740b773cb060d9803f1ae2664e0d081011e59d623f7fe909552e807a4e63cb02e7f9005e8a19ab2a680004d8af9f6b49fff06", + "name": "/home/user/workarea/oai_recorded_data/tx-payload-bits-rec-0-2025_06_19T11_19_00_029" + }, + { + "hash": "d8300b206ede81639c0d8f25030d85ff3b4e848456a7d73c706350fbc2b4ce7b114cddf29173e069335fcf4aeab37818129259afacf0fd02efa34b9b6d985edb", + "name": "/home/user/workarea/oai_recorded_data/tx-scrambled-bits-rec-0-2025_06_19T11_19_00_029" + } + ], + "core:version": "1.2.1" + } +} +``` + +Each SigMF metadata has three sections: +- global: The standardized global parameters are presented here to understand and read the binary data. +- captures: The standardized capture parameters provide details about the capture process. +- annotations: It provides details about the recording scenario. + +The following figure shows an example of SigMF metadata file, for example for the frequency-domain RX data. + +```json +{ + "global": { + "core:author": "Abdo Gaber", + "core:collection": "data-collection-rec-0-2025_06_19T11_19_00_037", + "core:dataset": "raw-ce-fd-data-rec-0-2025_06_19T11_19_00_037.sigmf-data", + "core:datatype": "cf32_le", + "core:description": "Frequency-domain raw channel estimates (at DMRS positions)", + "core:hw": "USRP X410", + "core:license": "MIT License", + "core:num_channels": 1, + "core:recorder": "NI Data Recording Application for OAI", + "core:sample_rate": 61440000.0, + "core:sha512": "55ae5bc81b4812e68f6e1c195600f240fc3ca71113c732271ee42a5524da98636c3c7ac587c46fd87c6d1b9253ca6504a4b94eafba8f4065099096fc7721228c", + "core:version": "1.2.1" + }, + "captures": [ + { + "core:datetime": "2025_06_19T11:19:00.037", + "core:frequency": 3319680000.0, + "core:sample_start": 0, + "serialization:counts": [ + 600, + 13 + ], + "serialization:scheme": [ + "subcarriers", + "ofdm_symbols" + ] + } + ], + "annotations": [ + { + "core:sample_count": 7800, + "core:sample_start": 0, + "num_transmitters": 1, + "system_components:channel": [ + { + "carrier_frequency": 3319680000.0, + "channel_model": "tdl_d", + "delay_spread": 5.0000000000000004e-08, + "emulation_mode": "ni rf real time", + "snr_esn0_db": 20.0, + "speed": 5.0, + "transmitter_id": "tx_0" + } + ], + "system_components:receiver": { + "bandwidth": 40000000.0, + "clock_reference": "external", + "gain": 30.0, + "hw_subtype": "ZBX", + "manufacturer": "NI", + "num_rx_antennas": 1, + "phy_freq_domain_receiver_type": "trad_rx", + "seid": "328AB35" + }, + "system_components:transmitter": [ + { + "signal:detail": { + "5gnr": { + "cell_id": 0, + "cp_mode": "normal", + "frame": 785, + "frame_structure": "tdd", + "frequency_range": "fr1", + "link_direction": "uplink", + "num_slots": 1, + "num_tx_antennas": 1, + "pusch:content": "compliant", + "pusch:mapping_type": "B", + "pusch:mcs": 9, + "pusch:mcs_table_index": 0, + "pusch:modulation": "qpsk", + "pusch:num_layer": 1, + "pusch:num_ofdm_symbols": 13, + "pusch:num_prb": 50, + "pusch:payload_bit_pattern": "zeros", + "pusch:start_ofdm_symbol": 0, + "pusch:start_prb": 0, + "pusch:transform_precoding": "disabled", + "pusch_dmrs:antennna_port": 0, + "pusch_dmrs:duration_num_ofdm_symbols": 1, + "pusch_dmrs:num_add_positions": 2, + "pusch_dmrs:ofdm_symbol_idx": [ + 0, + 5, + 10 + ], + "pusch_dmrs:resource_map_config": "5g nr type 1", + "pusch_dmrs:start_ofdm_symbol": 0, + "rnti": 4660, + "slot": 8, + "subcarrier_spacing": 30000 + }, + "generator": "OpenAirInterface: https://www.openairinterface.org/", + "standard": "5gnr" + }, + "signal:emitter": { + "bandwidth": 40000000.0, + "clock_reference": "external", + "frequency": 3319680000.0, + "gain_tx": 48.0, + "hw": "USRP X410", + "hw_subtype": "ZBX", + "manufacturer": "NI", + "sample_rate": 61440000.0, + "seid": "323F75F" + }, + "transmitter_id": "tx_0" + } + ] + } + ] +} +``` + +## Synchronization Validation +For synchronization validation and to show how to read SigMF metadata, a simple script `common/utils/data_recording/sync_validation_demo.py` has been created to validate that, for example: the recorded bits from gNB and UE are in sync. + +## Data Recording Application Limitation + +- MIMO Support: The data recording app is ready, tested and validated for SISO. For MIMO, it should be enhanced, tested, and validated. +- It supports the uplink gNB and UE messages listed above. If the user would like to record another message for example from DL, the user needs to define the required meta-data. User can use the existing meta-data definition of UL as a template. Then, add those messages to the headers of different Data Recording App services. +- Data serialization in Tx scrambled bits message without considering location of DMRS symbols: Only captured valid data bits is stored. It means the location of DMRS symbols are not considered and filled with zeros and stored as it is in the grid presented on the figure below. For example: + - Number of bits per IQ Symbol = 4 + - Number of subcarrier = 72 + - Number of OFDM symbols = 13 + - So, the valid number of bits in the transport block (slot) is: 3312 bits. If we will fill DMRS locations by zeros, the number of bits is: 3744 bits, but it is not done due to the real-timing issues. For Tx scrambled bits data de-serialization, the user can reconstruct the Tx Scrambled Bits Grid (2D Grid) by using the captured DMRS grid or Channel Estimates Grid as a reference and no need to derive the DMRS symbols locations based on 5G NR config parameters. + +Data serialization + +### To Do List: +- Provide an overview about the different services of the Data Recording App (Data Control Service, Data collection (T-Tracer) Service, Data Conversion Service) and the APIs definition between them. diff --git a/doc/images/data_recording_arch.svg b/doc/images/data_recording_arch.svg new file mode 100644 index 0000000000..ea5019210c --- /dev/null +++ b/doc/images/data_recording_arch.svg @@ -0,0 +1,48 @@ + + + + + + + + + + diff --git a/doc/images/data_serialization_tx_scrambled_bit_message.svg b/doc/images/data_serialization_tx_scrambled_bit_message.svg new file mode 100644 index 0000000000..a86047134a --- /dev/null +++ b/doc/images/data_serialization_tx_scrambled_bit_message.svg @@ -0,0 +1,48 @@ + + + + + + + + + + diff --git a/doc/images/sigmf_dataset.svg b/doc/images/sigmf_dataset.svg new file mode 100644 index 0000000000..42393f488a --- /dev/null +++ b/doc/images/sigmf_dataset.svg @@ -0,0 +1,48 @@ + + + + + + + + + + From 465d7de5a9601aad5f7452bc5d255e72efbf23a7 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 21 Jul 2025 12:34:46 +0200 Subject: [PATCH 262/964] Remove --usim-test command line option Remove the --usim-test option: to my knowledge, it's not used by users, and is misleadingly placed in various places where there should not be a difference w.r.t. USIM configuration. When making the changes, I assumed that --usim-test would be 0 (the default), which is the case in all executables when not specified in options except for the nr_dlsim, nr_pbchsmi, nr_ulsim simulators. The only exception is the initialization of PDCP from the MAC, which is not correct (the PDCP is in the CU, so it does not make sense to call it from the MAC which is in the DU). Instead, always initialize from main, even in the NSA case (NSA was covered by the incorrect initialization from MAC). This in turn let to some more cleanup around function du_rlc_data_req(). After receiving GTP packets at the DU, they were given to the PDCP to enqueue the packet at RLC. This does not work anymore, since the PDCP is not initialized; it also does not seem necessary, as this enqueue functionality is necessary to decouple PDCP and RLC to avoid deadlocks in monolithic, but in split-mode, this cannot happen. Instead, call directly into the RLC when receiving GTP packets. --- doc/F1AP/F1-design.md | 4 ++-- executables/nr-softmodem.c | 10 ++------ executables/softmodem-common.h | 5 ---- openair1/SIMULATION/NR_PHY/dlsim.c | 1 - openair1/SIMULATION/NR_PHY/pbchsim.c | 1 - openair1/SIMULATION/NR_PHY/ulsim.c | 1 - openair2/GNB_APP/gnb_config.c | 24 +++++-------------- openair2/LAYER2/MAC/ue_procedures.c | 3 +-- .../LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c | 2 +- openair2/LAYER2/NR_MAC_gNB/main.c | 3 --- openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c | 16 ------------- openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h | 8 ------- openair2/RRC/LTE/MESSAGES/asn1_msg.c | 12 ---------- openair3/NAS/UE/EMM/Authentication.c | 9 +------ .../UE/EMM/SAP/EmmDeregisteredNormalService.c | 9 +------ openair3/NAS/UE/EMM/emm_main.c | 5 ---- openair3/NAS/UE/UEprocess.c | 1 - 17 files changed, 14 insertions(+), 100 deletions(-) diff --git a/doc/F1AP/F1-design.md b/doc/F1AP/F1-design.md index 65ea6b38cf..b96f29c149 100644 --- a/doc/F1AP/F1-design.md +++ b/doc/F1AP/F1-design.md @@ -389,8 +389,8 @@ into the RLC via `enqueue_rlc_data_req()`, or (f1ap) sends a GTP message through the GTP API. In the DU in DL, assuming the GTP-U tunnel exists, GTP decapsulates the packet -and calls the reception call back `du_rlc_data_req()`, which calls -`enqueue_rlc_data_req()` in turn. +and calls the reception call back `nr_rlc_data_req()`, which enqueues the +packet into the UE's RLC buffer. ## Tunnel Setup diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c index 602606039a..5cc5e3a4fc 100644 --- a/executables/nr-softmodem.c +++ b/executables/nr-softmodem.c @@ -261,9 +261,9 @@ static int create_gNB_tasks(ngran_node_t node_type, configmodule_interface_t *cf RC.nrrrc = calloc(1, sizeof(*RC.nrrrc)); RC.nrrrc[0] = RCconfig_NRRRC(); - if (!get_softmodem_params()->nsa && !(node_type == ngran_gNB_DU)) { + if (node_type != ngran_gNB_DU) { // we start pdcp in both cuup (for drb) and cucp (for srb) - init_pdcp(); + nr_pdcp_layer_init(); } if (get_softmodem_params()->nsa) { //&& !NODE_IS_DU(node_type) @@ -513,12 +513,6 @@ static void wait_nfapi_init(char *thread_name) pthread_mutex_unlock(&nfapi_sync_mutex); } -void init_pdcp(void) { - if (!NODE_IS_DU(get_node_type())) { - nr_pdcp_layer_init(); - } -} - #ifdef E2_AGENT static void initialize_agent(ngran_node_t node_type, e2_agent_args_t oai_args) { diff --git a/executables/softmodem-common.h b/executables/softmodem-common.h index 005677a9de..33d4f4cf04 100644 --- a/executables/softmodem-common.h +++ b/executables/softmodem-common.h @@ -66,7 +66,6 @@ extern "C" #define CONFIG_HLP_CLK "tells hardware to use a clock reference (0:internal, 1:external, 2:gpsdo)\n" #define CONFIG_HLP_TME "tells hardware to use a time reference (0:internal, 1:external, 2:gpsdo)\n" #define CONFIG_HLP_TUNE_OFFSET "LO tuning offset to use in Hz\n" -#define CONFIG_HLP_USIM "use XOR autentication algo in case of test usim mode\n" #define CONFIG_HLP_NOSNGLT "Disables single-thread mode in lte-softmodem\n" #define CONFIG_HLP_DLF "Set the downlink frequency for all component carriers\n" #define CONFIG_HLP_ULF "Set the uplink frequency offset for all component carriers\n" @@ -134,7 +133,6 @@ extern "C" #define TIMING_SOURCE softmodem_params.timing_source #define TUNE_OFFSET softmodem_params.tune_offset #define SEND_DMRSSYNC softmodem_params.send_dmrs_sync -#define USIM_TEST softmodem_params.usim_test #define CHEST_FREQ softmodem_params.chest_freq #define CHEST_TIME softmodem_params.chest_time #define NFAPI softmodem_params.nfapi @@ -156,7 +154,6 @@ extern int usrp_tx_thread; {"phy-test", CONFIG_HLP_PHYTST, PARAMFLAG_BOOL, .iptr=&PHY_TEST, .defintval=0, TYPE_INT, 0}, \ {"do-ra", CONFIG_HLP_DORA, PARAMFLAG_BOOL, .iptr=&DO_RA, .defintval=0, TYPE_INT, 0}, \ {"sl-mode", CONFIG_HLP_SL_MODE, 0, .u8ptr=&SL_MODE, .defintval=0, TYPE_UINT8, 0}, \ - {"usim-test", CONFIG_HLP_USIM, PARAMFLAG_BOOL, .u8ptr=&USIM_TEST, .defintval=0, TYPE_UINT8, 0}, \ {"clock-source", CONFIG_HLP_CLK, 0, .uptr=&CLOCK_SOURCE, .defintval=0, TYPE_UINT, 0}, \ {"time-source", CONFIG_HLP_TME, 0, .uptr=&TIMING_SOURCE, .defintval=0, TYPE_UINT, 0}, \ {"tune-offset", CONFIG_HLP_TUNE_OFFSET, 0, .dblptr=&TUNE_OFFSET, .defintval=0, TYPE_DOUBLE, 0}, \ @@ -221,7 +218,6 @@ extern int usrp_tx_thread; { .s5 = { NULL } }, \ { .s5 = { NULL } }, \ { .s5 = { NULL } }, \ - { .s5 = { NULL } }, \ { .s3a = { config_checkstr_assign_integer, \ {"MONOLITHIC", "PNF", "VNF", "AERIAL","UE_STUB_PNF","UE_STUB_OFFNET","STANDALONE_PNF"}, \ {NFAPI_MONOLITHIC, NFAPI_MODE_PNF, NFAPI_MODE_VNF, NFAPI_MODE_AERIAL,NFAPI_UE_STUB_PNF,NFAPI_UE_STUB_OFFNET,NFAPI_MODE_STANDALONE_PNF}, \ @@ -324,7 +320,6 @@ typedef struct { int phy_test; int do_ra; uint8_t sl_mode; - uint8_t usim_test; int emulate_rf; int chain_offset; int numerology; diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index f1fa7885a4..33fd847ecf 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -654,7 +654,6 @@ printf("%d\n", slot); InitSinLUT(); get_softmodem_params()->phy_test = 1; - get_softmodem_params()->usim_test = 1; get_softmodem_params()->do_ra = 0; IS_SOFTMODEM_DLSIM = true; diff --git a/openair1/SIMULATION/NR_PHY/pbchsim.c b/openair1/SIMULATION/NR_PHY/pbchsim.c index 4fc6f788b7..6279663e74 100644 --- a/openair1/SIMULATION/NR_PHY/pbchsim.c +++ b/openair1/SIMULATION/NR_PHY/pbchsim.c @@ -154,7 +154,6 @@ int main(int argc, char **argv) int ssb_scan_threads = 0; channel_desc_t *gNB2UE; - get_softmodem_params()->usim_test = 1; //uint8_t extended_prefix_flag=0; //int8_t interf1=-21,interf2=-21; diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index 4e127fe0b7..56c9a9dd9f 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -576,7 +576,6 @@ int main(int argc, char *argv[]) get_softmodem_params()->phy_test = 1; get_softmodem_params()->do_ra = 0; - get_softmodem_params()->usim_test = 1; if (snr1set == 0) snr1 = snr0 + 10; diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 5274a4696d..f01b5968f7 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -1237,15 +1237,9 @@ static NR_ServingCellConfigCommon_t *get_scc_config(configmodule_interface_t *cf // TODO: Make CSS aggregation levels configurable int css_num_agg_level_candidates[NUM_PDCCH_AGG_LEVELS]; css_num_agg_level_candidates[PDCCH_AGG_LEVEL1] = NR_SearchSpace__nrofCandidates__aggregationLevel1_n0; - if (get_softmodem_params()->usim_test) { - css_num_agg_level_candidates[PDCCH_AGG_LEVEL2] = NR_SearchSpace__nrofCandidates__aggregationLevel2_n0; - css_num_agg_level_candidates[PDCCH_AGG_LEVEL4] = NR_SearchSpace__nrofCandidates__aggregationLevel4_n1; - css_num_agg_level_candidates[PDCCH_AGG_LEVEL8] = NR_SearchSpace__nrofCandidates__aggregationLevel8_n1; - } else { - css_num_agg_level_candidates[PDCCH_AGG_LEVEL2] = NR_SearchSpace__nrofCandidates__aggregationLevel2_n0; - css_num_agg_level_candidates[PDCCH_AGG_LEVEL4] = NR_SearchSpace__nrofCandidates__aggregationLevel4_n2; - css_num_agg_level_candidates[PDCCH_AGG_LEVEL8] = NR_SearchSpace__nrofCandidates__aggregationLevel8_n0; - } + css_num_agg_level_candidates[PDCCH_AGG_LEVEL2] = NR_SearchSpace__nrofCandidates__aggregationLevel2_n0; + css_num_agg_level_candidates[PDCCH_AGG_LEVEL4] = NR_SearchSpace__nrofCandidates__aggregationLevel4_n2; + css_num_agg_level_candidates[PDCCH_AGG_LEVEL8] = NR_SearchSpace__nrofCandidates__aggregationLevel8_n0; css_num_agg_level_candidates[PDCCH_AGG_LEVEL16] = NR_SearchSpace__nrofCandidates__aggregationLevel16_n0; NR_SearchSpace_t *ss1 = rrc_searchspace_config(true, 1, 0, css_num_agg_level_candidates); @@ -1674,15 +1668,9 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg) // Construct default aggragation level list or read from config int uess_num_agg_level_candidates[NUM_PDCCH_AGG_LEVELS]; uess_num_agg_level_candidates[PDCCH_AGG_LEVEL1] = NR_SearchSpace__nrofCandidates__aggregationLevel1_n0; - if (get_softmodem_params()->usim_test) { - uess_num_agg_level_candidates[PDCCH_AGG_LEVEL2] = NR_SearchSpace__nrofCandidates__aggregationLevel2_n0; - uess_num_agg_level_candidates[PDCCH_AGG_LEVEL4] = NR_SearchSpace__nrofCandidates__aggregationLevel4_n1; - uess_num_agg_level_candidates[PDCCH_AGG_LEVEL8] = NR_SearchSpace__nrofCandidates__aggregationLevel8_n1; - } else { - uess_num_agg_level_candidates[PDCCH_AGG_LEVEL2] = NR_SearchSpace__nrofCandidates__aggregationLevel2_n2; - uess_num_agg_level_candidates[PDCCH_AGG_LEVEL4] = NR_SearchSpace__nrofCandidates__aggregationLevel4_n0; - uess_num_agg_level_candidates[PDCCH_AGG_LEVEL8] = NR_SearchSpace__nrofCandidates__aggregationLevel8_n0; - } + uess_num_agg_level_candidates[PDCCH_AGG_LEVEL2] = NR_SearchSpace__nrofCandidates__aggregationLevel2_n2; + uess_num_agg_level_candidates[PDCCH_AGG_LEVEL4] = NR_SearchSpace__nrofCandidates__aggregationLevel4_n0; + uess_num_agg_level_candidates[PDCCH_AGG_LEVEL8] = NR_SearchSpace__nrofCandidates__aggregationLevel8_n0; uess_num_agg_level_candidates[PDCCH_AGG_LEVEL16] = NR_SearchSpace__nrofCandidates__aggregationLevel16_n0; int* agg_level_list = uess_num_agg_level_candidates; int num_agg_levels = 5; diff --git a/openair2/LAYER2/MAC/ue_procedures.c b/openair2/LAYER2/MAC/ue_procedures.c index fced846a3c..69beaa7281 100644 --- a/openair2/LAYER2/MAC/ue_procedures.c +++ b/openair2/LAYER2/MAC/ue_procedures.c @@ -2460,8 +2460,7 @@ ue_get_sdu(module_id_t module_idP, int CC_id, frame_t frameP, && (bsr_len + phr_len + total_rlc_pdu_header_len + sdu_length_total + MIN_MAC_HDR_RLC_SIZE <= buflen)) { // Workaround for issue in OAI eNB or EPC which are not able to process SRB2 message multiplexed with SRB1 on the same MAC PDU - if (( get_softmodem_params()->usim_test == 0) && (lcid == DCCH1) - && (lcid_rlc_pdu_count == 0) && (num_sdus)) { + if ((lcid == DCCH1) && (lcid_rlc_pdu_count == 0) && (num_sdus)) { // Skip SRB2 multiplex if at least one SRB1 SDU is already multiplexed break; } diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c index b65a829f40..d9b0136069 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -94,7 +94,7 @@ bool DURecvCb(protocol_ctxt_t *ctxt_pP, // The buffer comes from the stack in gtp-u thread, we have a make a separate buffer to enqueue in a inter-thread message queue uint8_t *sdu = malloc16(sdu_buffer_sizeP); memcpy(sdu, sdu_buffer_pP, sdu_buffer_sizeP); - du_rlc_data_req(ctxt_pP, srb_flagP, rb_idP, muiP, confirmP, sdu_buffer_sizeP, sdu); + nr_rlc_data_req(ctxt_pP, srb_flagP, rb_idP, muiP, sdu_buffer_sizeP, sdu); return true; } diff --git a/openair2/LAYER2/NR_MAC_gNB/main.c b/openair2/LAYER2/NR_MAC_gNB/main.c index e4808fe7c7..c4f0fad659 100644 --- a/openair2/LAYER2/NR_MAC_gNB/main.c +++ b/openair2/LAYER2/NR_MAC_gNB/main.c @@ -310,9 +310,6 @@ void mac_top_init_gNB(ngran_node_t node_type, nr_rlc_op_mode_t mode = NODE_IS_MONOLITHIC(node_type) ? NR_RLC_OP_MODE_MONO_GNB : NR_RLC_OP_MODE_SPLIT_GNB; int success = nr_rlc_module_init(mode); AssertFatal(success == 0,"Could not initialize RLC layer\n"); - - // These should be out of here later - if (get_softmodem_params()->usim_test == 0 ) nr_pdcp_layer_init(); } else { RC.nrmac = NULL; } diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c index 4375692e9b..e170e90823 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c @@ -218,22 +218,6 @@ static void enqueue_rlc_data_req(const protocol_ctxt_t *const ctxt_pP, if (pthread_mutex_unlock(&q.m) != 0) abort(); } -void du_rlc_data_req(const protocol_ctxt_t *const ctxt_pP, - const srb_flag_t srb_flagP, - const rb_id_t rb_idP, - const mui_t muiP, - confirm_t confirmP, - sdu_size_t sdu_sizeP, - uint8_t *sdu_pP) -{ - enqueue_rlc_data_req(ctxt_pP, - srb_flagP, - rb_idP, muiP, - confirmP, - sdu_sizeP, - sdu_pP); -} - /****************************************************************************/ /* rlc_data_req queue - end */ /****************************************************************************/ diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h index a77cc895e6..8d6a65cad6 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h @@ -36,14 +36,6 @@ struct NR_SRB_ToAddMod; void nr_pdcp_layer_init(void); -void du_rlc_data_req(const protocol_ctxt_t *const ctxt_pP, - const srb_flag_t srb_flagP, - const rb_id_t rb_idP, - const mui_t muiP, - confirm_t confirmP, - sdu_size_t sdu_sizeP, - uint8_t *sdu_pP); - bool nr_pdcp_data_ind(const protocol_ctxt_t *const ctxt_pP, const srb_flag_t srb_flagP, const rb_id_t rb_id, diff --git a/openair2/RRC/LTE/MESSAGES/asn1_msg.c b/openair2/RRC/LTE/MESSAGES/asn1_msg.c index 6ab23569af..9511a7494b 100644 --- a/openair2/RRC/LTE/MESSAGES/asn1_msg.c +++ b/openair2/RRC/LTE/MESSAGES/asn1_msg.c @@ -4717,18 +4717,6 @@ OAI_UECapability_t *fill_ue_capability(char *UE_EUTRA_Capability_xer_fname, bool // UE_EUTRA_Capability->measParameters.bandListEUTRA.list.count = 0; // no measurements on other bands // UE_EUTRA_Capability->featureGroupIndicators // null - if (get_softmodem_params()->usim_test == 1) { - // featureGroup is mandatory for CMW tests - // featureGroup is filled only for usim-test mode - BIT_STRING_t *bit_string = CALLOC(1, sizeof(*bit_string)); - char featrG[4] = { 0x00, 0x08, 0x00, 0x04 }; - bit_string->buf = CALLOC(1, 4); - memcpy(bit_string->buf, featrG, 4); - bit_string->size = 4; - bit_string->bits_unused = 0; - UE_EUTRA_Capability->featureGroupIndicators = bit_string; - } - if (get_softmodem_params()->nsa && received_nr_msg) { allocate_en_DC_r15(UE_EUTRA_Capability); diff --git a/openair3/NAS/UE/EMM/Authentication.c b/openair3/NAS/UE/EMM/Authentication.c index 55b269f413..33e42e9d99 100644 --- a/openair3/NAS/UE/EMM/Authentication.c +++ b/openair3/NAS/UE/EMM/Authentication.c @@ -210,14 +210,7 @@ int emm_proc_authentication_request(nas_user_t *user, int native_ksi, int ksi, * of the core network by means of the received AUTN parameter and * request the USIM to compute RES, CK and IK for given RAND */ - if(get_softmodem_params()->usim_test == 0) - { - rc = usim_api_authenticate(&user->usim_data, rand, autn, &auts, &res, &ck, &ik); - } - else - { - rc = usim_api_authenticate_test(&user->usim_data, rand, autn, &auts, &res, &ck, &ik); - } + rc = usim_api_authenticate(&user->usim_data, rand, autn, &auts, &res, &ck, &ik); } if (rc != RETURNok) { diff --git a/openair3/NAS/UE/EMM/SAP/EmmDeregisteredNormalService.c b/openair3/NAS/UE/EMM/SAP/EmmDeregisteredNormalService.c index a49f71cd4b..e497353a01 100644 --- a/openair3/NAS/UE/EMM/SAP/EmmDeregisteredNormalService.c +++ b/openair3/NAS/UE/EMM/SAP/EmmDeregisteredNormalService.c @@ -110,14 +110,7 @@ int EmmDeregisteredNormalService(nas_user_t *user, const emm_reg_t *evt) /* * Initiate the attach procedure for EPS services */ - if(get_softmodem_params()->usim_test == 0) - { - rc = emm_proc_attach(user, EMM_ATTACH_TYPE_EPS); - } - else - { - rc = emm_proc_attach(user, EMM_ATTACH_TYPE_IMSI); // CMW500 IMSI initial attach expected - } + rc = emm_proc_attach(user, EMM_ATTACH_TYPE_EPS); break; case _EMMREG_ATTACH_REQ: diff --git a/openair3/NAS/UE/EMM/emm_main.c b/openair3/NAS/UE/EMM/emm_main.c index 3deabbe9be..e934012e4c 100644 --- a/openair3/NAS/UE/EMM/emm_main.c +++ b/openair3/NAS/UE/EMM/emm_main.c @@ -51,11 +51,6 @@ Description Defines the EPS Mobility Management procedure call manager, #include "IdleMode.h" #include "common/utils/mem/oai_memory.h" -/****************************************************************************/ -/**************** E X T E R N A L D E F I N I T I O N S ****************/ -/****************************************************************************/ -extern uint8_t usim_test; - /****************************************************************************/ /******************* L O C A L D E F I N I T I O N S *******************/ /****************************************************************************/ diff --git a/openair3/NAS/UE/UEprocess.c b/openair3/NAS/UE/UEprocess.c index 1de5db45ab..2a38c6a461 100644 --- a/openair3/NAS/UE/UEprocess.c +++ b/openair3/NAS/UE/UEprocess.c @@ -72,7 +72,6 @@ static void _nas_signal_handler(int signal); static void _nas_clean(user_api_id_t *user_api_id, int net_fd); -uint8_t usim_test = 0; // FIXME user must be set up with right itti message instance // FIXME allocate user and initialize its fields nas_user_t *user = NULL; From db22e234465244b65ded22c160e75f93050d5f4d Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 21 Jul 2025 12:38:20 +0200 Subject: [PATCH 263/964] Avoid uninitialized variable btilde MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pre-initialize this variable. It should be set in pucch2x_scrambling(), but the compiler warns with In function ‘pucch2x_modulation’, inlined from ‘generate_pucch2x’ at oai/openair1/PHY/LTE_UE_TRANSPORT/pucch_ue.c:425:3: oai/openair1/PHY/LTE_UE_TRANSPORT/pucch_ue.c:361:18: warning: ‘btilde’ may be used uninitialized [-Wmaybe-uninitialized] 361 | d[i] = btilde[i] == 1 ? -amp : amp; oai/openair1/PHY/LTE_UE_TRANSPORT/pucch_ue.c: In function ‘generate_pucch2x’: oai/openair1/PHY/LTE_UE_TRANSPORT/pucch_ue.c:387:11: note: ‘btilde’ declared here 387 | uint8_t btilde[20]; --- openair1/PHY/LTE_UE_TRANSPORT/pucch_ue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair1/PHY/LTE_UE_TRANSPORT/pucch_ue.c b/openair1/PHY/LTE_UE_TRANSPORT/pucch_ue.c index 8db7549b36..d6361f4606 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/pucch_ue.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/pucch_ue.c @@ -384,7 +384,7 @@ void generate_pucch2x(int32_t **txdataF, int i,j; uint32_t B=0; - uint8_t btilde[20]; + uint8_t btilde[20] = {0}; int16_t d[22]; uint8_t deltaPUCCH_Shift = fp->pucch_config_common.deltaPUCCH_Shift; uint8_t NRB2 = fp->pucch_config_common.nRB_CQI; From 0ccf1879ae28dcb792132bc12064962c4905b0b8 Mon Sep 17 00:00:00 2001 From: luis_pereira87 Date: Thu, 29 May 2025 12:21:17 +0100 Subject: [PATCH 264/964] Improve SearchSpace selection There is a removal of the NR_SearchSpace__searchSpaceType_PR because, at this point, the gNB already selected the searchspace and it calls this function only to find the coreset with controlResourceSetId based on the previously searchspace id selected; There is no need to send a pointer to the entire searchspace structure because we only need the controlResourceSetId: NR_ControlResourceSetId_t coreset_id = *ss->controlResourceSetId; It also prevents a segmentation fault, in develop when NR_SearchSpace__searchSpaceType_PR_common because gNB calls sched_ctrl->coreset = get_coreset(nr_mac, scc, bwpd, sched_ctrl->search_space, target_ss); the bwpd is NR_BWP_DownlinkDedicated_t *bwpd = NULL; and is it incompatible with the cast to NR_BWP_Downlink_t in coreset = ((NR_BWP_Downlink_t*)bwp)->bwp_Common->pdcch_ConfigCommon->choice.setup->commonControlResourceSet; this was never noticed until now because gNB barely used NR_SearchSpace__searchSpaceType_PR_common --- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 33 ++++++++++--------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index e732148b08..ed49f3451d 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -405,28 +405,31 @@ NR_ControlResourceSet_t *get_coreset(gNB_MAC_INST *nrmac, } static NR_SearchSpace_t *get_searchspace(NR_ServingCellConfigCommon_t *scc, - NR_BWP_DownlinkDedicated_t *bwp_Dedicated, + NR_BWP_DownlinkDedicated_t *bwp_dedicated, NR_SearchSpace__searchSpaceType_PR target_ss) { - int n = 0; - if(bwp_Dedicated) - n = bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list.count; - else - n = scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->commonSearchSpaceList->list.count; + if (bwp_dedicated) { + const int n = bwp_dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list.count; + for (int i = 0; i < n; i++) { + NR_SearchSpace_t *ss = bwp_dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list.array[i]; + if (ss->searchSpaceType->present == target_ss) { + AssertFatal(ss->controlResourceSetId, "searchSpaceId %ld has a NULL controlResourceSetId\n", ss->searchSpaceId); + return ss; + } + } + AssertFatal(false, "Couldn't find an adequate SearchSpace for target SearchSpace %d in BWP_DownlinkDedicated\n", target_ss); + } - for (int i=0;ipdcch_Config->choice.setup->searchSpacesToAddModList->list.array[i]; - else - ss = scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->commonSearchSpaceList->list.array[i]; - AssertFatal(ss->controlResourceSetId != NULL, "ss->controlResourceSetId is null\n"); - AssertFatal(ss->searchSpaceType != NULL, "ss->searchSpaceType is null\n"); + const int n = scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->commonSearchSpaceList->list.count; + for (int i = 0; i < n; i++) { + NR_SearchSpace_t *ss = + scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->commonSearchSpaceList->list.array[i]; if (ss->searchSpaceType->present == target_ss) { + AssertFatal(ss->controlResourceSetId, "searchSpaceId %ld has a NULL controlResourceSetId\n", ss->searchSpaceId); return ss; } } - AssertFatal(0, "Couldn't find an adequate searchspace bwp_Dedicated %p\n",bwp_Dedicated); + AssertFatal(false, "Couldn't find an adequate SearchSpace for target SearchSpace %d in ServingCellConfigCommon\n", target_ss); } NR_sched_pdcch_t set_pdcch_structure(gNB_MAC_INST *gNB_mac, From 641cf84c0c4a59816d9495870fe225b21aaf1fcb Mon Sep 17 00:00:00 2001 From: luis_pereira87 Date: Thu, 29 May 2025 12:22:55 +0100 Subject: [PATCH 265/964] Improve CORESET selection --- .../LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c | 3 +- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 52 ++++++++----------- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 5 +- 3 files changed, 26 insertions(+), 34 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c index 76e9db4fb3..a6d48037a7 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c @@ -686,7 +686,8 @@ static void other_sib_sched_control(module_id_t module_idP, } AssertFatal(nr_of_candidates > 0, "nr_of_candidates is 0\n"); - NR_ControlResourceSet_t *coreset = get_coreset(gNB_mac, scc, NULL, ss, NR_SearchSpace__searchSpaceType_PR_common); + AssertFatal(ss->controlResourceSetId, "ss->controlResourceSetId is NULL\n"); + NR_ControlResourceSet_t *coreset = get_coreset(gNB_mac, scc, NULL, *ss->controlResourceSetId); if (!gNB_mac->sched_pdcch_otherSI) { gNB_mac->sched_pdcch_otherSI = calloc(1, sizeof(*gNB_mac->sched_pdcch_otherSI)); *gNB_mac->sched_pdcch_otherSI = set_pdcch_structure(gNB_mac, ss, coreset, scc, NULL, type0_PDCCH_CSS_config); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index ed49f3451d..f8c842706c 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -369,39 +369,31 @@ NR_pdsch_dmrs_t get_dl_dmrs_params(const NR_ServingCellConfigCommon_t *scc, NR_ControlResourceSet_t *get_coreset(gNB_MAC_INST *nrmac, NR_ServingCellConfigCommon_t *scc, - void *bwp, - NR_SearchSpace_t *ss, - NR_SearchSpace__searchSpaceType_PR ss_type) { - - NR_ControlResourceSetId_t coreset_id = *ss->controlResourceSetId; - - if (ss_type == NR_SearchSpace__searchSpaceType_PR_common) { // common search space - NR_ControlResourceSet_t *coreset; - if(coreset_id == 0) { - coreset = nrmac->sched_ctrlCommon->coreset; // this is coreset 0 - } else if (bwp) { - coreset = ((NR_BWP_Downlink_t*)bwp)->bwp_Common->pdcch_ConfigCommon->choice.setup->commonControlResourceSet; - } else if (scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->commonControlResourceSet) { - coreset = scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->commonControlResourceSet; - } else { - coreset = NULL; - } - - if (coreset) AssertFatal(coreset_id == coreset->controlResourceSetId, - "ID of common ss coreset does not correspond to id set in the " - "search space\n"); - return coreset; - } else { - const int n = ((NR_BWP_DownlinkDedicated_t*)bwp)->pdcch_Config->choice.setup->controlResourceSetToAddModList->list.count; + NR_BWP_DownlinkDedicated_t *bwp_dedicated, + NR_ControlResourceSetId_t coreset_id) +{ + if (coreset_id == 0) { + return nrmac->sched_ctrlCommon->coreset; // this is coreset 0 + } + if (bwp_dedicated) { + const int n = bwp_dedicated->pdcch_Config->choice.setup->controlResourceSetToAddModList->list.count; for (int i = 0; i < n; i++) { - NR_ControlResourceSet_t *coreset = - ((NR_BWP_DownlinkDedicated_t*)bwp)->pdcch_Config->choice.setup->controlResourceSetToAddModList->list.array[i]; - if (coreset_id == coreset->controlResourceSetId) { + NR_ControlResourceSet_t *coreset = bwp_dedicated->pdcch_Config->choice.setup->controlResourceSetToAddModList->list.array[i]; + if (coreset->controlResourceSetId == coreset_id) { return coreset; } } - AssertFatal(0, "Couldn't find coreset with id %ld\n", coreset_id); + AssertFatal(false, "Couldn't find CORESET with id %ld in BWP_DownlinkDedicated\n", coreset_id); } + if (scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->commonControlResourceSet) { + NR_ControlResourceSet_t *coreset = + scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->commonControlResourceSet; + if (coreset->controlResourceSetId == coreset_id) { + return coreset; + } + AssertFatal(false, "Couldn't find CORESET with id %ld in commonControlResourceSet\n", coreset_id); + } + AssertFatal(false, "Couldn't find coreset with id %ld\n", coreset_id); } static NR_SearchSpace_t *get_searchspace(NR_ServingCellConfigCommon_t *scc, @@ -2594,7 +2586,7 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac, // setting PDCCH related structures for sched_ctrl sched_ctrl->search_space = get_searchspace(scc, bwpd, target_ss); - sched_ctrl->coreset = get_coreset(nr_mac, scc, bwpd, sched_ctrl->search_space, target_ss); + sched_ctrl->coreset = get_coreset(nr_mac, scc, bwpd, *sched_ctrl->search_space->controlResourceSetId); sched_ctrl->sched_pdcch = set_pdcch_structure(nr_mac, sched_ctrl->search_space, @@ -2635,7 +2627,7 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac, } AssertFatal(sched_ctrl->search_space != NULL, "SearchSpace cannot be null for RA\n"); - sched_ctrl->coreset = get_coreset(nr_mac, scc, dl_bwp, sched_ctrl->search_space, NR_SearchSpace__searchSpaceType_PR_common); + sched_ctrl->coreset = get_coreset(nr_mac, scc, bwpd, *sched_ctrl->search_space->controlResourceSetId); NR_COMMON_channels_t *cc = &nr_mac->common_channels[0]; int ssb_index = cc->ssb_index[UE->UE_beam_index]; sched_ctrl->sched_pdcch = set_pdcch_structure(nr_mac, diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index ea07fbeea4..66a9262f22 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -283,9 +283,8 @@ void set_r_pucch_parms(int rsetindex, /* find coreset within the search space */ NR_ControlResourceSet_t *get_coreset(gNB_MAC_INST *nrmac, NR_ServingCellConfigCommon_t *scc, - void *bwp, - NR_SearchSpace_t *ss, - NR_SearchSpace__searchSpaceType_PR ss_type); + NR_BWP_DownlinkDedicated_t *bwp_dedicated, + NR_ControlResourceSetId_t coreset_id); long get_K2(NR_PUSCH_TimeDomainResourceAllocationList_t *tdaList, int time_domain_assignment, From 8c58abf85acee6148901c57b5895c28f76ace8b9 Mon Sep 17 00:00:00 2001 From: luis_pereira87 Date: Thu, 29 May 2025 12:30:42 +0100 Subject: [PATCH 266/964] Fix fill 'initialDownlinkBWP->pdsch_Config' when there are DedicatedBWPs This fixes the reported 'RSRP = 0' issue when the UE is in the InitialBWP and we have DedicatedBWPs configured --- openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c index c7fc724747..30ba85c76a 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c @@ -3276,16 +3276,16 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid, } asn1cSeqAdd(&csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list, ssbresset0); - int bwp_loop_end = n_dl_bwp > 0 ? n_dl_bwp : 1; + int bwp_loop_end = n_dl_bwp + 1; for (int bwp_loop = 0; bwp_loop < bwp_loop_end; bwp_loop++) { int curr_bwp, bwp_id; struct NR_SetupRelease_PDSCH_Config *pdsch_Config; - if (n_dl_bwp == 0) { + if (bwp_loop == 0) { pdsch_Config = SpCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config; curr_bwp = NRRIV2BW(scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); bwp_id = 0; } else { - NR_BWP_Downlink_t *bwp = SpCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[bwp_loop]; + NR_BWP_Downlink_t *bwp = SpCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[bwp_loop - 1]; pdsch_Config = bwp->bwp_Dedicated->pdsch_Config; curr_bwp = NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); bwp_id = bwp->bwp_Id; From 7a5d1e55f0286666da8b341f122fce7d5c3770a5 Mon Sep 17 00:00:00 2001 From: luis_pereira87 Date: Thu, 29 May 2025 12:46:00 +0100 Subject: [PATCH 267/964] Add a 'common' type SearchSpace in the NR_BWP_DownlinkDedicated IE for DedicatedBWPs to get DCIs decoded in common searchspace of a DedicatedBWP After RRCSetup, until RRCReconfigurationComplete, gNB continues to schedule ULSCH using DCIs in a common searchspace. In theory, the UE should decode DCIs in: ... However, due to the limited amount of time to investigate this issue, the easy way I found to get DCIs decoded in common searchspace of a DedicatedBWP was by adding a common searchspace in the bwp-Dedicated: ... This way, let's call it a workaround. --- openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c index 30ba85c76a..5052ca6e7a 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c @@ -1631,13 +1631,18 @@ static void config_downlinkBWP(NR_BWP_Downlink_t *bwp, NR_ControlResourceSet_t *coreset2 = get_coreset_config(bwp->bwp_Id, curr_bwp, ssb_bitmap); asn1cSeqAdd(&bwp->bwp_Dedicated->pdcch_Config->choice.setup->controlResourceSetToAddModList->list, coreset2); - searchspaceid = 10 + bwp->bwp_Id; num_cces = get_coreset_num_cces(coreset2->frequencyDomainResources.buf, coreset2->duration); - verify_agg_levels(num_cces, num_agg_level_candidates, coreset->controlResourceSetId, searchspaceid, rrc_num_agg_level_candidates); - NR_SearchSpace_t *ss2 = - rrc_searchspace_config(false, searchspaceid, coreset2->controlResourceSetId, rrc_num_agg_level_candidates); + verify_agg_levels(num_cces, num_agg_level_candidates, coreset2->controlResourceSetId, searchspaceid, rrc_num_agg_level_candidates); + + searchspaceid = 10 + bwp->bwp_Id; + NR_SearchSpace_t *ss2 = rrc_searchspace_config(true, searchspaceid, coreset2->controlResourceSetId, rrc_num_agg_level_candidates); asn1cSeqAdd(&bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list, ss2); + searchspaceid = 20 + bwp->bwp_Id; + NR_SearchSpace_t *ss3 = + rrc_searchspace_config(false, searchspaceid, coreset2->controlResourceSetId, rrc_num_agg_level_candidates); + asn1cSeqAdd(&bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list, ss3); + bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToReleaseList = NULL; bwp->bwp_Dedicated->pdsch_Config = config_pdsch(ssb_bitmap, bwp->bwp_Id, dl_antenna_ports); From 72d9761698097dc5e33b2497a8835332f0138943 Mon Sep 17 00:00:00 2001 From: luis_pereira87 Date: Thu, 29 May 2025 12:37:24 +0100 Subject: [PATCH 268/964] Remove 'searchspaceid' from 'verify_agg_levels' function because it was used only for LOG --- openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c index 5052ca6e7a..02f02089c4 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c @@ -80,7 +80,6 @@ static NR_BWP_t clone_generic_parameters(const NR_BWP_t *gp) static void verify_agg_levels(int num_cce_in_coreset, const int in_num_agg_level_candidates[NUM_PDCCH_AGG_LEVELS], int coresetid, - int searchspaceid, int out_num_agg_level_candidates[NUM_PDCCH_AGG_LEVELS]) { int agg_level_to_n_cces[] = {1, 2, 4, 8, 16}; @@ -94,10 +93,9 @@ static void verify_agg_levels(int num_cce_in_coreset, if (num_agg_level_candidates * agg_level_to_n_cces[i] > num_cce_in_coreset) { int new_agg_level_candidates = num_cce_in_coreset / agg_level_to_n_cces[i]; LOG_E(NR_RRC, - "Invalid configuration: Not enough CCEs in coreset %d, searchspace %d, agg_level %d, number of requested " + "Invalid configuration: Not enough CCEs in coreset %d, agg_level %d, number of requested " "candidates = %d, number of CCES in coreset %d. Aggregation level candidates limited to %d\n", coresetid, - searchspaceid, agg_level_to_n_cces[i], in_num_agg_level_candidates[i], num_cce_in_coreset, @@ -1594,7 +1592,7 @@ static void config_downlinkBWP(NR_BWP_Downlink_t *bwp, int searchspaceid = 5 + bwp->bwp_Id; int rrc_num_agg_level_candidates[NUM_PDCCH_AGG_LEVELS]; int num_cces = get_coreset_num_cces(coreset->frequencyDomainResources.buf, coreset->duration); - verify_agg_levels(num_cces, num_agg_level_candidates, coreset->controlResourceSetId, searchspaceid, rrc_num_agg_level_candidates); + verify_agg_levels(num_cces, num_agg_level_candidates, coreset->controlResourceSetId, rrc_num_agg_level_candidates); NR_SearchSpace_t *ss = rrc_searchspace_config(true, searchspaceid, coreset->controlResourceSetId, rrc_num_agg_level_candidates); asn1cSeqAdd(&bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->commonSearchSpaceList->list, ss); @@ -1632,7 +1630,7 @@ static void config_downlinkBWP(NR_BWP_Downlink_t *bwp, asn1cSeqAdd(&bwp->bwp_Dedicated->pdcch_Config->choice.setup->controlResourceSetToAddModList->list, coreset2); num_cces = get_coreset_num_cces(coreset2->frequencyDomainResources.buf, coreset2->duration); - verify_agg_levels(num_cces, num_agg_level_candidates, coreset2->controlResourceSetId, searchspaceid, rrc_num_agg_level_candidates); + verify_agg_levels(num_cces, num_agg_level_candidates, coreset2->controlResourceSetId, rrc_num_agg_level_candidates); searchspaceid = 10 + bwp->bwp_Id; NR_SearchSpace_t *ss2 = rrc_searchspace_config(true, searchspaceid, coreset2->controlResourceSetId, rrc_num_agg_level_candidates); @@ -3178,7 +3176,6 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid, verify_agg_levels(num_cces, configuration->num_agg_level_candidates, coreset->controlResourceSetId, - searchspaceid, rrc_num_agg_level_candidates); NR_SearchSpace_t *ss2 = rrc_searchspace_config(false, searchspaceid, coreset->controlResourceSetId, rrc_num_agg_level_candidates); asn1cSeqAdd(&bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list, ss); From 0aa19da5680c09664749ce2f75c83427de494b8d Mon Sep 17 00:00:00 2001 From: luis_pereira87 Date: Thu, 29 May 2025 12:11:14 +0100 Subject: [PATCH 269/964] CI: Add DedicatedBWP to '40 MHz TDD F1+E1 SA' in 'RAN-SA-B200-Module-SABOX-Container' --- .../gnb-du.sa.band78.106prb.usrpb200.conf | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf b/ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf index 45482642b9..66e721ef84 100644 --- a/ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf +++ b/ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf @@ -34,11 +34,9 @@ gNBs = # downlinkConfigCommon #frequencyInfoDL - # this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP) - absoluteFrequencySSB = 641280; + absoluteFrequencySSB = 641280; # GSCN: 7929, Freq: 3619.200 MHz dl_frequencyBand = 78; - # this is 3600 MHz - dl_absoluteFrequencyPointA = 640008; + dl_absoluteFrequencyPointA = 640752; # 3611.280 MHz #scs-SpecificCarrierList dl_offstToCarrier = 0; # subcarrierSpacing @@ -47,13 +45,12 @@ gNBs = dl_carrierBandwidth = 106; #initialDownlinkBWP #genericParameters - # this is RBstart=27,L=48 (275*(L-1))+RBstart - initialDLBWPlocationAndBandwidth = 28875; # 6366 12925 12956 28875 12952 + initialDLBWPlocationAndBandwidth = 13750; # RBstart=0, L=51 (275*(L-1))+RBstart # subcarrierSpacing # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 initialDLBWPsubcarrierSpacing = 1; #pdcch-ConfigCommon - initialDLBWPcontrolResourceSetZero = 12; + initialDLBWPcontrolResourceSetZero = 10; initialDLBWPsearchSpaceZero = 0; #uplinkConfigCommon @@ -68,7 +65,7 @@ gNBs = pMax = 20; #initialUplinkBWP #genericParameters - initialULBWPlocationAndBandwidth = 28875; + initialULBWPlocationAndBandwidth = 13750; # RBstart=0, L=51 (275*(L-1))+RBstart # subcarrierSpacing # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 initialULBWPsubcarrierSpacing = 1; @@ -152,6 +149,18 @@ gNBs = ); + servingCellConfigDedicated = ({ + dl_bwp-Id_1 = 1; + dl_bwp1_locationAndBandwidth = 28875; # RBstart=0, L=106 (275*(L-1))+RBstart + dl_bwp1_subcarrierSpacing = 1; + firstActiveDownlinkBWP-Id = 1; + defaultDownlinkBWP-Id = 1; + ul_bwp-Id_1 = 1; + ul_bwp1_locationAndBandwidth = 28875; # RBstart=0, L=106 (275*(L-1))+RBstart + ul_bwp1_subcarrierSpacing = 1; + firstActiveUplinkBWP-Id = 1; + }); + # ------- SCTP definitions SCTP : From d9145418388c738679ff59cabf8f639a31ce7994 Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 27 Jun 2025 17:53:57 +0200 Subject: [PATCH 270/964] use CSET0 for common search space in dedicated BWP --- openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c | 26 ++++++++++++++------ 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c index 02f02089c4..eba1152cd0 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c @@ -1590,17 +1590,27 @@ static void config_downlinkBWP(NR_BWP_Downlink_t *bwp, bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->commonSearchSpaceList=calloc(1,sizeof(*bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->commonSearchSpaceList)); int searchspaceid = 5 + bwp->bwp_Id; - int rrc_num_agg_level_candidates[NUM_PDCCH_AGG_LEVELS]; - int num_cces = get_coreset_num_cces(coreset->frequencyDomainResources.buf, coreset->duration); - verify_agg_levels(num_cces, num_agg_level_candidates, coreset->controlResourceSetId, rrc_num_agg_level_candidates); - NR_SearchSpace_t *ss = rrc_searchspace_config(true, searchspaceid, coreset->controlResourceSetId, rrc_num_agg_level_candidates); + int agg_level_candidates[NUM_PDCCH_AGG_LEVELS]; + NR_SearchSpace_t *ss = NULL; + if (!is_SA) { + int num_cces = get_coreset_num_cces(coreset->frequencyDomainResources.buf, coreset->duration); + verify_agg_levels(num_cces, num_agg_level_candidates, coreset->controlResourceSetId, agg_level_candidates); + ss = rrc_searchspace_config(true, searchspaceid, coreset->controlResourceSetId, agg_level_candidates); + } else { + agg_level_candidates[PDCCH_AGG_LEVEL1] = NR_SearchSpace__nrofCandidates__aggregationLevel1_n0; + agg_level_candidates[PDCCH_AGG_LEVEL2] = NR_SearchSpace__nrofCandidates__aggregationLevel2_n0; + agg_level_candidates[PDCCH_AGG_LEVEL4] = NR_SearchSpace__nrofCandidates__aggregationLevel4_n1; + agg_level_candidates[PDCCH_AGG_LEVEL8] = NR_SearchSpace__nrofCandidates__aggregationLevel8_n0; + agg_level_candidates[PDCCH_AGG_LEVEL16] = NR_SearchSpace__nrofCandidates__aggregationLevel16_n0; + ss = rrc_searchspace_config(true, searchspaceid, 0, agg_level_candidates); + } asn1cSeqAdd(&bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->commonSearchSpaceList->list, ss); bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->searchSpaceSIB1=NULL; bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->searchSpaceOtherSystemInformation=NULL; bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->pagingSearchSpace=NULL; bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->ra_SearchSpace=NULL; - if(is_SA == false) { + if(!is_SA) { bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->ra_SearchSpace=calloc(1,sizeof(*bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->ra_SearchSpace)); *bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->ra_SearchSpace=ss->searchSpaceId; } @@ -1628,12 +1638,12 @@ static void config_downlinkBWP(NR_BWP_Downlink_t *bwp, // frees NR_ControlResourceSet_t *coreset2 = get_coreset_config(bwp->bwp_Id, curr_bwp, ssb_bitmap); asn1cSeqAdd(&bwp->bwp_Dedicated->pdcch_Config->choice.setup->controlResourceSetToAddModList->list, coreset2); - - num_cces = get_coreset_num_cces(coreset2->frequencyDomainResources.buf, coreset2->duration); + int rrc_num_agg_level_candidates[NUM_PDCCH_AGG_LEVELS]; + int num_cces = get_coreset_num_cces(coreset2->frequencyDomainResources.buf, coreset2->duration); verify_agg_levels(num_cces, num_agg_level_candidates, coreset2->controlResourceSetId, rrc_num_agg_level_candidates); searchspaceid = 10 + bwp->bwp_Id; - NR_SearchSpace_t *ss2 = rrc_searchspace_config(true, searchspaceid, coreset2->controlResourceSetId, rrc_num_agg_level_candidates); + NR_SearchSpace_t *ss2 = rrc_searchspace_config(true, searchspaceid, is_SA ? 0 : coreset2->controlResourceSetId, agg_level_candidates); asn1cSeqAdd(&bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list, ss2); searchspaceid = 20 + bwp->bwp_Id; From f57f6a8d4e44e0aceece71a15409df6f725aef43 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Tue, 1 Jul 2025 17:44:11 +0200 Subject: [PATCH 271/964] factorize code that initialize all 0xff simd vectors --- .../LTE_UE_TRANSPORT/dlsch_llr_computation.c | 31 +++++++++------ .../dlsch_llr_computation_avx2.c | 38 ++++++------------- .../NR_TRANSPORT/nr_ulsch_llr_computation.c | 20 +++------- openair1/PHY/TOOLS/tools_defs.h | 24 ++++++++++++ 4 files changed, 61 insertions(+), 52 deletions(-) diff --git a/openair1/PHY/LTE_UE_TRANSPORT/dlsch_llr_computation.c b/openair1/PHY/LTE_UE_TRANSPORT/dlsch_llr_computation.c index fd1b2a3e9a..bcab4cd8dd 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/dlsch_llr_computation.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/dlsch_llr_computation.c @@ -38,12 +38,9 @@ #include "transport_proto_ue.h" #include "PHY/sse_intrin.h" -//#define DEBUG_LLR_SIC - -const int16_t zeros[8] __attribute__((aligned(16))) = {0, 0, 0, 0, 0, 0, 0, 0}; -const int16_t ones[8] __attribute__((aligned(16))) = {0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff}; +// #define DEBUG_LLR_SIC //============================================================================================== -// Auxiliary Makros +// Auxiliary Makros // calculates psi_a = psi_r*a_r + psi_i*a_i #define prodsum_psi_a_epi16(psi_r, a_r, psi_i, a_i, psi_a) \ @@ -54,18 +51,18 @@ const int16_t ones[8] __attribute__((aligned(16))) = {0xffff, 0xffff, 0xffff, 0x simde__m128i psi_a = simde_mm_adds_epi16(tmp_result, tmp_result2); // calculate interference magnitude -#define interference_abs_epi16(psi, int_ch_mag, int_mag, c1, c2) \ - tmp_result = simde_mm_cmplt_epi16(psi, int_ch_mag); \ - tmp_result2 = simde_mm_xor_si128(tmp_result, (*(simde__m128i *)&ones[0])); \ - tmp_result = simde_mm_and_si128(tmp_result, c1); \ - tmp_result2 = simde_mm_and_si128(tmp_result2, c2); \ +#define interference_abs_epi16(psi, int_ch_mag, int_mag, c1, c2) \ + tmp_result = simde_mm_cmplt_epi16(psi, int_ch_mag); \ + tmp_result2 = simde_mm_xor_si128(tmp_result, ones); \ + tmp_result = simde_mm_and_si128(tmp_result, c1); \ + tmp_result2 = simde_mm_and_si128(tmp_result2, c2); \ simde__m128i int_mag = simde_mm_or_si128(tmp_result, tmp_result2); // calculate interference magnitude // tmp_result = ones in shorts corr. to interval 2<=x<=4, tmp_result2 interval < 2, tmp_result3 interval 46 #define interference_abs_64qam_epi16(psi, int_ch_mag, int_two_ch_mag, int_three_ch_mag, a, c1, c3, c5, c7) \ tmp_result = simde_mm_cmplt_epi16(psi, int_two_ch_mag); \ - tmp_result3 = simde_mm_xor_si128(tmp_result, (*(simde__m128i *)&ones[0])); \ + tmp_result3 = simde_mm_xor_si128(tmp_result, ones); \ tmp_result2 = simde_mm_cmplt_epi16(psi, int_ch_mag); \ tmp_result = simde_mm_xor_si128(tmp_result, tmp_result2); \ tmp_result4 = simde_mm_cmpgt_epi16(psi, int_three_ch_mag); \ @@ -1123,6 +1120,8 @@ void qpsk_qam16(int16_t *stream0_in, oai_mm_separate_real_imag_parts(&ch_mag_int, NULL, xmm2, xmm3); simde__m128i tmp_result, tmp_result2; + //generate a const of all ff in case the compiler doesn't optimize it inside the loop + const simde__m128i ones = allones128(); // calculate optimal interference amplitudes interference_abs_epi16(psi_r_p1_p1 , ch_mag_int, a_r_p1_p1 , ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); interference_abs_epi16(psi_i_p1_p1 , ch_mag_int, a_i_p1_p1 , ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); @@ -1351,6 +1350,8 @@ void qpsk_qam64(short *stream0_in, two_ch_mag_int_with_sigma2 = ch_mag_int; // *4 three_ch_mag_int_with_sigma2 = simde_mm_adds_epi16(ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2); // *6 simde__m128i tmp_result, tmp_result2, tmp_result3, tmp_result4; + //generate a const of all ff in case the compiler doesn't optimize it inside the loop + const simde__m128i ones = allones128(); interference_abs_64qam_epi16(psi_r_p1_p1, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_p1_p1, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, SEVEN_OVER_SQRT_2_42); interference_abs_64qam_epi16(psi_i_p1_p1, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_p1_p1, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, @@ -2081,6 +2082,8 @@ void qam16_qam16(short *stream0_in, simde__m128i y0_p_3_3 = simde_mm_adds_epi16(y0r_three_over_sqrt10, y0i_three_over_sqrt10); simde__m128i y0_m_3_3 = simde_mm_subs_epi16(y0r_three_over_sqrt10, y0i_three_over_sqrt10); simde__m128i tmp_result, tmp_result2; + //generate a const of all ff in case the compiler doesn't optimize it inside the loop + const simde__m128i ones = allones128(); // Compute optimal interfering symbol magnitude interference_abs_epi16(psi_r_p1_p1 ,ch_mag_int,a_r_p1_p1,ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); interference_abs_epi16(psi_i_p1_p1 ,ch_mag_int,a_i_p1_p1,ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); @@ -2597,6 +2600,8 @@ void qam16_qam64(int16_t *stream0_in, ch_mag_int_with_sigma2 = simde_mm_srai_epi16(ch_mag_int, 1); // *2 two_ch_mag_int_with_sigma2 = ch_mag_int; // *4 simde__m128i tmp_result, tmp_result2, tmp_result3, tmp_result4; + //generate a const of all ff in case the compiler doesn't optimize it inside the loop + const simde__m128i ones = allones128(); three_ch_mag_int_with_sigma2 = simde_mm_adds_epi16(ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2); // *6 interference_abs_64qam_epi16(psi_r_p1_p1 ,ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_p1_p1,ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42,FIVE_OVER_SQRT_2_42, @@ -4927,6 +4932,8 @@ void qam64_qam16(short *stream0_in, simde__m128i y0_m_7_5 = simde_mm_subs_epi16(y0r_seven_over_sqrt_21, y0i_five_over_sqrt_21); simde__m128i y0_m_7_7 = simde_mm_subs_epi16(y0r_seven_over_sqrt_21, y0i_seven_over_sqrt_21); simde__m128i tmp_result, tmp_result2; + //generate a const of all ff in case the compiler doesn't optimize it inside the loop + const simde__m128i ones = allones128(); interference_abs_epi16(psi_r_p7_p7, ch_mag_int, a_r_p7_p7, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); interference_abs_epi16(psi_r_p7_p5, ch_mag_int, a_r_p7_p5, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); interference_abs_epi16(psi_r_p7_p3, ch_mag_int, a_r_p7_p3, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); @@ -6425,6 +6432,8 @@ void qam64_qam64(short *stream0_in, two_ch_mag_int_with_sigma2 = ch_mag_int; // *4 three_ch_mag_int_with_sigma2 = simde_mm_adds_epi16(ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2); // *6 simde__m128i tmp_result, tmp_result2, tmp_result3, tmp_result4; + //generate a const of all ff in case the compiler doesn't optimize it inside the loop + const simde__m128i ones = allones128(); interference_abs_64qam_epi16(psi_r_p7_p7, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_p7_p7, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, SEVEN_OVER_SQRT_2_42); interference_abs_64qam_epi16(psi_r_p7_p5, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_p7_p5, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, diff --git a/openair1/PHY/LTE_UE_TRANSPORT/dlsch_llr_computation_avx2.c b/openair1/PHY/LTE_UE_TRANSPORT/dlsch_llr_computation_avx2.c index 0877b2ba7e..a4f641896b 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/dlsch_llr_computation_avx2.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/dlsch_llr_computation_avx2.c @@ -37,40 +37,21 @@ #if defined(__x86_64__) - static const int16_t ones256[16] __attribute__((aligned(32))) = {0xffff, - 0xffff, - 0xffff, - 0xffff, - 0xffff, - 0xffff, - 0xffff, - 0xffff, - 0xffff, - 0xffff, - 0xffff, - 0xffff, - 0xffff, - 0xffff, - 0xffff, - 0xffff}; - - - // Auxiliary Makros - + // Auxiliary Macros // calculate interference magnitude #define interference_abs_epi16(psi, int_ch_mag, int_mag, c1, c2) \ - tmp_result = simde_mm256_cmpgt_epi16(int_ch_mag, psi); \ - tmp_result2 = simde_mm256_xor_si256(tmp_result, (*(simde__m256i *)&ones256[0])); \ - tmp_result = simde_mm256_and_si256(tmp_result, c1); \ - tmp_result2 = simde_mm256_and_si256(tmp_result2, c2); \ - const simde__m256i int_mag = simde_mm256_or_si256(tmp_result, tmp_result2); + tmp_result = simde_mm256_cmpgt_epi16(int_ch_mag, psi); \ + tmp_result2 = simde_mm256_xor_si256(tmp_result, ff256); \ + tmp_result = simde_mm256_and_si256(tmp_result, c1); \ + tmp_result2 = simde_mm256_and_si256(tmp_result2, c2); \ + const simde__m256i int_mag = simde_mm256_or_si256(tmp_result, tmp_result2); // calculate interference magnitude // tmp_result = ones in shorts corr. to interval 2<=x<=4, tmp_result2 interval < 2, tmp_result3 interval 46 #define interference_abs_64qam_epi16(psi, int_ch_mag, int_two_ch_mag, int_three_ch_mag, a, c1, c3, c5, c7) \ tmp_result = simde_mm256_cmpgt_epi16(int_two_ch_mag, psi); \ - tmp_result3 = simde_mm256_xor_si256(tmp_result, (*(simde__m256i *)&ones256[0])); \ + tmp_result3 = simde_mm256_xor_si256(tmp_result, ff256); \ tmp_result2 = simde_mm256_cmpgt_epi16(int_ch_mag, psi); \ tmp_result = simde_mm256_xor_si256(tmp_result, tmp_result2); \ tmp_result4 = simde_mm256_cmpgt_epi16(psi, int_three_ch_mag); \ @@ -195,7 +176,8 @@ void qam64_qam16_avx2(short *stream0_in, int i,j; uint32_t len256 = (length)>>3; - + //generate a const of all ff in case the compiler doesn't optimize it inside the loop + const simde__m256i ff256 = allones256(); for (i=0; i>3; + //generate a const of all ff in case the compiler doesn't optimize it inside the loop + const simde__m256i ff256 = allones256(); for (i=0; i6 @@ -409,7 +404,7 @@ static inline simde__m128i interference_abs_64qam_epi16(simde__m128i psi, simde__m128i c7) { simde__m128i tmp_result = simde_mm_cmpgt_epi16(int_two_ch_mag, psi); - simde__m128i tmp_result3 = simde_mm_xor_si128(tmp_result, (*(simde__m128i *)&ones[0])); + simde__m128i tmp_result3 = simde_mm_xor_si128(tmp_result, allones128()); simde__m128i tmp_result2 = simde_mm_cmpgt_epi16(int_ch_mag, psi); tmp_result = simde_mm_xor_si128(tmp_result, tmp_result2); simde__m128i tmp_result4 = simde_mm_cmpgt_epi16(psi, int_three_ch_mag); @@ -437,7 +432,7 @@ static inline simde__m128i prodsum_psi_a_epi16(simde__m128i psi_r, simde__m128i static inline simde__m128i interference_abs_epi16(simde__m128i psi, simde__m128i int_ch_mag, simde__m128i c1, simde__m128i c2) { simde__m128i tmp_result = simde_mm_cmplt_epi16(psi, int_ch_mag); - simde__m128i tmp_result2 = simde_mm_xor_si128(tmp_result, (*(simde__m128i *)&ones[0])); + simde__m128i tmp_result2 = simde_mm_xor_si128(tmp_result,allones128()); tmp_result = simde_mm_and_si128(tmp_result, c1); tmp_result2 = simde_mm_and_si128(tmp_result2, c2); return simde_mm_or_si128(tmp_result, tmp_result2); @@ -492,9 +487,6 @@ static inline simde__m128i max_epi16(simde__m128i m0, simde__m128i m1, simde__m1 #else -static const int16_t ones256[16] __attribute__((aligned(32))) = {0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff}; - // calculate interference magnitude // tmp_result = ones in shorts corr. to interval 2<=x<=4, tmp_result2 interval < 2, tmp_result3 interval 46 @@ -508,7 +500,7 @@ static inline simde__m256i interference_abs_64qam_epi16_256(simde__m256i psi, simde__m256i c7) { simde__m256i tmp_result = simde_mm256_cmpgt_epi16(int_two_ch_mag, psi); - simde__m256i tmp_result3 = simde_mm256_xor_si256(tmp_result, (*(simde__m256i *)&ones256[0])); + simde__m256i tmp_result3 = simde_mm256_xor_si256(tmp_result, allones256()); simde__m256i tmp_result2 = simde_mm256_cmpgt_epi16(int_ch_mag, psi); tmp_result = simde_mm256_xor_si256(tmp_result, tmp_result2); simde__m256i tmp_result4 = simde_mm256_cmpgt_epi16(psi, int_three_ch_mag); @@ -536,7 +528,7 @@ static inline simde__m256i prodsum_psi_a_epi16_256(simde__m256i psi_r, simde__m2 static inline simde__m256i interference_abs_epi16_256(simde__m256i psi, simde__m256i int_ch_mag, simde__m256i c1, simde__m256i c2) { simde__m256i tmp_result = simde_mm256_cmpgt_epi16(int_ch_mag, psi); - simde__m256i tmp_result2 = simde_mm256_xor_si256(tmp_result, (*(simde__m256i *)&ones256[0])); + simde__m256i tmp_result2 = simde_mm256_xor_si256(tmp_result, allones256()); tmp_result = simde_mm256_and_si256(tmp_result, c1); tmp_result2 = simde_mm256_and_si256(tmp_result2, c2); return simde_mm256_or_si256(tmp_result, tmp_result2); diff --git a/openair1/PHY/TOOLS/tools_defs.h b/openair1/PHY/TOOLS/tools_defs.h index 64e5061476..7d60e19bae 100644 --- a/openair1/PHY/TOOLS/tools_defs.h +++ b/openair1/PHY/TOOLS/tools_defs.h @@ -532,6 +532,20 @@ static inline void multadd_cpx_vector(const c16_t *x1, const c16_t *x2, c16_t *y } } +static const int16_t ones_epi16[16] __attribute__((aligned(32))) = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; +static inline simde__m256i protected_abs256(const simde__m256i in) +{ + const simde__m256i no32768 = + simde_mm256_adds_epi16(simde_mm256_subs_epi16(in, *(simde__m256i *)ones_epi16), *(simde__m256i *)ones_epi16); + return simde_mm256_abs_epi16(no32768); +} + +static inline simde__m128i protected_abs128(const simde__m128i in) +{ + const simde__m128i no32768 = simde_mm_adds_epi16(simde_mm_subs_epi16(in, *(simde__m128i *)ones_epi16), *(simde__m128i *)ones_epi16); + return simde_mm_abs_epi16(no32768); +} + // lte_dfts.c void init_fft(uint16_t size, uint8_t logsize, @@ -919,6 +933,16 @@ c32_t dot_product(const c16_t *x, void oai_mm_separate_real_imag_parts(simde__m128i *out_re, simde__m128i *out_im, simde__m128i in0, simde__m128i in1); void oai_mm256_separate_real_imag_parts(simde__m256i *out_re, simde__m256i *out_im, simde__m256i in0, simde__m256i in1); +// generates vpcmpeqd ymm0, ymm0, ymm0 +static inline simde__m256i allones256(void) +{ + return simde_mm256_set1_epi64x(-1); +} +static inline simde__m128i allones128(void) +{ + return simde_mm_set1_epi32(-1); +} + void InitSinLUT(void); // fast calculation of e^{i*2*pi*phase} From 3264eca6dbbca3475b49265d692239390fcc1259 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Tue, 1 Jul 2025 17:46:37 +0200 Subject: [PATCH 272/964] enhance llr unitary tests --- openair1/PHY/NR_TRANSPORT/tests/test_llr.cpp | 95 +++++++++----------- openair1/PHY/TOOLS/phy_test_tools.hpp | 2 +- 2 files changed, 44 insertions(+), 53 deletions(-) diff --git a/openair1/PHY/NR_TRANSPORT/tests/test_llr.cpp b/openair1/PHY/NR_TRANSPORT/tests/test_llr.cpp index bd0c95d2ae..f07aa8e552 100644 --- a/openair1/PHY/NR_TRANSPORT/tests/test_llr.cpp +++ b/openair1/PHY/NR_TRANSPORT/tests/test_llr.cpp @@ -48,12 +48,11 @@ void exit_function(const char *file, const char *function, const int line, const #include "openair1/PHY/TOOLS/phy_test_tools.hpp" #include -int16_t saturating_sub(int16_t a, int16_t b) +int16_t saturating_sub(int a, int b) { - int32_t result = (int32_t)a - (int32_t)b; - - if (result < INT16_MIN) { - return INT16_MIN; + int result = a - abs(b); + if (result < -INT16_MAX) { + return -INT16_MAX; } else if (result > INT16_MAX) { return INT16_MAX; } else { @@ -71,8 +70,8 @@ void nr_16qam_llr_ref(c16_t *rxdataF_comp, int32_t *ch_mag, int16_t *llr, uint32 int16_t mag_imag = ch_mag_i16[2 * i + 1]; llr[4 * i] = real; llr[4 * i + 1] = imag; - llr[4 * i + 2] = saturating_sub(mag_real, std::abs(real)); - llr[4 * i + 3] = saturating_sub(mag_imag, std::abs(imag)); + llr[4 * i + 2] = saturating_sub(mag_real, real); + llr[4 * i + 3] = saturating_sub(mag_imag, imag); } } @@ -91,12 +90,12 @@ void nr_64qam_llr_ref(c16_t *rxdataF_comp, int16_t mag_imag = ch_mag_i16[2 * i + 1]; llr[6 * i] = real; llr[6 * i + 1] = imag; - llr[6 * i + 2] = saturating_sub(mag_real, std::abs(real)); - llr[6 * i + 3] = saturating_sub(mag_imag, std::abs(imag)); + llr[6 * i + 2] = saturating_sub(mag_real, real); + llr[6 * i + 3] = saturating_sub(mag_imag, imag); int16_t mag_realb = ch_magb_i16[2 * i]; int16_t mag_imagb = ch_magb_i16[2 * i + 1]; - llr[6 * i + 4] = saturating_sub(mag_realb, std::abs(llr[6 * i + 2])); - llr[6 * i + 5] = saturating_sub(mag_imagb, std::abs(llr[6 * i + 3])); + llr[6 * i + 4] = saturating_sub(mag_realb, llr[6 * i + 2]); + llr[6 * i + 5] = saturating_sub(mag_imagb, llr[6 * i + 3]); } } @@ -117,16 +116,16 @@ void nr_256qam_llr_ref(c16_t *rxdataF_comp, int16_t mag_imag = ch_mag_i16[2 * i + 1]; llr[8 * i] = real; llr[8 * i + 1] = imag; - llr[8 * i + 2] = saturating_sub(mag_real, std::abs(real)); - llr[8 * i + 3] = saturating_sub(mag_imag, std::abs(imag)); + llr[8 * i + 2] = saturating_sub(mag_real, real); + llr[8 * i + 3] = saturating_sub(mag_imag, imag); int16_t magb_real = ch_magb_i16[2 * i]; int16_t magb_imag = ch_magb_i16[2 * i + 1]; - llr[8 * i + 4] = saturating_sub(magb_real, std::abs(llr[8 * i + 2])); - llr[8 * i + 5] = saturating_sub(magb_imag, std::abs(llr[8 * i + 3])); + llr[8 * i + 4] = saturating_sub(magb_real, llr[8 * i + 2]); + llr[8 * i + 5] = saturating_sub(magb_imag, llr[8 * i + 3]); int16_t magc_real = ch_magc_i16[2 * i]; int16_t magc_imag = ch_magc_i16[2 * i + 1]; - llr[8 * i + 6] = saturating_sub(magc_real, std::abs(llr[8 * i + 4])); - llr[8 * i + 7] = saturating_sub(magc_imag, std::abs(llr[8 * i + 5])); + llr[8 * i + 6] = saturating_sub(magc_real, llr[8 * i + 4]); + llr[8 * i + 7] = saturating_sub(magc_imag, llr[8 * i + 5]); } } @@ -136,23 +135,21 @@ void test_function_16_qam(AlignedVector512 nb_res) uint32_t nb_re = nb_res[i]; auto rf_data = generate_random_c16(nb_re); auto magnitude_data = generate_random_uint16(nb_re * 2); - AlignedVector512 llr_ref; - llr_ref.resize(nb_re); + AlignedVector512 llr_ref; + llr_ref.resize(nb_re * 4); std::fill(llr_ref.begin(), llr_ref.end(), 0); nr_16qam_llr_ref((c16_t *)rf_data.data(), (int32_t *)magnitude_data.data(), (int16_t *)llr_ref.data(), nb_re); - AlignedVector512 llr; - llr.resize(nb_re); + AlignedVector512 llr; + llr.resize(nb_re * 4); std::fill(llr.begin(), llr.end(), 0); nr_16qam_llr((int32_t *)rf_data.data(), (int32_t *)magnitude_data.data(), (int16_t *)llr.data(), nb_re); int num_errors = 0; - for (auto i = 0U; i < nb_re; i++) { - EXPECT_EQ(llr_ref[i], llr[i]) - << "Mismatch 16qam REF " << std::hex << llr_ref[i] << " != DUT " << llr[i] << " at " << std::dec << i; - if (llr_ref[i] != llr[i]) { - num_errors++; - } + for (auto i = 0U; i < llr_ref.size(); i++) { + EXPECT_LE(llr_ref[i] - llr[i] ? (llr_ref[i] - llr[i]) / (float)llr[i] : 0, 0.001) + << "Mismatch 16qam REF " << std::hex << llr_ref[i] << " != DUT " << llr[i] << " at " << std::dec << i + << "total err: " << ++num_errors; } EXPECT_EQ(num_errors, 0) << " Errors during testing 16qam llr " << num_errors << " nb res " << nb_re; } @@ -165,8 +162,8 @@ void test_function_64_qam(AlignedVector512 nb_res) auto rf_data = generate_random_c16(nb_re); auto magnitude_data = generate_random_uint16(nb_re * 2); auto magnitude_b_data = generate_random_uint16(nb_re * 2); - AlignedVector512 llr_ref; - llr_ref.resize(nb_re * 3); + AlignedVector512 llr_ref; + llr_ref.resize(nb_re * 6); std::fill(llr_ref.begin(), llr_ref.end(), 0); nr_64qam_llr_ref((c16_t *)rf_data.data(), (int32_t *)magnitude_data.data(), @@ -174,8 +171,8 @@ void test_function_64_qam(AlignedVector512 nb_res) (int16_t *)llr_ref.data(), nb_re); - AlignedVector512 llr; - llr.resize(nb_re * 3); + AlignedVector512 llr; + llr.resize(nb_re * 6); std::fill(llr.begin(), llr.end(), 0); nr_64qam_llr((int32_t *)rf_data.data(), (int32_t *)magnitude_data.data(), @@ -184,12 +181,10 @@ void test_function_64_qam(AlignedVector512 nb_res) nb_re); int num_errors = 0; - for (auto i = 0U; i < nb_re * 3; i++) { - EXPECT_EQ(llr_ref[i], llr[i]) - << "Mismatch 64qam REF " << std::hex << llr_ref[i] << " != DUT " << llr[i] << " at " << std::dec << i; - if (llr_ref[i] != llr[i]) { - num_errors++; - } + for (auto i = 0U; i < llr.size(); i++) { + EXPECT_LE(llr_ref[i] - llr[i] ? (llr_ref[i] - llr[i]) / (float)llr[i] : 0, 0.001) + << "Mismatch 64qam REF " << std::hex << llr_ref[i] << " != DUT " << llr[i] << " at " << std::dec << i + << "total err: " << ++num_errors; } EXPECT_EQ(num_errors, 0) << " Errors during testing 64qam llr " << num_errors << " nb res " << nb_re; } @@ -203,8 +198,8 @@ void test_function_256_qam(AlignedVector512 nb_res) auto magnitude_data = generate_random_uint16(nb_re * 2); auto magnitude_b_data = generate_random_uint16(nb_re * 2); auto magnitude_c_data = generate_random_uint16(nb_re * 2); - AlignedVector512 llr_ref; - llr_ref.resize(nb_re * 4); + AlignedVector512 llr_ref; + llr_ref.resize(nb_re * 8); std::fill(llr_ref.begin(), llr_ref.end(), 0); nr_256qam_llr_ref((c16_t *)rf_data.data(), (int32_t *)magnitude_data.data(), @@ -213,8 +208,8 @@ void test_function_256_qam(AlignedVector512 nb_res) (int16_t *)llr_ref.data(), nb_re); - AlignedVector512 llr; - llr.resize(nb_re * 4); + AlignedVector512 llr; + llr.resize(nb_re * 8); std::fill(llr.begin(), llr.end(), 0); nr_256qam_llr((int32_t *)rf_data.data(), (int32_t *)magnitude_data.data(), @@ -224,12 +219,10 @@ void test_function_256_qam(AlignedVector512 nb_res) nb_re); int num_errors = 0; - for (auto i = 0U; i < nb_re * 4; i++) { - EXPECT_EQ(llr_ref[i], llr[i]) - << "Mismatch 256qam REF " << std::hex << llr_ref[i] << " != DUT " << llr[i] << " at " << std::dec << i; - if (llr_ref[i] != llr[i]) { - num_errors++; - } + for (auto i = 0U; i < llr.size(); i++) { + EXPECT_LE(llr_ref[i] - llr[i] ? (llr_ref[i] - llr[i]) / (float)llr[i] : 0, 0.001) + << "Mismatch 256qam REF " << std::hex << llr_ref[i] << " != DUT " << llr[i] << " at " << std::dec << i + << "total err: " << ++num_errors; } EXPECT_EQ(num_errors, 0) << " Errors during testing 256qam llr " << num_errors << " nb res " << nb_re; } @@ -401,11 +394,9 @@ TEST(test_llr, check_2_res_256_qam) int num_errors = 0; for (auto i = 0U; i < 2 * 8; i++) { - EXPECT_EQ(llr_ref[i], llr[i]) - << "Mismatch 256qam REF " << std::hex << llr_ref[i] << " != DUT " << llr[i] << " at " << std::dec << i; - if (llr_ref[i] != llr[i]) { - num_errors++; - } + EXPECT_LE(llr_ref[i] - llr[i] ? (llr_ref[i] - llr[i]) / (float)llr[i] : 0, 0.001) + << "Mismatch 256qam REF " << std::hex << llr_ref[i] << " != DUT " << llr[i] << " at " << std::dec << i + << "total err: " << ++num_errors; } EXPECT_EQ(num_errors, 0) << " Errors during testing 256qam llr " << num_errors << " nb res " << 2; } diff --git a/openair1/PHY/TOOLS/phy_test_tools.hpp b/openair1/PHY/TOOLS/phy_test_tools.hpp index dcaa192dd4..bf9760cde6 100644 --- a/openair1/PHY/TOOLS/phy_test_tools.hpp +++ b/openair1/PHY/TOOLS/phy_test_tools.hpp @@ -81,7 +81,7 @@ AlignedVector512 generate_random_c16(size_t num) { std::random_device rd; std::mt19937 rng(rd()); - std::uniform_int_distribution dist(INT16_MIN, INT16_MAX); + std::uniform_int_distribution dist(-INT16_MAX, INT16_MAX); AlignedVector512 vec; vec.resize(num); auto gen = [&]() { return (c16_t){dist(rng), dist(rng)}; }; From 8dd2119d4ea0d18c3dfeb32c34191748e0bfa599 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Tue, 1 Jul 2025 18:31:02 +0200 Subject: [PATCH 273/964] bad type multi casts with wrong meaning like cast to ** a array of 2D (wrong in C) --- .../PHY/NR_ESTIMATION/nr_freq_equalization.c | 14 +- openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h | 6 +- .../PHY/NR_TRANSPORT/nr_transport_proto.h | 69 +------ .../PHY/NR_TRANSPORT/nr_ulsch_demodulation.c | 125 ++++++------- .../NR_TRANSPORT/nr_ulsch_llr_computation.c | 6 +- .../NR_UE_TRANSPORT/nr_dlsch_demodulation.c | 60 +++--- .../PHY/nr_phy_common/inc/nr_phy_common.h | 6 +- .../PHY/nr_phy_common/src/nr_phy_common.c | 172 +++++++----------- 8 files changed, 181 insertions(+), 277 deletions(-) diff --git a/openair1/PHY/NR_ESTIMATION/nr_freq_equalization.c b/openair1/PHY/NR_ESTIMATION/nr_freq_equalization.c index c593c04cc5..8f12f100c2 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_freq_equalization.c +++ b/openair1/PHY/NR_ESTIMATION/nr_freq_equalization.c @@ -34,13 +34,13 @@ void nr_init_fde() nr_inv_ch[i] = simde_mm_set1_epi16(4096/i); } -void nr_freq_equalization (NR_DL_FRAME_PARMS *frame_parms, - int32_t *rxdataF_comp, - int32_t *ul_ch_mag, - int32_t *ul_ch_magb, - uint8_t symbol, - uint16_t Msc_RS, - uint8_t Qm) +void nr_freq_equalization(NR_DL_FRAME_PARMS *frame_parms, + c16_t *rxdataF_comp, + c16_t *ul_ch_mag, + c16_t *ul_ch_magb, + uint8_t symbol, + uint16_t Msc_RS, + uint8_t Qm) { simde__m128i *rxdataF_comp128 = (simde__m128i *)rxdataF_comp; simde__m128i *ul_ch_mag128 = (simde__m128i *)ul_ch_mag; diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h index 483e1ea090..768b75ae62 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h @@ -90,9 +90,9 @@ int nr_srs_channel_estimation( int8_t *snr); void nr_freq_equalization(NR_DL_FRAME_PARMS *frame_parms, - int *rxdataF_comp, - int *ul_ch_mag, - int *ul_ch_mag_b, + c16_t *rxdataF_comp, + c16_t *ul_ch_mag, + c16_t *ul_ch_mag_b, unsigned char symbol, unsigned short Msc_RS, unsigned char Qm); diff --git a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h index db49237a9e..1aabf118ef 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h +++ b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h @@ -159,63 +159,6 @@ void nr_ulsch_qam64_qam64(c16_t *stream0_in, c16_t *rho01, uint32_t length); -/** \brief This function generates log-likelihood ratios (decoder input) for single-stream QPSK received waveforms. - @param rxdataF_comp Compensated channel output - @param ulsch_llr llr output - @param nb_re number of REs for this allocation - @param symbol OFDM symbol index in sub-frame -*/ -void nr_ulsch_qpsk_llr(int32_t *rxdataF_comp, - int16_t *ulsch_llr, - uint32_t nb_re, - uint8_t symbol); - - -/** \brief This function generates log-likelihood ratios (decoder input) for single-stream 16 QAM received waveforms. - @param rxdataF_comp Compensated channel output - @param ul_ch_mag uplink channel magnitude multiplied by the 1st amplitude threshold in QAM 16 - @param ulsch_llr llr output - @param nb_re number of RBs for this allocation - @param symbol OFDM symbol index in sub-frame -*/ -void nr_ulsch_16qam_llr(int32_t *rxdataF_comp, - int32_t **ul_ch_mag, - int16_t *ulsch_llr, - uint32_t nb_re, - uint8_t symbol); - -/** \brief This function generates log-likelihood ratios (decoder input) for single-stream 64 QAM received waveforms. - @param rxdataF_comp Compensated channel output - @param ul_ch_mag uplink channel magnitude multiplied by the 1st amplitude threshold in QAM 64 - @param ul_ch_magb uplink channel magnitude multiplied by the 2bd amplitude threshold in QAM 64 - @param ulsch_llr llr output - @param nb_re number of REs for this allocation - @param symbol OFDM symbol index in sub-frame -*/ -void nr_ulsch_64qam_llr(int32_t *rxdataF_comp, - int32_t **ul_ch_mag, - int32_t **ul_ch_magb, - int16_t *ulsch_llr, - uint32_t nb_re, - uint8_t symbol); - -/** \brief This function generates log-likelihood ratios (decoder input) for single-stream 256 QAM received waveforms. - @param rxdataF_comp Compensated channel output - @param ul_ch_mag uplink channel magnitude multiplied by the 1st amplitude threshold in QAM 256 - @param ul_ch_magb uplink channel magnitude multiplied by the 2bd amplitude threshold in QAM 256 - @param ul_ch_magc uplink channel magnitude multiplied by the 3rd amplitude threshold in QAM 256 - @param ulsch_llr llr output - @param nb_re number of REs for this allocation - @param symbol OFDM symbol index in sub-frame -*/ -void nr_ulsch_256qam_llr(int32_t *rxdataF_comp, - int32_t **ul_ch_mag, - int32_t **ul_ch_magb, - int32_t **ul_ch_magc, - int16_t *ulsch_llr, - uint32_t nb_re, - uint8_t symbol); - /** \brief This function computes the log-likelihood ratios for 4, 16, and 64 QAM @param rxdataF_comp Compensated channel output @param ul_ch_mag uplink channel magnitude multiplied by the 1st amplitude threshold in QAM 64 @@ -226,13 +169,13 @@ void nr_ulsch_256qam_llr(int32_t *rxdataF_comp, @param mod_order modulation order */ void nr_ulsch_compute_llr(int32_t *rxdataF_comp, - int32_t *ul_ch_mag, - int32_t *ul_ch_magb, - int32_t *ul_ch_magc, - int16_t *ulsch_llr, + c16_t *ul_ch_mag, + c16_t *ul_ch_magb, + c16_t *ul_ch_magc, + int16_t *ulsch_llr, uint32_t nb_re, - uint8_t symbol, - uint8_t mod_order); + uint8_t symbol, + uint8_t mod_order); void reset_active_stats(PHY_VARS_gNB *gNB, int frame); void reset_active_ulsch(PHY_VARS_gNB *gNB, int frame); diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c index 1729c8c8c4..5b8b9c4291 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c @@ -225,22 +225,22 @@ static void nr_ulsch_channel_level(int size_est, } -static void nr_ulsch_channel_compensation(c16_t *rxFext, - c16_t *chFext, - c16_t *ul_ch_maga, - c16_t *ul_ch_magb, - c16_t *ul_ch_magc, +static void nr_ulsch_channel_compensation(uint32_t buffer_length, + int nb_rx_ant, + c16_t rxFext[][buffer_length], + c16_t chFext[][nb_rx_ant][buffer_length], + c16_t ul_ch_maga[][buffer_length], + c16_t ul_ch_magb[][buffer_length], + c16_t ul_ch_magc[][buffer_length], int32_t **rxComp, - c16_t *rho, - NR_DL_FRAME_PARMS *frame_parms, - nfapi_nr_pusch_pdu_t* rel15_ul, + int nb_layers, + c16_t rho[][nb_layers][buffer_length], + nfapi_nr_pusch_pdu_t *rel15_ul, uint32_t symbol, - uint32_t buffer_length, uint32_t output_shift) { int mod_order = rel15_ul->qam_mod_order; int nrOfLayers = rel15_ul->nrOfLayers; - int nb_rx_ant = frame_parms->nb_antennas_rx; simde__m256i QAM_ampa_256 = simde_mm256_setzero_si256(); simde__m256i QAM_ampb_256 = simde_mm256_setzero_si256(); @@ -263,13 +263,13 @@ static void nr_ulsch_channel_compensation(c16_t *rxFext, } for (int aatx = 0; aatx < nrOfLayers; aatx++) { - simde__m256i *rxComp_256 = (simde__m256i*)&rxComp[aatx * nb_rx_ant][symbol * buffer_length]; - simde__m256i *rxF_ch_maga_256 = (simde__m256i*)&ul_ch_maga[aatx * buffer_length]; - simde__m256i *rxF_ch_magb_256 = (simde__m256i*)&ul_ch_magb[aatx * buffer_length]; - simde__m256i *rxF_ch_magc_256 = (simde__m256i*)&ul_ch_magc[aatx * buffer_length]; + simde__m256i *rxComp_256 = (simde__m256i *)&rxComp[aatx * nb_rx_ant][symbol * buffer_length]; + simde__m256i *rxF_ch_maga_256 = (simde__m256i *)ul_ch_maga[aatx]; + simde__m256i *rxF_ch_magb_256 = (simde__m256i *)ul_ch_magb[aatx]; + simde__m256i *rxF_ch_magc_256 = (simde__m256i *)ul_ch_magc[aatx]; for (int aarx = 0; aarx < nb_rx_ant; aarx++) { - simde__m256i *rxF_256 = (simde__m256i*) &rxFext[aarx * buffer_length]; - simde__m256i *chF_256 = (simde__m256i*) &chFext[(aatx * nb_rx_ant + aarx) * buffer_length]; + simde__m256i *rxF_256 = (simde__m256i *)rxFext[aarx]; + simde__m256i *chF_256 = (simde__m256i *)chFext[aatx][aarx]; for (int i = 0; i < buffer_length >> 3; i++) { @@ -292,11 +292,11 @@ static void nr_ulsch_channel_compensation(c16_t *rxFext, rxF_ch_magc_256[i] = simde_mm256_add_epi16(rxF_ch_magc_256[i], simde_mm256_mulhrs_epi16(mag, QAM_ampc_256)); } } - if (rho != NULL) { + if (nb_layers > 1) { for (int atx = 0; atx < nrOfLayers; atx++) { - simde__m256i *rho_256 = (simde__m256i * )&rho[(aatx * nrOfLayers + atx) * buffer_length]; - simde__m256i *chF_256 = (simde__m256i *)&chFext[(aatx * nb_rx_ant + aarx) * buffer_length]; - simde__m256i *chF2_256 = (simde__m256i *)&chFext[ (atx * nb_rx_ant + aarx) * buffer_length]; + simde__m256i *rho_256 = (simde__m256i *)rho[aatx][atx]; + simde__m256i *chF_256 = (simde__m256i *)chFext[aatx][aarx]; + simde__m256i *chF2_256 = (simde__m256i *)chFext[atx][aarx]; for (int i = 0; i < buffer_length >> 3; i++) { rho_256[i] = simde_mm256_adds_epi16(rho_256[i], oai_mm256_cpx_mult_conj(chF_256[i], chF2_256[i], output_shift)); } @@ -523,25 +523,20 @@ static void nr_ulsch_construct_HhH_elements(c16_t *conjch00_ch00, } // MMSE Rx function: nr_ulsch_mmse_2layers() -static uint8_t nr_ulsch_mmse_2layers(NR_DL_FRAME_PARMS *frame_parms, - int **rxdataF_comp, - int **ul_ch_mag, - int **ul_ch_magb, - int **ul_ch_magc, - int nb_layer, - int nb_rx_ant, +static uint8_t nr_ulsch_mmse_2layers(int **rxdataF_comp, uint32_t buffer_length, - c16_t ul_ch_estimates_ext[nb_layer][nb_rx_ant][buffer_length], + int nb_rx_ant, + c16_t ul_ch_mag[][buffer_length], + c16_t ul_ch_magb[][buffer_length], + c16_t ul_ch_magc[][buffer_length], + c16_t ul_ch_estimates_ext[][nb_rx_ant][buffer_length], unsigned short nb_rb, - unsigned char n_rx, unsigned char mod_order, int shift, unsigned char symbol, int length, uint32_t noise_var) { - c16_t *ch00, *ch01, *ch10, *ch11; - c16_t *ch20, *ch30, *ch21, *ch31; uint32_t nb_rb_0 = length/12 + ((length%12)?1:0); /* we need at least alignment to 16 bytes, let's put 32 to be sure @@ -570,7 +565,9 @@ static uint8_t nr_ulsch_mmse_2layers(NR_DL_FRAME_PARMS *frame_parms, c16_t af_mf_11[12 * nb_rb] __attribute__((aligned(32))); uint32_t determ_fin[12*nb_rb] __attribute__((aligned(32))); - switch (n_rx) { + c16_t *ch00, *ch01, *ch10, *ch11; + c16_t *ch20, *ch30, *ch21, *ch31; + switch (nb_rx_ant) { case 2:// ch00 = ul_ch_estimates_ext[0][0]; ch01 = ul_ch_estimates_ext[1][0]; @@ -606,7 +603,7 @@ static uint8_t nr_ulsch_mmse_2layers(NR_DL_FRAME_PARMS *frame_parms, * */ - if (n_rx>=2){ + if (nb_rx_ant >= 2) { // (1/2^log2_maxh)*conj_H_00xH_00: (1/(64*2))conjH_00*H_00*2^15 nr_ulsch_conjch0_mult_ch1(ch00, ch00, @@ -656,7 +653,7 @@ static uint8_t nr_ulsch_mmse_2layers(NR_DL_FRAME_PARMS *frame_parms, nb_rb_0, shift); } - if (n_rx==4){ + if (nb_rx_ant == 4) { // (1/2^log2_maxh)*conj_H_20xH_20: (1/(64*2*16))conjH_20*H_20*2^15 nr_ulsch_conjch0_mult_ch1(ch20, ch20, @@ -732,7 +729,7 @@ static uint8_t nr_ulsch_mmse_2layers(NR_DL_FRAME_PARMS *frame_parms, nb_rb_0, symbol); } - if (n_rx==2){ + if (nb_rx_ant == 2) { nr_ulsch_construct_HhH_elements(conjch00_ch00, conjch01_ch01, conjch11_ch11, @@ -805,7 +802,7 @@ static uint8_t nr_ulsch_mmse_2layers(NR_DL_FRAME_PARMS *frame_parms, simde__m128i *after_mf_d_128 = (simde__m128i *)af_mf_11; simde__m128i *rxdataF_comp128_0 = (simde__m128i *)&rxdataF_comp[0][symbol * buffer_length]; - simde__m128i *rxdataF_comp128_1 = (simde__m128i *)&rxdataF_comp[n_rx][symbol * buffer_length]; + simde__m128i *rxdataF_comp128_1 = (simde__m128i *)&rxdataF_comp[nb_rx_ant][symbol * buffer_length]; if (mod_order > 2) { if (mod_order == 4) { @@ -821,12 +818,12 @@ static uint8_t nr_ulsch_mmse_2layers(NR_DL_FRAME_PARMS *frame_parms, QAM_amp128b = simde_mm_set1_epi16(QAM256_n2); QAM_amp128c = simde_mm_set1_epi16(QAM256_n3); } - ul_ch_mag128_0 = (simde__m128i *) &ul_ch_mag[0]; + ul_ch_mag128_0 = (simde__m128i *)&ul_ch_mag[0]; ul_ch_mag128b_0 = (simde__m128i *)&ul_ch_magb[0]; ul_ch_mag128c_0 = (simde__m128i *)&ul_ch_magc[0]; - ul_ch_mag128_1 = (simde__m128i *) &((int *)ul_ch_mag)[1 * buffer_length]; - ul_ch_mag128b_1 = (simde__m128i *)&((int *)ul_ch_magb)[1 * buffer_length]; - ul_ch_mag128c_1 = (simde__m128i *)&((int *)ul_ch_magc)[1 * buffer_length]; + ul_ch_mag128_1 = (simde__m128i *)&ul_ch_mag[1]; + ul_ch_mag128b_1 = (simde__m128i *)&ul_ch_magb[1]; + ul_ch_mag128c_1 = (simde__m128i *)&ul_ch_magc[1]; } for (int rb = 0; rb < 3 * nb_rb_0; rb++) { @@ -973,28 +970,29 @@ static void inner_rx(PHY_VARS_gNB *gNB, for (int i = 0; i < nb_layer; i++) memset(&pusch_vars->rxdataF_comp[i*nb_rx_ant][symbol * buffer_length], 0, sizeof(int32_t) * buffer_length); - nr_ulsch_channel_compensation((c16_t*)rxFext, - (c16_t*)chFext, - (c16_t*)rxF_ch_maga, - (c16_t*)rxF_ch_magb, - (c16_t*)rxF_ch_magc, + nr_ulsch_channel_compensation(buffer_length, + nb_rx_ant, + rxFext, + chFext, + rxF_ch_maga, + rxF_ch_magb, + rxF_ch_magc, pusch_vars->rxdataF_comp, - (nb_layer == 1) ? NULL : (c16_t*)rho, - frame_parms, + nb_layer, + rho, rel15_ul, symbol, - buffer_length, output_shift); if (nb_layer == 1 && rel15_ul->transform_precoding == transformPrecoder_enabled && rel15_ul->qam_mod_order <= 6) { if (rel15_ul->qam_mod_order > 2) nr_freq_equalization(frame_parms, - &pusch_vars->rxdataF_comp[0][symbol * buffer_length], - (int *)rxF_ch_maga, - (int *)rxF_ch_magb, - symbol, - pusch_vars->ul_valid_re_per_slot[symbol], - rel15_ul->qam_mod_order); + (c16_t *)&pusch_vars->rxdataF_comp[0][symbol * buffer_length], + rxF_ch_maga[0], + rxF_ch_magb[0], + symbol, + pusch_vars->ul_valid_re_per_slot[symbol], + rel15_ul->qam_mod_order); nr_idft(&pusch_vars->rxdataF_comp[0][symbol * buffer_length], pusch_vars->ul_valid_re_per_slot[symbol]); } if (rel15_ul->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) { @@ -1024,17 +1022,14 @@ static void inner_rx(PHY_VARS_gNB *gNB, rel15_ul->qam_mod_order); } else { - nr_ulsch_mmse_2layers(frame_parms, - (int32_t **)pusch_vars->rxdataF_comp, - (int **)rxF_ch_maga, - (int **)rxF_ch_magb, - (int **)rxF_ch_magc, - nb_layer, - nb_rx_ant, + nr_ulsch_mmse_2layers((int32_t **)pusch_vars->rxdataF_comp, buffer_length, + nb_rx_ant, + rxF_ch_maga, + rxF_ch_magb, + rxF_ch_magc, chFext, rel15_ul->rb_size, - frame_parms->nb_antennas_rx, rel15_ul->qam_mod_order, pusch_vars->log2_maxh, symbol, @@ -1045,9 +1040,9 @@ static void inner_rx(PHY_VARS_gNB *gNB, if (nb_layer != 2 || rel15_ul->qam_mod_order > 6) for (int aatx = 0; aatx < nb_layer; aatx++) nr_ulsch_compute_llr((int32_t *)&pusch_vars->rxdataF_comp[aatx * nb_rx_ant][symbol * buffer_length], - (int32_t *)rxF_ch_maga[aatx], - (int32_t *)rxF_ch_magb[aatx], - (int32_t *)rxF_ch_magc[aatx], + rxF_ch_maga[aatx], + rxF_ch_magb[aatx], + rxF_ch_magc[aatx], llr[aatx], pusch_vars->ul_valid_re_per_slot[symbol], symbol, diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c index a118cf629e..3f4660744d 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c @@ -39,9 +39,9 @@ #endif void nr_ulsch_compute_llr(int32_t *rxdataF_comp, - int32_t *ul_ch_mag, - int32_t *ul_ch_magb, - int32_t *ul_ch_magc, + c16_t *ul_ch_mag, + c16_t *ul_ch_magb, + c16_t *ul_ch_magc, int16_t *ulsch_llr, uint32_t nb_re, uint8_t symbol, diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c index 37c8382ec5..9289c67919 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c @@ -82,9 +82,9 @@ static void nr_dlsch_mmse(uint32_t rx_size_symbol, unsigned char n_rx, unsigned char n_tx, // number of layer int32_t rxdataF_comp[][n_rx][rx_size_symbol * NR_SYMBOLS_PER_SLOT], - int32_t dl_ch_mag[][n_rx][rx_size_symbol], - int32_t dl_ch_magb[][n_rx][rx_size_symbol], - int32_t dl_ch_magr[][n_rx][rx_size_symbol], + c16_t dl_ch_mag[][n_rx][rx_size_symbol], + c16_t dl_ch_magb[][n_rx][rx_size_symbol], + c16_t dl_ch_magr[][n_rx][rx_size_symbol], int32_t dl_ch_estimates_ext[][rx_size_symbol], unsigned short nb_rb, unsigned char mod_order, @@ -109,9 +109,9 @@ static void nr_dlsch_llr(uint32_t rx_size_symbol, uint sz, int16_t layer_llr[][sz], int32_t rxdataF_comp[][nbRx][rx_size_symbol * NR_SYMBOLS_PER_SLOT], - int32_t dl_ch_mag[rx_size_symbol], - int32_t dl_ch_magb[rx_size_symbol], - int32_t dl_ch_magr[rx_size_symbol], + c16_t dl_ch_mag[rx_size_symbol], + c16_t dl_ch_magb[rx_size_symbol], + c16_t dl_ch_magr[rx_size_symbol], NR_DL_UE_HARQ_t *dlsch0_harq, NR_DL_UE_HARQ_t *dlsch1_harq, unsigned char symbol, @@ -178,9 +178,9 @@ static void nr_dlsch_channel_compensation(uint32_t rx_size_symbol, int nbRx, c16_t rxdataF_ext[][rx_size_symbol], int32_t dl_ch_estimates_ext[][rx_size_symbol], - int32_t dl_ch_mag[][nbRx][rx_size_symbol], - int32_t dl_ch_magb[][nbRx][rx_size_symbol], - int32_t dl_ch_magr[][nbRx][rx_size_symbol], + c16_t dl_ch_mag[][nbRx][rx_size_symbol], + c16_t dl_ch_magb[][nbRx][rx_size_symbol], + c16_t dl_ch_magr[][nbRx][rx_size_symbol], int32_t rxdataF_comp[][nbRx][rx_size_symbol * NR_SYMBOLS_PER_SLOT], int ***rho, NR_DL_FRAME_PARMS *frame_parms, @@ -221,9 +221,9 @@ static void nr_dlsch_detection_mrc(uint32_t rx_size_symbol, short n_rx, int32_t rxdataF_comp[][n_rx][rx_size_symbol * NR_SYMBOLS_PER_SLOT], int ***rho, - int32_t dl_ch_mag[][n_rx][rx_size_symbol], - int32_t dl_ch_magb[][n_rx][rx_size_symbol], - int32_t dl_ch_magr[][n_rx][rx_size_symbol], + c16_t dl_ch_mag[][n_rx][rx_size_symbol], + c16_t dl_ch_magb[][n_rx][rx_size_symbol], + c16_t dl_ch_magr[][n_rx][rx_size_symbol], unsigned char symbol, int length); @@ -331,13 +331,13 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, __attribute__((aligned(32))) int32_t dl_ch_estimates_ext[matrixSz][rx_size_symbol]; memset(dl_ch_estimates_ext, 0, sizeof(dl_ch_estimates_ext)); - __attribute__((aligned(32))) int32_t dl_ch_mag[nl][ue->frame_parms.nb_antennas_rx][rx_size_symbol]; + __attribute__((aligned(32))) c16_t dl_ch_mag[nl][ue->frame_parms.nb_antennas_rx][rx_size_symbol]; memset(dl_ch_mag, 0, sizeof(dl_ch_mag)); - __attribute__((aligned(32))) int32_t dl_ch_magb[nl][nbRx][rx_size_symbol]; + __attribute__((aligned(32))) c16_t dl_ch_magb[nl][nbRx][rx_size_symbol]; memset(dl_ch_magb, 0, sizeof(dl_ch_magb)); - __attribute__((aligned(32))) int32_t dl_ch_magr[nl][nbRx][rx_size_symbol]; + __attribute__((aligned(32))) c16_t dl_ch_magr[nl][nbRx][rx_size_symbol]; memset(dl_ch_magr, 0, sizeof(dl_ch_magr)); NR_UE_COMMON *common_vars = &ue->common_vars; NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; @@ -866,9 +866,9 @@ static void nr_dlsch_channel_compensation(uint32_t rx_size_symbol, int nbRx, c16_t rxdataF_ext[][rx_size_symbol], int32_t dl_ch_estimates_ext[][rx_size_symbol], - int32_t dl_ch_mag[][nbRx][rx_size_symbol], - int32_t dl_ch_magb[][nbRx][rx_size_symbol], - int32_t dl_ch_magr[][nbRx][rx_size_symbol], + c16_t dl_ch_mag[][nbRx][rx_size_symbol], + c16_t dl_ch_magb[][nbRx][rx_size_symbol], + c16_t dl_ch_magr[][nbRx][rx_size_symbol], int32_t rxdataF_comp[][nbRx][rx_size_symbol * NR_SYMBOLS_PER_SLOT], int ***rho, NR_DL_FRAME_PARMS *frame_parms, @@ -882,7 +882,7 @@ static void nr_dlsch_channel_compensation(uint32_t rx_size_symbol, PHY_NR_MEASUREMENTS *measurements) { simde__m128i *dl_ch128, *dl_ch128_2, *dl_ch_mag128, *dl_ch_mag128b, *dl_ch_mag128r, *rxdataF128, *rxdataF_comp128, *rho128; - simde__m128i mmtmpD0, mmtmpD1, QAM_amp128 = {0}, QAM_amp128b = {0}, QAM_amp128r = {0}; + simde__m128i QAM_amp128 = {0}, QAM_amp128b = {0}, QAM_amp128r = {0}; uint32_t nb_rb_0 = length / 12 + ((length % 12) ? 1 : 0); @@ -913,10 +913,10 @@ static void nr_dlsch_channel_compensation(uint32_t rx_size_symbol, if (mod_order > 2) { // get channel amplitude if not QPSK - mmtmpD0 = simde_mm_madd_epi16(dl_ch128[0], dl_ch128[0]); + simde__m128i mmtmpD0 = simde_mm_madd_epi16(dl_ch128[0], dl_ch128[0]); mmtmpD0 = simde_mm_srai_epi32(mmtmpD0, output_shift); - mmtmpD1 = simde_mm_madd_epi16(dl_ch128[1], dl_ch128[1]); + simde__m128i mmtmpD1 = simde_mm_madd_epi16(dl_ch128[1], dl_ch128[1]); mmtmpD1 = simde_mm_srai_epi32(mmtmpD1, output_shift); mmtmpD0 = simde_mm_packs_epi32(mmtmpD0, mmtmpD1); //|H[0]|^2 |H[1]|^2 |H[2]|^2 |H[3]|^2 |H[4]|^2 |H[5]|^2 |H[6]|^2 |H[7]|^2 @@ -1224,9 +1224,9 @@ static void nr_dlsch_detection_mrc(uint32_t rx_size_symbol, short n_rx, int32_t rxdataF_comp[][n_rx][rx_size_symbol * NR_SYMBOLS_PER_SLOT], int ***rho, - int32_t dl_ch_mag[][n_rx][rx_size_symbol], - int32_t dl_ch_magb[][n_rx][rx_size_symbol], - int32_t dl_ch_magr[][n_rx][rx_size_symbol], + c16_t dl_ch_mag[][n_rx][rx_size_symbol], + c16_t dl_ch_magb[][n_rx][rx_size_symbol], + c16_t dl_ch_magr[][n_rx][rx_size_symbol], unsigned char symbol, int length) { @@ -1557,9 +1557,9 @@ static void nr_dlsch_mmse(uint32_t rx_size_symbol, unsigned char n_rx, unsigned char nl, // number of layer int32_t rxdataF_comp[][n_rx][rx_size_symbol * NR_SYMBOLS_PER_SLOT], - int32_t dl_ch_mag[][n_rx][rx_size_symbol], - int32_t dl_ch_magb[][n_rx][rx_size_symbol], - int32_t dl_ch_magr[][n_rx][rx_size_symbol], + c16_t dl_ch_mag[][n_rx][rx_size_symbol], + c16_t dl_ch_magb[][n_rx][rx_size_symbol], + c16_t dl_ch_magr[][n_rx][rx_size_symbol], int32_t dl_ch_estimates_ext[][rx_size_symbol], unsigned short nb_rb, unsigned char mod_order, @@ -1754,9 +1754,9 @@ static void nr_dlsch_llr(uint32_t rx_size_symbol, uint sz, int16_t layer_llr[][sz], int32_t rxdataF_comp[][nbRx][rx_size_symbol * NR_SYMBOLS_PER_SLOT], - int32_t dl_ch_mag[rx_size_symbol], - int32_t dl_ch_magb[rx_size_symbol], - int32_t dl_ch_magr[rx_size_symbol], + c16_t dl_ch_mag[rx_size_symbol], + c16_t dl_ch_magb[rx_size_symbol], + c16_t dl_ch_magr[rx_size_symbol], NR_DL_UE_HARQ_t *dlsch0_harq, NR_DL_UE_HARQ_t *dlsch1_harq, unsigned char symbol, diff --git a/openair1/PHY/nr_phy_common/inc/nr_phy_common.h b/openair1/PHY/nr_phy_common/inc/nr_phy_common.h index 97e9bee87e..d52b6d9c43 100644 --- a/openair1/PHY/nr_phy_common/inc/nr_phy_common.h +++ b/openair1/PHY/nr_phy_common/inc/nr_phy_common.h @@ -47,9 +47,9 @@ typedef struct { csi_mapping_parms_t get_csi_mapping_parms(int row, int b, int l0, int l1); int get_cdm_group_size(int cdm_type); void nr_qpsk_llr(int32_t *rxdataF_comp, int16_t *llr, uint32_t nb_re); -void nr_16qam_llr(int32_t *rxdataF_comp, int32_t *ch_mag_in, int16_t *llr, uint32_t nb_re); -void nr_64qam_llr(int32_t *rxdataF_comp, int32_t *ch_mag, int32_t *ch_mag2, int16_t *llr, uint32_t nb_re); -void nr_256qam_llr(int32_t *rxdataF_comp, int32_t *ch_mag, int32_t *ch_mag2, int32_t *ch_mag3, int16_t *llr, uint32_t nb_re); +void nr_16qam_llr(int32_t *rxdataF_comp, c16_t *ch_mag_in, int16_t *llr, uint32_t nb_re); +void nr_64qam_llr(int32_t *rxdataF_comp, c16_t *ch_mag, c16_t *ch_mag2, int16_t *llr, uint32_t nb_re); +void nr_256qam_llr(int32_t *rxdataF_comp, c16_t *ch_mag, c16_t *ch_mag2, c16_t *ch_mag3, int16_t *llr, uint32_t nb_re); void freq2time(uint16_t ofdm_symbol_size, int16_t *freq_signal, int16_t *time_signal); void nr_est_delay(int ofdm_symbol_size, const c16_t *ls_est, c16_t *ch_estimates_time, delay_t *delay); unsigned int nr_get_tx_amp(int power_dBm, int power_max_dBm, int total_nb_rb, int nb_rb); diff --git a/openair1/PHY/nr_phy_common/src/nr_phy_common.c b/openair1/PHY/nr_phy_common/src/nr_phy_common.c index 5a950eba86..e86652bd49 100644 --- a/openair1/PHY/nr_phy_common/src/nr_phy_common.c +++ b/openair1/PHY/nr_phy_common/src/nr_phy_common.c @@ -43,17 +43,17 @@ void init_byte2bit16(void) } simde__m128i byte2m128i[256]; -void init_byte2m128i(void) { - - for (int s=0;s<256;s++) { - byte2m128i[s] = simde_mm_insert_epi16(byte2m128i[s],(1-2*(s&1)),0); - byte2m128i[s] = simde_mm_insert_epi16(byte2m128i[s],(1-2*((s>>1)&1)),1); - byte2m128i[s] = simde_mm_insert_epi16(byte2m128i[s],(1-2*((s>>2)&1)),2); - byte2m128i[s] = simde_mm_insert_epi16(byte2m128i[s],(1-2*((s>>3)&1)),3); - byte2m128i[s] = simde_mm_insert_epi16(byte2m128i[s],(1-2*((s>>4)&1)),4); - byte2m128i[s] = simde_mm_insert_epi16(byte2m128i[s],(1-2*((s>>5)&1)),5); - byte2m128i[s] = simde_mm_insert_epi16(byte2m128i[s],(1-2*((s>>6)&1)),6); - byte2m128i[s] = simde_mm_insert_epi16(byte2m128i[s],(1-2*((s>>7)&1)),7); +void init_byte2m128i(void) +{ + for (int s = 0; s < 256; s++) { + byte2m128i[s] = simde_mm_insert_epi16(byte2m128i[s], (1 - 2 * (s & 1)), 0); + byte2m128i[s] = simde_mm_insert_epi16(byte2m128i[s], (1 - 2 * ((s >> 1) & 1)), 1); + byte2m128i[s] = simde_mm_insert_epi16(byte2m128i[s], (1 - 2 * ((s >> 2) & 1)), 2); + byte2m128i[s] = simde_mm_insert_epi16(byte2m128i[s], (1 - 2 * ((s >> 3) & 1)), 3); + byte2m128i[s] = simde_mm_insert_epi16(byte2m128i[s], (1 - 2 * ((s >> 4) & 1)), 4); + byte2m128i[s] = simde_mm_insert_epi16(byte2m128i[s], (1 - 2 * ((s >> 5) & 1)), 5); + byte2m128i[s] = simde_mm_insert_epi16(byte2m128i[s], (1 - 2 * ((s >> 6) & 1)), 6); + byte2m128i[s] = simde_mm_insert_epi16(byte2m128i[s], (1 - 2 * ((s >> 7) & 1)), 7); } } @@ -71,17 +71,12 @@ void init_delay_table(uint16_t ofdm_symbol_size, } } -int16_t saturating_sub(int16_t a, int16_t b) +static inline c16_t saturating_sub(c16_t a, c16_t b) { - int32_t result = (int32_t)a - (int32_t)b; - - if (result < INT16_MIN) { - return INT16_MIN; - } else if (result > INT16_MAX) { - return INT16_MAX; - } else { - return (int16_t)result; - } + c32_t tmp = {a.r - abs(b.r), a.i - abs(b.i)}; + tmp = (c32_t){min(tmp.r, INT16_MAX), min(tmp.i, INT16_MAX)}; + c16_t tmp2 = (c16_t){max(tmp.r, -INT16_MAX), max(tmp.i, -INT16_MAX)}; + return tmp2; } //---------------------------------------------------------------------------------------------- @@ -101,23 +96,21 @@ void nr_qpsk_llr(int32_t *rxdataF_comp, int16_t *llr, uint32_t nb_re) // 16-QAM //---------------------------------------------------------------------------------------------- -void nr_16qam_llr(int32_t *rxdataF_comp, int32_t *ch_mag_in, int16_t *llr, uint32_t nb_re) +void nr_16qam_llr(int32_t *rxdataF_comp, c16_t *ch_mag_in, int16_t *llr, uint32_t nb_re) { simde__m256i *rxF_256 = (simde__m256i *)rxdataF_comp; - simde__m256i *ch_mag = (simde__m256i *)ch_mag_in; + simde__m256i *ch_mag256 = (simde__m256i *)ch_mag_in; int64_t *llr_64 = (int64_t *)llr; #ifndef USE_128BIT - simde__m256i xmm0, xmm1, xmm2; - for (int i = 0; i < (nb_re >> 3); i++) { // registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I| - xmm0 = simde_mm256_abs_epi16(*rxF_256); + simde__m256i xmm0 = protected_abs256(*rxF_256); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2 - xmm0 = simde_mm256_subs_epi16(*ch_mag, xmm0); + xmm0 = simde_mm256_subs_epi16(*ch_mag256, xmm0); - xmm1 = simde_mm256_unpacklo_epi32(*rxF_256, xmm0); - xmm2 = simde_mm256_unpackhi_epi32(*rxF_256, xmm0); + simde__m256i xmm1 = simde_mm256_unpacklo_epi32(*rxF_256, xmm0); + simde__m256i xmm2 = simde_mm256_unpackhi_epi32(*rxF_256, xmm0); // xmm1 |1st 2ed 3rd 4th 9th 10th 13rd 14th| // xmm2 |5th 6th 7th 8th 11st 12ed 15th 16th| @@ -131,20 +124,20 @@ void nr_16qam_llr(int32_t *rxdataF_comp, int32_t *ch_mag_in, int16_t *llr, uint3 *llr_64++ = simde_mm256_extract_epi64(xmm2, 2); *llr_64++ = simde_mm256_extract_epi64(xmm2, 3); rxF_256++; - ch_mag++; + ch_mag256++; } nb_re &= 0x7; #endif simde__m128i *rxF_128 = (simde__m128i *)rxF_256; - simde__m128i *ch_mag_128 = (simde__m128i *)ch_mag; + simde__m128i *ch_mag_128 = (simde__m128i *)ch_mag256; simde__m128i *llr_128 = (simde__m128i *)llr_64; // Each iteration does 4 RE (gives 16 16bit-llrs) for (int i = 0; i < (nb_re >> 2); i++) { // registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I| - simde__m128i xmm0 = simde_mm_abs_epi16(*rxF_128); + simde__m128i xmm0 = protected_abs128(*rxF_128); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2 xmm0 = simde_mm_subs_epi16(*ch_mag_128, xmm0); @@ -157,18 +150,13 @@ void nr_16qam_llr(int32_t *rxdataF_comp, int32_t *ch_mag_in, int16_t *llr, uint3 nb_re &= 0x3; - int16_t *rxDataF_i16 = (int16_t *)rxF_128; - int16_t *ch_mag_i16 = (int16_t *)ch_mag_128; - int16_t *llr_i16 = (int16_t *)llr_128; + c16_t *rxDataF = (c16_t *)rxF_128; + c16_t *ch_mag = (c16_t *)ch_mag_128; + c16_t *llr_tail = (c16_t *)llr_128; for (uint i = 0U; i < nb_re; i++) { - int16_t real = rxDataF_i16[2 * i]; - int16_t imag = rxDataF_i16[2 * i + 1]; - int16_t mag_real = ch_mag_i16[2 * i]; - int16_t mag_imag = ch_mag_i16[2 * i + 1]; - llr_i16[4 * i] = real; - llr_i16[4 * i + 1] = imag; - llr_i16[4 * i + 2] = saturating_sub(mag_real, abs(real)); - llr_i16[4 * i + 3] = saturating_sub(mag_imag, abs(imag)); + c16_t tmp = *rxDataF++; + *llr_tail++ = tmp; + *llr_tail++ = saturating_sub(*ch_mag++, tmp); } } @@ -176,7 +164,7 @@ void nr_16qam_llr(int32_t *rxdataF_comp, int32_t *ch_mag_in, int16_t *llr, uint3 // 64-QAM //---------------------------------------------------------------------------------------------- -void nr_64qam_llr(int32_t *rxdataF_comp, int32_t *ch_mag, int32_t *ch_mag2, int16_t *llr, uint32_t nb_re) +void nr_64qam_llr(int32_t *rxdataF_comp, c16_t *ch_mag, c16_t *ch_mag2, int16_t *llr, uint32_t nb_re) { simde__m256i *rxF = (simde__m256i *)rxdataF_comp; @@ -184,15 +172,14 @@ void nr_64qam_llr(int32_t *rxdataF_comp, int32_t *ch_mag, int32_t *ch_mag2, int1 simde__m256i *ch_magb = (simde__m256i *)ch_mag2; int32_t *llr_32 = (int32_t *)llr; - #ifndef USE_128BIT for (int i = 0; i < (nb_re >> 3); i++) { simde__m256i xmm0 = simde_mm256_loadu_si256(rxF); // registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I| - simde__m256i xmm1 = simde_mm256_abs_epi16(xmm0); + simde__m256i xmm1 = protected_abs256(xmm0); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2 xmm1 = simde_mm256_subs_epi16(*ch_maga, xmm1); - simde__m256i xmm2 = simde_mm256_abs_epi16(xmm1); + simde__m256i xmm2 = protected_abs256(xmm1); xmm2 = simde_mm256_subs_epi16(*ch_magb, xmm2); // xmm0 |1st 4th 7th 10th 13th 16th 19th 22ed| // xmm1 |2ed 5th 8th 11th 14th 17th 20th 23rd| @@ -244,9 +231,9 @@ void nr_64qam_llr(int32_t *rxdataF_comp, int32_t *ch_mag, int32_t *ch_mag2, int1 for (int i = 0; i < (nb_re >> 2); i++) { simde__m128i xmm0, xmm1, xmm2; xmm0 = *rxF_128; - xmm1 = simde_mm_abs_epi16(xmm0); + xmm1 = protected_abs128(xmm0); xmm1 = simde_mm_subs_epi16(*ch_mag_128, xmm1); - xmm2 = simde_mm_abs_epi16(xmm1); + xmm2 = protected_abs128(xmm1); xmm2 = simde_mm_subs_epi16(*ch_magb_128, xmm2); *llr_32++ = simde_mm_extract_epi32(xmm0, 0); @@ -268,27 +255,19 @@ void nr_64qam_llr(int32_t *rxdataF_comp, int32_t *ch_mag, int32_t *ch_mag2, int1 nb_re &= 0x3; - int16_t *rxDataF_i16 = (int16_t *)rxF_128; - int16_t *ch_mag_i16 = (int16_t *)ch_mag_128; - int16_t *ch_magb_i16 = (int16_t *)ch_magb_128; - int16_t *llr_i16 = (int16_t *)llr_32; + c16_t *rxDataF = (c16_t *)rxF_128; + c16_t *ch_mag_tail = (c16_t *)ch_mag_128; + c16_t *ch_magb_tail = (c16_t *)ch_magb_128; + c16_t *llr_tail = (c16_t *)llr_32; for (int i = 0; i < nb_re; i++) { - int16_t real = rxDataF_i16[2 * i]; - int16_t imag = rxDataF_i16[2 * i + 1]; - int16_t mag_real = ch_mag_i16[2 * i]; - int16_t mag_imag = ch_mag_i16[2 * i + 1]; - llr_i16[6 * i] = real; - llr_i16[6 * i + 1] = imag; - llr_i16[6 * i + 2] = saturating_sub(mag_real, abs(real)); - llr_i16[6 * i + 3] = saturating_sub(mag_imag, abs(imag)); - int16_t mag_realb = ch_magb_i16[2 * i]; - int16_t mag_imagb = ch_magb_i16[2 * i + 1]; - llr_i16[6 * i + 4] = saturating_sub(mag_realb, abs(llr_i16[6 * i + 2])); - llr_i16[6 * i + 5] = saturating_sub(mag_imagb, abs(llr_i16[6 * i + 3])); + *llr_tail++ = *rxDataF; + c16_t tmp = saturating_sub(*ch_mag_tail++, *rxDataF++); + *llr_tail++ = tmp; + *llr_tail++ = saturating_sub(*ch_magb_tail++, tmp); } } -void nr_256qam_llr(int32_t *rxdataF_comp, int32_t *ch_mag, int32_t *ch_mag2, int32_t *ch_mag3, int16_t *llr, uint32_t nb_re) +void nr_256qam_llr(int32_t *rxdataF_comp, c16_t *ch_mag, c16_t *ch_mag2, c16_t *ch_mag3, int16_t *llr, uint32_t nb_re) { simde__m256i *rxF_256 = (simde__m256i *)rxdataF_comp; simde__m256i *llr256 = (simde__m256i *)llr; @@ -297,26 +276,24 @@ void nr_256qam_llr(int32_t *rxdataF_comp, int32_t *ch_mag, int32_t *ch_mag2, int simde__m256i *ch_magb = (simde__m256i *)ch_mag2; simde__m256i *ch_magc = (simde__m256i *)ch_mag3; #ifndef USE_128BIT - simde__m256i xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6; - for (int i = 0; i < (nb_re >> 3); i++) { // registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I| - xmm0 = simde_mm256_abs_epi16(*rxF_256); + simde__m256i xmm0 = protected_abs256(*rxF_256); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2 xmm0 = simde_mm256_subs_epi16(*ch_maga, xmm0); // xmmtmpD2 contains 16 LLRs - xmm1 = simde_mm256_abs_epi16(xmm0); + simde__m256i xmm1 = protected_abs256(xmm0); xmm1 = simde_mm256_subs_epi16(*ch_magb, xmm1); // contains 16 LLRs - xmm2 = simde_mm256_abs_epi16(xmm1); + simde__m256i xmm2 = protected_abs256(xmm1); xmm2 = simde_mm256_subs_epi16(*ch_magc, xmm2); // contains 16 LLRs // rxF[i] A0 A1 A2 A3 A4 A5 A6 A7 bits 7,6 // xmm0 B0 B1 B2 B3 B4 B5 B6 B7 bits 5,4 // xmm1 C0 C1 C2 C3 C4 C5 C6 C7 bits 3,2 // xmm2 D0 D1 D2 D3 D4 D5 D6 D7 bits 1,0 - xmm3 = simde_mm256_unpacklo_epi32(*rxF_256, xmm0); // A0 B0 A1 B1 A4 B4 A5 B5 - xmm4 = simde_mm256_unpackhi_epi32(*rxF_256, xmm0); // A2 B2 A3 B3 A6 B6 A7 B7 - xmm5 = simde_mm256_unpacklo_epi32(xmm1, xmm2); // C0 D0 C1 D1 C4 D4 C5 D5 - xmm6 = simde_mm256_unpackhi_epi32(xmm1, xmm2); // C2 D2 C3 D3 C6 D6 C7 D7 + simde__m256i xmm3 = simde_mm256_unpacklo_epi32(*rxF_256, xmm0); // A0 B0 A1 B1 A4 B4 A5 B5 + simde__m256i xmm4 = simde_mm256_unpackhi_epi32(*rxF_256, xmm0); // A2 B2 A3 B3 A6 B6 A7 B7 + simde__m256i xmm5 = simde_mm256_unpacklo_epi32(xmm1, xmm2); // C0 D0 C1 D1 C4 D4 C5 D5 + simde__m256i xmm6 = simde_mm256_unpackhi_epi32(xmm1, xmm2); // C2 D2 C3 D3 C6 D6 C7 D7 xmm0 = simde_mm256_unpacklo_epi64(xmm3, xmm5); // A0 B0 C0 D0 A4 B4 C4 D4 xmm1 = simde_mm256_unpackhi_epi64(xmm3, xmm5); // A1 B1 C1 D1 A5 B5 C5 D5 @@ -341,16 +318,15 @@ void nr_256qam_llr(int32_t *rxdataF_comp, int32_t *ch_mag, int32_t *ch_mag2, int simde__m128i *ch_maga_128 = (simde__m128i *)ch_maga; simde__m128i *ch_magb_128 = (simde__m128i *)ch_magb; simde__m128i *ch_magc_128 = (simde__m128i *)ch_magc; - for (int i = 0; i < (nb_re >> 2); i++) { simde__m128i xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6; // registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I| - xmm0 = simde_mm_abs_epi16(*rxF_128); + xmm0 = protected_abs128(*rxF_128); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2 xmm0 = simde_mm_subs_epi16(*ch_maga_128, xmm0); - xmm1 = simde_mm_abs_epi16(xmm0); + xmm1 = protected_abs128(xmm0); xmm1 = simde_mm_subs_epi16(*ch_magb_128, xmm1); // contains 8 LLRs - xmm2 = simde_mm_abs_epi16(xmm1); + xmm2 = protected_abs128(xmm1); xmm2 = simde_mm_subs_epi16(*ch_magc_128, xmm2); // contains 8 LLRs // rxF[i] A0 A1 A2 A3 // xmm0 B0 B1 B2 B3 @@ -372,30 +348,20 @@ void nr_256qam_llr(int32_t *rxdataF_comp, int32_t *ch_mag, int32_t *ch_mag2, int ch_magc_128++; } - if (nb_re & 3) { - for (int i = 0; i < (nb_re & 0x3); i++) { - int16_t *rxDataF_i16 = (int16_t *)rxF_128; - int16_t *ch_mag_i16 = (int16_t *)ch_maga_128; - int16_t *ch_magb_i16 = (int16_t *)ch_magb_128; - int16_t *ch_magc_i16 = (int16_t *)ch_magc_128; - int16_t *llr_i16 = (int16_t *)llr_128; - int16_t real = rxDataF_i16[2 * i + 0]; - int16_t imag = rxDataF_i16[2 * i + 1]; - int16_t mag_real = ch_mag_i16[2 * i]; - int16_t mag_imag = ch_mag_i16[2 * i + 1]; - llr_i16[8 * i] = real; - llr_i16[8 * i + 1] = imag; - llr_i16[8 * i + 2] = saturating_sub(mag_real, abs(real)); - llr_i16[8 * i + 3] = saturating_sub(mag_imag, abs(imag)); - int16_t magb_real = ch_magb_i16[2 * i]; - int16_t magb_imag = ch_magb_i16[2 * i + 1]; - llr_i16[8 * i + 4] = saturating_sub(magb_real, abs(llr_i16[8 * i + 2])); - llr_i16[8 * i + 5] = saturating_sub(magb_imag, abs(llr_i16[8 * i + 3])); - int16_t magc_real = ch_magc_i16[2 * i]; - int16_t magc_imag = ch_magc_i16[2 * i + 1]; - llr_i16[8 * i + 6] = saturating_sub(magc_real, abs(llr_i16[8 * i + 4])); - llr_i16[8 * i + 7] = saturating_sub(magc_imag, abs(llr_i16[8 * i + 5])); - } + nb_re &= 0x3; + c16_t *rxDataF = (c16_t *)rxF_128; + c16_t *ch_mag_tail = (c16_t *)ch_maga_128; + c16_t *ch_magb_tail = (c16_t *)ch_magb_128; + c16_t *ch_magc_tail = (c16_t *)ch_magc_128; + c16_t *llr_tail = (c16_t *)llr_128; + for (int i = 0; i < nb_re; i++) { + c16_t tmp = *rxDataF++; + *llr_tail++ = tmp; + c16_t tmp1 = saturating_sub(*ch_mag_tail++, tmp); + *llr_tail++ = tmp1; + c16_t tmp2 = saturating_sub(*ch_magb_tail++, tmp1); + *llr_tail++ = tmp2; + *llr_tail++ = saturating_sub(*ch_magc_tail++, tmp2); } } From b37cd0413481d610786463f3a6967e70e81340c5 Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Tue, 22 Jul 2025 13:41:36 -0400 Subject: [PATCH 274/964] Set sib1 reception flag as per spec TS 38.213 4.1 says coreset 0 is present only if kssb < 24 for FR1 and < 12 for FR2. This commit sets get_sib1 flag based on kssb. Also, setting of mac state is taken out of function nr_ue_decode_mib(). --- openair2/LAYER2/NR_MAC_UE/config_ue.c | 28 +++++++++++++++++--- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 8 ------ 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index 297be42261..627605a216 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -1000,6 +1000,12 @@ static void update_mib_conf(NR_MIB_t *target, NR_MIB_t *source) target->intraFreqReselection = source->intraFreqReselection; } +static bool is_cset0_present(frequency_range_t const fr, uint8_t const kssb) +{ + // TS 38.213 4.1 defines if CORESET 0 is present or not based on Kssb + return (fr == FR1) ? (kssb < 24) : (kssb < 12); +} + void nr_rrc_mac_config_req_mib(module_id_t module_id, int cc_idP, NR_MIB_t *mib, int sched_sib, bool barred) { NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); @@ -1018,11 +1024,25 @@ void nr_rrc_mac_config_req_mib(module_id_t module_id, int cc_idP, NR_MIB_t *mib, update_mib_conf(mac->mib, mib); mac->phy_config.Mod_id = module_id; mac->phy_config.CC_id = cc_idP; - if (sched_sib == 1) - mac->get_sib1 = true; - else if (sched_sib > 1) - mac->get_otherSI[sched_sib - 2] = true; + nr_ue_decode_mib(mac, cc_idP); + + if (sched_sib == 1) { + bool const is_c0 = is_cset0_present(mac->frequency_range, mac->ssb_subcarrier_offset); + mac->get_sib1 = is_c0; + AssertFatal(is_c0, "RRC scheduling SIB1 reception but MIB indicates no SIB1 present in current cell\n"); + } else if (sched_sib > 1) + mac->get_otherSI[sched_sib - 2] = true; + + if (get_softmodem_params()->phy_test) + mac->state = UE_CONNECTED; + else if (mac->state == UE_NOT_SYNC) { + if (IS_SA_MODE(get_softmodem_params()) && mac->get_sib1) + mac->state = UE_RECEIVING_SIB; + else + mac->state = UE_PERFORMING_RA; + } + ret = pthread_mutex_unlock(&mac->if_mutex); AssertFatal(!ret, "mutex failed %d\n", ret); } diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 8a892557b2..fb0645560e 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -238,14 +238,6 @@ void nr_ue_decode_mib(NR_UE_MAC_INST_t *mac, int cc_id) mac->ssb_subcarrier_offset = ssb_subcarrier_offset; mac->dmrs_TypeA_Position = mac->mib->dmrs_TypeA_Position; - if (get_softmodem_params()->phy_test) - mac->state = UE_CONNECTED; - else if (mac->state == UE_NOT_SYNC) { - if (IS_SA_MODE(get_softmodem_params()) && mac->get_sib1) - mac->state = UE_RECEIVING_SIB; - else - mac->state = UE_PERFORMING_RA; - } } static void configure_ratematching_csi(fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_pdu, From eb44d715ca7d8da7215fa48c42b2ebdb60a42879 Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Mon, 12 May 2025 16:13:30 -0400 Subject: [PATCH 275/964] Dlsim dump processing buffers Write extracted rxF buffer to output bin file. Fix offset in writing rxF buffer. --- .../NR_UE_TRANSPORT/nr_dlsch_demodulation.c | 15 ++--- openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 8 ++- openair1/SIMULATION/NR_PHY/dlsim.c | 57 ++++++++++++------- 3 files changed, 50 insertions(+), 30 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c index ebe4c946be..d045c6f198 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c @@ -480,10 +480,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, ue->phy_cpu_stats.cpu_time_stats[DLSCH_EXTRACT_RBS_STATS].p_time / (cpuf * 1000.0)); } if (ue->phy_sim_pdsch_rxdataF_ext) - for (unsigned char aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { - int offset = ((void *)rxdataF_ext[aarx] - (void *)rxdataF_ext) + symbol * rx_size_symbol; - memcpy(ue->phy_sim_pdsch_rxdataF_ext + offset, rxdataF_ext, rx_size_symbol * sizeof(c16_t)); - } + memcpy(ue->phy_sim_pdsch_rxdataF_ext + symbol * sizeof(rxdataF_ext), rxdataF_ext, sizeof(rxdataF_ext)); nb_re_pdsch = (pilots == 1) ? ((config_type == NFAPI_NR_DMRS_TYPE1) ? nb_rb_pdsch * (12 - 6 * dlsch_config->n_dmrs_cdm_groups) : nb_rb_pdsch * (12 - 4 * dlsch_config->n_dmrs_cdm_groups)) @@ -776,12 +773,16 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, if (ue->phy_sim_pdsch_rxdataF_comp) for (int a = 0; a < nbRx; a++) { - int offset = (void *)rxdataF_comp[0][a] - (void *)rxdataF_comp[0] + symbol * rx_size_symbol * sizeof(c16_t); - memcpy(ue->phy_sim_pdsch_rxdataF_comp + offset, rxdataF_comp[0][a] + symbol * rx_size_symbol, sizeof(c16_t) * rx_size_symbol); + for (int l = 0; l < nl; l++) { + int offset = (void *)rxdataF_comp[l][a] - (void *)rxdataF_comp[0] + symbol * rx_size_symbol * sizeof(c16_t); + memcpy(ue->phy_sim_pdsch_rxdataF_comp + offset, + rxdataF_comp[l][a] + symbol * rx_size_symbol, + sizeof(c16_t) * rx_size_symbol); + } memcpy((c16_t *)ue->phy_sim_pdsch_dl_ch_estimates + pdsch_est_size * a, dl_ch_estimates, pdsch_est_size * sizeof(c16_t)); } if (ue->phy_sim_pdsch_dl_ch_estimates_ext) - memcpy((c16_t *)ue->phy_sim_pdsch_dl_ch_estimates_ext + symbol * rx_size_symbol, + memcpy(ue->phy_sim_pdsch_dl_ch_estimates_ext + symbol * sizeof(dl_ch_estimates_ext), dl_ch_estimates_ext, sizeof(dl_ch_estimates_ext)); return (0); diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index 791f3e4631..fc22fe693e 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -1042,6 +1042,8 @@ int pbch_pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_ phy_pdcch_config->nb_search_space = 0; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PDCCH, VCD_FUNCTION_OUT); TracyCZoneEnd(ctx); + if (ue->phy_sim_rxdataF) + memcpy(ue->phy_sim_rxdataF, rxdataF[0], sizeof(int32_t) * nb_symb_pdcch * ue->frame_parms.ofdm_symbol_size); return sampleShift; } @@ -1166,9 +1168,11 @@ void pdsch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_ } if (ue->phy_sim_rxdataF) - memcpy(ue->phy_sim_rxdataF, rxdataF, sizeof(int32_t)*rxdataF_sz*ue->frame_parms.nb_antennas_rx); + memcpy(ue->phy_sim_rxdataF + start_symb_sch * ue->frame_parms.ofdm_symbol_size * sizeof(c16_t), + &rxdataF[0][start_symb_sch * ue->frame_parms.ofdm_symbol_size], + sizeof(int32_t) * nb_symb_sch * ue->frame_parms.ofdm_symbol_size); if (ue->phy_sim_pdsch_llr) - memcpy(ue->phy_sim_pdsch_llr, llr[0], sizeof(int16_t)*rx_llr_buf_sz); + memcpy(ue->phy_sim_pdsch_llr, llr[0], sizeof(int16_t) * rx_llr_buf_sz); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC, VCD_FUNCTION_OUT); for (int i=0; iphy_sim_pdsch_llr; TBS = dlsch0->dlsch_config.TBS;//rel15->TBSize[0]; - uint16_t length_dmrs = get_num_dmrs(rel15->dlDmrsSymbPos); - uint16_t nb_rb = rel15->rbSize; - uint8_t nb_re_dmrs = rel15->dmrsConfigType == NFAPI_NR_DMRS_TYPE1 ? 6*dlsch0->dlsch_config.n_dmrs_cdm_groups : 4*dlsch0->dlsch_config.n_dmrs_cdm_groups; - uint8_t mod_order = rel15->qamModOrder[0]; - uint8_t nb_symb_sch = rel15->NrOfSymbols; + uint16_t length_dmrs = get_num_dmrs(dlsch0->dlsch_config.dlDmrsSymbPos); + uint16_t nb_rb = dlsch0->dlsch_config.number_rbs; + uint8_t nb_re_dmrs = dlsch0->dlsch_config.dmrsConfigType == NFAPI_NR_DMRS_TYPE1 ? 6*dlsch0->dlsch_config.n_dmrs_cdm_groups : 4*dlsch0->dlsch_config.n_dmrs_cdm_groups; + uint8_t mod_order = dlsch0->dlsch_config.qamModOrder; + uint8_t nb_symb_sch = dlsch0->dlsch_config.number_symbols; uint32_t unav_res = ptrsSymbPerSlot * ptrsRePerSymb; available_bits = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, unav_res, mod_order, rel15->nrOfLayers); if (pdu_bit_map & 0x1) { @@ -1367,23 +1367,38 @@ printf("%d\n", slot); if (UE->frame_parms.nb_antennas_rx>1) LOG_M("rxsig1.m", "rxs1", UE->common_vars.rxdata[1], frame_length_complex_samples, dec, op_format); LOG_M("rxF0.m", "rxF0", UE->phy_sim_rxdataF, frame_parms->samples_per_slot_wCP, dec, op_format); - LOG_M("rxF_ext.m", "rxFe", UE->phy_sim_pdsch_rxdataF_ext, g_rbSize * 12 * 14, dec, op_format); const uint32_t numReSym = (g_rbSize * 12 + 15) & (~15); - const uint32_t numValidReSym = g_rbSize * 12; - { - const int s = rel15->StartSymbolIndex; - const int n = rel15->NrOfSymbols; - for (int i = s; i < s + n; i++) { - char fName[50]; - snprintf(fName, sizeof(fName), "chestF0_ext_s%d.m", i); - LOG_M(fName, - "chF0_ext", - ((c16_t *)UE->phy_sim_pdsch_dl_ch_estimates_ext) + (i * numReSym), - numValidReSym, - dec, - op_format); - snprintf(fName, sizeof(fName), "rxF_comp_s%d.m", i); - LOG_M(fName, "rxFc", ((c16_t *)UE->phy_sim_pdsch_rxdataF_comp) + (i * numReSym), numValidReSym, dec, op_format); + for (int l = 0; l < g_nrOfLayers; l++) { + for (int r = 0; r < n_rx; r++) { + const int s = rel15->StartSymbolIndex; + const int n = rel15->NrOfSymbols; + for (int i = s; i < s + n; i++) { + const uint32_t dmrsBitMap = phy_data.dlsch[0].dlsch_config.dlDmrsSymbPos; + const uint32_t dmrsCfg = phy_data.dlsch[0].dlsch_config.dmrsConfigType; + const uint32_t nrb = phy_data.dlsch[0].dlsch_config.number_rbs; + const uint32_t ncdmg = phy_data.dlsch[0].dlsch_config.n_dmrs_cdm_groups; + const uint32_t numValidReSym = ((dmrsBitMap >> i) & 1) + ? ((dmrsCfg == NFAPI_NR_DMRS_TYPE1) ? nrb * (12 - 6 * ncdmg) : nrb * (12 - 4 * ncdmg)) + : (nrb * 12); + char fName[50]; + snprintf(fName, sizeof(fName), "chestF_ext_l%d_r%d_s%d.m", l, r, i); + uint32_t buff_offset = (i * g_nrOfLayers * n_rx * numReSym) + (l * n_rx * numReSym) + (r * numReSym); + LOG_M(fName, + "chF0_ext", + ((c16_t *)UE->phy_sim_pdsch_dl_ch_estimates_ext) + buff_offset, + numValidReSym, + dec, + op_format); + snprintf(fName, sizeof(fName), "rxF_comp_l%d_s%d.m", l, i); + LOG_M(fName, "rxFc", ((c16_t *)UE->phy_sim_pdsch_rxdataF_comp) + (l * NR_SYMBOLS_PER_SLOT * numReSym) + (i * numReSym), numValidReSym, dec, op_format); + if (l == 0) { + snprintf(fName, sizeof(fName), "rxF_ext_r%d_s%d.m", r, i); + buff_offset = (i * n_rx * numReSym) + (r * numReSym); + LOG_M(fName, "rxFext", ((c16_t *)UE->phy_sim_pdsch_rxdataF_ext) + buff_offset, numValidReSym, dec, op_format); + } + snprintf(fName, sizeof(fName), "chestF0_s%d.m", i); + LOG_M(fName, "chF0", ((c16_t *)UE->phy_sim_pdsch_dl_ch_estimates) + i * frame_parms->ofdm_symbol_size, nrb*12, dec, op_format); + } } } LOG_M("chestF0.m", "chF0", UE->phy_sim_pdsch_dl_ch_estimates, frame_parms->ofdm_symbol_size * 14, dec, op_format); From dad6cf8dc3895be22e85a8abeb3cf14c9fb27cff Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Thu, 10 Jul 2025 16:11:09 -0400 Subject: [PATCH 276/964] Fix bug in LLR threshold buffer The LLR threshold buffers hold only for one symbol but the LLRs are computed for all symbols together. So only the threshold of last symbol was used for computing LLR for all other symbols. This commit calls nr_dlsch_llr for each symbol togther with rest of nr_rx_pdsch() and calls nr_dlsch_layer_demapping at the last symbol. Fixes issue 948. --- .../NR_UE_TRANSPORT/nr_dlsch_demodulation.c | 61 +++++++------------ .../NR_UE_TRANSPORT/nr_transport_proto_ue.h | 2 + openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 11 ++++ 3 files changed, 35 insertions(+), 39 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c index d045c6f198..15297a2ba3 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c @@ -312,6 +312,8 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, unsigned char harq_pid, uint32_t pdsch_est_size, int32_t dl_ch_estimates[][pdsch_est_size], + int layer_llr_size, + int16_t layer_llr[][layer_llr_size], int16_t *llr[2], uint32_t dl_valid_re[NR_SYMBOLS_PER_SLOT], c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP], @@ -681,47 +683,28 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, dlsch); dl_valid_re[symbol] -= ptrs_re_per_slot[0][symbol]; } + start_meas_nr_ue_phy(ue, DLSCH_LLR_STATS); + nr_dlsch_llr(rx_size_symbol, + nbRx, + layer_llr_size, + layer_llr, + rxdataF_comp, + dl_ch_mag[0][0], + dl_ch_magb[0][0], + dl_ch_magr[0][0], + dlsch0_harq, + dlsch1_harq, + symbol, + dl_valid_re[symbol], + dlsch, + llr_offset[symbol]); + if (symbol < startSymbIdx + nbSymb - 1) // up to the penultimate symbol + llr_offset[symbol + 1] = dl_valid_re[symbol] * dlsch_config->qamModOrder + llr_offset[symbol]; + stop_meas_nr_ue_phy(ue, DLSCH_LLR_STATS); /* at last symbol in a slot calculate LLR's for whole slot */ - if(symbol == (startSymbIdx + nbSymb - 1)) { - const uint32_t rx_llr_layer_size = (G + dlsch[0].Nl - 1) / dlsch[0].Nl; - - if (dlsch[0].Nl == 0 || rx_llr_layer_size == 0 || rx_llr_layer_size > 10 * 1000 * 1000) { - LOG_E(PHY, "rx_llr_layer_size %d, G %d, Nl, %d, discarding this pdsch\n", rx_llr_layer_size, G, dlsch[0].Nl); - return -1; - } - - __attribute__((aligned(32))) int16_t layer_llr[dlsch[0].Nl][rx_llr_layer_size]; - for(int i = startSymbIdx; i < startSymbIdx + nbSymb; i++) { - /* Calculate LLR's for each symbol */ - start_meas_nr_ue_phy(ue, DLSCH_LLR_STATS); - nr_dlsch_llr(rx_size_symbol, - nbRx, - rx_llr_layer_size, - layer_llr, - rxdataF_comp, - dl_ch_mag[0][0], - dl_ch_magb[0][0], - dl_ch_magr[0][0], - dlsch0_harq, - dlsch1_harq, - i, - dl_valid_re[i], - dlsch, - llr_offset[i]); - if (i < startSymbIdx + nbSymb - 1) // up to the penultimate symbol - llr_offset[i + 1] = dl_valid_re[i] * dlsch_config->qamModOrder + llr_offset[i]; - stop_meas_nr_ue_phy(ue, DLSCH_LLR_STATS); - } - + if (symbol == (startSymbIdx + nbSymb - 1)) { start_meas_nr_ue_phy(ue, DLSCH_LAYER_DEMAPPING); - nr_dlsch_layer_demapping(llr, - dlsch[0].Nl, - dlsch_config->qamModOrder, - G, - codeword_TB0, - codeword_TB1, - rx_llr_layer_size, - layer_llr); + nr_dlsch_layer_demapping(llr, dlsch[0].Nl, dlsch_config->qamModOrder, G, codeword_TB0, codeword_TB1, layer_llr_size, layer_llr); stop_meas_nr_ue_phy(ue, DLSCH_LAYER_DEMAPPING); /* for (int i=0; i < 2; i++){ diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h index 8e266a57a3..cdb10d0533 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h @@ -310,6 +310,8 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, unsigned char harq_pid, uint32_t pdsch_est_size, int32_t dl_ch_estimates[][pdsch_est_size], + int layer_llr_size, + int16_t layer_llr[][layer_llr_size], int16_t *llr[2], uint32_t dl_valid_re[NR_SYMBOLS_PER_SLOT], c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP], diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index fc22fe693e..e31d0491bc 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -605,6 +605,15 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, uint32_t llr_offset[NR_SYMBOLS_PER_SLOT] = {0}; int32_t log2_maxh = 0; + + const uint32_t rx_llr_layer_size = (G + dlsch[0].Nl - 1) / dlsch[0].Nl; + + if (dlsch[0].Nl == 0 || rx_llr_layer_size == 0 || rx_llr_layer_size > 10 * 1000 * 1000) { + LOG_E(PHY, "rx_llr_layer_size %d, G %d, Nl, %d, discarding this pdsch\n", rx_llr_layer_size, G, dlsch[0].Nl); + return -1; + } + __attribute__((aligned(32))) int16_t layer_llr[dlsch[0].Nl][rx_llr_layer_size]; + start_meas_nr_ue_phy(ue, RX_PDSCH_STATS); pdsch_scope_req_t scope_req = { .copy_chanest_to_scope = false, .copy_rxdataF_to_scope = false, @@ -639,6 +648,8 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, harq_pid, pdsch_est_size, pdsch_dl_ch_estimates, + rx_llr_layer_size, + layer_llr, llr, dl_valid_re, rxdataF, From e9d95e89623716840840debafebff6a25f3a738b Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Thu, 10 Jul 2025 21:13:52 -0400 Subject: [PATCH 277/964] Add new physim test cases for nr_dlsim Following tests are added: 1. 256QAM with TDL-A channel model 2. 256QAM with 2 layers --- openair1/PHY/CODING/tests/CMakeLists.txt | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/openair1/PHY/CODING/tests/CMakeLists.txt b/openair1/PHY/CODING/tests/CMakeLists.txt index 8d7fac20d7..2f8f88d547 100644 --- a/openair1/PHY/CODING/tests/CMakeLists.txt +++ b/openair1/PHY/CODING/tests/CMakeLists.txt @@ -113,10 +113,12 @@ add_physim_test(5g nr_dlsim offset.test5 "217 PRB 100 PDSCH-PRBs 110 PDSCH-Offse add_physim_test(5g nr_dlsim mcs.mimo.test1 "106 PRBs 50 PDSCH-PRBs MCS Index 27" -n300 -e27 -s30) add_physim_test(5g nr_dlsim mcs.mimo.test2 "106 PRBs 50 PDSCH-PRBs MCS Index 16" -n300 -e16 -s11 -S13) add_physim_test(5g nr_dlsim mcs.mimo.test3 "106 MCS-TABLE 256 QAM MCS Index 26" -n300 -q1 -e26 -s30) -add_physim_test(5g nr_dlsim mcs.mimo.test4 "MCS 0, low SNR performance" -n300 -e0 -t95 -S-1.0 -i 2 1 0) -add_physim_test(5g nr_dlsim mcs.mimo.test5 "4x4 MIMO, 1 Layer" -n30 -s20 -U 3 0 0 2 -gA -x1 -y4 -z4) -add_physim_test(5g nr_dlsim mcs.mimo.test6 "4x4 MIMO, 2 Layers" -n30 -s20 -U 3 0 0 2 -gA -x2 -y4 -z4) -add_physim_test(5g nr_dlsim mcs.mimo.test7 "4x4 MIMO, 4 Layers" -n30 -s20 -U 3 0 0 2 -x4 -y4 -z4) +add_physim_test(5g nr_dlsim mcs.mimo.test4 "106 MCS-TABLE 256 QAM Fading Channel" -n300 -q1 -e24 -s30 -gA) +add_physim_test(5g nr_dlsim mcs.mimo.test5 "MCS 0, low SNR performance" -n300 -e0 -t95 -S-1.0 -i 2 1 0) +add_physim_test(5g nr_dlsim mcs.mimo.test6 "4x4 MIMO, 1 Layer" -n30 -s20 -U 3 0 0 2 -gA -x1 -y4 -z4) +add_physim_test(5g nr_dlsim mcs.mimo.test7 "4x4 MIMO, 2 Layers" -n30 -s20 -U 3 0 0 2 -gA -x2 -y4 -z4) +add_physim_test(5g nr_dlsim mcs.mimo.test8 "4x4 MIMO, 2 Layers 256 QAM" -n30 -s25 -e22 -q1 -U 3 0 0 2 -gA -x2 -y4 -z4) +add_physim_test(5g nr_dlsim mcs.mimo.test9 "4x4 MIMO, 4 Layers" -n30 -s20 -U 3 0 0 2 -x4 -y4 -z4) add_physim_test(5g nr_dlsim dmrs.ptrs.test1 "3 PTRS, 8 Interpolated Symbols" -n300 -s5 -T 2 2 2) add_physim_test(5g nr_dlsim dmrs.ptrs.test2 "6 PTRS, 5 Interpolated Symbols" -n300 -s5 -T 2 1 2) add_physim_test(5g nr_dlsim dmrs.ptrs.test3 "11 PTRS, 0 Interpolated Symbols" -n300 -s5 -T 2 0 4) From c65db568f5d93ce23d7609524ff722aa81324c0f Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 21 Jul 2025 13:05:29 +0200 Subject: [PATCH 278/964] take into account starting PRB when deciding even/odd PRB for CSI PDSCH rate-matching --- openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c index 37c8382ec5..0999f92de4 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c @@ -493,8 +493,8 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, uint32_t csi_re_count = 0; uint32_t csi_res_even = csi_res_bitmap & 0xfff; uint32_t csi_res_odd = (csi_res_bitmap >> 16) & 0xfff; - - for (int rb = 0; rb < nb_rb_pdsch; rb++) { + int start = start_rb + dlsch_config->BWPStart; + for (int rb = start; rb < start + nb_rb_pdsch; rb++) { uint32_t rb_csi_pattern = (rb % 2 == 0) ? csi_res_even : csi_res_odd; csi_re_count += __builtin_popcount(rb_csi_pattern); } From fffe9531c360434cbd6cccb269146b5f7bd17dfd Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Tue, 22 Jul 2025 13:51:05 +0200 Subject: [PATCH 279/964] add assert in a case of wrong gNB configuration file --- common/utils/nr/nr_common.c | 1 + 1 file changed, 1 insertion(+) diff --git a/common/utils/nr/nr_common.c b/common/utils/nr/nr_common.c index 7875fe546a..7954db7d54 100644 --- a/common/utils/nr/nr_common.c +++ b/common/utils/nr/nr_common.c @@ -1160,6 +1160,7 @@ uint32_t get_ssb_offset_to_pointA(uint32_t absoluteFrequencySSB, const int ssb_offset_point_a = ((scaled_abs_diff / 12) - 10) * scaling; // Offset to point A needs to be divisible by scaling AssertFatal(ssb_offset_point_a % scaling == 0, "PRB offset %d not valid for scs %d\n", ssb_offset_point_a, ssbSubcarrierSpacing); + AssertFatal(ssb_offset_point_a >= 0, "ssb offset is negative %d for scs %d\n", ssb_offset_point_a, ssbSubcarrierSpacing); return ssb_offset_point_a; } From 3ca12f78e5a9f1abff7e57b4ae2b900d470b9085 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Wed, 23 Jul 2025 07:48:17 +0200 Subject: [PATCH 280/964] simplify function nr_pdcch_extract_rbs_single() --- openair1/PHY/NR_UE_TRANSPORT/dci_nr.c | 107 ++++++++------------------ 1 file changed, 33 insertions(+), 74 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c index a027b042ca..7dcbbbe969 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c @@ -269,9 +269,9 @@ static void nr_pdcch_extract_rbs_single(uint32_t rxdataF_sz, LOG_DDD("dl_ch0 = &dl_ch_estimates[aarx = (%d)][0]\n", aarx); const int offset = symbol * coreset_nbr_rb * NBR_RE_PER_RB_WITH_DMRS; - c16_t *dl_ch0_ext = &dl_ch_estimates_ext[aarx][offset]; + c16_t *dl_ch0_ext = dl_ch_estimates_ext[aarx] + offset; LOG_DDD("dl_ch0_ext = &dl_ch_estimates_ext[aarx = (%d)][symbol * (frame_parms->N_RB_DL * 9) = (%d)]\n", aarx, offset); - c16_t *rxF_ext = &rxdataF_ext[aarx][offset]; + c16_t *rxF_ext = rxdataF_ext[aarx] + offset; LOG_DDD("rxF_ext = &rxdataF_ext[aarx = (%d)][symbol * (frame_parms->N_RB_DL * 9) = (%d)]\n", aarx, offset); /* @@ -301,81 +301,40 @@ static void nr_pdcch_extract_rbs_single(uint32_t rxdataF_sz, c_rb += 6; c_rb_by6 = c_rb / 6; } - - // first we set initial conditions for pointer to rxdataF depending on the situation of the first RB within the CORESET - // (c_rb = n_BWP_start) - if ((frame_parms->N_RB_DL & 1) == 1 && (c_rb + n_BWP_start) == (frame_parms->N_RB_DL >> 1)) { - // treatment of RB containing the DC - // if odd number RBs in system bandwidth and first RB to be treated is higher than middle system bandwidth (around DC) - // we have to treat the RB in two parts: first part from i=0 to 5, the data is at the end of rxdataF (pointing at the - // end of the table) - c16_t *rxF = rxFbase + frame_parms->first_carrier_offset + 12 * (c_rb + n_BWP_start); - - int i = 0, j = 0; - for (; i < 6; i++) { // treating first part of the RB note that i=5 would correspond to DC. We treat it in NR - if ((i != 1) && (i != 5)) { - dl_ch0_ext[j] = dl_ch0[i]; - rxF_ext[j] = rxF[i]; - LOG_DSYMB(""); - j++; - } else { - LOG_DSYMB("\t\t <==> DM-RS PDCCH, this is a pilot symbol\n"); - } - } - - // then we point at the begining of the symbol part of rxdataF do process second part of RB - for (; i < 12; i++) { - if ((i != 9)) { - dl_ch0_ext[j] = dl_ch0[i]; - rxF_ext[j] = rxFbase[i - 6]; - LOG_DSYMB(""); - j++; - } else { - LOG_DSYMB("\t\t <==> DM-RS PDCCH, this is a pilot symbol\n"); - } - } - - } else { // treatment of any RB that does not contain the DC - c16_t *rxF=NULL; - if ((frame_parms->N_RB_DL & 1) == 0) { - if ((c_rb + n_BWP_start) < (frame_parms->N_RB_DL >> 1)) - // if RB to be treated is lower than middle system bandwidth then rxdataF pointed - // at (offset + c_br + symbol * ofdm_symbol_size): even case - rxF = rxFbase + (frame_parms->first_carrier_offset + 12 * c_rb) + n_BWP_start * 12; - else - // number of RBs is even and c_rb is higher than half system bandwidth (we don't skip DC) - // if these conditions are true the pointer has to be situated at the 1st part of the rxdataF - // we point at the 1st part of the rxdataF in symbol - rxF = rxFbase + 12 * (c_rb + n_BWP_start - (frame_parms->N_RB_DL >> 1)); - } else { - if ((c_rb + n_BWP_start) < (frame_parms->N_RB_DL >> 1)) - // if RB to be treated is lower than middle system bandwidth then rxdataF pointed - // at (offset + c_br + symbol * ofdm_symbol_size): odd case - rxF = rxFbase + frame_parms->first_carrier_offset + 12 * (c_rb + n_BWP_start); - else if ((c_rb + n_BWP_start) > (frame_parms->N_RB_DL >> 1)) - // number of RBs is odd and c_rb is higher than half system bandwidth + 1 - // if these conditions are true the pointer has to be situated at the 1st part of - // the rxdataF just after the first IQ symbols of the RB containing DC - // we point at the 1st part of the rxdataF in symbol - rxF = rxFbase + 12 * (c_rb + n_BWP_start - (frame_parms->N_RB_DL >> 1)) - 6; - } - AssertFatal(rxF, "bug"); - int j = 0; - - for (int i = 0; i < 12; i++) { - if ((i != 1) && (i != 5) && (i != 9)) { - rxF_ext[j] = rxF[i]; - dl_ch0_ext[j] = dl_ch0[i]; - LOG_DSYMB(""); - j++; - } else { - LOG_DSYMB("\t\t <==> DM-RS PDCCH, this is a pilot symbol\n"); - } - } + c16_t *rxF = NULL; + if ((frame_parms->N_RB_DL & 1) == 0) { + if ((c_rb + n_BWP_start) < (frame_parms->N_RB_DL >> 1)) + // if RB to be treated is lower than middle system bandwidth then rxdataF pointed + // at (offset + c_br + symbol * ofdm_symbol_size): even case + rxF = rxFbase + (frame_parms->first_carrier_offset + 12 * c_rb) + n_BWP_start * 12; + else + // number of RBs is even and c_rb is higher than half system bandwidth (we don't skip DC) + // if these conditions are true the pointer has to be situated at the 1st part of the rxdataF + // we point at the 1st part of the rxdataF in symbol + rxF = rxFbase + 12 * (c_rb + n_BWP_start - (frame_parms->N_RB_DL >> 1)); + } else { + if ((c_rb + n_BWP_start) < (frame_parms->N_RB_DL >> 1)) + // if RB to be treated is lower than middle system bandwidth then rxdataF pointed + // at (offset + c_br + symbol * ofdm_symbol_size): odd case + rxF = rxFbase + frame_parms->first_carrier_offset + 12 * (c_rb + n_BWP_start); + else if ((c_rb + n_BWP_start) > (frame_parms->N_RB_DL >> 1)) + // number of RBs is odd and c_rb is higher than half system bandwidth + 1 + // if these conditions are true the pointer has to be situated at the 1st part of + // the rxdataF just after the first IQ symbols of the RB containing DC + // we point at the 1st part of the rxdataF in symbol + rxF = rxFbase + 12 * (c_rb + n_BWP_start - (frame_parms->N_RB_DL >> 1)) - 6; + else + rxF = rxFbase + frame_parms->first_carrier_offset + 12 * (c_rb + n_BWP_start); + } + const int valid_re[NBR_RE_PER_RB_WITHOUT_DMRS] = {0, 2, 3, 4, 6, 7, 8, 10, 11}; + for (int i = 0; i < sizeofArray(valid_re); i++) { + rxF_ext[i] = rxF[valid_re[i]]; + dl_ch0_ext[i] = dl_ch0[valid_re[i]]; + LOG_DSYMB(""); } dl_ch0_ext += NBR_RE_PER_RB_WITHOUT_DMRS; rxF_ext += NBR_RE_PER_RB_WITHOUT_DMRS; - dl_ch0 += 12; + dl_ch0 += NBR_RE_PER_RB_WITH_DMRS; } } } From 2c22f49a456075323d8cfb3d68dccdef191c5773 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Wed, 23 Jul 2025 07:49:37 +0200 Subject: [PATCH 281/964] simplify nr_pdcch_channel_compensation() --- openair1/PHY/NR_UE_TRANSPORT/dci_nr.c | 38 +++++++++++---------------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c index 7dcbbbe969..c5ea4e35a0 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c @@ -352,29 +352,23 @@ void nr_pdcch_channel_compensation(int32_t rx_size, uint32_t coreset_nbr_rb) { for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { - simde__m128i *dl_ch128 = (simde__m128i *)&dl_ch_estimates_ext[aarx][symbol * coreset_nbr_rb * 12]; - simde__m128i *rxdataF128 = (simde__m128i *)&rxdataF_ext[aarx][symbol * coreset_nbr_rb * 12]; - simde__m128i *rxdataF_comp128 = (simde__m128i *)&rxdataF_comp[aarx][symbol * coreset_nbr_rb * 12]; - //printf("ch compensation dl_ch ext addr %p \n", &dl_ch_estimates_ext[(aatx<<1)+aarx][symbol*20*12]); - //printf("rxdataf ext addr %p symbol %d\n", &rxdataF_ext[aarx][symbol*20*12], symbol); - //printf("rxdataf_comp addr %p\n",&rxdataF_comp[(aatx<<1)+aarx][symbol*20*12]); - + const int sz = coreset_nbr_rb * 12; + c16_t *dl_ch = dl_ch_estimates_ext[aarx] + symbol * sz; + c16_t *rxdataF = rxdataF_ext[aarx] + symbol * sz; + c16_t *rxdataF_c = rxdataF_comp[aarx] + symbol * sz; // multiply by conjugated channel - mult_cpx_conj_vector((c16_t *)dl_ch128, (c16_t *)rxdataF128, (c16_t *)rxdataF_comp128, 12 * coreset_nbr_rb, output_shift); - - for (int rb = 0; rb < 12 * coreset_nbr_rb; rb++) { - LOG_DDD("rxdataF128[%d]=(%d,%d) X dlch[%d]=(%d,%d) rxdataF_comp128[%d]=(%d,%d)\n", - rb, - ((c16_t *)rxdataF128)[rb].r, - ((c16_t *)rxdataF128)[rb].i, - rb, - ((c16_t *)dl_ch128)[rb].r, - ((c16_t *)dl_ch128)[rb].i, - rb, - ((c16_t *)rxdataF_comp128)[rb].r, - ((c16_t *)rxdataF_comp128)[rb].i); - - } + mult_cpx_conj_vector(dl_ch, rxdataF, rxdataF_c, sz, output_shift); + for (int rb = 0; rb < sz; rb++) + LOG_DDD("rxdataF[%d]=(%d,%d) X dlch[%d]=(%d,%d) rxdataF_comp[%d]=(%d,%d)\n", + rb, + rxdataF[rb].r, + rxdataF[rb].i, + rb, + dl_ch[rb].r, + dl_ch[rb].i, + rb, + rxdataF_c[rb].r, + rxdataF_c[rb].i); } } From b30da5c0b22476f8567931ddcc0ecbc8e85654f3 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Wed, 23 Jul 2025 07:52:08 +0200 Subject: [PATCH 282/964] reduce size and make local rxdataF_comp in nr_rx_pdcch() --- openair1/PHY/NR_UE_TRANSPORT/dci_nr.c | 87 +++++++++++---------------- 1 file changed, 35 insertions(+), 52 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c index c5ea4e35a0..29f8fdb6b3 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c @@ -44,9 +44,7 @@ #include "assertions.h" #include "T.h" -//#define DEBUG_DCI_DECODING 1 - -//#define NR_PDCCH_DCI_DEBUG // activates NR_PDCCH_DCI_DEBUG logs +// #define NR_PDCCH_DCI_DEBUG // activates NR_PDCCH_DCI_DEBUG logs #ifdef NR_PDCCH_DCI_DEBUG #define LOG_DDD(a, ...) printf("<-NR_PDCCH_DCI_DEBUG (%s)-> " a, __func__, ##__VA_ARGS__ ) #define LOG_DSYMB(b) \ @@ -188,20 +186,23 @@ static void nr_pdcch_demapping_deinterleaving(c16_t *llr, static void nr_pdcch_llr(NR_DL_FRAME_PARMS *frame_parms, int32_t rx_size, - c16_t rxdataF_comp[][rx_size], + uint32_t coreset_nbr_rb, + c16_t rxdataF_comp[coreset_nbr_rb * 12], c16_t *pdcch_llr, - uint8_t symbol, - uint32_t coreset_nbr_rb) + uint8_t symbol) { - c16_t *rxF = &rxdataF_comp[0][(symbol * coreset_nbr_rb * 12)]; - c16_t *pdcch_llrp = &pdcch_llr[symbol * coreset_nbr_rb * 9]; + c16_t *rxF = rxdataF_comp; + c16_t *llr = pdcch_llr + symbol * coreset_nbr_rb * 9; - if (!pdcch_llrp) { + if (!llr) { LOG_E(NR_PHY_DCI, "pdcch_qpsk_llr: llr is null, symbol %d\n", symbol); return; } - LOG_DDD("llr logs: pdcch qpsk llr for symbol %d (pos %d), llr offset %ld\n",symbol,(symbol*frame_parms->N_RB_DL*12),pdcch_llrp-pdcch_llr); + LOG_DDD("llr logs: pdcch qpsk llr for symbol %d (pos %d), llr offset %ld\n", + symbol, + symbol * frame_parms->N_RB_DL * 12, + llr - pdcch_llr); for (int i = 0; i < coreset_nbr_rb * 9; i++) { // We clip the signal @@ -210,10 +211,9 @@ static void nr_pdcch_llr(NR_DL_FRAME_PARMS *frame_parms, res.r = max(-32, res.r); res.i = min(rxF->i, 31); res.i = max(-32, res.i); - *pdcch_llrp = res; - LOG_DDD("llr logs: rb=%d i=%d *rxF:%d => *pdcch_llrp:%d\n",i/18,i,*rxF,*pdcch_llrp); + *llr++ = res; + LOG_DDD("llr logs: rb=%d i=%d rxF:%d,%d => pdcch_llr:%d,%d\n", i / 18, i, rxF->r, rxF->i, llr->r, llr->i); rxF++; - pdcch_llrp++; } } @@ -330,7 +330,6 @@ static void nr_pdcch_extract_rbs_single(uint32_t rxdataF_sz, for (int i = 0; i < sizeofArray(valid_re); i++) { rxF_ext[i] = rxF[valid_re[i]]; dl_ch0_ext[i] = dl_ch0[valid_re[i]]; - LOG_DSYMB(""); } dl_ch0_ext += NBR_RE_PER_RB_WITHOUT_DMRS; rxF_ext += NBR_RE_PER_RB_WITHOUT_DMRS; @@ -339,23 +338,21 @@ static void nr_pdcch_extract_rbs_single(uint32_t rxdataF_sz, } } -#define print_shorts(s,x) printf("%s %d,%d,%d,%d,%d,%d,%d,%d\n",s,(x)[0],(x)[1],(x)[2],(x)[3],(x)[4],(x)[5],(x)[6],(x)[7]) - -void nr_pdcch_channel_compensation(int32_t rx_size, - c16_t rxdataF_ext[][rx_size], - c16_t dl_ch_estimates_ext[][rx_size], - c16_t rxdataF_comp[][rx_size], - int32_t **rho, - NR_DL_FRAME_PARMS *frame_parms, - uint8_t symbol, - uint8_t output_shift, - uint32_t coreset_nbr_rb) +static void nr_pdcch_channel_compensation(int32_t rx_size, + uint32_t coreset_nbr_rb, + c16_t rxdataF_ext[][rx_size], + c16_t dl_ch_estimates_ext[][rx_size], + c16_t rxdataF_comp[][coreset_nbr_rb * 12], + int32_t **rho, + NR_DL_FRAME_PARMS *frame_parms, + uint8_t symbol, + uint8_t output_shift) { for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { const int sz = coreset_nbr_rb * 12; c16_t *dl_ch = dl_ch_estimates_ext[aarx] + symbol * sz; c16_t *rxdataF = rxdataF_ext[aarx] + symbol * sz; - c16_t *rxdataF_c = rxdataF_comp[aarx] + symbol * sz; + c16_t *rxdataF_c = rxdataF_comp[aarx]; // multiply by conjugated channel mult_cpx_conj_vector(dl_ch, rxdataF, rxdataF_c, sz, output_shift); for (int rb = 0; rb < sz; rb++) @@ -375,10 +372,11 @@ void nr_pdcch_channel_compensation(int32_t rx_size, static void nr_pdcch_detection_mrc(NR_DL_FRAME_PARMS *frame_parms, int32_t rx_size, c16_t rxdataF_comp[][rx_size], int symbol) { if (frame_parms->nb_antennas_rx>1) { + LOG_D(NR_PHY_DCI, "we enter nr_pdcch_detection_mrc(frame_parms->nb_antennas_rx=%d)\n", frame_parms->nb_antennas_rx); const int sz = frame_parms->N_RB_DL * 12; - - simde__m128i *rxdataF_comp128_0 = (simde__m128i *)&rxdataF_comp[0][symbol * sz]; - simde__m128i *rxdataF_comp128_1 = (simde__m128i *)&rxdataF_comp[1][symbol * sz]; + + simde__m128i *rxdataF_comp128_0 = (simde__m128i *)rxdataF_comp[0]; + simde__m128i *rxdataF_comp128_1 = (simde__m128i *)rxdataF_comp[1]; // MRC on each re of rb for (int i = 0; i < sz >> 2; i++) { @@ -406,15 +404,10 @@ void nr_rx_pdcch(PHY_VARS_NR_UE *ue, // Pointers to extracted PDCCH symbols in frequency-domain. int32_t rx_size = ((4 * frame_parms->N_RB_DL * 12 + 31) >> 5) << 5; __attribute__((aligned(32))) c16_t rxdataF_ext[frame_parms->nb_antennas_rx][rx_size]; - __attribute__((aligned(32))) c16_t rxdataF_comp[frame_parms->nb_antennas_rx][rx_size]; __attribute__((aligned(32))) c16_t pdcch_dl_ch_estimates_ext[frame_parms->nb_antennas_rx][rx_size]; - - memset(rxdataF_comp, 0, sizeof(rxdataF_comp)); - // Pointer to llrs, 4-bit resolution. int32_t llr_size = 4 * n_rb * 9; c16_t llr[llr_size]; - memset(llr, 0, sizeof(llr)); LOG_D(NR_PHY_DCI, @@ -466,36 +459,26 @@ void nr_rx_pdcch(PHY_VARS_NR_UE *ue, LOG_D(NR_PHY_DCI, "we enter nr_pdcch_channel_compensation(log2_maxh=%d)\n", log2_maxh); LOG_D(NR_PHY_DCI, "in nr_pdcch_channel_compensation(rxdataF_ext x dl_ch_estimates_ext -> rxdataF_comp)\n"); // compute LLRs for ofdm symbol 0 only - nr_pdcch_channel_compensation(rx_size, rxdataF_ext, + __attribute__((aligned(32))) c16_t rxdataF_comp[frame_parms->nb_antennas_rx][n_rb * 12]; + nr_pdcch_channel_compensation(rx_size, + n_rb, + rxdataF_ext, pdcch_dl_ch_estimates_ext, rxdataF_comp, NULL, frame_parms, s, - log2_maxh, - n_rb); // log2_maxh+I0_shift + log2_maxh); // log2_maxh+I0_shift - UEscopeCopy(ue, pdcchRxdataF_comp, rxdataF_comp, sizeof(struct complex16), frame_parms->nb_antennas_rx, rx_size, 0); + UEscopeCopy(ue, pdcchRxdataF_comp, rxdataF_comp, sizeof(struct complex16), frame_parms->nb_antennas_rx, n_rb * 12, 0); - if (frame_parms->nb_antennas_rx > 1) { - LOG_D(NR_PHY_DCI, "we enter nr_pdcch_detection_mrc(frame_parms->nb_antennas_rx=%d)\n", frame_parms->nb_antennas_rx); - nr_pdcch_detection_mrc(frame_parms, rx_size, rxdataF_comp,s); - } + nr_pdcch_detection_mrc(frame_parms, n_rb * 12, rxdataF_comp, s); LOG_D(NR_PHY_DCI, "we enter nr_pdcch_llr(for symbol %d), pdcch_vars[eNB_id]->rxdataF_comp ---> pdcch_vars[eNB_id]->llr \n", s); LOG_D(NR_PHY_DCI, "in nr_pdcch_llr(rxdataF_comp -> llr)\n"); - nr_pdcch_llr(frame_parms, - rx_size, - rxdataF_comp, - llr, - s, - n_rb); + nr_pdcch_llr(frame_parms, rx_size, n_rb, rxdataF_comp[0], llr, s); UEscopeCopy(ue, pdcchLlr, llr, sizeof(c16_t), 1, llr_size, 0); - -#ifdef DEBUG_DCI_DECODING - printf("demapping: slot %u, mi %d\n",slot,get_mi(frame_parms,slot)); -#endif } nr_pdcch_demapping_deinterleaving(llr, From e8f6d14c47f501793e2a70581c6314afada8e743 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Wed, 23 Jul 2025 07:56:33 +0200 Subject: [PATCH 283/964] simplify and make more local variables in nr_rx_pdcch() and fix small bugs (size 9 RE instaed of 12 RE) --- openair1/PHY/NR_UE_TRANSPORT/dci_nr.c | 116 ++++++++++---------------- 1 file changed, 42 insertions(+), 74 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c index 29f8fdb6b3..112739e09b 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c @@ -218,35 +218,29 @@ static void nr_pdcch_llr(NR_DL_FRAME_PARMS *frame_parms, } //compute average channel_level on each (TX,RX) antenna pair -void nr_pdcch_channel_level(int32_t rx_size, - c16_t dl_ch_estimates_ext[][rx_size], - NR_DL_FRAME_PARMS *frame_parms, - int32_t *avg, - int symbol, - int nb_rb) +static int32_t nr_pdcch_channel_level(int nb_rb, c16_t dl_ch_estimates_ext[][nb_rb * 9], int nb_antennas_rx, int symbol) { - for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { - - simde__m128i *dl_ch128 = (simde__m128i *)&dl_ch_estimates_ext[aarx][symbol * nb_rb * 12]; - + int32_t avgs = 0; + for (int aarx = 0; aarx < nb_antennas_rx; aarx++) { + simde__m128i *dl_ch128 = (simde__m128i *)&dl_ch_estimates_ext[aarx]; //compute average level - avg[aarx] = simde_mm_average(dl_ch128, nb_rb * 12, 0, nb_rb * 12); - //LOG_DDD("Channel level : %d\n", avg[aarx]); + int32_t tmp = simde_mm_average(dl_ch128, nb_rb * 9, 0, nb_rb * 9); + avgs = cmax(avgs, tmp); } + return avgs; } // This function will extract the mapped DM-RS PDCCH REs as per 38.211 Section 7.4.1.3.2 (Mapping to physical resources) static void nr_pdcch_extract_rbs_single(uint32_t rxdataF_sz, + uint32_t coreset_nbr_rb, c16_t rxdataF[][rxdataF_sz], int32_t est_size, c16_t dl_ch_estimates[][est_size], - int32_t rx_size, - c16_t rxdataF_ext[][rx_size], - c16_t dl_ch_estimates_ext[][rx_size], + c16_t rxdataF_ext[][coreset_nbr_rb * 9], + c16_t dl_ch_estimates_ext[][coreset_nbr_rb * 9], int symbol, NR_DL_FRAME_PARMS *frame_parms, uint8_t *coreset_freq_dom, - uint32_t coreset_nbr_rb, uint32_t n_BWP_start) { /* @@ -268,11 +262,8 @@ static void nr_pdcch_extract_rbs_single(uint32_t rxdataF_sz, c16_t *rxFbase = rxdataF[aarx] + frame_parms->ofdm_symbol_size * symbol; LOG_DDD("dl_ch0 = &dl_ch_estimates[aarx = (%d)][0]\n", aarx); - const int offset = symbol * coreset_nbr_rb * NBR_RE_PER_RB_WITH_DMRS; - c16_t *dl_ch0_ext = dl_ch_estimates_ext[aarx] + offset; - LOG_DDD("dl_ch0_ext = &dl_ch_estimates_ext[aarx = (%d)][symbol * (frame_parms->N_RB_DL * 9) = (%d)]\n", aarx, offset); - c16_t *rxF_ext = rxdataF_ext[aarx] + offset; - LOG_DDD("rxF_ext = &rxdataF_ext[aarx = (%d)][symbol * (frame_parms->N_RB_DL * 9) = (%d)]\n", aarx, offset); + c16_t *dl_ch0_ext = dl_ch_estimates_ext[aarx]; + c16_t *rxF_ext = rxdataF_ext[aarx]; /* * The following for loop handles treatment of PDCCH contained in table rxdataF (in frequency domain) @@ -338,20 +329,17 @@ static void nr_pdcch_extract_rbs_single(uint32_t rxdataF_sz, } } -static void nr_pdcch_channel_compensation(int32_t rx_size, - uint32_t coreset_nbr_rb, - c16_t rxdataF_ext[][rx_size], - c16_t dl_ch_estimates_ext[][rx_size], +static void nr_pdcch_channel_compensation(uint32_t coreset_nbr_rb, + c16_t rxdataF_ext[][coreset_nbr_rb * 9], + c16_t dl_ch_estimates_ext[][coreset_nbr_rb * 9], c16_t rxdataF_comp[][coreset_nbr_rb * 12], - int32_t **rho, - NR_DL_FRAME_PARMS *frame_parms, - uint8_t symbol, + int antRx, uint8_t output_shift) { - for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { - const int sz = coreset_nbr_rb * 12; - c16_t *dl_ch = dl_ch_estimates_ext[aarx] + symbol * sz; - c16_t *rxdataF = rxdataF_ext[aarx] + symbol * sz; + for (int aarx = 0; aarx < antRx; aarx++) { + const int sz = coreset_nbr_rb * 9; + c16_t *dl_ch = dl_ch_estimates_ext[aarx]; + c16_t *rxdataF = rxdataF_ext[aarx]; c16_t *rxdataF_c = rxdataF_comp[aarx]; // multiply by conjugated channel mult_cpx_conj_vector(dl_ch, rxdataF, rxdataF_c, sz, output_shift); @@ -369,19 +357,18 @@ static void nr_pdcch_channel_compensation(int32_t rx_size, } } -static void nr_pdcch_detection_mrc(NR_DL_FRAME_PARMS *frame_parms, int32_t rx_size, c16_t rxdataF_comp[][rx_size], int symbol) +static void nr_pdcch_detection_mrc(int n_rb, c16_t rxdataF_comp[][n_rb * 9]) { - if (frame_parms->nb_antennas_rx>1) { - LOG_D(NR_PHY_DCI, "we enter nr_pdcch_detection_mrc(frame_parms->nb_antennas_rx=%d)\n", frame_parms->nb_antennas_rx); - const int sz = frame_parms->N_RB_DL * 12; + LOG_D(NR_PHY_DCI, "we enter nr_pdcch_detection_mrc (hard coded 2 antennas)\n"); + const int sz = n_rb * 9; - simde__m128i *rxdataF_comp128_0 = (simde__m128i *)rxdataF_comp[0]; - simde__m128i *rxdataF_comp128_1 = (simde__m128i *)rxdataF_comp[1]; + simde__m128i *rxdataF_comp128_0 = (simde__m128i *)rxdataF_comp[0]; + simde__m128i *rxdataF_comp128_1 = (simde__m128i *)rxdataF_comp[1]; - // MRC on each re of rb - for (int i = 0; i < sz >> 2; i++) { - rxdataF_comp128_0[i] = simde_mm_adds_epi16(simde_mm_srai_epi16(rxdataF_comp128_0[i], 1), simde_mm_srai_epi16(rxdataF_comp128_1[i], 1)); - } + // MRC on each re of rb + for (int i = 0; i < sz >> 2; i++) { + rxdataF_comp128_0[i] = + simde_mm_adds_epi16(simde_mm_srai_epi16(rxdataF_comp128_0[i], 1), simde_mm_srai_epi16(rxdataF_comp128_1[i], 1)); } } @@ -395,16 +382,12 @@ void nr_rx_pdcch(PHY_VARS_NR_UE *ue, { NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; - uint8_t log2_maxh, aarx; - int32_t avgs; - int32_t avgP[4]; int n_rb,rb_offset; get_coreset_rballoc(rel15->coreset.frequency_domain_resource,&n_rb,&rb_offset); + const int antRx = frame_parms->nb_antennas_rx; // Pointers to extracted PDCCH symbols in frequency-domain. int32_t rx_size = ((4 * frame_parms->N_RB_DL * 12 + 31) >> 5) << 5; - __attribute__((aligned(32))) c16_t rxdataF_ext[frame_parms->nb_antennas_rx][rx_size]; - __attribute__((aligned(32))) c16_t pdcch_dl_ch_estimates_ext[frame_parms->nb_antennas_rx][rx_size]; // Pointer to llrs, 4-bit resolution. int32_t llr_size = 4 * n_rb * 9; c16_t llr[llr_size]; @@ -418,61 +401,46 @@ void nr_rx_pdcch(PHY_VARS_NR_UE *ue, for (int s=rel15->coreset.StartSymbolIndex; s<(rel15->coreset.StartSymbolIndex+rel15->coreset.duration); s++) { LOG_D(NR_PHY_DCI, "in nr_pdcch_extract_rbs_single(rxdataF -> rxdataF_ext || dl_ch_estimates -> dl_ch_estimates_ext)\n"); + __attribute__((aligned(32))) c16_t rxdataF_ext[antRx][n_rb * 9]; + __attribute__((aligned(32))) c16_t pdcch_dl_ch_estimates_ext[antRx][n_rb * 9]; nr_pdcch_extract_rbs_single(ue->frame_parms.samples_per_slot_wCP, + n_rb, rxdataF, pdcch_est_size, pdcch_dl_ch_estimates, - rx_size, rxdataF_ext, pdcch_dl_ch_estimates_ext, s, frame_parms, rel15->coreset.frequency_domain_resource, - n_rb, rel15->BWPStart); - LOG_D(NR_PHY_DCI, - "we enter nr_pdcch_channel_level(avgP=%d) => compute channel level based on ofdm symbol 0, " - "pdcch_vars[eNB_id]->dl_ch_estimates_ext\n", - *avgP); LOG_D(NR_PHY_DCI, "in nr_pdcch_channel_level(dl_ch_estimates_ext -> dl_ch_estimates_ext)\n"); // compute channel level based on ofdm symbol 0 - nr_pdcch_channel_level(rx_size, - pdcch_dl_ch_estimates_ext, - frame_parms, - avgP, - s, - n_rb); - avgs = 0; - - for (aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) - avgs = cmax(avgs, avgP[aarx]); - - log2_maxh = (log2_approx(avgs) / 2) + 5; //+frame_parms->nb_antennas_rx; + int32_t avgs = nr_pdcch_channel_level(n_rb, pdcch_dl_ch_estimates_ext, antRx, s); + uint8_t log2_maxh = (log2_approx(avgs) / 2) + 5; //+antRx; #ifdef UE_DEBUG_TRACE LOG_D(NR_PHY_DCI, "slot %d: pdcch log2_maxh = %d (%d,%d)\n", proc->nr_slot_rx, log2_maxh, avgP[0], avgs); #endif #if T_TRACER - T(T_UE_PHY_PDCCH_ENERGY, T_INT(0), T_INT(0), T_INT(proc->frame_rx % 1024), T_INT(proc->nr_slot_rx), T_INT(avgP[0]), T_INT(avgP[1]), T_INT(avgP[2]), T_INT(avgP[3])); + T(T_UE_PHY_PDCCH_ENERGY, T_INT(0), T_INT(0), T_INT(proc->frame_rx % 1024), T_INT(proc->nr_slot_rx), T_INT(avgs)); #endif LOG_D(NR_PHY_DCI, "we enter nr_pdcch_channel_compensation(log2_maxh=%d)\n", log2_maxh); LOG_D(NR_PHY_DCI, "in nr_pdcch_channel_compensation(rxdataF_ext x dl_ch_estimates_ext -> rxdataF_comp)\n"); // compute LLRs for ofdm symbol 0 only - __attribute__((aligned(32))) c16_t rxdataF_comp[frame_parms->nb_antennas_rx][n_rb * 12]; - nr_pdcch_channel_compensation(rx_size, - n_rb, + __attribute__((aligned(32))) c16_t rxdataF_comp[antRx][n_rb * 12]; + nr_pdcch_channel_compensation(n_rb, rxdataF_ext, pdcch_dl_ch_estimates_ext, rxdataF_comp, - NULL, - frame_parms, - s, + antRx, log2_maxh); // log2_maxh+I0_shift - UEscopeCopy(ue, pdcchRxdataF_comp, rxdataF_comp, sizeof(struct complex16), frame_parms->nb_antennas_rx, n_rb * 12, 0); + UEscopeCopy(ue, pdcchRxdataF_comp, rxdataF_comp, sizeof(struct complex16), antRx, n_rb * 12, 0); - nr_pdcch_detection_mrc(frame_parms, n_rb * 12, rxdataF_comp, s); + if (antRx > 1) + nr_pdcch_detection_mrc(n_rb * 12, rxdataF_comp); LOG_D(NR_PHY_DCI, "we enter nr_pdcch_llr(for symbol %d), pdcch_vars[eNB_id]->rxdataF_comp ---> pdcch_vars[eNB_id]->llr \n", s); LOG_D(NR_PHY_DCI, "in nr_pdcch_llr(rxdataF_comp -> llr)\n"); From 19d783f6d983b83e0072f79d43056fc11c4679f4 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Wed, 23 Jul 2025 08:03:48 +0200 Subject: [PATCH 284/964] generalize constant nb re per rn in dci_nr.c --- openair1/PHY/NR_UE_TRANSPORT/dci_nr.c | 80 +++++++++++++-------------- 1 file changed, 39 insertions(+), 41 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c index 112739e09b..5f41880251 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c @@ -61,14 +61,14 @@ #define LOG_DDD(a...) #define LOG_DSYMB(a...) #endif + #define NR_NBR_CORESET_ACT_BWP 3 // The number of CoreSets per BWP is limited to 3 (including initial CORESET: ControlResourceId 0) #define NR_NBR_SEARCHSPACE_ACT_BWP \ 10 // The number of SearSpaces per BWP is limited to 10 (including initial SEARCHSPACE: SearchSpaceId 0) -#ifdef LOG_I -#undef LOG_I -#define LOG_I(A, B...) printf(B) -#endif +#define RE_PER_RB 12 +// after removing the 3 DMRS RE, the RB contains 9 RE with PDCCH +#define RE_PER_RB_OUT_DMRS 9 static void nr_pdcch_demapping_deinterleaving(c16_t *llr, c16_t *e_rx, @@ -168,7 +168,7 @@ static void nr_pdcch_demapping_deinterleaving(c16_t *llr, } int rb_count = 0; - const int data_sc = 9; // 9 sub-carriers with data per PRB + const int data_sc = RE_PER_RB_OUT_DMRS; // 9 sub-carriers with data per PRB for (int c_id = 0; c_id < number_of_candidates; c_id++) { for (int symbol_idx = start_symbol; symbol_idx < start_symbol + coreset_time_dur; symbol_idx++) { for (int cce_count = 0; cce_count < L[c_id]; cce_count++) { @@ -187,12 +187,12 @@ static void nr_pdcch_demapping_deinterleaving(c16_t *llr, static void nr_pdcch_llr(NR_DL_FRAME_PARMS *frame_parms, int32_t rx_size, uint32_t coreset_nbr_rb, - c16_t rxdataF_comp[coreset_nbr_rb * 12], + c16_t rxdataF_comp[coreset_nbr_rb * RE_PER_RB], c16_t *pdcch_llr, uint8_t symbol) { c16_t *rxF = rxdataF_comp; - c16_t *llr = pdcch_llr + symbol * coreset_nbr_rb * 9; + c16_t *llr = pdcch_llr + symbol * coreset_nbr_rb * RE_PER_RB_OUT_DMRS; if (!llr) { LOG_E(NR_PHY_DCI, "pdcch_qpsk_llr: llr is null, symbol %d\n", symbol); @@ -201,10 +201,10 @@ static void nr_pdcch_llr(NR_DL_FRAME_PARMS *frame_parms, LOG_DDD("llr logs: pdcch qpsk llr for symbol %d (pos %d), llr offset %ld\n", symbol, - symbol * frame_parms->N_RB_DL * 12, + symbol * frame_parms->N_RB_DL * RE_PER_RB, llr - pdcch_llr); - for (int i = 0; i < coreset_nbr_rb * 9; i++) { + for (int i = 0; i < coreset_nbr_rb * RE_PER_RB_OUT_DMRS; i++) { // We clip the signal c16_t res; res.r = min(rxF->r, 31); @@ -218,13 +218,16 @@ static void nr_pdcch_llr(NR_DL_FRAME_PARMS *frame_parms, } //compute average channel_level on each (TX,RX) antenna pair -static int32_t nr_pdcch_channel_level(int nb_rb, c16_t dl_ch_estimates_ext[][nb_rb * 9], int nb_antennas_rx, int symbol) +static int32_t nr_pdcch_channel_level(int nb_rb, + c16_t dl_ch_estimates_ext[][nb_rb * RE_PER_RB_OUT_DMRS], + int nb_antennas_rx, + int symbol) { int32_t avgs = 0; for (int aarx = 0; aarx < nb_antennas_rx; aarx++) { simde__m128i *dl_ch128 = (simde__m128i *)&dl_ch_estimates_ext[aarx]; //compute average level - int32_t tmp = simde_mm_average(dl_ch128, nb_rb * 9, 0, nb_rb * 9); + int32_t tmp = simde_mm_average(dl_ch128, nb_rb * RE_PER_RB_OUT_DMRS, 0, nb_rb * RE_PER_RB_OUT_DMRS); avgs = cmax(avgs, tmp); } return avgs; @@ -236,8 +239,8 @@ static void nr_pdcch_extract_rbs_single(uint32_t rxdataF_sz, c16_t rxdataF[][rxdataF_sz], int32_t est_size, c16_t dl_ch_estimates[][est_size], - c16_t rxdataF_ext[][coreset_nbr_rb * 9], - c16_t dl_ch_estimates_ext[][coreset_nbr_rb * 9], + c16_t rxdataF_ext[][coreset_nbr_rb * RE_PER_RB_OUT_DMRS], + c16_t dl_ch_estimates_ext[][coreset_nbr_rb * RE_PER_RB_OUT_DMRS], int symbol, NR_DL_FRAME_PARMS *frame_parms, uint8_t *coreset_freq_dom, @@ -254,9 +257,6 @@ static void nr_pdcch_extract_rbs_single(uint32_t rxdataF_sz, * */ -#define NBR_RE_PER_RB_WITH_DMRS 12 - // after removing the 3 DMRS RE, the RB contains 9 RE with PDCCH -#define NBR_RE_PER_RB_WITHOUT_DMRS 9 for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { const c16_t *dl_ch0 = dl_ch_estimates[aarx] + frame_parms->ofdm_symbol_size * symbol; c16_t *rxFbase = rxdataF[aarx] + frame_parms->ofdm_symbol_size * symbol; @@ -297,47 +297,45 @@ static void nr_pdcch_extract_rbs_single(uint32_t rxdataF_sz, if ((c_rb + n_BWP_start) < (frame_parms->N_RB_DL >> 1)) // if RB to be treated is lower than middle system bandwidth then rxdataF pointed // at (offset + c_br + symbol * ofdm_symbol_size): even case - rxF = rxFbase + (frame_parms->first_carrier_offset + 12 * c_rb) + n_BWP_start * 12; + rxF = rxFbase + (frame_parms->first_carrier_offset + RE_PER_RB * c_rb) + n_BWP_start * RE_PER_RB; else // number of RBs is even and c_rb is higher than half system bandwidth (we don't skip DC) // if these conditions are true the pointer has to be situated at the 1st part of the rxdataF // we point at the 1st part of the rxdataF in symbol - rxF = rxFbase + 12 * (c_rb + n_BWP_start - (frame_parms->N_RB_DL >> 1)); + rxF = rxFbase + RE_PER_RB * (c_rb + n_BWP_start - (frame_parms->N_RB_DL >> 1)); } else { if ((c_rb + n_BWP_start) < (frame_parms->N_RB_DL >> 1)) // if RB to be treated is lower than middle system bandwidth then rxdataF pointed // at (offset + c_br + symbol * ofdm_symbol_size): odd case - rxF = rxFbase + frame_parms->first_carrier_offset + 12 * (c_rb + n_BWP_start); + rxF = rxFbase + frame_parms->first_carrier_offset + RE_PER_RB * (c_rb + n_BWP_start); else if ((c_rb + n_BWP_start) > (frame_parms->N_RB_DL >> 1)) // number of RBs is odd and c_rb is higher than half system bandwidth + 1 // if these conditions are true the pointer has to be situated at the 1st part of // the rxdataF just after the first IQ symbols of the RB containing DC // we point at the 1st part of the rxdataF in symbol - rxF = rxFbase + 12 * (c_rb + n_BWP_start - (frame_parms->N_RB_DL >> 1)) - 6; + rxF = rxFbase + RE_PER_RB * (c_rb + n_BWP_start - (frame_parms->N_RB_DL >> 1)) - 6; else - rxF = rxFbase + frame_parms->first_carrier_offset + 12 * (c_rb + n_BWP_start); + rxF = rxFbase + frame_parms->first_carrier_offset + RE_PER_RB * (c_rb + n_BWP_start); } - const int valid_re[NBR_RE_PER_RB_WITHOUT_DMRS] = {0, 2, 3, 4, 6, 7, 8, 10, 11}; + const int valid_re[RE_PER_RB_OUT_DMRS] = {0, 2, 3, 4, 6, 7, 8, 10, 11}; for (int i = 0; i < sizeofArray(valid_re); i++) { - rxF_ext[i] = rxF[valid_re[i]]; - dl_ch0_ext[i] = dl_ch0[valid_re[i]]; + *rxF_ext++ = rxF[valid_re[i]]; + *dl_ch0_ext++ = dl_ch0[valid_re[i]]; } - dl_ch0_ext += NBR_RE_PER_RB_WITHOUT_DMRS; - rxF_ext += NBR_RE_PER_RB_WITHOUT_DMRS; - dl_ch0 += NBR_RE_PER_RB_WITH_DMRS; + dl_ch0 += RE_PER_RB; } } } static void nr_pdcch_channel_compensation(uint32_t coreset_nbr_rb, - c16_t rxdataF_ext[][coreset_nbr_rb * 9], - c16_t dl_ch_estimates_ext[][coreset_nbr_rb * 9], - c16_t rxdataF_comp[][coreset_nbr_rb * 12], + c16_t rxdataF_ext[][coreset_nbr_rb * RE_PER_RB_OUT_DMRS], + c16_t dl_ch_estimates_ext[][coreset_nbr_rb * RE_PER_RB_OUT_DMRS], + c16_t rxdataF_comp[][coreset_nbr_rb * RE_PER_RB], int antRx, uint8_t output_shift) { for (int aarx = 0; aarx < antRx; aarx++) { - const int sz = coreset_nbr_rb * 9; + const int sz = coreset_nbr_rb * RE_PER_RB_OUT_DMRS; c16_t *dl_ch = dl_ch_estimates_ext[aarx]; c16_t *rxdataF = rxdataF_ext[aarx]; c16_t *rxdataF_c = rxdataF_comp[aarx]; @@ -357,10 +355,10 @@ static void nr_pdcch_channel_compensation(uint32_t coreset_nbr_rb, } } -static void nr_pdcch_detection_mrc(int n_rb, c16_t rxdataF_comp[][n_rb * 9]) +static void nr_pdcch_detection_mrc(int n_rb, c16_t rxdataF_comp[][n_rb * RE_PER_RB_OUT_DMRS]) { LOG_D(NR_PHY_DCI, "we enter nr_pdcch_detection_mrc (hard coded 2 antennas)\n"); - const int sz = n_rb * 9; + const int sz = n_rb * RE_PER_RB_OUT_DMRS; simde__m128i *rxdataF_comp128_0 = (simde__m128i *)rxdataF_comp[0]; simde__m128i *rxdataF_comp128_1 = (simde__m128i *)rxdataF_comp[1]; @@ -387,9 +385,9 @@ void nr_rx_pdcch(PHY_VARS_NR_UE *ue, const int antRx = frame_parms->nb_antennas_rx; // Pointers to extracted PDCCH symbols in frequency-domain. - int32_t rx_size = ((4 * frame_parms->N_RB_DL * 12 + 31) >> 5) << 5; + int32_t rx_size = ((4 * frame_parms->N_RB_DL * RE_PER_RB + 31) >> 5) << 5; // Pointer to llrs, 4-bit resolution. - int32_t llr_size = 4 * n_rb * 9; + int32_t llr_size = 4 * n_rb * RE_PER_RB_OUT_DMRS; c16_t llr[llr_size]; memset(llr, 0, sizeof(llr)); @@ -401,8 +399,8 @@ void nr_rx_pdcch(PHY_VARS_NR_UE *ue, for (int s=rel15->coreset.StartSymbolIndex; s<(rel15->coreset.StartSymbolIndex+rel15->coreset.duration); s++) { LOG_D(NR_PHY_DCI, "in nr_pdcch_extract_rbs_single(rxdataF -> rxdataF_ext || dl_ch_estimates -> dl_ch_estimates_ext)\n"); - __attribute__((aligned(32))) c16_t rxdataF_ext[antRx][n_rb * 9]; - __attribute__((aligned(32))) c16_t pdcch_dl_ch_estimates_ext[antRx][n_rb * 9]; + __attribute__((aligned(32))) c16_t rxdataF_ext[antRx][n_rb * RE_PER_RB_OUT_DMRS]; + __attribute__((aligned(32))) c16_t pdcch_dl_ch_estimates_ext[antRx][n_rb * RE_PER_RB_OUT_DMRS]; nr_pdcch_extract_rbs_single(ue->frame_parms.samples_per_slot_wCP, n_rb, rxdataF, @@ -429,7 +427,7 @@ void nr_rx_pdcch(PHY_VARS_NR_UE *ue, LOG_D(NR_PHY_DCI, "we enter nr_pdcch_channel_compensation(log2_maxh=%d)\n", log2_maxh); LOG_D(NR_PHY_DCI, "in nr_pdcch_channel_compensation(rxdataF_ext x dl_ch_estimates_ext -> rxdataF_comp)\n"); // compute LLRs for ofdm symbol 0 only - __attribute__((aligned(32))) c16_t rxdataF_comp[antRx][n_rb * 12]; + __attribute__((aligned(32))) c16_t rxdataF_comp[antRx][n_rb * RE_PER_RB]; nr_pdcch_channel_compensation(n_rb, rxdataF_ext, pdcch_dl_ch_estimates_ext, @@ -437,10 +435,10 @@ void nr_rx_pdcch(PHY_VARS_NR_UE *ue, antRx, log2_maxh); // log2_maxh+I0_shift - UEscopeCopy(ue, pdcchRxdataF_comp, rxdataF_comp, sizeof(struct complex16), antRx, n_rb * 12, 0); + UEscopeCopy(ue, pdcchRxdataF_comp, rxdataF_comp, sizeof(struct complex16), antRx, n_rb * RE_PER_RB, 0); if (antRx > 1) - nr_pdcch_detection_mrc(n_rb * 12, rxdataF_comp); + nr_pdcch_detection_mrc(n_rb * RE_PER_RB, rxdataF_comp); LOG_D(NR_PHY_DCI, "we enter nr_pdcch_llr(for symbol %d), pdcch_vars[eNB_id]->rxdataF_comp ---> pdcch_vars[eNB_id]->llr \n", s); LOG_D(NR_PHY_DCI, "in nr_pdcch_llr(rxdataF_comp -> llr)\n"); @@ -572,6 +570,6 @@ void nr_dci_decoding_procedure(PHY_VARS_NR_UE *ue, rel15->dci_format_options[k]); } } - e_rx_cand_idx += 9 * L * 6; // e_rx index for next candidate (L CCEs, 6 REGs per CCE and 9 REs per REG ) + e_rx_cand_idx += RE_PER_RB_OUT_DMRS * L * 6; // e_rx index for next candidate (L CCEs, 6 REGs per CCE and 9 REs per REG ) } } From b41c9e2e851e17683dfdd8b1879c017088049b87 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Tue, 22 Jul 2025 19:35:51 +0200 Subject: [PATCH 285/964] move static some functions that are used only in one file --- openair2/LAYER2/NR_MAC_UE/config_ue.c | 2 +- openair2/LAYER2/NR_MAC_UE/mac_proto.h | 49 +--------- .../NR_MAC_UE/nr_ue_dci_configuration.c | 10 +- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 98 +++++++++++++------ openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 10 +- 5 files changed, 80 insertions(+), 89 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index 297be42261..dc01be2f98 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -548,7 +548,7 @@ static void config_common_ue(NR_UE_MAC_INST_t *mac, NR_ServingCellConfigCommon_t } } -void release_common_ss_cset(NR_BWP_PDCCH_t *pdcch) +static void release_common_ss_cset(NR_BWP_PDCCH_t *pdcch) { pdcch->otherSI_SS_id = -1; pdcch->ra_SS_id = -1; diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index aacbbdcab2..29c1d7c51b 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -59,8 +59,6 @@ void nr_ue_mac_default_configs(NR_UE_MAC_INST_t *mac); void nr_ue_decode_mib(NR_UE_MAC_INST_t *mac, int cc_id); -void release_common_ss_cset(NR_BWP_PDCCH_t *pdcch); - /**\brief decode SIB1 and other SIs pdus in NR_UE, from if_module dl_ind \param mac pointer to MAC instance \param cc_id component carrier id @@ -117,12 +115,6 @@ void nr_ue_dl_scheduler(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_info csi_payload_t nr_ue_aperiodic_csi_reporting(NR_UE_MAC_INST_t *mac, dci_field_t csi_request, int tda, long *K2); -/*! \fn int8_t nr_ue_get_SR(NR_UE_MAC_INST_t *mac, frame_t frame, slot_t slot, NR_SchedulingRequestId_t sr_id); - \brief This function schedules a positive or negative SR for schedulingRequestID sr_id - depending on the presence of any active SR and the prohibit timer. - If the max number of retransmissions is reached, it triggers a new RA */ -int8_t nr_ue_get_SR(NR_UE_MAC_INST_t *mac, frame_t frame, slot_t slot, NR_SchedulingRequestId_t sr_id); - nr_dci_format_t nr_ue_process_dci_indication_pdu(NR_UE_MAC_INST_t *mac, frame_t frame, int slot, fapi_nr_dci_indication_pdu_t *dci); int8_t nr_ue_process_csirs_measurements(NR_UE_MAC_INST_t *mac, @@ -138,30 +130,11 @@ bool trigger_periodic_scheduling_request(NR_UE_MAC_INST_t *mac, int nr_get_csi_measurements(NR_UE_MAC_INST_t *mac, frame_t frame, int slot, PUCCH_sched_t *pucch); -csi_payload_t get_ssb_rsrp_payload(NR_UE_MAC_INST_t *mac, - struct NR_CSI_ReportConfig *csi_reportconfig, - NR_CSI_ResourceConfigId_t csi_ResourceConfigId, - NR_CSI_MeasConfig_t *csi_MeasConfig); - -csi_payload_t get_csirs_RI_PMI_CQI_payload(NR_UE_MAC_INST_t *mac, - struct NR_CSI_ReportConfig *csi_reportconfig, - NR_CSI_ResourceConfigId_t csi_ResourceConfigId, - NR_CSI_MeasConfig_t *csi_MeasConfig, - CSI_mapping_t mapping_type); - -csi_payload_t get_csirs_RSRP_payload(NR_UE_MAC_INST_t *mac, - struct NR_CSI_ReportConfig *csi_reportconfig, - NR_CSI_ResourceConfigId_t csi_ResourceConfigId, - const NR_CSI_MeasConfig_t *csi_MeasConfig); - csi_payload_t nr_get_csi_payload(NR_UE_MAC_INST_t *mac, int csi_report_id, CSI_mapping_t mapping_type, NR_CSI_MeasConfig_t *csi_MeasConfig); -uint8_t get_rsrp_index(int rsrp); -uint8_t get_rsrp_diff_index(int best_rsrp,int current_rsrp); - /* \brief Get payload (MAC PDU) from UE PHY @param dl_info pointer to dl indication @param ul_time_alignment pointer to timing advance parameters @@ -170,8 +143,6 @@ uint8_t get_rsrp_diff_index(int best_rsrp,int current_rsrp); */ void nr_ue_send_sdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_info, int pdu_id); -void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac,nr_downlink_indication_t *dl_info, int pdu_id); - typedef struct { union { NR_BSR_SHORT s; @@ -187,28 +158,12 @@ int nr_write_ce_ulsch_pdu(uint8_t *mac_ce, const type_bsr_t *bsr, uint8_t *mac_ce_end); -void config_dci_pdu(NR_UE_MAC_INST_t *mac, - fapi_nr_dl_config_request_t *dl_config, - const int rnti_type, - const int slot, - const NR_SearchSpace_t *ss); - void ue_dci_configuration(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_request_t *dl_config, const frame_t frame, const int slot); void set_precoding_information_parameters(nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu, int n_antenna_port, long transformPrecoder, int precoding_information, NR_PUSCH_Config_t *pusch_Config); -void set_harq_status(NR_UE_MAC_INST_t *mac, - uint8_t pucch_id, - uint8_t harq_id, - int8_t delta_pucch, - uint16_t data_toul_fb, - uint8_t dai, - int n_CCE, - int N_CCE, - frame_t frame, - int slot); bool get_downlink_ack(NR_UE_MAC_INST_t *mac, frame_t frame, int slot, PUCCH_sched_t *pucch); initial_pucch_resource_t get_initial_pucch_resource(const int idx); @@ -285,9 +240,7 @@ and fills the PRACH PDU per each FD occasion. @param slotP Slot index @returns void */ -void nr_ue_pucch_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, int slotP); -void nr_schedule_csirs_reception(NR_UE_MAC_INST_t *mac, int frame, int slot); -void nr_schedule_csi_for_im(NR_UE_MAC_INST_t *mac, int frame, int slot); + void configure_csi_resource_mapping(fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu, NR_CSI_RS_ResourceMapping_t *resourceMapping, uint32_t bwp_size, diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c index 7a2e9c6ed9..388b28f846 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c @@ -104,11 +104,11 @@ NR_ControlResourceSet_t *ue_get_coreset(const NR_BWP_PDCCH_t *config, const int return coreset; } -void config_dci_pdu(NR_UE_MAC_INST_t *mac, - fapi_nr_dl_config_request_t *dl_config, - const int rnti_type, - const int slot, - const NR_SearchSpace_t *ss) +static void config_dci_pdu(NR_UE_MAC_INST_t *mac, + fapi_nr_dl_config_request_t *dl_config, + const int rnti_type, + const int slot, + const NR_SearchSpace_t *ss) { const NR_UE_DL_BWP_t *current_DL_BWP = mac->current_DL_BWP; const NR_UE_UL_BWP_t *current_UL_BWP = mac->current_UL_BWP; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 8a892557b2..e623900f29 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -113,6 +113,43 @@ random-access procedure */ static void nr_ue_process_rar(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_info, int pdu_id); +/*! \fn int8_t nr_ue_get_SR(NR_UE_MAC_INST_t *mac, frame_t frame, slot_t slot, NR_SchedulingRequestId_t sr_id); + \brief This function schedules a positive or negative SR for schedulingRequestID sr_id + depending on the presence of any active SR and the prohibit timer. + If the max number of retransmissions is reached, it triggers a new RA */ +static int8_t nr_ue_get_SR(NR_UE_MAC_INST_t *mac, frame_t frame, slot_t slot, NR_SchedulingRequestId_t sr_id); + +static csi_payload_t get_ssb_rsrp_payload(NR_UE_MAC_INST_t *mac, + struct NR_CSI_ReportConfig *csi_reportconfig, + NR_CSI_ResourceConfigId_t csi_ResourceConfigId, + NR_CSI_MeasConfig_t *csi_MeasConfig); + +static csi_payload_t get_csirs_RI_PMI_CQI_payload(NR_UE_MAC_INST_t *mac, + struct NR_CSI_ReportConfig *csi_reportconfig, + NR_CSI_ResourceConfigId_t csi_ResourceConfigId, + NR_CSI_MeasConfig_t *csi_MeasConfig, + CSI_mapping_t mapping_type); +static csi_payload_t get_csirs_RSRP_payload(NR_UE_MAC_INST_t *mac, + struct NR_CSI_ReportConfig *csi_reportconfig, + NR_CSI_ResourceConfigId_t csi_ResourceConfigId, + const NR_CSI_MeasConfig_t *csi_MeasConfig); +static uint8_t get_rsrp_index(int rsrp); + +static uint8_t get_rsrp_diff_index(int best_rsrp, int current_rsrp); + +static void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_info, int pdu_id); + +static void set_harq_status(NR_UE_MAC_INST_t *mac, + uint8_t pucch_id, + uint8_t harq_id, + int8_t delta_pucch, + uint16_t data_toul_fb, + uint8_t dai, + int n_CCE, + int N_CCE, + frame_t frame, + int slot); + int get_pucch0_mcs(const int O_ACK, const int O_SR, const int ack_payload, const int sr_payload) { int mcs = 0; @@ -1442,16 +1479,16 @@ int8_t nr_ue_process_csirs_measurements(NR_UE_MAC_INST_t *mac, return 0; } -void set_harq_status(NR_UE_MAC_INST_t *mac, - uint8_t pucch_id, - uint8_t harq_id, - int8_t delta_pucch, - uint16_t data_toul_fb, - uint8_t dai, - int n_CCE, - int N_CCE, - frame_t frame, - int slot) +static void set_harq_status(NR_UE_MAC_INST_t *mac, + uint8_t pucch_id, + uint8_t harq_id, + int8_t delta_pucch, + uint16_t data_toul_fb, + uint8_t dai, + int n_CCE, + int N_CCE, + frame_t frame, + int slot) { NR_UE_DL_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[harq_id]; current_harq->active = true; @@ -2527,7 +2564,7 @@ bool trigger_periodic_scheduling_request(NR_UE_MAC_INST_t *mac, PUCCH_sched_t *p return sr_count > 0; } -int8_t nr_ue_get_SR(NR_UE_MAC_INST_t *mac, frame_t frame, slot_t slot, NR_SchedulingRequestId_t sr_id) +static int8_t nr_ue_get_SR(NR_UE_MAC_INST_t *mac, frame_t frame, slot_t slot, NR_SchedulingRequestId_t sr_id) { // no UL-SCH resources available for this tti && UE has a valid PUCCH resources for SR configuration for this tti NR_UE_SCHEDULING_INFO *si = &mac->scheduling_info; @@ -2811,11 +2848,10 @@ csi_payload_t nr_get_csi_payload(NR_UE_MAC_INST_t *mac, return csi; } - -csi_payload_t get_ssb_rsrp_payload(NR_UE_MAC_INST_t *mac, - struct NR_CSI_ReportConfig *csi_reportconfig, - NR_CSI_ResourceConfigId_t csi_ResourceConfigId, - NR_CSI_MeasConfig_t *csi_MeasConfig) +static csi_payload_t get_ssb_rsrp_payload(NR_UE_MAC_INST_t *mac, + struct NR_CSI_ReportConfig *csi_reportconfig, + NR_CSI_ResourceConfigId_t csi_ResourceConfigId, + NR_CSI_MeasConfig_t *csi_MeasConfig) { int nb_ssb = 0; // nb of ssb in the resource int nb_meas = 0; // nb of ssb to report measurements on @@ -2892,11 +2928,11 @@ csi_payload_t get_ssb_rsrp_payload(NR_UE_MAC_INST_t *mac, return csi; } -csi_payload_t get_csirs_RI_PMI_CQI_payload(NR_UE_MAC_INST_t *mac, - struct NR_CSI_ReportConfig *csi_reportconfig, - NR_CSI_ResourceConfigId_t csi_ResourceConfigId, - NR_CSI_MeasConfig_t *csi_MeasConfig, - CSI_mapping_t mapping_type) +static csi_payload_t get_csirs_RI_PMI_CQI_payload(NR_UE_MAC_INST_t *mac, + struct NR_CSI_ReportConfig *csi_reportconfig, + NR_CSI_ResourceConfigId_t csi_ResourceConfigId, + NR_CSI_MeasConfig_t *csi_MeasConfig, + CSI_mapping_t mapping_type) { int p1_bits = 0; int p2_bits = 0; @@ -2980,10 +3016,10 @@ csi_payload_t get_csirs_RI_PMI_CQI_payload(NR_UE_MAC_INST_t *mac, return csi; } -csi_payload_t get_csirs_RSRP_payload(NR_UE_MAC_INST_t *mac, - struct NR_CSI_ReportConfig *csi_reportconfig, - NR_CSI_ResourceConfigId_t csi_ResourceConfigId, - const NR_CSI_MeasConfig_t *csi_MeasConfig) +static csi_payload_t get_csirs_RSRP_payload(NR_UE_MAC_INST_t *mac, + struct NR_CSI_ReportConfig *csi_reportconfig, + NR_CSI_ResourceConfigId_t csi_ResourceConfigId, + const NR_CSI_MeasConfig_t *csi_MeasConfig) { int n_bits = 0; uint64_t temp_payload = 0; @@ -3047,8 +3083,8 @@ csi_payload_t get_csirs_RSRP_payload(NR_UE_MAC_INST_t *mac, // returns index from RSRP // according to Table 10.1.6.1-1 in 38.133 -uint8_t get_rsrp_index(int rsrp) { - +static uint8_t get_rsrp_index(int rsrp) +{ int index = rsrp + 157; if (rsrp>-44) index = 113; @@ -3058,17 +3094,15 @@ uint8_t get_rsrp_index(int rsrp) { return index; } - // returns index from differential RSRP // according to Table 10.1.6.1-2 in 38.133 -uint8_t get_rsrp_diff_index(int best_rsrp,int current_rsrp) { - +static uint8_t get_rsrp_diff_index(int best_rsrp, int current_rsrp) +{ int diff = best_rsrp-current_rsrp; if (diff>30) return 15; else return (diff>>1); - } void nr_ue_send_sdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_info, int pdu_id) @@ -3697,7 +3731,7 @@ static int nr_ue_validate_successrar(uint8_t *pduP, // F: lenght of L is 0:8 or 1:16 bits wide // R: Reserved bit, set to zero. //////////////////////////////// -void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_info, int pdu_id) +static void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_info, int pdu_id) { frame_t frameP = dl_info->frame; int slot = dl_info->slot; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 6c257bcacf..3e90445aa3 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -78,6 +78,10 @@ static uint8_t nr_ue_get_sdu(NR_UE_MAC_INST_t *mac, int P_MAX, bool *BSRsent); +static void nr_ue_pucch_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, int slotP); +static void nr_schedule_csirs_reception(NR_UE_MAC_INST_t *mac, int frame, int slot); +static void nr_schedule_csi_for_im(NR_UE_MAC_INST_t *mac, int frame, int slot); + static void clear_ul_config_request(NR_UE_MAC_INST_t *mac) { int slots = mac->frame_structure.numb_slots_frame; @@ -1709,7 +1713,7 @@ static bool schedule_uci_on_pusch(NR_UE_MAC_INST_t *mac, return mux_done; } -void nr_ue_pucch_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, int slotP) +static void nr_ue_pucch_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, int slotP) { PUCCH_sched_t pucch[3] = {0}; // TODO the size might change in the future in case of multiple SR or multiple CSI in a slot @@ -1784,7 +1788,7 @@ void nr_ue_pucch_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, int slotP) } } -void nr_schedule_csi_for_im(NR_UE_MAC_INST_t *mac, int frame, int slot) +static void nr_schedule_csi_for_im(NR_UE_MAC_INST_t *mac, int frame, int slot) { if (!mac->sc_info.csi_MeasConfig) return; @@ -2025,7 +2029,7 @@ void configure_csi_resource_mapping(fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_c } } -void nr_schedule_csirs_reception(NR_UE_MAC_INST_t *mac, int frame, int slot) +static void nr_schedule_csirs_reception(NR_UE_MAC_INST_t *mac, int frame, int slot) { if (!mac->sc_info.csi_MeasConfig) return; From 343b983aa99d8526bbdc7a1e42822f5eeccd36c9 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Wed, 23 Jul 2025 08:23:26 +0200 Subject: [PATCH 286/964] fix SIMD tail length in nr_pdcch_detection_mrc() and replace >> operator by / --- openair1/PHY/NR_UE_TRANSPORT/dci_nr.c | 30 +++++++++++++-------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c index 5f41880251..9449ee3084 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c @@ -185,7 +185,6 @@ static void nr_pdcch_demapping_deinterleaving(c16_t *llr, } static void nr_pdcch_llr(NR_DL_FRAME_PARMS *frame_parms, - int32_t rx_size, uint32_t coreset_nbr_rb, c16_t rxdataF_comp[coreset_nbr_rb * RE_PER_RB], c16_t *pdcch_llr, @@ -288,13 +287,13 @@ static void nr_pdcch_extract_rbs_single(uint32_t rxdataF_sz, int c_rb_by6 = c_rb / 6; // skip zeros in frequency domain bitmap - while ((coreset_freq_dom[c_rb_by6 >> 3] & (1 << (7 - (c_rb_by6 & 7)))) == 0) { + while ((coreset_freq_dom[c_rb_by6 / 8] & (1 << (7 - (c_rb_by6 & 7)))) == 0) { c_rb += 6; c_rb_by6 = c_rb / 6; } c16_t *rxF = NULL; if ((frame_parms->N_RB_DL & 1) == 0) { - if ((c_rb + n_BWP_start) < (frame_parms->N_RB_DL >> 1)) + if ((c_rb + n_BWP_start) < frame_parms->N_RB_DL / 2) // if RB to be treated is lower than middle system bandwidth then rxdataF pointed // at (offset + c_br + symbol * ofdm_symbol_size): even case rxF = rxFbase + (frame_parms->first_carrier_offset + RE_PER_RB * c_rb) + n_BWP_start * RE_PER_RB; @@ -302,18 +301,18 @@ static void nr_pdcch_extract_rbs_single(uint32_t rxdataF_sz, // number of RBs is even and c_rb is higher than half system bandwidth (we don't skip DC) // if these conditions are true the pointer has to be situated at the 1st part of the rxdataF // we point at the 1st part of the rxdataF in symbol - rxF = rxFbase + RE_PER_RB * (c_rb + n_BWP_start - (frame_parms->N_RB_DL >> 1)); + rxF = rxFbase + RE_PER_RB * (c_rb + n_BWP_start - frame_parms->N_RB_DL / 2); } else { - if ((c_rb + n_BWP_start) < (frame_parms->N_RB_DL >> 1)) + if ((c_rb + n_BWP_start) < frame_parms->N_RB_DL / 2) // if RB to be treated is lower than middle system bandwidth then rxdataF pointed // at (offset + c_br + symbol * ofdm_symbol_size): odd case rxF = rxFbase + frame_parms->first_carrier_offset + RE_PER_RB * (c_rb + n_BWP_start); - else if ((c_rb + n_BWP_start) > (frame_parms->N_RB_DL >> 1)) + else if ((c_rb + n_BWP_start) > frame_parms->N_RB_DL / 2) // number of RBs is odd and c_rb is higher than half system bandwidth + 1 // if these conditions are true the pointer has to be situated at the 1st part of // the rxdataF just after the first IQ symbols of the RB containing DC // we point at the 1st part of the rxdataF in symbol - rxF = rxFbase + RE_PER_RB * (c_rb + n_BWP_start - (frame_parms->N_RB_DL >> 1)) - 6; + rxF = rxFbase + RE_PER_RB * (c_rb + n_BWP_start - frame_parms->N_RB_DL / 2) - 6; else rxF = rxFbase + frame_parms->first_carrier_offset + RE_PER_RB * (c_rb + n_BWP_start); } @@ -360,14 +359,17 @@ static void nr_pdcch_detection_mrc(int n_rb, c16_t rxdataF_comp[][n_rb * RE_PER_ LOG_D(NR_PHY_DCI, "we enter nr_pdcch_detection_mrc (hard coded 2 antennas)\n"); const int sz = n_rb * RE_PER_RB_OUT_DMRS; - simde__m128i *rxdataF_comp128_0 = (simde__m128i *)rxdataF_comp[0]; - simde__m128i *rxdataF_comp128_1 = (simde__m128i *)rxdataF_comp[1]; + c16_t *rx0 = rxdataF_comp[0]; + c16_t *rx1 = rxdataF_comp[1]; // MRC on each re of rb - for (int i = 0; i < sz >> 2; i++) { - rxdataF_comp128_0[i] = - simde_mm_adds_epi16(simde_mm_srai_epi16(rxdataF_comp128_0[i], 1), simde_mm_srai_epi16(rxdataF_comp128_1[i], 1)); + int i = 0; + for (; i < (sz & ~3); i += 4) { + *(simde__m128i *)(rx0 + i) = + simde_mm_adds_epi16(simde_mm_srai_epi16(*(simde__m128i *)(rx0 + i), 1), simde_mm_srai_epi16(*(simde__m128i *)(rx1 + i), 1)); } + for (; i < sz; i++) + rx0[i] = (c16_t){(rx0[i].r + rx1[i].r) / 2, (rx0[i].i + rx1[i].i) / 2}; } void nr_rx_pdcch(PHY_VARS_NR_UE *ue, @@ -384,8 +386,6 @@ void nr_rx_pdcch(PHY_VARS_NR_UE *ue, get_coreset_rballoc(rel15->coreset.frequency_domain_resource,&n_rb,&rb_offset); const int antRx = frame_parms->nb_antennas_rx; - // Pointers to extracted PDCCH symbols in frequency-domain. - int32_t rx_size = ((4 * frame_parms->N_RB_DL * RE_PER_RB + 31) >> 5) << 5; // Pointer to llrs, 4-bit resolution. int32_t llr_size = 4 * n_rb * RE_PER_RB_OUT_DMRS; c16_t llr[llr_size]; @@ -442,7 +442,7 @@ void nr_rx_pdcch(PHY_VARS_NR_UE *ue, LOG_D(NR_PHY_DCI, "we enter nr_pdcch_llr(for symbol %d), pdcch_vars[eNB_id]->rxdataF_comp ---> pdcch_vars[eNB_id]->llr \n", s); LOG_D(NR_PHY_DCI, "in nr_pdcch_llr(rxdataF_comp -> llr)\n"); - nr_pdcch_llr(frame_parms, rx_size, n_rb, rxdataF_comp[0], llr, s); + nr_pdcch_llr(frame_parms, n_rb, rxdataF_comp[0], llr, s); UEscopeCopy(ue, pdcchLlr, llr, sizeof(c16_t), 1, llr_size, 0); } From 8f16b02b2495bfd3245820493a8ec18960f11995 Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 24 Jul 2025 18:03:37 +0200 Subject: [PATCH 287/964] fix tun_if.c warning: specified bound 16 equals destination size --- common/utils/tun_if.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/utils/tun_if.c b/common/utils/tun_if.c index 4bb1f7ec58..f74ab3c7f2 100644 --- a/common/utils/tun_if.c +++ b/common/utils/tun_if.c @@ -120,7 +120,7 @@ static bool setInterfaceParameter(int sock_fd, const char *ifn, int af, const ch { DevAssert(af == AF_INET || af == AF_INET6); struct ifreq ifr = {0}; - strncpy(ifr.ifr_name, ifn, sizeof(ifr.ifr_name)); + strncpy(ifr.ifr_name, ifn, sizeof(ifr.ifr_name) - 1); struct in6_ifreq ifr6 = {0}; void *ioctl_opt = NULL; @@ -167,7 +167,7 @@ static bool change_interface_state(int sock_fd, const char *ifn, if_action_t if_ const char *action = if_action == INTERFACE_DOWN ? "DOWN" : "UP"; struct ifreq ifr = {0}; - strncpy(ifr.ifr_name, ifn, sizeof(ifr.ifr_name)); + strncpy(ifr.ifr_name, ifn, sizeof(ifr.ifr_name) - 1); /* get flags of this interface: see netdevice(7) */ bool success = ioctl(sock_fd, SIOCGIFFLAGS, (caddr_t)&ifr) == 0; From f835705dd143286abbbb2178cba3d87ed88da083 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Fri, 25 Jul 2025 14:59:05 +0200 Subject: [PATCH 288/964] fix array sizes and aligment issues in 5G UE dci decoder --- openair1/PHY/NR_UE_TRANSPORT/dci_nr.c | 112 ++++++++------------------ 1 file changed, 35 insertions(+), 77 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c index 9449ee3084..bf2d91bdc8 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c @@ -184,26 +184,9 @@ static void nr_pdcch_demapping_deinterleaving(c16_t *llr, } } -static void nr_pdcch_llr(NR_DL_FRAME_PARMS *frame_parms, - uint32_t coreset_nbr_rb, - c16_t rxdataF_comp[coreset_nbr_rb * RE_PER_RB], - c16_t *pdcch_llr, - uint8_t symbol) +static void nr_pdcch_llr(uint32_t sz, c16_t *rxF, c16_t *llr) { - c16_t *rxF = rxdataF_comp; - c16_t *llr = pdcch_llr + symbol * coreset_nbr_rb * RE_PER_RB_OUT_DMRS; - - if (!llr) { - LOG_E(NR_PHY_DCI, "pdcch_qpsk_llr: llr is null, symbol %d\n", symbol); - return; - } - - LOG_DDD("llr logs: pdcch qpsk llr for symbol %d (pos %d), llr offset %ld\n", - symbol, - symbol * frame_parms->N_RB_DL * RE_PER_RB, - llr - pdcch_llr); - - for (int i = 0; i < coreset_nbr_rb * RE_PER_RB_OUT_DMRS; i++) { + for (int i = 0; i < sz; i++) { // We clip the signal c16_t res; res.r = min(rxF->r, 31); @@ -217,16 +200,14 @@ static void nr_pdcch_llr(NR_DL_FRAME_PARMS *frame_parms, } //compute average channel_level on each (TX,RX) antenna pair -static int32_t nr_pdcch_channel_level(int nb_rb, - c16_t dl_ch_estimates_ext[][nb_rb * RE_PER_RB_OUT_DMRS], - int nb_antennas_rx, - int symbol) +static int32_t nr_pdcch_channel_level(int nb_re, int arraySz, c16_t dl_ch_estimates_ext[][arraySz], int nb_antennas_rx) { int32_t avgs = 0; for (int aarx = 0; aarx < nb_antennas_rx; aarx++) { simde__m128i *dl_ch128 = (simde__m128i *)&dl_ch_estimates_ext[aarx]; - //compute average level - int32_t tmp = simde_mm_average(dl_ch128, nb_rb * RE_PER_RB_OUT_DMRS, 0, nb_rb * RE_PER_RB_OUT_DMRS); + // compute average level + // if nb_re is not %4, some samples are missed inside simde_mm_average, so let's discard it + int32_t tmp = simde_mm_average(dl_ch128, nb_re & ~3, 0, nb_re & ~3); avgs = cmax(avgs, tmp); } return avgs; @@ -238,8 +219,9 @@ static void nr_pdcch_extract_rbs_single(uint32_t rxdataF_sz, c16_t rxdataF[][rxdataF_sz], int32_t est_size, c16_t dl_ch_estimates[][est_size], - c16_t rxdataF_ext[][coreset_nbr_rb * RE_PER_RB_OUT_DMRS], - c16_t dl_ch_estimates_ext[][coreset_nbr_rb * RE_PER_RB_OUT_DMRS], + int arraySz, + c16_t rxdataF_ext[][arraySz], + c16_t dl_ch_estimates_ext[][arraySz], int symbol, NR_DL_FRAME_PARMS *frame_parms, uint8_t *coreset_freq_dom, @@ -296,25 +278,23 @@ static void nr_pdcch_extract_rbs_single(uint32_t rxdataF_sz, if ((c_rb + n_BWP_start) < frame_parms->N_RB_DL / 2) // if RB to be treated is lower than middle system bandwidth then rxdataF pointed // at (offset + c_br + symbol * ofdm_symbol_size): even case - rxF = rxFbase + (frame_parms->first_carrier_offset + RE_PER_RB * c_rb) + n_BWP_start * RE_PER_RB; + rxF = rxFbase + frame_parms->first_carrier_offset + RE_PER_RB * (c_rb + n_BWP_start); else // number of RBs is even and c_rb is higher than half system bandwidth (we don't skip DC) // if these conditions are true the pointer has to be situated at the 1st part of the rxdataF // we point at the 1st part of the rxdataF in symbol rxF = rxFbase + RE_PER_RB * (c_rb + n_BWP_start - frame_parms->N_RB_DL / 2); } else { - if ((c_rb + n_BWP_start) < frame_parms->N_RB_DL / 2) + if ((c_rb + n_BWP_start) <= frame_parms->N_RB_DL / 2) // if RB to be treated is lower than middle system bandwidth then rxdataF pointed // at (offset + c_br + symbol * ofdm_symbol_size): odd case rxF = rxFbase + frame_parms->first_carrier_offset + RE_PER_RB * (c_rb + n_BWP_start); - else if ((c_rb + n_BWP_start) > frame_parms->N_RB_DL / 2) - // number of RBs is odd and c_rb is higher than half system bandwidth + 1 + else + // number of RBs is odd and c_rb is higher than half system bandwidth + 1 // if these conditions are true the pointer has to be situated at the 1st part of // the rxdataF just after the first IQ symbols of the RB containing DC // we point at the 1st part of the rxdataF in symbol rxF = rxFbase + RE_PER_RB * (c_rb + n_BWP_start - frame_parms->N_RB_DL / 2) - 6; - else - rxF = rxFbase + frame_parms->first_carrier_offset + RE_PER_RB * (c_rb + n_BWP_start); } const int valid_re[RE_PER_RB_OUT_DMRS] = {0, 2, 3, 4, 6, 7, 8, 10, 11}; for (int i = 0; i < sizeofArray(valid_re); i++) { @@ -326,50 +306,31 @@ static void nr_pdcch_extract_rbs_single(uint32_t rxdataF_sz, } } -static void nr_pdcch_channel_compensation(uint32_t coreset_nbr_rb, - c16_t rxdataF_ext[][coreset_nbr_rb * RE_PER_RB_OUT_DMRS], - c16_t dl_ch_estimates_ext[][coreset_nbr_rb * RE_PER_RB_OUT_DMRS], - c16_t rxdataF_comp[][coreset_nbr_rb * RE_PER_RB], +static void nr_pdcch_channel_compensation(int arraySz, + c16_t rxdataF_ext[][arraySz], + c16_t dl_ch_estimates_ext[][arraySz], + c16_t rxdataF_comp[][arraySz], int antRx, uint8_t output_shift) { for (int aarx = 0; aarx < antRx; aarx++) { - const int sz = coreset_nbr_rb * RE_PER_RB_OUT_DMRS; - c16_t *dl_ch = dl_ch_estimates_ext[aarx]; - c16_t *rxdataF = rxdataF_ext[aarx]; - c16_t *rxdataF_c = rxdataF_comp[aarx]; - // multiply by conjugated channel - mult_cpx_conj_vector(dl_ch, rxdataF, rxdataF_c, sz, output_shift); - for (int rb = 0; rb < sz; rb++) - LOG_DDD("rxdataF[%d]=(%d,%d) X dlch[%d]=(%d,%d) rxdataF_comp[%d]=(%d,%d)\n", - rb, - rxdataF[rb].r, - rxdataF[rb].i, - rb, - dl_ch[rb].r, - dl_ch[rb].i, - rb, - rxdataF_c[rb].r, - rxdataF_c[rb].i); + // multiply by conjugated channel, this function require size in _m128i, else it doesn't process all samples + mult_cpx_conj_vector(dl_ch_estimates_ext[aarx], rxdataF_ext[aarx], rxdataF_comp[aarx], arraySz, output_shift); } } -static void nr_pdcch_detection_mrc(int n_rb, c16_t rxdataF_comp[][n_rb * RE_PER_RB_OUT_DMRS]) +static void nr_pdcch_detection_mrc(int sz, c16_t rxdataF_comp[][sz]) { LOG_D(NR_PHY_DCI, "we enter nr_pdcch_detection_mrc (hard coded 2 antennas)\n"); - const int sz = n_rb * RE_PER_RB_OUT_DMRS; - c16_t *rx0 = rxdataF_comp[0]; c16_t *rx1 = rxdataF_comp[1]; // MRC on each re of rb - int i = 0; - for (; i < (sz & ~3); i += 4) { + // input always aligned and accepting tail padding to process all actual samples + for (int i = 0; i < sz; i += 4) { *(simde__m128i *)(rx0 + i) = simde_mm_adds_epi16(simde_mm_srai_epi16(*(simde__m128i *)(rx0 + i), 1), simde_mm_srai_epi16(*(simde__m128i *)(rx1 + i), 1)); } - for (; i < sz; i++) - rx0[i] = (c16_t){(rx0[i].r + rx1[i].r) / 2, (rx0[i].i + rx1[i].i) / 2}; } void nr_rx_pdcch(PHY_VARS_NR_UE *ue, @@ -387,25 +348,25 @@ void nr_rx_pdcch(PHY_VARS_NR_UE *ue, const int antRx = frame_parms->nb_antennas_rx; // Pointer to llrs, 4-bit resolution. - int32_t llr_size = 4 * n_rb * RE_PER_RB_OUT_DMRS; + int32_t llr_size = (rel15->coreset.duration-rel15->coreset.StartSymbolIndex) * n_rb * RE_PER_RB_OUT_DMRS; c16_t llr[llr_size]; - memset(llr, 0, sizeof(llr)); LOG_D(NR_PHY_DCI, "pdcch coreset: freq %x, n_rb %d, rb_offset %d\n", rel15->coreset.frequency_domain_resource[0], n_rb, rb_offset); - for (int s=rel15->coreset.StartSymbolIndex; s<(rel15->coreset.StartSymbolIndex+rel15->coreset.duration); s++) { + for (int s = rel15->coreset.StartSymbolIndex; s < rel15->coreset.StartSymbolIndex + rel15->coreset.duration; s++) { LOG_D(NR_PHY_DCI, "in nr_pdcch_extract_rbs_single(rxdataF -> rxdataF_ext || dl_ch_estimates -> dl_ch_estimates_ext)\n"); - - __attribute__((aligned(32))) c16_t rxdataF_ext[antRx][n_rb * RE_PER_RB_OUT_DMRS]; - __attribute__((aligned(32))) c16_t pdcch_dl_ch_estimates_ext[antRx][n_rb * RE_PER_RB_OUT_DMRS]; + const int arraySz = ceil_mod(n_rb * RE_PER_RB_OUT_DMRS, 32); + __attribute__((aligned(32))) c16_t rxdataF_ext[antRx][arraySz]; + __attribute__((aligned(32))) c16_t pdcch_dl_ch_estimates_ext[antRx][arraySz]; nr_pdcch_extract_rbs_single(ue->frame_parms.samples_per_slot_wCP, n_rb, rxdataF, pdcch_est_size, pdcch_dl_ch_estimates, + arraySz, rxdataF_ext, pdcch_dl_ch_estimates_ext, s, @@ -415,7 +376,7 @@ void nr_rx_pdcch(PHY_VARS_NR_UE *ue, LOG_D(NR_PHY_DCI, "in nr_pdcch_channel_level(dl_ch_estimates_ext -> dl_ch_estimates_ext)\n"); // compute channel level based on ofdm symbol 0 - int32_t avgs = nr_pdcch_channel_level(n_rb, pdcch_dl_ch_estimates_ext, antRx, s); + int32_t avgs = nr_pdcch_channel_level(n_rb, arraySz, pdcch_dl_ch_estimates_ext, antRx); uint8_t log2_maxh = (log2_approx(avgs) / 2) + 5; //+antRx; #ifdef UE_DEBUG_TRACE @@ -427,25 +388,22 @@ void nr_rx_pdcch(PHY_VARS_NR_UE *ue, LOG_D(NR_PHY_DCI, "we enter nr_pdcch_channel_compensation(log2_maxh=%d)\n", log2_maxh); LOG_D(NR_PHY_DCI, "in nr_pdcch_channel_compensation(rxdataF_ext x dl_ch_estimates_ext -> rxdataF_comp)\n"); // compute LLRs for ofdm symbol 0 only - __attribute__((aligned(32))) c16_t rxdataF_comp[antRx][n_rb * RE_PER_RB]; - nr_pdcch_channel_compensation(n_rb, + __attribute__((aligned(32))) c16_t rxdataF_comp[antRx][arraySz]; + nr_pdcch_channel_compensation(arraySz, rxdataF_ext, pdcch_dl_ch_estimates_ext, rxdataF_comp, antRx, log2_maxh); // log2_maxh+I0_shift - UEscopeCopy(ue, pdcchRxdataF_comp, rxdataF_comp, sizeof(struct complex16), antRx, n_rb * RE_PER_RB, 0); + UEscopeCopy(ue, pdcchRxdataF_comp, rxdataF_comp, sizeof(struct complex16), antRx, n_rb * RE_PER_RB_OUT_DMRS, 0); if (antRx > 1) - nr_pdcch_detection_mrc(n_rb * RE_PER_RB, rxdataF_comp); + nr_pdcch_detection_mrc(arraySz, rxdataF_comp); - LOG_D(NR_PHY_DCI, "we enter nr_pdcch_llr(for symbol %d), pdcch_vars[eNB_id]->rxdataF_comp ---> pdcch_vars[eNB_id]->llr \n", s); - LOG_D(NR_PHY_DCI, "in nr_pdcch_llr(rxdataF_comp -> llr)\n"); - nr_pdcch_llr(frame_parms, n_rb, rxdataF_comp[0], llr, s); - - UEscopeCopy(ue, pdcchLlr, llr, sizeof(c16_t), 1, llr_size, 0); + nr_pdcch_llr(n_rb * RE_PER_RB_OUT_DMRS, rxdataF_comp[0], llr + s * n_rb * RE_PER_RB_OUT_DMRS); } + UEscopeCopy(ue, pdcchLlr, llr, sizeof(c16_t), 1, llr_size, 0); nr_pdcch_demapping_deinterleaving(llr, pdcch_e_rx, From 62dd459959d8b1f80916b8af60a48bf6c375cd23 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Tue, 29 Jul 2025 08:58:10 +0200 Subject: [PATCH 289/964] CI: change frequency for OAIUE pipeline --- ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf | 4 ++-- ci-scripts/yaml_files/5g_sa_n310_nrue/docker-compose.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf b/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf index 62a7830541..e30cef3857 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf @@ -35,8 +35,8 @@ gNBs = # downlinkConfigCommon #frequencyInfoDL dl_frequencyBand = 78; - absoluteFrequencySSB = 634080; - dl_absoluteFrequencyPointA = 632808; + absoluteFrequencySSB = 628320; + dl_absoluteFrequencyPointA = 627062; #scs-SpecificCarrierList dl_offstToCarrier = 0; # subcarrierSpacing diff --git a/ci-scripts/yaml_files/5g_sa_n310_nrue/docker-compose.yml b/ci-scripts/yaml_files/5g_sa_n310_nrue/docker-compose.yml index a0a15ac11e..aac787a916 100644 --- a/ci-scripts/yaml_files/5g_sa_n310_nrue/docker-compose.yml +++ b/ci-scripts/yaml_files/5g_sa_n310_nrue/docker-compose.yml @@ -17,7 +17,7 @@ services: #entrypoint: /bin/bash -c "sleep infinity" environment: TZ: Europe/Paris - USE_ADDITIONAL_OPTIONS: --usrp-args type=n3xx,name=ni-n3xx-31641B9,addr=192.168.10.2 -r 106 --numerology 1 --band 78 -C 3511200000 --ue-fo-compensation --ue-rxgain 65 --tune-offset 20000000 -A 90 --log_config.global_log_options level,nocolor,time --uicc0.imsi 001020000000111 --uicc0.nssai_sd 16777215 + USE_ADDITIONAL_OPTIONS: --usrp-args type=n3xx,name=ni-n3xx-31641B9,addr=192.168.10.2 -r 106 --numerology 1 --band 78 -C 3425010000 --ssb 509 --ue-fo-compensation --ue-rxgain 65 --tune-offset 20000000 -A 90 --log_config.global_log_options level,nocolor,time --uicc0.imsi 001020000000111 --uicc0.nssai_sd 16777215 volumes: - ../../conf_files/ue.sa.conf:/opt/oai-nr-ue/etc/nr-ue.conf healthcheck: From 7d27592b4ffae5d6e405cd3785e0e7b07ea89f8a Mon Sep 17 00:00:00 2001 From: Matthias Mehlhose Date: Tue, 3 Jun 2025 12:16:10 +0000 Subject: [PATCH 290/964] Initial unit test to refactor and fix nr_layer_precoder_simd function (See #955) --- openair1/PHY/CMakeLists.txt | 1 + openair1/PHY/MODULATION/CMakeLists.txt | 3 + openair1/PHY/MODULATION/nr_modulation.c | 5 +- openair1/PHY/MODULATION/tests/CMakeLists.txt | 5 + .../MODULATION/tests/test_nr_modulation.cpp | 153 ++++++++++++++++++ 5 files changed, 164 insertions(+), 3 deletions(-) create mode 100644 openair1/PHY/MODULATION/CMakeLists.txt create mode 100644 openair1/PHY/MODULATION/tests/CMakeLists.txt create mode 100644 openair1/PHY/MODULATION/tests/test_nr_modulation.cpp diff --git a/openair1/PHY/CMakeLists.txt b/openair1/PHY/CMakeLists.txt index 2d74e9aedc..83e7dc0530 100644 --- a/openair1/PHY/CMakeLists.txt +++ b/openair1/PHY/CMakeLists.txt @@ -2,3 +2,4 @@ add_subdirectory(nr_phy_common) add_subdirectory(TOOLS) add_subdirectory(NR_TRANSPORT) add_subdirectory(CODING) +add_subdirectory(MODULATION) diff --git a/openair1/PHY/MODULATION/CMakeLists.txt b/openair1/PHY/MODULATION/CMakeLists.txt new file mode 100644 index 0000000000..dc1a5e0301 --- /dev/null +++ b/openair1/PHY/MODULATION/CMakeLists.txt @@ -0,0 +1,3 @@ +if (ENABLE_TESTS) + add_subdirectory(tests) +endif() diff --git a/openair1/PHY/MODULATION/nr_modulation.c b/openair1/PHY/MODULATION/nr_modulation.c index 994c0798c2..4df83cedf9 100644 --- a/openair1/PHY/MODULATION/nr_modulation.c +++ b/openair1/PHY/MODULATION/nr_modulation.c @@ -765,9 +765,8 @@ void nr_layer_precoder_simd(const int n_layers, // Multiplication and shift const simde__m256i reals = simde_mm256_srai_epi32(simde_mm256_madd_epi16(x, w_c), 15); // (int32_t) .r = (x.r * w.r - x.i * w.i) >> 15 - const simde__m256i imags = simde_mm256_slli_epi32( - simde_mm256_madd_epi16(x, w_s), - 1); // (int32_t) .i = (x.r * w.i + x.i * w.r) << 1, since higher 16 bit of each 32 bit is taken by blend_epi16 + const simde__m256i imags = + simde_mm256_slli_epi32(simde_mm256_madd_epi16(x, w_s), 1); // (int32_t) .i = (x.r * w.i + x.i * w.r) << 1, since higher 16 bit of each 32 bit is taken by blend_epi16 // Re-arrange to match c16_t format const simde__m256i produ = simde_mm256_blend_epi16(reals, imags, 0xAA); diff --git a/openair1/PHY/MODULATION/tests/CMakeLists.txt b/openair1/PHY/MODULATION/tests/CMakeLists.txt new file mode 100644 index 0000000000..426181698d --- /dev/null +++ b/openair1/PHY/MODULATION/tests/CMakeLists.txt @@ -0,0 +1,5 @@ +add_executable(test_nr_modulation test_nr_modulation.cpp) +target_link_libraries(test_nr_modulation PRIVATE PHY_NR GTest::gtest minimal_lib) +add_dependencies(tests test_nr_modulation) +add_test(NAME test_nr_modulation + COMMAND ./test_nr_modulation) diff --git a/openair1/PHY/MODULATION/tests/test_nr_modulation.cpp b/openair1/PHY/MODULATION/tests/test_nr_modulation.cpp new file mode 100644 index 0000000000..c6f39aee5e --- /dev/null +++ b/openair1/PHY/MODULATION/tests/test_nr_modulation.cpp @@ -0,0 +1,153 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +// Initial unit test for nr_layer_precoder_simd_[cm, simd] functions +// Issue: gNB: SIMD Precoding Bug in nr_layer_precoder_simd for PMI = 4 +// https://gitlab.eurecom.fr/oai/openairinterface5g/-/issues/955 + +#include "gtest/gtest.h" +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#include "openair1/PHY/TOOLS/tools_defs.h" // c16_t +#include "nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h" // nfapi_nr_pm_pdu_t +#include "nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h" // fapi_nr_dl_config_dci_dl_pdu_rel15_t + +//#include "openair1/PHY/MODULATION/nr_modulation.h" // nr_layer_precoder_simd_[cm, simd] + +// Forward declare the function but hide the Variable-Length Array (VLA) feature from C not available in C++ +c16_t nr_layer_precoder_cm(int n_layers, + int symbol_size, + c16_t (*dataF_in)[/*symbol_size*/], // c16_t dataF_in[n_layers][symbol_size] + int ant, + nfapi_nr_pm_pdu_t *pmi_pdu, + int offset); + +// Forward declare the function but hide the Variable-Length Array (VLA) feature from C not available in C++ +void nr_layer_precoder_simd(int n_layers, + int symbol_size, + const c16_t (*dataF_in)[/*symbol_size*/], // c16_t dataF_in[n_layers][symbol_size] + int ant, + const nfapi_nr_pm_pdu_t *pmi_pdu, + int offset, + int re_cnt, + c16_t *dataF_out); + +#ifdef __cplusplus +} +#endif + +TEST(NrLayerPrecoderTest, Basic) +{ + constexpr int n_layers = 2; + constexpr int symbol_size = 24; + constexpr int ant = 1; + constexpr int re_cnt = 24; + + // Initialize the 2D input data buffer + std::vector buffer_in(n_layers * symbol_size); + std::vector buffer_out(n_layers * symbol_size); + + for (int i = 0; i < n_layers * symbol_size; ++i) { + buffer_in[i] = {static_cast(i + 1), static_cast(-i - 1)}; + buffer_out[i] = {static_cast(0), static_cast(0)}; + } + + // Cast flat buffer to the required 2D Variable-Length Array (VLA) style pointer + c16_t(*dataF_in)[symbol_size] = reinterpret_cast(buffer_in.data()); + c16_t(*dataF_out)[symbol_size] = reinterpret_cast(buffer_out.data()); + + // Create and populate the pmi_pdu structure + nfapi_nr_pm_pdu_t pmi_pdu = {0}; + for (int layer = 0; layer < n_layers; ++layer) { + pmi_pdu.weights[layer][ant].precoder_weight_Re = 1 << 14; // e.g., Q15 representation of ~0.5 + pmi_pdu.weights[layer][ant].precoder_weight_Im = 0; + } + + // Call the C function + for (int symbol = 0; symbol < re_cnt; symbol++) + dataF_out[ant][symbol] = nr_layer_precoder_cm(n_layers, symbol_size, dataF_in, ant, &pmi_pdu, symbol); + + // You can calculate the expected value manually or test rough correctness + for (int symbol = 0; symbol < re_cnt; symbol++) { + int result_real = 14 + (symbol - 1) & ~1; + int result_imag = 14 + (symbol) & ~1; + EXPECT_EQ(dataF_out[ant][symbol].r, result_real) + << " at [" << ant << "][" << symbol << "] got real part: " << dataF_out[ant][symbol].r; + ; + EXPECT_EQ(dataF_out[ant][symbol].i, -result_imag) + << " at [" << ant << "][" << symbol << "] got imag part: " << dataF_out[ant][symbol].i; + ; + } +} + +TEST(NrLayerPrecoderTest, SIMD) +{ + constexpr int n_layers = 2; + constexpr int symbol_size = 24; + constexpr int ant = 1; + constexpr int re_cnt = 24; + + // Initialize the 2D input data buffer + std::vector buffer_in(n_layers * symbol_size); + std::vector buffer_out(n_layers * symbol_size); + + for (int i = 0; i < n_layers * symbol_size; ++i) { + buffer_in[i] = {static_cast(i + 1), static_cast(-i - 1)}; + buffer_out[i] = {static_cast(0), static_cast(0)}; + } + + // Cast flat buffer to the required 2D Variable-Length Array (VLA) style pointer + c16_t(*dataF_in)[symbol_size] = reinterpret_cast(buffer_in.data()); + c16_t(*dataF_out)[symbol_size] = reinterpret_cast(buffer_out.data()); + + // Create and populate the pmi_pdu structure + nfapi_nr_pm_pdu_t pmi_pdu = {0}; + for (int layer = 0; layer < n_layers; ++layer) { + pmi_pdu.weights[layer][ant].precoder_weight_Re = 1 << 14; // e.g., Q15 representation of ~0.5 + pmi_pdu.weights[layer][ant].precoder_weight_Im = 0; + } + + // Call the C function + nr_layer_precoder_simd(n_layers, symbol_size, dataF_in, ant, &pmi_pdu, 0, re_cnt, dataF_out[ant]); + + // You can calculate the expected value manually or test rough correctness + for (int symbol = 0; symbol < re_cnt; symbol++) { + int result_real = 14 + (symbol - 1) & ~1; + int result_imag = 14 + (symbol) & ~1; + EXPECT_EQ(dataF_out[ant][symbol].r, result_real) + << " at [" << ant << "][" << symbol << "] got real part: " << dataF_out[ant][symbol].r; + ; + EXPECT_EQ(dataF_out[ant][symbol].i, -result_imag) + << " at [" << ant << "][" << symbol << "] got imag part: " << dataF_out[ant][symbol].i; + ; + } +} + +int main(int argc, char **argv) +{ + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} From 905a8a495e9f49ef23d6a03a4ebcba12f41da7ee Mon Sep 17 00:00:00 2001 From: Mario Joa-Ng Date: Wed, 4 Jun 2025 21:45:31 -0400 Subject: [PATCH 291/964] mod: unit test code to compare CM and SIMD results on both antennas --- .../MODULATION/tests/test_nr_modulation.cpp | 64 +++++++++++++++++++ openair1/PHY/TOOLS/tools_defs.h | 2 +- openair2/LAYER2/NR_MAC_gNB/config.c | 8 +-- 3 files changed, 66 insertions(+), 8 deletions(-) diff --git a/openair1/PHY/MODULATION/tests/test_nr_modulation.cpp b/openair1/PHY/MODULATION/tests/test_nr_modulation.cpp index c6f39aee5e..2640af1c26 100644 --- a/openair1/PHY/MODULATION/tests/test_nr_modulation.cpp +++ b/openair1/PHY/MODULATION/tests/test_nr_modulation.cpp @@ -63,6 +63,7 @@ TEST(NrLayerPrecoderTest, Basic) { constexpr int n_layers = 2; constexpr int symbol_size = 24; + constexpr int n_ants = 2; constexpr int ant = 1; constexpr int re_cnt = 24; @@ -72,6 +73,8 @@ TEST(NrLayerPrecoderTest, Basic) for (int i = 0; i < n_layers * symbol_size; ++i) { buffer_in[i] = {static_cast(i + 1), static_cast(-i - 1)}; + } + for (int i = 0; i < n_ants * symbol_size; ++i) { buffer_out[i] = {static_cast(0), static_cast(0)}; } @@ -107,6 +110,7 @@ TEST(NrLayerPrecoderTest, SIMD) { constexpr int n_layers = 2; constexpr int symbol_size = 24; + constexpr int n_ants = 2; constexpr int ant = 1; constexpr int re_cnt = 24; @@ -116,6 +120,8 @@ TEST(NrLayerPrecoderTest, SIMD) for (int i = 0; i < n_layers * symbol_size; ++i) { buffer_in[i] = {static_cast(i + 1), static_cast(-i - 1)}; + } + for (int i = 0; i < n_ants * symbol_size; ++i) { buffer_out[i] = {static_cast(0), static_cast(0)}; } @@ -146,6 +152,64 @@ TEST(NrLayerPrecoderTest, SIMD) } } +TEST(NrLayerPrecoderTest, Compare_CM_SIMD) +{ + constexpr int n_layers = 1; + constexpr int symbol_size = 24; + constexpr int n_ants = 2; + constexpr int re_cnt = 24; + + // Initialize the 2D input data buffer + std::vector buffer_in(n_layers * symbol_size); + std::vector buffer_out(n_ants * symbol_size); + std::vector buffer_out2(n_ants * symbol_size); + + for (int i = 0; i < n_layers * symbol_size; ++i) { + buffer_in[i] = {static_cast(i + 1), static_cast(-i - 1)}; + } + for (int i = 0; i < n_ants * symbol_size; ++i) { + buffer_out[i] = {static_cast(0), static_cast(0)}; + buffer_out2[i] = {static_cast(0), static_cast(0)}; + } + + // Cast flat buffer to the required 2D Variable-Length Array (VLA) style pointer + c16_t(*dataF_in)[symbol_size] = reinterpret_cast(buffer_in.data()); + c16_t(*dataF_out)[symbol_size] = reinterpret_cast(buffer_out.data()); + c16_t(*dataF_out2)[symbol_size] = reinterpret_cast(buffer_out2.data()); + + // Create and populate the pmi_pdu structure + nfapi_nr_pm_pdu_t pmi_pdu = {0}; + pmi_pdu.pm_idx = 4; + for (int layer = 0; layer < n_layers; ++layer) { + // Could not use convert_precoder_weight() as complex.h could not be used in googletest + // Use the logic in convert_precoder_weight() + // precoder [−1,−j] + pmi_pdu.weights[layer][0].precoder_weight_Re = round(-32767 * 1.0); + pmi_pdu.weights[layer][0].precoder_weight_Im = 0x0000; // Q15 representation of 0 + pmi_pdu.weights[layer][1].precoder_weight_Re = 0x0000; // Q15 representation of 0 + pmi_pdu.weights[layer][1].precoder_weight_Im = round(-32767 * 1.0); + } + + // Get the results for all the antenna + for (int ant = 0; ant < n_ants; ant++) { + + // Call the C function + for (int symbol = 0; symbol < re_cnt; symbol++) + dataF_out[ant][symbol] = nr_layer_precoder_cm(n_layers, symbol_size, dataF_in, ant, &pmi_pdu, symbol); + + // Call the C function + nr_layer_precoder_simd(n_layers, symbol_size, dataF_in, ant, &pmi_pdu, 0, re_cnt, dataF_out2[ant]); + + // Compare the result from both C function + for (int symbol = 0; symbol < re_cnt; symbol++) { + EXPECT_EQ(dataF_out_cm[ant][symbol].r, dataF_out_simd[ant][symbol].r) + << " at [" << ant << "][" << symbol << "] got real part: " << dataF_out_cm[ant][symbol].r << " result " << dataF_out_simd[ant][symbol].r; + EXPECT_EQ(dataF_out_cm[ant][symbol].i, dataF_out_simd[ant][symbol].i) + << " at [" << ant << "][" << symbol << "] got imag part: " << dataF_out_cm[ant][symbol].i << " result " << dataF_out_simd[ant][symbol].i; + } + } +} + int main(int argc, char **argv) { testing::InitGoogleTest(&argc, argv); diff --git a/openair1/PHY/TOOLS/tools_defs.h b/openair1/PHY/TOOLS/tools_defs.h index 64e5061476..3b8d027adf 100644 --- a/openair1/PHY/TOOLS/tools_defs.h +++ b/openair1/PHY/TOOLS/tools_defs.h @@ -163,7 +163,7 @@ extern "C" { __attribute__((always_inline)) inline c16_t c16conj(const c16_t a) { return (c16_t) { .r = a.r, - .i = (int16_t)-a.i + .i = (int16_t)-a.i }; } diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c index bfc9f63538..cd75bb5aee 100644 --- a/openair2/LAYER2/NR_MAC_gNB/config.c +++ b/openair2/LAYER2/NR_MAC_gNB/config.c @@ -61,13 +61,7 @@ c16_t convert_precoder_weight(double complex c_in) { - double cr = creal(c_in) * 32768 + 0.5; - if (cr < 0) - cr -= 1; - double ci = cimag(c_in) * 32768 + 0.5; - if (ci < 0) - ci -= 1; - return (c16_t) {.r = (short)cr, .i = (short)ci}; + return (c16_t) {.r = round(32767*creal(c_in)), .i = round(32767*cimag(c_in))}; } void get_K1_K2(int N1, int N2, int *K1, int *K2, int layers) From 5b0b40c1026c7ebf63844bb69676cc8a13865e07 Mon Sep 17 00:00:00 2001 From: Matthias Mehlhose Date: Tue, 22 Jul 2025 13:59:38 +0000 Subject: [PATCH 292/964] mod: use random numbers in unit test function --- .../MODULATION/tests/test_nr_modulation.cpp | 47 ++++++++++--------- openair2/LAYER2/NR_MAC_gNB/config.c | 2 +- 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/openair1/PHY/MODULATION/tests/test_nr_modulation.cpp b/openair1/PHY/MODULATION/tests/test_nr_modulation.cpp index 2640af1c26..ca8b61acd7 100644 --- a/openair1/PHY/MODULATION/tests/test_nr_modulation.cpp +++ b/openair1/PHY/MODULATION/tests/test_nr_modulation.cpp @@ -85,7 +85,7 @@ TEST(NrLayerPrecoderTest, Basic) // Create and populate the pmi_pdu structure nfapi_nr_pm_pdu_t pmi_pdu = {0}; for (int layer = 0; layer < n_layers; ++layer) { - pmi_pdu.weights[layer][ant].precoder_weight_Re = 1 << 14; // e.g., Q15 representation of ~0.5 + pmi_pdu.weights[layer][ant].precoder_weight_Re = -SHRT_MAX; // Q15 representation of (~-1.0) -0.999969482421875 (-1+2^-15) pmi_pdu.weights[layer][ant].precoder_weight_Im = 0; } @@ -95,14 +95,13 @@ TEST(NrLayerPrecoderTest, Basic) // You can calculate the expected value manually or test rough correctness for (int symbol = 0; symbol < re_cnt; symbol++) { - int result_real = 14 + (symbol - 1) & ~1; - int result_imag = 14 + (symbol) & ~1; + int result_real = -26 - (symbol<<1); + int result_imag = -24 - (symbol<<1); + EXPECT_EQ(dataF_out[ant][symbol].r, result_real) << " at [" << ant << "][" << symbol << "] got real part: " << dataF_out[ant][symbol].r; - ; EXPECT_EQ(dataF_out[ant][symbol].i, -result_imag) << " at [" << ant << "][" << symbol << "] got imag part: " << dataF_out[ant][symbol].i; - ; } } @@ -132,7 +131,7 @@ TEST(NrLayerPrecoderTest, SIMD) // Create and populate the pmi_pdu structure nfapi_nr_pm_pdu_t pmi_pdu = {0}; for (int layer = 0; layer < n_layers; ++layer) { - pmi_pdu.weights[layer][ant].precoder_weight_Re = 1 << 14; // e.g., Q15 representation of ~0.5 + pmi_pdu.weights[layer][ant].precoder_weight_Re = -SHRT_MAX; // Q15 representation of (~-1.0) -0.999969482421875 (-1+2^-15) pmi_pdu.weights[layer][ant].precoder_weight_Im = 0; } @@ -141,14 +140,13 @@ TEST(NrLayerPrecoderTest, SIMD) // You can calculate the expected value manually or test rough correctness for (int symbol = 0; symbol < re_cnt; symbol++) { - int result_real = 14 + (symbol - 1) & ~1; - int result_imag = 14 + (symbol) & ~1; + int result_real = -26 - (symbol<<1); + int result_imag = -24 - (symbol<<1); + EXPECT_EQ(dataF_out[ant][symbol].r, result_real) << " at [" << ant << "][" << symbol << "] got real part: " << dataF_out[ant][symbol].r; - ; EXPECT_EQ(dataF_out[ant][symbol].i, -result_imag) << " at [" << ant << "][" << symbol << "] got imag part: " << dataF_out[ant][symbol].i; - ; } } @@ -161,21 +159,21 @@ TEST(NrLayerPrecoderTest, Compare_CM_SIMD) // Initialize the 2D input data buffer std::vector buffer_in(n_layers * symbol_size); - std::vector buffer_out(n_ants * symbol_size); - std::vector buffer_out2(n_ants * symbol_size); + std::vector buffer_out_cm(n_ants * symbol_size); + std::vector buffer_out_simd(n_ants * symbol_size); for (int i = 0; i < n_layers * symbol_size; ++i) { - buffer_in[i] = {static_cast(i + 1), static_cast(-i - 1)}; + buffer_in[i] = {static_cast((rand() % (2 * SHRT_MAX + 1)) - SHRT_MAX), static_cast((rand() % (2 * SHRT_MAX + 1)) - SHRT_MAX)}; } for (int i = 0; i < n_ants * symbol_size; ++i) { - buffer_out[i] = {static_cast(0), static_cast(0)}; - buffer_out2[i] = {static_cast(0), static_cast(0)}; + buffer_out_cm[i] = {static_cast(0), static_cast(0)}; + buffer_out_simd[i] = {static_cast(0), static_cast(0)}; } // Cast flat buffer to the required 2D Variable-Length Array (VLA) style pointer c16_t(*dataF_in)[symbol_size] = reinterpret_cast(buffer_in.data()); - c16_t(*dataF_out)[symbol_size] = reinterpret_cast(buffer_out.data()); - c16_t(*dataF_out2)[symbol_size] = reinterpret_cast(buffer_out2.data()); + c16_t(*dataF_out_cm)[symbol_size] = reinterpret_cast(buffer_out_cm.data()); + c16_t(*dataF_out_simd)[symbol_size] = reinterpret_cast(buffer_out_simd.data()); // Create and populate the pmi_pdu structure nfapi_nr_pm_pdu_t pmi_pdu = {0}; @@ -184,10 +182,10 @@ TEST(NrLayerPrecoderTest, Compare_CM_SIMD) // Could not use convert_precoder_weight() as complex.h could not be used in googletest // Use the logic in convert_precoder_weight() // precoder [−1,−j] - pmi_pdu.weights[layer][0].precoder_weight_Re = round(-32767 * 1.0); - pmi_pdu.weights[layer][0].precoder_weight_Im = 0x0000; // Q15 representation of 0 - pmi_pdu.weights[layer][1].precoder_weight_Re = 0x0000; // Q15 representation of 0 - pmi_pdu.weights[layer][1].precoder_weight_Im = round(-32767 * 1.0); + pmi_pdu.weights[layer][0].precoder_weight_Re = -SHRT_MAX; // Q15 representation of (~-1.0) -0.999969482421875 (-1+2^-15) + pmi_pdu.weights[layer][0].precoder_weight_Im = 0x0000; // Q15 representation of 0 + pmi_pdu.weights[layer][1].precoder_weight_Re = 0x0000; // Q15 representation of 0 + pmi_pdu.weights[layer][1].precoder_weight_Im = -SHRT_MAX; // Q15 representation of (~-1.0) -0.999969482421875 (-1+2^-15) } // Get the results for all the antenna @@ -195,10 +193,10 @@ TEST(NrLayerPrecoderTest, Compare_CM_SIMD) // Call the C function for (int symbol = 0; symbol < re_cnt; symbol++) - dataF_out[ant][symbol] = nr_layer_precoder_cm(n_layers, symbol_size, dataF_in, ant, &pmi_pdu, symbol); + dataF_out_cm[ant][symbol] = nr_layer_precoder_cm(n_layers, symbol_size, dataF_in, ant, &pmi_pdu, symbol); // Call the C function - nr_layer_precoder_simd(n_layers, symbol_size, dataF_in, ant, &pmi_pdu, 0, re_cnt, dataF_out2[ant]); + nr_layer_precoder_simd(n_layers, symbol_size, dataF_in, ant, &pmi_pdu, 0, re_cnt, dataF_out_simd[ant]); // Compare the result from both C function for (int symbol = 0; symbol < re_cnt; symbol++) { @@ -212,6 +210,9 @@ TEST(NrLayerPrecoderTest, Compare_CM_SIMD) int main(int argc, char **argv) { + // Initialize random seed + srand(time(0)); + testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c index cd75bb5aee..99e4249bb2 100644 --- a/openair2/LAYER2/NR_MAC_gNB/config.c +++ b/openair2/LAYER2/NR_MAC_gNB/config.c @@ -61,7 +61,7 @@ c16_t convert_precoder_weight(double complex c_in) { - return (c16_t) {.r = round(32767*creal(c_in)), .i = round(32767*cimag(c_in))}; + return (c16_t) {.r = round(SHRT_MAX*creal(c_in)), .i = round(SHRT_MAX*cimag(c_in))}; } void get_K1_K2(int N1, int N2, int *K1, int *K2, int layers) From 9a7d80ef7daf63190b3b61be634a221e79996723 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 30 Jul 2025 08:57:02 +0200 Subject: [PATCH 293/964] CMake module path to beginning Move the path to the beginning, so that we can use it early. Specifically, it was after the SCTP module, and the next commit will use the Findsctp.cmake module to find SCTP. Use the cmake-proper variable. --- CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 99c537dc22..4c78030c30 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,6 +36,8 @@ if(NOT DEFINED ENV{CPM_SOURCE_CACHE}) endif() include("cmake_targets/CPM.cmake") +set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake_targets/tools/MODULES" "${CMAKE_MODULE_PATH}") + ############################## ### CCache: reduce compilation time ############################## @@ -1710,7 +1712,6 @@ include_directories("${NFAPI_DIR}/pnf_sim/inc") add_library(oai_iqplayer MODULE ${OPENAIR_DIR}/radio/iqplayer/iqplayer_lib.c ) -set(CMAKE_MODULE_PATH "${OPENAIR_DIR}/cmake_targets/tools/MODULES" "${CMAKE_MODULE_PATH}") ################################# # add executables for operation From 6c8fc09525bed03af57a44f644e738114653c227 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Tue, 29 Jul 2025 09:29:58 +0200 Subject: [PATCH 294/964] CI: change frequency for AW2S pipeline --- ci-scripts/as_ue/aw2s-multi-00102-20.cfg | 2 +- ci-scripts/ci_infra.yaml | 4 ++-- ci-scripts/conf_files/gnb.sa.band78.51prb.aw2s.ddsuu.conf | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/ci-scripts/as_ue/aw2s-multi-00102-20.cfg b/ci-scripts/as_ue/aw2s-multi-00102-20.cfg index 5fc05d6301..c02a6b357d 100644 --- a/ci-scripts/as_ue/aw2s-multi-00102-20.cfg +++ b/ci-scripts/as_ue/aw2s-multi-00102-20.cfg @@ -5,7 +5,7 @@ { #define N_ANTENNA_DL 1 #define N_ANTENNA_UL 1 -#define DL_ARFCN 631296 +#define DL_ARFCN 627360 #define TDD 1 log_options: "all.level=debug,all.max_size=0,nas.level=debug,nas.max_size=1,rrc.level=debug,rrc.max_size=1", diff --git a/ci-scripts/ci_infra.yaml b/ci-scripts/ci_infra.yaml index cda6258244..2717cf18c6 100644 --- a/ci-scripts/ci_infra.yaml +++ b/ci-scripts/ci_infra.yaml @@ -147,12 +147,12 @@ ltebox-nepes: amarisoft_ue: Host: amariue - InitScript: /root/lteue-linux-2025-03-15/lteue /root/oaicicd/ran_sa_aw2s_asue/aw2s-multi-00102-20.cfg & + InitScript: /root/lteue-linux-2025-03-15/lteue /root/oaicicd/ran_sa_aw2s_asue_20MHz/aw2s-multi-00102-20.cfg & TermScript: /root/lteue-linux-2025-03-15/ws.js -t 10 127.0.0.1:9002 '{"message":"quit"}' || killall -KILL lteue-avx2 NetworkScript: ip netns exec ue1 ip a show dev pdn0 amarisoft_ue_2x2: Host: amariue - InitScript: /root/lteue-linux-2025-03-15/lteue /root/oaicicd/ran_sa_aw2s_asue_2x2/aw2s-multi-00102-2x2-v2.cfg & + InitScript: /root/lteue-linux-2025-03-15/lteue /root/oaicicd/ran_sa_aw2s_asue_20MHz_2x2/aw2s-multi-00102-2x2-v2.cfg & TermScript: /root/lteue-linux-2025-03-15/ws.js -t 10 127.0.0.1:9002 '{"message":"quit"}' || killall -KILL lteue-avx2 NetworkScript: ip netns exec ue1 ip a show dev pdn0 amarisoft_ue_fhi72: diff --git a/ci-scripts/conf_files/gnb.sa.band78.51prb.aw2s.ddsuu.conf b/ci-scripts/conf_files/gnb.sa.band78.51prb.aw2s.ddsuu.conf index 143a1455e3..3bfe9ede51 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.51prb.aw2s.ddsuu.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.51prb.aw2s.ddsuu.conf @@ -34,11 +34,11 @@ gNBs = # downlinkConfigCommon #frequencyInfoDL - # this is 3469.44 MHz => 301 REs from PointA 25 PRBs + 1 RE - absoluteFrequencySSB = 631296; + # this is 3410.400 MHz + absoluteFrequencySSB = 627360; dl_frequencyBand = 78; - # this is 3469.44 - (51*12*30e-3/2) = 3460.26 MHz - dl_absoluteFrequencyPointA = 630684; + # this is 3401.220 MHz + dl_absoluteFrequencyPointA = 626748; #scs-SpecificCarrierList dl_offstToCarrier = 0; # subcarrierSpacing From b65b5dd40e22b343f0f4ddd5c1141203c8a44ab0 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Thu, 17 Jul 2025 12:40:47 +0200 Subject: [PATCH 295/964] Remove specific directory for LTE SIM management tools Move into openair3/NAS/TOOLS/CMakeLists.txt, and simplify the CMakeLists.txt. Co-authored-by: Robert Schmidt --- .gitignore | 1 - CMakeLists.txt | 2 +- cmake_targets/build_oai | 15 +--- cmake_targets/nas_sim_tools/CMakeLists.txt | 79 ---------------------- cmake_targets/tools/build_helper | 1 - docker/Dockerfile.lteUE.rhel9 | 6 +- docker/Dockerfile.lteUE.rocky | 6 +- docker/Dockerfile.lteUE.ubuntu22 | 6 +- openair3/NAS/CMakeLists.txt | 1 + openair3/NAS/TOOLS/CMakeLists.txt | 36 ++++++++++ openair3/NAS/TOOLS/conf2uedata.c | 2 + openair3/NAS/TOOLS/nvram.c | 2 + openair3/NAS/TOOLS/usim.c | 2 + 13 files changed, 55 insertions(+), 104 deletions(-) delete mode 100755 cmake_targets/nas_sim_tools/CMakeLists.txt create mode 100755 openair3/NAS/TOOLS/CMakeLists.txt diff --git a/.gitignore b/.gitignore index c4a4022fba..d1c6979e76 100644 --- a/.gitignore +++ b/.gitignore @@ -5,7 +5,6 @@ cmake_targets/log/ cmake_targets/*/build/ cmake_targets/ran_build/ -cmake_targets/nas_sim_tools/build/ log/ lte_build_oai/ diff --git a/CMakeLists.txt b/CMakeLists.txt index 99c537dc22..4765d8d9c7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -172,7 +172,7 @@ else () endif() # add autotools definitions that were maybe used! -add_definitions("-DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_FCNTL_H=1 -DHAVE_ARPA_INET_H=1 -DHAVE_SYS_TIME_H=1 -DHAVE_SYS_SOCKET_H=1 -DHAVE_STRERROR=1 -DHAVE_SOCKET=1 -DHAVE_MEMSET=1 -DHAVE_GETTIMEOFDAY=1 -DHAVE_STDLIB_H=1 -DHAVE_MALLOC=1 -DHAVE_LIBSCTP") +add_definitions(-DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_FCNTL_H=1 -DHAVE_ARPA_INET_H=1 -DHAVE_SYS_TIME_H=1 -DHAVE_SYS_SOCKET_H=1 -DHAVE_STRERROR=1 -DHAVE_SOCKET=1 -DHAVE_MEMSET=1 -DHAVE_GETTIMEOFDAY=1 -DHAVE_STDLIB_H=1 -DHAVE_MALLOC=1 -DHAVE_LIBSCTP) # we need -rdynamic to incorporate all symbols in shared objects, see man page set(commonOpts "-pipe -fPIC -Wall -fno-strict-aliasing -rdynamic") diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index cbe197c973..83570c80eb 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -244,7 +244,7 @@ function main() { shift;; --UE) UE=1 - TARGET_LIST="$TARGET_LIST lte-uesoftmodem" + TARGET_LIST="$TARGET_LIST lte-uesoftmodem conf2uedata usim nvram" echo_info "Will compile UE" shift;; --nrUE) @@ -513,18 +513,7 @@ function main() { fi if [ "$UE" = 1 ] ; then - - echo_info "Compiling UE specific part" - - [ "$CLEAN" = "1" ] && rm -rf $DIR/nas_sim_tools/build - mkdir -p $DIR/nas_sim_tools/build - cd $DIR/nas_sim_tools/build - - ${CMAKE_CMD% *} .. - compilations nas_sim_tools usim.txt "usim" "${BUILD_TOOL_OPT}" - compilations nas_sim_tools nvram.txt "nvram" "${BUILD_TOOL_OPT}" - compilations nas_sim_tools conf2uedata.txt "conf2uedata" "${BUILD_TOOL_OPT}" - + echo_info "Generate LTE USIM default sim content UE specific part" # generate USIM data if [ -f conf2uedata ]; then install_nas_tools $conf_nvram_path $DIR/$BUILD_DIR/build "$DIR/$BUILD_DIR/build/conf2uedata.txt" diff --git a/cmake_targets/nas_sim_tools/CMakeLists.txt b/cmake_targets/nas_sim_tools/CMakeLists.txt deleted file mode 100755 index 98b0772582..0000000000 --- a/cmake_targets/nas_sim_tools/CMakeLists.txt +++ /dev/null @@ -1,79 +0,0 @@ -cmake_minimum_required(VERSION 3.5) - -project(NAS_SIM_TOOLS) - -include(FindPkgConfig) -pkg_search_module(CONFIG libconfig REQUIRED) -include_directories(${CONFIG_INCLUDE_DIRS}) -add_definitions(-std=gnu99) -include("../macros.cmake") - -ENABLE_LANGUAGE(C) - -set(CMAKE_C_FLAGS - "${CMAKE_C_FLAGS} ${C_FLAGS_PROCESSOR} -Werror -Wall -Wstrict-prototypes -g") - -set(OPENAIR_DIR $ENV{OPENAIR_DIR}) -set(OPENAIR3_DIR $ENV{OPENAIR_DIR}/openair3) -include_directories (${OPENAIR_DIR}/openair2/COMMON) -include_directories (${OPENAIR_DIR}) - -set(CONF2UEDATA_LIB_SRC - ${OPENAIR_DIR}/openair3/NAS/TOOLS/conf_emm.c - ${OPENAIR_DIR}/openair3/NAS/TOOLS/conf_user_data.c - ${OPENAIR_DIR}/openair3/NAS/TOOLS/conf_usim.c - ${OPENAIR_DIR}/openair3/NAS/TOOLS/conf_network.c - ${OPENAIR_DIR}/openair3/NAS/TOOLS/conf_user_plmn.c - ${OPENAIR_DIR}/openair3/NAS/TOOLS/conf_parser.c - ${OPENAIR_DIR}/openair3/NAS/TOOLS/fs.c - ${OPENAIR_DIR}/openair3/NAS/TOOLS/display.c - ${OPENAIR_DIR}/openair3/NAS/UE/API/USIM/usim_api.c - ${OPENAIR_DIR}/openair3/NAS/UE/API/USIM/aka_functions.c - ${OPENAIR_DIR}/common/utils/mem/memory.c - ${OPENAIR_DIR}/openair3/NAS/COMMON/UTIL/OctetString.c - ${OPENAIR_DIR}/common/utils/utils.c -) - -include_directories( - ${OPENAIR_DIR}/common/utils - ${OPENAIR_DIR}/openair3/NAS/UE - ${OPENAIR_DIR}/openair3/NAS/COMMON - ${OPENAIR_DIR}/openair3/NAS/UE/API/USER - ${OPENAIR_DIR}/openair3/NAS/UE/API/USIM - ${OPENAIR_DIR}/openair3/NAS/UE/EMM/ - ${OPENAIR_DIR}/openair3/NAS/UE/ESM/ - ${OPENAIR_DIR}/openair3/NAS/COMMON/IES/ - ${OPENAIR_DIR}/openair3/NAS/COMMON/UTIL -) - -# conf2uedata binary - -set(conf2uedata_SRC - ${OPENAIR_DIR}/openair3/NAS/TOOLS/conf2uedata.c - ${CONF2UEDATA_LIB_SRC} -) - -add_executable(conf2uedata ${conf2uedata_SRC} ) -target_link_libraries(conf2uedata ${CONFIG_LIBRARIES}) - -# usim binary - -set(usim_SRC - ${OPENAIR_DIR}/openair3/NAS/TOOLS/usim.c - ${CONF2UEDATA_LIB_SRC} -) - - -add_executable(usim ${usim_SRC} ) -target_link_libraries(usim ${CONFIG_LIBRARIES}) - -# nvram binary - -set(nvram_SRC - ${OPENAIR_DIR}/openair3/NAS/TOOLS/nvram.c - ${CONF2UEDATA_LIB_SRC} -) - - -add_executable(nvram ${nvram_SRC}) -target_link_libraries(nvram ${CONFIG_LIBRARIES}) diff --git a/cmake_targets/tools/build_helper b/cmake_targets/tools/build_helper index 264e26d890..f13dd314ef 100755 --- a/cmake_targets/tools/build_helper +++ b/cmake_targets/tools/build_helper @@ -177,7 +177,6 @@ clean_all_files() { dir=$OPENAIR_DIR/cmake_targets rm -rf $dir/ran_build $dir/ran_build_noLOG rm -rf $dir/lte-simulators/build - rm -rf $dir/nas_sim_tools/build rm -rf $dir/oaisim_build_oai/build $dir/oaisim_build_oai/CMakeLists.txt rm -rf $dir/autotests/bin $dir/autotests/log $dir/autotests/*/build } diff --git a/docker/Dockerfile.lteUE.rhel9 b/docker/Dockerfile.lteUE.rhel9 index 9ddf9e1f32..56b7266331 100644 --- a/docker/Dockerfile.lteUE.rhel9 +++ b/docker/Dockerfile.lteUE.rhel9 @@ -55,9 +55,9 @@ RUN dnf update -y && \ WORKDIR /opt/oai-lte-ue/bin COPY --from=lte-ue-build \ /oai-ran/cmake_targets/ran_build/build/lte-uesoftmodem \ - /oai-ran/cmake_targets/nas_sim_tools/build/conf2uedata \ - /oai-ran/cmake_targets/nas_sim_tools/build/nvram \ - /oai-ran/cmake_targets/nas_sim_tools/build/usim \ + /oai-ran/cmake_targets/ran_build/build/conf2uedata \ + /oai-ran/cmake_targets/ran_build/build/nvram \ + /oai-ran/cmake_targets/ran_build/build/usim \ ./ COPY ./docker/scripts/lte_ue_entrypoint.sh ./entrypoint.sh diff --git a/docker/Dockerfile.lteUE.rocky b/docker/Dockerfile.lteUE.rocky index 4d98776c1d..39b99f4e0e 100644 --- a/docker/Dockerfile.lteUE.rocky +++ b/docker/Dockerfile.lteUE.rocky @@ -56,9 +56,9 @@ RUN dnf update -y && \ WORKDIR /opt/oai-lte-ue/bin COPY --from=lte-ue-build \ /oai-ran/cmake_targets/ran_build/build/lte-uesoftmodem \ - /oai-ran/cmake_targets/nas_sim_tools/build/conf2uedata \ - /oai-ran/cmake_targets/nas_sim_tools/build/nvram \ - /oai-ran/cmake_targets/nas_sim_tools/build/usim \ + /oai-ran/cmake_targets/ran_build/build/conf2uedata \ + /oai-ran/cmake_targets/ran_build/build/nvram \ + /oai-ran/cmake_targets/ran_build/build/usim \ ./ COPY ./docker/scripts/lte_ue_entrypoint.sh ./entrypoint.sh diff --git a/docker/Dockerfile.lteUE.ubuntu22 b/docker/Dockerfile.lteUE.ubuntu22 index 5174dab36a..27623dbd33 100644 --- a/docker/Dockerfile.lteUE.ubuntu22 +++ b/docker/Dockerfile.lteUE.ubuntu22 @@ -89,9 +89,9 @@ COPY --from=lte-ue-build /usr/lib/x86_64-linux-gnu/libasan.so.8.0.0 /usr/lib/x86 WORKDIR /opt/oai-lte-ue/bin COPY --from=lte-ue-build \ /oai-ran/cmake_targets/ran_build/build/lte-uesoftmodem \ - /oai-ran/cmake_targets/nas_sim_tools/build/conf2uedata \ - /oai-ran/cmake_targets/nas_sim_tools/build/nvram \ - /oai-ran/cmake_targets/nas_sim_tools/build/usim \ + /oai-ran/cmake_targets/ran_build/build/conf2uedata \ + /oai-ran/cmake_targets/ran_build/build/nvram \ + /oai-ran/cmake_targets/ran_build/build/usim \ ./ COPY ./docker/scripts/lte_ue_entrypoint.sh ./entrypoint.sh diff --git a/openair3/NAS/CMakeLists.txt b/openair3/NAS/CMakeLists.txt index 50bfe97bc3..54ccefb0f5 100644 --- a/openair3/NAS/CMakeLists.txt +++ b/openair3/NAS/CMakeLists.txt @@ -1,3 +1,4 @@ add_subdirectory(COMMON) add_subdirectory(NR_UE) add_subdirectory(UE) +add_subdirectory(TOOLS) diff --git a/openair3/NAS/TOOLS/CMakeLists.txt b/openair3/NAS/TOOLS/CMakeLists.txt new file mode 100755 index 0000000000..e57db8255f --- /dev/null +++ b/openair3/NAS/TOOLS/CMakeLists.txt @@ -0,0 +1,36 @@ +add_library(conf2uedata_lib OBJECT + conf_emm.c + conf_user_data.c + conf_usim.c + conf_network.c + conf_user_plmn.c + conf_parser.c + fs.c + display.c + ../UE/API/USIM/usim_api.c + ../UE/API/USIM/aka_functions.c + ../COMMON/UTIL/OctetString.c + ${OPENAIR_DIR}/common/utils/mem/memory.c + ${OPENAIR_DIR}/common/utils/utils.c +) + +add_executable(conf2uedata conf2uedata.c) +target_link_libraries(conf2uedata PRIVATE conf2uedata_lib) +set_target_properties(conf2uedata PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) +target_link_libraries(conf2uedata PRIVATE LOG minimal_lib ${libconfig_LIBRARIES}) + +add_executable(usim usim.c) +target_link_libraries(usim PRIVATE conf2uedata_lib) +set_target_properties(usim PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) +target_link_libraries(usim PRIVATE LOG minimal_lib ${libconfig_LIBRARIES}) + +add_executable(nvram nvram.c) +target_link_libraries(nvram PRIVATE conf2uedata_lib) +set_target_properties(nvram PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) +target_link_libraries(nvram PRIVATE LOG minimal_lib ${libconfig_LIBRARIES}) + +if (${T_TRACER}) + add_dependencies(conf2uedata generate_T) + add_dependencies(usim generate_T) + add_dependencies(nvram generate_T) +endif (${T_TRACER}) diff --git a/openair3/NAS/TOOLS/conf2uedata.c b/openair3/NAS/TOOLS/conf2uedata.c index 80a6933c05..d746d5ed3d 100644 --- a/openair3/NAS/TOOLS/conf2uedata.c +++ b/openair3/NAS/TOOLS/conf2uedata.c @@ -3,6 +3,7 @@ #include // memset, strncpy #include +#include "log.h" #include "conf2uedata.h" #include "display.h" #include "conf_parser.h" @@ -42,6 +43,7 @@ int main(int argc, char**argv) { exit(1); } + logInit(); if ( parse_config_file(output_dir, conf_file, OUTPUT_ALL) == false ) { exit(1); } diff --git a/openair3/NAS/TOOLS/nvram.c b/openair3/NAS/TOOLS/nvram.c index ad39462dc9..4162e5fc58 100644 --- a/openair3/NAS/TOOLS/nvram.c +++ b/openair3/NAS/TOOLS/nvram.c @@ -42,6 +42,7 @@ Description Implements the utility used to generate data stored in the #include #include +#include "log.h" #include "conf_parser.h" #include "display.h" @@ -104,6 +105,7 @@ int main (int argc, char * const argv[]) _display_usage(argv[0]); exit(EXIT_SUCCESS); } + logInit(); /* compute default data directory if no output_dir is given */ if ( output_dir == NULL ) { diff --git a/openair3/NAS/TOOLS/usim.c b/openair3/NAS/TOOLS/usim.c index 9d74499144..40de38e4b2 100644 --- a/openair3/NAS/TOOLS/usim.c +++ b/openair3/NAS/TOOLS/usim.c @@ -42,6 +42,7 @@ Description Implements the utility used to generate data stored in the #include #include +#include "log.h" #include "conf_parser.h" #include "display.h" @@ -105,6 +106,7 @@ int main (int argc, char * const argv[]) exit(EXIT_SUCCESS); } + logInit(); /* compute default data directory if no output_dir is given */ if ( output_dir == NULL ) { output_dir = getenv(OUTPUT_DIR_ENV); From 990fc9c55ad346baac1019018ca66c2a434e141b Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Thu, 17 Jul 2025 14:28:15 +0200 Subject: [PATCH 296/964] Fix potential out-of-bound write MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tell strncpy() the size including the NULL byte to make sure we copy all data. This just fixes these warnings: openair3/NAS/TOOLS/conf_usim.c: In function ‘gen_usim_data’: openair3/NAS/TOOLS/conf_usim.c:191:17: warning: ‘strncpy’ output truncated before terminating nul copying as many bytes from a string as its length [-Wstringop-truncation] openair3/NAS/TOOLS/conf_usim.c:190:53: note: length computed here openair3/NAS/TOOLS/conf_usim.c:195:17: warning: ‘strncpy’ output truncated before terminating nul copying as many bytes from a string as its length [-Wstringop-truncation] openair3/NAS/TOOLS/conf_usim.c:194:54: note: length computed here add copy with limited size and truncate properly with null C string termination. As clang-format doesn't handle tab indented files and as it is not the OAI coding rule, the entire file is re-indented with present OAI coding rule. --- openair3/NAS/COMMON/UTIL/nas_log.h | 4 +- openair3/NAS/TOOLS/conf_usim.c | 531 ++++++++++++++--------------- 2 files changed, 258 insertions(+), 277 deletions(-) diff --git a/openair3/NAS/COMMON/UTIL/nas_log.h b/openair3/NAS/COMMON/UTIL/nas_log.h index 710c165440..de7b6357fe 100644 --- a/openair3/NAS/COMMON/UTIL/nas_log.h +++ b/openair3/NAS/COMMON/UTIL/nas_log.h @@ -97,6 +97,7 @@ typedef enum { #define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) #ifdef LOG_E + # define LOG_TRACE(s, x, args...) \ do { \ switch (s) { \ @@ -111,9 +112,6 @@ do { \ # define LOG_FUNC_IN LOG_ENTER(NAS) # define LOG_FUNC_OUT LOG_END(NAS) # define LOG_FUNC_RETURN(rETURNcODE) LOG_RETURN(NAS,rETURNcODE) - -extern int nas_log_func_indent; - #else # define LOG_TRACE(s, x, args...) # define LOG_DUMP(dATA, lEN) LOG_DUMPMSG(NAS, LOG_DUMP_CHAR,dATA, lEN, " Dump %d:\n", lEN) diff --git a/openair3/NAS/TOOLS/conf_usim.c b/openair3/NAS/TOOLS/conf_usim.c index 3a5c6dbf6d..f66df1457c 100644 --- a/openair3/NAS/TOOLS/conf_usim.c +++ b/openair3/NAS/TOOLS/conf_usim.c @@ -8,301 +8,284 @@ #include "conf_usim.h" bool parse_ue_sim_param(config_setting_t *ue_setting, int user_id, usim_data_conf_t *u) { - int rc = true; - config_setting_t *ue_param_setting = NULL; - ue_param_setting = config_setting_get_member(ue_setting, SIM); - if (ue_param_setting == NULL) { - printf("Check SIM section for UE%d. EXITING...\n", user_id); - return false; - } - rc = config_setting_lookup_string(ue_param_setting, MSIN, &u->msin); - if (rc != 1 || strlen(u->msin) > 10 || strlen(u->msin) < 9) { - printf("Check SIM MSIN section for UE%d. Exiting\n", user_id); - return false; - } - rc = config_setting_lookup_string(ue_param_setting, USIM_API_K, - &u->usim_api_k); - if (rc != 1) { - printf("Check SIM USIM_API_K section for UE%d. Exiting\n", user_id); - return false; - } - rc = config_setting_lookup_string(ue_param_setting, OPC, &u->opc); - if (rc != 1) { - printf("Check SIM OPC section for UE%d. Exiting\n", user_id); - return false; - } - rc = config_setting_lookup_string(ue_param_setting, MSISDN, &u->msisdn); - if (rc != 1) { - printf("Check SIM MSISDN section for UE%d. Exiting\n", user_id); - return false; - } - return true; + int rc = true; + config_setting_t *ue_param_setting = NULL; + ue_param_setting = config_setting_get_member(ue_setting, SIM); + if (ue_param_setting == NULL) { + printf("Check SIM section for UE%d. EXITING...\n", user_id); + return false; + } + rc = config_setting_lookup_string(ue_param_setting, MSIN, &u->msin); + if (rc != 1 || strlen(u->msin) > 10 || strlen(u->msin) < 9) { + printf("Check SIM MSIN section for UE%d. Exiting\n", user_id); + return false; + } + rc = config_setting_lookup_string(ue_param_setting, USIM_API_K, &u->usim_api_k); + if (rc != 1) { + printf("Check SIM USIM_API_K section for UE%d. Exiting\n", user_id); + return false; + } + rc = config_setting_lookup_string(ue_param_setting, OPC, &u->opc); + if (rc != 1) { + printf("Check SIM OPC section for UE%d. Exiting\n", user_id); + return false; + } + rc = config_setting_lookup_string(ue_param_setting, MSISDN, &u->msisdn); + if (rc != 1) { + printf("Check SIM MSISDN section for UE%d. Exiting\n", user_id); + return false; + } + return true; } void gen_usim_data(usim_data_conf_t *u, usim_data_t *usim_data, const user_plmns_t *user_plmns, const networks_t networks) { - int hplmn_index = get_plmn_index(u->hplmn, networks); - const plmn_conf_param_t *conf = &networks.items[hplmn_index].conf; - memset(usim_data, 0, sizeof(usim_data_t)); - usim_data->imsi.length = 8; - usim_data->imsi.u.num.parity = get_msin_parity(u->msin, - conf->mcc, - conf->mnc); + int hplmn_index = get_plmn_index(u->hplmn, networks); + const plmn_conf_param_t *conf = &networks.items[hplmn_index].conf; + memset(usim_data, 0, sizeof(usim_data_t)); + usim_data->imsi.length = 8; + usim_data->imsi.u.num.parity = get_msin_parity(u->msin, conf->mcc, conf->mnc); - usim_data->imsi.u.num.digit1 = conf->mcc[0]; - usim_data->imsi.u.num.digit2 = conf->mcc[1]; - usim_data->imsi.u.num.digit3 = conf->mcc[2]; + usim_data->imsi.u.num.digit1 = conf->mcc[0]; + usim_data->imsi.u.num.digit2 = conf->mcc[1]; + usim_data->imsi.u.num.digit3 = conf->mcc[2]; - usim_data->imsi.u.num.digit4 = conf->mnc[0]; - usim_data->imsi.u.num.digit5 = conf->mnc[1]; + usim_data->imsi.u.num.digit4 = conf->mnc[0]; + usim_data->imsi.u.num.digit5 = conf->mnc[1]; - if (strlen(conf->mnc) == 2) { - usim_data->imsi.u.num.digit6 = u->msin[0]; - usim_data->imsi.u.num.digit7 = u->msin[1]; - usim_data->imsi.u.num.digit8 = u->msin[2]; - usim_data->imsi.u.num.digit9 = u->msin[3]; - usim_data->imsi.u.num.digit10 = u->msin[4]; - usim_data->imsi.u.num.digit11 = u->msin[5]; - usim_data->imsi.u.num.digit12 = u->msin[6]; - usim_data->imsi.u.num.digit13 = u->msin[7]; - usim_data->imsi.u.num.digit14 = u->msin[8]; - usim_data->imsi.u.num.digit15 = u->msin[9]; - } else { - usim_data->imsi.u.num.digit6 = conf->mnc[2]; - usim_data->imsi.u.num.digit7 = u->msin[0]; - usim_data->imsi.u.num.digit8 = u->msin[1]; - usim_data->imsi.u.num.digit9 = u->msin[2]; - usim_data->imsi.u.num.digit10 = u->msin[3]; - usim_data->imsi.u.num.digit11 = u->msin[4]; - usim_data->imsi.u.num.digit12 = u->msin[5]; - usim_data->imsi.u.num.digit13 = u->msin[6]; - usim_data->imsi.u.num.digit14 = u->msin[7]; - usim_data->imsi.u.num.digit15 = u->msin[8]; - } + if (strlen(conf->mnc) == 2) { + usim_data->imsi.u.num.digit6 = u->msin[0]; + usim_data->imsi.u.num.digit7 = u->msin[1]; + usim_data->imsi.u.num.digit8 = u->msin[2]; + usim_data->imsi.u.num.digit9 = u->msin[3]; + usim_data->imsi.u.num.digit10 = u->msin[4]; + usim_data->imsi.u.num.digit11 = u->msin[5]; + usim_data->imsi.u.num.digit12 = u->msin[6]; + usim_data->imsi.u.num.digit13 = u->msin[7]; + usim_data->imsi.u.num.digit14 = u->msin[8]; + usim_data->imsi.u.num.digit15 = u->msin[9]; + } else { + usim_data->imsi.u.num.digit6 = conf->mnc[2]; + usim_data->imsi.u.num.digit7 = u->msin[0]; + usim_data->imsi.u.num.digit8 = u->msin[1]; + usim_data->imsi.u.num.digit9 = u->msin[2]; + usim_data->imsi.u.num.digit10 = u->msin[3]; + usim_data->imsi.u.num.digit11 = u->msin[4]; + usim_data->imsi.u.num.digit12 = u->msin[5]; + usim_data->imsi.u.num.digit13 = u->msin[6]; + usim_data->imsi.u.num.digit14 = u->msin[7]; + usim_data->imsi.u.num.digit15 = u->msin[8]; + } - /* - * Ciphering and Integrity Keys - */ - usim_data->keys.ksi = KSI; - memset(&usim_data->keys.ck, 0, USIM_CK_SIZE); - memset(&usim_data->keys.ik, 0, USIM_IK_SIZE); - /* - * Higher Priority PLMN search period - */ - usim_data->hpplmn = 0x00; /* Disable timer */ + /* + * Ciphering and Integrity Keys + */ + usim_data->keys.ksi = KSI; + memset(&usim_data->keys.ck, 0, USIM_CK_SIZE); + memset(&usim_data->keys.ik, 0, USIM_IK_SIZE); + /* + * Higher Priority PLMN search period + */ + usim_data->hpplmn = 0x00; /* Disable timer */ - /* - * List of Forbidden PLMNs - */ - for (int i = 0; i < USIM_FPLMN_MAX; i++) { - memset(&usim_data->fplmn[i], 0xff, sizeof(plmn_t)); - } - if (user_plmns->forbiddens.size > 0) { - for (int i = 0; i < user_plmns->forbiddens.size; i++) { - usim_data->fplmn[i] = networks.items[user_plmns->forbiddens.items[i]].plmn; - } - } + /* + * List of Forbidden PLMNs + */ + for (int i = 0; i < USIM_FPLMN_MAX; i++) { + memset(&usim_data->fplmn[i], 0xff, sizeof(plmn_t)); + } + if (user_plmns->forbiddens.size > 0) { + for (int i = 0; i < user_plmns->forbiddens.size; i++) { + usim_data->fplmn[i] = networks.items[user_plmns->forbiddens.items[i]].plmn; + } + } - /* - * Location Information - */ - usim_data->loci.tmsi = DEFAULT_TMSI; - usim_data->loci.lai.plmn = networks.items[hplmn_index].plmn; - usim_data->loci.lai.lac = DEFAULT_LAC; - usim_data->loci.status = USIM_LOCI_NOT_UPDATED; - /* - * Packet Switched Location Information - */ - usim_data->psloci.p_tmsi = DEFAULT_P_TMSI; - usim_data->psloci.signature[0] = 0x01; - usim_data->psloci.signature[1] = 0x02; - usim_data->psloci.signature[2] = 0x03; - usim_data->psloci.rai.plmn = networks.items[hplmn_index].plmn; - usim_data->psloci.rai.lac = DEFAULT_LAC; - usim_data->psloci.rai.rac = DEFAULT_RAC; - usim_data->psloci.status = USIM_PSLOCI_NOT_UPDATED; - /* - * Administrative Data - */ - usim_data->ad.UE_Operation_Mode = USIM_NORMAL_MODE; - usim_data->ad.Additional_Info = 0xffff; - usim_data->ad.MNC_Length = strlen(conf->mnc); - /* - * EPS NAS security context - */ - usim_data->securityctx.length = 52; - usim_data->securityctx.KSIasme.type = USIM_KSI_ASME_TAG; - usim_data->securityctx.KSIasme.length = 1; - usim_data->securityctx.KSIasme.value[0] = KSI_ASME; - usim_data->securityctx.Kasme.type = USIM_K_ASME_TAG; - usim_data->securityctx.Kasme.length = USIM_K_ASME_SIZE; - memset(usim_data->securityctx.Kasme.value, 0, - usim_data->securityctx.Kasme.length); - usim_data->securityctx.ulNAScount.type = USIM_UL_NAS_COUNT_TAG; - usim_data->securityctx.ulNAScount.length = USIM_UL_NAS_COUNT_SIZE; - memset(usim_data->securityctx.ulNAScount.value, 0, - usim_data->securityctx.ulNAScount.length); - usim_data->securityctx.dlNAScount.type = USIM_DL_NAS_COUNT_TAG; - usim_data->securityctx.dlNAScount.length = USIM_DL_NAS_COUNT_SIZE; - memset(usim_data->securityctx.dlNAScount.value, 0, - usim_data->securityctx.dlNAScount.length); - usim_data->securityctx.algorithmID.type = USIM_INT_ENC_ALGORITHMS_TAG; - usim_data->securityctx.algorithmID.length = 1; - usim_data->securityctx.algorithmID.value[0] = SECURITY_ALGORITHMS; - /* - * Subcriber's Number - */ - usim_data->msisdn.length = 7; - usim_data->msisdn.number.ext = 1; - usim_data->msisdn.number.ton = MSISDN_TON_UNKNOWKN; - usim_data->msisdn.number.npi = MSISDN_NPI_ISDN_TELEPHONY; - usim_data->msisdn.conf1_record_id = 0xff; /* Not used */ - usim_data->msisdn.ext1_record_id = 0xff; /* Not used */ - int j = 0; - for (int i = 0; i < strlen(u->msisdn); i += 2) { - usim_data->msisdn.number.digit[j].msb = u->msisdn[i]; - j++; - } - j = 0; - for (int i = 1; i < strlen(u->msisdn); i += 2) { - usim_data->msisdn.number.digit[j].lsb = u->msisdn[i]; - j++; + /* + * Location Information + */ + usim_data->loci.tmsi = DEFAULT_TMSI; + usim_data->loci.lai.plmn = networks.items[hplmn_index].plmn; + usim_data->loci.lai.lac = DEFAULT_LAC; + usim_data->loci.status = USIM_LOCI_NOT_UPDATED; + /* + * Packet Switched Location Information + */ + usim_data->psloci.p_tmsi = DEFAULT_P_TMSI; + usim_data->psloci.signature[0] = 0x01; + usim_data->psloci.signature[1] = 0x02; + usim_data->psloci.signature[2] = 0x03; + usim_data->psloci.rai.plmn = networks.items[hplmn_index].plmn; + usim_data->psloci.rai.lac = DEFAULT_LAC; + usim_data->psloci.rai.rac = DEFAULT_RAC; + usim_data->psloci.status = USIM_PSLOCI_NOT_UPDATED; + /* + * Administrative Data + */ + usim_data->ad.UE_Operation_Mode = USIM_NORMAL_MODE; + usim_data->ad.Additional_Info = 0xffff; + usim_data->ad.MNC_Length = strlen(conf->mnc); + /* + * EPS NAS security context + */ + usim_data->securityctx.length = 52; + usim_data->securityctx.KSIasme.type = USIM_KSI_ASME_TAG; + usim_data->securityctx.KSIasme.length = 1; + usim_data->securityctx.KSIasme.value[0] = KSI_ASME; + usim_data->securityctx.Kasme.type = USIM_K_ASME_TAG; + usim_data->securityctx.Kasme.length = USIM_K_ASME_SIZE; + memset(usim_data->securityctx.Kasme.value, 0, usim_data->securityctx.Kasme.length); + usim_data->securityctx.ulNAScount.type = USIM_UL_NAS_COUNT_TAG; + usim_data->securityctx.ulNAScount.length = USIM_UL_NAS_COUNT_SIZE; + memset(usim_data->securityctx.ulNAScount.value, 0, usim_data->securityctx.ulNAScount.length); + usim_data->securityctx.dlNAScount.type = USIM_DL_NAS_COUNT_TAG; + usim_data->securityctx.dlNAScount.length = USIM_DL_NAS_COUNT_SIZE; + memset(usim_data->securityctx.dlNAScount.value, 0, usim_data->securityctx.dlNAScount.length); + usim_data->securityctx.algorithmID.type = USIM_INT_ENC_ALGORITHMS_TAG; + usim_data->securityctx.algorithmID.length = 1; + usim_data->securityctx.algorithmID.value[0] = SECURITY_ALGORITHMS; + /* + * Subcriber's Number + */ + usim_data->msisdn.length = 7; + usim_data->msisdn.number.ext = 1; + usim_data->msisdn.number.ton = MSISDN_TON_UNKNOWKN; + usim_data->msisdn.number.npi = MSISDN_NPI_ISDN_TELEPHONY; + usim_data->msisdn.conf1_record_id = 0xff; /* Not used */ + usim_data->msisdn.ext1_record_id = 0xff; /* Not used */ + int j = 0; + for (int i = 0; i < strlen(u->msisdn); i += 2) { + usim_data->msisdn.number.digit[j].msb = u->msisdn[i]; + j++; + } + j = 0; + for (int i = 1; i < strlen(u->msisdn); i += 2) { + usim_data->msisdn.number.digit[j].lsb = u->msisdn[i]; + j++; + } + if (strlen(u->msisdn) % 2 == 0) { + for (int i = strlen(u->msisdn) / 2; i < 10; i++) { + usim_data->msisdn.number.digit[i].msb = 0xf; + usim_data->msisdn.number.digit[i].lsb = 0xf; + } + } else { + usim_data->msisdn.number.digit[strlen(u->msisdn) / 2].lsb = 0xf; + for (int i = (strlen(u->msisdn) / 2) + 1; i < 10; i++) { + usim_data->msisdn.number.digit[i].msb = 0xf; + usim_data->msisdn.number.digit[i].lsb = 0xf; + } + } + /* + * PLMN Network Name and Operator PLMN List + */ + for (int i = 0; i < user_plmns->operators.size; i++) { + network_record_t record = networks.items[user_plmns->operators.items[i]].record; + usim_pnn_t *pnn = usim_data->pnn + i; + pnn->fullname.type = USIM_PNN_FULLNAME_TAG; + pnn->fullname.length = min(sizeof(pnn->fullname.value) - 1, strlen(record.fullname)); + memcpy(pnn->fullname.value, record.fullname + 1, pnn->fullname.length); + pnn->fullname.value[pnn->fullname.length] = 0; + pnn->shortname.type = USIM_PNN_SHORTNAME_TAG; + pnn->shortname.length = min(sizeof(pnn->shortname.value) - 1, strlen(record.shortname)); + memcpy(pnn->shortname.value, record.shortname + 1, pnn->shortname.length); + pnn->shortname.value[pnn->shortname.length] = 0; + usim_data->opl[i] = (usim_opl_t){record.plmn, record.tac_start, record.tac_end, i}; + } + if (user_plmns->operators.size < USIM_OPL_MAX) { + for (int i = user_plmns->operators.size; i < USIM_OPL_MAX; i++) { + memset(&usim_data->opl[i].plmn, 0xff, sizeof(plmn_t)); + } + } - } - if (strlen(u->msisdn) % 2 == 0) { - for (int i = strlen(u->msisdn) / 2; i < 10; i++) { - usim_data->msisdn.number.digit[i].msb = 0xf; - usim_data->msisdn.number.digit[i].lsb = 0xf; - } - } else { - usim_data->msisdn.number.digit[strlen(u->msisdn) / 2].lsb = 0xf; - for (int i = (strlen(u->msisdn) / 2) + 1; i < 10; i++) { - usim_data->msisdn.number.digit[i].msb = 0xf; - usim_data->msisdn.number.digit[i].lsb = 0xf; - } - } - /* - * PLMN Network Name and Operator PLMN List - */ - for (int i = 0; i < user_plmns->operators.size; i++) { - network_record_t record = networks.items[user_plmns->operators.items[i]].record; - usim_data->pnn[i].fullname.type = USIM_PNN_FULLNAME_TAG; - usim_data->pnn[i].fullname.length = strlen(record.fullname); - strncpy((char*) usim_data->pnn[i].fullname.value, record.fullname, - usim_data->pnn[i].fullname.length); - usim_data->pnn[i].shortname.type = USIM_PNN_SHORTNAME_TAG; - usim_data->pnn[i].shortname.length = strlen(record.shortname); - strncpy((char*) usim_data->pnn[i].shortname.value, record.shortname, - usim_data->pnn[i].shortname.length); - usim_data->opl[i].plmn = record.plmn; - usim_data->opl[i].start = record.tac_start; - usim_data->opl[i].end = record.tac_end; - usim_data->opl[i].record_id = i; - } - if (user_plmns->operators.size < USIM_OPL_MAX) { - for (int i = user_plmns->operators.size; i < USIM_OPL_MAX; i++) { - memset(&usim_data->opl[i].plmn, 0xff, sizeof(plmn_t)); - } - } + /* + * List of Equivalent HPLMNs + */ + for (int i = 0; i < user_plmns->equivalents_home.size; i++) { + usim_data->ehplmn[i] = networks.items[user_plmns->equivalents_home.items[i]].plmn; + } + if (user_plmns->equivalents_home.size < USIM_EHPLMN_MAX) { + for (int i = user_plmns->equivalents_home.size; i < USIM_EHPLMN_MAX; i++) { + memset(&usim_data->ehplmn[i], 0xff, sizeof(plmn_t)); + } + } + /* + * Home PLMN Selector with Access Technology + */ + usim_data->hplmn.plmn = networks.items[hplmn_index].plmn; + usim_data->hplmn.AcT = (USIM_ACT_GSM | USIM_ACT_UTRAN | USIM_ACT_EUTRAN); - /* - * List of Equivalent HPLMNs - */ - for (int i = 0; i < user_plmns->equivalents_home.size; i++) { - usim_data->ehplmn[i] = networks.items[user_plmns->equivalents_home.items[i]].plmn; - } - if (user_plmns->equivalents_home.size < USIM_EHPLMN_MAX) { - for (int i = user_plmns->equivalents_home.size; i < USIM_EHPLMN_MAX; i++) { - memset(&usim_data->ehplmn[i], 0xff, sizeof(plmn_t)); - } - } - /* - * Home PLMN Selector with Access Technology - */ - usim_data->hplmn.plmn = networks.items[hplmn_index].plmn; - usim_data->hplmn.AcT = (USIM_ACT_GSM | USIM_ACT_UTRAN | USIM_ACT_EUTRAN); + /* + * List of user controlled PLMN selector with Access Technology + */ + for (int i = 0; i < USIM_PLMN_MAX; i++) { + memset(&usim_data->plmn[i], 0xff, sizeof(plmn_t)); + } + if (user_plmns->users_controlled.size > 0) { + for (int i = 0; i < user_plmns->users_controlled.size; i++) { + usim_data->plmn[i].plmn = networks.items[user_plmns->users_controlled.items[i]].plmn; + } + } - /* - * List of user controlled PLMN selector with Access Technology - */ - for (int i = 0; i < USIM_PLMN_MAX; i++) { - memset(&usim_data->plmn[i], 0xff, sizeof(plmn_t)); - } - if (user_plmns->users_controlled.size > 0) { - for (int i = 0; i < user_plmns->users_controlled.size; i++) { - usim_data->plmn[i].plmn = networks.items[user_plmns->users_controlled.items[i]].plmn; - } - } + // List of operator controlled PLMN selector with Access Technology - // List of operator controlled PLMN selector with Access Technology - - for (int i = 0; i < USIM_OPLMN_MAX; i++) { - memset(&usim_data->oplmn[i], 0xff, sizeof(plmn_t)); - } - if (user_plmns->operators_controlled.size > 0) { - for (int i = 0; i < user_plmns->operators_controlled.size; i++) { - usim_data->oplmn[i].plmn = networks.items[user_plmns->operators_controlled.items[i]].plmn; - usim_data->oplmn[i].AcT = (USIM_ACT_GSM | USIM_ACT_UTRAN - | USIM_ACT_EUTRAN); - } - } - /* - * EPS Location Information - */ - usim_data->epsloci.guti.gummei.plmn = - networks.items[hplmn_index].plmn; - usim_data->epsloci.guti.gummei.MMEgid = DEFAULT_MME_ID; - usim_data->epsloci.guti.gummei.MMEcode = DEFAULT_MME_CODE; - usim_data->epsloci.guti.m_tmsi = DEFAULT_M_TMSI; - usim_data->epsloci.tai.plmn = usim_data->epsloci.guti.gummei.plmn; - usim_data->epsloci.tai.tac = DEFAULT_TAC; - usim_data->epsloci.status = USIM_EPSLOCI_UPDATED; - /* - * Non-Access Stratum configuration - */ - usim_data->nasconfig.NAS_SignallingPriority.type = - USIM_NAS_SIGNALLING_PRIORITY_TAG; - usim_data->nasconfig.NAS_SignallingPriority.length = 1; - usim_data->nasconfig.NAS_SignallingPriority.value[0] = 0x00; - usim_data->nasconfig.NMO_I_Behaviour.type = USIM_NMO_I_BEHAVIOUR_TAG; - usim_data->nasconfig.NMO_I_Behaviour.length = 1; - usim_data->nasconfig.NMO_I_Behaviour.value[0] = 0x00; - usim_data->nasconfig.AttachWithImsi.type = USIM_ATTACH_WITH_IMSI_TAG; - usim_data->nasconfig.AttachWithImsi.length = 1; + for (int i = 0; i < USIM_OPLMN_MAX; i++) { + memset(&usim_data->oplmn[i], 0xff, sizeof(plmn_t)); + } + if (user_plmns->operators_controlled.size > 0) { + for (int i = 0; i < user_plmns->operators_controlled.size; i++) { + usim_data->oplmn[i].plmn = networks.items[user_plmns->operators_controlled.items[i]].plmn; + usim_data->oplmn[i].AcT = (USIM_ACT_GSM | USIM_ACT_UTRAN | USIM_ACT_EUTRAN); + } + } + /* + * EPS Location Information + */ + usim_data->epsloci.guti.gummei.plmn = networks.items[hplmn_index].plmn; + usim_data->epsloci.guti.gummei.MMEgid = DEFAULT_MME_ID; + usim_data->epsloci.guti.gummei.MMEcode = DEFAULT_MME_CODE; + usim_data->epsloci.guti.m_tmsi = DEFAULT_M_TMSI; + usim_data->epsloci.tai.plmn = usim_data->epsloci.guti.gummei.plmn; + usim_data->epsloci.tai.tac = DEFAULT_TAC; + usim_data->epsloci.status = USIM_EPSLOCI_UPDATED; + /* + * Non-Access Stratum configuration + */ + usim_data->nasconfig.NAS_SignallingPriority.type = USIM_NAS_SIGNALLING_PRIORITY_TAG; + usim_data->nasconfig.NAS_SignallingPriority.length = 1; + usim_data->nasconfig.NAS_SignallingPriority.value[0] = 0x00; + usim_data->nasconfig.NMO_I_Behaviour.type = USIM_NMO_I_BEHAVIOUR_TAG; + usim_data->nasconfig.NMO_I_Behaviour.length = 1; + usim_data->nasconfig.NMO_I_Behaviour.value[0] = 0x00; + usim_data->nasconfig.AttachWithImsi.type = USIM_ATTACH_WITH_IMSI_TAG; + usim_data->nasconfig.AttachWithImsi.length = 1; #if defined(START_WITH_GUTI) - usim_data->nasconfig.AttachWithImsi.value[0] = 0x00; + usim_data->nasconfig.AttachWithImsi.value[0] = 0x00; #else - usim_data->nasconfig.AttachWithImsi.value[0] = 0x01; + usim_data->nasconfig.AttachWithImsi.value[0] = 0x01; #endif - usim_data->nasconfig.MinimumPeriodicSearchTimer.type = - USIM_MINIMUM_PERIODIC_SEARCH_TIMER_TAG; - usim_data->nasconfig.MinimumPeriodicSearchTimer.length = 1; - usim_data->nasconfig.MinimumPeriodicSearchTimer.value[0] = 0x00; - usim_data->nasconfig.ExtendedAccessBarring.type = - USIM_EXTENDED_ACCESS_BARRING_TAG; - usim_data->nasconfig.ExtendedAccessBarring.length = 1; - usim_data->nasconfig.ExtendedAccessBarring.value[0] = 0x00; - usim_data->nasconfig.Timer_T3245_Behaviour.type = - USIM_TIMER_T3245_BEHAVIOUR_TAG; - usim_data->nasconfig.Timer_T3245_Behaviour.length = 1; - usim_data->nasconfig.Timer_T3245_Behaviour.value[0] = 0x00; + usim_data->nasconfig.MinimumPeriodicSearchTimer.type = USIM_MINIMUM_PERIODIC_SEARCH_TIMER_TAG; + usim_data->nasconfig.MinimumPeriodicSearchTimer.length = 1; + usim_data->nasconfig.MinimumPeriodicSearchTimer.value[0] = 0x00; + usim_data->nasconfig.ExtendedAccessBarring.type = USIM_EXTENDED_ACCESS_BARRING_TAG; + usim_data->nasconfig.ExtendedAccessBarring.length = 1; + usim_data->nasconfig.ExtendedAccessBarring.value[0] = 0x00; + usim_data->nasconfig.Timer_T3245_Behaviour.type = USIM_TIMER_T3245_BEHAVIOUR_TAG; + usim_data->nasconfig.Timer_T3245_Behaviour.length = 1; + usim_data->nasconfig.Timer_T3245_Behaviour.value[0] = 0x00; - /* initialize the subscriber authentication security key */ - if (hex_string_to_hex_value(usim_data->keys.usim_api_k, - u->usim_api_k, USIM_API_K_SIZE) == -1 || - hex_string_to_hex_value(usim_data->keys.opc, - u->opc, OPC_SIZE) == -1) { - fprintf(stderr, "fix your configuration file\n"); - exit(1); - } + /* initialize the subscriber authentication security key */ + if (hex_string_to_hex_value(usim_data->keys.usim_api_k, u->usim_api_k, USIM_API_K_SIZE) == -1 + || hex_string_to_hex_value(usim_data->keys.opc, u->opc, OPC_SIZE) == -1) { + fprintf(stderr, "fix your configuration file\n"); + exit(1); + } } bool write_usim_data(const char *directory, int user_id, usim_data_t *usim_data){ - int rc; - char *filename = make_filename(directory, USIM_API_NVRAM_FILENAME, user_id); - rc = usim_api_write(filename, usim_data); - free(filename); - return rc; + int rc; + char *filename = make_filename(directory, USIM_API_NVRAM_FILENAME, user_id); + rc = usim_api_write(filename, usim_data); + free(filename); + return rc; } From ff52194857cec573e9259c771818fdf36310178f Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 17 Jul 2025 14:02:49 +0200 Subject: [PATCH 297/964] Remove unused parameter from build_oai --- cmake_targets/build_oai | 6 ------ 1 file changed, 6 deletions(-) diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index 83570c80eb..0b6f31d930 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -34,7 +34,6 @@ source "$THIS_SCRIPT_PATH"/tools/build_helper set_openair_env # Variables for UE data generation -gen_nvram_path=$OPENAIR_DIR/cmake_targets/ran_build/build conf_nvram_path=$OPENAIR_DIR/openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf HW="" @@ -93,8 +92,6 @@ Options: Makes the NR UE softmodem --UE-conf-nvram [configuration file] Specify conf_nvram_path (default \"$conf_nvram_path\") ---UE-gen-nvram [output path] - Specify gen_nvram_path (default \"$gen_nvram_path\") -w | --hardware USRP, BLADERF, LMSSDR, IRIS, SIMU, AW2SORI, AERIAL, None (Default) Adds this RF board support (in external packages installation and in compilation) @@ -259,9 +256,6 @@ function main() { --UE-conf-nvram) conf_nvram_path=$(readlink -f "$2") shift 2;; - --UE-gen-nvram) - gen_nvram_path=$(readlink -f "$2") - shift 2;; -w | --hardware) case "$2" in "USRP" | "BLADERF" | "LMSSDR" | "IRIS") From 426e3453cd73dfb363dde8a149c1eb778e00a8d2 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Fri, 18 Jul 2025 10:56:18 +0200 Subject: [PATCH 298/964] trace to try to debug old 4G bug --- openair2/RRC/LTE/rrc_UE.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/openair2/RRC/LTE/rrc_UE.c b/openair2/RRC/LTE/rrc_UE.c index 39b8f426ce..d53d4ea1b1 100644 --- a/openair2/RRC/LTE/rrc_UE.c +++ b/openair2/RRC/LTE/rrc_UE.c @@ -2893,8 +2893,10 @@ int decode_BCCH_DLSCH_Message( // even frame if ((UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus&1) == 0) { LTE_SystemInformationBlockType1_t *sib1 = UE_rrc_inst[ctxt_pP->module_id].sib1[eNB_index]; - memcpy( (void *)sib1, - (void *)&bcch_message->message.choice.c1.choice.systemInformationBlockType1, + if (!sib1) + LOG_E(PHY,"UE_rrc_inst[%d][%d] is null\n", ctxt_pP->module_id, eNB_index); + memcpy( sib1, + &bcch_message->message.choice.c1.choice.systemInformationBlockType1, sizeof(LTE_SystemInformationBlockType1_t) ); LOG_D( RRC, "[UE %"PRIu8"] Decoding First SIB1\n", ctxt_pP->module_id ); decode_SIB1( ctxt_pP, eNB_index, rsrq, rsrp ); From 02ce4aaf82525b2e82de79bfb65f69332484d081 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Fri, 18 Jul 2025 22:05:02 +0200 Subject: [PATCH 299/964] Fix a 4G UE bug --- openair2/LAYER2/MAC/main_ue.c | 2 -- openair2/RRC/LTE/rrc_UE.c | 6 ++++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/openair2/LAYER2/MAC/main_ue.c b/openair2/LAYER2/MAC/main_ue.c index bed2aa5b09..324668b981 100644 --- a/openair2/LAYER2/MAC/main_ue.c +++ b/openair2/LAYER2/MAC/main_ue.c @@ -46,8 +46,6 @@ #include #include "executables/softmodem-common.h" -extern void openair_rrc_top_init_ue( int eMBMS_active, char *uecap_xer, uint8_t cba_group_active, uint8_t HO_active); - void dl_phy_sync_success(module_id_t module_idP, frame_t frameP, unsigned char eNB_index, uint8_t first_sync) { //init as MR LOG_D(MAC, "[UE %d] Frame %d: PHY Sync to eNB_index %d successful \n", module_idP, frameP, eNB_index); diff --git a/openair2/RRC/LTE/rrc_UE.c b/openair2/RRC/LTE/rrc_UE.c index d53d4ea1b1..b9d2551fcb 100644 --- a/openair2/RRC/LTE/rrc_UE.c +++ b/openair2/RRC/LTE/rrc_UE.c @@ -2892,9 +2892,11 @@ int decode_BCCH_DLSCH_Message( if ((ctxt_pP->frame % 2) == 0) { // even frame if ((UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus&1) == 0) { + if (!UE_rrc_inst[ctxt_pP->module_id].sib1[eNB_index]) { + LOG_E(PHY,"UE_rrc_inst[%d].sib1[%d] is null, allocating\n", ctxt_pP->module_id, eNB_index); + openair_rrc_ue_init(ctxt_pP->module_id, eNB_index); + } LTE_SystemInformationBlockType1_t *sib1 = UE_rrc_inst[ctxt_pP->module_id].sib1[eNB_index]; - if (!sib1) - LOG_E(PHY,"UE_rrc_inst[%d][%d] is null\n", ctxt_pP->module_id, eNB_index); memcpy( sib1, &bcch_message->message.choice.c1.choice.systemInformationBlockType1, sizeof(LTE_SystemInformationBlockType1_t) ); From ac6561335c987f2325b474cc2f9e986231293d7e Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Wed, 30 Jul 2025 17:37:34 +0200 Subject: [PATCH 300/964] CI: adjust gNB conf file in OAIUE pipeline Following frequency change in the pipeline, we observed degraded UL channel conditions resulting in low UL throughput. Increasing attenuation on the gNB side was found to mitigate this issue by improving UL channel quality and reducing UL noise power. Increase tested UL and DL bitrates in OAIUE pipeline. --- .../conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf | 2 +- ci-scripts/xml_files/container_sa_n310_nrue.xml | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf b/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf index e30cef3857..396d83cd9d 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf @@ -197,7 +197,7 @@ RUs = ( local_rf = "yes"; nb_tx = 1; nb_rx = 1; - att_tx = 0; + att_tx = 10; att_rx = 0; bands = [78]; max_pdschReferenceSignalPower = -27; diff --git a/ci-scripts/xml_files/container_sa_n310_nrue.xml b/ci-scripts/xml_files/container_sa_n310_nrue.xml index 7d093be3d7..16a23dc57a 100644 --- a/ci-scripts/xml_files/container_sa_n310_nrue.xml +++ b/ci-scripts/xml_files/container_sa_n310_nrue.xml @@ -105,8 +105,8 @@ Iperf - iperf (DL/20Mbps/UDP)(30 sec)(single-ue profile) - -u -b 20M -t 30 -i 1 -R + iperf (DL/30Mbps/UDP)(30 sec) + -u -b 30M -t 30 -i 1 -R oai_ue_caracal oc-cn5g 25 @@ -115,8 +115,8 @@ Iperf - iperf (UL/5Mbps/UDP)(30 sec)(single-ue profile) - -u -b 5M -t 30 -i 1 + iperf (UL/20Mbps/UDP)(30 sec) + -u -b 20M -t 30 -i 1 oai_ue_caracal oc-cn5g 25 From 83bb8017cfd8fc038230486cb7798d3ea91894ba Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 30 Jul 2025 09:14:01 +0200 Subject: [PATCH 301/964] Correct Findsctp.cmake - Provide some documentation - Make cmake keywards and sctp lib name lowercase - Use standard form of find_package_handle_standard_args() - Make an imported target sctp::sctp that will fail if being used in cmake unless defined, which will avoid that "sctp" appears in the cmake code but is silently discarded See also: https://cmake.org/cmake/help/latest/manual/cmake-developer.7.html#a-sample-find-module --- cmake_targets/tools/MODULES/FindSCTP.cmake | 46 ---------------- cmake_targets/tools/MODULES/Findsctp.cmake | 64 ++++++++++++++++++++++ 2 files changed, 64 insertions(+), 46 deletions(-) delete mode 100755 cmake_targets/tools/MODULES/FindSCTP.cmake create mode 100644 cmake_targets/tools/MODULES/Findsctp.cmake diff --git a/cmake_targets/tools/MODULES/FindSCTP.cmake b/cmake_targets/tools/MODULES/FindSCTP.cmake deleted file mode 100755 index de8e878a99..0000000000 --- a/cmake_targets/tools/MODULES/FindSCTP.cmake +++ /dev/null @@ -1,46 +0,0 @@ -# - Try to find SCTP library and headers -# Once done, this will define -# -# SCTP_FOUND - system has SCTP -# SCTP_INCLUDE_DIR - the SCTP include directories -# SCTP_LIBRARIES - link these to use SCTP - -if (SCTP_INCLUDE_DIR AND SCTP_LIBRARIES) - set(SCTP_FIND_QUIETLY TRUE) -endif (SCTP_INCLUDE_DIR AND SCTP_LIBRARIES) - -# Include dir -find_path(SCTP_INCLUDE_DIR - NAMES netinet/sctp.h -) - -# Library -find_library(SCTP_LIBRARY - NAMES sctp -) - -# Set the include dir variables and the libraries and let libfind_process do the rest. -# NOTE: Singular variables for this library, plural for libraries this this lib depends on. -#set(SCTP_PROCESS_INCLUDES SCTP_INCLUDE_DIR) -#set(SCTP_PROCESS_LIBS SCTP_LIBRARY) -#libfind_process(SCTP) - - -# handle the QUIETLY and REQUIRED arguments and set SCTP_FOUND to TRUE if -# all listed variables are TRUE -INCLUDE(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(SCTP DEFAULT_MSG SCTP_LIBRARY SCTP_INCLUDE_DIR) - -# If we successfully found the sctp library then add the library to the -# SCTP_LIBRARIES cmake variable otherwise set SCTP_LIBRARIES to nothing. -IF(SCTP_FOUND) - SET( SCTP_LIBRARIES ${SCTP_LIBRARY} ) -ELSE(SCTP_FOUND) - SET( SCTP_LIBRARIES ) -ENDIF(SCTP_FOUND) - - -# Lastly make it so that the SCTP_LIBRARY and SCTP_INCLUDE_DIR variables -# only show up under the advanced options in the gui cmake applications. -MARK_AS_ADVANCED( SCTP_LIBRARY SCTP_INCLUDE_DIR ) - diff --git a/cmake_targets/tools/MODULES/Findsctp.cmake b/cmake_targets/tools/MODULES/Findsctp.cmake new file mode 100644 index 0000000000..44e3ee6a2b --- /dev/null +++ b/cmake_targets/tools/MODULES/Findsctp.cmake @@ -0,0 +1,64 @@ +# - Try to find SCTP library and headers +# +# Imported Targets +# ^^^^^^^^^^^^^^^^ +# +# This module provides the following imported targets, if found: +# +# ``sctp::sctp`` +# The SCTP library +# +# Result Variables +# ^^^^^^^^^^^^^^^^ +# +# this will define +# +# sctp_FOUND - system has SCTP +# sctp_INCLUDE_DIRS - the SCTP include directories +# sctp_LIBRARIES - link these to use SCTP + +# Include dir +find_path(sctp_INCLUDE_DIR + NAMES netinet/sctp.h +) + +# Library +find_library(sctp_LIBRARY + NAMES sctp +) + +# Set the include dir variables and the libraries and let libfind_process do the rest. +# NOTE: Singular variables for this library, plural for libraries this this lib depends on. +#set(sctp_PROCESS_INCLUDES sctp_INCLUDE_DIR) +#set(sctp_PROCESS_LIBS sctp_LIBRARY) +#libfind_process(sctp) + + +# handle the QUIETLY and REQUIRED arguments and set sctp_FOUND to TRUE if +# all listed variables are TRUE +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(sctp + FOUND_VAR sctp_FOUND + REQUIRED_VARS + sctp_LIBRARY + sctp_INCLUDE_DIR +) + +# If we successfully found the sctp library then add the library to the +# sctp_LIBRARIES cmake variable otherwise set sctp_LIBRARIES to nothing. +if(sctp_FOUND) + set(sctp_LIBRARIES ${sctp_LIBRARY}) + set(sctp_INCLUDE_DIRS ${sctp_INCLUDE_DIR}) +endif() + +if(sctp_FOUND AND NOT TARGET sctp::sctp) + add_library(sctp::sctp UNKNOWN IMPORTED) + set_target_properties(sctp::sctp PROPERTIES + IMPORTED_LOCATION "${sctp_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${sctp_INCLUDE_DIRS}" + ) +endif() + +# Lastly make it so that the SCTP_LIBRARY and SCTP_INCLUDE_DIR variables +# only show up under the advanced options in the gui cmake applications. +mark_as_advanced(SCTP_LIBRARY SCTP_INCLUDE_DIR) From aa82d83228c79f07628b686f4a634cced9427589 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 20 Jan 2025 14:48:59 +0100 Subject: [PATCH 302/964] Correctly link sctp into SCTP_CLIENT Remove sctp from all other targets, since we use sctp::sctp on SCTP_CLIENT (would fail if it does not exist), and SCTP_CLIENT already fulfils the SCTP dependency. --- CMakeLists.txt | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4c78030c30..84d33a0590 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1408,12 +1408,14 @@ add_library(MME_APP ${MME_APP_SRC}) target_link_libraries(MME_APP PRIVATE m2ap m3ap) target_link_libraries(MME_APP PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) +find_package(sctp REQUIRED) set(SCTP_SRC ${OPENAIR3_DIR}/SCTP/sctp_common.c ${OPENAIR3_DIR}/SCTP/sctp_eNB_task.c ${OPENAIR3_DIR}/SCTP/sctp_eNB_itti_messaging.c ) add_library(SCTP_CLIENT ${SCTP_SRC}) +target_link_libraries(SCTP_CLIENT PRIVATE sctp::sctp) target_link_libraries(SCTP_CLIENT PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) set(NAS_SRC ${OPENAIR3_DIR}/NAS/) @@ -1758,7 +1760,7 @@ target_link_libraries(lte-softmodem PRIVATE ${NAS_UE_LIB} ITTI SIMU shlib_loader -Wl,--end-group z dl) -target_link_libraries(lte-softmodem PRIVATE pthread m CONFIG_LIB rt sctp) +target_link_libraries(lte-softmodem PRIVATE pthread m CONFIG_LIB rt) target_link_libraries(lte-softmodem PRIVATE ${T_LIB}) target_link_libraries(lte-softmodem PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) target_link_libraries(lte-softmodem PRIVATE ${blas_LIBRARIES} ${cblas_LIBRARIES} ${lapacke_LIBRARIES} ${lapack_LIBRARIES}) @@ -1814,7 +1816,7 @@ target_link_libraries(lte-uesoftmodem PRIVATE ${NAS_UE_LIB} ITTI shlib_loader -Wl,--end-group z dl) -target_link_libraries(lte-uesoftmodem PRIVATE pthread m CONFIG_LIB rt sctp) +target_link_libraries(lte-uesoftmodem PRIVATE pthread m CONFIG_LIB rt) target_link_libraries(lte-uesoftmodem PRIVATE ${T_LIB}) target_link_libraries(lte-uesoftmodem PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) target_link_libraries(lte-uesoftmodem PRIVATE ${blas_LIBRARIES} ${cblas_LIBRARIES} ${lapacke_LIBRARIES} ${lapack_LIBRARIES}) @@ -1851,7 +1853,7 @@ target_link_libraries(nr-softmodem PRIVATE time_management -Wl,--end-group z dl) -target_link_libraries(nr-softmodem PRIVATE pthread m CONFIG_LIB rt sctp) +target_link_libraries(nr-softmodem PRIVATE pthread m CONFIG_LIB rt) target_link_libraries(nr-softmodem PRIVATE ${T_LIB}) target_link_libraries(nr-softmodem PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) target_link_libraries(nr-softmodem PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) @@ -1888,7 +1890,7 @@ target_link_libraries(nr-cuup PRIVATE CONFIG_LIB ITTI SCTP_CLIENT GTPV1U e1ap f1ap time_management - z sctp dl pthread shlib_loader ${T_LIB}) + z dl pthread shlib_loader ${T_LIB}) target_link_libraries(nr-cuup PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs) if(E2_AGENT) target_link_libraries(nr-cuup PRIVATE e2_agent e2_agent_arg e2_ran_func_cuup) From 1e39f20d872f1489198280643f21379bbbe410f2 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 20 Jan 2025 14:49:37 +0100 Subject: [PATCH 303/964] Make GTP compile on its own, without LTE Avoid the include gtpv1_u_messages_types.h, as this pulls in e.g., LTE RRC definitions. The CU-UP load tester integrated in one of the following commits should be able to build without LTE RRC, if it was for GTP. Unfortunately, ITTI also pulls in LTE RRC, so it's also somewhat useless... Put some forward declarations instead. That also shows that the API is unnecessarily complex, and would need some cleanup. --- openair3/ocp-gtpu/gtp_itf.h | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/openair3/ocp-gtpu/gtp_itf.h b/openair3/ocp-gtpu/gtp_itf.h index 7a8c4da627..a86dbefcf1 100644 --- a/openair3/ocp-gtpu/gtp_itf.h +++ b/openair3/ocp-gtpu/gtp_itf.h @@ -1,16 +1,41 @@ #ifndef __GTPUNEW_ITF_H__ #define __GTPUNEW_ITF_H__ +#include +#include +#include +#include + #define GTPNOK -1 # define GTPU_HEADER_OVERHEAD_MAX 64 -#include "openair2/COMMON/gtpv1_u_messages_types.h" +#include "common/platform_types.h" #include "common/utils/hashtable/hashtable.h" #ifdef __cplusplus extern "C" { #endif +/* forward declaration */ +struct protocol_ctxt_s; +typedef struct protocol_ctxt_s protocol_ctxt_t; +struct gtpv1u_enb_create_tunnel_req_s; +typedef struct gtpv1u_enb_create_tunnel_req_s gtpv1u_enb_create_tunnel_req_t; +struct gtpv1u_enb_create_tunnel_resp_s; +typedef struct gtpv1u_enb_create_tunnel_resp_s gtpv1u_enb_create_tunnel_resp_t; +struct gtpv1u_enb_delete_tunnel_req_s; +typedef struct gtpv1u_enb_delete_tunnel_req_s gtpv1u_enb_delete_tunnel_req_t; +struct gtpv1u_enb_create_x2u_tunnel_req_s; +typedef struct gtpv1u_enb_create_x2u_tunnel_req_s gtpv1u_enb_create_x2u_tunnel_req_t; +struct gtpv1u_enb_create_x2u_tunnel_resp_s; +typedef struct gtpv1u_enb_create_x2u_tunnel_resp_s gtpv1u_enb_create_x2u_tunnel_resp_t; +struct gtpv1u_gnb_create_tunnel_req_s; +typedef struct gtpv1u_gnb_create_tunnel_req_s gtpv1u_gnb_create_tunnel_req_t; +struct gtpv1u_gnb_create_tunnel_resp_s; +typedef struct gtpv1u_gnb_create_tunnel_resp_s gtpv1u_gnb_create_tunnel_resp_t; +struct gtpv1u_gnb_delete_tunnel_req_s; +typedef struct gtpv1u_gnb_delete_tunnel_req_s gtpv1u_gnb_delete_tunnel_req_t; + typedef bool (*gtpCallback)(protocol_ctxt_t *ctxt_pP, const srb_flag_t srb_flagP, const rb_id_t rb_idP, @@ -116,7 +141,7 @@ extern "C" { hash_table_t *ue_mapping; } gtpv1u_data_t; #define GTPV1U_BEARER_OFFSET 3 -#define GTPV1U_MAX_BEARERS_ID (max_val_LTE_DRB_Identity - GTPV1U_BEARER_OFFSET) +#define GTPV1U_MAX_BEARERS_ID (32 - GTPV1U_BEARER_OFFSET) /* max_val_LTE_DRB_Identity */ typedef enum { BEARER_DOWN = 0, BEARER_IN_CONFIG, From dbe9e8684be3861d29ee2f65184fda797e3e587b Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 3 Feb 2025 08:06:21 +0100 Subject: [PATCH 304/964] OAI hashtable not used in GTP --- openair3/ocp-gtpu/gtp_itf.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/openair3/ocp-gtpu/gtp_itf.h b/openair3/ocp-gtpu/gtp_itf.h index a86dbefcf1..f0af60a5f7 100644 --- a/openair3/ocp-gtpu/gtp_itf.h +++ b/openair3/ocp-gtpu/gtp_itf.h @@ -11,7 +11,6 @@ # define GTPU_HEADER_OVERHEAD_MAX 64 #include "common/platform_types.h" -#include "common/utils/hashtable/hashtable.h" #ifdef __cplusplus extern "C" { #endif @@ -135,11 +134,6 @@ typedef struct gtpv1u_gnb_delete_tunnel_req_s gtpv1u_gnb_delete_tunnel_req_t; instance_t gtpv1Init(openAddr_t context); void *gtpv1uTask(void *args); - // Legacy to fix - typedef struct gtpv1u_data_s { - /* RB tree of UEs */ - hash_table_t *ue_mapping; - } gtpv1u_data_t; #define GTPV1U_BEARER_OFFSET 3 #define GTPV1U_MAX_BEARERS_ID (32 - GTPV1U_BEARER_OFFSET) /* max_val_LTE_DRB_Identity */ typedef enum { From 44933f18c61e00b42567976118eab795dd55d9ee Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 4 Feb 2025 19:33:20 +0100 Subject: [PATCH 305/964] Code does nothing: gtpv1u_data_g never populated, always HASH_TABLE_KEY_NOT_EXISTS --- common/ran_context.h | 3 --- openair2/RRC/LTE/rrc_eNB.c | 37 ------------------------------------- 2 files changed, 40 deletions(-) diff --git a/common/ran_context.h b/common/ran_context.h index e009d0987f..91baa78d84 100644 --- a/common/ran_context.h +++ b/common/ran_context.h @@ -46,7 +46,6 @@ struct gNB_RRC_INST_s; struct eNB_MAC_INST_s; struct eNB_MAC_INST_NB_IoT_s; struct gNB_MAC_INST_s; -struct gtpv1u_data_s; struct RU_t_s; typedef struct { @@ -100,8 +99,6 @@ typedef struct { struct eNB_MAC_INST_NB_IoT_s **nb_iot_mac; /// NR MAC context variables struct gNB_MAC_INST_s **nrmac; - /// GTPu descriptor - struct gtpv1u_data_s *gtpv1u_data_g; /// RU descriptors. These describe what each radio unit is supposed to do and contain the necessary functions for fronthaul interfaces struct RU_t_s **ru; /// Mask to indicate fronthaul setup status of RU (hard-limit to 64 RUs) diff --git a/openair2/RRC/LTE/rrc_eNB.c b/openair2/RRC/LTE/rrc_eNB.c index 8d0fd2f8ed..90b2d3b86f 100644 --- a/openair2/RRC/LTE/rrc_eNB.c +++ b/openair2/RRC/LTE/rrc_eNB.c @@ -7721,9 +7721,6 @@ void *rrc_enb_process_itti_msg(void *notUsed) { case X2AP_HANDOVER_REQ_ACK: { struct rrc_eNB_ue_context_s *ue_context_p = NULL; - x2ap_handover_req_ack_t *x2ap_handover_req_ack = NULL; - hashtable_rc_t hash_rc = HASH_TABLE_KEY_NOT_EXISTS; - gtpv1u_ue_data_t *gtpv1u_ue_data_p = NULL; ue_context_p = rrc_eNB_get_ue_context(RC.rrc[instance], X2AP_HANDOVER_REQ_ACK(msg_p).rnti); if (ue_context_p == NULL) { @@ -7738,40 +7735,6 @@ void *rrc_enb_process_itti_msg(void *notUsed) { if (ue_context_p->ue_context.handover_info->state != HO_REQUEST) abort(); - hash_rc = hashtable_get(RC.gtpv1u_data_g->ue_mapping, ue_context_p->ue_context.rnti, (void **)>pv1u_ue_data_p); - - /* set target enb gtp teid */ - if (hash_rc == HASH_TABLE_KEY_NOT_EXISTS) { - LOG_E(RRC, "X2AP_HANDOVER_REQ_ACK func(), hashtable_get failed: while getting ue rnti %x in hashtable ue_mapping\n", ue_context_p->ue_context.rnti); - } else { - uint8_t nb_e_rabs_tobesetup = 0; - ebi_t eps_bearer_id = 0; - int ip_offset = 0; - in_addr_t in_addr; - x2ap_handover_req_ack = &X2AP_HANDOVER_REQ_ACK(msg_p); - nb_e_rabs_tobesetup = x2ap_handover_req_ack->nb_e_rabs_tobesetup; - ue_context_p->ue_context.nb_x2u_e_rabs = nb_e_rabs_tobesetup; - - for (int i = 0; i < nb_e_rabs_tobesetup; i++) { - ip_offset = 0; - eps_bearer_id = x2ap_handover_req_ack->e_rabs_tobesetup[i].e_rab_id; - ue_context_p->ue_context.enb_gtp_x2u_ebi[i] = eps_bearer_id; - ue_context_p->ue_context.enb_gtp_x2u_teid[i] = x2ap_handover_req_ack->e_rabs_tobesetup[i].gtp_teid; - gtpv1u_ue_data_p->bearers[eps_bearer_id - GTPV1U_BEARER_OFFSET].teid_teNB = x2ap_handover_req_ack->e_rabs_tobesetup[i].gtp_teid; - - if ((x2ap_handover_req_ack->e_rabs_tobesetup[i].eNB_addr.length == 4) || (x2ap_handover_req_ack->e_rabs_tobesetup[i].eNB_addr.length == 20)) { - in_addr = *((in_addr_t *)x2ap_handover_req_ack->e_rabs_tobesetup[i].eNB_addr.buffer); - ip_offset = 4; - gtpv1u_ue_data_p->bearers[eps_bearer_id - GTPV1U_BEARER_OFFSET].tenb_ip_addr = in_addr; - ue_context_p->ue_context.enb_gtp_x2u_addrs[i] = x2ap_handover_req_ack->e_rabs_tobesetup[i].eNB_addr; - } - - if ((x2ap_handover_req_ack->e_rabs_tobesetup[i].eNB_addr.length == 16) || (x2ap_handover_req_ack->e_rabs_tobesetup[i].eNB_addr.length == 20)) { - memcpy(gtpv1u_ue_data_p->bearers[eps_bearer_id - GTPV1U_BEARER_OFFSET].tenb_ip6_addr.s6_addr, &x2ap_handover_req_ack->e_rabs_tobesetup[i].eNB_addr.buffer[ip_offset], 16); - } - } - } - rrc_eNB_process_handoverCommand(instance, ue_context_p, &X2AP_HANDOVER_REQ_ACK(msg_p)); ue_context_p->ue_context.handover_info->state = HO_PREPARE; break; From eabb8115136606c202b2716a71bc0f9857141d8c Mon Sep 17 00:00:00 2001 From: Romain Beurdouche Date: Thu, 31 Jul 2025 09:33:27 +0200 Subject: [PATCH 306/964] feat(LDPCImplementation.md): Fix documentation * Outdated names of the functions of the segment coding interface. * Ambiguity about loading of the segment coding libraries. --- openair1/PHY/CODING/DOC/LDPCImplementation.md | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/openair1/PHY/CODING/DOC/LDPCImplementation.md b/openair1/PHY/CODING/DOC/LDPCImplementation.md index 325b208a64..0fae4e1574 100644 --- a/openair1/PHY/CODING/DOC/LDPCImplementation.md +++ b/openair1/PHY/CODING/DOC/LDPCImplementation.md @@ -1,6 +1,6 @@ # LDPC coding implementation The LDPC encoder and decoder are implemented in a shared library, dynamically loaded at run-time using the [oai shared library loader](file://../../../../common/utils/DOC/loader.md). -Two types of library are available with two different interfaces. There are libraries implementing the encoder and decoder of code segments and libraries implementing the encoder and decoder of slots. +Two types of library are available with two different interfaces. There are libraries implementing the encoder and decoder of slots and libraries implementing the encoder and decoder of code segments. ## LDPC slot coding The interface of the library is defined in [nrLDPC_coding_interface.h](file://../nrLDPC_coding/nrLDPC_coding_interface.h). @@ -108,11 +108,12 @@ Libraries implementing the slotwise LDPC coding must be named `libldpc<_version> `libldpc_xdma.so` is completed. ## LDPC segment coding -The interface of the library is defined in [nrLDPC_defs.h](file://../nrLDPC_defs.h). -The code loading the LDPC library is in [nrLDPC_load.c](file://../nrLDPC_load.c), in function `load_nrLDPClib`, which must be called at init time. +The interface of the library is defined in [nrLDPC_defs.h](file://../nrLDPC_defs.h) as typedefs of the functions of the interface. +The name of the functions implementing these typedefs can be found in [nrLDPC_extern.h](file://../nrLDPC_extern.h). LDPC segment coding libraries are not loaded directly by OAI but are statically linked in libraries implementing the LDPC slot coding interface using an adaptation layer between the slot coding interface and the segment coding interface. -This way, these libraries can be loaded to implement the slot coding interface as well as the segment coding interface in `ldpctest`. +This way, these libraries can be loaded to implement the slot coding interface as well as the segment coding interface in `ldpctest`. +`ldpctest` therefore loads directly the segment coding interface with the loader implemented in [nrLDPC_load.c](file://../nrLDPC_load.c) as function `load_nrLDPClib`. ### Selecting the LDPC library at run time @@ -137,7 +138,7 @@ loading `libldpc_cl.so` instead of `libldpc.so`: `make ldpc_cl` -This command creates the `libldpc_cl.so` shared library. To perform this build successfully, only the OpenCL header `(/usr/include/CL/opencl.h)` and library `(/usr/lib/x86_64-linux-gnu/libOpenCL.so)`are required, they implement OpenCL API support which is not hardware dependent. +This command creates the `libldpc_cl.so` shared library. To perform this build successfully, only the OpenCL header `/usr/include/CL/opencl.h` and library `/usr/lib/x86_64-linux-gnu/libOpenCL.so` are required, they implement OpenCL API support which is not hardware dependent. ``` Scanning dependencies of target nrLDPC_decoder_kernels_CL @@ -303,10 +304,15 @@ log init done ### LDPC libraries -Libraries implementing the LDPC algorithms must be named `libldpc<_version>.so`, they must implement three functions: `nrLDPC_initcall` `nrLDPC_decod` and `nrLDPC_encod`. The prototypes for these functions is defined in [nrLDPC_defs.h](file://nrLDPC_defs.h). +The prototypes for the functions of the interface are defined in [nrLDPC_defs.h](file://nrLDPC_defs.h) as typedefs. +Libraries implementing the LDPC algorithms must be named `libldpc<_version>.so`, they must implement four functions with the names and types: +* `LDPCinit` implementing type `LDPC_initfunc_t *` +* `LDPCshutdown` implementing type `LDPC_shutdownfunc_t *` +* `LDPCdecoder` implementing type `LDPC_decoderfunc_t *` +* `LDPCencoder` implementing type `LDPC_encoderfunc_t *` -`libldpc_cuda.so`has been tested with the `ldpctest` executable, usage from the softmodem's has to be tested. +`libldpc_cuda.so` has been tested with the `ldpctest` executable, usage from the softmodem's has to be tested. -`libldpc_cl.so`is under development. +`libldpc_cl.so` is under development. [oai Wikis home](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/home) From ea8e5d85be7b462657fadb13c7d84fa84ccf6382 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 9 Jul 2025 07:31:28 +0200 Subject: [PATCH 307/964] Add telnet command to get UE's BWP --- common/utils/telnetsrv/telnetsrv_ci.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/common/utils/telnetsrv/telnetsrv_ci.c b/common/utils/telnetsrv/telnetsrv_ci.c index fff1423c16..d58071baf2 100644 --- a/common/utils/telnetsrv/telnetsrv_ci.c +++ b/common/utils/telnetsrv/telnetsrv_ci.c @@ -215,6 +215,19 @@ int force_ue_release(char *buf, int debug, telnet_printfunc_t prnt) return 0; } +static int get_current_bwp(char *buf, int debug, telnet_printfunc_t prnt) +{ + int rnti = fetch_rnti(buf, prnt); + NR_UE_info_t *UE = find_nr_UE(&RC.nrmac[0]->UE_info, rnti); + int dl_bwp = UE->current_DL_BWP.bwp_id; + const char *dl_bwp_text = dl_bwp > 0 ? "dedicated" : "initial"; + int ul_bwp = UE->current_UL_BWP.bwp_id; + const char *ul_bwp_text = ul_bwp > 0 ? "dedicated" : "initial"; + + prnt("UE %04x DL BWP ID %d (%s) UL BWP ID %d (%s)\n", UE->rnti, dl_bwp, dl_bwp_text, ul_bwp, ul_bwp_text); + return 0; +} + static telnetshell_cmddef_t cicmds[] = { {"get_single_rnti", "", get_single_rnti}, {"force_reestab", "[rnti(hex,opt)]", trigger_reestab}, @@ -223,6 +236,7 @@ static telnetshell_cmddef_t cicmds[] = { {"force_ul_failure", "[rnti(hex,opt)]", force_ul_failure}, {"trigger_f1_ho", "[rrc_ue_id(int,opt)]", rrc_gNB_trigger_f1_ho}, {"fetch_du_by_ue_id", "[rrc_ue_id(int,opt)]", fetch_du_by_ue_id}, + {"get_current_bwp", "[rnti(hex,opt)]", get_current_bwp}, {"", "", NULL}, }; From aa4c2df59391bdce8fa1213aae4d651519e8a281 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 9 Jul 2025 07:36:41 +0200 Subject: [PATCH 308/964] Remove non-existing XML steps --- ci-scripts/xml_files/container_sa_e1_b200_quectel.xml | 2 -- 1 file changed, 2 deletions(-) diff --git a/ci-scripts/xml_files/container_sa_e1_b200_quectel.xml b/ci-scripts/xml_files/container_sa_e1_b200_quectel.xml index b9535e6ea4..84234e5372 100644 --- a/ci-scripts/xml_files/container_sa_e1_b200_quectel.xml +++ b/ci-scripts/xml_files/container_sa_e1_b200_quectel.xml @@ -30,9 +30,7 @@ 310000 800813 330101 - 800814 330102 - 800815 330103 310001 350000 From 128a6f3945f992a3d827e0f2103c6b5190a7f051 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 9 Jul 2025 07:38:00 +0200 Subject: [PATCH 309/964] Add XML step to check UE is on dedicated BWP --- ci-scripts/xml_files/container_sa_e1_b200_quectel.xml | 8 ++++++++ 1 file changed, 8 insertions(+) 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 84234e5372..4fbffbd9e8 100644 --- a/ci-scripts/xml_files/container_sa_e1_b200_quectel.xml +++ b/ci-scripts/xml_files/container_sa_e1_b200_quectel.xml @@ -33,6 +33,7 @@ 330102 330103 310001 + 400001 350000 370001 370000 @@ -145,6 +146,13 @@ 95 + + Custom_Command + Check UE is on dedicated BWP ID 1 + ofqot + echo ci get_current_bwp | nc -N 127.0.0.1 9091 | grep 'DL BWP ID 1 (dedicated) UL BWP ID 1 (dedicated)' + + Iperf iperf (UL/8Mbps/UDP)(30 sec) From 93196e630bae4f10bb876cfd1f9dd210fe5c83f7 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 30 Jul 2025 16:58:43 +0200 Subject: [PATCH 310/964] Bugfix: when no UE found, return -1 --- common/utils/telnetsrv/telnetsrv_ci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/utils/telnetsrv/telnetsrv_ci.c b/common/utils/telnetsrv/telnetsrv_ci.c index d58071baf2..4b84a8ca93 100644 --- a/common/utils/telnetsrv/telnetsrv_ci.c +++ b/common/utils/telnetsrv/telnetsrv_ci.c @@ -42,7 +42,7 @@ #define TELNETSERVERCODE #include "telnetsrv.h" -#define ERROR_MSG_RET(mSG, aRGS...) do { prnt(mSG, ##aRGS); return 1; } while (0) +#define ERROR_MSG_RET(mSG, aRGS...) do { prnt(mSG, ##aRGS); return -1; } while (0) static int get_single_ue_rnti_mac(void) { From b77be2ae28d7acc86d27e208320d3a82a45d75df Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 30 Jul 2025 17:20:57 +0200 Subject: [PATCH 311/964] Telnet CI: Handle error of no RNTI --- common/utils/telnetsrv/telnetsrv_ci.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/common/utils/telnetsrv/telnetsrv_ci.c b/common/utils/telnetsrv/telnetsrv_ci.c index 4b84a8ca93..24dba02191 100644 --- a/common/utils/telnetsrv/telnetsrv_ci.c +++ b/common/utils/telnetsrv/telnetsrv_ci.c @@ -136,6 +136,8 @@ int trigger_reestab(char *buf, int debug, telnet_printfunc_t prnt) if (!RC.nrmac) ERROR_MSG_RET("no MAC/RLC present, cannot trigger reestablishment\n"); int rnti = fetch_rnti(buf, prnt); + if (rnti < 0) + ERROR_MSG_RET("could not identify UE (no UE, no such RNTI, or multiple UEs)\n"); nr_rlc_test_trigger_reestablishment(rnti); prnt("Reset RLC counters of UE RNTI %04x to trigger reestablishment\n", rnti); return 0; @@ -199,6 +201,8 @@ int force_ul_failure(char *buf, int debug, telnet_printfunc_t prnt) if (!RC.nrmac) ERROR_MSG_RET("no MAC/RLC present, force_ul_failure failed\n"); int rnti = fetch_rnti(buf, prnt); + if (rnti < 0) + ERROR_MSG_RET("could not identify UE (no UE, no such RNTI, or multiple UEs)\n"); NR_UE_info_t *UE = find_nr_UE(&RC.nrmac[0]->UE_info, rnti); nr_mac_trigger_ul_failure(&UE->UE_sched_ctrl, UE->current_UL_BWP.scs); return 0; @@ -208,6 +212,8 @@ int force_ue_release(char *buf, int debug, telnet_printfunc_t prnt) { force_ul_failure(buf, debug, prnt); int rnti = fetch_rnti(buf, prnt); + if (rnti < 0) + ERROR_MSG_RET("could not identify UE (no UE, no such RNTI, or multiple UEs)\n"); NR_UE_info_t *UE = find_nr_UE(&RC.nrmac[0]->UE_info, rnti); NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; sched_ctrl->ul_failure_timer = 2; @@ -218,6 +224,8 @@ int force_ue_release(char *buf, int debug, telnet_printfunc_t prnt) static int get_current_bwp(char *buf, int debug, telnet_printfunc_t prnt) { int rnti = fetch_rnti(buf, prnt); + if (rnti < 0) + ERROR_MSG_RET("could not identify UE (no UE, no such RNTI, or multiple UEs)\n"); NR_UE_info_t *UE = find_nr_UE(&RC.nrmac[0]->UE_info, rnti); int dl_bwp = UE->current_DL_BWP.bwp_id; const char *dl_bwp_text = dl_bwp > 0 ? "dedicated" : "initial"; From 228f64275507aef5594a2216685ddc2dc7228cf5 Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 31 Jul 2025 15:30:09 +0200 Subject: [PATCH 312/964] config_isparamset doesn't work for array types, using numelt instead --- openair2/GNB_APP/gnb_config.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 5274a4696d..2e6915016a 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -1503,7 +1503,8 @@ static seq_arr_t *fill_du_sibs(paramdef_t *GNBparamarray) if (NODE_IS_DU(get_node_type())) AssertFatal(GNBparamarray[GNB_CU_SIBS_IDX].numelt == 0, "This is DU, do not input CU SIBs\n"); - if (!config_isparamset(GNBparamarray, GNB_DU_SIBS_IDX)) + // TODO config_isparamset doesn't seem to work for array types, checking numelt instead + if (GNBparamarray[GNB_DU_SIBS_IDX].numelt == 0) return NULL; seq_arr_t *du_SIBs = malloc(sizeof(seq_arr_t)); @@ -1808,12 +1809,13 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg) beam_info->beams_per_period = beams_per_period; beam_info->beam_allocation_size = -1; // to be initialized once we have information on frame configuration } - if (config_isparamset(MacRLC_ParamList.paramarray[j], MACRLC_BEAMWEIGHTS_IDX)) { + // TODO config_isparamset doesn't seem to work for array types, checking numelt instead + int n = MacRLC_ParamList.paramarray[j][MACRLC_BEAMWEIGHTS_IDX].numelt; + if (n > 0) { if (NFAPI_MODE == NFAPI_MONOLITHIC) { GET_PARAMS_LIST(L1_ParamList, L1_Params, L1PARAMS_DESC, CONFIG_STRING_L1_LIST, NULL); AssertFatal(*(L1_ParamList.paramarray[j][L1_ANALOG_DAS].uptr) == 0, "No need to set beam weights in case of DAS\n"); } - int n = MacRLC_ParamList.paramarray[j][MACRLC_BEAMWEIGHTS_IDX].numelt; int num_beam = n; if (!ab) { AssertFatal(n % num_tx == 0, "Error! Number of beam input needs to be multiple of TX antennas\n"); @@ -1998,7 +2000,8 @@ static seq_arr_t *fill_cu_sibs(paramdef_t *GNBparamarray) if (NODE_IS_CU(get_node_type())) AssertFatal(GNBparamarray[GNB_DU_SIBS_IDX].numelt == 0, "This is CU, do not input DU SIBs\n"); - if (!config_isparamset(GNBparamarray, GNB_CU_SIBS_IDX)) + // TODO config_isparamset doesn't seem to work for array types, checking numelt instead + if (GNBparamarray[GNB_CU_SIBS_IDX].numelt == 0) return NULL; seq_arr_t *SIBs = malloc(sizeof(seq_arr_t)); From 73cfaba2dc40a6f0599ad85f7cbbbe2bc70dd793 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Thu, 24 Jul 2025 21:04:28 +0200 Subject: [PATCH 313/964] CI: refactor iperf3 UDP analysis function - Add helper function to normalize bitrate values to Mbps for calculations. - Add helper function to extract data from iperf test report. - Clean up the UDP analysis function, improve test report formatting. - Fix an issue where Gbps values were incorrectly reported due to inconsistent unit parsing. - Update CI unit test report checks to match the new formatting. --- ci-scripts/cls_oaicitest.py | 101 ++++++++++---------- ci-scripts/tests/log/iperf_udp_msg_nok.txt | 6 +- ci-scripts/tests/log/iperf_udp_msg_nok2.txt | 6 +- ci-scripts/tests/log/iperf_udp_msg_nok3.txt | 6 +- ci-scripts/tests/log/iperf_udp_msg_ok.txt | 6 +- ci-scripts/tests/log/iperf_udp_msg_ok2.txt | 6 +- 6 files changed, 67 insertions(+), 64 deletions(-) diff --git a/ci-scripts/cls_oaicitest.py b/ci-scripts/cls_oaicitest.py index 53bdacaacc..5cb2708efc 100644 --- a/ci-scripts/cls_oaicitest.py +++ b/ci-scripts/cls_oaicitest.py @@ -83,6 +83,29 @@ def Iperf_ComputeTime(args): raise Exception('Iperf time not found!') return int(result.group('iperf_time')) +def convert_to_mbps(value, magnitude): + value = float(value) + if magnitude == 'K' or magnitude == 'k': + return value / 1000 + elif magnitude == 'M': + return value + elif magnitude == 'G': + return value * 1000 + else: + return value + +def extract_iperf_data(res): + if not res: + return None + bitrate_val = res.group('bitrate') + magnitude = res.group('magnitude') + return { + 'bitrate_mbps': convert_to_mbps(bitrate_val, magnitude), + 'jitter': res.group('jitter'), + 'packetloss': res.group('packetloss'), + 'bitrate_disp': f'{float(bitrate_val):.2f} {magnitude}bps' + } + def Iperf_analyzeV3TCPJson(filename, iperf_tcp_rate_target): try: with open(filename) as f: @@ -130,54 +153,37 @@ def Iperf_analyzeV3BIDIRJson(filename): return (True, msg) def Iperf_analyzeV3UDP(filename, iperf_bitrate_threshold, iperf_packetloss_threshold, target_bitrate): - if (not os.path.isfile(filename)): + if not os.path.isfile(filename): return (False, 'Iperf3 UDP: Log file not present') - if (os.path.getsize(filename)==0): + if os.path.getsize(filename) == 0: return (False, 'Iperf3 UDP: Log file is empty') - sender_bitrate = None - receiver_bitrate = None - with open(filename, 'r') as server_file: - for line in server_file.readlines(): - res_sender = re.search(r'(?P[0-9\.]+)\s+(?P[KMG]?bits\/sec)\s+(?P[0-9\.]+\s+ms)\s+(?P-?\d+)/(?P-?\d+) \((?P[0-9\.]+).*?\s+(sender)', line) - res_receiver = re.search(r'(?P[0-9\.]+)\s+(?P[KMG]?bits\/sec)\s+(?P[0-9\.]+\s+ms)\s+(?P-?\d+)/(?P-?\d+)\s+\((?P[0-9\.]+)%\).*?(receiver)', line) - if res_sender is not None: - sender_bitrate = res_sender.group('bitrate') - sender_unit = res_sender.group('unit') - sender_jitter = res_sender.group('jitter') - sender_lostPack = res_sender.group('lostPack') - sender_sentPack = res_sender.group('sentPack') - sender_packetloss = res_sender.group('lost') - if res_receiver is not None: - receiver_bitrate = res_receiver.group('bitrate') - receiver_unit = res_receiver.group('unit') - receiver_jitter = res_receiver.group('jitter') - receiver_lostPack = res_receiver.group('lostPack') - receiver_receivedPack = res_receiver.group('receivedPack') - receiver_packetloss = res_receiver.group('lost') - if receiver_bitrate is not None and sender_bitrate is not None: - if sender_unit == 'Kbits/sec': - sender_bitrate = float(sender_bitrate) / 1000 - if receiver_unit == 'Kbits/sec': - receiver_bitrate = float(receiver_bitrate) / 1000 - br_perf = 100 * float(receiver_bitrate) / float(target_bitrate) - br_perf = '%.2f ' % br_perf - sender_bitrate = '%.2f ' % float(sender_bitrate) - receiver_bitrate = '%.2f ' % float(receiver_bitrate) - req_msg = f'Sender Bitrate : {sender_bitrate} Mbps' - bir_msg = f'Receiver Bitrate: {receiver_bitrate} Mbps' - brl_msg = f'{br_perf}%' - jit_msg = f'Jitter : {receiver_jitter}' - pal_msg = f'Packet Loss : {receiver_packetloss} %' - if float(br_perf) < float(iperf_bitrate_threshold): - brl_msg = f'too low! < {iperf_bitrate_threshold}%' - if float(receiver_packetloss) > float(iperf_packetloss_threshold): - pal_msg += f' (too high! > {iperf_packetloss_threshold}%)' - result = float(br_perf) >= float(iperf_bitrate_threshold) and float(receiver_packetloss) <= float(iperf_packetloss_threshold) - return (result, f'{req_msg}\n{bir_msg} ({brl_msg})\n{jit_msg}\n{pal_msg}') - else: + sender_data = None + receiver_data = None + with open(filename, 'r') as server_file: + for line in server_file: + res_sender = re.search(r'(?P[0-9\.]+)\s+(?P[kKMG]?)bits\/sec\s+(?P[0-9\.]+\s+ms)\s+(?P-?\d+)/(?P-?\d+)\s+\((?P[0-9\.eE\-\+]+).*?\s+(sender)', line) + res_receiver = re.search(r'(?P[0-9\.]+)\s+(?P[kKMG]?)bits\/sec\s+(?P[0-9\.]+\s+ms)\s+(?P-?\d+)/(?P-?\d+)\s+\((?P[0-9\.eE\-\+]+)%\).*?(receiver)', line) + if res_sender: + sender_data = extract_iperf_data(res_sender) + if res_receiver: + receiver_data = extract_iperf_data(res_receiver) + if not sender_data or not receiver_data: return (False, 'Could not analyze iperf report') + br_perf = 100 * receiver_data['bitrate_mbps'] / float(target_bitrate) + br_perf_str = f'{br_perf:.2f}%' + req_msg = f"Sender Bitrate : {sender_data['bitrate_disp']}" + bir_msg = f"Receiver Bitrate: {receiver_data['bitrate_disp']} ({br_perf_str})" + jit_msg = f"Jitter : {receiver_data['jitter']}" + pal_msg = f"Packet Loss : {receiver_data['packetloss']}%" + if br_perf < float(iperf_bitrate_threshold): + bir_msg += f' (too low! < {iperf_bitrate_threshold}%)' + if float(receiver_data['packetloss']) > float(iperf_packetloss_threshold): + pal_msg += f' (too high! > {iperf_packetloss_threshold}%)' + result = br_perf >= float(iperf_bitrate_threshold) and float(receiver_data['packetloss']) <= float(iperf_packetloss_threshold) + return (result, f'{req_msg}\n{bir_msg}\n{jit_msg}\n{pal_msg}') + def Iperf_analyzeV2UDP(server_filename, iperf_bitrate_threshold, iperf_packetloss_threshold, target_bitrate): result = None if (not os.path.isfile(server_filename)): @@ -190,12 +196,9 @@ def Iperf_analyzeV2UDP(server_filename, iperf_bitrate_threshold, iperf_packetlos result = re.search(statusTemplate, str(line)) or result if result is None: return (False, 'Could not parse server report!') - bitrate = float(result.group('bitrate')) - magn = result.group('magnitude') - if magn == "k" or magn == "K": - bitrate /= 1000 - elif magn == "G": # we assume bitrate in Mbps, therefore it must be G now - bitrate *= 1000 + bitrate_val = float(result.group('bitrate')) + magnitude = result.group('magnitude') + bitrate = convert_to_mbps(bitrate_val, magnitude) jitter = float(result.group('jitter')) packetloss = float(result.group('packetloss')) br_perf = float(bitrate)/float(target_bitrate) * 100 diff --git a/ci-scripts/tests/log/iperf_udp_msg_nok.txt b/ci-scripts/tests/log/iperf_udp_msg_nok.txt index 0e03a2dc76..a2ec0e22d6 100644 --- a/ci-scripts/tests/log/iperf_udp_msg_nok.txt +++ b/ci-scripts/tests/log/iperf_udp_msg_nok.txt @@ -1,4 +1,4 @@ -Sender Bitrate : 0.52 Mbps -Receiver Bitrate: 0.52 Mbps (too low! < 99%) +Sender Bitrate : 524.00 Kbps +Receiver Bitrate: 524.00 Kbps (52.40%) (too low! < 99%) Jitter : 0.026 ms -Packet Loss : 10 % (too high! > 0%) +Packet Loss : 10% (too high! > 0%) diff --git a/ci-scripts/tests/log/iperf_udp_msg_nok2.txt b/ci-scripts/tests/log/iperf_udp_msg_nok2.txt index c0c34193f2..e24cc1402a 100644 --- a/ci-scripts/tests/log/iperf_udp_msg_nok2.txt +++ b/ci-scripts/tests/log/iperf_udp_msg_nok2.txt @@ -1,4 +1,4 @@ -Sender Bitrate : 0.00 Mbps -Receiver Bitrate: 3.98 Mbps (too low! < 99%) +Sender Bitrate : 0.00 bps +Receiver Bitrate: 3.98 Mbps (4.97%) (too low! < 99%) Jitter : 3.847 ms -Packet Loss : 0.038 % (too high! > 0%) +Packet Loss : 0.038% (too high! > 0%) diff --git a/ci-scripts/tests/log/iperf_udp_msg_nok3.txt b/ci-scripts/tests/log/iperf_udp_msg_nok3.txt index c302493e85..b027491913 100644 --- a/ci-scripts/tests/log/iperf_udp_msg_nok3.txt +++ b/ci-scripts/tests/log/iperf_udp_msg_nok3.txt @@ -1,4 +1,4 @@ -Sender Bitrate : 1.03 Mbps -Receiver Bitrate: 0.00 Mbps (too low! < 99%) +Sender Bitrate : 1.03 Mbps +Receiver Bitrate: 0.00 bps (0.00%) (too low! < 99%) Jitter : 0.000 ms -Packet Loss : 0 % +Packet Loss : 0% diff --git a/ci-scripts/tests/log/iperf_udp_msg_ok.txt b/ci-scripts/tests/log/iperf_udp_msg_ok.txt index defea05c79..a771c6fdb1 100644 --- a/ci-scripts/tests/log/iperf_udp_msg_ok.txt +++ b/ci-scripts/tests/log/iperf_udp_msg_ok.txt @@ -1,4 +1,4 @@ -Sender Bitrate : 1.00 Mbps -Receiver Bitrate: 1.00 Mbps (99.60 %) +Sender Bitrate : 996.00 Kbps +Receiver Bitrate: 996.00 Kbps (99.60%) Jitter : 0.029 ms -Packet Loss : 0 % +Packet Loss : 0% diff --git a/ci-scripts/tests/log/iperf_udp_msg_ok2.txt b/ci-scripts/tests/log/iperf_udp_msg_ok2.txt index 31a5ec14cd..856b851112 100644 --- a/ci-scripts/tests/log/iperf_udp_msg_ok2.txt +++ b/ci-scripts/tests/log/iperf_udp_msg_ok2.txt @@ -1,4 +1,4 @@ -Sender Bitrate : 4.67 Mbps -Receiver Bitrate: 4.67 Mbps (100.00 %) +Sender Bitrate : 4.67 Mbps +Receiver Bitrate: 4.67 Mbps (100.00%) Jitter : 3.413 ms -Packet Loss : 0 % +Packet Loss : 0% From a9f10bd794ad828af12b14dbd7db05965984362c Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Thu, 31 Jul 2025 11:26:55 +0200 Subject: [PATCH 314/964] Add CI unit test for highrate iperf test --- ci-scripts/tests/ping-iperf.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/ci-scripts/tests/ping-iperf.py b/ci-scripts/tests/ping-iperf.py index 225fe4e868..de68122cee 100644 --- a/ci-scripts/tests/ping-iperf.py +++ b/ci-scripts/tests/ping-iperf.py @@ -60,5 +60,20 @@ class TestPingIperf(unittest.TestCase): success = self.ci.Iperf2_Unidir(self.html, self.cont, infra_file=infra_file) self.assertTrue(success) + def test_iperf_highrate(self): + # note: needs to be five seconds because Iperf() adds -O 3, so if it is + # too short, the server is terminated before the client loaded + # everything + self.ci.iperf_args = "-u -t 5 -b 1000M -R -O 0" + self.ci.svr_id = "test" + self.ci.svr_node = "localhost" + self.ci.iperf_packetloss_threshold = "0" + self.ci.iperf_bitrate_threshold = "0" + self.ci.iperf_profile = "balanced" + infra_file = "tests/config/infra_ping_iperf.yaml" + # TODO Should need nothing but options and UE(s) to use + success = self.ci.Iperf(self.html, self.cont, infra_file=infra_file) + self.assertTrue(success) + if __name__ == '__main__': unittest.main() From af3302d2d6d41f7b8a4b2da6f790f086c3537c30 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 1 Aug 2025 11:32:49 +0200 Subject: [PATCH 315/964] Remove unused statement --- ci-scripts/ran.py | 1 - 1 file changed, 1 deletion(-) diff --git a/ci-scripts/ran.py b/ci-scripts/ran.py index f0f790ba2c..46711b1b73 100644 --- a/ci-scripts/ran.py +++ b/ci-scripts/ran.py @@ -124,7 +124,6 @@ class RANManagement(): self.testCase_id = HTML.testCase_id mySSH = SSH.SSHConnection() - cwd = os.getcwd() mySSH.open(lIpAddr, lUserName, lPassWord) mySSH.command('cd ' + lSourcePath, '\$', 5) From be60dbd38c280064c18afe79eaf259e859e38d00 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 31 Jul 2025 18:28:46 +0200 Subject: [PATCH 316/964] CI: shorten UE names (IP might not be available) --- ci-scripts/cls_module.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci-scripts/cls_module.py b/ci-scripts/cls_module.py index 3ec6ffc9e5..65edbfdb56 100644 --- a/ci-scripts/cls_module.py +++ b/ci-scripts/cls_module.py @@ -65,7 +65,7 @@ class Module_UE: logging.info(f'initialized UE {self} from {filename}') def __str__(self): - return f"{self.module_name}@{self.host} [IP: {self.getIP()}]" + return f"{self.module_name}@{self.host}" def __repr__(self): return self.__str__() From 442c29cfcd51b9f00db1433ef262638c450b0069 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 31 Jul 2025 18:29:00 +0200 Subject: [PATCH 317/964] CI: use getConnection() to simplify code --- ci-scripts/cls_module.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/ci-scripts/cls_module.py b/ci-scripts/cls_module.py index 65edbfdb56..3fed4f3dd6 100644 --- a/ci-scripts/cls_module.py +++ b/ci-scripts/cls_module.py @@ -73,12 +73,8 @@ class Module_UE: def _command(self, cmd, silent = False): if cmd is None: raise Exception("no command provided") - if self.host == "" or self.host == "localhost": - c = cls_cmd.LocalCmd() - else: - c = cls_cmd.RemoteCmd(self.host) - response = c.run(cmd, silent=silent) - c.close() + with cls_cmd.getConnection(self.host) as c: + response = c.run(cmd, silent=silent) return response #-----------------$ From bbf4cd4a90109dcae1e996e6d79488e4fe0621d8 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Fri, 1 Aug 2025 13:38:05 +0200 Subject: [PATCH 318/964] gNB: fix scheduling of rel-17 SIBs --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c index a6d48037a7..134b43f583 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c @@ -775,7 +775,7 @@ static bool test_other_sib_sched_occasion(int window_pos, int rel_frame, int rel_slot) { - int x = window_pos * window_len; + int x = (window_pos - 1) * window_len; int T = 8 << period; int test_frame = (frame - rel_frame) % MAX_FRAME_NUMBER; int si_slot = (x % n_slots_frame) + rel_slot; @@ -848,7 +848,7 @@ void schedule_nr_other_sib(module_id_t module_idP, for (int ssb = 0; ssb < num_ssb; ssb++) { for (int i = 0; i < schedInfo->schedulingInfoList.list.count; i++) { NR_SchedulingInfo_t *schedulingInfo = schedInfo->schedulingInfoList.list.array[i]; - if (test_other_sib_sched_occasion(i, + if (test_other_sib_sched_occasion(i + 1, window_length_sl, schedulingInfo->si_Periodicity, n_slots_frame, From aff31d45b40f9038d967abbdd287eb9b78b217ca Mon Sep 17 00:00:00 2001 From: francescomani Date: Sun, 3 Aug 2025 10:25:00 +0200 Subject: [PATCH 319/964] formatting --- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 38 +++++++++---------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index f8c842706c..e5f2939df8 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -429,32 +429,28 @@ NR_sched_pdcch_t set_pdcch_structure(gNB_MAC_INST *gNB_mac, NR_ControlResourceSet_t *coreset, NR_ServingCellConfigCommon_t *scc, NR_BWP_t *bwp, - NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config) { - - int sps; - NR_sched_pdcch_t pdcch; - + NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config) +{ AssertFatal(*ss->controlResourceSetId == coreset->controlResourceSetId, "coreset id in SS %ld does not correspond to the one in coreset %ld", *ss->controlResourceSetId, coreset->controlResourceSetId); + int sps; + NR_sched_pdcch_t pdcch; if (bwp) { // This is not for SIB1 - if(coreset->controlResourceSetId == 0){ - pdcch.BWPSize = gNB_mac->cset0_bwp_size; + if(coreset->controlResourceSetId == 0) { + pdcch.BWPSize = gNB_mac->cset0_bwp_size; pdcch.BWPStart = gNB_mac->cset0_bwp_start; - } - else { - pdcch.BWPSize = NRRIV2BW(bwp->locationAndBandwidth, MAX_BWP_SIZE); + } else { + pdcch.BWPSize = NRRIV2BW(bwp->locationAndBandwidth, MAX_BWP_SIZE); pdcch.BWPStart = NRRIV2PRBOFFSET(bwp->locationAndBandwidth, MAX_BWP_SIZE); } pdcch.SubcarrierSpacing = bwp->subcarrierSpacing; - pdcch.CyclicPrefix = (bwp->cyclicPrefix==NULL) ? 0 : *bwp->cyclicPrefix; - + pdcch.CyclicPrefix = (bwp->cyclicPrefix == NULL) ? 0 : *bwp->cyclicPrefix; //AssertFatal(pdcch_scs==kHz15, "PDCCH SCS above 15kHz not allowed if a symbol above 2 is monitored"); sps = bwp->cyclicPrefix == NULL ? 14 : 12; - } - else { - AssertFatal(type0_PDCCH_CSS_config!=NULL,"type0_PDCCH_CSS_config is null,bwp %p\n",bwp); + } else { + AssertFatal(type0_PDCCH_CSS_config != NULL, "type0_PDCCH_CSS_config is null,bwp %p\n", bwp); pdcch.BWPSize = type0_PDCCH_CSS_config->num_rbs; pdcch.BWPStart = type0_PDCCH_CSS_config->cset_start_rb; pdcch.SubcarrierSpacing = type0_PDCCH_CSS_config->scs_pdcch; @@ -462,15 +458,15 @@ NR_sched_pdcch_t set_pdcch_structure(gNB_MAC_INST *gNB_mac, sps = 14; } - AssertFatal(ss->monitoringSymbolsWithinSlot!=NULL,"ss->monitoringSymbolsWithinSlot is null\n"); - AssertFatal(ss->monitoringSymbolsWithinSlot->buf!=NULL,"ss->monitoringSymbolsWithinSlot->buf is null\n"); + AssertFatal(ss->monitoringSymbolsWithinSlot != NULL, "ss->monitoringSymbolsWithinSlot is null\n"); + BIT_STRING_t *symbolsInSlot = ss->monitoringSymbolsWithinSlot; + AssertFatal(symbolsInSlot->buf != NULL, "ss->monitoringSymbolsWithinSlot->buf is null\n"); // for SPS=14 8 MSBs in positions 13 downto 6 - uint16_t monitoringSymbolsWithinSlot = (ss->monitoringSymbolsWithinSlot->buf[0]<<(sps-8)) | - (ss->monitoringSymbolsWithinSlot->buf[1]>>(16-sps)); + int monitoringSymbolsWithinSlot = (symbolsInSlot->buf[0] << (sps - 8)) | (symbolsInSlot->buf[1] >> (16 - sps)); - for (int i=0; i>(sps-1-i))&1) { + for (int i = 0; i < sps; i++) { + if ((monitoringSymbolsWithinSlot >> (sps - 1 - i)) & 1) { pdcch.StartSymbolIndex=i; break; } From 7f4397a091f2da284fb416091fafd4a2cc7a956f Mon Sep 17 00:00:00 2001 From: francescomani Date: Sun, 3 Aug 2025 10:35:46 +0200 Subject: [PATCH 320/964] workaround to take into account SS0 1st symbol depending on SSB --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index e5f2939df8..9828531c35 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -467,7 +467,7 @@ NR_sched_pdcch_t set_pdcch_structure(gNB_MAC_INST *gNB_mac, for (int i = 0; i < sps; i++) { if ((monitoringSymbolsWithinSlot >> (sps - 1 - i)) & 1) { - pdcch.StartSymbolIndex=i; + pdcch.StartSymbolIndex = ss->searchSpaceId == 0 ? i + type0_PDCCH_CSS_config->first_symbol_index : i; break; } } From 88ec5fb239a9de6395e5c9eea9f00f38228c5276 Mon Sep 17 00:00:00 2001 From: francescomani Date: Sun, 3 Aug 2025 10:41:16 +0200 Subject: [PATCH 321/964] highlighting UE LOG with sync SSC printed --- openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c index d5c2514634..da70fd50e8 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c @@ -147,7 +147,7 @@ static bool nr_pbch_detection(const UE_nr_rxtx_proc_t *proc, 1, 1); } - LOG_I(PHY, "Initial sync: pbch decoded sucessfully, ssb index %d\n", *ssb_index); + LOG_A(PHY, "Initial sync: pbch decoded sucessfully, ssb index %d\n", *ssb_index); return true; } } From 350cf8d6ef93b34bf564326d414722b58bd1ef28 Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Sun, 3 Aug 2025 11:09:32 -0400 Subject: [PATCH 322/964] Fix PUCCH 2 DMRS in UE for start RB not multiple of 4 --- openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c | 27 ++++++++++++------------- openair1/PHY/defs_nr_common.h | 2 ++ 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c b/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c index c73af09eef..3fcbe2a2f3 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c @@ -491,7 +491,7 @@ static inline void nr_pucch2_3_4_scrambling(uint16_t M_bit, uint16_t rnti, uint1 const int roundedSz = (M_bit + 31) / 32; uint32_t *seq = gold_cache((rnti << 15) + n_id, roundedSz); #ifdef DEBUG_NR_PUCCH_TX - printf("\t\t [nr_pucch2_3_4_scrambling] gold sequence s=%x, M_bit %d\n",s,M_bit); + printf("\t\t [nr_pucch2_3_4_scrambling] gold sequence s=%x, M_bit %d\n", *seq, M_bit); #endif uint8_t *btildep = btilde; @@ -718,9 +718,10 @@ void nr_generate_pucch2(const PHY_VARS_NR_UE *ue, temp_x2 *= 14UL * nr_slot_tx + l + startingSymbolIndex + 1; temp_x2 *= 2UL * pucch_pdu->dmrs_scrambling_id + 1; temp_x2 = (temp_x2 + 2ULL * pucch_pdu->dmrs_scrambling_id) % (1UL << 31); - uint idxGold = startingPRB >> 2; - uint32_t *seq = gold_cache(temp_x2, idxGold + pucch_pdu->prb_size); - int m = 0; + uint32_t idxGold = startingPRB * NR_PUCCH_DMRS_RB * DMRS_MOD_ORDER / 32; + uint32_t m = (startingPRB * NR_PUCCH_DMRS_RB * DMRS_MOD_ORDER) % 32; + const int seq_sz = ((startingPRB + pucch_pdu->prb_size) * NR_PUCCH_DMRS_RB * DMRS_MOD_ORDER + 31) / 32; + uint32_t *seq = gold_cache(temp_x2, seq_sz); for (int rb=0; rbprb_size; rb++) { //startingPRB = startingPRB + rb; const bool nb_rb_is_even = frame_parms->N_RB_DL & 1; @@ -757,15 +758,14 @@ void nr_generate_pucch2(const PHY_VARS_NR_UE *ue, txdataF[0][re_offset] = d[outSample + k]; #ifdef DEBUG_NR_PUCCH_TX printf( - "\t [nr_generate_pucch2] (n=%d,i=%d) mapping PUCCH to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d " + "\t [nr_generate_pucch2] (n=%d) mapping PUCCH to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d " "\tfirst_carrier_offset=%d \tz_pucch[%d]=txptr(%d)=(x_n(l=%d,n=%d)=(%d,%d))\n", n, - i, amp, frame_parms->ofdm_symbol_size, frame_parms->N_RB_DL, frame_parms->first_carrier_offset, - i + k, + k, re_offset, l, n, @@ -776,20 +776,19 @@ void nr_generate_pucch2(const PHY_VARS_NR_UE *ue, } if (n%3 == 1) { // mapping DM-RS signal according to TS38.211 subclause 6.4.1.3.2 - txdataF[0][re_offset].r = (int16_t)(baseVal * (1 - (2 * ((uint8_t)((seq[idxGold] >> (2 * m)) & 1))))); - txdataF[0][re_offset].i = (int16_t)(baseVal * (1 - (2 * ((uint8_t)((seq[idxGold] >> (2 * m + 1)) & 1))))); - m++; + txdataF[0][re_offset].r = (int16_t)(baseVal * (1 - (2 * ((uint8_t)((seq[idxGold] >> (m)) & 1))))); + txdataF[0][re_offset].i = (int16_t)(baseVal * (1 - (2 * ((uint8_t)((seq[idxGold] >> (m + 1)) & 1))))); + m += 2; #ifdef DEBUG_NR_PUCCH_TX printf( - "\t [nr_generate_pucch2] (n=%d,i=%d) mapping DM-RS to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d " + "\t [nr_generate_pucch2] (n=%d) mapping DM-RS to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d " "\tfirst_carrier_offset=%d \tz_dm-rs[%d]=txptr(%d)=(x_n(l=%d,n=%d)=(%d,%d))\n", n, - i, amp, frame_parms->ofdm_symbol_size, frame_parms->N_RB_DL, frame_parms->first_carrier_offset, - i + kk, + kk, re_offset, l, n, @@ -804,7 +803,7 @@ void nr_generate_pucch2(const PHY_VARS_NR_UE *ue, outSample += 8; - if (m % 16 == 0) { + if (m % 32 == 0) { idxGold++; m = 0; } diff --git a/openair1/PHY/defs_nr_common.h b/openair1/PHY/defs_nr_common.h index d125e382ff..67f7470d29 100644 --- a/openair1/PHY/defs_nr_common.h +++ b/openair1/PHY/defs_nr_common.h @@ -91,6 +91,8 @@ #define PBCH_MAX_RE_PER_SYMBOL (20 * 12) +#define NR_PUCCH_DMRS_RB 4 + typedef enum { NR_MU_0=0, NR_MU_1, From 39c6cb203c0b49e0c471828a6df869a32dd03949 Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Sun, 3 Aug 2025 11:12:59 -0400 Subject: [PATCH 323/964] Not include DC for CSI IM measurement DC subcarrier has a significantly higher energy compared to other CSI IM resource elements. This causes the average interference + noise estimation to be higher than CSI-RS signal power making the CQI 0. With a third-party gnb that schedules PDSCH based on CQI, the UE never receives DL DCI once it starts sending CSI reports. --- openair1/PHY/NR_UE_TRANSPORT/csi_rx.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c b/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c index 764fbbabc6..bb576460f6 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c +++ b/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c @@ -782,6 +782,8 @@ static void nr_csi_im_power_estimation(const PHY_VARS_NR_UE *ue, LOG_I(NR_PHY, "(ant_rx %i, sc %i) real %i, imag %i\n", ant_rx, sc, rx_signal[sc].r, rx_signal[sc].i); #endif + if (sc == 0) // skip DC for noise power estimation + continue; sum_re += rx_signal[sc].r; sum_im += rx_signal[sc].i; sum2_re += rx_signal[sc].r * rx_signal[sc].r; From acf6b957b304618e9c96264290bcd8b8fb5f31d5 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sun, 29 Jun 2025 21:29:56 +0200 Subject: [PATCH 324/964] Refactor post processor into post_process_ulsch() Introduce an array with information on FAPI structures to save resource allocation into. It's in nr_mac_gNB.h because the next commit reuses this for all preprocessors. --- .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 438 +++++++++--------- openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 11 + 2 files changed, 224 insertions(+), 225 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index e0638e97cf..f6badf62eb 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -2356,6 +2356,217 @@ nfapi_nr_pusch_pdu_t *prepare_pusch_pdu(nfapi_nr_ul_tti_request_t *future_ul_tti return pusch_pdu; } +static void post_process_ulsch(gNB_MAC_INST *nr_mac, post_process_pusch_t *pusch, NR_UE_info_t *UE, NR_sched_pusch_t *sched_pusch) +{ + frame_t frame = pusch->frame; + slot_t slot = pusch->slot; + + NR_ServingCellConfigCommon_t *scc = nr_mac->common_channels[0].ServingCellConfigCommon; + NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; + NR_UE_UL_BWP_t *current_BWP = &UE->current_UL_BWP; + + /* the UE now has the grant for the request */ + sched_ctrl->SR = false; + + int8_t harq_id = sched_pusch->ul_harq_pid; + if (harq_id < 0) { + /* PP has not selected a specific HARQ Process, get a new one */ + harq_id = sched_ctrl->available_ul_harq.head; + AssertFatal(harq_id >= 0, "no free HARQ process available for UE %04x\n", UE->rnti); + remove_front_nr_list(&sched_ctrl->available_ul_harq); + sched_pusch->ul_harq_pid = harq_id; + } else { + /* PP selected a specific HARQ process. Check whether it will be a new + * transmission or a retransmission, and remove from the corresponding + * list */ + if (sched_ctrl->ul_harq_processes[harq_id].round == 0) + remove_nr_list(&sched_ctrl->available_ul_harq, harq_id); + else + remove_nr_list(&sched_ctrl->retrans_ul_harq, harq_id); + } + NR_UE_ul_harq_t *cur_harq = &sched_ctrl->ul_harq_processes[harq_id]; + DevAssert(!cur_harq->is_waiting); + if (nr_mac->radio_config.disable_harq) { + finish_nr_ul_harq(sched_ctrl, harq_id); + } else { + add_tail_nr_list(&sched_ctrl->feedback_ul_harq, harq_id); + cur_harq->feedback_slot = sched_pusch->slot; + cur_harq->is_waiting = true; + } + + /* Statistics */ + AssertFatal(cur_harq->round < nr_mac->ul_bler.harq_round_max, "Indexing ulsch_rounds[%d] is out of bounds\n", cur_harq->round); + UE->mac_stats.ul.rounds[cur_harq->round]++; + if (cur_harq->round == 0) { + UE->mac_stats.ulsch_total_bytes_scheduled += sched_pusch->tb_size; + /* Save information on MCS, TBS etc for the current initial transmission + * so we have access to it when retransmitting */ + cur_harq->sched_pusch = *sched_pusch; + /* save which time allocation and nrOfLayers have been used, to be used on + * retransmissions */ + cur_harq->sched_pusch.time_domain_allocation = sched_pusch->time_domain_allocation; + cur_harq->sched_pusch.nrOfLayers = sched_pusch->nrOfLayers; + cur_harq->sched_pusch.tpmi = sched_pusch->tpmi; + sched_ctrl->sched_ul_bytes += sched_pusch->tb_size; + UE->mac_stats.ul.total_rbs += sched_pusch->rbSize; + + } else { + UE->mac_stats.ul.total_rbs_retx += sched_pusch->rbSize; + } + UE->mac_stats.ul.current_bytes = sched_pusch->tb_size; + UE->mac_stats.ul.current_rbs = sched_pusch->rbSize; + sched_ctrl->last_ul_frame = sched_pusch->frame; + sched_ctrl->last_ul_slot = sched_pusch->slot; + + LOG_D(NR_MAC, + "ULSCH/PUSCH: %4d.%2d RNTI %04x UL sched %4d.%2d DCI L %d start %2d RBS %3d startSymbol %2d nb_symbol %2d dmrs_pos %x MCS " + "Table %2d MCS %2d nrOfLayers %2d num_dmrs_cdm_grps_no_data %2d TBS %4d HARQ PID %2d round %d RV %d NDI %d est %6d sched " + "%6d est BSR %6d TPC %d\n", + frame, + slot, + UE->rnti, + sched_pusch->frame, + sched_pusch->slot, + sched_ctrl->aggregation_level, + sched_pusch->rbStart, + sched_pusch->rbSize, + sched_pusch->tda_info.startSymbolIndex, + sched_pusch->tda_info.nrOfSymbols, + sched_pusch->dmrs_info.ul_dmrs_symb_pos, + current_BWP->mcs_table, + sched_pusch->mcs, + sched_pusch->nrOfLayers, + sched_pusch->dmrs_info.num_dmrs_cdm_grps_no_data, + sched_pusch->tb_size, + harq_id, + cur_harq->round, + nr_get_rv(cur_harq->round % 4), + cur_harq->ndi, + sched_ctrl->estimated_ul_buffer, + sched_ctrl->sched_ul_bytes, + sched_ctrl->estimated_ul_buffer - sched_ctrl->sched_ul_bytes, + sched_ctrl->tpc0); + + /* PUSCH in a later slot, but corresponding DCI now! */ + const int index = ul_buffer_index(sched_pusch->frame, + sched_pusch->slot, + nr_mac->frame_structure.numb_slots_frame, + nr_mac->UL_tti_req_ahead_size); + nfapi_nr_ul_tti_request_t *req = &nr_mac->UL_tti_req_ahead[0][index]; + if (req->SFN != sched_pusch->frame || req->Slot != sched_pusch->slot) + LOG_W(NR_MAC, + "%d.%d future UL_tti_req's frame.slot %d.%d does not match PUSCH %d.%d\n", + frame, + slot, + req->SFN, + req->Slot, + sched_pusch->frame, + sched_pusch->slot); + AssertFatal(req->n_pdus < sizeof(req->pdus_list) / sizeof(req->pdus_list[0]), + "Invalid UL_tti_req_ahead->n_pdus %d\n", + req->n_pdus); + + req->pdus_list[req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE; + req->pdus_list[req->n_pdus].pdu_size = sizeof(nfapi_nr_pusch_pdu_t); + nfapi_nr_pusch_pdu_t *pusch_pdu = prepare_pusch_pdu(req, + UE, + scc, + sched_pusch, + current_BWP->transform_precoding, + harq_id, + cur_harq->round, + current_BWP->pusch_Config && current_BWP->pusch_Config->frequencyHopping, + UE->rnti); + req->n_pdus += 1; + + // Calculate the normalized tx_power for PHR + long *deltaMCS = current_BWP->pusch_Config ? current_BWP->pusch_Config->pusch_PowerControl->deltaMCS : NULL; + int tbs_bits = pusch_pdu->pusch_data.tb_size << 3; + sched_pusch->phr_txpower_calc = compute_ph_factor(current_BWP->scs, + tbs_bits, + sched_pusch->rbSize, + sched_pusch->nrOfLayers, + sched_pusch->tda_info.nrOfSymbols, + sched_pusch->dmrs_info.N_PRB_DMRS * sched_pusch->dmrs_info.num_dmrs_symb, + deltaMCS, + false); + + /* a PDCCH PDU groups DCIs per BWP and CORESET. Save a pointer to each + * allocated PDCCH so we can easily allocate UE's DCIs independent of any + * CORESET order */ + NR_SearchSpace_t *ss = sched_ctrl->search_space; + NR_ControlResourceSet_t *coreset = sched_ctrl->coreset; + const int coresetid = coreset->controlResourceSetId; + nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu = pusch->pdcch_pdu_coreset[coresetid]; + if (!pdcch_pdu) { + nfapi_nr_ul_dci_request_pdus_t *ul_dci_request_pdu = &pusch->ul_dci_req->ul_dci_pdu_list[pusch->ul_dci_req->numPdus]; + memset(ul_dci_request_pdu, 0, sizeof(nfapi_nr_ul_dci_request_pdus_t)); + ul_dci_request_pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE; + ul_dci_request_pdu->PDUSize = (uint8_t)(4 + sizeof(nfapi_nr_dl_tti_pdcch_pdu)); + pdcch_pdu = &ul_dci_request_pdu->pdcch_pdu.pdcch_pdu_rel15; + pusch->ul_dci_req->numPdus += 1; + nr_configure_pdcch(pdcch_pdu, coreset, &sched_ctrl->sched_pdcch); + pusch->pdcch_pdu_coreset[coresetid] = pdcch_pdu; + } + + LOG_D(NR_MAC, "Configuring ULDCI/PDCCH in %d.%d at CCE %d, rnti %04x\n", frame, slot, sched_ctrl->cce_index, UE->rnti); + + /* Fill PDCCH DL DCI PDU */ + nfapi_nr_dl_dci_pdu_t *dci_pdu = prepare_dci_pdu(pdcch_pdu, + scc, + ss, + coreset, + sched_ctrl->aggregation_level, + sched_ctrl->cce_index, + UE->UE_beam_index, + UE->rnti); + pdcch_pdu->numDlDci++; + + dci_pdu_rel15_t uldci_payload; + memset(&uldci_payload, 0, sizeof(uldci_payload)); + if (current_BWP->dci_format == NR_UL_DCI_FORMAT_0_1) + LOG_D(NR_MAC_DCI, + "add ul dci harq %d for %d.%d %d.%d round %d\n", + harq_id, + frame, + slot, + sched_pusch->frame, + sched_pusch->slot, + sched_ctrl->ul_harq_processes[harq_id].round); + + // If nrOfLayers is the same as in srs_feedback, we use the best TPMI, i.e. the one in srs_feedback. + // Otherwise, we use the valid TPMI that we saved in the first transmission. + int *tpmi = NULL; + if (pusch_pdu->nrOfLayers != (sched_ctrl->srs_feedback.ul_ri + 1)) + tpmi = &sched_pusch->tpmi; + config_uldci(&UE->sc_info, + pusch_pdu, + &uldci_payload, + &sched_ctrl->srs_feedback, + tpmi, + sched_pusch->time_domain_allocation, + UE->UE_sched_ctrl.tpc0, + cur_harq->ndi, + current_BWP, + ss->searchSpaceType->present); + + // Reset TPC to 0 dB to not request new gain multiple times before computing new value for SNR + UE->UE_sched_ctrl.tpc0 = 1; + + fill_dci_pdu_rel15(&UE->sc_info, + &UE->current_DL_BWP, + current_BWP, + dci_pdu, + &uldci_payload, + current_BWP->dci_format, + TYPE_C_RNTI_, + current_BWP->bwp_id, + ss, + coreset, + UE->pdsch_HARQ_ACK_Codebook, + nr_mac->cset0_bwp_size); +} + static bool nr_ulsch_preprocessor(module_id_t module_id, frame_t frame, slot_t slot) { gNB_MAC_INST *nr_mac = RC.nrmac[module_id]; @@ -2442,21 +2653,14 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, slot_t slot, nfapi_ ul_dci_req->SFN = frame; ul_dci_req->Slot = slot; - /* a PDCCH PDU groups DCIs per BWP and CORESET. Save a pointer to each - * allocated PDCCH so we can easily allocate UE's DCIs independent of any - * CORESET order */ - nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_coreset[MAX_NUM_CORESET] = {0}; + post_process_pusch_t pusch = { frame, slot, ul_dci_req }; - - NR_ServingCellConfigCommon_t *scc = nr_mac->common_channels[0].ServingCellConfigCommon; NR_UEs_t *UE_info = &nr_mac->UE_info; UE_iterator(UE_info->connected_ue_list, UE) { NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; if (sched_ctrl->ul_failure && !get_softmodem_params()->phy_test) continue; - NR_UE_UL_BWP_t *current_BWP = &UE->current_UL_BWP; - UE->mac_stats.ul.current_bytes = 0; UE->mac_stats.ul.current_rbs = 0; @@ -2467,223 +2671,7 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, slot_t slot, nfapi_ if (sched_pusch->rbSize <= 0) continue; - uint16_t rnti = UE->rnti; - sched_ctrl->SR = false; - int8_t harq_id = sched_pusch->ul_harq_pid; - if (harq_id < 0) { - /* PP has not selected a specific HARQ Process, get a new one */ - harq_id = sched_ctrl->available_ul_harq.head; - AssertFatal(harq_id >= 0, - "no free HARQ process available for UE %04x\n", - UE->rnti); - remove_front_nr_list(&sched_ctrl->available_ul_harq); - sched_pusch->ul_harq_pid = harq_id; - } else { - /* PP selected a specific HARQ process. Check whether it will be a new - * transmission or a retransmission, and remove from the corresponding - * list */ - if (sched_ctrl->ul_harq_processes[harq_id].round == 0) - remove_nr_list(&sched_ctrl->available_ul_harq, harq_id); - else - remove_nr_list(&sched_ctrl->retrans_ul_harq, harq_id); - } - NR_UE_ul_harq_t *cur_harq = &sched_ctrl->ul_harq_processes[harq_id]; - DevAssert(!cur_harq->is_waiting); - if (nr_mac->radio_config.disable_harq) { - finish_nr_ul_harq(sched_ctrl, harq_id); - } else { - add_tail_nr_list(&sched_ctrl->feedback_ul_harq, harq_id); - cur_harq->feedback_slot = sched_pusch->slot; - cur_harq->is_waiting = true; - } - - /* Statistics */ - AssertFatal(cur_harq->round < nr_mac->ul_bler.harq_round_max, "Indexing ulsch_rounds[%d] is out of bounds\n", cur_harq->round); - UE->mac_stats.ul.rounds[cur_harq->round]++; - if (cur_harq->round == 0) { - UE->mac_stats.ulsch_total_bytes_scheduled += sched_pusch->tb_size; - /* Save information on MCS, TBS etc for the current initial transmission - * so we have access to it when retransmitting */ - cur_harq->sched_pusch = *sched_pusch; - /* save which time allocation and nrOfLayers have been used, to be used on - * retransmissions */ - cur_harq->sched_pusch.time_domain_allocation = sched_pusch->time_domain_allocation; - cur_harq->sched_pusch.nrOfLayers = sched_pusch->nrOfLayers; - cur_harq->sched_pusch.tpmi = sched_pusch->tpmi; - sched_ctrl->sched_ul_bytes += sched_pusch->tb_size; - UE->mac_stats.ul.total_rbs += sched_pusch->rbSize; - - } else { - LOG_D(NR_MAC, - "%d.%2d UL retransmission RNTI %04x sched %d.%2d HARQ PID %d round %d NDI %d\n", - frame, - slot, - rnti, - sched_pusch->frame, - sched_pusch->slot, - harq_id, - cur_harq->round, - cur_harq->ndi); - UE->mac_stats.ul.total_rbs_retx += sched_pusch->rbSize; - } - UE->mac_stats.ul.current_bytes = sched_pusch->tb_size; - UE->mac_stats.ul.current_rbs = sched_pusch->rbSize; - sched_ctrl->last_ul_frame = sched_pusch->frame; - sched_ctrl->last_ul_slot = sched_pusch->slot; - - LOG_D(NR_MAC, - "ULSCH/PUSCH: %4d.%2d RNTI %04x UL sched %4d.%2d DCI L %d start %2d RBS %3d startSymbol %2d nb_symbol %2d dmrs_pos %x MCS Table %2d MCS %2d nrOfLayers %2d num_dmrs_cdm_grps_no_data %2d TBS %4d HARQ PID %2d round %d RV %d NDI %d est %6d sched %6d est BSR %6d TPC %d\n", - frame, - slot, - rnti, - sched_pusch->frame, - sched_pusch->slot, - sched_ctrl->aggregation_level, - sched_pusch->rbStart, - sched_pusch->rbSize, - sched_pusch->tda_info.startSymbolIndex, - sched_pusch->tda_info.nrOfSymbols, - sched_pusch->dmrs_info.ul_dmrs_symb_pos, - current_BWP->mcs_table, - sched_pusch->mcs, - sched_pusch->nrOfLayers, - sched_pusch->dmrs_info.num_dmrs_cdm_grps_no_data, - sched_pusch->tb_size, - harq_id, - cur_harq->round, - nr_get_rv(cur_harq->round % 4), - cur_harq->ndi, - sched_ctrl->estimated_ul_buffer, - sched_ctrl->sched_ul_bytes, - sched_ctrl->estimated_ul_buffer - sched_ctrl->sched_ul_bytes, - sched_ctrl->tpc0); - - /* PUSCH in a later slot, but corresponding DCI now! */ - const int index = ul_buffer_index(sched_pusch->frame, - sched_pusch->slot, - nr_mac->frame_structure.numb_slots_frame, - nr_mac->UL_tti_req_ahead_size); - nfapi_nr_ul_tti_request_t *future_ul_tti_req = &nr_mac->UL_tti_req_ahead[0][index]; - if (future_ul_tti_req->SFN != sched_pusch->frame || future_ul_tti_req->Slot != sched_pusch->slot) - LOG_W(NR_MAC, - "%d.%d future UL_tti_req's frame.slot %d.%d does not match PUSCH %d.%d\n", - frame, slot, - future_ul_tti_req->SFN, - future_ul_tti_req->Slot, - sched_pusch->frame, - sched_pusch->slot); - AssertFatal(future_ul_tti_req->n_pdus < - sizeof(future_ul_tti_req->pdus_list) / sizeof(future_ul_tti_req->pdus_list[0]), - "Invalid future_ul_tti_req->n_pdus %d\n", future_ul_tti_req->n_pdus); - - future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE; - future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pdu_size = sizeof(nfapi_nr_pusch_pdu_t); - nfapi_nr_pusch_pdu_t *pusch_pdu = prepare_pusch_pdu(future_ul_tti_req, - UE, - scc, - sched_pusch, - current_BWP->transform_precoding, - harq_id, - cur_harq->round, - current_BWP->pusch_Config && current_BWP->pusch_Config->frequencyHopping, - rnti); - future_ul_tti_req->n_pdus += 1; - - LOG_D(NR_MAC, - "%4d.%2d Scheduling UE specific PUSCH for sched %d.%d, ul_tti_req %d.%d\n", - frame, - slot, - sched_pusch->frame, - sched_pusch->slot, - future_ul_tti_req->SFN, - future_ul_tti_req->Slot); - - - // Calacualte the normalized tx_power for PHR - long *deltaMCS = current_BWP->pusch_Config ? current_BWP->pusch_Config->pusch_PowerControl->deltaMCS : NULL; - int tbs_bits = pusch_pdu->pusch_data.tb_size << 3; - sched_pusch->phr_txpower_calc = compute_ph_factor(current_BWP->scs, - tbs_bits, - sched_pusch->rbSize, - sched_pusch->nrOfLayers, - sched_pusch->tda_info.nrOfSymbols, - sched_pusch->dmrs_info.N_PRB_DMRS * sched_pusch->dmrs_info.num_dmrs_symb, - deltaMCS, - false); - - /* look up the PDCCH PDU for this BWP and CORESET. If it does not exist, - * create it */ - NR_SearchSpace_t *ss = sched_ctrl->search_space; - NR_ControlResourceSet_t *coreset = sched_ctrl->coreset; - const int coresetid = coreset->controlResourceSetId; - nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu = pdcch_pdu_coreset[coresetid]; - if (!pdcch_pdu) { - nfapi_nr_ul_dci_request_pdus_t *ul_dci_request_pdu = &ul_dci_req->ul_dci_pdu_list[ul_dci_req->numPdus]; - memset(ul_dci_request_pdu, 0, sizeof(nfapi_nr_ul_dci_request_pdus_t)); - ul_dci_request_pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE; - ul_dci_request_pdu->PDUSize = (uint8_t)(4+sizeof(nfapi_nr_dl_tti_pdcch_pdu)); - pdcch_pdu = &ul_dci_request_pdu->pdcch_pdu.pdcch_pdu_rel15; - ul_dci_req->numPdus += 1; - nr_configure_pdcch(pdcch_pdu, coreset, &sched_ctrl->sched_pdcch); - pdcch_pdu_coreset[coresetid] = pdcch_pdu; - } - - LOG_D(NR_MAC,"Configuring ULDCI/PDCCH in %d.%d at CCE %d, rnti %04x\n", frame,slot,sched_ctrl->cce_index,rnti); - - /* Fill PDCCH DL DCI PDU */ - nfapi_nr_dl_dci_pdu_t *dci_pdu = prepare_dci_pdu(pdcch_pdu, - scc, - ss, - coreset, - sched_ctrl->aggregation_level, - sched_ctrl->cce_index, - UE->UE_beam_index, - rnti); - pdcch_pdu->numDlDci++; - - dci_pdu_rel15_t uldci_payload; - memset(&uldci_payload, 0, sizeof(uldci_payload)); - if (current_BWP->dci_format == NR_UL_DCI_FORMAT_0_1) - LOG_D(NR_MAC_DCI, - "add ul dci harq %d for %d.%d %d.%d round %d\n", - harq_id, - frame, - slot, - sched_pusch->frame, - sched_pusch->slot, - sched_ctrl->ul_harq_processes[harq_id].round); - - // If nrOfLayers is the same as in srs_feedback, we use the best TPMI, i.e. the one in srs_feedback. - // Otherwise, we use the valid TPMI that we saved in the first transmission. - int *tpmi = NULL; - if (pusch_pdu->nrOfLayers != (sched_ctrl->srs_feedback.ul_ri + 1)) - tpmi = &sched_pusch->tpmi; - config_uldci(&UE->sc_info, - pusch_pdu, - &uldci_payload, - &sched_ctrl->srs_feedback, - tpmi, - sched_pusch->time_domain_allocation, - UE->UE_sched_ctrl.tpc0, - cur_harq->ndi, - current_BWP, - ss->searchSpaceType->present); - - // Reset TPC to 0 dB to not request new gain multiple times before computing new value for SNR - UE->UE_sched_ctrl.tpc0 = 1; - - fill_dci_pdu_rel15(&UE->sc_info, - &UE->current_DL_BWP, - current_BWP, - dci_pdu, - &uldci_payload, - current_BWP->dci_format, - TYPE_C_RNTI_, - current_BWP->bwp_id, - ss, - coreset, - UE->pdsch_HARQ_ACK_Codebook, - nr_mac->cset0_bwp_size); + post_process_ulsch(nr_mac, &pusch, UE, sched_pusch); memset(sched_pusch, 0, sizeof(*sched_pusch)); } diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 84be6f4b5a..38ce8c2080 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -797,6 +797,17 @@ typedef struct { #define UE_iterator(BaSe, VaR) NR_UE_info_t ** VaR##pptr=BaSe, *VaR; while ((VaR=*(VaR##pptr++))) +typedef struct { + /// current frame for DCI + frame_t frame; + /// current slot for DCI + slot_t slot; + /// FAPI UL_DCI.request in which allocations are to be made + nfapi_nr_ul_dci_request_t *ul_dci_req; + /// group PDCCH PDU per CORESET + nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_coreset[MAX_NUM_CORESET]; +} post_process_pusch_t; + typedef void (*nr_pp_impl_dl)(module_id_t mod_id, frame_t frame, slot_t slot); typedef bool (*nr_pp_impl_ul)(module_id_t mod_id, frame_t frame, slot_t slot); From fcebec09adce9c25efee1c792f9bb49884a533b8 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 30 Jun 2025 09:20:31 +0200 Subject: [PATCH 325/964] Read TX power from HARQ.sched_pusch A later commit will remove sched_ctrl->sched_pusch. Instead, the TX power is also stored for each HARQ process (as they contain sched_pusch). Read it from there, which should have the same effect. --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index f6badf62eb..50958e0643 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -660,6 +660,7 @@ static void nr_rx_ra_sdu(const module_id_t mod_id, rnti_t rnti, uint8_t *sdu, const uint32_t sdu_len, + uint8_t harq_pid, const uint16_t timing_advance, const uint8_t ul_cqi, const uint16_t rssi) @@ -725,9 +726,11 @@ static void nr_rx_ra_sdu(const module_id_t mod_id, LOG_A(NR_MAC, "%4d.%2d PUSCH with TC_RNTI 0x%04x received correctly\n", frame, slot, rnti); NR_UE_sched_ctrl_t *UE_scheduling_control = &UE->UE_sched_ctrl; + DevAssert(harq_pid >= 0 && harq_pid < 8); if (ul_cqi != 0xff) { - UE_scheduling_control->tpc0 = nr_get_tpc(target_snrx10, ul_cqi, 30, UE_scheduling_control->sched_pusch.phr_txpower_calc); - UE_scheduling_control->pusch_snrx10 = ul_cqi * 5 - 640 - UE_scheduling_control->sched_pusch.phr_txpower_calc * 10; + NR_UE_ul_harq_t *harq = &UE_scheduling_control->ul_harq_processes[harq_pid]; + UE_scheduling_control->tpc0 = nr_get_tpc(target_snrx10, ul_cqi, 30, harq->sched_pusch.phr_txpower_calc); + UE_scheduling_control->pusch_snrx10 = ul_cqi * 5 - 640 - harq->sched_pusch.phr_txpower_calc * 10; } if (timing_advance != 0xffff) UE_scheduling_control->ta_update = timing_advance; @@ -943,7 +946,7 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP, } handle_nr_ul_harq(gNB_mac, UE, frameP, slotP, current_rnti, harq_pid, sduP == NULL); } else { - nr_rx_ra_sdu(gnb_mod_idP, CC_idP, frameP, slotP, current_rnti, sduP, sdu_lenP, timing_advance, ul_cqi, rssi); + nr_rx_ra_sdu(gnb_mod_idP, CC_idP, frameP, slotP, current_rnti, sduP, sdu_lenP, harq_pid, timing_advance, ul_cqi, rssi); } } From 243e956ee9793df6b98f5cadf9421c7085193f64 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 30 Jun 2025 10:46:56 +0200 Subject: [PATCH 326/964] Remove unused parameter from sched_pusch --- openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 1 - 1 file changed, 1 deletion(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 38ce8c2080..ea7d80a214 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -403,7 +403,6 @@ typedef struct NR_pusch_dmrs { typedef struct NR_sched_pusch { int frame; int slot; - int mu; /// RB allocation within active uBWP uint16_t rbSize; From f3068caa3774e121fb815ee2e9dbd3a6bc970f93 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 30 Jun 2025 10:38:44 +0200 Subject: [PATCH 327/964] Store selected MCS in UE iterator PF uses MCS and average throughput to decide which UE to schedule. Thus, the first loop selects the MCS, and the second does the main UE allocation after sorting by priority, depending on the MCS. A follow-up commit will remove sched_pusch from NR_UE_sched_ctrl_t. Thus, we cannot rely on sched_ctrl to store the MCS in the first loop, and look it up from there in the second. Instead, store it as part of the UE iterator data, and take it from there. --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 50958e0643..aaabf7847e 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -1839,6 +1839,7 @@ static uint32_t ul_pf_tbs[5][29]; // pre-computed, approximate TBS values for PF typedef struct UEsched_s { float coef; NR_UE_info_t * UE; + int selected_mcs; } UEsched_t; static int comparator(const void *p, const void *q) { @@ -1964,12 +1965,12 @@ static void pf_ul(module_id_t module_id, const NR_bler_options_t *bo = &nrmac->ul_bler; const int max_mcs_table = (current_BWP->mcs_table == 0 || current_BWP->mcs_table == 2) ? 28 : 27; const int max_mcs = min(bo->max_mcs, max_mcs_table); /* no per-user maximum MCS yet */ + int selected_mcs; if (bo->harq_round_max == 1) { - sched_pusch->mcs = max_mcs; - sched_ctrl->ul_bler_stats.mcs = sched_pusch->mcs; + selected_mcs = sched_ctrl->ul_bler_stats.mcs = max_mcs; } else { - sched_pusch->mcs = get_mcs_from_bler(bo, stats, &sched_ctrl->ul_bler_stats, max_mcs, frame); - LOG_D(NR_MAC, "%d.%d starting mcs %d bler %f\n", frame, slot, sched_pusch->mcs, sched_ctrl->ul_bler_stats.bler); + selected_mcs = get_mcs_from_bler(bo, stats, &sched_ctrl->ul_bler_stats, max_mcs, frame); + LOG_D(NR_MAC, "%d.%d starting mcs %d bler %f\n", frame, slot, selected_mcs, sched_ctrl->ul_bler_stats.bler); } /* Schedule UE on SR or UL inactivity and no data (otherwise, will be scheduled * based on data to transmit) */ @@ -2032,6 +2033,7 @@ static void pf_ul(module_id_t module_id, fill_pdcch_vrb_map(nrmac, CC_id, &sched_ctrl->sched_pdcch, CCEIndex, sched_ctrl->aggregation_level, dci_beam.idx); NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch; + sched_pusch->mcs = selected_mcs; update_ul_ue_R_Qm(sched_pusch->mcs, current_BWP->mcs_table, current_BWP->pusch_Config, &sched_pusch->R, &sched_pusch->Qm); sched_pusch->rbStart = rbStart; sched_pusch->rbSize = min_rb; @@ -2077,7 +2079,7 @@ static void pf_ul(module_id_t module_id, /* Create UE_sched for UEs eligibale for new data transmission*/ /* Calculate coefficient*/ - const uint32_t tbs = ul_pf_tbs[current_BWP->mcs_table][sched_pusch->mcs]; + const uint32_t tbs = ul_pf_tbs[current_BWP->mcs_table][selected_mcs]; float coeff_ue = (float) tbs / UE->ul_thr_ue; LOG_D(NR_MAC, "[UE %04x][%4d.%2d] b %d, ul_thr_ue %f, tbs %d, coeff_ue %f\n", UE->rnti, @@ -2089,6 +2091,7 @@ static void pf_ul(module_id_t module_id, coeff_ue); UE_sched[curUE].coef = coeff_ue; UE_sched[curUE].UE = UE; + UE_sched[curUE].selected_mcs = selected_mcs; curUE++; } @@ -2192,6 +2195,7 @@ static void pf_ul(module_id_t module_id, /* Calculate the current scheduling bytes */ const int B = cmax(sched_ctrl->estimated_ul_buffer - sched_ctrl->sched_ul_bytes, 0); + sched_pusch->mcs = iterator->selected_mcs; /* adjust rbSize and MCS according to PHR and BPRE */ if(sched_ctrl->pcmax != 0 || sched_ctrl->ph != 0) // verify if the PHR related parameter have been initialized nr_ue_max_mcs_min_rb(current_BWP->scs, sched_ctrl->ph, sched_pusch, current_BWP, min_rb, B, &max_rbSize, &sched_pusch->mcs); From 81b66fae5e7fb6f9090aec83d26af07ba57dac7d Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 30 Jun 2025 10:51:56 +0200 Subject: [PATCH 328/964] UL harq PID: similar to parent, reduce scope of sched_pusch --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index aaabf7847e..4007d0edea 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -1826,6 +1826,7 @@ static bool allocate_ul_retransmission(gNB_MAC_INST *nrmac, sched_pusch->bwp_info = bwp_info; sched_pusch->rbStart = rbStart; + sched_pusch->ul_harq_pid = harq_pid; /* no need to recompute the TBS, it will be the same */ /* Mark the corresponding RBs as used */ @@ -1908,9 +1909,9 @@ static void pf_ul(module_id_t module_id, uint16_t *rballoc_mask = &nrmac->common_channels[CC_id].vrb_map_UL[beam.idx][index * MAX_BWP_SIZE]; /* Check if retransmission is necessary */ - sched_pusch->ul_harq_pid = sched_ctrl->retrans_ul_harq.head; - LOG_D(NR_MAC,"pf_ul: UE %04x harq_pid %d\n", UE->rnti, sched_pusch->ul_harq_pid); - if (sched_pusch->ul_harq_pid >= 0) { + int ul_harq_pid = sched_ctrl->retrans_ul_harq.head; + LOG_D(NR_MAC,"pf_ul: UE %04x harq_pid %d\n", UE->rnti, ul_harq_pid); + if (ul_harq_pid >= 0) { /* Allocate retransmission*/ const int tda = get_ul_tda(nrmac, sched_frame, sched_slot); bool r = allocate_ul_retransmission(nrmac, @@ -1920,7 +1921,7 @@ static void pf_ul(module_id_t module_id, &n_rb_sched[beam.idx], dci_beam.idx, UE, - sched_pusch->ul_harq_pid, + ul_harq_pid, scc, tda); if (!r) { @@ -1936,6 +1937,7 @@ static void pf_ul(module_id_t module_id, remainUEs[beam.idx]--; continue; } + DevAssert(ul_harq_pid == -1); // all other allocations must be new ones /* skip this UE if there are no free HARQ processes. This can happen e.g. * if the UE disconnected in L2sim, in which case the gNB is not notified @@ -2040,6 +2042,7 @@ static void pf_ul(module_id_t module_id, sched_pusch->bwp_info = bwp_info; sched_pusch->frame = sched_frame; sched_pusch->slot = sched_slot; + sched_pusch->ul_harq_pid = -1; // new transmission sched_pusch->tb_size = nr_compute_tbs(sched_pusch->Qm, sched_pusch->R, sched_pusch->rbSize, @@ -2236,6 +2239,7 @@ static void pf_ul(module_id_t module_id, sched_pusch->bwp_info = bwp_info; sched_pusch->frame = sched_frame; sched_pusch->slot = sched_slot; + sched_pusch->ul_harq_pid = -1; // new transmission LOG_D(NR_MAC, "rbSize %d (max_rbSize %d), TBS %d, est buf %d, sched_ul %d, B %d, CCE %d, num_dmrs_symb %d, N_PRB_DMRS %d\n", rbSize, From 5b39baacc3cfd0d8e034c75ef4d3def506278b2b Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 30 Jun 2025 11:02:59 +0200 Subject: [PATCH 329/964] Refactor inactivity-based PUSCH allocation Write a single NR_sched_pusch_t structure in a single statement (where possible). Assign to sched_ctrl->sched_pusch in one place, where the post-processing functionality will be called in a follow-up commit. --- .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 104 +++++++++--------- 1 file changed, 53 insertions(+), 51 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 4007d0edea..afa7bb5a68 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -1879,7 +1879,6 @@ static void pf_ul(module_id_t module_id, LOG_D(NR_MAC,"pf_ul: preparing UL scheduling for UE %04x\n",UE->rnti); NR_UE_UL_BWP_t *current_BWP = &UE->current_UL_BWP; - NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch; const NR_mac_dir_stats_t *stats = &UE->mac_stats.ul; /* Calculate throughput */ @@ -1995,29 +1994,21 @@ static void pf_ul(module_id_t module_id, continue; } - sched_pusch->nrOfLayers = get_ul_nrOfLayers(sched_ctrl, current_BWP->dci_format); - sched_pusch->time_domain_allocation = get_ul_tda(nrmac, sched_frame, sched_slot); - sched_pusch->tda_info = get_ul_tda_info(current_BWP, + int tda = get_ul_tda(nrmac, sched_frame, sched_slot); + NR_tda_info_t tda_info = get_ul_tda_info(current_BWP, sched_ctrl->coreset->controlResourceSetId, sched_ctrl->search_space->searchSpaceType->present, TYPE_C_RNTI_, - sched_pusch->time_domain_allocation); - AssertFatal(sched_pusch->tda_info.valid_tda, "Invalid TDA from get_ul_tda_info\n"); - sched_pusch->dmrs_info = get_ul_dmrs_params(scc, current_BWP, &sched_pusch->tda_info, sched_pusch->nrOfLayers); + tda); + AssertFatal(tda_info.valid_tda, "Invalid TDA from get_ul_tda_info\n"); int rbStart = 0; // wrt BWP start - LOG_D(NR_MAC, - "Looking for min_rb %d RBs, starting at %d num_dmrs_cdm_grps_no_data %d\n", - min_rb, - rbStart, - sched_pusch->dmrs_info.num_dmrs_cdm_grps_no_data); - bwp_info_t bwp_info = get_pusch_bwp_start_size(UE); - const uint32_t bwpStart = bwp_info.bwpStart; - const uint32_t bwpSize = bwp_info.bwpSize; - const uint16_t slbitmap = SL_to_bitmap(sched_pusch->tda_info.startSymbolIndex, sched_pusch->tda_info.nrOfSymbols); - while (rbStart < bwpSize && (rballoc_mask[rbStart + bwpStart] & slbitmap)) + LOG_D(NR_MAC, "Looking for min_rb %d RBs, starting at %d\n", min_rb, rbStart); + bwp_info_t bi = get_pusch_bwp_start_size(UE); + const uint16_t slbitmap = SL_to_bitmap(tda_info.startSymbolIndex, tda_info.nrOfSymbols); + while (rbStart < bi.bwpSize && (rballoc_mask[rbStart + bi.bwpStart] & slbitmap)) rbStart++; - if (rbStart + min_rb > bwpSize) { + if (rbStart + min_rb > bi.bwpSize) { LOG_D(NR_MAC, "[UE %04x][%4d.%2d] could not allocate continuous UL data: no resources (rbStart %d, min_rb %d, bwpSize %d)\n", UE->rnti, @@ -2025,7 +2016,7 @@ static void pf_ul(module_id_t module_id, slot, rbStart, min_rb, - bwpSize); + bi.bwpSize); reset_beam_status(&nrmac->beam_info, sched_frame, sched_slot, UE->UE_beam_index, slots_per_frame, beam.new_beam); reset_beam_status(&nrmac->beam_info, frame, slot, UE->UE_beam_index, slots_per_frame, dci_beam.new_beam); continue; @@ -2034,47 +2025,58 @@ static void pf_ul(module_id_t module_id, sched_ctrl->cce_index = CCEIndex; fill_pdcch_vrb_map(nrmac, CC_id, &sched_ctrl->sched_pdcch, CCEIndex, sched_ctrl->aggregation_level, dci_beam.idx); - NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch; - sched_pusch->mcs = selected_mcs; - update_ul_ue_R_Qm(sched_pusch->mcs, current_BWP->mcs_table, current_BWP->pusch_Config, &sched_pusch->R, &sched_pusch->Qm); - sched_pusch->rbStart = rbStart; - sched_pusch->rbSize = min_rb; - sched_pusch->bwp_info = bwp_info; - sched_pusch->frame = sched_frame; - sched_pusch->slot = sched_slot; - sched_pusch->ul_harq_pid = -1; // new transmission - sched_pusch->tb_size = nr_compute_tbs(sched_pusch->Qm, - sched_pusch->R, - sched_pusch->rbSize, - sched_pusch->tda_info.nrOfSymbols, - sched_pusch->dmrs_info.N_PRB_DMRS * sched_pusch->dmrs_info.num_dmrs_symb, - 0, // nb_rb_oh - 0, - sched_pusch->nrOfLayers) >> 3; + int nrOfLayers = get_ul_nrOfLayers(sched_ctrl, current_BWP->dci_format); + NR_sched_pusch_t sched = { + .frame = sched_frame, + .slot = sched_slot, + .rbSize = min_rb, + .rbStart = rbStart, + .mcs = selected_mcs, + // R, Qm, tb_size below + .ul_harq_pid = -1, // new transmission + .nrOfLayers = nrOfLayers, + // tpmi in post-process + .time_domain_allocation = tda, + .tda_info = tda_info, + .dmrs_info = get_ul_dmrs_params(scc, current_BWP, &tda_info, nrOfLayers), + .bwp_info = bi, + // phr_txpower_calc below + }; + update_ul_ue_R_Qm(sched.mcs, current_BWP->mcs_table, current_BWP->pusch_Config, &sched.R, &sched.Qm); + sched.tb_size = nr_compute_tbs(sched.Qm, + sched.R, + sched.rbSize, + sched.tda_info.nrOfSymbols, + sched.dmrs_info.N_PRB_DMRS * sched.dmrs_info.num_dmrs_symb, + 0, // nb_rb_oh + 0, + sched.nrOfLayers) + >> 3; long *deltaMCS = current_BWP->pusch_Config ? current_BWP->pusch_Config->pusch_PowerControl->deltaMCS : NULL; - sched_pusch->phr_txpower_calc = compute_ph_factor(current_BWP->scs, - sched_pusch->tb_size << 3, - sched_pusch->rbSize, - sched_pusch->nrOfLayers, - sched_pusch->tda_info.nrOfSymbols, - sched_pusch->dmrs_info.N_PRB_DMRS * sched_pusch->dmrs_info.num_dmrs_symb, - deltaMCS, - false); + sched.phr_txpower_calc = compute_ph_factor(current_BWP->scs, + sched.tb_size << 3, + sched.rbSize, + sched.nrOfLayers, + sched.tda_info.nrOfSymbols, + sched.dmrs_info.N_PRB_DMRS * sched.dmrs_info.num_dmrs_symb, + deltaMCS, + false); + sched_ctrl->sched_pusch = sched; LOG_D(NR_MAC, "pf_ul %d.%d UE %x Scheduling PUSCH (no data) nrb %d mcs %d tbs %d bits phr_txpower %d\n", frame, slot, UE->rnti, - sched_pusch->rbSize, - sched_pusch->mcs, - sched_pusch->tb_size << 3, - sched_pusch->phr_txpower_calc); + sched.rbSize, + sched.mcs, + sched.tb_size << 3, + sched.phr_txpower_calc); /* Mark the corresponding RBs as used */ - n_rb_sched[beam.idx] -= sched_pusch->rbSize; - for (int rb = bwpStart; rb < sched_ctrl->sched_pusch.rbSize; rb++) - rballoc_mask[rb + sched_ctrl->sched_pusch.rbStart] |= slbitmap; + n_rb_sched[beam.idx] -= sched.rbSize; + for (int rb = bi.bwpStart; rb < sched.rbSize; rb++) + rballoc_mask[rb + sched.rbStart] |= slbitmap; remainUEs[beam.idx]--; continue; From a469f420857141563588c5cacc3ad0f674b6af63 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 30 Jun 2025 11:32:45 +0200 Subject: [PATCH 330/964] Refactor retransmission's NR_sched_pusch_t usage Avoid to overwrite the existing retInfo. Instead, create a new NR_sched_pusch_t and assign to sched_ctrl->sched_pusch in one place. A follow-up commit will directly trigger the post processor here. --- .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 49 ++++++++++--------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index afa7bb5a68..c5f74fe25e 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -1712,7 +1712,9 @@ static bool allocate_ul_retransmission(gNB_MAC_INST *nrmac, { const int CC_id = 0; NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; - NR_sched_pusch_t *retInfo = &sched_ctrl->ul_harq_processes[harq_pid].sched_pusch; + /* Get previous PUSCH field info */ + const NR_sched_pusch_t *retInfo = &sched_ctrl->ul_harq_processes[harq_pid].sched_pusch; + NR_sched_pusch_t new_sched = *retInfo; // potential new allocation NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP; int rbStart = 0; // wrt BWP start @@ -1721,7 +1723,6 @@ static bool allocate_ul_retransmission(gNB_MAC_INST *nrmac, const uint32_t bwpStart = bwp_info.bwpStart; const uint8_t nrOfLayers = retInfo->nrOfLayers; LOG_D(NR_MAC,"retInfo->time_domain_allocation = %d, tda = %d\n", retInfo->time_domain_allocation, tda); - LOG_D(NR_MAC,"tbs %d\n",retInfo->tb_size); NR_tda_info_t tda_info = get_ul_tda_info(ul_bwp, sched_ctrl->coreset->controlResourceSetId, sched_ctrl->search_space->searchSpaceType->present, @@ -1730,6 +1731,13 @@ static bool allocate_ul_retransmission(gNB_MAC_INST *nrmac, if (!tda_info.valid_tda) return false; + /* mark when retransmission will happen */ + int slots_frame = nrmac->frame_structure.numb_slots_frame; + new_sched.frame = (frame + (slot + tda_info.k2 + get_NTN_Koffset(scc)) / slots_frame) % MAX_FRAME_NUMBER; + new_sched.slot = (slot + tda_info.k2 + get_NTN_Koffset(scc)) % slots_frame; + new_sched.bwp_info = bwp_info; + DevAssert(new_sched.ul_harq_pid == harq_pid); + bool reuse_old_tda = (retInfo->tda_info.startSymbolIndex == tda_info.startSymbolIndex) && (retInfo->tda_info.nrOfSymbols <= tda_info.nrOfSymbols); if (reuse_old_tda && nrOfLayers == retInfo->nrOfLayers) { /* Check the resource is enough for retransmission */ @@ -1746,6 +1754,7 @@ static bool allocate_ul_retransmission(gNB_MAC_INST *nrmac, bwpSize); return false; } + new_sched.rbStart = rbStart; LOG_D(NR_MAC, "Retransmission keeping TDA %d and TBS %d\n", tda, retInfo->tb_size); } else { NR_pusch_dmrs_t dmrs_info = get_ul_dmrs_params(scc, ul_bwp, &tda_info, nrOfLayers); @@ -1782,11 +1791,12 @@ static bool allocate_ul_retransmission(gNB_MAC_INST *nrmac, LOG_D(NR_MAC, "Retransmission with TDA %d->%d and TBS %d -> %d\n", retInfo->time_domain_allocation, tda, retInfo->tb_size, new_tbs); /* we can allocate it. Overwrite the time_domain_allocation, the number * of RBs, and the new TB size. The rest is done below */ - retInfo->tb_size = new_tbs; - retInfo->rbSize = new_rbSize; - retInfo->time_domain_allocation = tda; - retInfo->dmrs_info = dmrs_info; - retInfo->tda_info = tda_info; + new_sched.rbSize = new_rbSize; + new_sched.rbStart = rbStart; + new_sched.tb_size = new_tbs; + new_sched.time_domain_allocation = tda; + new_sched.tda_info = tda_info; + new_sched.dmrs_info = dmrs_info; } /* Find a free CCE */ @@ -1808,31 +1818,22 @@ static bool allocate_ul_retransmission(gNB_MAC_INST *nrmac, sched_ctrl->cce_index = CCEIndex; fill_pdcch_vrb_map(nrmac, CC_id, &sched_ctrl->sched_pdcch, CCEIndex, sched_ctrl->aggregation_level, dci_beam_idx); - int slots_frame = nrmac->frame_structure.numb_slots_frame; - retInfo->frame = (frame + (slot + tda_info.k2 + get_NTN_Koffset(scc)) / slots_frame) % MAX_FRAME_NUMBER; - retInfo->slot = (slot + tda_info.k2 + get_NTN_Koffset(scc)) % slots_frame; - /* Get previous PSUCH field info */ - sched_ctrl->sched_pusch = *retInfo; - NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch; + // signal new allocation + sched_ctrl->sched_pusch = new_sched; LOG_D(NR_MAC, "%4d.%2d Allocate UL retransmission RNTI %04x sched %4d.%2d (%d RBs)\n", frame, slot, UE->rnti, - sched_pusch->frame, - sched_pusch->slot, - sched_pusch->rbSize); - - sched_pusch->bwp_info = bwp_info; - sched_pusch->rbStart = rbStart; - sched_pusch->ul_harq_pid = harq_pid; - /* no need to recompute the TBS, it will be the same */ + new_sched.frame, + new_sched.slot, + new_sched.rbSize); /* Mark the corresponding RBs as used */ - n_rb_sched -= sched_pusch->rbSize; - for (int rb = bwpStart; rb < sched_ctrl->sched_pusch.rbSize; rb++) - rballoc_mask[rb + sched_ctrl->sched_pusch.rbStart] |= SL_to_bitmap(sched_pusch->tda_info.startSymbolIndex, sched_pusch->tda_info.nrOfSymbols); + n_rb_sched -= new_sched.rbSize; + for (int rb = bwpStart; rb < new_sched.rbSize; rb++) + rballoc_mask[rb + new_sched.rbStart] |= SL_to_bitmap(new_sched.tda_info.startSymbolIndex, new_sched.tda_info.nrOfSymbols); return true; } From 4772dd889ebf1323c7278ea2409a37d15603855d Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 30 Jun 2025 11:51:23 +0200 Subject: [PATCH 331/964] Refactor ULSCH main allocation procedure Write a single NR_sched_pusch_t structure in a single statement (where possible). Assign to sched_ctrl->sched_pusch in one place, where the post-processing functionality will be called in a follow-up commit. --- .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 118 +++++++++--------- 1 file changed, 61 insertions(+), 57 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index c5f74fe25e..493c2a37e0 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -2108,7 +2108,6 @@ static void pf_ul(module_id_t module_id, while (iterator->UE != NULL) { NR_UE_UL_BWP_t *current_BWP = &iterator->UE->current_UL_BWP; NR_UE_sched_ctrl_t *sched_ctrl = &iterator->UE->UE_sched_ctrl; - NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch; NR_beam_alloc_t beam = beam_allocation_procedure(&nrmac->beam_info, sched_frame, sched_slot, iterator->UE->UE_beam_index, slots_per_frame); if (beam.idx < 0) { @@ -2152,33 +2151,28 @@ static void pf_ul(module_id_t module_id, LOG_D(NR_MAC, "%4d.%2d free CCE for UL DCI UE %04x\n", frame, slot, iterator->UE->rnti); - - sched_pusch->nrOfLayers = get_ul_nrOfLayers(sched_ctrl, current_BWP->dci_format); - sched_pusch->time_domain_allocation = get_ul_tda(nrmac, sched_frame, sched_slot); - sched_pusch->tda_info = get_ul_tda_info(current_BWP, - sched_ctrl->coreset->controlResourceSetId, - sched_ctrl->search_space->searchSpaceType->present, - TYPE_C_RNTI_, - sched_pusch->time_domain_allocation); - AssertFatal(sched_pusch->tda_info.valid_tda, "Invalid TDA from get_ul_tda_info\n"); - sched_pusch->dmrs_info = get_ul_dmrs_params(scc, current_BWP, &sched_pusch->tda_info, sched_pusch->nrOfLayers); + int tda = get_ul_tda(nrmac, sched_frame, sched_slot); + NR_tda_info_t tda_info = get_ul_tda_info(current_BWP, + sched_ctrl->coreset->controlResourceSetId, + sched_ctrl->search_space->searchSpaceType->present, + TYPE_C_RNTI_, + tda); + AssertFatal(tda_info.valid_tda, "Invalid TDA from get_ul_tda_info\n"); const int index = ul_buffer_index(sched_frame, sched_slot, slots_per_frame, nrmac->vrb_map_UL_size); uint16_t *rballoc_mask = &nrmac->common_channels[CC_id].vrb_map_UL[beam.idx][index * MAX_BWP_SIZE]; + /* find maximum amount of RBs that we can schedule starting from first free RB */ int rbStart = 0; - const uint16_t slbitmap = SL_to_bitmap(sched_pusch->tda_info.startSymbolIndex, sched_pusch->tda_info.nrOfSymbols); - bwp_info_t bwp_info = get_pusch_bwp_start_size(iterator->UE); - const uint32_t bwpStart = bwp_info.bwpStart; - const uint32_t bwpSize = bwp_info.bwpSize; - while (rbStart < bwpSize && (rballoc_mask[rbStart + bwpStart] & slbitmap)) + const uint16_t slbitmap = SL_to_bitmap(tda_info.startSymbolIndex, tda_info.nrOfSymbols); + bwp_info_t bi = get_pusch_bwp_start_size(iterator->UE); + while (rbStart < bi.bwpSize && (rballoc_mask[rbStart + bi.bwpStart] & slbitmap)) rbStart++; - sched_pusch->rbStart = rbStart; uint16_t max_rbSize = 1; - while (rbStart + max_rbSize < bwpSize && !(rballoc_mask[rbStart + bwpStart + max_rbSize] & slbitmap)) + while (rbStart + max_rbSize < bi.bwpSize && !(rballoc_mask[rbStart + bi.bwpStart + max_rbSize] & slbitmap)) max_rbSize++; - if (rbStart + min_rb > bwpSize || max_rbSize < min_rb) { + if (rbStart + min_rb > bi.bwpSize || max_rbSize < min_rb) { reset_beam_status(&nrmac->beam_info, frame, slot, iterator->UE->UE_beam_index, slots_per_frame, dci_beam.new_beam); reset_beam_status(&nrmac->beam_info, sched_frame, sched_slot, iterator->UE->UE_beam_index, slots_per_frame, beam.new_beam); LOG_D(NR_MAC, "[UE %04x][%4d.%2d] could not allocate UL data: no resources (rbStart %d, min_rb %d, bwpSize %d)\n", @@ -2187,7 +2181,7 @@ static void pf_ul(module_id_t module_id, slot, rbStart, min_rb, - bwpSize); + bi.bwpSize); iterator++; continue; } else @@ -2197,72 +2191,82 @@ static void pf_ul(module_id_t module_id, rbStart, min_rb, max_rbSize, - bwpSize); + bi.bwpSize); + + int nrOfLayers = get_ul_nrOfLayers(sched_ctrl, current_BWP->dci_format); + NR_sched_pusch_t sched = { + .frame = sched_frame, + .slot = sched_slot, + // rbSize set further below + .rbStart = rbStart, + .mcs = iterator->selected_mcs, + // R, Qm, tb_size set further below + .ul_harq_pid = -1, // new transmission + .nrOfLayers = nrOfLayers, + // tpmi in post-process + .time_domain_allocation = tda, + .tda_info = tda_info, + .dmrs_info = get_ul_dmrs_params(scc, current_BWP, &tda_info, nrOfLayers), + .bwp_info = bi, + // phr_txpower_calc below + }; /* Calculate the current scheduling bytes */ const int B = cmax(sched_ctrl->estimated_ul_buffer - sched_ctrl->sched_ul_bytes, 0); - sched_pusch->mcs = iterator->selected_mcs; /* adjust rbSize and MCS according to PHR and BPRE */ if(sched_ctrl->pcmax != 0 || sched_ctrl->ph != 0) // verify if the PHR related parameter have been initialized - nr_ue_max_mcs_min_rb(current_BWP->scs, sched_ctrl->ph, sched_pusch, current_BWP, min_rb, B, &max_rbSize, &sched_pusch->mcs); + nr_ue_max_mcs_min_rb(current_BWP->scs, sched_ctrl->ph, &sched, current_BWP, min_rb, B, &max_rbSize, &sched.mcs); - if (sched_pusch->mcs < sched_ctrl->ul_bler_stats.mcs) - sched_ctrl->ul_bler_stats.mcs = sched_pusch->mcs; /* force estimated MCS down */ + if (sched.mcs < sched_ctrl->ul_bler_stats.mcs) + sched_ctrl->ul_bler_stats.mcs = sched.mcs; /* force estimated MCS down */ - update_ul_ue_R_Qm(sched_pusch->mcs, current_BWP->mcs_table, current_BWP->pusch_Config, &sched_pusch->R, &sched_pusch->Qm); - uint16_t rbSize = 0; - uint32_t TBS = 0; - nr_find_nb_rb(sched_pusch->Qm, - sched_pusch->R, + update_ul_ue_R_Qm(sched.mcs, current_BWP->mcs_table, current_BWP->pusch_Config, &sched.R, &sched.Qm); + nr_find_nb_rb(sched.Qm, + sched.R, current_BWP->transform_precoding, - sched_pusch->nrOfLayers, - sched_pusch->tda_info.nrOfSymbols, - sched_pusch->dmrs_info.N_PRB_DMRS * sched_pusch->dmrs_info.num_dmrs_symb, + sched.nrOfLayers, + sched.tda_info.nrOfSymbols, + sched.dmrs_info.N_PRB_DMRS * sched.dmrs_info.num_dmrs_symb, B, min_rb, max_rbSize, - &TBS, - &rbSize); + &sched.tb_size, + &sched.rbSize); // Calacualte the normalized tx_power for PHR long *deltaMCS = current_BWP->pusch_Config ? current_BWP->pusch_Config->pusch_PowerControl->deltaMCS : NULL; - int tbs_bits = TBS << 3; + int tbs_bits = sched.tb_size << 3; - sched_pusch->phr_txpower_calc = compute_ph_factor(current_BWP->scs, - tbs_bits, - rbSize, - sched_pusch->nrOfLayers, - sched_pusch->tda_info.nrOfSymbols, - sched_pusch->dmrs_info.N_PRB_DMRS * sched_pusch->dmrs_info.num_dmrs_symb, - deltaMCS, - false); + sched.phr_txpower_calc = compute_ph_factor(current_BWP->scs, + tbs_bits, + sched.rbSize, + sched.nrOfLayers, + sched.tda_info.nrOfSymbols, + sched.dmrs_info.N_PRB_DMRS * sched.dmrs_info.num_dmrs_symb, + deltaMCS, + false); - sched_pusch->rbSize = rbSize; - sched_pusch->tb_size = TBS; - sched_pusch->bwp_info = bwp_info; - sched_pusch->frame = sched_frame; - sched_pusch->slot = sched_slot; - sched_pusch->ul_harq_pid = -1; // new transmission LOG_D(NR_MAC, "rbSize %d (max_rbSize %d), TBS %d, est buf %d, sched_ul %d, B %d, CCE %d, num_dmrs_symb %d, N_PRB_DMRS %d\n", - rbSize, + sched.rbSize, max_rbSize, - sched_pusch->tb_size, + sched.tb_size, sched_ctrl->estimated_ul_buffer, sched_ctrl->sched_ul_bytes, B, sched_ctrl->cce_index, - sched_pusch->dmrs_info.num_dmrs_symb, - sched_pusch->dmrs_info.N_PRB_DMRS); + sched.dmrs_info.num_dmrs_symb, + sched.dmrs_info.N_PRB_DMRS); /* Mark the corresponding RBs as used */ sched_ctrl->cce_index = CCEIndex; fill_pdcch_vrb_map(nrmac, CC_id, &sched_ctrl->sched_pdcch, CCEIndex, sched_ctrl->aggregation_level, dci_beam.idx); - n_rb_sched[beam.idx] -= sched_pusch->rbSize; - for (int rb = bwpStart; rb < sched_ctrl->sched_pusch.rbSize; rb++) - rballoc_mask[rb + sched_ctrl->sched_pusch.rbStart] |= slbitmap; + sched_ctrl->sched_pusch = sched; + n_rb_sched[beam.idx] -= sched.rbSize; + for (int rb = bi.bwpStart; rb < sched.rbSize; rb++) + rballoc_mask[rb + sched.rbStart] |= slbitmap; /* reduce max_num_ue once we are sure UE can be allocated, i.e., has CCE */ remainUEs[beam.idx]--; From d71cec79586c266c3a691ee719de8632bcc60ba1 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 30 Jun 2025 12:08:13 +0200 Subject: [PATCH 332/964] Refactor ULSCH phy-test scheduler Write a single NR_sched_pusch_t structure in a single statement (where possible). Assign to sched_ctrl->sched_pusch later, where the post-processing functionality will be called in a follow-up commit. --- .../LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c | 81 +++++++++---------- 1 file changed, 37 insertions(+), 44 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c index a470c48bc4..deaae2affb 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c @@ -232,6 +232,11 @@ bool nr_ul_preprocessor_phytest(module_id_t module_id, frame_t frame, slot_t slo return false; } + const int bw = ul_bwp->BWPSize; + const int BWPStart = ul_bwp->BWPStart; + uint16_t rbStart = 0; + uint16_t rbSize = min(bw, target_ul_bw); + NR_PUSCH_TimeDomainResourceAllocationList_t *tdaList = get_ul_tdalist(ul_bwp, sched_ctrl->coreset->controlResourceSetId, sched_ctrl->search_space->searchSpaceType->present, @@ -259,17 +264,6 @@ bool nr_ul_preprocessor_phytest(module_id_t module_id, frame_t frame, slot_t slo if (!is_xlsch_in_slot(ulsch_slot_bitmap, slot_period)) return false; - uint16_t rbStart = 0; - uint16_t rbSize; - - const int bw = ul_bwp->BWPSize; - const int BWPStart = ul_bwp->BWPStart; - - if (target_ul_bw>bw) - rbSize = bw; - else - rbSize = target_ul_bw; - NR_tda_info_t tda_info = get_ul_tda_info(ul_bwp, sched_ctrl->coreset->controlResourceSetId, sched_ctrl->search_space->searchSpaceType->present, @@ -277,8 +271,6 @@ bool nr_ul_preprocessor_phytest(module_id_t module_id, frame_t frame, slot_t slo tda); if (!tda_info.valid_tda) return false; - sched_ctrl->sched_pusch.tda_info = tda_info; - sched_ctrl->sched_pusch.time_domain_allocation = tda; // TODO implement beam procedures for phy-test mode int beam = 0; @@ -292,9 +284,6 @@ bool nr_ul_preprocessor_phytest(module_id_t module_id, frame_t frame, slot_t slo } } - sched_ctrl->sched_pusch.slot = sched_slot; - sched_ctrl->sched_pusch.frame = sched_frame; - int CCEIndex = get_cce_index(nr_mac, CC_id, slot, UE->rnti, &sched_ctrl->aggregation_level, @@ -311,40 +300,44 @@ bool nr_ul_preprocessor_phytest(module_id_t module_id, frame_t frame, slot_t slo sched_ctrl->cce_index = CCEIndex; - const int mcs = target_ul_mcs; - NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch; - sched_pusch->mcs = mcs; - sched_ctrl->ul_bler_stats.mcs = mcs; /* for logging output */ - sched_pusch->rbStart = rbStart; - sched_pusch->rbSize = rbSize; - /* get the PID of a HARQ process awaiting retransmission, or -1 for "any new" */ - sched_pusch->ul_harq_pid = sched_ctrl->retrans_ul_harq.head; + NR_sched_pusch_t sched = { + .frame = sched_frame, + .slot = sched_slot, + .rbSize = rbSize, + .rbStart = rbStart, + .mcs = target_ul_mcs, + // R, Qm, tb_size set further below + // PID of a HARQ process awaiting retransmission, or -1 for "any new" + .ul_harq_pid = sched_ctrl->retrans_ul_harq.head, + .nrOfLayers = target_ul_Nl, + // tpmi in post-process + .time_domain_allocation = tda, + .tda_info = tda_info, + .dmrs_info = get_ul_dmrs_params(scc, ul_bwp, &tda_info, target_ul_Nl), + .bwp_info = get_pusch_bwp_start_size(UE), + }; + sched_ctrl->ul_bler_stats.mcs = sched.mcs; /* for logging output */ /* Calculate TBS from MCS */ - sched_pusch->nrOfLayers = target_ul_Nl; - sched_pusch->R = nr_get_code_rate_ul(mcs, ul_bwp->mcs_table); - sched_pusch->Qm = nr_get_Qm_ul(mcs, ul_bwp->mcs_table); + sched.R = nr_get_code_rate_ul(sched.mcs, ul_bwp->mcs_table); + sched.Qm = nr_get_Qm_ul(sched.mcs, ul_bwp->mcs_table); if (ul_bwp->pusch_Config->tp_pi2BPSK - && ((ul_bwp->mcs_table == 3 && mcs < 2) || (ul_bwp->mcs_table == 4 && mcs < 6))) { - sched_pusch->R >>= 1; - sched_pusch->Qm <<= 1; + && ((ul_bwp->mcs_table == 3 && sched.mcs < 2) || (ul_bwp->mcs_table == 4 && sched.mcs < 6))) { + sched.R >>= 1; + sched.Qm <<= 1; } - NR_pusch_dmrs_t dmrs = get_ul_dmrs_params(scc, - ul_bwp, - &tda_info, - sched_pusch->nrOfLayers); - sched_ctrl->sched_pusch.dmrs_info = dmrs; + sched.tb_size = nr_compute_tbs(sched.Qm, + sched.R, + sched.rbSize, + tda_info.nrOfSymbols, + sched.dmrs_info.N_PRB_DMRS * sched.dmrs_info.num_dmrs_symb, + 0, // nb_rb_oh + 0, + sched.nrOfLayers /* NrOfLayers */) + >> 3; - sched_pusch->tb_size = nr_compute_tbs(sched_pusch->Qm, - sched_pusch->R, - sched_pusch->rbSize, - tda_info.nrOfSymbols, - dmrs.N_PRB_DMRS * dmrs.num_dmrs_symb, - 0, // nb_rb_oh - 0, - sched_pusch->nrOfLayers /* NrOfLayers */) - >> 3; + sched_ctrl->sched_pusch = sched; /* mark the corresponding RBs as used */ fill_pdcch_vrb_map(nr_mac, From dd9803020227a230a799f22b29c167beedc0f842 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 30 Jun 2025 17:23:52 +0200 Subject: [PATCH 333/964] Refactor to call post-processor in place Remove sched_ctrl->sched_ulsch, and call the post-processing function post_process_ulsch() in the places where sched_ctrl->sched_ulsch has been assigned. This will have two effects: - it is not necessary to have the final loop over all UEs, which might be costly especially towards many UEs. - till now, there is only a single sched_ulsch; however, a later commit will allow to schedule multiple PUSCH transmissions from a single (DL) slot. This would require to make sched_ctrl->sched_ulsch, and also iterate through all sched_ulsch. In this new scheme, we can simply call post_process_ulsch() multiple times, which is simpler (and therefore, implicitly handleded as of this commit). --- .../RAN_FUNCTION/CUSTOMIZED/ran_func_mac.c | 2 +- .../LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c | 27 +++--- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 1 - .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 92 ++++++++----------- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 4 +- openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 9 +- 6 files changed, 62 insertions(+), 73 deletions(-) diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.c b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.c index 5a451cff01..13b6306a1c 100644 --- a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.c +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.c @@ -66,7 +66,7 @@ bool read_mac_sm(void* data) } if (is_ul_slot(rd->slot, &RC.nrmac[mod_id]->frame_structure)) { rd->ul_curr_tbs = UE->mac_stats.ul.current_bytes; - rd->ul_sched_rb = sched_ctrl->sched_pusch.rbSize; + rd->ul_sched_rb = UE->mac_stats.ul.current_rbs; } rd->rnti = UE->rnti; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c index deaae2affb..6323ab4c6a 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c @@ -208,9 +208,11 @@ uint32_t target_ul_mcs = 9; uint32_t target_ul_bw = 50; uint32_t target_ul_Nl = 1; uint64_t ulsch_slot_bitmap = (1 << 8); -bool nr_ul_preprocessor_phytest(module_id_t module_id, frame_t frame, slot_t slot) +void nr_ul_preprocessor_phytest(gNB_MAC_INST *nr_mac, post_process_pusch_t *pp_pusch) { - gNB_MAC_INST *nr_mac = RC.nrmac[module_id]; + int frame = pp_pusch->frame; + int slot = pp_pusch->slot; + /* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */ NR_COMMON_channels_t *cc = nr_mac->common_channels; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; @@ -219,7 +221,7 @@ bool nr_ul_preprocessor_phytest(module_id_t module_id, frame_t frame, slot_t slo AssertFatal(nr_mac->UE_info.connected_ue_list[1] == NULL, "cannot handle more than one UE\n"); if (UE == NULL) - return false; + return; const int CC_id = 0; @@ -229,7 +231,7 @@ bool nr_ul_preprocessor_phytest(module_id_t module_id, frame_t frame, slot_t slo /* return if all UL HARQ processes wait for feedback */ if (sched_ctrl->retrans_ul_harq.head == -1 && sched_ctrl->available_ul_harq.head == -1) { LOG_D(NR_MAC, "[UE %04x][%4d.%2d] UE has no free UL HARQ process, skipping\n", UE->rnti, frame, slot); - return false; + return; } const int bw = ul_bwp->BWPSize; @@ -243,7 +245,7 @@ bool nr_ul_preprocessor_phytest(module_id_t module_id, frame_t frame, slot_t slo TYPE_C_RNTI_); const int temp_tda = get_ul_tda(nr_mac, frame, slot); if (temp_tda < 0) - return false; + return; AssertFatal(temp_tda < tdaList->list.count, "time domain assignment %d >= %d\n", temp_tda, tdaList->list.count); const int mu = ul_bwp->scs; int K2 = get_K2(tdaList, temp_tda, mu, scc); @@ -252,17 +254,18 @@ bool nr_ul_preprocessor_phytest(module_id_t module_id, frame_t frame, slot_t slo const int sched_slot = (slot + K2) % slots_frame; const int tda = get_ul_tda(nr_mac, sched_frame, sched_slot); if (tda < 0) - return false; + return; AssertFatal(tda < tdaList->list.count, "time domain assignment %d >= %d\n", tda, tdaList->list.count); + /* check if slot is UL, and that slot is 8 (assuming K2=6 because of UE * limitations). Note that if K2 or the TDD configuration is changed, below * conditions might exclude each other and never be true */ int slot_period = sched_slot % nr_mac->frame_structure.numb_slots_period; if (!is_xlsch_in_slot(ulsch_slot_bitmap, slot_period)) - return false; + return; NR_tda_info_t tda_info = get_ul_tda_info(ul_bwp, sched_ctrl->coreset->controlResourceSetId, @@ -270,7 +273,7 @@ bool nr_ul_preprocessor_phytest(module_id_t module_id, frame_t frame, slot_t slo TYPE_C_RNTI_, tda); if (!tda_info.valid_tda) - return false; + return; // TODO implement beam procedures for phy-test mode int beam = 0; @@ -280,7 +283,7 @@ bool nr_ul_preprocessor_phytest(module_id_t module_id, frame_t frame, slot_t slo for (int i = rbStart; i < rbStart + rbSize; ++i) { if ((vrb_map_UL[i+BWPStart] & SL_to_bitmap(tda_info.startSymbolIndex, tda_info.nrOfSymbols)) != 0) { LOG_E(MAC, "%4d.%2d RB %d is already reserved, cannot schedule UE\n", frame, slot, i); - return false; + return; } } @@ -295,7 +298,7 @@ bool nr_ul_preprocessor_phytest(module_id_t module_id, frame_t frame, slot_t slo 0); if (CCEIndex < 0) { LOG_E(MAC, "%s(): CCE list not empty, couldn't schedule PUSCH\n", __func__); - return false; + return; } sched_ctrl->cce_index = CCEIndex; @@ -337,7 +340,8 @@ bool nr_ul_preprocessor_phytest(module_id_t module_id, frame_t frame, slot_t slo sched.nrOfLayers /* NrOfLayers */) >> 3; - sched_ctrl->sched_pusch = sched; + /* save allocation to FAPI structures */ + post_process_ulsch(nr_mac, pp_pusch, UE, &sched); /* mark the corresponding RBs as used */ fill_pdcch_vrb_map(nr_mac, @@ -349,5 +353,4 @@ bool nr_ul_preprocessor_phytest(module_id_t module_id, frame_t frame, slot_t slo for (int rb = rbStart; rb < rbStart + rbSize; rb++) vrb_map_UL[rb+BWPStart] |= SL_to_bitmap(tda_info.startSymbolIndex, tda_info.nrOfSymbols); - return true; } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index f8c842706c..a6de5b987d 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -2692,7 +2692,6 @@ NR_UE_info_t *get_new_nr_ue_inst(uid_allocator_t *uia, rnti_t rnti, NR_CellGroup /* set illegal time domain allocation to force recomputation of all fields */ sched_ctrl->sched_pdsch.time_domain_allocation = -1; - sched_ctrl->sched_pusch.time_domain_allocation = -1; /* Set default BWPs */ AssertFatal(UE->sc_info.n_ul_bwp <= NR_MAX_NUM_BWP, "uplinkBWP_ToAddModList has %d BWP!\n", UE->sc_info.n_ul_bwp); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 493c2a37e0..4e8bce0392 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -1700,17 +1700,18 @@ static void nr_ue_max_mcs_min_rb(int mu, } static bool allocate_ul_retransmission(gNB_MAC_INST *nrmac, - frame_t frame, - slot_t slot, - uint16_t *rballoc_mask, - int *n_rb_sched, - int dci_beam_idx, - NR_UE_info_t* UE, - int harq_pid, - const NR_ServingCellConfigCommon_t *scc, - const int tda) + post_process_pusch_t *pp_pusch, + uint16_t *rballoc_mask, + int *n_rb_sched, + int dci_beam_idx, + NR_UE_info_t *UE, + int harq_pid, + const NR_ServingCellConfigCommon_t *scc, + const int tda) { const int CC_id = 0; + int frame = pp_pusch->frame; + int slot = pp_pusch->slot; NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; /* Get previous PUSCH field info */ const NR_sched_pusch_t *retInfo = &sched_ctrl->ul_harq_processes[harq_pid].sched_pusch; @@ -1820,7 +1821,7 @@ static bool allocate_ul_retransmission(gNB_MAC_INST *nrmac, fill_pdcch_vrb_map(nrmac, CC_id, &sched_ctrl->sched_pdcch, CCEIndex, sched_ctrl->aggregation_level, dci_beam_idx); // signal new allocation - sched_ctrl->sched_pusch = new_sched; + post_process_ulsch(nrmac, pp_pusch, UE, &new_sched); LOG_D(NR_MAC, "%4d.%2d Allocate UL retransmission RNTI %04x sched %4d.%2d (%d RBs)\n", frame, @@ -1848,9 +1849,8 @@ static int comparator(const void *p, const void *q) { return ((UEsched_t*)p)->coef < ((UEsched_t*)q)->coef; } -static void pf_ul(module_id_t module_id, - frame_t frame, - int slot, +static void pf_ul(gNB_MAC_INST *nrmac, + post_process_pusch_t *pp_pusch, frame_t sched_frame, int sched_slot, NR_UE_info_t *UE_list[], @@ -1859,7 +1859,8 @@ static void pf_ul(module_id_t module_id, int n_rb_sched[num_beams]) { const int CC_id = 0; - gNB_MAC_INST *nrmac = RC.nrmac[module_id]; + int frame = pp_pusch->frame; + int slot = pp_pusch->slot; NR_ServingCellConfigCommon_t *scc = nrmac->common_channels[CC_id].ServingCellConfigCommon; int slots_per_frame = nrmac->frame_structure.numb_slots_frame; const int min_rb = nrmac->min_grant_prb; @@ -1880,13 +1881,16 @@ static void pf_ul(module_id_t module_id, LOG_D(NR_MAC,"pf_ul: preparing UL scheduling for UE %04x\n",UE->rnti); NR_UE_UL_BWP_t *current_BWP = &UE->current_UL_BWP; - const NR_mac_dir_stats_t *stats = &UE->mac_stats.ul; + NR_mac_dir_stats_t *stats = &UE->mac_stats.ul; /* Calculate throughput */ const float a = 0.01f; const uint32_t b = stats->current_bytes; UE->ul_thr_ue = (1 - a) * UE->ul_thr_ue + a * b; + stats->current_bytes = 0; + stats->current_rbs = 0; + int total_rem_ues = 0; for (int i = 0; i < num_beams; i++) total_rem_ues += remainUEs[i]; @@ -1915,8 +1919,7 @@ static void pf_ul(module_id_t module_id, /* Allocate retransmission*/ const int tda = get_ul_tda(nrmac, sched_frame, sched_slot); bool r = allocate_ul_retransmission(nrmac, - frame, - slot, + pp_pusch, rballoc_mask, &n_rb_sched[beam.idx], dci_beam.idx, @@ -2063,7 +2066,8 @@ static void pf_ul(module_id_t module_id, sched.dmrs_info.N_PRB_DMRS * sched.dmrs_info.num_dmrs_symb, deltaMCS, false); - sched_ctrl->sched_pusch = sched; + /* save allocation to FAPI structures */ + post_process_ulsch(nrmac, pp_pusch, UE, &sched); LOG_D(NR_MAC, "pf_ul %d.%d UE %x Scheduling PUSCH (no data) nrb %d mcs %d tbs %d bits phr_txpower %d\n", frame, @@ -2263,7 +2267,9 @@ static void pf_ul(module_id_t module_id, sched_ctrl->cce_index = CCEIndex; fill_pdcch_vrb_map(nrmac, CC_id, &sched_ctrl->sched_pdcch, CCEIndex, sched_ctrl->aggregation_level, dci_beam.idx); - sched_ctrl->sched_pusch = sched; + /* save allocation to FAPI structures */ + post_process_ulsch(nrmac, pp_pusch, iterator->UE, &sched); + n_rb_sched[beam.idx] -= sched.rbSize; for (int rb = bi.bwpStart; rb < sched.rbSize; rb++) rballoc_mask[rb + sched.rbStart] |= slbitmap; @@ -2374,7 +2380,7 @@ nfapi_nr_pusch_pdu_t *prepare_pusch_pdu(nfapi_nr_ul_tti_request_t *future_ul_tti return pusch_pdu; } -static void post_process_ulsch(gNB_MAC_INST *nr_mac, post_process_pusch_t *pusch, NR_UE_info_t *UE, NR_sched_pusch_t *sched_pusch) +void post_process_ulsch(gNB_MAC_INST *nr_mac, post_process_pusch_t *pusch, NR_UE_info_t *UE, NR_sched_pusch_t *sched_pusch) { frame_t frame = pusch->frame; slot_t slot = pusch->slot; @@ -2585,12 +2591,14 @@ static void post_process_ulsch(gNB_MAC_INST *nr_mac, post_process_pusch_t *pusch nr_mac->cset0_bwp_size); } -static bool nr_ulsch_preprocessor(module_id_t module_id, frame_t frame, slot_t slot) +static void nr_ulsch_preprocessor(gNB_MAC_INST *nr_mac, post_process_pusch_t *pp_pusch) { - gNB_MAC_INST *nr_mac = RC.nrmac[module_id]; + int frame = pp_pusch->frame; + int slot = pp_pusch->slot; + // no UEs if (nr_mac->UE_info.connected_ue_list[0] == NULL) - return false; + return; NR_COMMON_channels_t *cc = nr_mac->common_channels; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; @@ -2603,7 +2611,7 @@ static bool nr_ulsch_preprocessor(module_id_t module_id, frame_t frame, slot_t s const int sched_frame = (frame + (slot + K2) / slots_frame) % MAX_FRAME_NUMBER; const int sched_slot = (slot + K2) % slots_frame; if (!is_ul_slot(sched_slot, &nr_mac->frame_structure)) - return false; + return; int num_beams = nr_mac->beam_info.beam_allocation ? nr_mac->beam_info.beams_per_period : 1; int bw = scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth; @@ -2618,8 +2626,7 @@ static bool nr_ulsch_preprocessor(module_id_t module_id, frame_t frame, slot_t s max_sched_ues = min(max_sched_ues, MAX_DCI_CORESET); /* proportional fair scheduling algorithm */ - pf_ul(module_id, frame, slot, sched_frame, sched_slot, nr_mac->UE_info.connected_ue_list, max_sched_ues, num_beams, len); - return true; + pf_ul(nr_mac, pp_pusch, sched_frame, sched_slot, nr_mac->UE_info.connected_ue_list, max_sched_ues, num_beams, len); } nr_pp_impl_ul nr_init_ulsch_preprocessor(int CC_id) @@ -2659,38 +2666,15 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, slot_t slot, nfapi_ /* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */ NR_SCHED_ENSURE_LOCKED(&nr_mac->sched_lock); + ul_dci_req->SFN = frame; + ul_dci_req->Slot = slot; + post_process_pusch_t pusch = { .frame = frame, .slot = slot, .ul_dci_req = ul_dci_req, .pdcch_pdu_coreset = {NULL}, }; + /* Uplink data ONLY can be scheduled when the current slot is downlink slot, * because we have to schedule the DCI0 first before schedule uplink data */ if (!is_dl_slot(slot, &nr_mac->frame_structure)) { LOG_D(NR_MAC, "Current slot %d is NOT DL slot, cannot schedule DCI0 for UL data\n", slot); return; } - bool do_sched = nr_mac->pre_processor_ul(module_id, frame, slot); - if (!do_sched) - return; - - ul_dci_req->SFN = frame; - ul_dci_req->Slot = slot; - post_process_pusch_t pusch = { frame, slot, ul_dci_req }; - - NR_UEs_t *UE_info = &nr_mac->UE_info; - UE_iterator(UE_info->connected_ue_list, UE) { - NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; - if (sched_ctrl->ul_failure && !get_softmodem_params()->phy_test) - continue; - - UE->mac_stats.ul.current_bytes = 0; - UE->mac_stats.ul.current_rbs = 0; - - /* dynamic PUSCH values (RB alloc, MCS, hence R, Qm, TBS) that change in - * every TTI are pre-populated by the preprocessor and used below */ - NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch; - LOG_D(NR_MAC,"UE %04x : sched_pusch->rbSize %d\n",UE->rnti,sched_pusch->rbSize); - if (sched_pusch->rbSize <= 0) - continue; - - post_process_ulsch(nr_mac, &pusch, UE, sched_pusch); - - memset(sched_pusch, 0, sizeof(*sched_pusch)); - } + nr_mac->pre_processor_ul(nr_mac, &pusch); } diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 66a9262f22..2c9e1a2a43 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -149,7 +149,7 @@ uint16_t nr_mac_compute_RIV(uint16_t N_RB_DL, uint16_t RBstart, uint16_t Lcrbs); void nr_preprocessor_phytest(module_id_t module_id, frame_t frame, slot_t slot); /* \brief UL preprocessor for phytest: schedules UE_id 0 with fixed MCS on a * fixed set of resources */ -bool nr_ul_preprocessor_phytest(module_id_t module_id, frame_t frame, slot_t slot); +void nr_ul_preprocessor_phytest(gNB_MAC_INST *nr_mac, post_process_pusch_t *pp_pusch); void handle_nr_uci_pucch_0_1(module_id_t mod_id, frame_t frame, @@ -498,4 +498,6 @@ void prepare_du_configuration_update(gNB_MAC_INST *mac, const NR_BCCH_DL_SCH_Message_t *sib1); void nr_mac_clean_cellgroup(NR_CellGroupConfig_t *cell_group); + +void post_process_ulsch(gNB_MAC_INST *nr_mac, post_process_pusch_t *pusch, NR_UE_info_t *UE, NR_sched_pusch_t *sched_pusch); #endif /*__LAYER2_NR_MAC_PROTO_H__*/ diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index ea7d80a214..1778d0507f 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -598,9 +598,6 @@ typedef struct { NR_sched_pucch_t *sched_pucch; int sched_pucch_size; - /// Sched PUSCH: scheduling decisions, copied into HARQ and cleared every TTI - NR_sched_pusch_t sched_pusch; - /// Sched SRS: scheduling decisions NR_sched_srs_t sched_srs; @@ -807,8 +804,12 @@ typedef struct { nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_coreset[MAX_NUM_CORESET]; } post_process_pusch_t; +/* forward declaration to use in nr_pp_impl_dl */ +struct gNB_MAC_INST_s; +typedef struct gNB_MAC_INST_s gNB_MAC_INST; + typedef void (*nr_pp_impl_dl)(module_id_t mod_id, frame_t frame, slot_t slot); -typedef bool (*nr_pp_impl_ul)(module_id_t mod_id, frame_t frame, slot_t slot); +typedef void (*nr_pp_impl_ul)(gNB_MAC_INST *nr_mac, post_process_pusch_t *pp_pusch); typedef struct f1_config_t { f1ap_setup_req_t *setup_req; From 7ee8e8eaba7fd620f23d8bd329d023dbdf161b95 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 7 Jul 2025 12:26:55 +0200 Subject: [PATCH 334/964] Fix bug: only sort relevant part of list This reduces the amount of elements to compare. --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 4e8bce0392..95a410373e 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -1869,7 +1869,7 @@ static void pf_ul(gNB_MAC_INST *nrmac, int remainUEs[num_beams]; for (int i = 0; i < num_beams; i++) remainUEs[i] = max_num_ue; - int curUE = 0; + int numUE = 0; /* Loop UE_list to calculate throughput and coeff */ UE_iterator(UE_list, UE) { @@ -2099,13 +2099,13 @@ static void pf_ul(gNB_MAC_INST *nrmac, UE->ul_thr_ue, tbs, coeff_ue); - UE_sched[curUE].coef = coeff_ue; - UE_sched[curUE].UE = UE; - UE_sched[curUE].selected_mcs = selected_mcs; - curUE++; + UE_sched[numUE].coef = coeff_ue; + UE_sched[numUE].UE = UE; + UE_sched[numUE].selected_mcs = selected_mcs; + numUE++; } - qsort(UE_sched, sizeofArray(UE_sched), sizeof(UEsched_t), comparator); + qsort(UE_sched, numUE, sizeof(UEsched_t), comparator); UEsched_t *iterator=UE_sched; /* Loop UE_sched to find max coeff and allocate transmission */ From 62e4025bc8464ae516898cea806700aae49d8706 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 30 Jun 2025 14:12:41 +0200 Subject: [PATCH 335/964] Integrate inactivity scheduling into main allocation loop Scheduling for inactivity only deviates in details from the main scheduling logic: we simply allocate a fixed number of RBs instead of making it dependent of data. In this commit, add an additional flag to sort UEs that are scheduled for inactivity in front of "normal" UEs (with traffic). Then, schedule those UEs by limiting/fixing the amount of RBs to schedule to min_grant_prb. Update the comparator() to properly sort UEs based on this flag and the coefficient by applying a consistent logic of -1/0/1 (see man qsort) for smaller/equal/larger. The inactivity flag, if set, will always have higher priority over the coefficient to schedule these UEs first, as was the case prior to this commit. --- .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 198 ++++++------------ 1 file changed, 63 insertions(+), 135 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 95a410373e..ecb4887c53 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -1841,12 +1841,27 @@ static bool allocate_ul_retransmission(gNB_MAC_INST *nrmac, static uint32_t ul_pf_tbs[5][29]; // pre-computed, approximate TBS values for PF coefficient typedef struct UEsched_s { float coef; + bool sched_inactive; NR_UE_info_t * UE; int selected_mcs; } UEsched_t; -static int comparator(const void *p, const void *q) { - return ((UEsched_t*)p)->coef < ((UEsched_t*)q)->coef; +static int comparator(const void *p, const void *q) +{ + const UEsched_t *pp = p; + const UEsched_t *qq = q; + if (pp->sched_inactive && qq->sched_inactive) + return 0; + else if (pp->sched_inactive) + return -1; + else if (qq->sched_inactive) + return 1; + /* both UEs are !sched_inactive */ + if (pp->coef < qq->coef) + return 1; + else if (pp->coef > qq->coef) + return -1; + return 0; } static void pf_ul(gNB_MAC_INST *nrmac, @@ -1977,129 +1992,23 @@ static void pf_ul(gNB_MAC_INST *nrmac, selected_mcs = get_mcs_from_bler(bo, stats, &sched_ctrl->ul_bler_stats, max_mcs, frame); LOG_D(NR_MAC, "%d.%d starting mcs %d bler %f\n", frame, slot, selected_mcs, sched_ctrl->ul_bler_stats.bler); } - /* Schedule UE on SR or UL inactivity and no data (otherwise, will be scheduled - * based on data to transmit) */ - if (B == 0 && do_sched) { - /* if no data, pre-allocate 5RB */ - /* Find a free CCE */ - int CCEIndex = get_cce_index(nrmac, - CC_id, slot, UE->rnti, - &sched_ctrl->aggregation_level, - dci_beam.idx, - sched_ctrl->search_space, - sched_ctrl->coreset, - &sched_ctrl->sched_pdcch, - false, - sched_ctrl->pdcch_cl_adjust); - if (CCEIndex < 0) { - LOG_D(NR_MAC, "[UE %04x][%4d.%2d] no free CCE for UL DCI (BSR 0)\n", UE->rnti, frame, slot); - reset_beam_status(&nrmac->beam_info, sched_frame, sched_slot, UE->UE_beam_index, slots_per_frame, beam.new_beam); - reset_beam_status(&nrmac->beam_info, frame, slot, UE->UE_beam_index, slots_per_frame, dci_beam.new_beam); - continue; - } - - int tda = get_ul_tda(nrmac, sched_frame, sched_slot); - NR_tda_info_t tda_info = get_ul_tda_info(current_BWP, - sched_ctrl->coreset->controlResourceSetId, - sched_ctrl->search_space->searchSpaceType->present, - TYPE_C_RNTI_, - tda); - AssertFatal(tda_info.valid_tda, "Invalid TDA from get_ul_tda_info\n"); - - int rbStart = 0; // wrt BWP start - LOG_D(NR_MAC, "Looking for min_rb %d RBs, starting at %d\n", min_rb, rbStart); - bwp_info_t bi = get_pusch_bwp_start_size(UE); - const uint16_t slbitmap = SL_to_bitmap(tda_info.startSymbolIndex, tda_info.nrOfSymbols); - while (rbStart < bi.bwpSize && (rballoc_mask[rbStart + bi.bwpStart] & slbitmap)) - rbStart++; - if (rbStart + min_rb > bi.bwpSize) { - LOG_D(NR_MAC, - "[UE %04x][%4d.%2d] could not allocate continuous UL data: no resources (rbStart %d, min_rb %d, bwpSize %d)\n", - UE->rnti, - frame, - slot, - rbStart, - min_rb, - bi.bwpSize); - reset_beam_status(&nrmac->beam_info, sched_frame, sched_slot, UE->UE_beam_index, slots_per_frame, beam.new_beam); - reset_beam_status(&nrmac->beam_info, frame, slot, UE->UE_beam_index, slots_per_frame, dci_beam.new_beam); - continue; - } - - sched_ctrl->cce_index = CCEIndex; - fill_pdcch_vrb_map(nrmac, CC_id, &sched_ctrl->sched_pdcch, CCEIndex, sched_ctrl->aggregation_level, dci_beam.idx); - - int nrOfLayers = get_ul_nrOfLayers(sched_ctrl, current_BWP->dci_format); - NR_sched_pusch_t sched = { - .frame = sched_frame, - .slot = sched_slot, - .rbSize = min_rb, - .rbStart = rbStart, - .mcs = selected_mcs, - // R, Qm, tb_size below - .ul_harq_pid = -1, // new transmission - .nrOfLayers = nrOfLayers, - // tpmi in post-process - .time_domain_allocation = tda, - .tda_info = tda_info, - .dmrs_info = get_ul_dmrs_params(scc, current_BWP, &tda_info, nrOfLayers), - .bwp_info = bi, - // phr_txpower_calc below - }; - update_ul_ue_R_Qm(sched.mcs, current_BWP->mcs_table, current_BWP->pusch_Config, &sched.R, &sched.Qm); - sched.tb_size = nr_compute_tbs(sched.Qm, - sched.R, - sched.rbSize, - sched.tda_info.nrOfSymbols, - sched.dmrs_info.N_PRB_DMRS * sched.dmrs_info.num_dmrs_symb, - 0, // nb_rb_oh - 0, - sched.nrOfLayers) - >> 3; - long *deltaMCS = current_BWP->pusch_Config ? current_BWP->pusch_Config->pusch_PowerControl->deltaMCS : NULL; - - sched.phr_txpower_calc = compute_ph_factor(current_BWP->scs, - sched.tb_size << 3, - sched.rbSize, - sched.nrOfLayers, - sched.tda_info.nrOfSymbols, - sched.dmrs_info.N_PRB_DMRS * sched.dmrs_info.num_dmrs_symb, - deltaMCS, - false); - /* save allocation to FAPI structures */ - post_process_ulsch(nrmac, pp_pusch, UE, &sched); - LOG_D(NR_MAC, - "pf_ul %d.%d UE %x Scheduling PUSCH (no data) nrb %d mcs %d tbs %d bits phr_txpower %d\n", - frame, - slot, - UE->rnti, - sched.rbSize, - sched.mcs, - sched.tb_size << 3, - sched.phr_txpower_calc); - - /* Mark the corresponding RBs as used */ - n_rb_sched[beam.idx] -= sched.rbSize; - for (int rb = bi.bwpStart; rb < sched.rbSize; rb++) - rballoc_mask[rb + sched.rbStart] |= slbitmap; - - remainUEs[beam.idx]--; - continue; - } /* Create UE_sched for UEs eligibale for new data transmission*/ /* Calculate coefficient*/ const uint32_t tbs = ul_pf_tbs[current_BWP->mcs_table][selected_mcs]; float coeff_ue = (float) tbs / UE->ul_thr_ue; - LOG_D(NR_MAC, "[UE %04x][%4d.%2d] b %d, ul_thr_ue %f, tbs %d, coeff_ue %f\n", + bool sched_inactive = B == 0 && do_sched; + LOG_D(NR_MAC, "[UE %04x][%4d.%2d] b %d, ul_thr_ue %f, tbs %d, coeff_ue %f, sched_inactive %d\n", UE->rnti, frame, slot, b, UE->ul_thr_ue, tbs, - coeff_ue); + coeff_ue, + sched_inactive); UE_sched[numUE].coef = coeff_ue; + UE_sched[numUE].sched_inactive = sched_inactive; UE_sched[numUE].UE = UE; UE_sched[numUE].selected_mcs = selected_mcs; numUE++; @@ -2172,11 +2081,14 @@ static void pf_ul(gNB_MAC_INST *nrmac, bwp_info_t bi = get_pusch_bwp_start_size(iterator->UE); while (rbStart < bi.bwpSize && (rballoc_mask[rbStart + bi.bwpStart] & slbitmap)) rbStart++; - uint16_t max_rbSize = 1; - while (rbStart + max_rbSize < bi.bwpSize && !(rballoc_mask[rbStart + bi.bwpStart + max_rbSize] & slbitmap)) - max_rbSize++; + /* if it's for inactivity, min_grant_prb is enough, otherwise check what + * would be the maximum */ + uint16_t max_rbSize = iterator->sched_inactive ? min_rb : bi.bwpSize; + uint16_t available_rb = 1; + while (rbStart + available_rb < bi.bwpSize && !(rballoc_mask[rbStart + bi.bwpStart + available_rb] & slbitmap) && available_rb < max_rbSize) + available_rb++; - if (rbStart + min_rb > bi.bwpSize || max_rbSize < min_rb) { + if (rbStart + min_rb > bi.bwpSize || available_rb < min_rb) { reset_beam_status(&nrmac->beam_info, frame, slot, iterator->UE->UE_beam_index, slots_per_frame, dci_beam.new_beam); reset_beam_status(&nrmac->beam_info, sched_frame, sched_slot, iterator->UE->UE_beam_index, slots_per_frame, beam.new_beam); LOG_D(NR_MAC, "[UE %04x][%4d.%2d] could not allocate UL data: no resources (rbStart %d, min_rb %d, bwpSize %d)\n", @@ -2190,11 +2102,11 @@ static void pf_ul(gNB_MAC_INST *nrmac, continue; } else LOG_D(NR_MAC, - "allocating UL data for RNTI %04x (rbStart %d, min_rb %d, max_rbSize %d, bwpSize %d)\n", + "allocating UL data for RNTI %04x (rbStart %d, min_rb %d, available_rb %d, bwpSize %d)\n", iterator->UE->rnti, rbStart, min_rb, - max_rbSize, + available_rb, bi.bwpSize); int nrOfLayers = get_ul_nrOfLayers(sched_ctrl, current_BWP->dci_format); @@ -2217,25 +2129,41 @@ static void pf_ul(gNB_MAC_INST *nrmac, /* Calculate the current scheduling bytes */ const int B = cmax(sched_ctrl->estimated_ul_buffer - sched_ctrl->sched_ul_bytes, 0); - /* adjust rbSize and MCS according to PHR and BPRE */ - if(sched_ctrl->pcmax != 0 || sched_ctrl->ph != 0) // verify if the PHR related parameter have been initialized - nr_ue_max_mcs_min_rb(current_BWP->scs, sched_ctrl->ph, &sched, current_BWP, min_rb, B, &max_rbSize, &sched.mcs); + /* adjust rbSize and MCS according to PHR and BPRE, only if there is data */ + if((sched_ctrl->pcmax != 0 || sched_ctrl->ph != 0) && B > 0) + nr_ue_max_mcs_min_rb(current_BWP->scs, sched_ctrl->ph, &sched, current_BWP, min_rb, B, &available_rb, &sched.mcs); if (sched.mcs < sched_ctrl->ul_bler_stats.mcs) sched_ctrl->ul_bler_stats.mcs = sched.mcs; /* force estimated MCS down */ update_ul_ue_R_Qm(sched.mcs, current_BWP->mcs_table, current_BWP->pusch_Config, &sched.R, &sched.Qm); - nr_find_nb_rb(sched.Qm, - sched.R, - current_BWP->transform_precoding, - sched.nrOfLayers, - sched.tda_info.nrOfSymbols, - sched.dmrs_info.N_PRB_DMRS * sched.dmrs_info.num_dmrs_symb, - B, - min_rb, - max_rbSize, - &sched.tb_size, - &sched.rbSize); + if (!iterator->sched_inactive) { + // this UE has data, find optimal number of RB for data and in range + // [min_rb,available_rb] + nr_find_nb_rb(sched.Qm, + sched.R, + current_BWP->transform_precoding, + sched.nrOfLayers, + sched.tda_info.nrOfSymbols, + sched.dmrs_info.N_PRB_DMRS * sched.dmrs_info.num_dmrs_symb, + B, + min_rb, + available_rb, + &sched.tb_size, + &sched.rbSize); + } else { + // this UE is scheduled due to SR or inactivity and no data + sched.rbSize = min_rb; + sched.tb_size = nr_compute_tbs(sched.Qm, + sched.R, + sched.rbSize, + sched.tda_info.nrOfSymbols, + sched.dmrs_info.N_PRB_DMRS * sched.dmrs_info.num_dmrs_symb, + 0, // nb_rb_oh + 0, + sched.nrOfLayers) + >> 3; + } // Calacualte the normalized tx_power for PHR long *deltaMCS = current_BWP->pusch_Config ? current_BWP->pusch_Config->pusch_PowerControl->deltaMCS : NULL; @@ -2251,9 +2179,9 @@ static void pf_ul(gNB_MAC_INST *nrmac, false); LOG_D(NR_MAC, - "rbSize %d (max_rbSize %d), TBS %d, est buf %d, sched_ul %d, B %d, CCE %d, num_dmrs_symb %d, N_PRB_DMRS %d\n", + "rbSize %d (available_rb %d), TBS %d, est buf %d, sched_ul %d, B %d, CCE %d, num_dmrs_symb %d, N_PRB_DMRS %d\n", sched.rbSize, - max_rbSize, + available_rb, sched.tb_size, sched_ctrl->estimated_ul_buffer, sched_ctrl->sched_ul_bytes, From 8cded62df0aad41a7b2db68ab867bceebeecbc76 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 13 Jun 2025 17:20:23 +0200 Subject: [PATCH 336/964] Refactor TDA allocation Make it simpler to see, in function nr_rrc_config_ul_tda(), which UL TDAs we allocate for a UE. --- openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c | 55 ++++++-------------- 1 file changed, 17 insertions(+), 38 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c index eba1152cd0..6e111ded06 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c @@ -1048,58 +1048,34 @@ void nr_rrc_config_dl_tda(struct NR_PDSCH_TimeDomainResourceAllocationList *pdsc } } -static struct NR_PUSCH_TimeDomainResourceAllocation *set_TimeDomainResourceAllocation(const int k2, uint8_t index, int ul_symb) +static struct NR_PUSCH_TimeDomainResourceAllocation *set_TimeDomainResourceAllocation(const int k2, long sliv) { struct NR_PUSCH_TimeDomainResourceAllocation *puschTdrAlloc = calloc_or_fail(1, sizeof(*puschTdrAlloc)); puschTdrAlloc->k2 = calloc_or_fail(1, sizeof(*puschTdrAlloc->k2)); *puschTdrAlloc->k2 = k2; puschTdrAlloc->mappingType = NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB; - switch (index) { - case 0: - puschTdrAlloc->startSymbolAndLength = get_SLIV(0, 13); - break; - case 1: - puschTdrAlloc->startSymbolAndLength = get_SLIV(0, 12); - break; - case 2: - // UL TDA index 2 for mixed slot (TDD) - puschTdrAlloc->startSymbolAndLength = - get_SLIV(NR_NUMBER_OF_SYMBOLS_PER_SLOT - ul_symb, ul_symb - 1); // starting in fist ul symbol til the last but one - break; - case 3: { - // UL TDA index 3 for msg3 in the mixed slot (TDD) - int no_mix_slot = ul_symb < 3 ? 1 : 0; // we need at least 2 symbols for scheduling Msg3 - *puschTdrAlloc->k2 += no_mix_slot; - if (no_mix_slot) - puschTdrAlloc->startSymbolAndLength = get_SLIV(0, 13); // full allocation if there is no mixed slot - else - puschTdrAlloc->startSymbolAndLength = - get_SLIV(NR_NUMBER_OF_SYMBOLS_PER_SLOT - ul_symb, ul_symb - 1); // starting in fist ul symbol til the last but one - } - break; - default: - break; - } + puschTdrAlloc->startSymbolAndLength = sliv; return puschTdrAlloc; } void nr_rrc_config_ul_tda(NR_ServingCellConfigCommon_t *scc, int min_fb_delay) { - //TODO change to accomodate for SRS - - const NR_PUSCH_TimeDomainResourceAllocationList_t *tda = + NR_PUSCH_TimeDomainResourceAllocationList_t *tda_list = scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList; - AssertFatal(tda->list.count == 0, "already have pusch_TimeDomainAllocationList members\n"); + AssertFatal(tda_list->list.count == 0, "already have pusch_TimeDomainAllocationList members\n"); const int k2 = min_fb_delay; + int mu = scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing; - struct NR_SetupRelease_PUSCH_ConfigCommon *pusch_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon; // UL TDA index 0 is basic slot configuration starting in symbol 0 til the last but one symbol - asn1cSeqAdd(&pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list, set_TimeDomainResourceAllocation(k2, 0, 0)); + NR_PUSCH_TimeDomainResourceAllocation_t *tda; + tda = set_TimeDomainResourceAllocation(k2, get_SLIV(0, 13)); + asn1cSeqAdd(&tda_list->list, tda); // UL TDA index 1 in case of SRS - asn1cSeqAdd(&pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list, set_TimeDomainResourceAllocation(k2, 1, 0)); + tda = set_TimeDomainResourceAllocation(k2, get_SLIV(0, 12)); + asn1cSeqAdd(&tda_list->list, tda); if (scc->tdd_UL_DL_ConfigurationCommon) { int ul_symb = 0; @@ -1117,21 +1093,24 @@ void nr_rrc_config_ul_tda(NR_ServingCellConfigCommon_t *scc, int min_fb_delay) } if (ul_symb>1) { // UL TDA index 2 for mixed slot (TDD) - asn1cSeqAdd(&pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list, - set_TimeDomainResourceAllocation(k2, 2, ul_symb)); + long sliv = get_SLIV(NR_NUMBER_OF_SYMBOLS_PER_SLOT - ul_symb, ul_symb - 1); + tda = set_TimeDomainResourceAllocation(k2, sliv); + asn1cSeqAdd(&tda_list->list, tda); } // UL TDA index 3 for msg3 in the mixed slot (TDD) int tdd_period_idx = get_tdd_period_idx(scc->tdd_UL_DL_ConfigurationCommon); int nb_periods_per_frame = get_nb_periods_per_frame(tdd_period_idx); int nb_slots_per_period = ((1 << mu) * 10) / nb_periods_per_frame; int k2_msg3 = nb_slots_per_period - get_delta_for_k2(mu); - struct NR_PUSCH_TimeDomainResourceAllocation *puschTdrAllocMsg3 = set_TimeDomainResourceAllocation(k2_msg3, 3, ul_symb); + bool no_mix_slot = ul_symb < 3; // we need at least 2 symbols for scheduling Msg3 + long sliv = no_mix_slot ? get_SLIV(0, 13) : get_SLIV(NR_NUMBER_OF_SYMBOLS_PER_SLOT - ul_symb, ul_symb - 1); + struct NR_PUSCH_TimeDomainResourceAllocation *puschTdrAllocMsg3 = set_TimeDomainResourceAllocation(k2_msg3, sliv); if (*puschTdrAllocMsg3->k2 < min_fb_delay) *puschTdrAllocMsg3->k2 += nb_slots_per_period; AssertFatal(*puschTdrAllocMsg3->k2 < 33, "Computed k2 for msg3 %ld is larger than the range allowed by RRC (0..32)\n", *puschTdrAllocMsg3->k2); - asn1cSeqAdd(&pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list, puschTdrAllocMsg3); + asn1cSeqAdd(&tda_list->list, puschTdrAllocMsg3); } } From 7cae3c2871651b9f76371f27e417dcd91e394604 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 13 Jun 2025 17:43:12 +0200 Subject: [PATCH 337/964] Comments on func --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index ecb4887c53..bbbd72c378 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -38,6 +38,8 @@ //#define SRS_IND_DEBUG +/* \brief Get the UL TDA for given frame and slot. It identifies the index of + * TDA in the TDA list, as hardcoded in nr_rrc_config_ul_tda(). */ int get_ul_tda(gNB_MAC_INST *nrmac, int frame, int slot) { /* we assume that this function is mutex-protected from outside */ @@ -51,7 +53,7 @@ int get_ul_tda(gNB_MAC_INST *nrmac, int frame, int slot) int s = get_slot_idx_in_period(slot, fs); tdd_bitmap_t *tdd_slot_bitmap = fs->period_cfg.tdd_slot_bitmap; if ((tdd_slot_bitmap[s].num_ul_symbols > 1) && is_mixed_slot(s, fs)) { - return 2; + return 2; // mixed slot, all symbols of mixed minus last } } @@ -59,10 +61,10 @@ int get_ul_tda(gNB_MAC_INST *nrmac, int frame, int slot) UE_iterator(nrmac->UE_info.connected_ue_list, UE) { NR_sched_srs_t sched_srs = UE->UE_sched_ctrl.sched_srs; if(sched_srs.srs_scheduled && sched_srs.frame == frame && sched_srs.slot == slot) - return 1; + return 1; // symbols 0--12 } - return 0; // if FDD or not mixed slot in TDD, for now use default TDA (TODO handle CSI-RS slots) + return 0; // symbols 0--13, // if FDD or not mixed slot in TDD, for now use default TDA (TODO handle CSI-RS slots) } bwp_info_t get_pusch_bwp_start_size(NR_UE_info_t *UE) From ac3451c6f75b48315bd4489665bc85294e292858 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 21 Jul 2025 10:50:46 +0200 Subject: [PATCH 338/964] Select ra_ResponseWindow automatically if not configured If the config file does not specify ra_ResponseWindow, select it to be 10 slots in mu=0, or 20 slots for all others. This should give us enough flexibility to allocate Msg2 without running out of the response window. The next commit will remove most ra_ResponseWindow options in configs. --- openair2/GNB_APP/RRC_nr_paramsvalues.h | 2 +- openair2/GNB_APP/gnb_config.c | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/openair2/GNB_APP/RRC_nr_paramsvalues.h b/openair2/GNB_APP/RRC_nr_paramsvalues.h index 44774342e5..1525c31b9a 100644 --- a/openair2/GNB_APP/RRC_nr_paramsvalues.h +++ b/openair2/GNB_APP/RRC_nr_paramsvalues.h @@ -228,7 +228,7 @@ {GNB_CONFIG_STRING_PREAMBLERECEIVEDTARGETPOWER,NULL,0,.i64ptr=&scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.preambleReceivedTargetPower,.defint64val=-118,TYPE_INT64,0/*75*/},\ {GNB_CONFIG_STRING_PREAMBLETRANSMAX,NULL,0,.i64ptr=&scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.preambleTransMax,.defint64val=NR_RACH_ConfigGeneric__preambleTransMax_n10,TYPE_INT64,0/*76*/},\ {GNB_CONFIG_STRING_POWERRAMPINGSTEP,NULL,0,.i64ptr=&scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.powerRampingStep,.defint64val=NR_RACH_ConfigGeneric__powerRampingStep_dB2,TYPE_INT64,0/*77*/},\ -{GNB_CONFIG_STRING_RARESPONSEWINDOW,NULL,0,.i64ptr=&scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.ra_ResponseWindow,.defint64val=NR_RACH_ConfigGeneric__ra_ResponseWindow_sl20,TYPE_INT64,0/*78*/},\ +{GNB_CONFIG_STRING_RARESPONSEWINDOW,NULL,0,.i64ptr=&scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.ra_ResponseWindow,.defint64val=-1,TYPE_INT64,0/*78*/},\ {GNB_CONFIG_STRING_SSBPERRACHOCCASIONANDCBPREAMBLESPERSSBPR,NULL,0,.uptr=&scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present,.defuintval=NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_one,TYPE_UINT,0/*79*/},\ {GNB_CONFIG_STRING_SSBPERRACHOCCASIONANDCBPREAMBLESPERSSB,NULL,0,.i64ptr=&scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.one,.defint64val=NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB__one_n64,TYPE_INT64,0 /*80*/}, \ {GNB_CONFIG_STRING_RACONTENTIONRESOLUTIONTIMER,NULL,0,.i64ptr=&scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->ra_ContentionResolutionTimer,.defint64val=NR_RACH_ConfigCommon__ra_ContentionResolutionTimer_sf64,TYPE_INT64,0/*81*/},\ diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index f01b5968f7..8f162ff1ce 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -575,6 +575,14 @@ void fix_scc(NR_ServingCellConfigCommon_t *scc, uint64_t ssbmap) rach_ConfigCommon->msg3_transformPrecoder = NULL; } + // by default, select ra_ResponseWindow automatically + if (rach_ConfigCommon->rach_ConfigGeneric.ra_ResponseWindow < 0) { + int mu = *scc->ssbSubcarrierSpacing; + // will select: mu=0 => 4 (10 slots), mu=1 => 5 (20 slots), mu>=3 => 7 (80 slots) + rach_ConfigCommon->rach_ConfigGeneric.ra_ResponseWindow = min(NR_RACH_ConfigGeneric__ra_ResponseWindow_sl80, NR_RACH_ConfigGeneric__ra_ResponseWindow_sl10 + mu); + } + DevAssert(rach_ConfigCommon->rach_ConfigGeneric.ra_ResponseWindow >= 0); + // prepare DL Allocation lists nr_rrc_config_dl_tda(dlcc->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList, frame_type, From 41d14b571c80c43a77078e83d8c115547b8748c5 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 21 Jul 2025 10:37:01 +0200 Subject: [PATCH 339/964] Remove most ra_ResponseWindow config options Since the parent commit, the ra_ResponseWindow will be chosen automatically. Correspondingly, remove most ra_ResponseWindow options from configuration files in the repository. One problem in some mu=1 configs is that the ra_ResponseWindow=4 (10 slots), which might be overly restrictive if the L1 slot ahead is somewhat close to 10 (e.g., 6), in which case we might not be always able to allocate Msg2 in time. A notable exception here is gnb-vnf.sa.band66.u0.25prb.nfapi.conf, in which we still provide it (1) since it uses a non-standard configuration of a ra_ResponseWindow longer than 10ms (see also issue #916 for more information) and (2) as an example. --- ci-scripts/conf_files/gnb-du.sa.band1.52prb.usrpb210.conf | 3 --- ci-scripts/conf_files/gnb-du.sa.band78.106prb.rfsim.conf | 3 --- ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf | 3 --- .../conf_files/gnb-vnf.sa.band77.162prb.nfapi.4x4.conf | 3 --- ci-scripts/conf_files/gnb-vnf.sa.band78.273prb.aerial.conf | 3 --- .../conf_files/gnb.band66.106prb.rfsim.phytest-dora.conf | 3 --- .../conf_files/gnb.band78.106prb.rfsim.phytest-dora.conf | 3 --- .../conf_files/gnb.band79.106prb.usrpn300.phytest-dora.conf | 3 --- .../conf_files/gnb.band79.162prb.usrpn300.phytest-dora.conf | 3 --- .../conf_files/gnb.band79.273prb.usrpn300.phytest-dora.conf | 3 --- ci-scripts/conf_files/gnb.nsa.band78.106prb.usrpb200.conf | 3 --- .../conf_files/gnb.nsa.band78.106prb.usrpn310.2x2.conf | 3 --- .../conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn-leo.conf | 3 --- ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn.conf | 3 --- ci-scripts/conf_files/gnb.sa.band261.u3.32prb.rfsim.conf | 3 --- ci-scripts/conf_files/gnb.sa.band66.106prb.rfsim.conf | 3 --- ci-scripts/conf_files/gnb.sa.band77.162prb.usrpn310.2x2.conf | 3 --- .../conf_files/gnb.sa.band77.273prb.fhi72.4x4-vvdn.conf | 3 --- .../gnb.sa.band77.273prb.fhi72.4x4.2L-metanoia.conf | 3 --- ci-scripts/conf_files/gnb.sa.band77.273prb.usrpn310.2x2.conf | 3 --- ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf | 3 --- ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.conf | 3 --- .../conf_files/gnb.sa.band78.106prb.rfsim.flexric.conf | 3 --- .../conf_files/gnb.sa.band78.106prb.rfsim.neighbour.conf | 3 --- ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.yaml | 3 --- ci-scripts/conf_files/gnb.sa.band78.106prb.usrp310.2x2.conf | 3 --- .../conf_files/gnb.sa.band78.106prb.usrpb200.sc-fdma.conf | 3 --- .../conf_files/gnb.sa.band78.106prb.usrpn310.ddsuu-2x2.conf | 3 --- ci-scripts/conf_files/gnb.sa.band78.162prb.usrpn310.2x2.conf | 3 --- ci-scripts/conf_files/gnb.sa.band78.24prb.rfsim.conf | 3 --- .../gnb.sa.band78.273prb.fhi72.4x4-benetel550.conf | 3 --- ci-scripts/conf_files/gnb.sa.band78.273prb.rfsim.2x2.conf | 3 --- .../conf_files/gnb.sa.band78.51prb.aw2s.ddsuu.2x2.conf | 3 --- ci-scripts/conf_files/gnb.sa.band78.51prb.aw2s.ddsuu.conf | 3 --- ci-scripts/conf_files/gnb.sa.band78.51prb.usrpb200.conf | 3 --- ci-scripts/conf_files/untested/benetel-5g.conf | 3 --- .../untested/episci/episci_rcc.band78.tm1.106PRB.nfapi.conf | 3 --- .../untested/episci/gnb_band78.sa.fr1.106PRB.2x2.l2sim.conf | 3 --- .../untested/episci/proxy_rcc.band78.tm1.106PRB.nfapi.conf | 3 --- .../conf_files/untested/gNB_SA_n78_106PRB.2x2_usrpn310.conf | 3 --- .../conf_files/untested/gNB_SA_n78_133PRB.2x2_usrpn310.conf | 3 --- .../untested/gnb.band78.sa.fr1.106PRB.usrpn310.conf | 3 --- .../untested/gnb.band78.tm1.fr1.106PRB.usrpb210.conf | 3 --- .../untested/gnb.band78.tm1.fr1.106PRB.usrpn310.conf | 3 --- .../untested/gnb.sa.band66.fr1.106PRB.usrpn300.conf | 3 --- .../untested/gnb.sa.band78.fr1.51PRB.usrpb210.conf | 3 --- .../untested/proxy_gnb.band78.sa.fr1.106PRB.usrpn310.conf | 3 --- doc/nfapi.md | 5 +++-- doc/testing_gnb_w_cots_ue_resources/gnb.conf | 3 --- targets/PROJECTS/GENERIC-LTE-EPC/CONF/benetel-5g.conf | 3 --- .../GENERIC-LTE-EPC/CONF/gnb.band257.tm1.32PRB.usrpn300.conf | 3 --- .../GENERIC-LTE-EPC/CONF/gnb.band257.tm1.32PRB.usrpx300.conf | 3 --- .../GENERIC-LTE-EPC/CONF/gnb.band257.tm1.66PRB.usrpn300.conf | 3 --- .../GENERIC-LTE-EPC/CONF/gnb.band261.tm1.32PRB.usrpn300.conf | 3 --- .../GENERIC-LTE-EPC/CONF/gnb.band66.tm1.106PRB.usrpn300.conf | 3 --- .../GENERIC-LTE-EPC/CONF/gnb.band66.tm1.106PRB.usrpx300.conf | 3 --- .../GENERIC-LTE-EPC/CONF/gnb.band66.tm1.24PRB.usrpx300.conf | 3 --- .../GENERIC-LTE-EPC/CONF/gnb.band66.tm1.25PRB.usrpn300.conf | 3 --- .../GENERIC-LTE-EPC/CONF/gnb.band66.tm1.25PRB.usrpx300.conf | 3 --- .../CONF/gnb.band78.106PRB.30kHz,usrpb2x0.conf | 3 --- .../GENERIC-LTE-EPC/CONF/gnb.band78.106PRB.slave.conf | 3 --- targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.slave.conf | 3 --- .../CONF/gnb.band78.tm1.106PRB.PTRS.usrpx300.conf | 3 --- .../GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpb210.conf | 3 --- .../GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf | 3 --- .../GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpx300.conf | 3 --- .../GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpn300.conf | 3 --- .../GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpx300.conf | 3 --- .../GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpb210.conf | 3 --- .../GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpn300.conf | 3 --- .../GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpx300.conf | 3 --- .../GENERIC-LTE-EPC/CONF/gnb.band78.tm1.273PRB.usrpn300.conf | 3 --- targets/PROJECTS/GENERIC-NR-5GC/CONF/du_gnb.conf | 3 --- .../CONF/gnb-du.sa.band66.25prb.rfsim.pci0.conf | 3 --- .../CONF/gnb-du.sa.band66.25prb.rfsim.pci1.conf | 3 --- .../CONF/gnb-du.sa.band77.273prb.fhi72.4x4-benetel650.conf | 3 --- ...-du.sa.band77.273prb.fhi72.8x8-benetel650_650-mplane.conf | 3 --- .../gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650.conf | 3 --- .../CONF/gnb-du.sa.band78.106prb.rfsim.pci0.conf | 3 --- .../CONF/gnb-du.sa.band78.106prb.rfsim.pci1.conf | 3 --- .../GENERIC-NR-5GC/CONF/gnb-vnf.sa.band78.106prb.nfapi.conf | 3 --- .../GENERIC-NR-5GC/CONF/gnb-vnf.sa.band78.273prb.aerial.conf | 3 --- .../GENERIC-NR-5GC/CONF/gnb-vnf.sa.band78.273prb.nfapi.conf | 3 --- .../PROJECTS/GENERIC-NR-5GC/CONF/gnb-vnf.sa.cbrs.aerial.conf | 3 --- .../CONF/gnb.band78.sa.fr1.106PRB.2x2.usrpn310.conf | 3 --- .../CONF/gnb.band78.sa.fr1.162PRB.2x2.usrpn310.conf | 3 --- .../GENERIC-NR-5GC/CONF/gnb.sa.band1.u0.52PRB.usrpb210.conf | 3 --- .../CONF/gnb.sa.band254.ntn.mu1.24prb.rfsim.conf | 3 --- .../CONF/gnb.sa.band255.ntn.mu0.25prb.rfsim.conf | 3 --- .../CONF/gnb.sa.band256.ntn.mu0.25prb.rfsim.conf | 3 --- .../CONF/gnb.sa.band257.u3.32prb.usrpx410.conf | 3 --- .../CONF/gnb.sa.band41.fr1.106PRB.usrpb210.conf | 3 --- .../CONF/gnb.sa.band41.fr1.52PRB.usrpb210.conf | 3 --- .../CONF/gnb.sa.band66.fr1.106PRB.usrpn300.conf | 3 --- .../CONF/gnb.sa.band66.fr1.106PRB.usrpx300.conf | 3 --- .../CONF/gnb.sa.band66.fr1.24PRB.usrpx300.conf | 3 --- .../CONF/gnb.sa.band66.fr1.25PRB.usrpx300.conf | 3 --- .../GENERIC-NR-5GC/CONF/gnb.sa.band66.u0.25prb.rfsim.conf | 3 --- .../CONF/gnb.sa.band77.106prb.fhi72.4x4-vvdn.conf | 3 --- .../CONF/gnb.sa.band77.162prb.usrpn310.4x4.conf | 3 --- .../CONF/gnb.sa.band77.273prb.fhi72.2x2-vvdn.conf | 3 --- .../CONF/gnb.sa.band77.273prb.fhi72.4x4-vvdn.conf | 3 --- .../CONF/gnb.sa.band77.fr1.273PRB.2x2.usrpn300.conf | 3 --- .../CONF/gnb.sa.band77.fr1.273PRB.usrpx300.conf | 3 --- .../CONF/gnb.sa.band78.106PRB.usrpb210.RA_2-Step.conf | 3 --- .../CONF/gnb.sa.band78.273prb.fhi72.4x2-benetel550.conf | 3 --- .../gnb.sa.band78.273prb.fhi72.4x4-benetel550-mplane.conf | 3 --- .../CONF/gnb.sa.band78.273prb.fhi72.4x4-benetel550.conf | 3 --- .../CONF/gnb.sa.band78.273prb.fhi72.4x4-foxconn.conf | 3 --- .../CONF/gnb.sa.band78.273prb.fhi72.4x4-liteon.conf | 3 --- .../CONF/gnb.sa.band78.273prb.fhi72.4x4-metanoia.conf | 3 --- .../CONF/gnb.sa.band78.fr1.106PRB.2x2.usrpn300.conf | 3 --- .../CONF/gnb.sa.band78.fr1.106PRB.usrpb210.2pattern.conf | 3 --- .../CONF/gnb.sa.band78.fr1.106PRB.usrpb210.4layer.conf | 3 --- .../CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf | 3 --- .../CONF/gnb.sa.band78.fr1.106PRB.usrpb210.redcap.yaml | 3 --- .../CONF/gnb.sa.band78.fr1.106PRB.usrpb210.sabox.conf | 3 --- .../CONF/gnb.sa.band78.fr1.106PRB.usrpb210.yaml | 3 --- .../CONF/gnb.sa.band78.fr1.162PRB.2x2.usrpn300.conf | 3 --- .../GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.189PRB.rfsim.conf | 3 --- .../CONF/gnb.sa.band78.fr1.217PRB.2x2.usrpn300.conf | 3 --- .../CONF/gnb.sa.band78.fr1.24PRB.usrpb210.conf | 3 --- .../CONF/gnb0.prs.band261.fr2.64PRB.usrpx310.conf | 3 --- .../CONF/gnb0.prs.band78.fr1.106PRB.usrpx310.conf | 3 --- .../CONF/gnb1.prs.band261.fr2.64PRB.usrpx310.conf | 3 --- .../CONF/gnb1.prs.band78.fr1.106PRB.usrpx310.conf | 3 --- 126 files changed, 3 insertions(+), 377 deletions(-) diff --git a/ci-scripts/conf_files/gnb-du.sa.band1.52prb.usrpb210.conf b/ci-scripts/conf_files/gnb-du.sa.band1.52prb.usrpb210.conf index 2af3185ffc..173c9b3f73 100644 --- a/ci-scripts/conf_files/gnb-du.sa.band1.52prb.usrpb210.conf +++ b/ci-scripts/conf_files/gnb-du.sa.band1.52prb.usrpb210.conf @@ -86,9 +86,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/ci-scripts/conf_files/gnb-du.sa.band78.106prb.rfsim.conf b/ci-scripts/conf_files/gnb-du.sa.band78.106prb.rfsim.conf index fce5e6dc6e..d2798cbccc 100644 --- a/ci-scripts/conf_files/gnb-du.sa.band78.106prb.rfsim.conf +++ b/ci-scripts/conf_files/gnb-du.sa.band78.106prb.rfsim.conf @@ -84,9 +84,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf b/ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf index 66e721ef84..f829996433 100644 --- a/ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf +++ b/ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf @@ -83,9 +83,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/ci-scripts/conf_files/gnb-vnf.sa.band77.162prb.nfapi.4x4.conf b/ci-scripts/conf_files/gnb-vnf.sa.band77.162prb.nfapi.4x4.conf index ba156df849..814518f3b1 100644 --- a/ci-scripts/conf_files/gnb-vnf.sa.band77.162prb.nfapi.4x4.conf +++ b/ci-scripts/conf_files/gnb-vnf.sa.band77.162prb.nfapi.4x4.conf @@ -85,9 +85,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 5; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/ci-scripts/conf_files/gnb-vnf.sa.band78.273prb.aerial.conf b/ci-scripts/conf_files/gnb-vnf.sa.band78.273prb.aerial.conf index 37223d712c..585d639f9f 100644 --- a/ci-scripts/conf_files/gnb-vnf.sa.band78.273prb.aerial.conf +++ b/ci-scripts/conf_files/gnb-vnf.sa.band78.273prb.aerial.conf @@ -97,9 +97,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 5; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/ci-scripts/conf_files/gnb.band66.106prb.rfsim.phytest-dora.conf b/ci-scripts/conf_files/gnb.band66.106prb.rfsim.phytest-dora.conf index b1d2d6d724..e69fee4722 100644 --- a/ci-scripts/conf_files/gnb.band66.106prb.rfsim.phytest-dora.conf +++ b/ci-scripts/conf_files/gnb.band66.106prb.rfsim.phytest-dora.conf @@ -84,9 +84,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/ci-scripts/conf_files/gnb.band78.106prb.rfsim.phytest-dora.conf b/ci-scripts/conf_files/gnb.band78.106prb.rfsim.phytest-dora.conf index e49f8c422a..eb7c1e01e2 100644 --- a/ci-scripts/conf_files/gnb.band78.106prb.rfsim.phytest-dora.conf +++ b/ci-scripts/conf_files/gnb.band78.106prb.rfsim.phytest-dora.conf @@ -83,9 +83,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 5; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/ci-scripts/conf_files/gnb.band79.106prb.usrpn300.phytest-dora.conf b/ci-scripts/conf_files/gnb.band79.106prb.usrpn300.phytest-dora.conf index 691fb86393..f36619e58a 100644 --- a/ci-scripts/conf_files/gnb.band79.106prb.usrpn300.phytest-dora.conf +++ b/ci-scripts/conf_files/gnb.band79.106prb.usrpn300.phytest-dora.conf @@ -83,9 +83,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/ci-scripts/conf_files/gnb.band79.162prb.usrpn300.phytest-dora.conf b/ci-scripts/conf_files/gnb.band79.162prb.usrpn300.phytest-dora.conf index bb0388f113..caa3381365 100644 --- a/ci-scripts/conf_files/gnb.band79.162prb.usrpn300.phytest-dora.conf +++ b/ci-scripts/conf_files/gnb.band79.162prb.usrpn300.phytest-dora.conf @@ -83,9 +83,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/ci-scripts/conf_files/gnb.band79.273prb.usrpn300.phytest-dora.conf b/ci-scripts/conf_files/gnb.band79.273prb.usrpn300.phytest-dora.conf index 67f1272563..586492e93f 100644 --- a/ci-scripts/conf_files/gnb.band79.273prb.usrpn300.phytest-dora.conf +++ b/ci-scripts/conf_files/gnb.band79.273prb.usrpn300.phytest-dora.conf @@ -85,9 +85,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/ci-scripts/conf_files/gnb.nsa.band78.106prb.usrpb200.conf b/ci-scripts/conf_files/gnb.nsa.band78.106prb.usrpb200.conf index bbe3168aa2..d71be72f17 100644 --- a/ci-scripts/conf_files/gnb.nsa.band78.106prb.usrpb200.conf +++ b/ci-scripts/conf_files/gnb.nsa.band78.106prb.usrpb200.conf @@ -78,9 +78,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 5; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/ci-scripts/conf_files/gnb.nsa.band78.106prb.usrpn310.2x2.conf b/ci-scripts/conf_files/gnb.nsa.band78.106prb.usrpn310.2x2.conf index a7900e5e41..1637e89521 100644 --- a/ci-scripts/conf_files/gnb.nsa.band78.106prb.usrpn310.2x2.conf +++ b/ci-scripts/conf_files/gnb.nsa.band78.106prb.usrpn310.2x2.conf @@ -83,9 +83,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 5; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn-leo.conf b/ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn-leo.conf index d08d900098..4d674d34b4 100644 --- a/ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn-leo.conf +++ b/ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn-leo.conf @@ -85,9 +85,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; 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 7fbaac5f5b..fd8c3ec68c 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 @@ -84,9 +84,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/ci-scripts/conf_files/gnb.sa.band261.u3.32prb.rfsim.conf b/ci-scripts/conf_files/gnb.sa.band261.u3.32prb.rfsim.conf index d5b1695d5c..6471c7bd02 100644 --- a/ci-scripts/conf_files/gnb.sa.band261.u3.32prb.rfsim.conf +++ b/ci-scripts/conf_files/gnb.sa.band261.u3.32prb.rfsim.conf @@ -82,9 +82,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 5; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/ci-scripts/conf_files/gnb.sa.band66.106prb.rfsim.conf b/ci-scripts/conf_files/gnb.sa.band66.106prb.rfsim.conf index 6c8ee24c1b..95384a0ae1 100644 --- a/ci-scripts/conf_files/gnb.sa.band66.106prb.rfsim.conf +++ b/ci-scripts/conf_files/gnb.sa.band66.106prb.rfsim.conf @@ -81,9 +81,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/ci-scripts/conf_files/gnb.sa.band77.162prb.usrpn310.2x2.conf b/ci-scripts/conf_files/gnb.sa.band77.162prb.usrpn310.2x2.conf index b0647e8e5f..23a8b34c3a 100644 --- a/ci-scripts/conf_files/gnb.sa.band77.162prb.usrpn310.2x2.conf +++ b/ci-scripts/conf_files/gnb.sa.band77.162prb.usrpn310.2x2.conf @@ -86,9 +86,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/ci-scripts/conf_files/gnb.sa.band77.273prb.fhi72.4x4-vvdn.conf b/ci-scripts/conf_files/gnb.sa.band77.273prb.fhi72.4x4-vvdn.conf index 74ab33a28d..b066c27810 100644 --- a/ci-scripts/conf_files/gnb.sa.band77.273prb.fhi72.4x4-vvdn.conf +++ b/ci-scripts/conf_files/gnb.sa.band77.273prb.fhi72.4x4-vvdn.conf @@ -84,9 +84,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 2; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 5; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/ci-scripts/conf_files/gnb.sa.band77.273prb.fhi72.4x4.2L-metanoia.conf b/ci-scripts/conf_files/gnb.sa.band77.273prb.fhi72.4x4.2L-metanoia.conf index 4e7042c2e4..b1da98b85b 100644 --- a/ci-scripts/conf_files/gnb.sa.band77.273prb.fhi72.4x4.2L-metanoia.conf +++ b/ci-scripts/conf_files/gnb.sa.band77.273prb.fhi72.4x4.2L-metanoia.conf @@ -79,9 +79,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 5; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/ci-scripts/conf_files/gnb.sa.band77.273prb.usrpn310.2x2.conf b/ci-scripts/conf_files/gnb.sa.band77.273prb.usrpn310.2x2.conf index 5567d233d4..3c51a977d8 100644 --- a/ci-scripts/conf_files/gnb.sa.band77.273prb.usrpn310.2x2.conf +++ b/ci-scripts/conf_files/gnb.sa.band77.273prb.usrpn310.2x2.conf @@ -86,9 +86,6 @@ gNBs = ( # powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; - # ra_ReponseWindow - # 1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; # ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR # 1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf b/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf index 396d83cd9d..7b0d176b3d 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf @@ -84,9 +84,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.conf b/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.conf index 9627a48d87..c297e40311 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.conf @@ -86,9 +86,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 5; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.flexric.conf b/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.flexric.conf index 12a86c3e64..c54af1a4bb 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.flexric.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.flexric.conf @@ -80,9 +80,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; - #ra_ReponseWindow - #1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.neighbour.conf b/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.neighbour.conf index e4f7d91900..0808c4b43d 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.neighbour.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.neighbour.conf @@ -82,9 +82,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.yaml b/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.yaml index 7b75481634..6240b62104 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.yaml +++ b/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.yaml @@ -72,9 +72,6 @@ gNBs: #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep: 1 - #ra_ReponseWindow - #1,2,4,8,10,20,40,80 - ra_ResponseWindow: 5 #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR: 4 diff --git a/ci-scripts/conf_files/gnb.sa.band78.106prb.usrp310.2x2.conf b/ci-scripts/conf_files/gnb.sa.band78.106prb.usrp310.2x2.conf index 4f546e7f30..263a8444ba 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.106prb.usrp310.2x2.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.106prb.usrp310.2x2.conf @@ -85,9 +85,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/ci-scripts/conf_files/gnb.sa.band78.106prb.usrpb200.sc-fdma.conf b/ci-scripts/conf_files/gnb.sa.band78.106prb.usrpb200.sc-fdma.conf index ba06b69dd2..ee59af2d80 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.106prb.usrpb200.sc-fdma.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.106prb.usrpb200.sc-fdma.conf @@ -78,9 +78,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/ci-scripts/conf_files/gnb.sa.band78.106prb.usrpn310.ddsuu-2x2.conf b/ci-scripts/conf_files/gnb.sa.band78.106prb.usrpn310.ddsuu-2x2.conf index 05e6c5c67d..59142efec8 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.106prb.usrpn310.ddsuu-2x2.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.106prb.usrpn310.ddsuu-2x2.conf @@ -98,9 +98,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/ci-scripts/conf_files/gnb.sa.band78.162prb.usrpn310.2x2.conf b/ci-scripts/conf_files/gnb.sa.band78.162prb.usrpn310.2x2.conf index aa7e011ef2..74e3f6e45f 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.162prb.usrpn310.2x2.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.162prb.usrpn310.2x2.conf @@ -99,9 +99,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/ci-scripts/conf_files/gnb.sa.band78.24prb.rfsim.conf b/ci-scripts/conf_files/gnb.sa.band78.24prb.rfsim.conf index e6baa257bc..4a3d2852c4 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.24prb.rfsim.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.24prb.rfsim.conf @@ -80,9 +80,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 5; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/ci-scripts/conf_files/gnb.sa.band78.273prb.fhi72.4x4-benetel550.conf b/ci-scripts/conf_files/gnb.sa.band78.273prb.fhi72.4x4-benetel550.conf index 6a3c31e71a..8d6a0e90cd 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.273prb.fhi72.4x4-benetel550.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.273prb.fhi72.4x4-benetel550.conf @@ -87,9 +87,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 5; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/ci-scripts/conf_files/gnb.sa.band78.273prb.rfsim.2x2.conf b/ci-scripts/conf_files/gnb.sa.band78.273prb.rfsim.2x2.conf index a9ef28fa5b..cd949fe8d0 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.273prb.rfsim.2x2.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.273prb.rfsim.2x2.conf @@ -83,9 +83,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 5; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/ci-scripts/conf_files/gnb.sa.band78.51prb.aw2s.ddsuu.2x2.conf b/ci-scripts/conf_files/gnb.sa.band78.51prb.aw2s.ddsuu.2x2.conf index fc90aa6a88..4a0fa03c60 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.51prb.aw2s.ddsuu.2x2.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.51prb.aw2s.ddsuu.2x2.conf @@ -87,9 +87,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/ci-scripts/conf_files/gnb.sa.band78.51prb.aw2s.ddsuu.conf b/ci-scripts/conf_files/gnb.sa.band78.51prb.aw2s.ddsuu.conf index 3bfe9ede51..4b46b8ca33 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.51prb.aw2s.ddsuu.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.51prb.aw2s.ddsuu.conf @@ -87,9 +87,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/ci-scripts/conf_files/gnb.sa.band78.51prb.usrpb200.conf b/ci-scripts/conf_files/gnb.sa.band78.51prb.usrpb200.conf index 83495e1c5d..0057d9b75f 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.51prb.usrpb200.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.51prb.usrpb200.conf @@ -78,9 +78,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/ci-scripts/conf_files/untested/benetel-5g.conf b/ci-scripts/conf_files/untested/benetel-5g.conf index 9bd8ed126e..35eda8f6d6 100644 --- a/ci-scripts/conf_files/untested/benetel-5g.conf +++ b/ci-scripts/conf_files/untested/benetel-5g.conf @@ -83,9 +83,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 2; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 5; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/ci-scripts/conf_files/untested/episci/episci_rcc.band78.tm1.106PRB.nfapi.conf b/ci-scripts/conf_files/untested/episci/episci_rcc.band78.tm1.106PRB.nfapi.conf index ae1b335a27..73e7ad0151 100644 --- a/ci-scripts/conf_files/untested/episci/episci_rcc.band78.tm1.106PRB.nfapi.conf +++ b/ci-scripts/conf_files/untested/episci/episci_rcc.band78.tm1.106PRB.nfapi.conf @@ -83,9 +83,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 5; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/ci-scripts/conf_files/untested/episci/gnb_band78.sa.fr1.106PRB.2x2.l2sim.conf b/ci-scripts/conf_files/untested/episci/gnb_band78.sa.fr1.106PRB.2x2.l2sim.conf index 27358d99af..dda8cc11c4 100644 --- a/ci-scripts/conf_files/untested/episci/gnb_band78.sa.fr1.106PRB.2x2.l2sim.conf +++ b/ci-scripts/conf_files/untested/episci/gnb_band78.sa.fr1.106PRB.2x2.l2sim.conf @@ -82,9 +82,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/ci-scripts/conf_files/untested/episci/proxy_rcc.band78.tm1.106PRB.nfapi.conf b/ci-scripts/conf_files/untested/episci/proxy_rcc.band78.tm1.106PRB.nfapi.conf index 978b8e22ec..9ca5210ec6 100644 --- a/ci-scripts/conf_files/untested/episci/proxy_rcc.band78.tm1.106PRB.nfapi.conf +++ b/ci-scripts/conf_files/untested/episci/proxy_rcc.band78.tm1.106PRB.nfapi.conf @@ -83,9 +83,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/ci-scripts/conf_files/untested/gNB_SA_n78_106PRB.2x2_usrpn310.conf b/ci-scripts/conf_files/untested/gNB_SA_n78_106PRB.2x2_usrpn310.conf index 43e11c6c40..e442987316 100644 --- a/ci-scripts/conf_files/untested/gNB_SA_n78_106PRB.2x2_usrpn310.conf +++ b/ci-scripts/conf_files/untested/gNB_SA_n78_106PRB.2x2_usrpn310.conf @@ -98,9 +98,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 3; diff --git a/ci-scripts/conf_files/untested/gNB_SA_n78_133PRB.2x2_usrpn310.conf b/ci-scripts/conf_files/untested/gNB_SA_n78_133PRB.2x2_usrpn310.conf index 4e8c55851e..9a9732f807 100644 --- a/ci-scripts/conf_files/untested/gNB_SA_n78_133PRB.2x2_usrpn310.conf +++ b/ci-scripts/conf_files/untested/gNB_SA_n78_133PRB.2x2_usrpn310.conf @@ -94,9 +94,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 3; diff --git a/ci-scripts/conf_files/untested/gnb.band78.sa.fr1.106PRB.usrpn310.conf b/ci-scripts/conf_files/untested/gnb.band78.sa.fr1.106PRB.usrpn310.conf index 4ffcf8fa3a..b1b94da121 100644 --- a/ci-scripts/conf_files/untested/gnb.band78.sa.fr1.106PRB.usrpn310.conf +++ b/ci-scripts/conf_files/untested/gnb.band78.sa.fr1.106PRB.usrpn310.conf @@ -103,9 +103,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 3; diff --git a/ci-scripts/conf_files/untested/gnb.band78.tm1.fr1.106PRB.usrpb210.conf b/ci-scripts/conf_files/untested/gnb.band78.tm1.fr1.106PRB.usrpb210.conf index dfd0996a05..b9c29636be 100644 --- a/ci-scripts/conf_files/untested/gnb.band78.tm1.fr1.106PRB.usrpb210.conf +++ b/ci-scripts/conf_files/untested/gnb.band78.tm1.fr1.106PRB.usrpb210.conf @@ -77,9 +77,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 5; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/ci-scripts/conf_files/untested/gnb.band78.tm1.fr1.106PRB.usrpn310.conf b/ci-scripts/conf_files/untested/gnb.band78.tm1.fr1.106PRB.usrpn310.conf index a8a45e8a68..6a63b00e6f 100644 --- a/ci-scripts/conf_files/untested/gnb.band78.tm1.fr1.106PRB.usrpn310.conf +++ b/ci-scripts/conf_files/untested/gnb.band78.tm1.fr1.106PRB.usrpn310.conf @@ -82,9 +82,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 5; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/ci-scripts/conf_files/untested/gnb.sa.band66.fr1.106PRB.usrpn300.conf b/ci-scripts/conf_files/untested/gnb.sa.band66.fr1.106PRB.usrpn300.conf index 29cc65e17b..18228fde1d 100644 --- a/ci-scripts/conf_files/untested/gnb.sa.band66.fr1.106PRB.usrpn300.conf +++ b/ci-scripts/conf_files/untested/gnb.sa.band66.fr1.106PRB.usrpn300.conf @@ -81,9 +81,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/ci-scripts/conf_files/untested/gnb.sa.band78.fr1.51PRB.usrpb210.conf b/ci-scripts/conf_files/untested/gnb.sa.band78.fr1.51PRB.usrpb210.conf index 85bc18fa17..62f5c042be 100644 --- a/ci-scripts/conf_files/untested/gnb.sa.band78.fr1.51PRB.usrpb210.conf +++ b/ci-scripts/conf_files/untested/gnb.sa.band78.fr1.51PRB.usrpb210.conf @@ -80,9 +80,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/ci-scripts/conf_files/untested/proxy_gnb.band78.sa.fr1.106PRB.usrpn310.conf b/ci-scripts/conf_files/untested/proxy_gnb.band78.sa.fr1.106PRB.usrpn310.conf index 0ff2cfa2e2..dd4a55c6a7 100644 --- a/ci-scripts/conf_files/untested/proxy_gnb.band78.sa.fr1.106PRB.usrpn310.conf +++ b/ci-scripts/conf_files/untested/proxy_gnb.band78.sa.fr1.106PRB.usrpn310.conf @@ -79,9 +79,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/doc/nfapi.md b/doc/nfapi.md index 41a3770be4..73aaf2e770 100644 --- a/doc/nfapi.md +++ b/doc/nfapi.md @@ -95,8 +95,9 @@ can proceed as follows: - in `vnf.conf` * modify `MACRLCs` section to configure south-bound nFAPI transport * delete `L1s`, `RUs`, and radio-specific sections. - * in `gNBs` section, increase the `ra_ResponseWindow` by one to extend the RA - window: this is necessary because the PNF triggers the scheduler in the VNF + * in `gNBs` section, select a sufficiently large `ra_ResponseWindow` if a UE + does not connect with a message that the response window timed out: + this is necessary because the PNF triggers the scheduler in the VNF in advance, which might make the RA window more likely to run out - copy `monolithic.conf`, which will be your PNF file (`pnf.conf`) - in `pnf.conf` diff --git a/doc/testing_gnb_w_cots_ue_resources/gnb.conf b/doc/testing_gnb_w_cots_ue_resources/gnb.conf index 44d339c951..c9cc393abc 100755 --- a/doc/testing_gnb_w_cots_ue_resources/gnb.conf +++ b/doc/testing_gnb_w_cots_ue_resources/gnb.conf @@ -82,9 +82,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 5; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/benetel-5g.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/benetel-5g.conf index ef39165e42..de96c77bcb 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/benetel-5g.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/benetel-5g.conf @@ -85,9 +85,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 2; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 5; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band257.tm1.32PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band257.tm1.32PRB.usrpn300.conf index f44a412b3c..12f56ca617 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band257.tm1.32PRB.usrpn300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band257.tm1.32PRB.usrpn300.conf @@ -82,9 +82,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 7; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band257.tm1.32PRB.usrpx300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band257.tm1.32PRB.usrpx300.conf index 3c0feb2ddc..0a8c5f802e 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band257.tm1.32PRB.usrpx300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band257.tm1.32PRB.usrpx300.conf @@ -82,9 +82,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 7; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band257.tm1.66PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band257.tm1.66PRB.usrpn300.conf index fa2dca082f..a77a65ab0a 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band257.tm1.66PRB.usrpn300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band257.tm1.66PRB.usrpn300.conf @@ -81,9 +81,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band261.tm1.32PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band261.tm1.32PRB.usrpn300.conf index 8ded185653..565e83c6a8 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band261.tm1.32PRB.usrpn300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band261.tm1.32PRB.usrpn300.conf @@ -82,9 +82,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 7; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.106PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.106PRB.usrpn300.conf index 260c844b25..8de8f20cfb 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.106PRB.usrpn300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.106PRB.usrpn300.conf @@ -83,9 +83,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.106PRB.usrpx300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.106PRB.usrpx300.conf index 67ea04255c..07c0f76f6e 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.106PRB.usrpx300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.106PRB.usrpx300.conf @@ -84,9 +84,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.24PRB.usrpx300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.24PRB.usrpx300.conf index ea1e70fa87..d794e222cb 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.24PRB.usrpx300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.24PRB.usrpx300.conf @@ -84,9 +84,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.25PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.25PRB.usrpn300.conf index 58adeb991e..e83011d03a 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.25PRB.usrpn300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.25PRB.usrpn300.conf @@ -84,9 +84,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.25PRB.usrpx300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.25PRB.usrpx300.conf index 227f06bd8b..10812dc846 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.25PRB.usrpx300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.25PRB.usrpx300.conf @@ -84,9 +84,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.106PRB.30kHz,usrpb2x0.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.106PRB.30kHz,usrpb2x0.conf index d863f36409..ddd31a810e 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.106PRB.30kHz,usrpb2x0.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.106PRB.30kHz,usrpb2x0.conf @@ -82,9 +82,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 5; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.106PRB.slave.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.106PRB.slave.conf index 0dcd0b95e4..77863ab39a 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.106PRB.slave.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.106PRB.slave.conf @@ -82,9 +82,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.slave.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.slave.conf index ef95a53a7d..ffc7b1b21c 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.slave.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.slave.conf @@ -81,9 +81,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.PTRS.usrpx300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.PTRS.usrpx300.conf index 554b886010..58bcdc1d37 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.PTRS.usrpx300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.PTRS.usrpx300.conf @@ -81,9 +81,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; - #ra_ReponseWindow - #1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpb210.conf index b3d3775208..e6805d7a92 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpb210.conf @@ -81,9 +81,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf index dd9b571b33..1a31985d8b 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf @@ -81,9 +81,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpx300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpx300.conf index 49108d242b..c0786bd56a 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpx300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpx300.conf @@ -81,9 +81,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpn300.conf index 1246e44b2b..82973bef95 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpn300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpn300.conf @@ -81,9 +81,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpx300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpx300.conf index e4f2fb8699..bcd16eda2a 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpx300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpx300.conf @@ -82,9 +82,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpb210.conf index 7dfbb5ee95..295a7ab6f1 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpb210.conf @@ -82,9 +82,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpn300.conf index ad610601a0..27a0fc0a84 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpn300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpn300.conf @@ -82,9 +82,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpx300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpx300.conf index 8107c5ffc6..f681e5723a 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpx300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpx300.conf @@ -82,9 +82,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.273PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.273PRB.usrpn300.conf index 167ad9b802..4054d851c2 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.273PRB.usrpn300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.273PRB.usrpn300.conf @@ -82,9 +82,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/du_gnb.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/du_gnb.conf index 02b1e89b88..ee35c48e89 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/du_gnb.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/du_gnb.conf @@ -84,9 +84,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band66.25prb.rfsim.pci0.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band66.25prb.rfsim.pci0.conf index c2e28725bd..9d6787d6b1 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band66.25prb.rfsim.pci0.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band66.25prb.rfsim.pci0.conf @@ -83,9 +83,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band66.25prb.rfsim.pci1.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band66.25prb.rfsim.pci1.conf index c5c84c9919..87d7fdbc4a 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band66.25prb.rfsim.pci1.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band66.25prb.rfsim.pci1.conf @@ -83,9 +83,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.4x4-benetel650.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.4x4-benetel650.conf index a267d2e864..f0de3e3ab1 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.4x4-benetel650.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.4x4-benetel650.conf @@ -88,9 +88,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 3; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 5; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650-mplane.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650-mplane.conf index 28f9baf6f8..2fc9481739 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650-mplane.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650-mplane.conf @@ -88,9 +88,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 3; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 5; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650.conf index 18f885945f..7b78314f8d 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650.conf @@ -88,9 +88,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 3; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 5; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band78.106prb.rfsim.pci0.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band78.106prb.rfsim.pci0.conf index 3221813bef..5f03792795 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band78.106prb.rfsim.pci0.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band78.106prb.rfsim.pci0.conf @@ -80,9 +80,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band78.106prb.rfsim.pci1.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band78.106prb.rfsim.pci1.conf index c7d8cb3269..a69417fa45 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band78.106prb.rfsim.pci1.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band78.106prb.rfsim.pci1.conf @@ -80,9 +80,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-vnf.sa.band78.106prb.nfapi.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-vnf.sa.band78.106prb.nfapi.conf index bb4aed3dfe..aea3176456 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-vnf.sa.band78.106prb.nfapi.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-vnf.sa.band78.106prb.nfapi.conf @@ -84,9 +84,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 5; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-vnf.sa.band78.273prb.aerial.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-vnf.sa.band78.273prb.aerial.conf index aa7c380e51..7b88ad23c4 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-vnf.sa.band78.273prb.aerial.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-vnf.sa.band78.273prb.aerial.conf @@ -105,9 +105,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 5; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-vnf.sa.band78.273prb.nfapi.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-vnf.sa.band78.273prb.nfapi.conf index 7cfc66748b..b5a124cf1a 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-vnf.sa.band78.273prb.nfapi.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-vnf.sa.band78.273prb.nfapi.conf @@ -83,9 +83,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 5; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 3; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-vnf.sa.cbrs.aerial.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-vnf.sa.cbrs.aerial.conf index 5f2293cfb9..e104f82131 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-vnf.sa.cbrs.aerial.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-vnf.sa.cbrs.aerial.conf @@ -87,9 +87,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 5; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.band78.sa.fr1.106PRB.2x2.usrpn310.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.band78.sa.fr1.106PRB.2x2.usrpn310.conf index b958ed809d..d9eb5e9fa7 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.band78.sa.fr1.106PRB.2x2.usrpn310.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.band78.sa.fr1.106PRB.2x2.usrpn310.conf @@ -114,9 +114,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.band78.sa.fr1.162PRB.2x2.usrpn310.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.band78.sa.fr1.162PRB.2x2.usrpn310.conf index a7010921bb..15c9684706 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.band78.sa.fr1.162PRB.2x2.usrpn310.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.band78.sa.fr1.162PRB.2x2.usrpn310.conf @@ -118,9 +118,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band1.u0.52PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band1.u0.52PRB.usrpb210.conf index e270dd690d..f30c2d445f 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band1.u0.52PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band1.u0.52PRB.usrpb210.conf @@ -81,9 +81,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band254.ntn.mu1.24prb.rfsim.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band254.ntn.mu1.24prb.rfsim.conf index dd3307d32c..a6ca5decbe 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band254.ntn.mu1.24prb.rfsim.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band254.ntn.mu1.24prb.rfsim.conf @@ -84,9 +84,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band255.ntn.mu0.25prb.rfsim.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band255.ntn.mu0.25prb.rfsim.conf index 7c2c3805ee..c811f0d64e 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band255.ntn.mu0.25prb.rfsim.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band255.ntn.mu0.25prb.rfsim.conf @@ -83,9 +83,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band256.ntn.mu0.25prb.rfsim.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band256.ntn.mu0.25prb.rfsim.conf index b720d6d720..3a472ff7a2 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band256.ntn.mu0.25prb.rfsim.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band256.ntn.mu0.25prb.rfsim.conf @@ -83,9 +83,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band257.u3.32prb.usrpx410.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band257.u3.32prb.usrpx410.conf index 667b15b10f..933cddfcb9 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band257.u3.32prb.usrpx410.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band257.u3.32prb.usrpx410.conf @@ -84,9 +84,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 5; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band41.fr1.106PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band41.fr1.106PRB.usrpb210.conf index a5e9841772..42ac3185f0 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band41.fr1.106PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band41.fr1.106PRB.usrpb210.conf @@ -79,9 +79,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band41.fr1.52PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band41.fr1.52PRB.usrpb210.conf index b72ca5dc32..a02394b5b2 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band41.fr1.52PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band41.fr1.52PRB.usrpb210.conf @@ -85,9 +85,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.106PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.106PRB.usrpn300.conf index 1d9693edb1..6b460b0b59 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.106PRB.usrpn300.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.106PRB.usrpn300.conf @@ -80,9 +80,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.106PRB.usrpx300.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.106PRB.usrpx300.conf index b666616764..afd7e6d96f 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.106PRB.usrpx300.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.106PRB.usrpx300.conf @@ -96,9 +96,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.24PRB.usrpx300.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.24PRB.usrpx300.conf index 013ca6663b..6b9b104bc0 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.24PRB.usrpx300.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.24PRB.usrpx300.conf @@ -100,9 +100,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.25PRB.usrpx300.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.25PRB.usrpx300.conf index c9dfd6c58a..560b33b0e9 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.25PRB.usrpx300.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.25PRB.usrpx300.conf @@ -100,9 +100,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.u0.25prb.rfsim.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.u0.25prb.rfsim.conf index f51bb977e0..9458c2b272 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.u0.25prb.rfsim.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.u0.25prb.rfsim.conf @@ -82,9 +82,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.106prb.fhi72.4x4-vvdn.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.106prb.fhi72.4x4-vvdn.conf index 7622e508bc..753670a9eb 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.106prb.fhi72.4x4-vvdn.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.106prb.fhi72.4x4-vvdn.conf @@ -86,9 +86,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 2; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 5; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.162prb.usrpn310.4x4.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.162prb.usrpn310.4x4.conf index ba427f747e..1890e60516 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.162prb.usrpn310.4x4.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.162prb.usrpn310.4x4.conf @@ -88,9 +88,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.273prb.fhi72.2x2-vvdn.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.273prb.fhi72.2x2-vvdn.conf index ce2a75d529..38580730f2 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.273prb.fhi72.2x2-vvdn.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.273prb.fhi72.2x2-vvdn.conf @@ -84,9 +84,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 2; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 5; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.273prb.fhi72.4x4-vvdn.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.273prb.fhi72.4x4-vvdn.conf index 55a78fd901..d55bc6dbda 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.273prb.fhi72.4x4-vvdn.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.273prb.fhi72.4x4-vvdn.conf @@ -86,9 +86,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 2; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 5; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.fr1.273PRB.2x2.usrpn300.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.fr1.273PRB.2x2.usrpn300.conf index f4c31e3ee7..5bfce9a2d9 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.fr1.273PRB.2x2.usrpn300.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.fr1.273PRB.2x2.usrpn300.conf @@ -85,9 +85,6 @@ gNBs = ( # powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; - # ra_ReponseWindow - # 1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; # ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR # 1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.fr1.273PRB.usrpx300.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.fr1.273PRB.usrpx300.conf index fcda4d3cc0..f6e571078e 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.fr1.273PRB.usrpx300.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.fr1.273PRB.usrpx300.conf @@ -85,9 +85,6 @@ gNBs = ( # powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; - # ra_ReponseWindow - # 1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; # ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR # 1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.106PRB.usrpb210.RA_2-Step.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.106PRB.usrpb210.RA_2-Step.conf index 8c419177d5..3dc33707f3 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.106PRB.usrpb210.RA_2-Step.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.106PRB.usrpb210.RA_2-Step.conf @@ -80,9 +80,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x2-benetel550.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x2-benetel550.conf index b66012c619..75fe0e6fdd 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x2-benetel550.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x2-benetel550.conf @@ -85,9 +85,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 3; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 5; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-benetel550-mplane.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-benetel550-mplane.conf index 6fa4c200dc..be35562fd7 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-benetel550-mplane.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-benetel550-mplane.conf @@ -87,9 +87,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 3; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 5; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-benetel550.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-benetel550.conf index 3d584fdaba..d8ca02a3be 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-benetel550.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-benetel550.conf @@ -87,9 +87,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 3; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 5; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-foxconn.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-foxconn.conf index bd4cd59f06..38f399c67f 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-foxconn.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-foxconn.conf @@ -85,9 +85,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 5; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 3; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-liteon.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-liteon.conf index 43f6f9cef8..3c9780130f 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-liteon.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-liteon.conf @@ -86,9 +86,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 2; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 5; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-metanoia.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-metanoia.conf index b6c940c78b..13617fb578 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-metanoia.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-metanoia.conf @@ -82,9 +82,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 5; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.2x2.usrpn300.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.2x2.usrpn300.conf index b4aa830dd5..ddf866b0fd 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.2x2.usrpn300.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.2x2.usrpn300.conf @@ -82,9 +82,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.2pattern.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.2pattern.conf index 89a1bb23c6..e29998478e 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.2pattern.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.2pattern.conf @@ -78,9 +78,6 @@ gNBs = # powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; - # ra_ReponseWindow - # 1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; # ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR # 1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.4layer.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.4layer.conf index d2f9dc0005..641c2228a4 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.4layer.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.4layer.conf @@ -81,9 +81,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf index 7f7054db31..7f750d7259 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf @@ -81,9 +81,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.redcap.yaml b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.redcap.yaml index 01c40ca3d7..605b56be93 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.redcap.yaml +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.redcap.yaml @@ -76,9 +76,6 @@ gNBs: #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep: 1 - #ra_ReponseWindow - #1,2,4,8,10,20,40,80 - ra_ResponseWindow: 5 #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR: 4 diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.sabox.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.sabox.conf index 46964ad72d..373ea830e0 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.sabox.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.sabox.conf @@ -80,9 +80,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.yaml b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.yaml index 87ad6080a0..8608ccd290 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.yaml +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.yaml @@ -76,9 +76,6 @@ gNBs: #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep: 1 - #ra_ReponseWindow - #1,2,4,8,10,20,40,80 - ra_ResponseWindow: 4 #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR: 4 diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.162PRB.2x2.usrpn300.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.162PRB.2x2.usrpn300.conf index 129b687c1a..30e95f83ec 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.162PRB.2x2.usrpn300.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.162PRB.2x2.usrpn300.conf @@ -83,9 +83,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.189PRB.rfsim.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.189PRB.rfsim.conf index 5270587271..22047cf06c 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.189PRB.rfsim.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.189PRB.rfsim.conf @@ -86,9 +86,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 5; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.217PRB.2x2.usrpn300.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.217PRB.2x2.usrpn300.conf index 9802cc0acd..09117464b0 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.217PRB.2x2.usrpn300.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.217PRB.2x2.usrpn300.conf @@ -82,9 +82,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.24PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.24PRB.usrpb210.conf index d3852e236a..1398020417 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.24PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.24PRB.usrpb210.conf @@ -80,9 +80,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 5; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb0.prs.band261.fr2.64PRB.usrpx310.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb0.prs.band261.fr2.64PRB.usrpx310.conf index fbc77bf957..c51a969208 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb0.prs.band261.fr2.64PRB.usrpx310.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb0.prs.band261.fr2.64PRB.usrpx310.conf @@ -83,9 +83,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 7; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; #one (0..15) 4,8,12,16,...60,64 diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb0.prs.band78.fr1.106PRB.usrpx310.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb0.prs.band78.fr1.106PRB.usrpx310.conf index f0ea334f7e..d64bd8e472 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb0.prs.band78.fr1.106PRB.usrpx310.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb0.prs.band78.fr1.106PRB.usrpx310.conf @@ -118,9 +118,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb1.prs.band261.fr2.64PRB.usrpx310.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb1.prs.band261.fr2.64PRB.usrpx310.conf index 143345f275..f04fcc8efc 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb1.prs.band261.fr2.64PRB.usrpx310.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb1.prs.band261.fr2.64PRB.usrpx310.conf @@ -83,9 +83,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 7; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb1.prs.band78.fr1.106PRB.usrpx310.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb1.prs.band78.fr1.106PRB.usrpx310.conf index c8c1582584..bc8af31818 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb1.prs.band78.fr1.106PRB.usrpx310.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb1.prs.band78.fr1.106PRB.usrpx310.conf @@ -117,9 +117,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 1; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; From 961a646dc756cba52c5c299e4f77563e89fcbec8 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 8 Jul 2025 11:54:38 +0200 Subject: [PATCH 340/964] Remove dedicated Msg3 TDA MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A dedicated Msg3 TDA is simply not necessary: get_feasible_msg3_tda() already iterates through all TDAs to find a suitable one for Msg3, and takes things such as parameter Δ already into account. The only prerequisite is that the ra_ResponseWindow is long enough. In some configurations, Msg3 TDA ensured that Msg2 still happened during ra_ResponseWindow, while Msg3 was outside of it. This is not necessarily the case anymore, unless ra_ResponseWindow is long enough. For the normal user, removing ra_ResponseWindow from the config will be enough. --- openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c index 6e111ded06..d780cf4fe7 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c @@ -1066,8 +1066,6 @@ void nr_rrc_config_ul_tda(NR_ServingCellConfigCommon_t *scc, int min_fb_delay) const int k2 = min_fb_delay; - int mu = scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing; - // UL TDA index 0 is basic slot configuration starting in symbol 0 til the last but one symbol NR_PUSCH_TimeDomainResourceAllocation_t *tda; tda = set_TimeDomainResourceAllocation(k2, get_SLIV(0, 13)); @@ -1097,20 +1095,6 @@ void nr_rrc_config_ul_tda(NR_ServingCellConfigCommon_t *scc, int min_fb_delay) tda = set_TimeDomainResourceAllocation(k2, sliv); asn1cSeqAdd(&tda_list->list, tda); } - // UL TDA index 3 for msg3 in the mixed slot (TDD) - int tdd_period_idx = get_tdd_period_idx(scc->tdd_UL_DL_ConfigurationCommon); - int nb_periods_per_frame = get_nb_periods_per_frame(tdd_period_idx); - int nb_slots_per_period = ((1 << mu) * 10) / nb_periods_per_frame; - int k2_msg3 = nb_slots_per_period - get_delta_for_k2(mu); - bool no_mix_slot = ul_symb < 3; // we need at least 2 symbols for scheduling Msg3 - long sliv = no_mix_slot ? get_SLIV(0, 13) : get_SLIV(NR_NUMBER_OF_SYMBOLS_PER_SLOT - ul_symb, ul_symb - 1); - struct NR_PUSCH_TimeDomainResourceAllocation *puschTdrAllocMsg3 = set_TimeDomainResourceAllocation(k2_msg3, sliv); - if (*puschTdrAllocMsg3->k2 < min_fb_delay) - *puschTdrAllocMsg3->k2 += nb_slots_per_period; - AssertFatal(*puschTdrAllocMsg3->k2 < 33, - "Computed k2 for msg3 %ld is larger than the range allowed by RRC (0..32)\n", - *puschTdrAllocMsg3->k2); - asn1cSeqAdd(&tda_list->list, puschTdrAllocMsg3); } } From 66023f6a8d25ce71bb7b6fcb3f80c3b05bc7f0e5 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 7 Jul 2025 18:44:41 +0200 Subject: [PATCH 341/964] Refactor get_feasible_msg3_tda() Simplify the code. Consider any slot for Msg3, and check that the TDA fits in a given slot (as before). --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 55856c0738..37a1460b1c 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -1013,18 +1013,10 @@ static bool get_feasible_msg3_tda(const NR_ServingCellConfigCommon_t *scc, if (fs->frame_type == TDD && !is_ul_slot(temp_slot, fs)) continue; - const tdd_bitmap_t *tdd_slot_bitmap = fs->period_cfg.tdd_slot_bitmap; int s = get_slot_idx_in_period(temp_slot, fs); - // check if enough symbols in case of mixed slot + const tdd_bitmap_t *bm = &fs->period_cfg.tdd_slot_bitmap[s]; bool is_mixed = is_mixed_slot(s, fs); - // if the mixed slot has not enough symbols, skip - if (is_mixed && tdd_slot_bitmap[s].num_ul_symbols < 3) - continue; - - uint16_t slot_mask = - is_mixed ? SL_to_bitmap(NR_NUMBER_OF_SYMBOLS_PER_SLOT - tdd_slot_bitmap[s].num_ul_symbols, - tdd_slot_bitmap[s].num_ul_symbols) - : 0x3fff; + uint16_t slot_mask = is_mixed ? SL_to_bitmap(NR_NUMBER_OF_SYMBOLS_PER_SLOT - bm->num_ul_symbols, bm->num_ul_symbols) : 0x3fff; long startSymbolAndLength = tda_list->list.array[i]->startSymbolAndLength; int start, nr; SLIV2SL(startSymbolAndLength, &start, &nr); From 626fce4f44d52229c8b9c2e2caa879ca34daefd1 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 1 Jul 2025 12:25:42 +0200 Subject: [PATCH 342/964] config_frame_structure(): make const --- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h | 2 +- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common_tdd.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h index 3770d2c6ec..ff6775df96 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h @@ -76,7 +76,7 @@ bool is_dl_slot(const slot_t slot, const frame_structure_t *fs); bool is_mixed_slot(const slot_t slot, const frame_structure_t *fs); int get_tdd_period_idx(NR_TDD_UL_DL_ConfigCommon_t *tdd); void config_frame_structure(int mu, - NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon, + const NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon, uint8_t tdd_period, uint8_t frame_type, frame_structure_t *fs); diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common_tdd.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common_tdd.c index 8720cbce8b..b9f41a64a3 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common_tdd.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common_tdd.c @@ -98,7 +98,7 @@ int get_tdd_period_idx(NR_TDD_UL_DL_ConfigCommon_t *tdd) * * @return Number of slots in the configured TDD period */ -static uint8_t set_tdd_bmap_period(NR_TDD_UL_DL_Pattern_t *pattern, tdd_period_config_t *pc, int8_t curr_total_slot) +static uint8_t set_tdd_bmap_period(const NR_TDD_UL_DL_Pattern_t *pattern, tdd_period_config_t *pc, int8_t curr_total_slot) { int8_t n_dl_slot = pattern->nrofDownlinkSlots; int8_t n_ul_slot = pattern->nrofUplinkSlots; @@ -154,7 +154,7 @@ static uint8_t set_tdd_bmap_period(NR_TDD_UL_DL_Pattern_t *pattern, tdd_period_c * * @return void */ -static void config_tdd_patterns(NR_TDD_UL_DL_ConfigCommon_t *tdd, frame_structure_t *fs) +static void config_tdd_patterns(const NR_TDD_UL_DL_ConfigCommon_t *tdd, frame_structure_t *fs) { int num_of_patterns = 1; uint8_t nb_slots_p2 = 0; @@ -188,7 +188,7 @@ static void config_tdd_patterns(NR_TDD_UL_DL_ConfigCommon_t *tdd, frame_structur * @param fs pointer to the frame structure to update */ void config_frame_structure(int mu, - NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon, + const NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon, uint8_t tdd_period, uint8_t frame_type, frame_structure_t *fs) From 53208bd163ab9aad4387a30597b1bb561a468b46 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Fri, 1 Aug 2025 13:39:28 +0200 Subject: [PATCH 343/964] NR UE: fix calculation of SI window expiry --- .../NR_MAC_UE/nr_ue_dci_configuration.c | 41 +++++++------------ 1 file changed, 14 insertions(+), 27 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c index 7a2e9c6ed9..4b0623d6fe 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c @@ -385,12 +385,14 @@ bool search_space_monitoring_ocasion_other_si(NR_UE_MAC_INST_t *mac, return false; } -bool is_window_valid(NR_UE_MAC_INST_t *mac, int window_slots, int abs_slot) +static bool is_window_valid(NR_UE_MAC_INST_t *mac, int window_slots, int abs_slot, int slots_per_frame) { if (mac->si_SchedInfo.si_window_start == -1) { // out of window return false; - } else if (abs_slot > mac->si_SchedInfo.si_window_start + window_slots) { + } else if ((abs_slot - mac->si_SchedInfo.si_window_start + MAX_FRAME_NUMBER * slots_per_frame) + % (MAX_FRAME_NUMBER * slots_per_frame) + >= window_slots) { // window expired mac->si_SchedInfo.si_window_start = -1; return false; @@ -407,33 +409,18 @@ static bool monitor_dci_for_other_SI(NR_UE_MAC_INST_t *mac, { // according to 5.2.2.3.2 in 331 const int abs_slot = frame * slots_per_frame + slot; + const si_schedinfo_config_t *config = mac->si_SchedInfo.si_SchedInfo_list.array[si_idx]; + const int window_slots = 5 << mac->si_SchedInfo.si_WindowLength; + const int x = (config->si_WindowPosition - 1) * window_slots; + const int T = 8 << config->si_Periodicity; // radio frame periodicity - si_schedinfo_config_t *config = mac->si_SchedInfo.si_SchedInfo_list.array[si_idx]; - int window_slots = 5 << mac->si_SchedInfo.si_WindowLength; - int x = (config->si_WindowPosition - 1) * window_slots; - int T = 8 << config->si_Periodicity; // radio frame periodicity - bool check_valid; - switch (config->type) { - case NR_SI_INFO : - if (mac->si_SchedInfo.si_window_start == -1) { - if ((frame % T) == (x / slots_per_frame) && (x % slots_per_frame == 0)) - mac->si_SchedInfo.si_window_start = abs_slot; // in terms of absolute slot number - } - check_valid = is_window_valid(mac, window_slots, abs_slot); - if (check_valid && search_space_monitoring_ocasion_other_si(mac, ss, abs_slot, frame, slot, slots_per_frame)) - return true; - break; - case NR_SI_INFO_v1700 : - if (mac->si_SchedInfo.si_window_start == -1) { - if ((frame % T == floor(x / slots_per_frame)) && (slot == x % slots_per_frame)) - mac->si_SchedInfo.si_window_start = abs_slot; - } - if (is_window_valid(mac, window_slots, abs_slot)) - return search_space_monitoring_ocasion_other_si(mac, ss, abs_slot, frame, slot, slots_per_frame); - break; - default : - AssertFatal(false, "Invalid SI-SchedulingInfo case\n"); + if (mac->si_SchedInfo.si_window_start == -1) { + if ((frame % T) == (x / slots_per_frame) && (slot == x % slots_per_frame)) + mac->si_SchedInfo.si_window_start = abs_slot; // in terms of absolute slot number } + if (is_window_valid(mac, window_slots, abs_slot, slots_per_frame)) + return search_space_monitoring_ocasion_other_si(mac, ss, abs_slot, frame, slot, slots_per_frame); + return false; } From d4f4cefd6bb15d4021b2dee0ca0d0999c3e110ff Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Fri, 25 Jul 2025 11:54:43 +0000 Subject: [PATCH 344/964] set ntn-UlSyncValidityDuration-r17 to 5 seconds for LEO scenario Now that we reliably receive SIB19, we can set the ntn-UlSyncValidityDuration-r17 to a sane value and thus make sure that the UE always has up-to-date SIB19 information. --- .../conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn-leo.conf | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn-leo.conf b/ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn-leo.conf index d08d900098..59438e8800 100644 --- a/ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn-leo.conf +++ b/ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn-leo.conf @@ -150,6 +150,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 = 5; cellSpecificKoffset_r17 = 40; ta-Common-r17 = 4627000; # 18.84 ms ta-CommonDrift-r17 = -230000; # -46 µs/s From 7827a40f19c2d1e19377e518decd6f39ce1ed526 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Fri, 25 Jul 2025 11:57:54 +0000 Subject: [PATCH 345/964] NTN config: setting sib1_tda is not required anymore --- ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn-leo.conf | 1 - ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn.conf | 1 - 2 files changed, 2 deletions(-) diff --git a/ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn-leo.conf b/ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn-leo.conf index 59438e8800..010e8be87e 100644 --- a/ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn-leo.conf +++ b/ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn-leo.conf @@ -16,7 +16,6 @@ gNBs = ////////// Physical parameters: - sib1_tda = 5; min_rxtxtime = 6; num_dlharq = 32; num_ulharq = 32; 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 7fbaac5f5b..bf3e6b295f 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 @@ -16,7 +16,6 @@ gNBs = ////////// Physical parameters: - sib1_tda = 5; min_rxtxtime = 6; disable_harq = 1; cu_sibs = [2]; From 16fd1bb67cd0e3b3adcc1232a08d6d1946034aff Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Fri, 25 Jul 2025 12:00:04 +0000 Subject: [PATCH 346/964] gNB: fix case when multiple Rel-17 SIBs would be defined The boolean value v17_sib was not set to true when allocating si_schedulingInfo_v17 and schedulingInfo2_r17. So multiple Rel-17 SIBs would lead to multiple allocations and only the last SIB being actually configured. Fix this by removing the redundant v17_sib variable and directly check if the memory was already allocated. Also move the definition and allocation of si_schedulingInfo_v17 closer to its actual usage. --- openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c index eba1152cd0..13e3014ca9 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c @@ -2418,9 +2418,7 @@ void update_SIB1_NR_SI(NR_BCCH_DL_SCH_Message_t *sib1_bcch, int num_sibs, int si schedulingInfo->si_BroadcastStatus = NR_SchedulingInfo__si_BroadcastStatus_broadcasting; schedulingInfo->si_Periodicity = NR_SchedulingInfo__si_Periodicity_rf16; bool reg_sib = false; - NR_SI_SchedulingInfo_v1700_t *si_schedulingInfo_v17 = NULL; NR_SchedulingInfo2_r17_t *schedulingInfo2_r17 = NULL; - bool v17_sib = false; for (int i = 0; i < num_sibs; i++) { int sib_num = sibs[i]; AssertFatal(sib_num > 1 && sib_num < 21, "other SIB invalid type\n"); @@ -2438,8 +2436,7 @@ void update_SIB1_NR_SI(NR_BCCH_DL_SCH_Message_t *sib1_bcch, int num_sibs, int si } asn1cSeqAdd(&schedulingInfo->sib_MappingInfo.list, mapping); } else { - if (v17_sib == false) { - si_schedulingInfo_v17 = calloc(1, sizeof(*si_schedulingInfo_v17)); + if (schedulingInfo2_r17 == NULL) { schedulingInfo2_r17 = calloc(1, sizeof(*schedulingInfo2_r17)); schedulingInfo2_r17->si_BroadcastStatus_r17 = NR_SchedulingInfo2_r17__si_BroadcastStatus_r17_broadcasting; schedulingInfo2_r17->si_Periodicity_r17 = NR_SchedulingInfo2_r17__si_Periodicity_r17_rf16; @@ -2458,7 +2455,8 @@ void update_SIB1_NR_SI(NR_BCCH_DL_SCH_Message_t *sib1_bcch, int num_sibs, int si AssertFatal(reg_sib, "At least 1 SIB from SchedulingInfo (SIB2 to SIB14 included) needs to be present\n"); asn1cSeqAdd(&info->schedulingInfoList.list, schedulingInfo); sib1->si_SchedulingInfo = info; - if (si_schedulingInfo_v17) { + if (schedulingInfo2_r17) { + NR_SI_SchedulingInfo_v1700_t *si_schedulingInfo_v17 = calloc_or_fail(1, sizeof(*si_schedulingInfo_v17)); asn1cSeqAdd(&si_schedulingInfo_v17->schedulingInfoList2_r17.list, schedulingInfo2_r17); NR_SIB1_v1610_IEs_t *sib1_v1610 = NULL; if (sib1->nonCriticalExtension) From 506dc7da52b05b3806775e11fe6425ffd576520b Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Fri, 1 Aug 2025 16:04:23 +0200 Subject: [PATCH 347/964] NR UE: invalidate SI window on successful SI reception to avoid wrongly reusing this old SI window for new SI reception This fix was suggested by Francesco Mani --- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 1 + 1 file changed, 1 insertion(+) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index fb0645560e..7752fcad4d 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -310,6 +310,7 @@ void nr_ue_decode_BCCH_DL_SCH(NR_UE_MAC_INST_t *mac, if (mac->get_otherSI[i]) mac->get_otherSI[i] = false; } + mac->si_SchedInfo.si_window_start = -1; T(T_NRUE_MAC_DL_PDU_WITH_DATA, T_INT(SI_RNTI), T_INT(-1 /* frame, unavailable here */), From 07629e29d67dbb6ecb30345568e1b66b7e342b5f Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 20 Jan 2025 14:49:21 +0100 Subject: [PATCH 348/964] Add CU-UP load tester and documentation This is a simple CU-UP load tester. It sets up a configurable number of UEs in the CU-UP, then sends GTP traffic in downlink/uplink in the N3-F1/F1-N3 direction at the CU-UP. It then compares the sent and received data. Additional parameters, such as amount of traffic, test length, packet size, and IP addresses/ports are configurable. To run: mkdir build && cd build && cmake .. -GNinja && ninja nr-cuup nr-cuup-load-test params_libconfig ./tests/nr-cuup/nr-cuup-load-test ./nr-cuup -O ../tests/nr-cuup/load-test.conf The tester should be able to detect lost and reordered packets. Example lost: Receive order 2,3,5,6 (lost packet 4) => on packet 2, expected 2, next=expected+1=3 => on packet 3, expected 3, next=expected+1=4 => on packet 5, expected 4, diff=5-4=1 (lost 1), next=payload+1=6 => on packet 6, expected 6 => 1 lost Example reordered: Receiver order 2,5,3,6 (lost packet 4) => on packet 2, expected 2, next=expected+1=3 => on packet 5, expected 3, diff=5-3=2 (lost 2), next=payload+1=6 => on packet 3, expected 6, (reduce lost by 1 to 1), next=expected=6 => on packet 6, expected 6 => 1 lost Example reordered: Receiver order 2,5,3,4,6 (no losses) --- CMakeLists.txt | 1 + doc/README.md | 2 + tests/CMakeLists.txt | 1 + tests/nr-cuup/CMakeLists.txt | 4 + tests/nr-cuup/README.md | 78 ++++ tests/nr-cuup/load-test.conf | 58 +++ tests/nr-cuup/nr-cuup-load-test.c | 673 ++++++++++++++++++++++++++++++ 7 files changed, 817 insertions(+) create mode 100644 tests/CMakeLists.txt create mode 100644 tests/nr-cuup/CMakeLists.txt create mode 100644 tests/nr-cuup/README.md create mode 100644 tests/nr-cuup/load-test.conf create mode 100644 tests/nr-cuup/nr-cuup-load-test.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 84d33a0590..5e14642507 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2184,3 +2184,4 @@ add_subdirectory(openair1) add_subdirectory(openair2) add_subdirectory(openair3) add_subdirectory(radio) +add_subdirectory(tests) diff --git a/doc/README.md b/doc/README.md index 756294fb5d..27c2688673 100644 --- a/doc/README.md +++ b/doc/README.md @@ -130,6 +130,8 @@ The other SDRs (AW2S, LimeSDR, ...) have no READMEs. # Testing - [UnitTests.md](./UnitTests.md) explains the unit testing setup +- Component tests are under `tests/`. Currently, there is a simple CU-UP + tester, see the corresponding [README.md](../tests/nr-cuup/README.md). - [TESTBenches.md](./TESTBenches.md) lists the CI setup and links to pipelines # Developer tools diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 0000000000..cefa52d456 --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(nr-cuup) diff --git a/tests/nr-cuup/CMakeLists.txt b/tests/nr-cuup/CMakeLists.txt new file mode 100644 index 0000000000..02becb2496 --- /dev/null +++ b/tests/nr-cuup/CMakeLists.txt @@ -0,0 +1,4 @@ +add_executable(nr-cuup-load-test nr-cuup-load-test.c) +target_link_libraries(nr-cuup-load-test PRIVATE GTPV1U ${T_LIB} utils ITTI e1ap + SCTP_CLIENT) +target_link_libraries(nr-cuup-load-test PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs) # ITTI diff --git a/tests/nr-cuup/README.md b/tests/nr-cuup/README.md new file mode 100644 index 0000000000..3095e5f600 --- /dev/null +++ b/tests/nr-cuup/README.md @@ -0,0 +1,78 @@ +This is a simple tester for the CU-UP. It configures the CU-UP via E1, and can +stream data via GTP in uplink and downlink directions. + +[[_TOC_]] + +# Overview + +From a schematic point of view, the tester/CU-UP interaction looks like this: + +``` + +-------+ ++------>| CU-UP |<------+ +| +-------+ | +| | | +| F1-U | E1 | NG-U +| (data) | (control) | (data) +| | | +| +-------+ | ++------>|tester |<------+ + +-------+ +``` + +The tester is for performance testing of a CU-UP, and behaves like an +integrated DU/CU-CP/UPF from the CU-UP's point of view. + +The tester and CU-UP have an E1 connection through which control information is +exchanged, e.g., configuration of UEs/bearers and associated information. In +other words, towards the CU-UP, the tester appears like a CU-CP. + +Further, for each UE/bearer, CU-UP is configured with GTP IP information and +the corresponding TEID. The CU-UP will forward downlink data arriving on NG-U +on the F1-U interface, and uplink data arriving on F1-U on the NG-U interface. +In other words, on the F1-U interface, the tester appears like a DU to the +CU-UP, and on the NG-U interface, the tester appears like a UPF to the CU-UP. + +A test scenario is fixed to these steps: + +1. The tester sets up a number of UEs via the E1 interface (it is possible to + see the message exchange in Wireshark). +2. The tester streams data in downlink/uplink (from the CU-UP's point of view) + and measures how much data is lost. +3. The tester releases all the UEs via the E1 interface, and disconnects from + the CU-UP. + +Note: The tester uses the same GTP module as the CU-UP. Thus, data might not +only be lost at the GTP interface of the CU-UP, but also at the tester. + +# Usage + +You can build the CU-UP and the tester like so: + + cd ~/openairinterface5g + mkdir build && cd build && cmake .. -GNinja && ninja nr-cuup nr-cuup-load-test params_libconfig + ./tests/nr-cuup/nr-cuup-load-test + ./nr-cuup -O ../tests/nr-cuup/load-test.conf + +This builds both tester and CU-UP in the directory `build/`, then starts the +load tester with default values + +- 1 UE +- 10s of Test +- 60 Mbps of traffic in both downlik/uplink with a packet size of 1400 bytes + +To see the available options, run + + ./tests/nr-cuup/nr-cuup-load-test -h + +The configuration file [`load-test.conf`](./load-test.conf) matches the default +tester configuration (F1-U GTP traffic over non-standard port 2153, NG-U GTP +over 2152, tests on localhost). The configuration file includes this +non-standard port 2153 as the GTP module, as of now, cannot bind on the same +interface and port for both F1-U and NG-U due to internal limitations. + +# Limitations + +- The tester does not yet create/remove UEs during a traffic test. +- It might be possible to integrate with an external GTP traffic generator, + but we did not test this. diff --git a/tests/nr-cuup/load-test.conf b/tests/nr-cuup/load-test.conf new file mode 100644 index 0000000000..9829640a02 --- /dev/null +++ b/tests/nr-cuup/load-test.conf @@ -0,0 +1,58 @@ +Active_gNBs = ( "gNB-OAI"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + gNB_CU_UP_ID = 0xe00; + +# cell_type = "CELL_MACRO_GNB"; + + gNB_name = "gNB-OAI"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + plmn_list = ({ mcc = 222; mnc = 01; mnc_length = 2; snssaiList = ({ sst = 1, sd = 0xffffff }) }); + + + tr_s_preference = "f1"; + + local_s_address = "127.0.0.6"; + remote_s_address = "127.0.0.1"; + local_s_portc = 501; + local_s_portd = 2153; + remote_s_portc = 500; + remote_s_portd = 2153; + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + E1_INTERFACE = + ( + { + type = "up"; + ipv4_cucp = "127.0.0.1"; + ipv4_cuup = "127.0.0.6"; + } + ) + + NETWORK_INTERFACES : + { + GNB_IPV4_ADDRESS_FOR_NG_AMF = "172.21.16.109"; + GNB_IPV4_ADDRESS_FOR_NGU = "127.0.0.7"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + } +); + +log_config: { + global_log_level = "info"; +}; diff --git a/tests/nr-cuup/nr-cuup-load-test.c b/tests/nr-cuup/nr-cuup-load-test.c new file mode 100644 index 0000000000..48e088fc3c --- /dev/null +++ b/tests/nr-cuup/nr-cuup-load-test.c @@ -0,0 +1,673 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include +#include +#include + +#include "common/utils/LOG/log.h" +#include "common/utils/ocp_itti/intertask_interface.h" // this pulls in all of OAI+4G+5G +#include "openair3/SCTP/sctp_eNB_task.h" +#include "openair2/E1AP/e1ap.h" +#include "openair3/ocp-gtpu/gtp_itf.h" + +configmodule_interface_t *uniqCfg; + +#define DL 0 +#define UL 1 + +int nr_rlc_get_available_tx_space(const rnti_t rntiP, const logical_chan_id_t channel_idP) { abort(); return 0; } /* in GTP */ +softmodem_params_t *get_softmodem_params(void) { static softmodem_params_t p = {0}; return &p; }; /* in ITTI */ +void e1_bearer_context_setup(const e1ap_bearer_setup_req_t *req) { abort(); } /* CU-UP */ +void e1_bearer_context_modif(const e1ap_bearer_mod_req_t *req) { abort(); } /* CU-UP */ +void e1_bearer_release_cmd(const e1ap_bearer_release_cmd_t *cmd) { abort(); } /* CU-UP */ +void e1_reset(void) { abort(); } /* CU-UP */ +instance_t *N3GTPUInst = NULL; /* CU-UP */ +instance_t CUuniqInstance=0; /* CU-UP */ + +void exit_function(const char *file, const char *function, const int line, const char *s, const int assert) +{ + LOG_E(GNB_APP, "error at %s:%d:%s: %s\n", file, line, function, s); + abort(); +} + +/* @brief Dummy function to pass a fptr to ITTI for staring RRC queue, without + * actually handling any messages. Functions called by main() will send/receive + * ITTI messages to E1, as if it was RRC. */ +static void *cuup_tester_rrc(void *) +{ + itti_mark_task_ready(TASK_RRC_GNB); + LOG_I(GNB_APP, "created RRC queue\n"); + return NULL; +} + +/* @brief Initialize E1 interface (as if it was CU-CP) */ +static void init_e1() +{ + net_ip_address_t ip = {.ipv4 = 1, .ipv4_address = "127.0.0.1" }; + e1ap_net_config_t conf = { .CUCP_e1_ip_address = ip }; + MessageDef *msg = itti_alloc_new_message(TASK_GNB_APP, 0, E1AP_REGISTER_REQ); + e1ap_net_config_t *e1ap_nc = &E1AP_REGISTER_REQ(msg).net_config; + *e1ap_nc = conf; + itti_send_msg_to_task(TASK_CUCP_E1, 0, msg); +} + +/* @brief Setup CU-UP connection and retrieve parameters for further + * connection. + * + * Waits for E1 Setup Request, sends response, and returns SCTP association ID + * and NSSAI used by this CU-UP. + */ +static void setup_cuup(sctp_assoc_t *assoc_id, e1ap_nssai_t *nssai) +{ + /* Wait for E1AP setup request, store CU-UP info */ + MessageDef *itti_req = NULL; + itti_receive_msg(TASK_RRC_GNB, &itti_req); + MessagesIds id = ITTI_MSG_ID(itti_req); + AssertFatal(id == E1AP_SETUP_REQ, "expected E1AP setup request, received %s instead\n", itti_get_message_name(id)); + *assoc_id = itti_req->ittiMsgHeader.originInstance; + e1ap_setup_req_t *req = &E1AP_SETUP_REQ(itti_req); + long t_id = req->transac_id; + DevAssert(req->supported_plmns = 1); + DevAssert(req->plmn[0].slice != NULL); + *nssai = *req->plmn[0].slice; + DevAssert(assoc_id != 0); + itti_free(TASK_GNB_APP, itti_req); + + // acknowledge the E1 setup request with a response + MessageDef *itti_resp = itti_alloc_new_message(TASK_GNB_APP, 0, E1AP_SETUP_RESP); + itti_resp->ittiMsgHeader.originInstance = *assoc_id; + e1ap_setup_resp_t *resp = &E1AP_SETUP_RESP(itti_resp); + resp->transac_id = t_id; + itti_send_msg_to_task(TASK_CUCP_E1, 0, itti_resp); +} + +/* @brief get E1AP bearer setup request based on parameters */ +static e1ap_bearer_setup_req_t get_breq(uint32_t ue_id, long pdu_id, long drb_id, const e1ap_nssai_t *nssai, const UP_TL_information_t *tnl) +{ + e1ap_bearer_setup_req_t bearer_req = { + .gNB_cu_cp_ue_id = ue_id, + .secInfo.cipheringAlgorithm = 0, /* no ciphering/NEA0 */ + .secInfo.integrityProtectionAlgorithm = 0, /* no integrity/NIA0 */ + /* encryptionKey not needed */ + /* integrityProtectionKey not needed */ + .numPDUSessions = 1, + }; + pdu_session_to_setup_t *pdu = &bearer_req.pduSession[0]; + pdu->sessionId = pdu_id; + pdu->nssai = *nssai; + pdu->securityIndication.integrityProtectionIndication = SECURITY_NOT_NEEDED; + pdu->securityIndication.confidentialityProtectionIndication = SECURITY_NOT_NEEDED; + pdu->UP_TL_information = *tnl; + pdu->numDRB2Setup = 1; + DRB_nGRAN_to_setup_t *drb = &pdu->DRBnGRanList[0]; + drb->id = drb_id; + drb->numQosFlow2Setup = 1; + drb->numCellGroups = 1; + + return bearer_req; +} + +/* @brief check for packet loss by verifing the sequence number. Can handle + * packet losses and reordering. + * @param payload the sequence number of the current packet + * @param expected the expected sequence number + * @param [inout] pointer to number of lost packets, which will be updated by + * the difference between payload and expected. + * @return the next expected packet number. */ +static uint32_t estimate_packetloss(const uint32_t payload, uint32_t expected, uint32_t *lost) +{ + if (payload == expected) { + /* all good */ + return expected + 1; + } else if (payload > expected) { + /* there was packet loss, assume all packets in between have been lost */ + uint32_t diff = payload - expected; + *lost += diff; + LOG_W(GNB_APP, "packet loss: expected %d received %d diff %d (total loss %d)\n", expected, payload, diff, *lost); + return payload + 1; + } else { /* payload < expected */ + /* reordered: we assumed current packet to be lost, so reduce the + * loss for this packet as it arrived in the end. */ + *lost -= 1; + LOG_W(GNB_APP, "packet reordering occurred: expected %d received %d\n", expected, payload); + return expected; /* we still wait for the next packet */ + } +} + +static struct ue_stat { + uint32_t count; + uint32_t lost; + uint64_t received; +} ue_stat[10][2] = {0}; +/* @brief ulReceived callback for F1-U + * + * Checks for packet loss by verifying that the first 4 bytes are corresponding + * to a continuous 4-byte (word) enumeration. */ +static bool recv_ng(protocol_ctxt_t *ctxt, + const ue_id_t ue_id, + const srb_flag_t flag, + const rb_id_t rb, + const mui_t mui, + const confirm_t confirm, + const sdu_size_t size, + unsigned char *const buf, + const pdcp_transmission_mode_t modeP, + const uint32_t *sourceL2Id, + const uint32_t *destinationL2Id, + const uint8_t qfi, + const bool rqi, + const int pdusession_id) +{ + uint32_t *payload = (uint32_t *) buf; + DevAssert(size % 4 == 0); + struct ue_stat *s = &ue_stat[ue_id][UL]; + s->count = estimate_packetloss(*payload, s->count, &s->lost); + s->received += size; + + return true; +} + +/* @brief Set up the NG-U (north-bound) GTP tunnel, and inform CU-UP via E1 */ +static up_params_t setup_cuup_ue_ng(sctp_assoc_t assoc_id, const e1ap_nssai_t *nssai, uint32_t ue_id, instance_t gtp_inst, const char *ip, uint16_t port) +{ + long pdu_id = 1; + long drb_id = pdu_id + 3; + in_addr_t addr_lo; + inet_pton(AF_INET, ip, &addr_lo); + + /* create the local tunnel (i.e., as if we were UPF) */ + transport_layer_addr_t null_addr = {.length = 32}; + teid_t teid_lo = newGtpuCreateTunnel(gtp_inst, ue_id, pdu_id, pdu_id, -1, -1, null_addr, port, NULL, recv_ng); + UP_TL_information_t tnl = {.teId = teid_lo}; + memcpy(&tnl.tlAddress, &addr_lo, 4); + + /* Create a new bearer */ + MessageDef *itti_breq = itti_alloc_new_message(TASK_GNB_APP, 0, E1AP_BEARER_CONTEXT_SETUP_REQ); + itti_breq->ittiMsgHeader.originInstance = assoc_id; + e1ap_bearer_setup_req_t *breq = &E1AP_BEARER_CONTEXT_SETUP_REQ(itti_breq); + *breq = get_breq(ue_id, pdu_id, drb_id, nssai, &tnl); + itti_send_msg_to_task(TASK_CUCP_E1, 0, itti_breq); + + /* Wait for the ack */ + MessageDef *itti_bresp; + itti_receive_msg(TASK_RRC_GNB, &itti_bresp); + MessagesIds id = ITTI_MSG_ID(itti_bresp); + AssertFatal(id == E1AP_BEARER_CONTEXT_SETUP_RESP, "expected E1AP bearer context setup response, received %s instead\n", itti_get_message_name(id)); + DevAssert(assoc_id == itti_bresp->ittiMsgHeader.originInstance); + e1ap_bearer_setup_resp_t *bresp = &E1AP_BEARER_CONTEXT_SETUP_RESP(itti_bresp); + DevAssert(bresp->gNB_cu_cp_ue_id == ue_id); + DevAssert(bresp->gNB_cu_up_ue_id == ue_id); + DevAssert(bresp->numPDUSessions == 1); + teid_t teid_rm = bresp->pduSession[0].tl_info.teId; + in_addr_t addr_rm; + memcpy(&addr_rm, &bresp->pduSession[0].tl_info.tlAddress, 4); + DevAssert(bresp->pduSession[0].numDRBSetup == 1); + DRB_nGRAN_setup_t *drb = &bresp->pduSession[0].DRBnGRanList[0]; + DevAssert(drb->id == drb_id); + DevAssert(drb->numUpParam == 1); + up_params_t f1_up = drb->UpParamList[0]; + itti_free(TASK_GNB_APP, itti_bresp); + + /* print diagnostics */ + char ip_lo[32] = {0}; + inet_ntop(AF_INET, &addr_lo, ip_lo, sizeof(ip_lo)); + char ip_rm[32] = {0}; + inet_ntop(AF_INET, &addr_rm, ip_rm, sizeof(ip_rm)); + GtpuUpdateTunnelOutgoingAddressAndTeid(gtp_inst, ue_id, pdu_id, addr_rm, teid_rm); + LOG_I(GNB_APP, "CU-UP created NG-U, local %s/%x remote %s/%x (port %d)\n", ip_lo, teid_lo, ip_rm, teid_rm, port); + + inet_ntop(AF_INET, &f1_up.tl_info.tlAddress, ip_rm, sizeof(ip_rm)); + LOG_I(GNB_APP, "CU-UP created F1-U, remove %s/%x\n", ip_rm, f1_up.tl_info.teId); + return f1_up; +} + +/* @brief get E1AP bearer modification request based on parameters */ +static e1ap_bearer_mod_req_t get_bmod(uint32_t ue_id, long pdu_id, up_params_t up) +{ + e1ap_bearer_mod_req_t bearer_mod = { + .gNB_cu_cp_ue_id = ue_id, + .gNB_cu_up_ue_id = ue_id, + .numPDUSessionsMod = 1, + }; + pdu_session_to_mod_t *pdum = &bearer_mod.pduSessionMod[0]; + pdum->sessionId = pdu_id; + pdum->numDRB2Modify = 1; + DRB_nGRAN_to_mod_t *drb = &pdum->DRBnGRanModList[0]; + drb->id = 4; + drb->numDlUpParam = 1; + drb->DlUpParamList[0] = up; + + return bearer_mod; +} + +/* @brief Received callback for F1-U + * + * Checks for packet loss by verifying that the first 4 bytes are corresponding + * to a continuous 4-byte (word) enumeration. */ +static bool recv_f1(protocol_ctxt_t *ctxt, + const srb_flag_t flag, + const rb_id_t rb, + const mui_t mui, + const confirm_t confirm, + const sdu_size_t size, + unsigned char *const buf, + const pdcp_transmission_mode_t modeP, + const uint32_t *sourceL2Id, + const uint32_t *destinationL2Id) +{ + int skip_bytes = 2; + uint32_t *payload = (uint32_t *) &buf[skip_bytes]; + DevAssert((size - skip_bytes) % 4 == 0); + int ue_id = ctxt->rntiMaybeUEid; + struct ue_stat *s = &ue_stat[ue_id][DL]; + s->count = estimate_packetloss(*payload, s->count, &s->lost); + s->received += size - skip_bytes; + + return true; +} + +/* @brief Set up the F1-U (south-bound) GTP tunnel, and inform CU-UP via E1 */ +static void setup_cuup_ue_f1(sctp_assoc_t assoc_id, uint32_t ue_id, instance_t gtp_inst, const char *ip, uint16_t port, up_params_t rm) +{ + int pdu_id = 1; + int drb_id = pdu_id + 3; + + /* create tunnel (i.e., as if we were DU) */ + transport_layer_addr_t addr = {.length = 32}; + memcpy(addr.buffer, &rm.tl_info.tlAddress, 4); + teid_t teid_lo = newGtpuCreateTunnel(gtp_inst, ue_id, drb_id, drb_id, rm.tl_info.teId, -1, addr, port, recv_f1, NULL); + + up_params_t lo = {.tl_info.teId = teid_lo, .cell_group_id = rm.cell_group_id}; + inet_pton(AF_INET, ip, &lo.tl_info.tlAddress); + + /* modify existing tunnel via E1 to pass in F1-U TEID */ + MessageDef *itti_bmod = itti_alloc_new_message(TASK_GNB_APP, 0, E1AP_BEARER_CONTEXT_MODIFICATION_REQ); + itti_bmod->ittiMsgHeader.originInstance = assoc_id; + e1ap_bearer_mod_req_t *bmod = &E1AP_BEARER_CONTEXT_MODIFICATION_REQ(itti_bmod); + *bmod = get_bmod(ue_id, pdu_id, lo); + itti_send_msg_to_task(TASK_CUCP_E1, 0, itti_bmod); + + /* Wait for the ack */ + MessageDef *itti_bmodr; + itti_receive_msg(TASK_RRC_GNB, &itti_bmodr); + MessagesIds id = ITTI_MSG_ID(itti_bmodr); + AssertFatal(id == E1AP_BEARER_CONTEXT_MODIFICATION_RESP, "expected E1AP bearer context modification response, received %s instead\n", itti_get_message_name(id)); + //DevAssert(assoc_id == itti_bmodr->ittiMsgHeader.originInstance); + itti_free(TASK_GNB_APP, itti_bmodr); + + /* print diagnostics */ + char ip_lo[32] = {0}; + inet_ntop(AF_INET, &lo.tl_info.tlAddress, ip_lo, sizeof(ip_lo)); + char ip_rm[32] = {0}; + inet_ntop(AF_INET, &rm.tl_info.tlAddress, ip_rm, sizeof(ip_rm)); + LOG_I(GNB_APP, "CU-UP created F1-U, local %s/%x remote %s/%x (port %d)\n", ip_lo, lo.tl_info.teId, ip_rm, rm.tl_info.teId, port); +} + +/* @brief release the UE over E1, and delete corresponding GTP tunnels */ +static void e1_release_ue(sctp_assoc_t assoc_id, uint32_t ue_id, instance_t f1_inst, instance_t ng_inst) +{ + MessageDef *itti_cmd = itti_alloc_new_message(TASK_GNB_APP, 0, E1AP_BEARER_CONTEXT_RELEASE_CMD); + itti_cmd->ittiMsgHeader.originInstance = assoc_id; + e1ap_bearer_release_cmd_t *cmd = &E1AP_BEARER_CONTEXT_RELEASE_CMD(itti_cmd); + cmd->gNB_cu_cp_ue_id = cmd->gNB_cu_up_ue_id = ue_id; + cmd->cause.type = E1AP_CAUSE_RADIO_NETWORK; + cmd->cause.value = E1AP_RADIO_CAUSE_NORMAL_RELEASE; + itti_send_msg_to_task(TASK_CUCP_E1, 0, itti_cmd); + + /* Wait for the ack */ + MessageDef *itti_cplt; + itti_receive_msg(TASK_RRC_GNB, &itti_cplt); + MessagesIds id = ITTI_MSG_ID(itti_cplt); + AssertFatal(id == E1AP_BEARER_CONTEXT_RELEASE_CPLT, "expected E1AP bearer context release complete, received %s instead\n", itti_get_message_name(id)); + itti_free(TASK_GNB_APP, itti_cplt); + + newGtpuDeleteAllTunnels(f1_inst, ue_id); + newGtpuDeleteAllTunnels(ng_inst, ue_id); +} + +/* @brief initialize GTP interface for IP:port */ +static instance_t init_gtp(const char *ip, uint16_t port) +{ + openAddr_t iface = {0}; + DevAssert(strlen(ip) <= sizeof(iface.originHost)); + strcpy(iface.originHost, ip); + snprintf(iface.originService, sizeof(iface.originService), "%d", port); + snprintf(iface.destinationService, sizeof(iface.destinationService), "%d", port); + return gtpv1Init(iface); +} + +/* @brief calculate time difference of two struct timespec */ +static float time_diff(struct timespec s, struct timespec e) +{ + //printf("start %ld.%ld end %ld.%ld\n", s.tv_sec, s.tv_nsec, e.tv_sec, e.tv_nsec); + float dur = e.tv_sec - s.tv_sec + (e.tv_nsec - s.tv_nsec) / 1000000000.f; + //printf("duration %f s %f us\n", dur, dur * 1000000.f); + return dur * 1000000.f; +} + +enum pdcp_len {PDCP_SN_LEN_12, PDCP_SN_LEN_18}; +/* @brief generate hardcoded PDCP header in case of UL transmission */ +static void write_pdcp_header(uint32_t sn, enum pdcp_len len, uint8_t *buf) +{ + DevAssert(len == PDCP_SN_LEN_12); + /* see nr_pdcp_entity_process_sdu() or 38.323 sec 6.2.2.2 */ + buf[0] = 0x80 | ((sn >> 8) & 0xf); + buf[1] = sn & 0xff; + //printf("%02x %02x\n", buf[0], buf[1]); +} + +/* @brief the configuration for a thread to send GTP traffic */ +struct thr_data { + /// pthread ID to join this thread + pthread_t t; + + /* in */ + /// GTP instance to send on + instance_t inst; + /// UE ID to be used + ue_id_t ue_id; + /// flag to decide if PDCP/SDAP header is to be prepended + bool is_ul; + /// length of data packet + unsigned int data_len; + /// target throughput to reach + uint64_t throughput; + /// duration of the data traffic to last + unsigned int duration; + + /* out */ + /// exact measured transmission time + float total_time; + /// exact measured data that has been sent + uint64_t total_data; +}; +/* @brief Main traffic generation/transmission function. + * + * The function calculates the amount of packets to be sent during each TTI + * (one millisecond) (as a float, to send the exact amount of packets). It then + * enters a loop, in which (1) it sends the packets of the current TTI, possibly + * including additional packets if they could not be sent in the last TTI, (2) + * measure the time since the last TTI boundary, and sleep, if necessary, to + * adjust to the exact throughput (3) update for additional packets to send if + * the last TTI took too long. The last point ensure that we send exactly an + * exact amount of data, possibly taking longer than specified. + * + * @param v pointer to generation function of type `struct thr_data`. + * @return always NULL */ +static void *sender_thread(void *v) +{ + struct thr_data *d = v; + + size_t oh = d->is_ul ? 3 : 0; + size_t packet_len = d->data_len + oh; + uint8_t buf[packet_len]; + memset(buf, 0, packet_len); + uint32_t *payload = (uint32_t *)(buf + oh); + uint64_t to_send = (float)d->throughput / 8.0 * d->duration; + const float pps_1ms = (float) d->throughput / 8.0 / d->data_len / 1000; + float pps_1ms_nextwin = pps_1ms; + int bearer = d->is_ul ? 4 : 1; + + + //printf("sending %ld Mbps for %ld s => data %ld, %.3f pps\n", (float) d->throughput / 1000000.0, d->duration, to_send, pps_1ms); + + int i_1ms = 0; + struct timespec start; + clock_gettime(CLOCK_MONOTONIC, &start); + size_t packet_count = 0; + while (true) { + int pps_now = pps_1ms_nextwin; + pps_1ms_nextwin = pps_1ms + pps_1ms_nextwin - (float) pps_now; + //printf("this window send %d packets next window %.3f (pps_1ms %.3f)\n", pps_now, pps_1ms_nextwin, pps_1ms); + for (uint32_t i = 0; i < pps_now; ++i) { + if (d->is_ul) + write_pdcp_header(packet_count, PDCP_SN_LEN_12, buf); + *payload = packet_count++; + gtpv1uSendDirect(d->inst, d->ue_id, bearer, (uint8_t *)buf, packet_len, false, false); + d->total_data += d->data_len; + } + + struct timespec t; + clock_gettime(CLOCK_MONOTONIC, &t); + float diff_us = time_diff(start, t); + int us_passed = diff_us - i_1ms*1000; + int iter_advance = us_passed / 1000 + 1; + int wait_usec = 1000 - us_passed; + //printf("diff %.3fus i_1ms %d us_passed %d iter %d wait %d (%.3f %%)\n", diff_us, i_1ms, us_passed, iter_advance, wait_usec, 100.0 * d->total_data / to_send); + DevAssert(iter_advance > 0); + if (wait_usec > 0) + usleep(wait_usec); + + if (iter_advance > 1) /* we have to send more in the next window */ + pps_1ms_nextwin += (iter_advance - 1) * pps_1ms_nextwin; + i_1ms += iter_advance; + if (d->total_data >= to_send) + break; + } + struct timespec end; + clock_gettime(CLOCK_MONOTONIC, &end); + d->total_time = time_diff(start, end) / 1000000.f; + return NULL; +} + +/* @brief print statistics of a UE (amount of data, achieved rate, if data was + * lost). */ +static bool print_stats(const char *pref, int ue_id, uint64_t total_data, float duration, const struct ue_stat *s) +{ + float tthr = 8.0 * total_data / duration / 1000000.f; + float rthr = 8.0 * s->received / duration / 1000000.f; + LOG_I(GNB_APP, "%d %s sent %ld in %.3f s received %ld bytes => rates [Mbps] transmit %.3f receive %.3f\n", + ue_id, + pref, + total_data, + duration, + s->received, + tthr, + rthr); + if (total_data == s->received) { + DevAssert(s->lost == 0); + LOG_A(GNB_APP, "%d %s received all data sent\n", ue_id, pref); + return true; + } else { + uint64_t m = total_data - s->received; + LOG_W(GNB_APP, "%d %s warning: missing %ld bytes (%.3f %%, %d packets)\n", ue_id, pref, m, 100.f * m / total_data, s->lost); + return false; + } +} + +/* @brief start a thread if specified through template, and in direction of + * given GTP bearer. + * @param template specifies if thread is to be started (throughput and + * duration are positive). If so, the template data is stored inside the + * thread. + * @param thr place to store thread data + * @param b the GTP bearer to use */ +static struct thr_data *start_thread(const struct thr_data *template, struct thr_data *thr, instance_t inst, ue_id_t ue_id) +{ + if (template->throughput == 0 || template->duration == 0) + return NULL; + + *thr = *template; + thr->inst = inst; + thr->ue_id = ue_id; + pthread_create(&thr->t, NULL, sender_thread, thr); + return thr; +} + +/* @brief print progress of a thread specified in thr_data, and prepend DL/UL + * based on dir. data access to thread data is not private, but we only read, + * so don't care. */ +static bool print_progress(const int dir, const struct thr_data *obs) +{ + if (!obs) + return false; + + uint64_t target = (uint64_t) obs->throughput / 8 * obs->duration; + float progress = (float)obs->total_data / target; + printf(" %s sent %3.f %%", dir == DL ? "DL" : "UL", 100.0 * progress); + return progress < 0.99; +} + +int main(int argc, char *argv[]) +{ + if ((uniqCfg = load_configmodule(argc, argv, CONFIG_ENABLECMDLINEONLY)) == NULL) { + exit_fun("[SOFTMODEM] Error, configuration module init failed\n"); + } + logInit(); + itti_init(TASK_MAX, tasks_info); + + unsigned int n_ue; + unsigned int duration_s; + unsigned int packet_size; + uint64_t target_rate_dl; + uint64_t target_rate_ul; + char *ng_ip = malloc_or_fail(100); + uint16_t ng_port; + char *f1_ip = malloc_or_fail(100); + uint16_t f1_port; + + paramdef_t param_def[] = { + {"n", "number of UEs\n", 0, .uptr = &n_ue, .defuintval = 1, TYPE_UINT}, + {"t", "duration of test (s)\n", 0, .uptr = &duration_s, .defuintval = 10, TYPE_UINT}, + {"p", "packet size\n", 0, .uptr = &packet_size, .defuintval = 1400, TYPE_UINT}, + {"d", "DL target rate (Mbps, per UE)\n", 0, .u64ptr = &target_rate_dl, .defint64val = 60, TYPE_UINT64}, + {"u", "UL target rate (Mbps, per UE)\n", 0, .u64ptr = &target_rate_ul, .defint64val = 60, TYPE_UINT64}, + {"ng-ip", "Tester NG-U IP\n", 0, .strptr = &ng_ip, .defstrval = "127.0.0.1", TYPE_STRING, 100}, + {"ng-port", "Tester NG-U port\n", 0, .u16ptr = &ng_port, .defuintval = 2152, TYPE_UINT16}, + {"f1-ip", "Tester F1-U IP\n", 0, .strptr = &f1_ip, .defstrval = "127.0.0.1", TYPE_STRING, 100}, + {"f1-port", "Tester F1-U port\n", 0, .u16ptr = &f1_port, .defuintval = 2153, TYPE_UINT16}, + }; + config_get(uniqCfg, param_def, sizeofArray(param_def), NULL); + // on command line, target rate is in Mbps, convert to bps + target_rate_dl *= 1000000LL; + target_rate_ul *= 1000000LL; + LOG_I(GNB_APP, + "CU-UP load tester: running test for\n" + "- Number of UEs %d\n" + "- Duration %d seconds\n" + "- Packet size %d\n" + "- Target DL rate %.3f Mbps (per UE)\n" + "- Target UL rate %.3f Mbps (per UE)\n" + "- Tester endpoint for CU-UP NG-U: %s:%d\n" + "- Tester endpoint for CU-UP F1-U: %s:%d\n", + n_ue, duration_s, packet_size, + (float) target_rate_dl / 1e6, + (float) target_rate_ul / 1e6, + ng_ip, ng_port, f1_ip, f1_port); + + struct thr_data dl_template = {.is_ul = false, .data_len = packet_size, .throughput = target_rate_dl, .duration = duration_s}; + struct thr_data ul_template = {.is_ul = true, .data_len = packet_size, .throughput = target_rate_ul, .duration = duration_s}; + + /* init GTP for NG-U comm with CU-UP */ + instance_t ng_inst = init_gtp(ng_ip, ng_port); + AssertFatal(ng_inst > 0, "could not initialize GTP interface on %s:%d towards CU-UP NG-U\n", ng_ip, ng_port); + + /* init GTP for F1-U comm with CU-UP */ + instance_t f1_inst = init_gtp(f1_ip, f1_port); + AssertFatal(f1_inst > 0, "could not initialize GTP interface on %s:%d towards CU-UP F1-U\n", f1_ip, f1_port); + + /* Start relevant services: SCTP, CUCP_E1: E1; GTP not actively used; RRC to + * register the queue so we can receive what E1 sends us back */ + int rc; + rc = itti_create_task(TASK_SCTP, sctp_eNB_task, NULL); + AssertFatal(rc >= 0, "Create task for SCTP failed\n"); + rc = itti_create_task(TASK_CUCP_E1, E1AP_CUCP_task, NULL); + AssertFatal(rc >= 0, "Create task for CUUP E1 failed\n"); + rc = itti_create_task(TASK_GTPV1_U, gtpv1uTask, NULL); + AssertFatal(rc >= 0, "Create task for GTPV1U failed\n"); + rc = itti_create_task(TASK_RRC_GNB, cuup_tester_rrc, NULL); + AssertFatal(rc >= 0, "Create task for RRC failed\n"); + init_e1(); + + /* Set up CU-UP connection: waits for CU-UP-initiated SCTP+E1 setup request */ + sctp_assoc_t assoc_id; + e1ap_nssai_t nssai; + setup_cuup(&assoc_id, &nssai); + + /* Set up UE contexts in CU-UP. the below two calls correspond to + * - setup_cuup_ue_ng(): E1 bearer context setup <=> completely sets up NG-U + * in CU-UP, gets TEID for F1-U UL + * - setup_cuup_ue_f1(): E1 bearer context modification <=> send TEID for + * F1-U DL (as if we had talked to the DU in the middle) */ + for (int ue = 0; ue < n_ue; ++ue) { + up_params_t f1_up = setup_cuup_ue_ng(assoc_id, &nssai, ue, ng_inst, ng_ip, ng_port); + setup_cuup_ue_f1(assoc_id, ue, f1_inst, f1_ip, f1_port, f1_up); + } + + usleep(1000); + + /* for each UE, start DL&UL data streams in dedicated thread, if configured */ + struct thr_data thrd[n_ue][2]; + memset(thrd, 0, sizeof(thrd)); + struct thr_data *obs_dl = NULL, *obs_ul = NULL; + for (int ue = 0; ue < n_ue; ++ue) { + obs_dl = start_thread(&dl_template, &thrd[ue][DL], ng_inst, ue); + obs_ul = start_thread(&ul_template, &thrd[ue][UL], f1_inst, ue); + } + /* show progress of one thread (all take the same time) */ + while (obs_dl || obs_ul) { + bool dlrunning = print_progress(DL, obs_dl); + bool ulrunning = print_progress(UL, obs_ul); + printf("\r"); + fflush(stdout); + if (!dlrunning && !ulrunning) + break; + usleep(100000); + } + /* join threads, if applicable */ + for (int ue = 0; ue < n_ue; ++ue) { + struct thr_data *dl = &thrd[ue][DL]; + if (dl->t) + pthread_join(dl->t, NULL); + struct thr_data *ul = &thrd[ue][UL]; + if (ul->t) + pthread_join(ul->t, NULL); + } + + /* wait a bit, to ensure all data is received after having sent it above */ + sleep(1); + + for (int ue = 0; ue < n_ue; ++ue) { + e1_release_ue(assoc_id, ue, f1_inst, ng_inst); + } + + /* show stats of all threads */ + bool success = true; + for (int ue = 0; ue < n_ue; ++ue) { + struct thr_data *thrddl = &thrd[ue][DL]; + struct ue_stat *statdl = &ue_stat[ue][DL]; + if (thrddl->t) + if (!print_stats("DL", ue, thrddl->total_data, thrddl->total_time, statdl)) + success = false; + struct thr_data *thrdul = &thrd[ue][UL]; + struct ue_stat *statul = &ue_stat[ue][UL]; + if (thrdul->t) + if (!print_stats("UL", ue, thrdul->total_data, thrdul->total_time, statul)) + success = false; + } + + if (success) + LOG_A(GNB_APP, "test succeeded\n"); + else + LOG_W(GNB_APP, "TEST FAILED\n"); + return success ? 0 : 1; +} From 905fe3fb714688bbf5c430177fcd58c7ba6072b8 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 3 Feb 2025 08:02:48 +0100 Subject: [PATCH 349/964] DU Buffer Report/DL Delivery Status: remove unused code --- openair2/COMMON/gtpv1_u_messages_def.h | 1 - openair2/COMMON/gtpv1_u_messages_types.h | 9 ---- openair3/ocp-gtpu/gtp_itf.cpp | 62 ------------------------ 3 files changed, 72 deletions(-) diff --git a/openair2/COMMON/gtpv1_u_messages_def.h b/openair2/COMMON/gtpv1_u_messages_def.h index 19001b883e..6fad3df938 100644 --- a/openair2/COMMON/gtpv1_u_messages_def.h +++ b/openair2/COMMON/gtpv1_u_messages_def.h @@ -25,4 +25,3 @@ MESSAGE_DEF(GTPV1U_ENB_DATA_FORWARDING_IND, MESSAGE_PRIORITY_MED, gtpv1u_enb_dat MESSAGE_DEF(GTPV1U_ENB_END_MARKER_REQ, MESSAGE_PRIORITY_MED, gtpv1u_enb_end_marker_req_t, Gtpv1uEndMarkerReq) MESSAGE_DEF(GTPV1U_ENB_END_MARKER_IND, MESSAGE_PRIORITY_MED, gtpv1u_enb_end_marker_ind_t, Gtpv1uEndMarkerInd) MESSAGE_DEF(GTPV1U_REQ, MESSAGE_PRIORITY_MED, Gtpv1uReq, gtpv1uReq) -MESSAGE_DEF(GTPV1U_DU_BUFFER_REPORT_REQ, MESSAGE_PRIORITY_MED, gtpv1u_DU_buffer_report_req_t, NRGtpv1uBufferReportReq) diff --git a/openair2/COMMON/gtpv1_u_messages_types.h b/openair2/COMMON/gtpv1_u_messages_types.h index 30471c9c4f..05ca7d7a74 100644 --- a/openair2/COMMON/gtpv1_u_messages_types.h +++ b/openair2/COMMON/gtpv1_u_messages_types.h @@ -37,8 +37,6 @@ #define GTPV1U_REQ(mSGpTR) (mSGpTR)->ittiMsg.gtpv1uReq -#define GTPV1U_DU_BUFFER_REPORT_REQ(mSGpTR) (mSGpTR)->ittiMsg.NRGtpv1uBufferReportReq - #define GTPV1U_ALL_TUNNELS_TEID (teid_t)0xFFFFFFFF typedef struct gtpv1u_enb_create_x2u_tunnel_req_s { @@ -188,11 +186,4 @@ typedef struct gtpv1u_gnb_delete_tunnel_resp_s { teid_t gnb_NGu_teid; ///< local NGU Tunnel Endpoint Identifier to be deleted } gtpv1u_gnb_delete_tunnel_resp_t; - -typedef struct gtpv1u_DU_buffer_report_req_s { - uint32_t buffer_availability; - ue_id_t ue_id; - int pdusession_id; -} gtpv1u_DU_buffer_report_req_t; - #endif /* GTPV1_U_MESSAGES_TYPES_H_ */ diff --git a/openair3/ocp-gtpu/gtp_itf.cpp b/openair3/ocp-gtpu/gtp_itf.cpp index 58be5ed638..174f75d89b 100644 --- a/openair3/ocp-gtpu/gtp_itf.cpp +++ b/openair3/ocp-gtpu/gtp_itf.cpp @@ -369,63 +369,6 @@ void gtpv1uSendDirect(instance_t instance, } } -static void fillDlDeliveryStatusReport(extensionHeader_t *extensionHeader, uint32_t RLC_buffer_availability, uint32_t NR_PDCP_PDU_SN){ - - extensionHeader->buffer[0] = (1+sizeof(DlDataDeliveryStatus_flagsT)+(NR_PDCP_PDU_SN>0?3:0)+(NR_PDCP_PDU_SN>0?1:0)+1)/4; - DlDataDeliveryStatus_flagsT DlDataDeliveryStatus; - DlDataDeliveryStatus.deliveredPdcpSn = 0; - DlDataDeliveryStatus.transmittedPdcpSn= NR_PDCP_PDU_SN>0?1:0; - DlDataDeliveryStatus.pduType = 1; - DlDataDeliveryStatus.drbBufferSize = htonl(RLC_buffer_availability); - memcpy(extensionHeader->buffer+1, &DlDataDeliveryStatus, sizeof(DlDataDeliveryStatus_flagsT)); - uint8_t offset = sizeof(DlDataDeliveryStatus_flagsT)+1; - - if(NR_PDCP_PDU_SN>0){ - extensionHeader->buffer[offset] = (NR_PDCP_PDU_SN >> 16) & 0xff; - extensionHeader->buffer[offset+1] = (NR_PDCP_PDU_SN >> 8) & 0xff; - extensionHeader->buffer[offset+2] = NR_PDCP_PDU_SN & 0xff; - LOG_D(GTPU, "Octets reporting NR_PDCP_PDU_SN, extensionHeader->buffer[offset]: %u, extensionHeader->buffer[offset+1]:%u, extensionHeader->buffer[offset+2]:%u \n", extensionHeader->buffer[offset], extensionHeader->buffer[offset+1],extensionHeader->buffer[offset+2]); - extensionHeader->buffer[offset+3] = 0x00; //Padding octet - offset = offset+3; - } - extensionHeader->buffer[offset] = 0x00; //No more extension headers - /*Total size of DDD_status PDU = size of mandatory part + - * 3 octets for highest transmitted/delivered PDCP SN + - * 1 octet for padding + 1 octet for next extension header type, - * according to TS 38.425: Fig. 5.5.2.2-1 and section 5.5.3.24*/ - extensionHeader->length = 1+sizeof(DlDataDeliveryStatus_flagsT)+ - (NR_PDCP_PDU_SN>0?3:0)+ - (NR_PDCP_PDU_SN>0?1:0)+1; -} - -static void gtpv1uSendDlDeliveryStatus(instance_t instance, gtpv1u_DU_buffer_report_req_t *req){ - ue_id_t ue_id=req->ue_id; - int bearer_id=req->pdusession_id; - pthread_mutex_lock(&globGtp.gtp_lock); - getInstRetVoid(compatInst(instance)); - getUeRetVoid(inst, ue_id); - - auto ptr2=ptrUe->second.bearers.find(bearer_id); - - if ( ptr2 == ptrUe->second.bearers.end() ) { - LOG_D(GTPU,"GTP-U instance: %ld sending a packet to a non existant UE ID:RAB: %lu/%x\n", instance, ue_id, bearer_id); - pthread_mutex_unlock(&globGtp.gtp_lock); - return; - } - - extensionHeader_t *extensionHeader; - extensionHeader = (extensionHeader_t *) calloc(1, sizeof(extensionHeader_t)); - fillDlDeliveryStatusReport(extensionHeader, req->buffer_availability,0); - - LOG_I(GTPU,"[%ld] GTP-U sending DL Data Delivery status to UE ID:RAB:teid %lu/%x/%x, oldseq %d, oldnum %d\n", - instance, ue_id, bearer_id,ptr2->second.teid_outgoing, ptr2->second.seqNum,ptr2->second.npduNum ); - // copy to release the mutex - gtpv1u_bearer_t tmp=ptr2->second; - pthread_mutex_unlock(&globGtp.gtp_lock); - gtpv1uCreateAndSendMsg( - compatInst(instance), tmp.outgoing_ip_addr, tmp.outgoing_port, GTP_GPDU, tmp.teid_outgoing, NULL, 0, false, false, 0, 0, NR_RAN_CONTAINER, extensionHeader->buffer, extensionHeader->length); -} - static void gtpv1uEndTunnel(instance_t instance, gtpv1u_enb_end_marker_req_t *req) { ue_id_t ue_id=req->rnti; @@ -1312,11 +1255,6 @@ void *gtpv1uTask(void *args) { switch (msgType) { // DATA TO BE SENT TO UDP - case GTPV1U_DU_BUFFER_REPORT_REQ:{ - gtpv1uSendDlDeliveryStatus(compatInst(myInstance), >PV1U_DU_BUFFER_REPORT_REQ(message_p)); - } - break; - case TERMINATE_MESSAGE: break; From d1a03c993c904e59b96369d9255f8c3677b80fd2 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 3 Feb 2025 09:28:26 +0100 Subject: [PATCH 350/964] Reformat gtp_itf.cpp --- openair3/ocp-gtpu/gtp_itf.cpp | 854 ++++++++++++++++++---------------- 1 file changed, 442 insertions(+), 412 deletions(-) diff --git a/openair3/ocp-gtpu/gtp_itf.cpp b/openair3/ocp-gtpu/gtp_itf.cpp index 174f75d89b..50c46b809f 100644 --- a/openair3/ocp-gtpu/gtp_itf.cpp +++ b/openair3/ocp-gtpu/gtp_itf.cpp @@ -25,85 +25,85 @@ extern "C" { #pragma pack(1) typedef struct Gtpv1uMsgHeader { - uint8_t PN:1; - uint8_t S:1; - uint8_t E:1; - uint8_t spare:1; - uint8_t PT:1; - uint8_t version:3; + uint8_t PN: 1; + uint8_t S: 1; + uint8_t E: 1; + uint8_t spare: 1; + uint8_t PT: 1; + uint8_t version: 3; uint8_t msgType; uint16_t msgLength; teid_t teid; } __attribute__((packed)) Gtpv1uMsgHeaderT; -//TS 38.425, Figure 5.5.2.2-1 +// TS 38.425, Figure 5.5.2.2-1 typedef struct DlDataDeliveryStatus_flags { - uint8_t LPR:1; //Lost packet report - uint8_t FFI:1; //Final Frame Ind - uint8_t deliveredPdcpSn:1; //Highest Delivered NR PDCP SN Ind - uint8_t transmittedPdcpSn:1; //Highest Transmitted NR PDCP SN Ind - uint8_t pduType:4; //PDU type - uint8_t CR:1; //Cause Report - uint8_t deliveredReTxPdcpSn:1; //Delivered retransmitted NR PDCP SN Ind - uint8_t reTxPdcpSn:1; //Retransmitted NR PDCP SN Ind - uint8_t DRI:1; //Data Rate Indication - uint8_t deliveredPdcpSnRange:1; //Delivered NR PDCP SN Range Ind - uint8_t spare:3; - uint32_t drbBufferSize; //Desired buffer size for the data radio bearer + uint8_t LPR: 1; // Lost packet report + uint8_t FFI: 1; // Final Frame Ind + uint8_t deliveredPdcpSn: 1; // Highest Delivered NR PDCP SN Ind + uint8_t transmittedPdcpSn: 1; // Highest Transmitted NR PDCP SN Ind + uint8_t pduType: 4; // PDU type + uint8_t CR: 1; // Cause Report + uint8_t deliveredReTxPdcpSn: 1; // Delivered retransmitted NR PDCP SN Ind + uint8_t reTxPdcpSn: 1; // Retransmitted NR PDCP SN Ind + uint8_t DRI: 1; // Data Rate Indication + uint8_t deliveredPdcpSnRange: 1; // Delivered NR PDCP SN Range Ind + uint8_t spare: 3; + uint32_t drbBufferSize; // Desired buffer size for the data radio bearer } __attribute__((packed)) DlDataDeliveryStatus_flagsT; typedef struct Gtpv1uMsgHeaderOptFields { uint8_t seqNum1Oct; uint8_t seqNum2Oct; uint8_t NPDUNum; - uint8_t NextExtHeaderType; + uint8_t NextExtHeaderType; } __attribute__((packed)) Gtpv1uMsgHeaderOptFieldsT; #define DL_PDU_SESSION_INFORMATION 0 #define UL_PDU_SESSION_INFORMATION 1 - typedef struct PDUSessionContainer { - uint8_t spare:4; - uint8_t PDU_type:4; - uint8_t QFI:6; - uint8_t Reflective_QoS_activation:1; - uint8_t Paging_Policy_Indicator:1; +typedef struct PDUSessionContainer { + uint8_t spare: 4; + uint8_t PDU_type: 4; + uint8_t QFI: 6; + uint8_t Reflective_QoS_activation: 1; + uint8_t Paging_Policy_Indicator: 1; } __attribute__((packed)) PDUSessionContainerT; typedef struct Gtpv1uExtHeader { uint8_t ExtHeaderLen; PDUSessionContainerT pdusession_cntr; uint8_t NextExtHeaderType; -}__attribute__((packed)) Gtpv1uExtHeaderT; +} __attribute__((packed)) Gtpv1uExtHeaderT; #pragma pack() // TS 29.281, fig 5.2.1-3 -#define PDU_SESSION_CONTAINER (0x85) -#define NR_RAN_CONTAINER (0x84) +#define PDU_SESSION_CONTAINER (0x85) +#define NR_RAN_CONTAINER (0x84) // TS 29.281, 5.2.1 -#define EXT_HDR_LNTH_OCTET_UNITS (4) -#define NO_MORE_EXT_HDRS (0) +#define EXT_HDR_LNTH_OCTET_UNITS (4) +#define NO_MORE_EXT_HDRS (0) // TS 29.060, table 7.1 defines the possible message types // here are all the possible messages (3GPP R16) -#define GTP_ECHO_REQ (1) -#define GTP_ECHO_RSP (2) -#define GTP_ERROR_INDICATION (26) -#define GTP_SUPPORTED_EXTENSION_HEADER_INDICATION (31) -#define GTP_END_MARKER (254) -#define GTP_GPDU (255) +#define GTP_ECHO_REQ (1) +#define GTP_ECHO_RSP (2) +#define GTP_ERROR_INDICATION (26) +#define GTP_SUPPORTED_EXTENSION_HEADER_INDICATION (31) +#define GTP_END_MARKER (254) +#define GTP_GPDU (255) typedef struct gtpv1u_bearer_s { /* TEID used in dl and ul */ - teid_t teid_incoming; ///< eNB TEID - teid_t teid_outgoing; ///< Remote TEID - in_addr_t outgoing_ip_addr; + teid_t teid_incoming; ///< eNB TEID + teid_t teid_outgoing; ///< Remote TEID + in_addr_t outgoing_ip_addr; struct in6_addr outgoing_ip6_addr; - tcp_udp_port_t outgoing_port; - uint16_t seqNum; - uint8_t npduNum; + tcp_udp_port_t outgoing_port; + uint16_t seqNum; + uint8_t npduNum; int outgoing_qfi; } gtpv1u_bearer_t; @@ -131,24 +131,27 @@ class gtpEndPoint { // we use the same port number for source and destination address // this allow using non standard gtp port number (different from 2152) // and so, for example tu run 4G and 5G cores on one system - tcp_udp_port_t get_dstport() { + tcp_udp_port_t get_dstport() + { return (tcp_udp_port_t)atol(addr.destinationService); } }; class gtpEndPoints { public: - pthread_mutex_t gtp_lock=PTHREAD_MUTEX_INITIALIZER; + pthread_mutex_t gtp_lock = PTHREAD_MUTEX_INITIALIZER; // the instance id will be the Linux socket handler, as this is uniq map instances; map te2ue_mapping; - gtpEndPoints() { + gtpEndPoints() + { unsigned int seed; fill_random(&seed, sizeof(seed)); srandom(seed); } - ~gtpEndPoints() { + ~gtpEndPoints() + { // automatically close all sockets on quit for (const auto &p : instances) close(p.first); @@ -158,7 +161,8 @@ class gtpEndPoints { static gtpEndPoints globGtp; // note TEid 0 is reserved for specific usage: echo req/resp, error and supported extensions -static teid_t gtpv1uNewTeid(void) { +static teid_t gtpv1uNewTeid(void) +{ #ifdef GTPV1U_LINEAR_TEID_ALLOCATION g_gtpv1u_teid = g_gtpv1u_teid + 1; return g_gtpv1u_teid; @@ -167,46 +171,45 @@ static teid_t gtpv1uNewTeid(void) { #endif } -instance_t legacyInstanceMapping=0; -#define compatInst(a) ((a)==0 || (a)==INSTANCE_DEFAULT ? legacyInstanceMapping:a) +instance_t legacyInstanceMapping = 0; +#define compatInst(a) ((a) == 0 || (a) == INSTANCE_DEFAULT ? legacyInstanceMapping : a) -#define getInstRetVoid(insT) \ - auto instChk=globGtp.instances.find(compatInst(insT)); \ - if (instChk == globGtp.instances.end()) { \ - LOG_E(GTPU,"try to get a gtp-u not existing output\n"); \ - pthread_mutex_unlock(&globGtp.gtp_lock); \ - return; \ - } \ - gtpEndPoint * inst=&instChk->second; - -#define getInstRetInt(insT) \ - auto instChk=globGtp.instances.find(compatInst(insT)); \ - if (instChk == globGtp.instances.end()) { \ - LOG_E(GTPU,"try to get a gtp-u not existing output\n"); \ - pthread_mutex_unlock(&globGtp.gtp_lock); \ - return GTPNOK; \ - } \ - gtpEndPoint * inst=&instChk->second; +#define getInstRetVoid(insT) \ + auto instChk = globGtp.instances.find(compatInst(insT)); \ + if (instChk == globGtp.instances.end()) { \ + LOG_E(GTPU, "try to get a gtp-u not existing output\n"); \ + pthread_mutex_unlock(&globGtp.gtp_lock); \ + return; \ + } \ + gtpEndPoint *inst = &instChk->second; +#define getInstRetInt(insT) \ + auto instChk = globGtp.instances.find(compatInst(insT)); \ + if (instChk == globGtp.instances.end()) { \ + LOG_E(GTPU, "try to get a gtp-u not existing output\n"); \ + pthread_mutex_unlock(&globGtp.gtp_lock); \ + return GTPNOK; \ + } \ + gtpEndPoint *inst = &instChk->second; -#define getUeRetVoid(insT, Ue) \ - auto ptrUe=insT->ue2te_mapping.find(Ue); \ - \ - if ( ptrUe==insT->ue2te_mapping.end() ) { \ +#define getUeRetVoid(insT, Ue) \ + auto ptrUe = insT->ue2te_mapping.find(Ue); \ + \ + if (ptrUe == insT->ue2te_mapping.end()) { \ LOG_E(GTPU, "[%ld] %s failed: while getting ue id %ld in hashtable ue_mapping\n", instance, __func__, ue_id); \ - pthread_mutex_unlock(&globGtp.gtp_lock); \ - return; \ + pthread_mutex_unlock(&globGtp.gtp_lock); \ + return; \ } - -#define getUeRetInt(insT, Ue) \ - auto ptrUe=insT->ue2te_mapping.find(Ue); \ - \ - if ( ptrUe==insT->ue2te_mapping.end() ) { \ + +#define getUeRetInt(insT, Ue) \ + auto ptrUe = insT->ue2te_mapping.find(Ue); \ + \ + if (ptrUe == insT->ue2te_mapping.end()) { \ LOG_E(GTPU, "[%ld] %s failed: while getting ue id %ld in hashtable ue_mapping\n", instance, __func__, ue_id); \ - pthread_mutex_unlock(&globGtp.gtp_lock); \ - return GTPNOK; \ + pthread_mutex_unlock(&globGtp.gtp_lock); \ + return GTPNOK; \ } - + #define HDR_MAX 256 // 256 is supposed to be larger than any gtp header static int gtpv1uCreateAndSendMsg(int h, uint32_t peerIp, @@ -221,29 +224,30 @@ static int gtpv1uCreateAndSendMsg(int h, int npduNum, int extHdrType, uint8_t *extensionHeader_buffer, - uint8_t extensionHeader_length) { + uint8_t extensionHeader_length) +{ LOG_D(GTPU, "Peer IP:%u peer port:%u outgoing teid:%u \n", peerIp, peerPort, teid); DevAssert(msgLen + HDR_MAX < 65536); // maximum size of UDP packet - uint8_t buffer[msgLen+HDR_MAX]; - uint8_t *curPtr=buffer; - Gtpv1uMsgHeaderT *msgHdr = (Gtpv1uMsgHeaderT *)buffer ; + uint8_t buffer[msgLen + HDR_MAX]; + uint8_t *curPtr = buffer; + Gtpv1uMsgHeaderT *msgHdr = (Gtpv1uMsgHeaderT *)buffer; // N should be 0 for us (it was used only in 2G and 3G) - msgHdr->PN=npduNumFlag; - msgHdr->S=seqNumFlag; + msgHdr->PN = npduNumFlag; + msgHdr->S = seqNumFlag; msgHdr->E = extHdrType != NO_MORE_EXT_HDRS; - msgHdr->spare=0; - //PT=0 is for GTP' TS 32.295 (charging) - msgHdr->PT=1; - msgHdr->version=1; - msgHdr->msgType=msgType; - msgHdr->teid=htonl(teid); + msgHdr->spare = 0; + // PT=0 is for GTP' TS 32.295 (charging) + msgHdr->PT = 1; + msgHdr->version = 1; + msgHdr->msgType = msgType; + msgHdr->teid = htonl(teid); - curPtr+=sizeof(Gtpv1uMsgHeaderT); + curPtr += sizeof(Gtpv1uMsgHeaderT); if (seqNumFlag || (extHdrType != NO_MORE_EXT_HDRS) || npduNumFlag) { *(uint16_t *)curPtr = seqNumFlag ? seqNum : 0x0000; - curPtr+=sizeof(uint16_t); + curPtr += sizeof(uint16_t); *(uint8_t *)curPtr = npduNumFlag ? npduNum : 0x00; curPtr++; *(uint8_t *)curPtr = extHdrType; @@ -255,7 +259,10 @@ static int gtpv1uCreateAndSendMsg(int h, if (extensionHeader_length > 0) { memcpy(curPtr, extensionHeader_buffer, extensionHeader_length); curPtr += extensionHeader_length; - LOG_D(GTPU, "Extension Header for DDD added. The length is: %d, extension header type is: %x \n", extensionHeader_length, *((uint8_t *)(buffer + 11))); + LOG_D(GTPU, + "Extension Header for DDD added. The length is: %d, extension header type is: %x \n", + extensionHeader_length, + *((uint8_t *)(buffer + 11))); extHdrType = extensionHeader_buffer[extensionHeader_length - 1]; LOG_D(GTPU, "Next extension header type is: %x \n", *((uint8_t *)(buffer + 11))); } else { @@ -263,28 +270,34 @@ static int gtpv1uCreateAndSendMsg(int h, } } - if (Msg!= NULL){ + if (Msg != NULL) { memcpy(curPtr, Msg, msgLen); - curPtr+=msgLen; + curPtr += msgLen; } - msgHdr->msgLength = htons(curPtr-(buffer+sizeof(Gtpv1uMsgHeaderT))); - AssertFatal(curPtr-(buffer+msgLen) < HDR_MAX, "fixed max size of all headers too short"); + msgHdr->msgLength = htons(curPtr - (buffer + sizeof(Gtpv1uMsgHeaderT))); + AssertFatal(curPtr - (buffer + msgLen) < HDR_MAX, "fixed max size of all headers too short"); // Fix me: add IPv6 support, using flag ipVersion - struct sockaddr_in to= {0}; - to.sin_family = AF_INET; - to.sin_port = htons(peerPort); - to.sin_addr.s_addr = peerIp ; - LOG_D(GTPU,"sending packet size: %ld to %s\n",curPtr-buffer, inet_ntoa(to.sin_addr) ); + struct sockaddr_in to = {0}; + to.sin_family = AF_INET; + to.sin_port = htons(peerPort); + to.sin_addr.s_addr = peerIp; + LOG_D(GTPU, "sending packet size: %ld to %s\n", curPtr - buffer, inet_ntoa(to.sin_addr)); int ret; - if ((ret=sendto(h, (void *)buffer, curPtr-buffer, 0,(struct sockaddr *)&to, sizeof(to) )) != curPtr-buffer ) { - LOG_E(GTPU, "[SD %d] Failed to send data to " IPV4_ADDR " on port %d, buffer size %lu, ret: %d, errno: %d\n", - h, IPV4_ADDR_FORMAT(peerIp), peerPort, curPtr-buffer, ret, errno); + if ((ret = sendto(h, (void *)buffer, curPtr - buffer, 0, (struct sockaddr *)&to, sizeof(to))) != curPtr - buffer) { + LOG_E(GTPU, + "[SD %d] Failed to send data to " IPV4_ADDR " on port %d, buffer size %lu, ret: %d, errno: %d\n", + h, + IPV4_ADDR_FORMAT(peerIp), + peerPort, + curPtr - buffer, + ret, + errno); return GTPNOK; } - return !GTPNOK; + return !GTPNOK; } void gtpv1uSendDirect(instance_t instance, @@ -371,99 +384,104 @@ void gtpv1uSendDirect(instance_t instance, static void gtpv1uEndTunnel(instance_t instance, gtpv1u_enb_end_marker_req_t *req) { - ue_id_t ue_id=req->rnti; - int bearer_id=req->rab_id; + ue_id_t ue_id = req->rnti; + int bearer_id = req->rab_id; pthread_mutex_lock(&globGtp.gtp_lock); getInstRetVoid(compatInst(instance)); getUeRetVoid(inst, ue_id); - auto ptr2=ptrUe->second.bearers.find(bearer_id); + auto ptr2 = ptrUe->second.bearers.find(bearer_id); - if ( ptr2 == ptrUe->second.bearers.end() ) { - LOG_E(GTPU,"[%ld] GTP-U sending a packet to a non existant UE:RAB: %lx/%x\n", instance, ue_id, bearer_id); + if (ptr2 == ptrUe->second.bearers.end()) { + LOG_E(GTPU, "[%ld] GTP-U sending a packet to a non existant UE:RAB: %lx/%x\n", instance, ue_id, bearer_id); pthread_mutex_unlock(&globGtp.gtp_lock); return; } - LOG_D(GTPU,"[%ld] sending a end packet packet to UE:RAB:teid %lx/%x/%x\n", - instance, ue_id, bearer_id,ptr2->second.teid_outgoing); - gtpv1u_bearer_t tmp=ptr2->second; + LOG_D(GTPU, + "[%ld] sending a end packet packet to UE:RAB:teid %lx/%x/%x\n", + instance, + ue_id, + bearer_id, + ptr2->second.teid_outgoing); + gtpv1u_bearer_t tmp = ptr2->second; pthread_mutex_unlock(&globGtp.gtp_lock); - Gtpv1uMsgHeaderT msgHdr; + Gtpv1uMsgHeaderT msgHdr; // N should be 0 for us (it was used only in 2G and 3G) - msgHdr.PN=0; - msgHdr.S=0; - msgHdr.E=0; - msgHdr.spare=0; - //PT=0 is for GTP' TS 32.295 (charging) - msgHdr.PT=1; - msgHdr.version=1; - msgHdr.msgType=GTP_END_MARKER; - msgHdr.msgLength=htons(0); - msgHdr.teid=htonl(tmp.teid_outgoing); + msgHdr.PN = 0; + msgHdr.S = 0; + msgHdr.E = 0; + msgHdr.spare = 0; + // PT=0 is for GTP' TS 32.295 (charging) + msgHdr.PT = 1; + msgHdr.version = 1; + msgHdr.msgType = GTP_END_MARKER; + msgHdr.msgLength = htons(0); + msgHdr.teid = htonl(tmp.teid_outgoing); // Fix me: add IPv6 support, using flag ipVersion - static struct sockaddr_in to= {0}; - to.sin_family = AF_INET; - to.sin_port = htons(tmp.outgoing_port); + static struct sockaddr_in to = {0}; + to.sin_family = AF_INET; + to.sin_port = htons(tmp.outgoing_port); to.sin_addr.s_addr = tmp.outgoing_ip_addr; char ip4[INET_ADDRSTRLEN]; - //char ip6[INET6_ADDRSTRLEN]; - LOG_D(GTPU,"[%ld] sending end packet to %s\n", instance, inet_ntoa(to.sin_addr) ); + // char ip6[INET6_ADDRSTRLEN]; + LOG_D(GTPU, "[%ld] sending end packet to %s\n", instance, inet_ntoa(to.sin_addr)); - if (sendto(compatInst(instance), (void *)&msgHdr, sizeof(msgHdr), 0,(struct sockaddr *)&to, sizeof(to) ) != sizeof(msgHdr)) { + if (sendto(compatInst(instance), (void *)&msgHdr, sizeof(msgHdr), 0, (struct sockaddr *)&to, sizeof(to)) != sizeof(msgHdr)) { LOG_E(GTPU, "[%ld] Failed to send data to %s on port %d, buffer size %lu\n", - compatInst(instance), inet_ntop(AF_INET, &tmp.outgoing_ip_addr, ip4, INET_ADDRSTRLEN), tmp.outgoing_port, sizeof(msgHdr)); + compatInst(instance), + inet_ntop(AF_INET, &tmp.outgoing_ip_addr, ip4, INET_ADDRSTRLEN), + tmp.outgoing_port, + sizeof(msgHdr)); } } -static int udpServerSocket(openAddr_s addr) { +static int udpServerSocket(openAddr_s addr) +{ LOG_I(GTPU, "Initializing UDP for local address %s with port %s\n", addr.originHost, addr.originService); int status; - struct addrinfo hints= {0}, *servinfo, *p; + struct addrinfo hints = {0}, *servinfo, *p; hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_DGRAM; hints.ai_flags = AI_PASSIVE; if ((status = getaddrinfo(addr.originHost, addr.originService, &hints, &servinfo)) != 0) { - LOG_E(GTPU,"getaddrinfo error: %s\n", gai_strerror(status)); + LOG_E(GTPU, "getaddrinfo error: %s\n", gai_strerror(status)); return -1; } - int sockfd=-1; + int sockfd = -1; // loop through all the results and bind to the first we can - for(p = servinfo; p != NULL; p = p->ai_next) { - if ((sockfd = socket(p->ai_family, p->ai_socktype, - p->ai_protocol)) == -1) { - LOG_W(GTPU,"socket: %s\n", strerror(errno)); + for (p = servinfo; p != NULL; p = p->ai_next) { + if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) { + LOG_W(GTPU, "socket: %s\n", strerror(errno)); continue; } if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) { close(sockfd); - LOG_W(GTPU,"bind: %s\n", strerror(errno)); + LOG_W(GTPU, "bind: %s\n", strerror(errno)); continue; } else { // We create the gtp instance on the socket - globGtp.instances[sockfd].addr=addr; + globGtp.instances[sockfd].addr = addr; if (p->ai_family == AF_INET) { - struct sockaddr_in *ipv4=(struct sockaddr_in *)p->ai_addr; - memcpy(globGtp.instances[sockfd].foundAddr, - &ipv4->sin_addr.s_addr, sizeof(ipv4->sin_addr.s_addr)); - globGtp.instances[sockfd].foundAddrLen=sizeof(ipv4->sin_addr.s_addr); - globGtp.instances[sockfd].ipVersion=4; + struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr; + memcpy(globGtp.instances[sockfd].foundAddr, &ipv4->sin_addr.s_addr, sizeof(ipv4->sin_addr.s_addr)); + globGtp.instances[sockfd].foundAddrLen = sizeof(ipv4->sin_addr.s_addr); + globGtp.instances[sockfd].ipVersion = 4; break; } else if (p->ai_family == AF_INET6) { - LOG_W(GTPU,"Local address is IP v6\n"); - struct sockaddr_in6 *ipv6=(struct sockaddr_in6 *)p->ai_addr; - memcpy(globGtp.instances[sockfd].foundAddr, - &ipv6->sin6_addr.s6_addr, sizeof(ipv6->sin6_addr.s6_addr)); - globGtp.instances[sockfd].foundAddrLen=sizeof(ipv6->sin6_addr.s6_addr); - globGtp.instances[sockfd].ipVersion=6; + LOG_W(GTPU, "Local address is IP v6\n"); + struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr; + memcpy(globGtp.instances[sockfd].foundAddr, &ipv6->sin6_addr.s6_addr, sizeof(ipv6->sin6_addr.s6_addr)); + globGtp.instances[sockfd].foundAddrLen = sizeof(ipv6->sin6_addr.s6_addr); + globGtp.instances[sockfd].ipVersion = 6; } else - AssertFatal(false,"Local address is not IPv4 or IPv6"); + AssertFatal(false, "Local address is not IPv4 or IPv6"); } break; // if we get here, we must have connected successfully @@ -473,46 +491,61 @@ static int udpServerSocket(openAddr_s addr) { if (p == NULL) { // looped off the end of the list with no successful bind - LOG_E(GTPU,"failed to bind socket: %s %s \n", addr.originHost, addr.originService); + LOG_E(GTPU, "failed to bind socket: %s %s \n", addr.originHost, addr.originService); return -1; } - int sendbuff = 1000*1000*10; - AssertFatal(0==setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &sendbuff, sizeof(sendbuff)),""); - LOG_D(GTPU,"[%d] Created listener for paquets to: %s:%s, send buffer size: %d\n", sockfd, addr.originHost, addr.originService,sendbuff); + int sendbuff = 1000 * 1000 * 10; + AssertFatal(0 == setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &sendbuff, sizeof(sendbuff)), ""); + LOG_D(GTPU, + "[%d] Created listener for paquets to: %s:%s, send buffer size: %d\n", + sockfd, + addr.originHost, + addr.originService, + sendbuff); return sockfd; } -instance_t gtpv1Init(openAddr_t context) { +instance_t gtpv1Init(openAddr_t context) +{ pthread_mutex_lock(&globGtp.gtp_lock); - int id=udpServerSocket(context); + int id = udpServerSocket(context); - if (id>=0) { + if (id >= 0) { itti_subscribe_event_fd(TASK_GTPV1_U, id); } else - LOG_E(GTPU,"can't create GTP-U instance\n"); + LOG_E(GTPU, "can't create GTP-U instance\n"); pthread_mutex_unlock(&globGtp.gtp_lock); LOG_I(GTPU, "Created gtpu instance id: %d\n", id); return id; } -void GtpuUpdateTunnelOutgoingAddressAndTeid(instance_t instance, ue_id_t ue_id, ebi_t bearer_id, in_addr_t newOutgoingAddr, teid_t newOutgoingTeid) { +void GtpuUpdateTunnelOutgoingAddressAndTeid(instance_t instance, + ue_id_t ue_id, + ebi_t bearer_id, + in_addr_t newOutgoingAddr, + teid_t newOutgoingTeid) +{ pthread_mutex_lock(&globGtp.gtp_lock); getInstRetVoid(compatInst(instance)); getUeRetVoid(inst, ue_id); - auto ptr2=ptrUe->second.bearers.find(bearer_id); + auto ptr2 = ptrUe->second.bearers.find(bearer_id); - if ( ptr2 == ptrUe->second.bearers.end() ) { - LOG_E(GTPU,"[%ld] Update tunnel for a existing ue id %lu, but wrong bearer_id %u\n", instance, ue_id, bearer_id); + if (ptr2 == ptrUe->second.bearers.end()) { + LOG_E(GTPU, "[%ld] Update tunnel for a existing ue id %lu, but wrong bearer_id %u\n", instance, ue_id, bearer_id); pthread_mutex_unlock(&globGtp.gtp_lock); return; } ptr2->second.outgoing_ip_addr = newOutgoingAddr; ptr2->second.teid_outgoing = newOutgoingTeid; - LOG_I(GTPU, "[%ld] Tunnel Outgoing TEID updated to %x and address to %x\n", instance, ptr2->second.teid_outgoing, ptr2->second.outgoing_ip_addr); + LOG_I(GTPU, + "[%ld] Tunnel Outgoing TEID updated to %x and address to %x\n", + instance, + ptr2->second.teid_outgoing, + ptr2->second.outgoing_ip_addr); pthread_mutex_unlock(&globGtp.gtp_lock); return; } @@ -526,21 +559,22 @@ teid_t newGtpuCreateTunnel(instance_t instance, transport_layer_addr_t remoteAddr, int port, gtpCallback callBack, - gtpCallbackSDAP callBackSDAP) { + gtpCallbackSDAP callBackSDAP) +{ pthread_mutex_lock(&globGtp.gtp_lock); getInstRetInt(compatInst(instance)); - auto it=inst->ue2te_mapping.find(ue_id); + auto it = inst->ue2te_mapping.find(ue_id); - if ( it != inst->ue2te_mapping.end() && it->second.bearers.find(outgoing_bearer_id) != it->second.bearers.end()) { - LOG_W(GTPU,"[%ld] Create a config for a already existing GTP tunnel (ue id %lu)\n", instance, ue_id); + if (it != inst->ue2te_mapping.end() && it->second.bearers.find(outgoing_bearer_id) != it->second.bearers.end()) { + LOG_W(GTPU, "[%ld] Create a config for a already existing GTP tunnel (ue id %lu)\n", instance, ue_id); inst->ue2te_mapping.erase(it); } - teid_t incoming_teid=gtpv1uNewTeid(); + teid_t incoming_teid = gtpv1uNewTeid(); while (globGtp.te2ue_mapping.find(incoming_teid) != globGtp.te2ue_mapping.end()) { LOG_W(GTPU, "[%ld] generated a random Teid that exists, re-generating (%x)\n", instance, incoming_teid); - incoming_teid=gtpv1uNewTeid(); + incoming_teid = gtpv1uNewTeid(); }; globGtp.te2ue_mapping[incoming_teid].ue_id = ue_id; @@ -550,34 +584,31 @@ teid_t newGtpuCreateTunnel(instance_t instance, globGtp.te2ue_mapping[incoming_teid].callBackSDAP = callBackSDAP; globGtp.te2ue_mapping[incoming_teid].pdusession_id = (uint8_t)outgoing_bearer_id; - gtpv1u_bearer_t *tmp=&inst->ue2te_mapping[ue_id].bearers[outgoing_bearer_id]; + gtpv1u_bearer_t *tmp = &inst->ue2te_mapping[ue_id].bearers[outgoing_bearer_id]; int addrs_length_in_bytes = remoteAddr.length / 8; switch (addrs_length_in_bytes) { case 4: - memcpy(&tmp->outgoing_ip_addr,remoteAddr.buffer,4); + memcpy(&tmp->outgoing_ip_addr, remoteAddr.buffer, 4); break; case 16: - memcpy(tmp->outgoing_ip6_addr.s6_addr,remoteAddr.buffer, - 16); + memcpy(tmp->outgoing_ip6_addr.s6_addr, remoteAddr.buffer, 16); break; case 20: - memcpy(&tmp->outgoing_ip_addr,remoteAddr.buffer,4); - memcpy(tmp->outgoing_ip6_addr.s6_addr, - remoteAddr.buffer+4, - 16); + memcpy(&tmp->outgoing_ip_addr, remoteAddr.buffer, 4); + memcpy(tmp->outgoing_ip6_addr.s6_addr, remoteAddr.buffer + 4, 16); default: AssertFatal(false, "SGW Address size impossible"); } tmp->teid_incoming = incoming_teid; - tmp->outgoing_port=port; - tmp->teid_outgoing= outgoing_teid; - tmp->outgoing_qfi=outgoing_qfi; + tmp->outgoing_port = port; + tmp->teid_outgoing = outgoing_teid; + tmp->outgoing_qfi = outgoing_qfi; pthread_mutex_unlock(&globGtp.gtp_lock); char ip4[INET_ADDRSTRLEN]; char ip6[INET6_ADDRSTRLEN]; @@ -593,28 +624,29 @@ teid_t newGtpuCreateTunnel(instance_t instance, } int gtpv1u_create_s1u_tunnel(instance_t instance, - const gtpv1u_enb_create_tunnel_req_t *create_tunnel_req, + const gtpv1u_enb_create_tunnel_req_t *create_tunnel_req, gtpv1u_enb_create_tunnel_resp_t *create_tunnel_resp, gtpCallback callBack) { - LOG_D(GTPU, "[%ld] Start create tunnels for UE ID %u, num_tunnels %d, sgw_S1u_teid %x\n", + LOG_D(GTPU, + "[%ld] Start create tunnels for UE ID %u, num_tunnels %d, sgw_S1u_teid %x\n", instance, create_tunnel_req->rnti, create_tunnel_req->num_tunnels, create_tunnel_req->sgw_S1u_teid[0]); pthread_mutex_lock(&globGtp.gtp_lock); getInstRetInt(compatInst(instance)); - - tcp_udp_port_t dstport=inst->get_dstport(); + + tcp_udp_port_t dstport = inst->get_dstport(); uint8_t addr[inst->foundAddrLen]; memcpy(addr, inst->foundAddr, inst->foundAddrLen); pthread_mutex_unlock(&globGtp.gtp_lock); - + for (int i = 0; i < create_tunnel_req->num_tunnels; i++) { AssertFatal(create_tunnel_req->eps_bearer_id[i] > 4, "From legacy code not clear, seems impossible (bearer=%d)\n", create_tunnel_req->eps_bearer_id[i]); - int incoming_rb_id=create_tunnel_req->eps_bearer_id[i]-4; + int incoming_rb_id = create_tunnel_req->eps_bearer_id[i] - 4; teid_t teid = newGtpuCreateTunnel(compatInst(instance), create_tunnel_req->rnti, incoming_rb_id, @@ -625,24 +657,24 @@ int gtpv1u_create_s1u_tunnel(instance_t instance, dstport, callBack, NULL); - create_tunnel_resp->status=0; - create_tunnel_resp->rnti=create_tunnel_req->rnti; - create_tunnel_resp->num_tunnels=create_tunnel_req->num_tunnels; - create_tunnel_resp->enb_S1u_teid[i]=teid; + create_tunnel_resp->status = 0; + create_tunnel_resp->rnti = create_tunnel_req->rnti; + create_tunnel_resp->num_tunnels = create_tunnel_req->num_tunnels; + create_tunnel_resp->enb_S1u_teid[i] = teid; create_tunnel_resp->eps_bearer_id[i] = create_tunnel_req->eps_bearer_id[i]; - memcpy(create_tunnel_resp->enb_addr.buffer,addr,sizeof(addr)); - create_tunnel_resp->enb_addr.length= sizeof(addr); + memcpy(create_tunnel_resp->enb_addr.buffer, addr, sizeof(addr)); + create_tunnel_resp->enb_addr.length = sizeof(addr); } return !GTPNOK; } -int gtpv1u_update_s1u_tunnel( - const instance_t instance, - const gtpv1u_enb_create_tunnel_req_t *const create_tunnel_req, - const rnti_t prior_rnti -) { - LOG_D(GTPU, "[%ld] Start update tunnels for old RNTI %x, new RNTI %x, num_tunnels %d, sgw_S1u_teid %x, eps_bearer_id %x\n", +int gtpv1u_update_s1u_tunnel(const instance_t instance, + const gtpv1u_enb_create_tunnel_req_t *const create_tunnel_req, + const rnti_t prior_rnti) +{ + LOG_D(GTPU, + "[%ld] Start update tunnels for old RNTI %x, new RNTI %x, num_tunnels %d, sgw_S1u_teid %x, eps_bearer_id %x\n", instance, prior_rnti, create_tunnel_req->rnti, @@ -652,22 +684,28 @@ int gtpv1u_update_s1u_tunnel( pthread_mutex_lock(&globGtp.gtp_lock); getInstRetInt(compatInst(instance)); - if ( inst->ue2te_mapping.find(create_tunnel_req->rnti) == inst->ue2te_mapping.end() ) { - LOG_E(GTPU,"[%ld] Update not already existing tunnel (new rnti %x, old rnti %x)\n", - instance, create_tunnel_req->rnti, prior_rnti); + if (inst->ue2te_mapping.find(create_tunnel_req->rnti) == inst->ue2te_mapping.end()) { + LOG_E(GTPU, + "[%ld] Update not already existing tunnel (new rnti %x, old rnti %x)\n", + instance, + create_tunnel_req->rnti, + prior_rnti); } - auto it=inst->ue2te_mapping.find(prior_rnti); + auto it = inst->ue2te_mapping.find(prior_rnti); - if ( it != inst->ue2te_mapping.end() ) { + if (it != inst->ue2te_mapping.end()) { pthread_mutex_unlock(&globGtp.gtp_lock); - AssertFatal(false, "logic bug: update of non-existing tunnel (new ue id %u, old ue id %u)\n", create_tunnel_req->rnti, prior_rnti); + AssertFatal(false, + "logic bug: update of non-existing tunnel (new ue id %u, old ue id %u)\n", + create_tunnel_req->rnti, + prior_rnti); /* we don't know if we need 4G or 5G PDCP and can therefore not create a * new tunnel */ return 0; } - inst->ue2te_mapping[create_tunnel_req->rnti]=it->second; + inst->ue2te_mapping[create_tunnel_req->rnti] = it->second; inst->ue2te_mapping.erase(it); pthread_mutex_unlock(&globGtp.gtp_lock); return 0; @@ -679,7 +717,8 @@ int gtpv1u_create_ngu_tunnel(const instance_t instance, gtpCallback callBack, gtpCallbackSDAP callBackSDAP) { - LOG_D(GTPU, "[%ld] Start create tunnels for ue id %lu, num_tunnels %d, sgw_S1u_teid %x\n", + LOG_D(GTPU, + "[%ld] Start create tunnels for ue id %lu, num_tunnels %d, sgw_S1u_teid %x\n", instance, create_tunnel_req->ue_id, create_tunnel_req->num_tunnels, @@ -702,12 +741,12 @@ int gtpv1u_create_ngu_tunnel(const instance_t instance, dstport, callBack, callBackSDAP); - create_tunnel_resp->status=0; - create_tunnel_resp->ue_id=create_tunnel_req->ue_id; - create_tunnel_resp->num_tunnels=create_tunnel_req->num_tunnels; - create_tunnel_resp->gnb_NGu_teid[i]=teid; - memcpy(create_tunnel_resp->gnb_addr.buffer,addr,sizeof(addr)); - create_tunnel_resp->gnb_addr.length= sizeof(addr); + create_tunnel_resp->status = 0; + create_tunnel_resp->ue_id = create_tunnel_req->ue_id; + create_tunnel_resp->num_tunnels = create_tunnel_req->num_tunnels; + create_tunnel_resp->gnb_NGu_teid[i] = teid; + memcpy(create_tunnel_resp->gnb_addr.buffer, addr, sizeof(addr)); + create_tunnel_resp->gnb_addr.length = sizeof(addr); create_tunnel_resp->pdusession_id[i] = create_tunnel_req->pdusession_id[i]; } @@ -742,11 +781,11 @@ int gtpv1u_update_ue_id(const instance_t instanceP, ue_id_t old_ue_id, ue_id_t n return !GTPNOK; } -int gtpv1u_create_x2u_tunnel( - const instance_t instanceP, - const gtpv1u_enb_create_x2u_tunnel_req_t *const create_tunnel_req_pP, - gtpv1u_enb_create_x2u_tunnel_resp_t *const create_tunnel_resp_pP) { - AssertFatal( false, "to be developped\n"); +int gtpv1u_create_x2u_tunnel(const instance_t instanceP, + const gtpv1u_enb_create_x2u_tunnel_req_t *const create_tunnel_req_pP, + gtpv1u_enb_create_x2u_tunnel_resp_t *const create_tunnel_resp_pP) +{ + AssertFatal(false, "to be developped\n"); } int newGtpuDeleteOneTunnel(instance_t instance, ue_id_t ue_id, int rb_id) @@ -770,23 +809,21 @@ int newGtpuDeleteOneTunnel(instance_t instance, ue_id_t ue_id, int rb_id) ue_it->second.bearers.erase(rb_id); pthread_mutex_unlock(&globGtp.gtp_lock); LOG_I(GTPU, "Deleted tunnel TEID %d (RB %d) for ue id %ld, remaining bearers:\n", teid, rb_id, ue_id); - for (auto b: ue_it->second.bearers) + for (auto b : ue_it->second.bearers) LOG_I(GTPU, "bearer %ld\n", b.first); return !GTPNOK; } -int newGtpuDeleteAllTunnels(instance_t instance, ue_id_t ue_id) { - LOG_D(GTPU, "[%ld] Start delete tunnels for ue id %lu\n", - instance, ue_id); +int newGtpuDeleteAllTunnels(instance_t instance, ue_id_t ue_id) +{ + LOG_D(GTPU, "[%ld] Start delete tunnels for ue id %lu\n", instance, ue_id); pthread_mutex_lock(&globGtp.gtp_lock); getInstRetInt(compatInst(instance)); getUeRetInt(inst, ue_id); - int nb=0; + int nb = 0; - for (auto j=ptrUe->second.bearers.begin(); - j!=ptrUe->second.bearers.end(); - ++j) { + for (auto j = ptrUe->second.bearers.begin(); j != ptrUe->second.bearers.end(); ++j) { globGtp.te2ue_mapping.erase(j->second.teid_incoming); nb++; } @@ -797,8 +834,8 @@ int newGtpuDeleteAllTunnels(instance_t instance, ue_id_t ue_id) { return !GTPNOK; } -int gtpv1u_delete_s1u_tunnel( const instance_t instance, - const gtpv1u_enb_delete_tunnel_req_t *const req_pP) { +int gtpv1u_delete_s1u_tunnel(const instance_t instance, const gtpv1u_enb_delete_tunnel_req_t *const req_pP) +{ LOG_D(GTPU, "[%ld] Start delete tunnels for RNTI %x\n", instance, req_pP->rnti); pthread_mutex_lock(&globGtp.gtp_lock); auto inst = &globGtp.instances[compatInst(instance)]; @@ -842,25 +879,24 @@ int gtpv1u_delete_all_s1u_tunnel(const instance_t instance, const rnti_t rnti) int newGtpuDeleteTunnels(instance_t instance, ue_id_t ue_id, int nbTunnels, int *pdusession_id) { - LOG_D(GTPU, "[%ld] Start delete tunnels for ue id %lu\n", - instance, ue_id); + LOG_D(GTPU, "[%ld] Start delete tunnels for ue id %lu\n", instance, ue_id); pthread_mutex_lock(&globGtp.gtp_lock); getInstRetInt(compatInst(instance)); getUeRetInt(inst, ue_id); - int nb=0; + int nb = 0; - for (int i=0; isecond.bearers.find(pdusession_id[i]); + for (int i = 0; i < nbTunnels; i++) { + auto ptr2 = ptrUe->second.bearers.find(pdusession_id[i]); - if ( ptr2 == ptrUe->second.bearers.end() ) { - LOG_E(GTPU,"[%ld] GTP-U instance: delete of not existing tunnel UE ID:RAB: %ld/%x\n", instance, ue_id, pdusession_id[i]); + if (ptr2 == ptrUe->second.bearers.end()) { + LOG_E(GTPU, "[%ld] GTP-U instance: delete of not existing tunnel UE ID:RAB: %ld/%x\n", instance, ue_id, pdusession_id[i]); } else { globGtp.te2ue_mapping.erase(ptr2->second.teid_incoming); nb++; } } - if (ptrUe->second.bearers.size() == 0 ) + if (ptrUe->second.bearers.size() == 0) // no tunnels on this ue id, erase the ue entry inst->ue2te_mapping.erase(ptrUe); @@ -869,56 +905,60 @@ int newGtpuDeleteTunnels(instance_t instance, ue_id_t ue_id, int nbTunnels, int return !GTPNOK; } -int gtpv1u_delete_x2u_tunnel( const instance_t instanceP, - const gtpv1u_enb_delete_tunnel_req_t *const req_pP) { - LOG_E(GTPU,"x2 tunnel not implemented\n"); +int gtpv1u_delete_x2u_tunnel(const instance_t instanceP, const gtpv1u_enb_delete_tunnel_req_t *const req_pP) +{ + LOG_E(GTPU, "x2 tunnel not implemented\n"); return 0; } -int gtpv1u_delete_ngu_tunnel( const instance_t instance, - gtpv1u_gnb_delete_tunnel_req_t *req) { - return newGtpuDeleteTunnels(instance, req->ue_id, req->num_pdusession, req->pdusession_id); +int gtpv1u_delete_ngu_tunnel(const instance_t instance, gtpv1u_gnb_delete_tunnel_req_t *req) +{ + return newGtpuDeleteTunnels(instance, req->ue_id, req->num_pdusession, req->pdusession_id); } -static int Gtpv1uHandleEchoReq(int h, - uint8_t *msgBuf, - uint32_t msgBufLen, - uint16_t peerPort, - uint32_t peerIp) { - Gtpv1uMsgHeaderT *msgHdr = (Gtpv1uMsgHeaderT *) msgBuf; +static int Gtpv1uHandleEchoReq(int h, uint8_t *msgBuf, uint32_t msgBufLen, uint16_t peerPort, uint32_t peerIp) +{ + Gtpv1uMsgHeaderT *msgHdr = (Gtpv1uMsgHeaderT *)msgBuf; - if ( msgHdr->version != 1 || msgHdr->PT != 1 ) { + if (msgHdr->version != 1 || msgHdr->PT != 1) { LOG_E(GTPU, "[%d] Received a packet that is not GTP header\n", h); return GTPNOK; } - if ( msgHdr->S != 1 ) { + if (msgHdr->S != 1) { LOG_E(GTPU, "[%d] Received a echo request packet with no sequence number \n", h); return GTPNOK; } - uint16_t seq=ntohs(*(uint16_t *)(msgHdr+1)); + uint16_t seq = ntohs(*(uint16_t *)(msgHdr + 1)); LOG_D(GTPU, "[%d] Received a echo request, TEID: %d, seq: %hu\n", h, msgHdr->teid, seq); - uint8_t recovery[2]= {14,0}; - return gtpv1uCreateAndSendMsg(h, peerIp, peerPort, GTP_ECHO_RSP, ntohl(msgHdr->teid), recovery, sizeof recovery, true, false, seq, 0, NO_MORE_EXT_HDRS, NULL, 0); + uint8_t recovery[2] = {14, 0}; + return gtpv1uCreateAndSendMsg(h, + peerIp, + peerPort, + GTP_ECHO_RSP, + ntohl(msgHdr->teid), + recovery, + sizeof recovery, + true, + false, + seq, + 0, + NO_MORE_EXT_HDRS, + NULL, + 0); } -static int Gtpv1uHandleError(int h, - uint8_t *msgBuf, - uint32_t msgBufLen, - uint16_t peerPort, - uint32_t peerIp) { +static int Gtpv1uHandleError(int h, uint8_t *msgBuf, uint32_t msgBufLen, uint16_t peerPort, uint32_t peerIp) +{ LOG_E(GTPU, "Received GTP error indication (error handling is missing/not implemented)\n"); int rc = GTPNOK; return rc; } -static int Gtpv1uHandleSupportedExt(int h, - uint8_t *msgBuf, - uint32_t msgBufLen, - uint16_t peerPort, - uint32_t peerIp) { - LOG_E(GTPU,"Supported extensions to be dev\n"); +static int Gtpv1uHandleSupportedExt(int h, uint8_t *msgBuf, uint32_t msgBufLen, uint16_t peerPort, uint32_t peerIp) +{ + LOG_E(GTPU, "Supported extensions to be dev\n"); int rc = GTPNOK; return rc; } @@ -926,14 +966,11 @@ static int Gtpv1uHandleSupportedExt(int h, // When end marker arrives, we notify the client with buffer size = 0 // The client will likely call "delete tunnel" // nevertheless we don't take the initiative -static int Gtpv1uHandleEndMarker(int h, - uint8_t *msgBuf, - uint32_t msgBufLen, - uint16_t peerPort, - uint32_t peerIp) { - Gtpv1uMsgHeaderT *msgHdr = (Gtpv1uMsgHeaderT *) msgBuf; +static int Gtpv1uHandleEndMarker(int h, uint8_t *msgBuf, uint32_t msgBufLen, uint16_t peerPort, uint32_t peerIp) +{ + Gtpv1uMsgHeaderT *msgHdr = (Gtpv1uMsgHeaderT *)msgBuf; - if ( msgHdr->version != 1 || msgHdr->PT != 1 ) { + if (msgHdr->version != 1 || msgHdr->PT != 1) { LOG_E(GTPU, "[%d] Received a packet that is not GTP header\n", h); return GTPNOK; } @@ -945,7 +982,7 @@ static int Gtpv1uHandleEndMarker(int h, auto tunnel = globGtp.te2ue_mapping.find(ntohl(msgHdr->teid)); if (tunnel == globGtp.te2ue_mapping.end()) { - LOG_E(GTPU,"[%d] Received a incoming packet on unknown teid (%x) Dropping!\n", h, msgHdr->teid); + LOG_E(GTPU, "[%d] Received a incoming packet on unknown teid (%x) Dropping!\n", h, msgHdr->teid); pthread_mutex_unlock(&globGtp.gtp_lock); return GTPNOK; } @@ -962,39 +999,27 @@ static int Gtpv1uHandleEndMarker(int h, ctxt.subframe = 0; ctxt.eNB_index = 0; ctxt.brOption = 0; - const srb_flag_t srb_flag=SRB_FLAG_NO; - const rb_id_t rb_id=tunnel->second.incoming_rb_id; - const mui_t mui=RLC_MUI_UNDEFINED; - const confirm_t confirm=RLC_SDU_CONFIRM_NO; - const pdcp_transmission_mode_t mode=PDCP_TRANSMISSION_MODE_DATA; - const uint32_t sourceL2Id=0; - const uint32_t destinationL2Id=0; + const srb_flag_t srb_flag = SRB_FLAG_NO; + const rb_id_t rb_id = tunnel->second.incoming_rb_id; + const mui_t mui = RLC_MUI_UNDEFINED; + const confirm_t confirm = RLC_SDU_CONFIRM_NO; + const pdcp_transmission_mode_t mode = PDCP_TRANSMISSION_MODE_DATA; + const uint32_t sourceL2Id = 0; + const uint32_t destinationL2Id = 0; pthread_mutex_unlock(&globGtp.gtp_lock); - if ( !tunnel->second.callBack(&ctxt, - srb_flag, - rb_id, - mui, - confirm, - 0, - NULL, - mode, - &sourceL2Id, - &destinationL2Id) ) - LOG_E(GTPU,"[%d] down layer refused incoming packet\n", h); + if (!tunnel->second.callBack(&ctxt, srb_flag, rb_id, mui, confirm, 0, NULL, mode, &sourceL2Id, &destinationL2Id)) + LOG_E(GTPU, "[%d] down layer refused incoming packet\n", h); - LOG_D(GTPU,"[%d] Received END marker packet for: teid:%x\n", h, ntohl(msgHdr->teid)); + LOG_D(GTPU, "[%d] Received END marker packet for: teid:%x\n", h, ntohl(msgHdr->teid)); return !GTPNOK; } -static int Gtpv1uHandleGpdu(int h, - uint8_t *msgBuf, - uint32_t msgBufLen, - uint16_t peerPort, - uint32_t peerIp) { - Gtpv1uMsgHeaderT *msgHdr = (Gtpv1uMsgHeaderT *) msgBuf; +static int Gtpv1uHandleGpdu(int h, uint8_t *msgBuf, uint32_t msgBufLen, uint16_t peerPort, uint32_t peerIp) +{ + Gtpv1uMsgHeaderT *msgHdr = (Gtpv1uMsgHeaderT *)msgBuf; - if ( msgHdr->version != 1 || msgHdr->PT != 1 ) { + if (msgHdr->version != 1 || msgHdr->PT != 1) { LOG_E(GTPU, "[%d] Received a packet that is not GTP header\n", h); return GTPNOK; } @@ -1005,13 +1030,13 @@ static int Gtpv1uHandleGpdu(int h, auto tunnel = globGtp.te2ue_mapping.find(ntohl(msgHdr->teid)); if (tunnel == globGtp.te2ue_mapping.end()) { - LOG_E(GTPU,"[%d] Received a incoming packet on unknown teid (%x) Dropping!\n", h, ntohl(msgHdr->teid)); + LOG_E(GTPU, "[%d] Received a incoming packet on unknown teid (%x) Dropping!\n", h, ntohl(msgHdr->teid)); pthread_mutex_unlock(&globGtp.gtp_lock); return GTPNOK; } /* see TS 29.281 5.1 */ - //Minimum length of GTP-U header if non of the optional fields are present + // Minimum length of GTP-U header if non of the optional fields are present unsigned int offset = sizeof(Gtpv1uMsgHeaderT); int8_t qfi = -1; @@ -1019,7 +1044,7 @@ static int Gtpv1uHandleGpdu(int h, uint32_t NR_PDCP_PDU_SN = 0; /* if E, S, or PN is set then there are 4 more bytes of header */ - if( msgHdr->E || msgHdr->S ||msgHdr->PN) + if (msgHdr->E || msgHdr->S || msgHdr->PN) offset += 4; if (msgHdr->E) { @@ -1030,53 +1055,53 @@ static int Gtpv1uHandleGpdu(int h, extension_header_length = msgBuf[offset]; switch (next_extension_header_type) { case PDU_SESSION_CONTAINER: { - if (offset + sizeof(PDUSessionContainerT) > msgBufLen ) { - LOG_E(GTPU, "gtp-u received header is malformed, ignore gtp packet\n"); - return GTPNOK; - } + if (offset + sizeof(PDUSessionContainerT) > msgBufLen) { + LOG_E(GTPU, "gtp-u received header is malformed, ignore gtp packet\n"); + return GTPNOK; + } PDUSessionContainerT *pdusession_cntr = (PDUSessionContainerT *)(msgBuf + offset + 1); qfi = pdusession_cntr->QFI; rqi = pdusession_cntr->Reflective_QoS_activation; break; } case NR_RAN_CONTAINER: { - if (offset + 1 > msgBufLen ) { - LOG_E(GTPU, "gtp-u received header is malformed, ignore gtp packet\n"); - return GTPNOK; - } - uint8_t PDU_type = (msgBuf[offset+1]>>4) & 0x0f; - if (PDU_type == 0){ //DL USER Data Format - int additional_offset = 6; //Additional offset capturing the first non-mandatory octet (TS 38.425, Figure 5.5.2.1-1) - if(msgBuf[offset+1]>>2 & 0x1){ //DL Discard Blocks flag is present - LOG_I(GTPU, "DL User Data: DL Discard Blocks handling not enabled\n"); - additional_offset = additional_offset + 9; //For the moment ignore + if (offset + 1 > msgBufLen) { + LOG_E(GTPU, "gtp-u received header is malformed, ignore gtp packet\n"); + return GTPNOK; + } + uint8_t PDU_type = (msgBuf[offset + 1] >> 4) & 0x0f; + if (PDU_type == 0) { // DL USER Data Format + int additional_offset = 6; // Additional offset capturing the first non-mandatory octet (TS 38.425, Figure 5.5.2.1-1) + if (msgBuf[offset + 1] >> 2 & 0x1) { // DL Discard Blocks flag is present + LOG_I(GTPU, "DL User Data: DL Discard Blocks handling not enabled\n"); + additional_offset = additional_offset + 9; // For the moment ignore } - if(msgBuf[offset+1]>>1 & 0x1){ //DL Flush flag is present + if (msgBuf[offset + 1] >> 1 & 0x1) { // DL Flush flag is present LOG_I(GTPU, "DL User Data: DL Flush handling not enabled\n"); - additional_offset = additional_offset + 3; //For the moment ignore + additional_offset = additional_offset + 3; // For the moment ignore } - if((msgBuf[offset+2]>>3)& 0x1){ //"Report delivered" enabled (TS 38.425, 5.4) + if ((msgBuf[offset + 2] >> 3) & 0x1) { //"Report delivered" enabled (TS 38.425, 5.4) /*Store the NR PDCP PDU SN for which a delivery status report shall be generated once the *PDU gets forwarded to the lower layers*/ - //NR_PDCP_PDU_SN = msgBuf[offset+6] << 16 | msgBuf[offset+7] << 8 | msgBuf[offset+8]; - NR_PDCP_PDU_SN = msgBuf[offset+additional_offset] << 16 | msgBuf[offset+additional_offset+1] << 8 | msgBuf[offset+additional_offset+2]; - LOG_D(GTPU, " NR_PDCP_PDU_SN: %u \n", NR_PDCP_PDU_SN); + // NR_PDCP_PDU_SN = msgBuf[offset+6] << 16 | msgBuf[offset+7] << 8 | msgBuf[offset+8]; + NR_PDCP_PDU_SN = msgBuf[offset + additional_offset] << 16 | msgBuf[offset + additional_offset + 1] << 8 + | msgBuf[offset + additional_offset + 2]; + LOG_D(GTPU, " NR_PDCP_PDU_SN: %u \n", NR_PDCP_PDU_SN); } - } - else{ + } else { LOG_W(GTPU, "NR-RAN container type: %d not supported \n", PDU_type); } break; } default: LOG_W(GTPU, "unhandled extension 0x%2.2x, skipping\n", next_extension_header_type); - break; + break; } offset += extension_header_length * EXT_HDR_LNTH_OCTET_UNITS; - if (offset > msgBufLen ) { - LOG_E(GTPU, "gtp-u received header is malformed, ignore gtp packet\n"); - return GTPNOK; + if (offset > msgBufLen) { + LOG_E(GTPU, "gtp-u received header is malformed, ignore gtp packet\n"); + return GTPNOK; } next_extension_header_type = msgBuf[offset - 1]; } @@ -1094,51 +1119,43 @@ static int Gtpv1uHandleGpdu(int h, ctxt.subframe = 0; ctxt.eNB_index = 0; ctxt.brOption = 0; - const srb_flag_t srb_flag=SRB_FLAG_NO; - const rb_id_t rb_id=tunnel->second.incoming_rb_id; - const mui_t mui=RLC_MUI_UNDEFINED; - const confirm_t confirm=RLC_SDU_CONFIRM_NO; + const srb_flag_t srb_flag = SRB_FLAG_NO; + const rb_id_t rb_id = tunnel->second.incoming_rb_id; + const mui_t mui = RLC_MUI_UNDEFINED; + const confirm_t confirm = RLC_SDU_CONFIRM_NO; const sdu_size_t sdu_buffer_size = msgBufLen - offset; - unsigned char *const sdu_buffer=msgBuf+offset; - const pdcp_transmission_mode_t mode=PDCP_TRANSMISSION_MODE_DATA; - const uint32_t sourceL2Id=0; - const uint32_t destinationL2Id=0; + unsigned char *const sdu_buffer = msgBuf + offset; + const pdcp_transmission_mode_t mode = PDCP_TRANSMISSION_MODE_DATA; + const uint32_t sourceL2Id = 0; + const uint32_t destinationL2Id = 0; pthread_mutex_unlock(&globGtp.gtp_lock); if (sdu_buffer_size > 0) { if (qfi != -1 && tunnel->second.callBackSDAP) { - if ( !tunnel->second.callBackSDAP(&ctxt, - tunnel->second.ue_id, - srb_flag, - rb_id, - mui, - confirm, - sdu_buffer_size, - sdu_buffer, - mode, - &sourceL2Id, - &destinationL2Id, - qfi, - rqi, - tunnel->second.pdusession_id) ) - LOG_E(GTPU,"[%d] down layer refused incoming packet\n", h); + if (!tunnel->second.callBackSDAP(&ctxt, + tunnel->second.ue_id, + srb_flag, + rb_id, + mui, + confirm, + sdu_buffer_size, + sdu_buffer, + mode, + &sourceL2Id, + &destinationL2Id, + qfi, + rqi, + tunnel->second.pdusession_id)) + LOG_E(GTPU, "[%d] down layer refused incoming packet\n", h); } else { - if ( !tunnel->second.callBack(&ctxt, - srb_flag, - rb_id, - mui, - confirm, - sdu_buffer_size, - sdu_buffer, - mode, - &sourceL2Id, - &destinationL2Id) ) - LOG_E(GTPU,"[%d] down layer refused incoming packet\n", h); + if (!tunnel->second + .callBack(&ctxt, srb_flag, rb_id, mui, confirm, sdu_buffer_size, sdu_buffer, mode, &sourceL2Id, &destinationL2Id)) + LOG_E(GTPU, "[%d] down layer refused incoming packet\n", h); } } - if(NR_PDCP_PDU_SN > 0 && NR_PDCP_PDU_SN %5 ==0){ - LOG_D (GTPU, "Create and send DL DATA Delivery status for the previously received PDU, NR_PDCP_PDU_SN: %u \n", NR_PDCP_PDU_SN); + if (NR_PDCP_PDU_SN > 0 && NR_PDCP_PDU_SN % 5 == 0) { + LOG_D(GTPU, "Create and send DL DATA Delivery status for the previously received PDU, NR_PDCP_PDU_SN: %u \n", NR_PDCP_PDU_SN); int rlc_tx_buffer_space = nr_rlc_get_available_tx_space(ctxt.rntiMaybeUEid, rb_id + 3); LOG_D(GTPU, "Available buffer size in RLC for Tx: %d \n", rlc_tx_buffer_space); /*Total size of DDD_status PDU = 1 octet to report extension header length @@ -1146,87 +1163,99 @@ static int Gtpv1uHandleGpdu(int h, * 1 octet for padding + 1 octet for next extension header type, * according to TS 38.425: Fig. 5.5.2.2-1 and section 5.5.3.24*/ extensionHeader_t *extensionHeader; - extensionHeader = (extensionHeader_t *) calloc(1, sizeof(extensionHeader_t)) ; - extensionHeader->buffer[0] = (1+sizeof(DlDataDeliveryStatus_flagsT)+3+1+1)/4; + extensionHeader = (extensionHeader_t *)calloc(1, sizeof(extensionHeader_t)); + extensionHeader->buffer[0] = (1 + sizeof(DlDataDeliveryStatus_flagsT) + 3 + 1 + 1) / 4; DlDataDeliveryStatus_flagsT DlDataDeliveryStatus; DlDataDeliveryStatus.deliveredPdcpSn = 0; - DlDataDeliveryStatus.transmittedPdcpSn= 1; + DlDataDeliveryStatus.transmittedPdcpSn = 1; DlDataDeliveryStatus.pduType = 1; - DlDataDeliveryStatus.drbBufferSize = htonl(rlc_tx_buffer_space); //htonl(10000000); //hardcoded for now but normally we should extract it from RLC - memcpy(extensionHeader->buffer+1, &DlDataDeliveryStatus, sizeof(DlDataDeliveryStatus_flagsT)); - uint8_t offset = sizeof(DlDataDeliveryStatus_flagsT)+1; + DlDataDeliveryStatus.drbBufferSize = + htonl(rlc_tx_buffer_space); // htonl(10000000); //hardcoded for now but normally we should extract it from RLC + memcpy(extensionHeader->buffer + 1, &DlDataDeliveryStatus, sizeof(DlDataDeliveryStatus_flagsT)); + uint8_t offset = sizeof(DlDataDeliveryStatus_flagsT) + 1; - extensionHeader->buffer[offset] = (NR_PDCP_PDU_SN >> 16) & 0xff; - extensionHeader->buffer[offset+1] = (NR_PDCP_PDU_SN >> 8) & 0xff; - extensionHeader->buffer[offset+2] = NR_PDCP_PDU_SN & 0xff; - LOG_D(GTPU, "Octets reporting NR_PDCP_PDU_SN, extensionHeader-> %u:%u:%u \n", + extensionHeader->buffer[offset] = (NR_PDCP_PDU_SN >> 16) & 0xff; + extensionHeader->buffer[offset + 1] = (NR_PDCP_PDU_SN >> 8) & 0xff; + extensionHeader->buffer[offset + 2] = NR_PDCP_PDU_SN & 0xff; + LOG_D(GTPU, + "Octets reporting NR_PDCP_PDU_SN, extensionHeader-> %u:%u:%u \n", extensionHeader->buffer[offset], - extensionHeader->buffer[offset+1], - extensionHeader->buffer[offset+2]); - extensionHeader->buffer[offset+3] = 0x00; //Padding octet - extensionHeader->buffer[offset+4] = 0x00; //No more extension headers + extensionHeader->buffer[offset + 1], + extensionHeader->buffer[offset + 2]); + extensionHeader->buffer[offset + 3] = 0x00; // Padding octet + extensionHeader->buffer[offset + 4] = 0x00; // No more extension headers /*Total size of DDD_status PDU = size of mandatory part + * 3 octets for highest transmitted/delivered PDCP SN + * 1 octet for padding + 1 octet for next extension header type, * according to TS 38.425: Fig. 5.5.2.2-1 and section 5.5.3.24*/ - extensionHeader->length = 1+sizeof(DlDataDeliveryStatus_flagsT)+3+1+1; - gtpv1uCreateAndSendMsg( - h, peerIp, peerPort, GTP_GPDU, globGtp.te2ue_mapping[ntohl(msgHdr->teid)].outgoing_teid, NULL, 0, false, false, 0, 0, NR_RAN_CONTAINER, extensionHeader->buffer, extensionHeader->length); + extensionHeader->length = 1 + sizeof(DlDataDeliveryStatus_flagsT) + 3 + 1 + 1; + gtpv1uCreateAndSendMsg(h, + peerIp, + peerPort, + GTP_GPDU, + globGtp.te2ue_mapping[ntohl(msgHdr->teid)].outgoing_teid, + NULL, + 0, + false, + false, + 0, + 0, + NR_RAN_CONTAINER, + extensionHeader->buffer, + extensionHeader->length); } - LOG_D(GTPU,"[%d] Received a %d bytes packet for: teid:%x\n", h, - msgBufLen-offset, - ntohl(msgHdr->teid)); + LOG_D(GTPU, "[%d] Received a %d bytes packet for: teid:%x\n", h, msgBufLen - offset, ntohl(msgHdr->teid)); return !GTPNOK; } -void gtpv1uReceiver(int h) { - uint8_t udpData[65536]; - int udpDataLen; - socklen_t from_len; +void gtpv1uReceiver(int h) +{ + uint8_t udpData[65536]; + int udpDataLen; + socklen_t from_len; struct sockaddr_in addr; from_len = (socklen_t)sizeof(struct sockaddr_in); - if ((udpDataLen = recvfrom(h, udpData, sizeof(udpData), 0, - (struct sockaddr *)&addr, &from_len)) < 0) { + if ((udpDataLen = recvfrom(h, udpData, sizeof(udpData), 0, (struct sockaddr *)&addr, &from_len)) < 0) { LOG_E(GTPU, "[%d] Recvfrom failed (%s)\n", h, strerror(errno)); return; } else if (udpDataLen == 0) { LOG_W(GTPU, "[%d] Recvfrom returned 0\n", h); return; } else { - if ( udpDataLen < (int)sizeof(Gtpv1uMsgHeaderT) ) { + if (udpDataLen < (int)sizeof(Gtpv1uMsgHeaderT)) { LOG_W(GTPU, "[%d] received malformed gtp packet \n", h); return; } - Gtpv1uMsgHeaderT* msg=(Gtpv1uMsgHeaderT*) udpData; - if ( (int)(ntohs(msg->msgLength) + sizeof(Gtpv1uMsgHeaderT)) != udpDataLen ) { + Gtpv1uMsgHeaderT *msg = (Gtpv1uMsgHeaderT *)udpData; + if ((int)(ntohs(msg->msgLength) + sizeof(Gtpv1uMsgHeaderT)) != udpDataLen) { LOG_W(GTPU, "[%d] received malformed gtp packet length\n", h); return; } LOG_D(GTPU, "[%d] Received GTP data, msg type: %x\n", h, msg->msgType); - switch(msg->msgType) { + switch (msg->msgType) { case GTP_ECHO_RSP: break; case GTP_ECHO_REQ: - Gtpv1uHandleEchoReq( h, udpData, udpDataLen, htons(addr.sin_port), addr.sin_addr.s_addr); + Gtpv1uHandleEchoReq(h, udpData, udpDataLen, htons(addr.sin_port), addr.sin_addr.s_addr); break; case GTP_ERROR_INDICATION: - Gtpv1uHandleError( h, udpData, udpDataLen, htons(addr.sin_port), addr.sin_addr.s_addr); + Gtpv1uHandleError(h, udpData, udpDataLen, htons(addr.sin_port), addr.sin_addr.s_addr); break; case GTP_SUPPORTED_EXTENSION_HEADER_INDICATION: - Gtpv1uHandleSupportedExt( h, udpData, udpDataLen, htons(addr.sin_port), addr.sin_addr.s_addr); + Gtpv1uHandleSupportedExt(h, udpData, udpDataLen, htons(addr.sin_port), addr.sin_addr.s_addr); break; case GTP_END_MARKER: - Gtpv1uHandleEndMarker( h, udpData, udpDataLen, htons(addr.sin_port), addr.sin_addr.s_addr); + Gtpv1uHandleEndMarker(h, udpData, udpDataLen, htons(addr.sin_port), addr.sin_addr.s_addr); break; case GTP_GPDU: - Gtpv1uHandleGpdu( h, udpData, udpDataLen, htons(addr.sin_port), addr.sin_addr.s_addr); + Gtpv1uHandleGpdu(h, udpData, udpDataLen, htons(addr.sin_port), addr.sin_addr.s_addr); break; default: @@ -1238,8 +1267,9 @@ void gtpv1uReceiver(int h) { #include -void *gtpv1uTask(void *args) { - while(1) { +void *gtpv1uTask(void *args) +{ + while (1) { /* Trying to fetch a message from the message queue. If the queue is empty, this function will block till a message is sent to the task. @@ -1247,8 +1277,8 @@ void *gtpv1uTask(void *args) { MessageDef *message_p = NULL; itti_receive_msg(TASK_GTPV1_U, &message_p); - if (message_p != NULL ) { - openAddr_t addr= {{0}}; + if (message_p != NULL) { + openAddr_t addr = {{0}}; const instance_t myInstance = ITTI_MSG_DESTINATION_INSTANCE(message_p); const int msgType = ITTI_MSG_ID(message_p); LOG_D(GTPU, "GTP-U received %s for instance %ld\n", messages_info[msgType].name, myInstance); @@ -1278,8 +1308,8 @@ void *gtpv1uTask(void *args) { // to be dev: should be removed, to use API strcpy(addr.originHost, GTPV1U_REQ(message_p).localAddrStr); strcpy(addr.originService, GTPV1U_REQ(message_p).localPortStr); - strcpy(addr.destinationService,addr.originService); - AssertFatal((legacyInstanceMapping=gtpv1Init(addr))!=0,"Instance 0 reserved for legacy\n"); + strcpy(addr.destinationService, addr.originService); + AssertFatal((legacyInstanceMapping = gtpv1Init(addr)) != 0, "Instance 0 reserved for legacy\n"); break; default: @@ -1288,14 +1318,14 @@ void *gtpv1uTask(void *args) { break; } - AssertFatal(EXIT_SUCCESS==itti_free(TASK_GTPV1_U, message_p), "Failed to free memory!\n"); + AssertFatal(EXIT_SUCCESS == itti_free(TASK_GTPV1_U, message_p), "Failed to free memory!\n"); } struct epoll_event events[20]; int nb_events = itti_get_events(TASK_GTPV1_U, events, 20); for (int i = 0; i < nb_events; i++) - if ((events[i].events&EPOLLIN)) + if ((events[i].events & EPOLLIN)) gtpv1uReceiver(events[i].data.fd); } From 510814a79a02b1b6db639c8fb9d646c32aa203a5 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 3 Feb 2025 12:10:27 +0100 Subject: [PATCH 351/964] Remove unused struct member --- openair3/ocp-gtpu/gtp_itf.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/openair3/ocp-gtpu/gtp_itf.cpp b/openair3/ocp-gtpu/gtp_itf.cpp index 50c46b809f..65c5c9d118 100644 --- a/openair3/ocp-gtpu/gtp_itf.cpp +++ b/openair3/ocp-gtpu/gtp_itf.cpp @@ -109,7 +109,6 @@ typedef struct gtpv1u_bearer_s { typedef struct { map bearers; - teid_t outgoing_teid; } teidData_t; typedef struct { From 483d610a9b62eeedf6cb9c36e91025e21b6c5eb6 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 4 Feb 2025 15:10:06 +0100 Subject: [PATCH 352/964] Reduce receiver mutex scope This seems to reduce packet loss on my machine. --- openair3/ocp-gtpu/gtp_itf.cpp | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/openair3/ocp-gtpu/gtp_itf.cpp b/openair3/ocp-gtpu/gtp_itf.cpp index 65c5c9d118..47f923e29c 100644 --- a/openair3/ocp-gtpu/gtp_itf.cpp +++ b/openair3/ocp-gtpu/gtp_itf.cpp @@ -1024,8 +1024,6 @@ static int Gtpv1uHandleGpdu(int h, uint8_t *msgBuf, uint32_t msgBufLen, uint16_t } pthread_mutex_lock(&globGtp.gtp_lock); - // the socket Linux file handler is the instance id - getInstRetInt(h); auto tunnel = globGtp.te2ue_mapping.find(ntohl(msgHdr->teid)); if (tunnel == globGtp.te2ue_mapping.end()) { @@ -1033,6 +1031,8 @@ static int Gtpv1uHandleGpdu(int h, uint8_t *msgBuf, uint32_t msgBufLen, uint16_t pthread_mutex_unlock(&globGtp.gtp_lock); return GTPNOK; } + ueidData_t uedata = tunnel->second; + pthread_mutex_unlock(&globGtp.gtp_lock); /* see TS 29.281 5.1 */ // Minimum length of GTP-U header if non of the optional fields are present @@ -1109,17 +1109,9 @@ static int Gtpv1uHandleGpdu(int h, uint8_t *msgBuf, uint32_t msgBufLen, uint16_t // This context is not good for gtp // frame, ... has no meaning // manyother attributes may come from create tunnel - protocol_ctxt_t ctxt; - ctxt.module_id = 0; - ctxt.enb_flag = 1; - ctxt.instance = inst->addr.originInstance; - ctxt.rntiMaybeUEid = tunnel->second.ue_id; - ctxt.frame = 0; - ctxt.subframe = 0; - ctxt.eNB_index = 0; - ctxt.brOption = 0; + protocol_ctxt_t ctxt = { .enb_flag = 1, .rntiMaybeUEid = uedata.ue_id, }; const srb_flag_t srb_flag = SRB_FLAG_NO; - const rb_id_t rb_id = tunnel->second.incoming_rb_id; + const rb_id_t rb_id = uedata.incoming_rb_id; const mui_t mui = RLC_MUI_UNDEFINED; const confirm_t confirm = RLC_SDU_CONFIRM_NO; const sdu_size_t sdu_buffer_size = msgBufLen - offset; @@ -1127,12 +1119,11 @@ static int Gtpv1uHandleGpdu(int h, uint8_t *msgBuf, uint32_t msgBufLen, uint16_t const pdcp_transmission_mode_t mode = PDCP_TRANSMISSION_MODE_DATA; const uint32_t sourceL2Id = 0; const uint32_t destinationL2Id = 0; - pthread_mutex_unlock(&globGtp.gtp_lock); if (sdu_buffer_size > 0) { - if (qfi != -1 && tunnel->second.callBackSDAP) { - if (!tunnel->second.callBackSDAP(&ctxt, - tunnel->second.ue_id, + if (qfi != -1 && uedata.callBackSDAP) { + if (!uedata.callBackSDAP(&ctxt, + uedata.ue_id, srb_flag, rb_id, mui, @@ -1144,11 +1135,10 @@ static int Gtpv1uHandleGpdu(int h, uint8_t *msgBuf, uint32_t msgBufLen, uint16_t &destinationL2Id, qfi, rqi, - tunnel->second.pdusession_id)) + uedata.pdusession_id)) LOG_E(GTPU, "[%d] down layer refused incoming packet\n", h); } else { - if (!tunnel->second - .callBack(&ctxt, srb_flag, rb_id, mui, confirm, sdu_buffer_size, sdu_buffer, mode, &sourceL2Id, &destinationL2Id)) + if (!uedata.callBack(&ctxt, srb_flag, rb_id, mui, confirm, sdu_buffer_size, sdu_buffer, mode, &sourceL2Id, &destinationL2Id)) LOG_E(GTPU, "[%d] down layer refused incoming packet\n", h); } } From 7c34825daeaab3f096c028e10e5dcb5c34897262 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 24 Jul 2025 19:27:42 +0200 Subject: [PATCH 353/964] Receiver thread: independent of ITTI This also seems to reduce the packet loss on my machine. Especially in uplink there are no losses anymore. --- openair3/ocp-gtpu/gtp_itf.cpp | 35 +++++++++++++++++++++++++---------- openair3/ocp-gtpu/gtp_itf.h | 1 - 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/openair3/ocp-gtpu/gtp_itf.cpp b/openair3/ocp-gtpu/gtp_itf.cpp index 47f923e29c..1197767947 100644 --- a/openair3/ocp-gtpu/gtp_itf.cpp +++ b/openair3/ocp-gtpu/gtp_itf.cpp @@ -11,6 +11,7 @@ extern "C" { #include #include "common/platform_types.h" +#include "common/utils/system.h" #include #include "common/utils/LOG/log.h" #include @@ -120,12 +121,18 @@ typedef struct { int pdusession_id; } ueidData_t; +typedef struct { + int h; + pthread_t t; +} gtpThread_t; + class gtpEndPoint { public: openAddr_t addr; uint8_t foundAddr[20]; int foundAddrLen; int ipVersion; + gtpThread_t thrData; map ue2te_mapping; // we use the same port number for source and destination address // this allow using non standard gtp port number (different from 2152) @@ -505,18 +512,23 @@ static int udpServerSocket(openAddr_s addr) return sockfd; } +static void* gtpv1uReceiver(void *thr); instance_t gtpv1Init(openAddr_t context) { pthread_mutex_lock(&globGtp.gtp_lock); int id = udpServerSocket(context); if (id >= 0) { - itti_subscribe_event_fd(TASK_GTPV1_U, id); + LOG_I(GTPU, "Created gtpu instance id: %d\n", id); + getInstRetInt(compatInst(id)); + inst->thrData.h = id; + char name[32]; + snprintf(name, sizeof(name), "GTPrx_%d", id); + threadCreate(&inst->thrData.t, gtpv1uReceiver, &inst->thrData, name, -1, OAI_PRIORITY_RT); } else LOG_E(GTPU, "can't create GTP-U instance\n"); pthread_mutex_unlock(&globGtp.gtp_lock); - LOG_I(GTPU, "Created gtpu instance id: %d\n", id); return id; } @@ -1198,7 +1210,7 @@ static int Gtpv1uHandleGpdu(int h, uint8_t *msgBuf, uint32_t msgBufLen, uint16_t return !GTPNOK; } -void gtpv1uReceiver(int h) +static void gtpv1uReceiveHandleMessage(int h) { uint8_t udpData[65536]; int udpDataLen; @@ -1254,6 +1266,16 @@ void gtpv1uReceiver(int h) } } +static void* gtpv1uReceiver(void *thr) +{ + gtpThread_t *gt = (gtpThread_t *)thr; + while (true) { + gtpv1uReceiveHandleMessage(gt->h); + } + LOG_W(GTPU, "exiting thread\n"); + return NULL; +} + #include void *gtpv1uTask(void *args) @@ -1309,13 +1331,6 @@ void *gtpv1uTask(void *args) AssertFatal(EXIT_SUCCESS == itti_free(TASK_GTPV1_U, message_p), "Failed to free memory!\n"); } - - struct epoll_event events[20]; - int nb_events = itti_get_events(TASK_GTPV1_U, events, 20); - - for (int i = 0; i < nb_events; i++) - if ((events[i].events & EPOLLIN)) - gtpv1uReceiver(events[i].data.fd); } return NULL; diff --git a/openair3/ocp-gtpu/gtp_itf.h b/openair3/ocp-gtpu/gtp_itf.h index f0af60a5f7..4449cba244 100644 --- a/openair3/ocp-gtpu/gtp_itf.h +++ b/openair3/ocp-gtpu/gtp_itf.h @@ -76,7 +76,6 @@ typedef struct gtpv1u_gnb_delete_tunnel_req_s gtpv1u_gnb_delete_tunnel_req_t; // the init function create a gtp instance and return the gtp instance id // the parameter originInstance will be sent back in each message from gtp to the creator - void gtpv1uReceiver(int h); void gtpv1uProcessTimeout(int handle,void *arg); int gtpv1u_create_s1u_tunnel(const instance_t instance, const gtpv1u_enb_create_tunnel_req_t *create_tunnel_req, From 5d9db1688ac7747a02de9aa0e12ae3a033c083ab Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 30 Jul 2025 18:46:08 +0200 Subject: [PATCH 354/964] Refactor port number out of newGtpuCreateTunnel() The (remote) port number of the GTP module is configured during initialization. It is therefore not required when calling newGtpuCreateTunnel(), and could even lead to bugs (if another port number is used than specified during GTP init). --- openair3/ocp-gtpu/gtp_itf.cpp | 7 +------ openair3/ocp-gtpu/gtp_itf.h | 1 - tests/nr-cuup/nr-cuup-load-test.c | 16 ++++++++-------- 3 files changed, 9 insertions(+), 15 deletions(-) diff --git a/openair3/ocp-gtpu/gtp_itf.cpp b/openair3/ocp-gtpu/gtp_itf.cpp index 1197767947..6f7f300bea 100644 --- a/openair3/ocp-gtpu/gtp_itf.cpp +++ b/openair3/ocp-gtpu/gtp_itf.cpp @@ -568,7 +568,6 @@ teid_t newGtpuCreateTunnel(instance_t instance, teid_t outgoing_teid, int outgoing_qfi, transport_layer_addr_t remoteAddr, - int port, gtpCallback callBack, gtpCallbackSDAP callBackSDAP) { @@ -617,7 +616,7 @@ teid_t newGtpuCreateTunnel(instance_t instance, } tmp->teid_incoming = incoming_teid; - tmp->outgoing_port = port; + tmp->outgoing_port = inst->get_dstport(); tmp->teid_outgoing = outgoing_teid; tmp->outgoing_qfi = outgoing_qfi; pthread_mutex_unlock(&globGtp.gtp_lock); @@ -648,7 +647,6 @@ int gtpv1u_create_s1u_tunnel(instance_t instance, pthread_mutex_lock(&globGtp.gtp_lock); getInstRetInt(compatInst(instance)); - tcp_udp_port_t dstport = inst->get_dstport(); uint8_t addr[inst->foundAddrLen]; memcpy(addr, inst->foundAddr, inst->foundAddrLen); pthread_mutex_unlock(&globGtp.gtp_lock); @@ -665,7 +663,6 @@ int gtpv1u_create_s1u_tunnel(instance_t instance, create_tunnel_req->sgw_S1u_teid[i], -1, // no pdu session in 4G create_tunnel_req->sgw_addr[i], - dstport, callBack, NULL); create_tunnel_resp->status = 0; @@ -737,7 +734,6 @@ int gtpv1u_create_ngu_tunnel(const instance_t instance, pthread_mutex_lock(&globGtp.gtp_lock); getInstRetInt(compatInst(instance)); - tcp_udp_port_t dstport = inst->get_dstport(); uint8_t addr[inst->foundAddrLen]; memcpy(addr, inst->foundAddr, inst->foundAddrLen); pthread_mutex_unlock(&globGtp.gtp_lock); @@ -749,7 +745,6 @@ int gtpv1u_create_ngu_tunnel(const instance_t instance, create_tunnel_req->outgoing_teid[i], create_tunnel_req->outgoing_qfi[i], create_tunnel_req->dst_addr[i], - dstport, callBack, callBackSDAP); create_tunnel_resp->status = 0; diff --git a/openair3/ocp-gtpu/gtp_itf.h b/openair3/ocp-gtpu/gtp_itf.h index 4449cba244..d341acb311 100644 --- a/openair3/ocp-gtpu/gtp_itf.h +++ b/openair3/ocp-gtpu/gtp_itf.h @@ -114,7 +114,6 @@ typedef struct gtpv1u_gnb_delete_tunnel_req_s gtpv1u_gnb_delete_tunnel_req_t; teid_t teid, int outgoing_qfi, transport_layer_addr_t remoteAddr, - int port, gtpCallback callBack, gtpCallbackSDAP callBackSDAP); diff --git a/tests/nr-cuup/nr-cuup-load-test.c b/tests/nr-cuup/nr-cuup-load-test.c index 48e088fc3c..0c417ca5aa 100644 --- a/tests/nr-cuup/nr-cuup-load-test.c +++ b/tests/nr-cuup/nr-cuup-load-test.c @@ -187,7 +187,7 @@ static bool recv_ng(protocol_ctxt_t *ctxt, } /* @brief Set up the NG-U (north-bound) GTP tunnel, and inform CU-UP via E1 */ -static up_params_t setup_cuup_ue_ng(sctp_assoc_t assoc_id, const e1ap_nssai_t *nssai, uint32_t ue_id, instance_t gtp_inst, const char *ip, uint16_t port) +static up_params_t setup_cuup_ue_ng(sctp_assoc_t assoc_id, const e1ap_nssai_t *nssai, uint32_t ue_id, instance_t gtp_inst, const char *ip) { long pdu_id = 1; long drb_id = pdu_id + 3; @@ -196,7 +196,7 @@ static up_params_t setup_cuup_ue_ng(sctp_assoc_t assoc_id, const e1ap_nssai_t *n /* create the local tunnel (i.e., as if we were UPF) */ transport_layer_addr_t null_addr = {.length = 32}; - teid_t teid_lo = newGtpuCreateTunnel(gtp_inst, ue_id, pdu_id, pdu_id, -1, -1, null_addr, port, NULL, recv_ng); + teid_t teid_lo = newGtpuCreateTunnel(gtp_inst, ue_id, pdu_id, pdu_id, -1, -1, null_addr, NULL, recv_ng); UP_TL_information_t tnl = {.teId = teid_lo}; memcpy(&tnl.tlAddress, &addr_lo, 4); @@ -233,7 +233,7 @@ static up_params_t setup_cuup_ue_ng(sctp_assoc_t assoc_id, const e1ap_nssai_t *n char ip_rm[32] = {0}; inet_ntop(AF_INET, &addr_rm, ip_rm, sizeof(ip_rm)); GtpuUpdateTunnelOutgoingAddressAndTeid(gtp_inst, ue_id, pdu_id, addr_rm, teid_rm); - LOG_I(GNB_APP, "CU-UP created NG-U, local %s/%x remote %s/%x (port %d)\n", ip_lo, teid_lo, ip_rm, teid_rm, port); + LOG_I(GNB_APP, "CU-UP created NG-U, local %s/%x remote %s/%x\n", ip_lo, teid_lo, ip_rm, teid_rm); inet_ntop(AF_INET, &f1_up.tl_info.tlAddress, ip_rm, sizeof(ip_rm)); LOG_I(GNB_APP, "CU-UP created F1-U, remove %s/%x\n", ip_rm, f1_up.tl_info.teId); @@ -286,7 +286,7 @@ static bool recv_f1(protocol_ctxt_t *ctxt, } /* @brief Set up the F1-U (south-bound) GTP tunnel, and inform CU-UP via E1 */ -static void setup_cuup_ue_f1(sctp_assoc_t assoc_id, uint32_t ue_id, instance_t gtp_inst, const char *ip, uint16_t port, up_params_t rm) +static void setup_cuup_ue_f1(sctp_assoc_t assoc_id, uint32_t ue_id, instance_t gtp_inst, const char *ip, up_params_t rm) { int pdu_id = 1; int drb_id = pdu_id + 3; @@ -294,7 +294,7 @@ static void setup_cuup_ue_f1(sctp_assoc_t assoc_id, uint32_t ue_id, instance_t g /* create tunnel (i.e., as if we were DU) */ transport_layer_addr_t addr = {.length = 32}; memcpy(addr.buffer, &rm.tl_info.tlAddress, 4); - teid_t teid_lo = newGtpuCreateTunnel(gtp_inst, ue_id, drb_id, drb_id, rm.tl_info.teId, -1, addr, port, recv_f1, NULL); + teid_t teid_lo = newGtpuCreateTunnel(gtp_inst, ue_id, drb_id, drb_id, rm.tl_info.teId, -1, addr, recv_f1, NULL); up_params_t lo = {.tl_info.teId = teid_lo, .cell_group_id = rm.cell_group_id}; inet_pton(AF_INET, ip, &lo.tl_info.tlAddress); @@ -319,7 +319,7 @@ static void setup_cuup_ue_f1(sctp_assoc_t assoc_id, uint32_t ue_id, instance_t g inet_ntop(AF_INET, &lo.tl_info.tlAddress, ip_lo, sizeof(ip_lo)); char ip_rm[32] = {0}; inet_ntop(AF_INET, &rm.tl_info.tlAddress, ip_rm, sizeof(ip_rm)); - LOG_I(GNB_APP, "CU-UP created F1-U, local %s/%x remote %s/%x (port %d)\n", ip_lo, lo.tl_info.teId, ip_rm, rm.tl_info.teId, port); + LOG_I(GNB_APP, "CU-UP created F1-U, local %s/%x remote %s/%x\n", ip_lo, lo.tl_info.teId, ip_rm, rm.tl_info.teId); } /* @brief release the UE over E1, and delete corresponding GTP tunnels */ @@ -609,8 +609,8 @@ int main(int argc, char *argv[]) * - setup_cuup_ue_f1(): E1 bearer context modification <=> send TEID for * F1-U DL (as if we had talked to the DU in the middle) */ for (int ue = 0; ue < n_ue; ++ue) { - up_params_t f1_up = setup_cuup_ue_ng(assoc_id, &nssai, ue, ng_inst, ng_ip, ng_port); - setup_cuup_ue_f1(assoc_id, ue, f1_inst, f1_ip, f1_port, f1_up); + up_params_t f1_up = setup_cuup_ue_ng(assoc_id, &nssai, ue, ng_inst, ng_ip); + setup_cuup_ue_f1(assoc_id, ue, f1_inst, f1_ip, f1_up); } usleep(1000); From 38ac898672258abdcf98bdfee149b91966727976 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 30 Jul 2025 19:06:20 +0200 Subject: [PATCH 355/964] Refactor GTP: pass addr structure directly This should simplify future transition to IPv6, as we can pass the right address directly. --- openair3/ocp-gtpu/gtp_itf.cpp | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/openair3/ocp-gtpu/gtp_itf.cpp b/openair3/ocp-gtpu/gtp_itf.cpp index 6f7f300bea..3099fbc455 100644 --- a/openair3/ocp-gtpu/gtp_itf.cpp +++ b/openair3/ocp-gtpu/gtp_itf.cpp @@ -922,7 +922,7 @@ int gtpv1u_delete_ngu_tunnel(const instance_t instance, gtpv1u_gnb_delete_tunnel return newGtpuDeleteTunnels(instance, req->ue_id, req->num_pdusession, req->pdusession_id); } -static int Gtpv1uHandleEchoReq(int h, uint8_t *msgBuf, uint32_t msgBufLen, uint16_t peerPort, uint32_t peerIp) +static int Gtpv1uHandleEchoReq(int h, uint8_t *msgBuf, uint32_t msgBufLen, const struct sockaddr_in *addr) { Gtpv1uMsgHeaderT *msgHdr = (Gtpv1uMsgHeaderT *)msgBuf; @@ -940,8 +940,8 @@ static int Gtpv1uHandleEchoReq(int h, uint8_t *msgBuf, uint32_t msgBufLen, uint1 LOG_D(GTPU, "[%d] Received a echo request, TEID: %d, seq: %hu\n", h, msgHdr->teid, seq); uint8_t recovery[2] = {14, 0}; return gtpv1uCreateAndSendMsg(h, - peerIp, - peerPort, + addr->sin_addr.s_addr, + htons(addr->sin_port), GTP_ECHO_RSP, ntohl(msgHdr->teid), recovery, @@ -955,14 +955,14 @@ static int Gtpv1uHandleEchoReq(int h, uint8_t *msgBuf, uint32_t msgBufLen, uint1 0); } -static int Gtpv1uHandleError(int h, uint8_t *msgBuf, uint32_t msgBufLen, uint16_t peerPort, uint32_t peerIp) +static int Gtpv1uHandleError(int h, uint8_t *msgBuf, uint32_t msgBufLen, const struct sockaddr_in *addr) { LOG_E(GTPU, "Received GTP error indication (error handling is missing/not implemented)\n"); int rc = GTPNOK; return rc; } -static int Gtpv1uHandleSupportedExt(int h, uint8_t *msgBuf, uint32_t msgBufLen, uint16_t peerPort, uint32_t peerIp) +static int Gtpv1uHandleSupportedExt(int h, uint8_t *msgBuf, uint32_t msgBufLen, const sockaddr_in *addr) { LOG_E(GTPU, "Supported extensions to be dev\n"); int rc = GTPNOK; @@ -972,7 +972,7 @@ static int Gtpv1uHandleSupportedExt(int h, uint8_t *msgBuf, uint32_t msgBufLen, // When end marker arrives, we notify the client with buffer size = 0 // The client will likely call "delete tunnel" // nevertheless we don't take the initiative -static int Gtpv1uHandleEndMarker(int h, uint8_t *msgBuf, uint32_t msgBufLen, uint16_t peerPort, uint32_t peerIp) +static int Gtpv1uHandleEndMarker(int h, uint8_t *msgBuf, uint32_t msgBufLen, const sockaddr_in *addr) { Gtpv1uMsgHeaderT *msgHdr = (Gtpv1uMsgHeaderT *)msgBuf; @@ -1021,7 +1021,7 @@ static int Gtpv1uHandleEndMarker(int h, uint8_t *msgBuf, uint32_t msgBufLen, uin return !GTPNOK; } -static int Gtpv1uHandleGpdu(int h, uint8_t *msgBuf, uint32_t msgBufLen, uint16_t peerPort, uint32_t peerIp) +static int Gtpv1uHandleGpdu(int h, uint8_t *msgBuf, uint32_t msgBufLen, const struct sockaddr_in *addr) { Gtpv1uMsgHeaderT *msgHdr = (Gtpv1uMsgHeaderT *)msgBuf; @@ -1186,8 +1186,8 @@ static int Gtpv1uHandleGpdu(int h, uint8_t *msgBuf, uint32_t msgBufLen, uint16_t * according to TS 38.425: Fig. 5.5.2.2-1 and section 5.5.3.24*/ extensionHeader->length = 1 + sizeof(DlDataDeliveryStatus_flagsT) + 3 + 1 + 1; gtpv1uCreateAndSendMsg(h, - peerIp, - peerPort, + addr->sin_addr.s_addr, + htons(addr->sin_port), GTP_GPDU, globGtp.te2ue_mapping[ntohl(msgHdr->teid)].outgoing_teid, NULL, @@ -1235,23 +1235,23 @@ static void gtpv1uReceiveHandleMessage(int h) break; case GTP_ECHO_REQ: - Gtpv1uHandleEchoReq(h, udpData, udpDataLen, htons(addr.sin_port), addr.sin_addr.s_addr); + Gtpv1uHandleEchoReq(h, udpData, udpDataLen, &addr); break; case GTP_ERROR_INDICATION: - Gtpv1uHandleError(h, udpData, udpDataLen, htons(addr.sin_port), addr.sin_addr.s_addr); + Gtpv1uHandleError(h, udpData, udpDataLen, &addr); break; case GTP_SUPPORTED_EXTENSION_HEADER_INDICATION: - Gtpv1uHandleSupportedExt(h, udpData, udpDataLen, htons(addr.sin_port), addr.sin_addr.s_addr); + Gtpv1uHandleSupportedExt(h, udpData, udpDataLen, &addr); break; case GTP_END_MARKER: - Gtpv1uHandleEndMarker(h, udpData, udpDataLen, htons(addr.sin_port), addr.sin_addr.s_addr); + Gtpv1uHandleEndMarker(h, udpData, udpDataLen, &addr); break; case GTP_GPDU: - Gtpv1uHandleGpdu(h, udpData, udpDataLen, htons(addr.sin_port), addr.sin_addr.s_addr); + Gtpv1uHandleGpdu(h, udpData, udpDataLen, &addr); break; default: From 9140b36a2d9fefd990c4e19a911d77acaedb6eae Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 4 Feb 2025 12:56:39 +0100 Subject: [PATCH 356/964] Refactor gtpv1u_bearer_t and use internally Reuse the gtpv1u_bearer_t for internal functions. Hopefully this will also simplify implementation of IPv6, as it encapsulates IP address handling within gtpv1u_bearer_t. --- openair3/ocp-gtpu/gtp_itf.cpp | 193 +++++++++++++++------------------- 1 file changed, 87 insertions(+), 106 deletions(-) diff --git a/openair3/ocp-gtpu/gtp_itf.cpp b/openair3/ocp-gtpu/gtp_itf.cpp index 3099fbc455..3bc214df62 100644 --- a/openair3/ocp-gtpu/gtp_itf.cpp +++ b/openair3/ocp-gtpu/gtp_itf.cpp @@ -96,13 +96,12 @@ typedef struct Gtpv1uExtHeader { #define GTP_END_MARKER (254) #define GTP_GPDU (255) +// GTP bearer context: for sending data typedef struct gtpv1u_bearer_s { - /* TEID used in dl and ul */ - teid_t teid_incoming; ///< eNB TEID - teid_t teid_outgoing; ///< Remote TEID - in_addr_t outgoing_ip_addr; - struct in6_addr outgoing_ip6_addr; - tcp_udp_port_t outgoing_port; + int sock_fd; + struct sockaddr_storage ip; + teid_t teid_incoming; + teid_t teid_outgoing; uint16_t seqNum; uint8_t npduNum; int outgoing_qfi; @@ -217,22 +216,16 @@ instance_t legacyInstanceMapping = 0; } #define HDR_MAX 256 // 256 is supposed to be larger than any gtp header -static int gtpv1uCreateAndSendMsg(int h, - uint32_t peerIp, - uint16_t peerPort, +static int gtpv1uCreateAndSendMsg(gtpv1u_bearer_t *bearer, int msgType, - teid_t teid, uint8_t *Msg, int msgLen, bool seqNumFlag, bool npduNumFlag, - int seqNum, - int npduNum, int extHdrType, uint8_t *extensionHeader_buffer, uint8_t extensionHeader_length) { - LOG_D(GTPU, "Peer IP:%u peer port:%u outgoing teid:%u \n", peerIp, peerPort, teid); DevAssert(msgLen + HDR_MAX < 65536); // maximum size of UDP packet uint8_t buffer[msgLen + HDR_MAX]; @@ -247,14 +240,14 @@ static int gtpv1uCreateAndSendMsg(int h, msgHdr->PT = 1; msgHdr->version = 1; msgHdr->msgType = msgType; - msgHdr->teid = htonl(teid); + msgHdr->teid = htonl(bearer->teid_outgoing); curPtr += sizeof(Gtpv1uMsgHeaderT); if (seqNumFlag || (extHdrType != NO_MORE_EXT_HDRS) || npduNumFlag) { - *(uint16_t *)curPtr = seqNumFlag ? seqNum : 0x0000; + *(uint16_t *)curPtr = seqNumFlag ? bearer->seqNum : 0x0000; curPtr += sizeof(uint16_t); - *(uint8_t *)curPtr = npduNumFlag ? npduNum : 0x00; + *(uint8_t *)curPtr = npduNumFlag ? bearer->npduNum : 0x00; curPtr++; *(uint8_t *)curPtr = extHdrType; curPtr++; @@ -283,20 +276,20 @@ static int gtpv1uCreateAndSendMsg(int h, msgHdr->msgLength = htons(curPtr - (buffer + sizeof(Gtpv1uMsgHeaderT))); AssertFatal(curPtr - (buffer + msgLen) < HDR_MAX, "fixed max size of all headers too short"); - // Fix me: add IPv6 support, using flag ipVersion - struct sockaddr_in to = {0}; - to.sin_family = AF_INET; - to.sin_port = htons(peerPort); - to.sin_addr.s_addr = peerIp; - LOG_D(GTPU, "sending packet size: %ld to %s\n", curPtr - buffer, inet_ntoa(to.sin_addr)); - int ret; - if ((ret = sendto(h, (void *)buffer, curPtr - buffer, 0, (struct sockaddr *)&to, sizeof(to))) != curPtr - buffer) { + // Fix me: add IPv6 support + DevAssert(bearer->ip.ss_family == AF_INET); + struct sockaddr_in *to = (struct sockaddr_in *)&bearer->ip; + LOG_D(GTPU, + "Peer IP:" IPV4_ADDR " port:%u outgoing teid:%x\n", + IPV4_ADDR_FORMAT(to->sin_addr.s_addr), + htons(to->sin_port), + bearer->teid_outgoing); + int ret = sendto(bearer->sock_fd, buffer, curPtr - buffer, 0, (struct sockaddr *)to, sizeof(*to)); + if (ret != curPtr - buffer) { LOG_E(GTPU, - "[SD %d] Failed to send data to " IPV4_ADDR " on port %d, buffer size %lu, ret: %d, errno: %d\n", - h, - IPV4_ADDR_FORMAT(peerIp), - peerPort, + "[SD %d] Failed to send data buffer size %lu, ret: %d, errno: %d\n", + bearer->sock_fd, curPtr - buffer, ret, errno); @@ -343,49 +336,33 @@ void gtpv1uSendDirect(instance_t instance, ptr2->second.npduNum++; // copy to release the mutex - gtpv1u_bearer_t tmp = ptr2->second; + gtpv1u_bearer_t bearer = ptr2->second; pthread_mutex_unlock(&globGtp.gtp_lock); - if (tmp.outgoing_qfi != -1) { - Gtpv1uExtHeaderT ext = {0}; + Gtpv1uExtHeaderT *opt_ext = NULL; + Gtpv1uExtHeaderT ext = {0}; + if (bearer.outgoing_qfi != -1) { + opt_ext = &ext; ext.ExtHeaderLen = 1; // in quad bytes EXT_HDR_LNTH_OCTET_UNITS ext.pdusession_cntr.spare = 0; ext.pdusession_cntr.PDU_type = UL_PDU_SESSION_INFORMATION; - ext.pdusession_cntr.QFI = tmp.outgoing_qfi; + ext.pdusession_cntr.QFI = bearer.outgoing_qfi; ext.pdusession_cntr.Reflective_QoS_activation = false; ext.pdusession_cntr.Paging_Policy_Indicator = false; ext.NextExtHeaderType = NO_MORE_EXT_HDRS; - gtpv1uCreateAndSendMsg(compatInst(instance), - tmp.outgoing_ip_addr, - tmp.outgoing_port, - GTP_GPDU, - tmp.teid_outgoing, - buf, - len, - seqNumFlag, - npduNumFlag, - tmp.seqNum, - tmp.npduNum, - PDU_SESSION_CONTAINER, - (uint8_t *)&ext, - sizeof(ext)); - } else { - gtpv1uCreateAndSendMsg(compatInst(instance), - tmp.outgoing_ip_addr, - tmp.outgoing_port, - GTP_GPDU, - tmp.teid_outgoing, - buf, - len, - seqNumFlag, - npduNumFlag, - tmp.seqNum, - tmp.npduNum, - NO_MORE_EXT_HDRS, - NULL, - 0); } + + DevAssert(compatInst(instance) == bearer.sock_fd); + gtpv1uCreateAndSendMsg(&bearer, + GTP_GPDU, + buf, + len, + seqNumFlag, + npduNumFlag, + opt_ext ? PDU_SESSION_CONTAINER : NO_MORE_EXT_HDRS, + (uint8_t *)opt_ext, + sizeof(*opt_ext)); } static void gtpv1uEndTunnel(instance_t instance, gtpv1u_enb_end_marker_req_t *req) @@ -424,22 +401,16 @@ static void gtpv1uEndTunnel(instance_t instance, gtpv1u_enb_end_marker_req_t *re msgHdr.msgType = GTP_END_MARKER; msgHdr.msgLength = htons(0); msgHdr.teid = htonl(tmp.teid_outgoing); - // Fix me: add IPv6 support, using flag ipVersion - static struct sockaddr_in to = {0}; - to.sin_family = AF_INET; - to.sin_port = htons(tmp.outgoing_port); - to.sin_addr.s_addr = tmp.outgoing_ip_addr; - char ip4[INET_ADDRSTRLEN]; - // char ip6[INET6_ADDRSTRLEN]; - LOG_D(GTPU, "[%ld] sending end packet to %s\n", instance, inet_ntoa(to.sin_addr)); - if (sendto(compatInst(instance), (void *)&msgHdr, sizeof(msgHdr), 0, (struct sockaddr *)&to, sizeof(to)) != sizeof(msgHdr)) { - LOG_E(GTPU, - "[%ld] Failed to send data to %s on port %d, buffer size %lu\n", - compatInst(instance), - inet_ntop(AF_INET, &tmp.outgoing_ip_addr, ip4, INET_ADDRSTRLEN), - tmp.outgoing_port, - sizeof(msgHdr)); + // Fix me: add IPv6 support + DevAssert(instance == tmp.sock_fd); + DevAssert(tmp.ip.ss_family == AF_INET); + struct sockaddr_in *to = (struct sockaddr_in *)&tmp.ip; + LOG_D(GTPU, "[%ld] sending end packet to " IPV4_ADDR " port %d\n", instance, IPV4_ADDR_FORMAT(to->sin_addr.s_addr), htons(to->sin_port)); + + ssize_t ret = sendto(tmp.sock_fd, &msgHdr, sizeof(msgHdr), 0, (struct sockaddr *)to, sizeof(*to)); + if (ret != sizeof(msgHdr)) { + LOG_E(GTPU, "[%d] Failed to send data with buffer size %lu: ret %ld errno %d\n", tmp.sock_fd, sizeof(msgHdr), ret, errno); } } @@ -550,13 +521,17 @@ void GtpuUpdateTunnelOutgoingAddressAndTeid(instance_t instance, return; } - ptr2->second.outgoing_ip_addr = newOutgoingAddr; + struct sockaddr_in *sockaddr = (struct sockaddr_in *)&ptr2->second.ip; + sockaddr->sin_family = AF_INET; + memcpy(&sockaddr->sin_addr, &newOutgoingAddr, sizeof(newOutgoingAddr)); + AssertFatal(ptr2->second.ip.ss_family == AF_INET, "only IPv4 is supported\n"); ptr2->second.teid_outgoing = newOutgoingTeid; LOG_I(GTPU, - "[%ld] Tunnel Outgoing TEID updated to %x and address to %x\n", + "[%ld] Tunnel Outgoing TEID updated to %x and IPv4 address to " IPV4_ADDR "\n", instance, ptr2->second.teid_outgoing, - ptr2->second.outgoing_ip_addr); + IPV4_ADDR_FORMAT(sockaddr->sin_addr.s_addr)); + pthread_mutex_unlock(&globGtp.gtp_lock); return; } @@ -594,42 +569,48 @@ teid_t newGtpuCreateTunnel(instance_t instance, globGtp.te2ue_mapping[incoming_teid].callBackSDAP = callBackSDAP; globGtp.te2ue_mapping[incoming_teid].pdusession_id = (uint8_t)outgoing_bearer_id; - gtpv1u_bearer_t *tmp = &inst->ue2te_mapping[ue_id].bearers[outgoing_bearer_id]; + gtpv1u_bearer_t bearer = { + .sock_fd = (int) compatInst(instance), // avoid warning on narrowing conversion: instance is long, sock_fd is int + .teid_incoming = incoming_teid, + .teid_outgoing = outgoing_teid, + .outgoing_qfi = outgoing_qfi, + }; int addrs_length_in_bytes = remoteAddr.length / 8; - + struct sockaddr_in *sa4 = (struct sockaddr_in *)&bearer.ip; + struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)&bearer.ip; switch (addrs_length_in_bytes) { case 4: - memcpy(&tmp->outgoing_ip_addr, remoteAddr.buffer, 4); + memcpy(&sa4->sin_addr, remoteAddr.buffer, 4); + sa4->sin_family = AF_INET; + sa4->sin_port = htons(inst->get_dstport()); break; case 16: - memcpy(tmp->outgoing_ip6_addr.s6_addr, remoteAddr.buffer, 16); + AssertFatal(false, "IPv6 not supported\n"); break; case 20: - memcpy(&tmp->outgoing_ip_addr, remoteAddr.buffer, 4); - memcpy(tmp->outgoing_ip6_addr.s6_addr, remoteAddr.buffer + 4, 16); + AssertFatal(false, "dual-IPv4/v6 not supported\n"); + break; default: AssertFatal(false, "SGW Address size impossible"); } - tmp->teid_incoming = incoming_teid; - tmp->outgoing_port = inst->get_dstport(); - tmp->teid_outgoing = outgoing_teid; - tmp->outgoing_qfi = outgoing_qfi; + inst->ue2te_mapping[ue_id].bearers[outgoing_bearer_id] = bearer; pthread_mutex_unlock(&globGtp.gtp_lock); char ip4[INET_ADDRSTRLEN]; char ip6[INET6_ADDRSTRLEN]; LOG_I(GTPU, - "[%ld] Created tunnel for UE ID %lu, teid for incoming: %x, teid for outgoing %x to remote IPv4: %s, IPv6 %s\n", + "[%ld] Created tunnel for UE ID %lu, teid for incoming: %x, teid for outgoing %x to remote IPv4: %s, IPv6 %s, port %d\n", instance, ue_id, - tmp->teid_incoming, - tmp->teid_outgoing, - inet_ntop(AF_INET, (void *)&tmp->outgoing_ip_addr, ip4, INET_ADDRSTRLEN), - inet_ntop(AF_INET6, (void *)&tmp->outgoing_ip6_addr.s6_addr, ip6, INET6_ADDRSTRLEN)); + bearer.teid_incoming, + bearer.teid_outgoing, + inet_ntop(AF_INET, &sa4->sin_addr, ip4, INET_ADDRSTRLEN), + inet_ntop(AF_INET6, &sa6->sin6_addr, ip6, INET6_ADDRSTRLEN), + ntohs(sa4->sin_port)); return incoming_teid; } @@ -922,6 +903,13 @@ int gtpv1u_delete_ngu_tunnel(const instance_t instance, gtpv1u_gnb_delete_tunnel return newGtpuDeleteTunnels(instance, req->ue_id, req->num_pdusession, req->pdusession_id); } +static gtpv1u_bearer_t create_bearer(int socket, const struct sockaddr_in *addr, uint32_t teid, uint16_t seq) +{ + gtpv1u_bearer_t bearer = {.sock_fd = socket, .teid_outgoing = teid, .seqNum = seq}; + memcpy(&bearer.ip, addr, sizeof(*addr)); + return bearer; +} + static int Gtpv1uHandleEchoReq(int h, uint8_t *msgBuf, uint32_t msgBufLen, const struct sockaddr_in *addr) { Gtpv1uMsgHeaderT *msgHdr = (Gtpv1uMsgHeaderT *)msgBuf; @@ -939,17 +927,13 @@ static int Gtpv1uHandleEchoReq(int h, uint8_t *msgBuf, uint32_t msgBufLen, const uint16_t seq = ntohs(*(uint16_t *)(msgHdr + 1)); LOG_D(GTPU, "[%d] Received a echo request, TEID: %d, seq: %hu\n", h, msgHdr->teid, seq); uint8_t recovery[2] = {14, 0}; - return gtpv1uCreateAndSendMsg(h, - addr->sin_addr.s_addr, - htons(addr->sin_port), + gtpv1u_bearer_t bearer = create_bearer(h, addr, ntohl(msgHdr->teid), seq); + return gtpv1uCreateAndSendMsg(&bearer, GTP_ECHO_RSP, - ntohl(msgHdr->teid), recovery, sizeof recovery, true, false, - seq, - 0, NO_MORE_EXT_HDRS, NULL, 0); @@ -1185,17 +1169,14 @@ static int Gtpv1uHandleGpdu(int h, uint8_t *msgBuf, uint32_t msgBufLen, const st * 1 octet for padding + 1 octet for next extension header type, * according to TS 38.425: Fig. 5.5.2.2-1 and section 5.5.3.24*/ extensionHeader->length = 1 + sizeof(DlDataDeliveryStatus_flagsT) + 3 + 1 + 1; - gtpv1uCreateAndSendMsg(h, - addr->sin_addr.s_addr, - htons(addr->sin_port), + uint32_t teid = globGtp.te2ue_mapping[ntohl(msgHdr->teid)].outgoing_teid; + gtpv1u_bearer_t bearer = create_bearer(h, addr, teid, 0); + gtpv1uCreateAndSendMsg(&bearer, GTP_GPDU, - globGtp.te2ue_mapping[ntohl(msgHdr->teid)].outgoing_teid, NULL, 0, false, false, - 0, - 0, NR_RAN_CONTAINER, extensionHeader->buffer, extensionHeader->length); From 8d5501edc283c244111fb6c6a8cd7e3f80eb9d75 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 30 Jul 2025 13:35:11 +0200 Subject: [PATCH 357/964] Harmonize GTP log messages Make a common pattern, which makes it simpler to find them in gNB logs, and, maybe more importantly, link tunnel creation and update (the update message was missing the "incoming" TEID, so it is not easy to link to creation apart from the UE ID, but even then the UE might have multiple tunnels). --- openair3/ocp-gtpu/gtp_itf.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/openair3/ocp-gtpu/gtp_itf.cpp b/openair3/ocp-gtpu/gtp_itf.cpp index 3bc214df62..fec0f035eb 100644 --- a/openair3/ocp-gtpu/gtp_itf.cpp +++ b/openair3/ocp-gtpu/gtp_itf.cpp @@ -526,11 +526,19 @@ void GtpuUpdateTunnelOutgoingAddressAndTeid(instance_t instance, memcpy(&sockaddr->sin_addr, &newOutgoingAddr, sizeof(newOutgoingAddr)); AssertFatal(ptr2->second.ip.ss_family == AF_INET, "only IPv4 is supported\n"); ptr2->second.teid_outgoing = newOutgoingTeid; + char ip4[INET_ADDRSTRLEN]; + char ip6[INET6_ADDRSTRLEN]; + struct sockaddr_in *sa4 = (struct sockaddr_in *)sockaddr; + struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sockaddr; LOG_I(GTPU, - "[%ld] Tunnel Outgoing TEID updated to %x and IPv4 address to " IPV4_ADDR "\n", + "[%ld] UE ID %ld: Update tunnel TEID incoming %x outgoing %x to remote IPv4 %s, IPv6 %s, port %d\n", instance, + ue_id, + ptr2->second.teid_incoming, ptr2->second.teid_outgoing, - IPV4_ADDR_FORMAT(sockaddr->sin_addr.s_addr)); + inet_ntop(AF_INET, &sa4->sin_addr, ip4, INET_ADDRSTRLEN), + inet_ntop(AF_INET6, &sa6->sin6_addr, ip6, INET6_ADDRSTRLEN), + ntohs(sa4->sin_port)); pthread_mutex_unlock(&globGtp.gtp_lock); return; @@ -603,7 +611,7 @@ teid_t newGtpuCreateTunnel(instance_t instance, char ip4[INET_ADDRSTRLEN]; char ip6[INET6_ADDRSTRLEN]; LOG_I(GTPU, - "[%ld] Created tunnel for UE ID %lu, teid for incoming: %x, teid for outgoing %x to remote IPv4: %s, IPv6 %s, port %d\n", + "[%ld] UE ID %ld: Create tunnel TEID incoming %x outgoing %x to remote IPv4 %s, IPv6 %s, port %d\n", instance, ue_id, bearer.teid_incoming, @@ -817,7 +825,7 @@ int newGtpuDeleteAllTunnels(instance_t instance, ue_id_t ue_id) inst->ue2te_mapping.erase(ptrUe); pthread_mutex_unlock(&globGtp.gtp_lock); - LOG_I(GTPU, "[%ld] Deleted all tunnels for ue id %ld (%d tunnels deleted)\n", instance, ue_id, nb); + LOG_I(GTPU, "[%ld] UE ID %ld: Delete all tunnels (%d tunnels)\n", instance, ue_id, nb); return !GTPNOK; } From 0a5130cf106c50a6403db320e015f35578f48a96 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 31 Jul 2025 08:48:24 +0200 Subject: [PATCH 358/964] Remove unused control port number from F1 Remove these F1-C port numbers. The configuration is not actually applied, and the default F1-C port number 38472 (see F1AP_PORT_NUMBER) is hardcoded in the F1 module. For the moment, I leave the configuration option, in case we want to allow to configure the port numbers later). --- ci-scripts/conf_files/gnb-cu.sa.band78.106prb.conf | 2 -- ci-scripts/conf_files/gnb-cu.sa.f1.conf | 2 -- ci-scripts/conf_files/gnb-cucp.sa.f1.conf | 2 -- ci-scripts/conf_files/gnb-cucp.sa.f1.quectel.conf | 2 -- ci-scripts/conf_files/gnb-cuup.sa.f1.conf | 2 -- ci-scripts/conf_files/gnb-cuup.sa.f1.quectel.conf | 2 -- ci-scripts/conf_files/gnb-du.sa.band1.52prb.usrpb210.conf | 2 -- ci-scripts/conf_files/gnb-du.sa.band78.106prb.rfsim.conf | 2 -- ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf | 2 -- doc/F1AP/F1-design.md | 2 -- targets/PROJECTS/GENERIC-NR-5GC/CONF/cu_gnb.conf | 2 -- targets/PROJECTS/GENERIC-NR-5GC/CONF/du_gnb.conf | 2 -- targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-cu.sa.f1.conf | 2 -- .../GENERIC-NR-5GC/CONF/gnb-du.sa.band66.25prb.rfsim.pci0.conf | 2 -- .../GENERIC-NR-5GC/CONF/gnb-du.sa.band66.25prb.rfsim.pci1.conf | 2 -- .../CONF/gnb-du.sa.band77.273prb.fhi72.4x4-benetel650.conf | 2 -- ...gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650-mplane.conf | 2 -- .../CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650.conf | 2 -- .../GENERIC-NR-5GC/CONF/gnb-du.sa.band78.106prb.rfsim.pci0.conf | 2 -- .../GENERIC-NR-5GC/CONF/gnb-du.sa.band78.106prb.rfsim.pci1.conf | 2 -- 20 files changed, 40 deletions(-) diff --git a/ci-scripts/conf_files/gnb-cu.sa.band78.106prb.conf b/ci-scripts/conf_files/gnb-cu.sa.band78.106prb.conf index 311c8551fd..051ebd04fc 100644 --- a/ci-scripts/conf_files/gnb-cu.sa.band78.106prb.conf +++ b/ci-scripts/conf_files/gnb-cu.sa.band78.106prb.conf @@ -23,9 +23,7 @@ gNBs = local_s_address = "192.168.71.150"; remote_s_address = "192.168.71.171"; - local_s_portc = 501; local_s_portd = 2153; - remote_s_portc = 500; remote_s_portd = 2153; # ------- SCTP definitions diff --git a/ci-scripts/conf_files/gnb-cu.sa.f1.conf b/ci-scripts/conf_files/gnb-cu.sa.f1.conf index 84e5dbadb0..280281997e 100644 --- a/ci-scripts/conf_files/gnb-cu.sa.f1.conf +++ b/ci-scripts/conf_files/gnb-cu.sa.f1.conf @@ -23,9 +23,7 @@ gNBs = local_s_address = "127.0.0.4"; remote_s_address = "127.0.0.5"; - local_s_portc = 501; local_s_portd = 2153; - remote_s_portc = 500; remote_s_portd = 2153; # ------- SCTP definitions diff --git a/ci-scripts/conf_files/gnb-cucp.sa.f1.conf b/ci-scripts/conf_files/gnb-cucp.sa.f1.conf index 28bb7cfc33..214b5dd519 100644 --- a/ci-scripts/conf_files/gnb-cucp.sa.f1.conf +++ b/ci-scripts/conf_files/gnb-cucp.sa.f1.conf @@ -23,9 +23,7 @@ gNBs = local_s_address = "192.168.71.150"; remote_s_address = "0.0.0.0"; # multiple DUs - local_s_portc = 501; local_s_portd = 2152; - remote_s_portc = 500; remote_s_portd = 2152; # ------- SCTP definitions diff --git a/ci-scripts/conf_files/gnb-cucp.sa.f1.quectel.conf b/ci-scripts/conf_files/gnb-cucp.sa.f1.quectel.conf index 8cebc8640a..6a76eb7689 100644 --- a/ci-scripts/conf_files/gnb-cucp.sa.f1.quectel.conf +++ b/ci-scripts/conf_files/gnb-cucp.sa.f1.quectel.conf @@ -23,9 +23,7 @@ gNBs = local_s_address = "127.0.0.4"; remote_s_address = "127.0.0.5"; - local_s_portc = 501; local_s_portd = 2153; - remote_s_portc = 500; remote_s_portd = 2153; # ------- SCTP definitions diff --git a/ci-scripts/conf_files/gnb-cuup.sa.f1.conf b/ci-scripts/conf_files/gnb-cuup.sa.f1.conf index 5dd6c77a9c..e87ac862b1 100644 --- a/ci-scripts/conf_files/gnb-cuup.sa.f1.conf +++ b/ci-scripts/conf_files/gnb-cuup.sa.f1.conf @@ -22,9 +22,7 @@ gNBs = local_s_address = "192.168.72.161"; remote_s_address = "192.168.72.171"; - local_s_portc = 501; local_s_portd = 2153; - remote_s_portc = 500; remote_s_portd = 2153; # ------- SCTP definitions diff --git a/ci-scripts/conf_files/gnb-cuup.sa.f1.quectel.conf b/ci-scripts/conf_files/gnb-cuup.sa.f1.quectel.conf index b9f65cdf53..dbe510ea3f 100644 --- a/ci-scripts/conf_files/gnb-cuup.sa.f1.quectel.conf +++ b/ci-scripts/conf_files/gnb-cuup.sa.f1.quectel.conf @@ -22,9 +22,7 @@ gNBs = local_s_address = "127.0.0.6"; remote_s_address = "127.0.0.5"; - local_s_portc = 501; local_s_portd = 2153; - remote_s_portc = 500; remote_s_portd = 2153; # ------- SCTP definitions diff --git a/ci-scripts/conf_files/gnb-du.sa.band1.52prb.usrpb210.conf b/ci-scripts/conf_files/gnb-du.sa.band1.52prb.usrpb210.conf index 2af3185ffc..50bed1fb5d 100644 --- a/ci-scripts/conf_files/gnb-du.sa.band1.52prb.usrpb210.conf +++ b/ci-scripts/conf_files/gnb-du.sa.band1.52prb.usrpb210.conf @@ -163,9 +163,7 @@ MACRLCs = ( tr_n_preference = "f1"; local_n_address = "127.0.0.5"; remote_n_address = "127.0.0.4"; - local_n_portc = 500; local_n_portd = 2153; - remote_n_portc = 501; remote_n_portd = 2153; pusch_TargetSNRx10 = 200; pucch_TargetSNRx10 = 200; diff --git a/ci-scripts/conf_files/gnb-du.sa.band78.106prb.rfsim.conf b/ci-scripts/conf_files/gnb-du.sa.band78.106prb.rfsim.conf index fce5e6dc6e..328efe1b90 100644 --- a/ci-scripts/conf_files/gnb-du.sa.band78.106prb.rfsim.conf +++ b/ci-scripts/conf_files/gnb-du.sa.band78.106prb.rfsim.conf @@ -168,9 +168,7 @@ MACRLCs = ( tr_n_preference = "f1"; local_n_address = "192.168.71.171"; remote_n_address = "192.168.71.150"; - local_n_portc = 500; local_n_portd = 2153; - remote_n_portc = 501; remote_n_portd = 2153; pusch_TargetSNRx10 = 200; pucch_TargetSNRx10 = 200; diff --git a/ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf b/ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf index 45482642b9..408111630f 100644 --- a/ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf +++ b/ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf @@ -195,9 +195,7 @@ MACRLCs = ( tr_n_preference = "f1"; local_n_address = "127.0.0.5"; remote_n_address = "127.0.0.4"; - local_n_portc = 500; local_n_portd = 2153; - remote_n_portc = 501; remote_n_portd = 2153; pusch_TargetSNRx10 = 200; pucch_TargetSNRx10 = 200; diff --git a/doc/F1AP/F1-design.md b/doc/F1AP/F1-design.md index 65ea6b38cf..afc1e268b9 100644 --- a/doc/F1AP/F1-design.md +++ b/doc/F1AP/F1-design.md @@ -221,9 +221,7 @@ In the CU file: ignored, but we recommend to put `0.0.0.0` ("any") - Ports should match the ones in the DU config, but for simplicity and standards-conformity, simply set all to 2152: - - `local_s_portc` in CU should match `remote_n_portc` in DU - `local_s_portd` in CU should match `remote_n_portd` in DU - - `remote_s_portc` in CU should match `local_n_portc` in DU - `remote_s_portd` in CU should match `local_n_portd` in DU In the DU file: diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/cu_gnb.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/cu_gnb.conf index 1666ea4a70..3261f716c7 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/cu_gnb.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/cu_gnb.conf @@ -22,9 +22,7 @@ gNBs = local_s_address = "127.0.0.4"; remote_s_address = "127.0.0.3"; - local_s_portc = 501; local_s_portd = 2152; - remote_s_portc = 500; remote_s_portd = 2152; # ------- SCTP definitions diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/du_gnb.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/du_gnb.conf index 02b1e89b88..ef180cab63 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/du_gnb.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/du_gnb.conf @@ -168,9 +168,7 @@ MACRLCs = ( tr_n_preference = "f1"; local_n_address = "127.0.0.3"; remote_n_address = "127.0.0.4"; - local_n_portc = 500; local_n_portd = 2152; - remote_n_portc = 501; remote_n_portd = 2152; } diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-cu.sa.f1.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-cu.sa.f1.conf index f57725cc9b..87190eef4f 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-cu.sa.f1.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-cu.sa.f1.conf @@ -20,9 +20,7 @@ gNBs = local_s_if_name = "lo"; local_s_address = "127.0.0.3"; remote_s_address = "0.0.0.0"; # multiple DUs - local_s_portc = 501; local_s_portd = 2152; - remote_s_portc = 500; remote_s_portd = 2152; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band66.25prb.rfsim.pci0.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band66.25prb.rfsim.pci0.conf index c2e28725bd..c2401c29c5 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band66.25prb.rfsim.pci0.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band66.25prb.rfsim.pci0.conf @@ -166,9 +166,7 @@ MACRLCs = ({ local_n_if_name = "lo"; local_n_address = "127.0.0.4"; remote_n_address = "127.0.0.3"; - local_n_portc = 500; local_n_portd = 2152; - remote_n_portc = 501; remote_n_portd = 2152; pusch_FailureThres = 1000; }); diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band66.25prb.rfsim.pci1.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band66.25prb.rfsim.pci1.conf index c5c84c9919..f2e7113e74 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band66.25prb.rfsim.pci1.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band66.25prb.rfsim.pci1.conf @@ -166,9 +166,7 @@ MACRLCs = ({ local_n_if_name = "lo"; local_n_address = "127.0.0.5"; remote_n_address = "127.0.0.3"; - local_n_portc = 500; local_n_portd = 2152; - remote_n_portc = 501; remote_n_portd = 2152; pusch_FailureThres = 1000; }); diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.4x4-benetel650.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.4x4-benetel650.conf index a267d2e864..08548e62d6 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.4x4-benetel650.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.4x4-benetel650.conf @@ -175,9 +175,7 @@ MACRLCs = ( local_n_if_name = "enp193s0f0"; local_n_address = "172.21.16.51"; remote_n_address = "172.21.6.90"; - local_n_portc = 500; local_n_portd = 2153; - remote_n_portc = 501; remote_n_portd = 2153; pusch_TargetSNRx10 = 170; pucch_TargetSNRx10 = 230; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650-mplane.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650-mplane.conf index 28f9baf6f8..615ff5f3e4 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650-mplane.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650-mplane.conf @@ -175,9 +175,7 @@ MACRLCs = ( local_n_if_name = "enp193s0f0"; local_n_address = "172.21.16.51"; remote_n_address = "172.21.6.90"; - local_n_portc = 500; local_n_portd = 2153; - remote_n_portc = 501; remote_n_portd = 2153; pusch_TargetSNRx10 = 120; pucch_TargetSNRx10 = 200; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650.conf index 18f885945f..163871e45a 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650.conf @@ -175,9 +175,7 @@ MACRLCs = ( local_n_if_name = "enp193s0f0"; local_n_address = "172.21.16.51"; remote_n_address = "172.21.6.90"; - local_n_portc = 500; local_n_portd = 2153; - remote_n_portc = 501; remote_n_portd = 2153; pusch_TargetSNRx10 = 120; pucch_TargetSNRx10 = 200; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band78.106prb.rfsim.pci0.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band78.106prb.rfsim.pci0.conf index 3221813bef..97acbdc54e 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band78.106prb.rfsim.pci0.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band78.106prb.rfsim.pci0.conf @@ -163,9 +163,7 @@ MACRLCs = ({ local_n_if_name = "lo"; local_n_address = "127.0.0.4"; remote_n_address = "127.0.0.3"; - local_n_portc = 500; local_n_portd = 2152; - remote_n_portc = 501; remote_n_portd = 2152; pusch_FailureThres = 1000; }); diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band78.106prb.rfsim.pci1.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band78.106prb.rfsim.pci1.conf index c7d8cb3269..b05e1de4a4 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band78.106prb.rfsim.pci1.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band78.106prb.rfsim.pci1.conf @@ -163,9 +163,7 @@ MACRLCs = ({ local_n_if_name = "lo"; local_n_address = "127.0.0.5"; remote_n_address = "127.0.0.3"; - local_n_portc = 500; local_n_portd = 2152; - remote_n_portc = 501; remote_n_portd = 2152; pusch_FailureThres = 1000; }); From faef56e4323f4d9581010fc1d82159834d86cd74 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 31 Jul 2025 08:51:29 +0200 Subject: [PATCH 359/964] Remove old 4G F1 configuration files 4G F1 has been removed from the code base, so these configs are now useless. See also commit 9dc2282249d1 ("Remove 4G F1") --- .../PROJECTS/GENERIC-LTE-EPC/CONF/cu.lte.conf | 196 ------------------ .../CONF/du.lte.band7.10MHz.if4p5.conf | 102 --------- 2 files changed, 298 deletions(-) delete mode 100644 targets/PROJECTS/GENERIC-LTE-EPC/CONF/cu.lte.conf delete mode 100644 targets/PROJECTS/GENERIC-LTE-EPC/CONF/du.lte.band7.10MHz.if4p5.conf diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/cu.lte.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/cu.lte.conf deleted file mode 100644 index e486be3605..0000000000 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/cu.lte.conf +++ /dev/null @@ -1,196 +0,0 @@ -Active_eNBs = ( "eNB-CU-Eurecom-LTEBox"); -# Asn1_verbosity, choice in: none, info, annoying -Asn1_verbosity = "none"; - -eNBs = ( - { - ////////// Identification parameters: - eNB_ID = 0xe00; - - cell_type = "CELL_MACRO_ENB"; - - eNB_name = "eNB-CU-Eurecom-LTEBox"; - - // Tracking area code, 0x0000 and 0xfffe are reserved values - tracking_area_code = 1; - plmn_list = ( { mcc = 208; mnc = 95; mnc_length = 2; } ) - - nr_cellid = 12345678L - - tr_s_preference = "f1" - - remote_s_address = "192.168.12.4"; - local_s_address = "192.168.12.45"; - local_s_portc = 501; - remote_s_portc = 500; - local_s_portd = 601; - remote_s_portd = 600; - - ////////// Physical parameters: - - component_carriers = ( - { - node_function = "3GPP_eNodeB"; - node_timing = "synch_to_ext_device"; - node_synch_ref = 0; - frame_type = "FDD"; - tdd_config = 3; - tdd_config_s = 0; - prefix_type = "NORMAL"; - eutra_band = 7; - downlink_frequency = 2665000000L; - uplink_frequency_offset = -120000000; - Nid_cell = 0; - N_RB_DL = 50; - pbch_repetition = "FALSE"; - prach_root = 0; - prach_config_index = 0; - prach_high_speed = "DISABLE"; - prach_zero_correlation = 1; - prach_freq_offset = 2; - pucch_delta_shift = 1; - pucch_nRB_CQI = 0; - pucch_nCS_AN = 0; - pucch_n1_AN = 0; - pdsch_referenceSignalPower = -27; - pdsch_p_b = 0; - pusch_n_SB = 1; - pusch_enable64QAM = "DISABLE"; - pusch_hoppingMode = "interSubFrame"; - pusch_hoppingOffset = 0; - pusch_groupHoppingEnable = "ENABLE"; - pusch_groupAssignment = 0; - pusch_sequenceHoppingEnabled = "DISABLE"; - pusch_nDMRS1 = 1; - phich_duration = "NORMAL"; - phich_resource = "ONESIXTH"; - srs_enable = "DISABLE"; - /* - srs_BandwidthConfig =; - srs_SubframeConfig =; - srs_ackNackST =; - srs_MaxUpPts =; - */ - - pusch_p0_Nominal = -96; - pusch_alpha = "AL1"; - pucch_p0_Nominal = -104; - msg3_delta_Preamble = 6; - pucch_deltaF_Format1 = "deltaF2"; - pucch_deltaF_Format1b = "deltaF3"; - pucch_deltaF_Format2 = "deltaF0"; - pucch_deltaF_Format2a = "deltaF0"; - pucch_deltaF_Format2b = "deltaF0"; - - rach_numberOfRA_Preambles = 64; - rach_preamblesGroupAConfig = "DISABLE"; - /* - rach_sizeOfRA_PreamblesGroupA = ; - rach_messageSizeGroupA = ; - rach_messagePowerOffsetGroupB = ; - */ - rach_powerRampingStep = 4; - rach_preambleInitialReceivedTargetPower = -108; - rach_preambleTransMax = 10; - rach_raResponseWindowSize = 10; - rach_macContentionResolutionTimer = 48; - rach_maxHARQ_Msg3Tx = 4; - - pcch_default_PagingCycle = 128; - pcch_nB = "oneT"; - bcch_modificationPeriodCoeff= 2; - ue_TimersAndConstants_t300 = 1000; - ue_TimersAndConstants_t301 = 1000; - ue_TimersAndConstants_t310 = 1000; - ue_TimersAndConstants_t311 = 10000; - ue_TimersAndConstants_n310 = 20; - ue_TimersAndConstants_n311 = 1; - ue_TransmissionMode = 1; - - //Parameters for SIB18 - rxPool_sc_CP_Len = "normal"; - rxPool_sc_Period = "sf40"; - rxPool_data_CP_Len = "normal"; - rxPool_ResourceConfig_prb_Num = 20; - rxPool_ResourceConfig_prb_Start = 5; - rxPool_ResourceConfig_prb_End = 44; - rxPool_ResourceConfig_offsetIndicator_present = "prSmall"; - rxPool_ResourceConfig_offsetIndicator_choice = 0; - rxPool_ResourceConfig_subframeBitmap_present = "prBs40"; - rxPool_ResourceConfig_subframeBitmap_choice_bs_buf = "00000000000000000000"; - rxPool_ResourceConfig_subframeBitmap_choice_bs_size = 5; - rxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused = 0; - /* - rxPool_dataHoppingConfig_hoppingParameter = 0; - rxPool_dataHoppingConfig_numSubbands = "ns1"; - rxPool_dataHoppingConfig_rbOffset = 0; - rxPool_commTxResourceUC-ReqAllowed = "TRUE"; - */ - - // Parameters for SIB19 - discRxPool_cp_Len = "normal" - discRxPool_discPeriod = "rf32" - discRxPool_numRetx = 1; - discRxPool_numRepetition = 2; - discRxPool_ResourceConfig_prb_Num = 5; - discRxPool_ResourceConfig_prb_Start = 3; - discRxPool_ResourceConfig_prb_End = 21; - discRxPool_ResourceConfig_offsetIndicator_present = "prSmall"; - discRxPool_ResourceConfig_offsetIndicator_choice = 0; - discRxPool_ResourceConfig_subframeBitmap_present = "prBs40"; - discRxPool_ResourceConfig_subframeBitmap_choice_bs_buf = "f0ffffffff"; - discRxPool_ResourceConfig_subframeBitmap_choice_bs_size = 5; - discRxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused = 0; - } - ); - - - srb1_parameters : - { - # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] - timer_poll_retransmit = 80; - - # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] - timer_reordering = 35; - - # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] - timer_status_prohibit = 0; - - # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] - poll_pdu = 4; - - # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] - poll_byte = 99999; - - # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] - max_retx_threshold = 4; - } - - # ------- SCTP definitions - SCTP : - { - # Number of streams to use in input/output - SCTP_INSTREAMS = 2; - SCTP_OUTSTREAMS = 2; - }; - - - ////////// MME parameters: - mme_ip_address = ({ ipv4 = "127.0.1.10"; }); - - NETWORK_INTERFACES : { - ENB_IPV4_ADDRESS_FOR_S1_MME = "127.0.1.30/24"; - ENB_IPV4_ADDRESS_FOR_S1U = "127.0.1.30/24"; - ENB_PORT_FOR_S1U = 2152; # Spec 2152 - ENB_IPV4_ADDRESS_FOR_X2C = "127.0.1.30/24"; - ENB_PORT_FOR_X2C = 36422; # Spec 36422 - }; - } -); - -log_config = { - global_log_level = "info"; - pdcp_log_level = "info"; - rrc_log_level = "info"; - gtp_log_level = "info"; -}; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/du.lte.band7.10MHz.if4p5.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/du.lte.band7.10MHz.if4p5.conf deleted file mode 100644 index f66bc1b29e..0000000000 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/du.lte.band7.10MHz.if4p5.conf +++ /dev/null @@ -1,102 +0,0 @@ -Active_eNBs = ( "eNB-Eurecom-DU"); -# Asn1_verbosity, choice in: none, info, annoying -Asn1_verbosity = "none"; - -eNBs = -( - { - ////////// Identification parameters: - eNB_CU_ID = 0xe00; - - eNB_name = "eNB-Eurecom-DU"; - - // Tracking area code, 0x0000 and 0xfffe are reserved values - tracking_area_code = 1; - plmn_list = ( { mcc = 208; mnc = 95; mnc_length = 2; } ) - - nr_cellid = 12345678L - - ////////// Physical parameters: - - component_carriers = ( - { - node_function = "3GPP_eNODEB"; - node_timing = "synch_to_ext_device"; - node_synch_ref = 0; - frame_type = "FDD"; - tdd_config = 3; - tdd_config_s = 0; - prefix_type = "NORMAL"; - eutra_band = 7; - downlink_frequency = 2665000000L; - uplink_frequency_offset = -120000000; - Nid_cell = 0; - N_RB_DL = 50; - Nid_cell_mbsfn = 0; - nb_antenna_ports = 1; - nb_antennas_tx = 1; - nb_antennas_rx = 1; - tx_gain = 90; - rx_gain = 125; - - pucch_deltaF_Format1 = "deltaF2"; - pucch_deltaF_Format1b = "deltaF3"; - pucch_deltaF_Format2 = "deltaF0"; - pucch_deltaF_Format2a = "deltaF0"; - pucch_deltaF_Format2b = "deltaF0"; - } - ); - - - # ------- SCTP definitions - SCTP : - { - # Number of streams to use in input/output - SCTP_INSTREAMS = 2; - SCTP_OUTSTREAMS = 2; - }; - } -); - -MACRLCs = ( - { - num_cc = 1; - tr_s_preference = "local_L1"; - tr_n_preference = "f1"; - remote_n_address = "127.0.0.4"; - local_n_address = "127.0.0.3"; - local_n_portc = 500; - remote_n_portc = 501; - local_n_portd = 600; - remote_n_portd = 601; - } -); - -L1s = ( - { - num_cc = 1; - tr_n_preference = "local_mac"; - } -); - -RUs = ( - { - local_rf = "yes"; - nb_tx = 1; - nb_rx = 1; - att_tx = 10; - att_rx = 10; - bands = [7]; - max_pdschReferenceSignalPower = -27; - max_rxgain = 125; - eNB_instances = [0]; - } -); - -log_config = { - global_log_level = "info"; - hw_log_level = "info"; - phy_log_level = "info"; - mac_log_level = "info"; - rlc_log_level = "info"; -}; From 6bf88bd3d9f8db8bffe7ac3e09aaefc3bb838486 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 4 Aug 2025 08:36:42 +0200 Subject: [PATCH 360/964] Remove F1 interface names from configuration files These options are not taken into account, they are not even defined in the configuration module. --- targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-cu.sa.f1.conf | 1 - .../GENERIC-NR-5GC/CONF/gnb-du.sa.band66.25prb.rfsim.pci0.conf | 1 - .../GENERIC-NR-5GC/CONF/gnb-du.sa.band66.25prb.rfsim.pci1.conf | 1 - .../CONF/gnb-du.sa.band77.273prb.fhi72.4x4-benetel650.conf | 1 - .../gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650-mplane.conf | 1 - .../CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650.conf | 1 - .../GENERIC-NR-5GC/CONF/gnb-du.sa.band78.106prb.rfsim.pci0.conf | 1 - .../GENERIC-NR-5GC/CONF/gnb-du.sa.band78.106prb.rfsim.pci1.conf | 1 - 8 files changed, 8 deletions(-) diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-cu.sa.f1.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-cu.sa.f1.conf index 87190eef4f..102c23018e 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-cu.sa.f1.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-cu.sa.f1.conf @@ -17,7 +17,6 @@ gNBs = tr_s_preference = "f1"; - local_s_if_name = "lo"; local_s_address = "127.0.0.3"; remote_s_address = "0.0.0.0"; # multiple DUs local_s_portd = 2152; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band66.25prb.rfsim.pci0.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band66.25prb.rfsim.pci0.conf index c2401c29c5..f2ac964033 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band66.25prb.rfsim.pci0.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band66.25prb.rfsim.pci0.conf @@ -163,7 +163,6 @@ MACRLCs = ({ num_cc = 1; tr_s_preference = "local_L1"; tr_n_preference = "f1"; - local_n_if_name = "lo"; local_n_address = "127.0.0.4"; remote_n_address = "127.0.0.3"; local_n_portd = 2152; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band66.25prb.rfsim.pci1.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band66.25prb.rfsim.pci1.conf index f2e7113e74..96acca0d10 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band66.25prb.rfsim.pci1.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band66.25prb.rfsim.pci1.conf @@ -163,7 +163,6 @@ MACRLCs = ({ num_cc = 1; tr_s_preference = "local_L1"; tr_n_preference = "f1"; - local_n_if_name = "lo"; local_n_address = "127.0.0.5"; remote_n_address = "127.0.0.3"; local_n_portd = 2152; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.4x4-benetel650.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.4x4-benetel650.conf index 08548e62d6..5c6506beb3 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.4x4-benetel650.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.4x4-benetel650.conf @@ -172,7 +172,6 @@ MACRLCs = ( num_cc = 1; tr_s_preference = "local_L1"; tr_n_preference = "f1"; - local_n_if_name = "enp193s0f0"; local_n_address = "172.21.16.51"; remote_n_address = "172.21.6.90"; local_n_portd = 2153; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650-mplane.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650-mplane.conf index 615ff5f3e4..522266a70e 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650-mplane.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650-mplane.conf @@ -172,7 +172,6 @@ MACRLCs = ( num_cc = 1; tr_s_preference = "local_L1"; tr_n_preference = "f1"; - local_n_if_name = "enp193s0f0"; local_n_address = "172.21.16.51"; remote_n_address = "172.21.6.90"; local_n_portd = 2153; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650.conf index 163871e45a..90692c7b8e 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650.conf @@ -172,7 +172,6 @@ MACRLCs = ( num_cc = 1; tr_s_preference = "local_L1"; tr_n_preference = "f1"; - local_n_if_name = "enp193s0f0"; local_n_address = "172.21.16.51"; remote_n_address = "172.21.6.90"; local_n_portd = 2153; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band78.106prb.rfsim.pci0.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band78.106prb.rfsim.pci0.conf index 97acbdc54e..fa456a03cf 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band78.106prb.rfsim.pci0.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band78.106prb.rfsim.pci0.conf @@ -160,7 +160,6 @@ MACRLCs = ({ num_cc = 1; tr_s_preference = "local_L1"; tr_n_preference = "f1"; - local_n_if_name = "lo"; local_n_address = "127.0.0.4"; remote_n_address = "127.0.0.3"; local_n_portd = 2152; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band78.106prb.rfsim.pci1.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band78.106prb.rfsim.pci1.conf index b05e1de4a4..350ce578d3 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band78.106prb.rfsim.pci1.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band78.106prb.rfsim.pci1.conf @@ -160,7 +160,6 @@ MACRLCs = ({ num_cc = 1; tr_s_preference = "local_L1"; tr_n_preference = "f1"; - local_n_if_name = "lo"; local_n_address = "127.0.0.5"; remote_n_address = "127.0.0.3"; local_n_portd = 2152; From 1becaf06714c288212cb1f9907f09e3b0df6b1cf Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Wed, 30 Jul 2025 15:42:02 -0400 Subject: [PATCH 361/964] Fix periodic CSI scheduling in UE Changed the search structure to have periodic resoruce id in the outer loop and configured resource set as inner loop to prevent configuring resource that is not needed. Use const for input pointers. --- openair2/LAYER2/NR_MAC_UE/mac_proto.h | 2 +- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 21 ++++++++++---------- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 2 +- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index aacbbdcab2..dd29351629 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -289,7 +289,7 @@ void nr_ue_pucch_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, int slotP); void nr_schedule_csirs_reception(NR_UE_MAC_INST_t *mac, int frame, int slot); void nr_schedule_csi_for_im(NR_UE_MAC_INST_t *mac, int frame, int slot); void configure_csi_resource_mapping(fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu, - NR_CSI_RS_ResourceMapping_t *resourceMapping, + const NR_CSI_RS_ResourceMapping_t *resourceMapping, uint32_t bwp_size, uint32_t bwp_start); diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 8a892557b2..de8dbb47e4 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -249,26 +249,27 @@ void nr_ue_decode_mib(NR_UE_MAC_INST_t *mac, int cc_id) } static void configure_ratematching_csi(fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_pdu, - fapi_nr_dl_config_request_t *dl_config, + const fapi_nr_dl_config_request_t *dl_config, int rnti_type, int frame, int slot, int mu, int slots_per_frame, - NR_PDSCH_Config_t *pdsch_config) + const NR_PDSCH_Config_t *pdsch_config) { // only for C-RNTI, MCS-C-RNTI, CS-RNTI (and only C-RNTI is supported for now) if (rnti_type != TYPE_C_RNTI_) return; if (pdsch_config && pdsch_config->zp_CSI_RS_ResourceToAddModList) { - for (int i = 0; i < pdsch_config->zp_CSI_RS_ResourceToAddModList->list.count; i++) { - NR_ZP_CSI_RS_Resource_t *zp_res = pdsch_config->zp_CSI_RS_ResourceToAddModList->list.array[i]; - NR_ZP_CSI_RS_ResourceId_t id = zp_res->zp_CSI_RS_ResourceId; - NR_SetupRelease_ZP_CSI_RS_ResourceSet_t *zp_set = pdsch_config->p_ZP_CSI_RS_ResourceSet; - AssertFatal(zp_set && zp_set->choice.setup, "Only periodic ZP resource set is implemented\n"); - bool found = false; - for (int j = 0; j < zp_set->choice.setup->zp_CSI_RS_ResourceIdList.list.count; j++) { + bool found = false; + const NR_SetupRelease_ZP_CSI_RS_ResourceSet_t *zp_set = pdsch_config->p_ZP_CSI_RS_ResourceSet; + AssertFatal(zp_set && zp_set->choice.setup, "Only periodic ZP resource set is implemented\n"); + const NR_ZP_CSI_RS_Resource_t *zp_res = NULL; + for (int j = 0; j < zp_set->choice.setup->zp_CSI_RS_ResourceIdList.list.count; j++) { + for (int i = 0; i < pdsch_config->zp_CSI_RS_ResourceToAddModList->list.count; i++) { + zp_res = pdsch_config->zp_CSI_RS_ResourceToAddModList->list.array[i]; + NR_ZP_CSI_RS_ResourceId_t id = zp_res->zp_CSI_RS_ResourceId; if (*zp_set->choice.setup->zp_CSI_RS_ResourceIdList.list.array[j] == id) { found = true; break; @@ -291,7 +292,7 @@ static void configure_ratematching_csi(fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsc for (int i = 0; i < dl_config->number_pdus; i++) { // This assumes that CSI-RS are scheduled before this moment which is true in current implementation - fapi_nr_dl_config_request_pdu_t *csi_req = &dl_config->dl_config_list[i]; + const fapi_nr_dl_config_request_pdu_t *csi_req = &dl_config->dl_config_list[i]; if (csi_req->pdu_type == FAPI_NR_DL_CONFIG_TYPE_CSI_RS) { AssertFatal(dlsch_pdu->numCsiRsForRateMatching < NFAPI_MAX_NUM_CSI_RATEMATCH, "csiRsForRateMatching out of bounds\n"); dlsch_pdu->csiRsForRateMatching[dlsch_pdu->numCsiRsForRateMatching] = csi_req->csirs_config_pdu.csirs_config_rel15; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 6c257bcacf..5eaf492304 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -1919,7 +1919,7 @@ uint8_t set_csirs_measurement_bitmap(NR_CSI_MeasConfig_t *csi_measconfig, NR_CSI } void configure_csi_resource_mapping(fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu, - NR_CSI_RS_ResourceMapping_t *resourceMapping, + const NR_CSI_RS_ResourceMapping_t *resourceMapping, uint32_t bwp_size, uint32_t bwp_start) { From 61ea0a9e81a4bd3b048a776bb8be65cf44335741 Mon Sep 17 00:00:00 2001 From: Xin Zhe Khooi Date: Fri, 28 Mar 2025 03:00:19 +0000 Subject: [PATCH 362/964] ldpc_t2: generalize for broader BBDEV support (ACC100/200) - Generalized LDPC T2 implementation to support other DPDK BBDEV accelerators (e.g., Intel ACC100/200) - Added BBDEV capability checks during initialization - Introduced LLR scaling to improve decoding performance on Intel ACC cards - Implemented self-managed HARQ buffers for ACC200 (no internal HARQ memory) - Library usage documentation update, and added developer documentation Co-authored-by: Romain Beurdouche --- doc/LDPC_T2_OFFLOAD_SETUP.md | 307 ++++++-- openair1/PHY/CODING/DOC/LDPCImplementation.md | 2 +- .../nrLDPC_coding_t2/CMakeLists.txt | 24 +- .../nrLDPC_coding/nrLDPC_coding_t2/README.md | 143 ++++ .../nrLDPC_coding_t2/nrLDPC_coding_t2.c | 686 +++++++++++++----- .../nrLDPC_coding_t2/nrLDPC_coding_t2.h | 5 +- 6 files changed, 928 insertions(+), 239 deletions(-) create mode 100644 openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_t2/README.md diff --git a/doc/LDPC_T2_OFFLOAD_SETUP.md b/doc/LDPC_T2_OFFLOAD_SETUP.md index 24d36e39cf..0e9506db78 100644 --- a/doc/LDPC_T2_OFFLOAD_SETUP.md +++ b/doc/LDPC_T2_OFFLOAD_SETUP.md @@ -7,7 +7,7 @@ - OAI T1/T2 LDPC offload + OAI LDPC offload (O-RAN AAL/DPDK BBDEV) @@ -16,19 +16,57 @@ [[_TOC_]] -This documentation aims to provide a tutorial for AMD Xilinx T2 Telco card integration into OAI and its usage. +This documentation describes the integration of LDPC coding for lookaside acceleration using O-RAN AAL/DPDK BBDEV in OAI, along with its usage. +For details on the implementation, please consult the [developer notes](../openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_t2/README.md). # Requirements - - bitstream image and PMD driver for the T2 card provided by AccelerComm - - DPDK 20.11.9 with patch from Accelercomm: version ACCL_BBDEV_DPDK20.11.3_ldpc_3.1.918.patch - - tested on RHEL7.9, RHEL9.2, Ubuntu 22.04 +In principle, any lookaside LDPC accelerator supporting the O-RAN AAL/DPDK BBDEV should work. +However, the current implementation has only been validated for the Xilinx T2, Intel ACC100, and Intel ACC200 (VRB1). +Therefore, your mileage may vary when using other BBDEV devices as there may be some hardware-specific changes required -- contributions are welcome! -# DPDK setup +## DPDK Version Requirements + +The following DPDK versions are supported: +- For the Xilinx T2 card, DPDK20.11+ is supported. +- As for the Intel ACC100/ACC200, only DPDK22.11+ is supported. + +## Tested Devices/ DPDK versions + +### Xilinx T2 + +- DPDK20.11.9*. +- DPDK22.11.7*. +> Note: FPGA bitstream image and the corresponding patch file (e.g., `ACCL_BBDEV_DPDK20.11.3_ldpc_3.1.918.patch` for DPDK20.11) from Accelercomm required. + +### Intel ACC100 + +- DPDK22.11.7*. +- DPDK23.11.3*. +- DPDK24.11.2. +> Note: [Patch]((https://github.com/DPDK/dpdk/commit/fdde63a1dfc129d0a510a831aa98253b36a2a1cd)) required for pre-DPDK24.11 versions when using the Intel ACC100. + +### Intel ACC200 (also known as VRB1) +- DPDK22.11.7. +- DPDK23.11.3. +- DPDK24.11.2. + +# System Setup ## DPDK installation -*Note: Following instructions are valid for ACCL_BBDEV_DPDK20.11.3_ldpc_3.1.918.patch version, which is compatible with DPDK 20.11.9. Installation steps, which should be followed for older versions of the patch file (for example ACL_BBDEV_DPDK20.11.3_BL_1006_build_1105_dev_branch_MCT_optimisations_1106_physical_std.patch) are present in older version of this documentation, under the tag 2023.w48.* -``` +> Important: +> - If you are using the Xilinx T2 card, you will need to apply the vendor-supplied patches before compiling DPDK. +> - If you are using the Intel ACC100, you will need to [patch](https://github.com/DPDK/dpdk/commit/fdde63a1dfc129d0a510a831aa98253b36a2a1cd) the ACC100's driver if you are using DPDK22.11 or DPDK23.11. + + +Refer to the guide [here](./ORAN_FHI7.2_Tutorial.md?ref_type=heads#dpdk-data-plane-development-kit) to install, and then validate your DPDK installation. + +
+ Notes on DPDK patching/installation for Xilinx T2. + +*Note: The following instructions apply to `ACCL_BBDEV_DPDK20.11.3_ldpc_3.1.918.patch`, compatible with DPDK 20.11.9. For older patches (e.g., `ACL_BBDEV_DPDK20.11.3_BL_1006_build_1105_dev_branch_MCT_optimisations_1106_physical_std.patch`), refer to the T2 documentation in `2023.w48`.* + +```bash # Get DPDK source code git clone https://github.com/DPDK/dpdk-stable.git ~/dpdk-stable cd ~/dpdk-stable @@ -37,50 +75,127 @@ git apply ~/ACL_BBDEV_DPDK20.11.3_ldpc_3.1.918.patch ``` Replace `~/ACL_BBDEV_DPDK20.11.3_ldpc_3.1.918.patch` by patch file provided by Accelercomm. -``` + +If you would like to install DPDK to a custom directory, here is an example. +```bash cd ~/dpdk-stable -meson setup build -# meson setup --prefix=/opt/dpdk-t2 build for installation with non-default installation prefix +# meson setup build +meson setup --prefix=/opt/dpdk-t2 build # for installation with non-default installation prefix cd build ninja sudo ninja install sudo ldconfig + ``` -## DPDK configuration - - load required kernel module +
+ +## System configuration + +### Setting up Hugepages + +First, we must setup hugepages on the system. +In our setup, we setup 16 of the 1G hugepages. +Apart from 1G, 2MB hugepages works too, but make sure to allocate a sufficient number of them. + ``` -sudo modprobe vfio-pci -``` - - check presence of the card and its PCI addres on the host machine -``` -lspci | grep "Xilinx" -``` - - bind the card with vfio-pci driver -``` -sudo python3 ~/dpdk-stable/usertools/dpdk-devbind.py --bind=vfio-pci 41:00.0 -``` -Replace PCI address of the card *41:00.0* by address detected by *lspci | grep "Xilinx"* command - - hugepages setup (10 x 1GB hugepages) -``` -sudo python3 ~/dpdk-stable/usertools/dpdk-hugepages.py -p 1G --setup 10G +# sudo dpdk-hugepages.py -p 1G --setup 16G ``` -*Note: device binding and hugepages setup has to be done after every reboot of -the host machine* +### Locating the Accelerator -# Modifications in the OAI code -## DPDK lib and PMD path specification -If DPDK library was installed into custom path, you have to point to the right directory with `PKG_CONFIG_PATH`, prior to the OAI build. Sample command to set the DPDK path to `/opt/dpdk-t2/lib64/pkgconfig/`: +Next, we check whether our system can detect our accelerator using `dpdk-devbind.py`. +You should see Baseband devices detected by DPDK, as follows: ``` -export PKG_CONFIG_PATH=/opt/dpdk-t2/lib64/pkgconfig/:$PKG_CONFIG_PATH +# sudo dpdk-devbind.py -s +... +Baseband devices using DPDK-compatible driver +============================================= +0000:f7:00.0 'Device 57c0' unused=vfio-pci +... ``` -# OAI Build +As you can see here, our Intel ACC200 has the address of `0000:f7:00.0`. +Depending on the accelerator you are using, the address may vary. + +### Loading VFIO-PCI and enabling SR-IOV +Following, make sure to load the `vfio-pci` kernel modules and ensure that SR-IOV is enabled. + +``` +# sudo modprobe vfio-pci enable_sriov=1 disable_idle_d3=1 +``` + +### Binding the Accelerator with `vfio-pci` + +Lastly, we bind our accelerator with the `vfio-pci` driver. +``` +# sudo dpdk-devbind.py --bind=vfio-pci 0000:f7:00.0 +``` + +> Note: For the Xilinx T2, we can use this device directly. +If you use an Intel vRAN accelerator, read on. + +### Additional Steps for Intel vRAN Accelerators + +> IMPORTANT NOTE: +> - Currently, we only support using the Virtual Functions (VFs) of the Intel vRAN accelerators, but not the Physical Function (PF). +> - One key advantage of using VFs is that this allows us to share the accelerator with other DU instances on the same machine, which is common in practice. + +If you are using an Intel vRAN accelerator, you will need to use the [pf_bb_config](https://github.com/intel/pf-bb-config) tool to configure the accelerator beforehand. + +#### pf_bb_config +For more details, please consult the `pf_bb_config` README. + +``` +# git clone https://github.com/intel/pf-bb-config +# cd ~/pf-bb-config +# ./build.sh +``` +This clones and builds the `pf_bb_config` binary. + +Next, we show an example for the Intel ACC200. +We use an existing configuration located at `./vrb1/vrb1_config_16vf.cfg`. + +Here, it is necessary to specify a VFIO token (in this case, we use the UUID `00112233-4455-6677-8899-aabbccddeeff`). +Note that in practice, a random UUID should be used. +``` +# sudo ./pf_bb_config VRB1 -v 00112233-4455-6677-8899-aabbccddeeff -c vrb1/vrb1_config_16vf.cfg +== pf_bb_config Version v25.01-0-g812e032 == +VRB1 PF [0000:f7:00.0] configuration complete! +Log file = /var/log/pf_bb_cfg_0000:f7:00.0.log +``` + +#### Creating VFs + +Finally, we create the VF(s) for our accelerator. +In this example, we only create one SR-IOV VF. +``` +# echo 1 | sudo tee /sys/bus/pci/devices/0000:f7:00.0/sriov_numvfs +``` + +If you encounter any error when creating the VF(s), e.g., `tee: '/sys/bus/pci/devices/0000:f7:00.0/sriov_numvfs': No such file or directory`, then try enabling SR-IOV again. +``` +# echo 1 | sudo tee /sys/module/vfio_pci/parameters/enable_sriov +``` + +After you have successfully created the VF, you should see an additional baseband device, in our case, it is `0000:f7:00.1`. +We will use this device with OAI later. +The newly created VF should also be using the same `vfio-pci` driver as the PF, if it is not, you will need to do a `dpdk-devbind.py` to bind it with `vfio-pci`. +``` +# sudo dpdk-devbind.py -s +... +Baseband devices using DPDK-compatible driver +============================================= +0000:f7:00.0 'Device 57c0' drv=vfio-pci unused= +0000:f7:00.1 'Device 57c0' drv=vfio-pci unused= +... +``` + +# Building OAI with ORAN-AAL OTA deployment is precisely described in the following tutorial: - [NR_SA_Tutorial_COTS_UE](https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/develop/doc/NR_SA_Tutorial_COTS_UE.md) -Instead of section *3.2 Build OAI gNB* from the tutorial, run following commands: +Instead of section *3.2 Build OAI gNB* from the tutorial, run the following commands: -``` +```bash # Get openairinterface5g source code git clone https://gitlab.eurecom.fr/oai/openairinterface5g.git ~/openairinterface5g cd ~/openairinterface5g @@ -97,21 +212,35 @@ cd cmake_targets ./build_oai -w USRP --ninja --gNB -P --build-lib "ldpc_t2" -C ``` -Shared object file *libldpc_t2.so* is created during the compilation. This object is conditionally compiled. Selection of the library to compile is done using *--build-lib ldpc_t2*. +A shared object file `libldpc_t2.so` will be created during the compilation. +This object is conditionally compiled. +The selection of the library to compile is done using `--build-lib ldpc_t2`. -*Required poll mode driver has to be present on the host machine and required DPDK version has to be installed on the host, prior to the build of OAI* +> Note: The required DPDK poll mode driver has to be present on the host machine and required DPDK version has to be installed on the host, prior to building OAI. -# Setup of T2-related DPDK EAL parameters -To configure T2-related DPDK Environment Abstraction Layer (EAL) parameters, you can set the following parameters via the command line of PHY simulators or softmodem: -- `nrLDPC_coding_t2.dpdk_dev` - **mandatory** parameter, specifies PCI address of the T2 card. PCI address of the T2 card can be detected by `lspci | grep "Xilinx"` command. -- `nrLDPC_coding_t2.dpdk_core_list` - **mandatory** parameter, specifies CPU cores assigned to DPDK for T2 processing. Ensure that the CPU cores specified in *nrLDPC_coding_t2.dpdk_core_list* are available and not used by other processes to avoid conflicts. -- `nrLDPC_coding_t2.dpdk_prefix` - DPDK shared data file prefix, by default set to *b6*. +# O-RAN AAL DPDK EAL parameters +To configure O-RAN AAL/DPDK BBDEV, you can set the following parameters via the command line of PHY simulators or nr-softmodem: -**Note:** These parameters can also be provided in a configuration file: +- `nrLDPC_coding_t2.dpdk_dev` - **mandatory** parameter, specifies the PCI address of our accelerator. It must follow the format `WWWW:XX:YY.Z`. + +- `nrLDPC_coding_t2.dpdk_core_list` - **mandatory** parameter, specifies the CPU cores assigned to DPDK . +Ensure that the CPU cores specified in `nrLDPC_coding_t2.dpdk_core_list` are available and not used by other processes to avoid conflicts. + +- `nrLDPC_coding_t2.dpdk_prefix` - optional parameter, DPDK shared data file prefix, by default set to *b6*. + +- `nrLDPC_coding_t2.vfio_vf_token` - optional parameter, VFIO token set for the VF, if applicable. + +- `nrLDPC_coding_t2.num_harq_codeblock` - optional parameter, size of the HARQ buffer in terms of the number of 32kB blocks, by default set to *512* (maximum for the T2; as for the ACCs, this can be further increased). + +- `nrLDPC_coding_t2.eal_init_bbdev` - optional parameter, set this to 1 when using with FHI72 with the Intel ACCs. For the T2, this is not required. + +**Note:** These parameters can also be provided in a configuration file. +Example for the ACC200: ``` nrLDPC_coding_t2 : { - dpdk_dev : "41:00.0"; + dpdk_dev : "0000:f7:00.1"; dpdk_core_list : "14-15"; + vfio_vf_token: "00112233-4455-6677-8899-aabbccddeeff"; }; loader : { @@ -121,38 +250,90 @@ loader : { }; ``` -# 5G PHY simulators +# Running OAI with O-RAN AAL -## nr_ulsim test -Offload of the channel decoding to the T2 card is in nr_ulsim specified by *--loader.ldpc.shlibversion _t2* option. Example command for running nr_ulsim with LDPC decoding offload to the T2 card: -``` +In general, to offload of the channel coding to the LDPC accelerator, we use use the `--loader.ldpc.shlibversion _t2` option. + +## 5G PHY simulators + +### nr_ulsim + +Example command: +```bash cd ~/openairinterface5g source oaienv cd cmake_targets/ran_build/build -sudo ./nr_ulsim -n100 -s20 -m20 -r273 -R273 --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev 01:00.0 --nrLDPC_coding_t2.dpdk_core_list 0-1 -``` -## nr_dlsim test -Offload of the channel encoding to the AMD Xilinx T2 card is in nr_dlsim specified by *-c* option. Example command for running nr_dlsim with LDPC encoding offload to the T2 card: +sudo ./nr_ulsim -n100 -s20 -m20 -r273 -R273 --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev 0000:f7:00.1 --nrLDPC_coding_t2.dpdk_core_list 0-1 --nrLDPC_coding_t2.vfio_vf_token 00112233-4455-6677-8899-aabbccddeeff ``` +### nr_dlsim + +Example command: +```bash cd ~/openairinterface5g source oaienv cd cmake_targets/ran_build/build -sudo ./nr_dlsim -n300 -s30 -R 106 -e 27 --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev 01:00.0 --nrLDPC_coding_t2.dpdk_core_list 0-1 +sudo ./nr_dlsim -n300 -s30 -R 106 -e 27 --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev 0000:f7:00.1 --nrLDPC_coding_t2.dpdk_core_list 0-1 --nrLDPC_coding_t2.vfio_vf_token 00112233-4455-6677-8899-aabbccddeeff ``` -# OTA test -Offload of the channel encoding and decoding to the AMD Xilinx T2 card is enabled by *--loader.ldpc.shlibversion _t2* option. +## OTA test -## Run OAI gNB with USRP B210 -``` +### Running OAI gNB with USRP B210/FHI72 + +Example command: +```bash cd ~/openairinterface5g source oaienv cd cmake_targets/ran_build/build -sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev 01:00.0 --nrLDPC_coding_t2.dpdk_core_list 0-1 +sudo ./nr-softmodem -O ~/gnb.conf --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev 0000:f7:00.1 --nrLDPC_coding_t2.dpdk_core_list 14-15 --nrLDPC_coding_t2.vfio_vf_token 00112233-4455-6677-8899-aabbccddeeff --nrLDPC_coding_t2.eal_init_bbdev 1 ``` -# Limitations -## AMD Xilinx T2 card - - functionality of the LDPC encoding and decoding offload verified in OTA SISO setup with USRP N310 and Quectel RM500Q, blocking of the card reported for MIMO setup (2 layers) +# Known Issue(s) -*Note: AMD Xilinx T1 Telco card is not supported anymore.* +## BBDEV CPU Usage + +When running the E2E setup (this applies to both USRP and FHI72), BBDEV may not be using the list of CPU cores as specified by `nrLDPC_coding_t2.dpdk_core_list` accordingly. +This is an issue under investigation, and subject for future fixes. +In the meantime, we recommend allocating idle, and isolated CPU cores in the configuration for BBDEV. + +## Potential Low Throughput + +The current implementation has been tested to work in an end-to-end setup and is functional. +However, there are still opportunities for optimization, particularly in LDPC decoding performance, which is an area of ongoing improvement. +As such, downlink/uplink throughput may be suboptimal with the default configurations, but enhancements are actively being explored. + +To achieve better E2E performance with the current implementation, we recommend the following adjustments: +1. Increasing the number of LDPC decoding iterations of the L1, e.g., `max_ldpc_iterations` to 200. +2. Increasing the BLER targets of the MAC scheduler. + +Example configuration snippet: +``` +... +MACRLCs = ( +{ + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + pusch_TargetSNRx10 = 180; + pucch_TargetSNRx10 = 220; + dl_bler_target_upper = .35; + dl_bler_target_lower = .15; + ul_bler_target_upper = .35; + ul_bler_target_lower = .15; + pusch_FailureThres = 1000; + ul_max_mcs = 28; + +} +); + +L1s = ( +{ + num_cc = 1; + tr_n_preference = "local_mac"; + prach_dtx_threshold = 120; + pucch0_dtx_threshold = 100; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 + max_ldpc_iterations = 200; +} +); +... +``` diff --git a/openair1/PHY/CODING/DOC/LDPCImplementation.md b/openair1/PHY/CODING/DOC/LDPCImplementation.md index 0fae4e1574..dc2959bc73 100644 --- a/openair1/PHY/CODING/DOC/LDPCImplementation.md +++ b/openair1/PHY/CODING/DOC/LDPCImplementation.md @@ -39,7 +39,7 @@ Building C object CMakeFiles/ldpc_t2.dir/openair1/PHY/CODING/nrLDPC_coding/nrLDP Linking C shared module libldpc_t2.so ``` -At runtime, to successfully use the T2 board, you need to install vendor specific drivers and tools.\ +At runtime, to successfully use LDPC accelerators (e.g., Xilinx T2/Intel ACCs), you will need to install the corresponding drivers and tools. Please refer to the dedicated documentation at [LDPC_T2_OFFLOAD_SETUP.md](file://../../../../doc/LDPC_T2_OFFLOAD_SETUP.md). `./nr-softmodem -O libconfig:gnb.band78.sa.fr1.106PRB.usrpb210.conf:dbgl5 --rfsim --rfsimulator.serveraddr server --log_config.gtpu_log_level info --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev 01:00.0 --nrLDPC_coding_t2.dpdk_core_list 0-1` diff --git a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_t2/CMakeLists.txt b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_t2/CMakeLists.txt index f64384568a..b6a0cacf39 100644 --- a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_t2/CMakeLists.txt +++ b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_t2/CMakeLists.txt @@ -1,25 +1,35 @@ ########################################################## - -# LDPC offload library - AMD T2 Accelerator Card +# LDPC offload library - DPDK BBDEV ########################################################## add_boolean_option(ENABLE_LDPC_T2 OFF "Build support for LDPC Offload to T2 library" OFF) if (ENABLE_LDPC_T2) - pkg_check_modules(LIBDPDK_T2 REQUIRED libdpdk>=20.11.9) + if(LIBDPDK_T2_VERSION VERSION_LESS "21.11") + add_compile_definitions(DPDK_VER_PRE_21_11) + endif() + find_library(PMD_T2 NAMES rte_baseband_accl_ldpc HINTS ${LIBDPDK_T2_LIBRARY_DIRS}) - if (NOT PMD_T2) - message(FATAL_ERROR "could not find poll-mode driver for AccelerComm T2 LDPC Offload (rte_baseband_accl_ldpc.so)") + if (PMD_T2) + add_compile_definitions(LDPC_T2) + message(STATUS "found poll-mode driver for AccelerComm T2 LDPC Offload (rte_baseband_accl_ldpc.so)") + else() + if (LIBDPDK_T2_VERSION VERSION_LESS "22.11") + message(FATAL_ERROR "for non-T2 BBDEV PMDs, we support the Intel ACC100 and ACC200 (VRB1), using DPDK 22.11 or later.") + endif() endif() - message(STATUS "T2 build: use ${PMD_T2}") add_library(ldpc_t2 MODULE nrLDPC_coding_t2.c) set_target_properties(ldpc_t2 PROPERTIES COMPILE_FLAGS "-DALLOW_EXPERIMENTAL_API") set_target_properties(ldpc_t2 PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) - target_link_libraries(ldpc_t2 PRIVATE ldpc_gen_HEADERS ${LIBDPDK_T2_LDFLAGS} ${PMD_T2}) + target_include_directories(ldpc_t2 PRIVATE ${LIBDPDK_T2_INCLUDE_DIRS}) + target_link_libraries(ldpc_t2 PRIVATE ldpc_gen_HEADERS ${LIBDPDK_T2_LDFLAGS}) + if (PMD_T2) + target_link_libraries(ldpc_t2 PRIVATE ${PMD_T2}) + endif() add_dependencies(nr-softmodem ldpc_t2) add_dependencies(nr-uesoftmodem ldpc_t2) diff --git a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_t2/README.md b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_t2/README.md new file mode 100644 index 0000000000..ee55f7ff21 --- /dev/null +++ b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_t2/README.md @@ -0,0 +1,143 @@ +This document highlights some of the key aspects of the implementation for O-RAN AAL/DPDK BBDEV; for user documentation, please consult the [setup guide](../../../../../doc/LDPC_T2_OFFLOAD_SETUP.md) instead. + +## Overview + +The current implementation supports the following BBDEV devices and respective DPDK versions: +- Xilinx T2 on DPDK20.11+ +- Intel ACC100* on DPDK22.11+ +- Intel ACC200 (VRB1) on DPDK22.11+ + +> Important notes: +> - For the Intel ACC100, for DPDK22.11 and DPDK23.11, users are required to [patch](https://github.com/DPDK/dpdk/commit/fdde63a1dfc129d0a510a831aa98253b36a2a1cd) the ACC100's driver. +> - If you intend to use this implementation in an FHI7.2 setup, only the F-release and beyond is supported. + +## Implementation Details + +Below, we highlight some of the important details in this implementation. + +### HARQ + +To maintain the HARQ buffers in the LDPC decoding process, the BBDEV either uses its internal memory (not visible to DPDK), or using external memory (i.e., DDR) managed by OAI. +For the Xilinx T2 and Intel ACC100, they use the internal memory while the Intel ACC200 uses the DDR memory. + +If internal memory is supported by the device, we will set `RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_IN_ENABLE` and `RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_OUT_ENABLE`. + +The following two fields are important for HARQ: `harq_combined_input` and `harq_combined_output`. + +For the first transmission, there is no HARQ input. +Thus, the flag `RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE` is not set. +However, there will be a HARQ output, so we set the flag `RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE`. +We also set the corresponding fields for `harq_combined_output`. + +For the second transmission (or subsequent retransmissions), we need to provide a HARQ input at the same time, there will also be a HARQ output. +Therefore, both fields, `harq_combined_input` and `harq_combined_output` must be set accordingly. + +As HARQ requires the output of the previous transmission/ HARQ round as its input, we need to maintain a separate variable to hold the previous round's information. +To do so, we define `harq_buffers` (which is a pointer to an array of size `num_harq_codeblock` allocated in the heap later) in the `active_device` struct (see the following) in our implementation. +```C +struct active_device { + ... + uint32_t num_harq_codeblock; + /* Persistent data structure to keep track of HARQ-related information */ + // Note: This is used to store/keep track of the combined output information across iterations + struct rte_bbdev_op_data *harq_buffers; + ... +} active_dev; +``` + + +In the following, we elaborate on how the HARQ-related fields are set. + +#### Internal Memory + +When using the internal memory, we need to specify the *offset* of the hardware's memory where we want to store the HARQ combined output, and read from it accordingly later. + +In the current implementation, we use a fixed offset of 32K, i.e., this means that each block is 32K. + +An index is derived from a unique HARQ PID assigned by OAI, modulo `active_dev.num_harq_codeblock` (which is configurable by the user through `nrLDPC_coding_t2.num_harq_codeblock`). +Using that index, we then derived the corresponding offset in the memory (i.e., `harq_combined_offset`). + +```C +... + +// Calculate offset in the HARQ combined buffers +// Unique segment offset +uint32_t segment_offset = (nrLDPC_slot_decoding_parameters->TBs[h].harq_unique_pid * NR_LDPC_MAX_NUM_CB) + i; +// Prune to avoid shooting above maximum id +uint32_t pruned_segment_offset = segment_offset % active_dev.num_harq_codeblock; +// Segment offset to byte offset +uint32_t harq_combined_offset = pruned_segment_offset * LDPC_MAX_CB_SIZE; + +... +``` + +This `harq_combined_offset` is then set for `harq_combined_input.offset` and `harq_combined_output.offset` to tell BBDEV where to read/write the HARQ buffers. + +Especially for the Intel ACCs, when providing the HARQ input, the `harq_combined_input.length` must be provided. +To do so, we maintain the length of previous round's output using `harq_buffers` by copying it in `retrieve_ldpc_dec_op`. + +#### External Memory + +Different from the Xilinx T2 and Intel ACC100, the Intel ACC200 uses DDR memory to maintain the HARQ buffers which is managed by OAI. + +In short, we use `harq_buffers` from the `active_device` struct, which have been initialzed with corresponding DPDK mempools for BBDEV to read/write the HARQ input/outputs. + +For indexing, we use the `pruned_segment_offset`, which is derived from the unique HARQ PID assigned by OAI, modulo `active_dev.num_harq_codeblock` (which is configurable by the user through `nrLDPC_coding_t2.num_harq_codeblock`). + +`harq_combined_input.offset` and `harq_combined_output.offset` is always set to 0 in our implementation. +Instead, we provide BBDEV the pointers to our allocated mempool regions through `harq_combined_input.data` and `harq_combined_output.data`. + +In `retrieve_ldpc_dec_op`, we perform a `rte_memcpy` to copy the HARQ combined outputs to `harq_buffers`, along with other necessary metadata information to prepare for subsequent HARQ rounds. +Similar to the Intel ACC100, when providing the HARQ input, the `harq_combined_input.length` must be provided. + +### LLR Scaling + +The LLR output from OAI's demodulation block is in 16 bits. +However, accelerators typically assume that the LLR inputs are scaled down using fixed-point arithmetic, e.g., 8 bits. + +For the Xilinx T2, saturation is performed. +However, our tests have shown that this implementation did not work well for the Intel ACCs. + +To that end, we perform LLR scaling differently for the Intel ACCs. +Through the function `llr_scaling`, we look at the min and max LLR values, perform scaling and subsequently saturation accordingly. + +The fixed-point representations supported by the hardware is defined by the `llr_size` and `llr_decimal`. +For example, if `llr_size=8`, and `llr_decimal=1`, it means that we use a S8.1 representation (1 fractional bit), the min and max values are -64 to 63.5. + +> *Limitation:* +> We observe that in certain configurations, such as when using 2 MIMO layers, the LLR (Log-Likelihood Ratio) outputs exhibit a much wider dynamic range (e.g., from -10,000 to 10,000) compared to the typical sub-1,000 range seen in most other cases. +> This suggests potential inconsistencies in the LLR values generated by the demodulator. +> We believe that the decoding performance, when compared to the CPU implementation under the same number of LDPC decoding iterations, could be improved by refining the LLR scaling approach or revisiting the LLR generation process during demodulation. +> This remains an area of active investigation. +> +> *Workaround:* +> As a temporary measure, increasing the number of LDPC decoding iterations—e.g., to 150—has shown to yield a decoding success rate comparable to that of the CPU implementation. +> This comes at a negligible increase in decoding time based on our current evaluation. + +### Special Case(s) + +#### TB mode + +For the T2, only CB mode is supported. + +For the Intel ACCs, while we also use CB mode mostly, there is a special case that must be handled properly as specified by the BBDEV documentations: +``` +... The case when one CB belongs to TB and is being enqueued individually to BBDEV, this case is considered as a special case of partial TB where its number of CBs is 1. Therefore, it requires to get processed in TB-mode. ... +``` + +In such a case, we perform a check on whether there is only one TB, AND if the TB has only one CB. +If so, this has to be handled separately by using TB mode. + +### Future Work(s) + +#### TB mode + +The current channel coding interface assumes LDPC encoding and decoding are performed on a per-code block basis. +However, to fully leverage Transport Block (TB) mode as supported in BBDEV, which can improve efficiency, the L1 implementation surrounding channel coding needs to be refactored. +This remains an area for future investigation. + +#### CRC24A/CRC16 + +CRC24A/CRC16 is supported by the BBDEV device (i.e., Intel ACC200). +However, we do not make use of them and rely on OAI's existing CRC functions. +To use of BBDEV's CRC24A/CRC16 capability will be looked into in future MRs. diff --git a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_t2/nrLDPC_coding_t2.c b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_t2/nrLDPC_coding_t2.c index 04ad571de0..bd1aad254d 100644 --- a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_t2/nrLDPC_coding_t2.c +++ b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_t2/nrLDPC_coding_t2.c @@ -19,6 +19,7 @@ #include #include #include +#include #include @@ -47,16 +48,20 @@ #define TIME_OUT_POLL 1e8 /* Headroom for filler LLRs insertion in HARQ buffer */ #define FILLER_HEADROOM 1024 -/* Number of segments that could be stored in HARQ combined buffers */ -#define HARQ_CODEBLOCK_ID_MAX (16 << 5) pthread_mutex_t encode_mutex; pthread_mutex_t decode_mutex; -/* Represents tested active devices */ +/* we assume one active baseband device only */ struct active_device { const char *driver_name; uint8_t dev_id; + struct rte_bbdev_info info; + uint32_t num_harq_codeblock; + /* Persistent data structure to keep track of HARQ-related information */ + // Note: This is used to store/keep track of the combined output information across iterations + struct rte_bbdev_op_data *harq_buffers; + bool support_internal_harq_memory; int dec_queue; int enc_queue; uint16_t queue_ids[MAX_QUEUES]; @@ -65,13 +70,15 @@ struct active_device { struct rte_mempool *bbdev_enc_op_pool; struct rte_mempool *in_mbuf_pool; struct rte_mempool *hard_out_mbuf_pool; -} active_devs[RTE_BBDEV_MAX_DEVS]; -static int nb_active_devs; + struct rte_mempool *harq_in_mbuf_pool; + struct rte_mempool *harq_out_mbuf_pool; +} active_dev; /* Data buffers used by BBDEV ops */ struct data_buffers { struct rte_bbdev_op_data *inputs; struct rte_bbdev_op_data *hard_outputs; + struct rte_bbdev_op_data *harq_outputs; }; /* Operation parameters specific for given test case */ @@ -93,26 +100,34 @@ struct thread_params { struct rte_mempool *bbdev_op_pool; }; -static uint16_t nb_segments_decoding(nrLDPC_slot_decoding_parameters_t *nrLDPC_slot_decoding_parameters) { +static uint16_t nb_segments_decoding(nrLDPC_slot_decoding_parameters_t *nrLDPC_slot_decoding_parameters) +{ uint16_t nb_segments = 0; for (int h = 0; h < nrLDPC_slot_decoding_parameters->nb_TBs; ++h) { - nb_segments+=nrLDPC_slot_decoding_parameters->TBs[h].C; + nb_segments += nrLDPC_slot_decoding_parameters->TBs[h].C; } return nb_segments; } -static uint16_t nb_segments_encoding(nrLDPC_slot_encoding_parameters_t *nrLDPC_slot_encoding_parameters) { +static uint16_t nb_segments_encoding(nrLDPC_slot_encoding_parameters_t *nrLDPC_slot_encoding_parameters) +{ uint16_t nb_segments = 0; for (int h = 0; h < nrLDPC_slot_encoding_parameters->nb_TBs; ++h) { - nb_segments+=nrLDPC_slot_encoding_parameters->TBs[h].C; + nb_segments += nrLDPC_slot_encoding_parameters->TBs[h].C; } return nb_segments; } +/* Read flag value 0/1 from bitmap */ +// DPDK BBDEV copy +static inline bool check_bit(uint32_t bitmap, uint32_t bitmask) +{ + return bitmap & bitmask; +} + /* calculates optimal mempool size not smaller than the val */ // DPDK BBDEV copy -static unsigned int -optimal_mempool_size(unsigned int val) +static unsigned int optimal_mempool_size(unsigned int val) { return rte_align32pow2(val + 1) - 1; } @@ -131,17 +146,16 @@ static int create_mempools(struct active_device *ad, int socket_id, uint16_t num OPS_POOL_SIZE_MIN)); /* Decoder ops mempool */ - ad->bbdev_dec_op_pool = rte_bbdev_op_pool_create("bbdev_op_pool_dec", RTE_BBDEV_OP_LDPC_DEC, - /* Encoder ops mempool */ ops_pool_size, OPS_CACHE_SIZE, socket_id); - ad->bbdev_enc_op_pool = rte_bbdev_op_pool_create("bbdev_op_pool_enc", RTE_BBDEV_OP_LDPC_ENC, - ops_pool_size, OPS_CACHE_SIZE, socket_id); + ad->bbdev_dec_op_pool = rte_bbdev_op_pool_create("bbdev_op_pool_dec", + RTE_BBDEV_OP_LDPC_DEC, + /* Encoder ops mempool */ ops_pool_size, + OPS_CACHE_SIZE, + socket_id); + ad->bbdev_enc_op_pool = + rte_bbdev_op_pool_create("bbdev_op_pool_enc", RTE_BBDEV_OP_LDPC_ENC, ops_pool_size, OPS_CACHE_SIZE, socket_id); if ((ad->bbdev_dec_op_pool == NULL) || (ad->bbdev_enc_op_pool == NULL)) - AssertFatal(1 == 0, - "ERROR Failed to create %u items ops pool for dev %u on socket %d.", - ops_pool_size, - ad->dev_id, - socket_id); + AssertFatal(1 == 0, "ERROR Failed to create %u items ops pool for dev %u on socket %d.", ops_pool_size, ad->dev_id, socket_id); /* Inputs */ mbuf_pool_size = optimal_mempool_size(ops_pool_size * nb_segments); @@ -149,9 +163,9 @@ static int create_mempools(struct active_device *ad, int socket_id, uint16_t num ad->in_mbuf_pool = rte_pktmbuf_pool_create("in_mbuf_pool", mbuf_pool_size, 0, 0, data_room_size, socket_id); AssertFatal(ad->in_mbuf_pool != NULL, "ERROR Failed to create %u items input pktmbuf pool for dev %u on socket %d.", - mbuf_pool_size, - ad->dev_id, - socket_id); + mbuf_pool_size, + ad->dev_id, + socket_id); /* Hard outputs */ data_room_size = RTE_MAX(out_buff_sz + RTE_PKTMBUF_HEADROOM + FILLER_HEADROOM, (unsigned int)RTE_MBUF_DEFAULT_BUF_SIZE); @@ -161,6 +175,27 @@ static int create_mempools(struct active_device *ad, int socket_id, uint16_t num mbuf_pool_size, ad->dev_id, socket_id); + + /* HARQ outputs */ + data_room_size = LDPC_MAX_CB_SIZE; + ad->harq_out_mbuf_pool = rte_pktmbuf_pool_create("harq_out_mbuf_pool", mbuf_pool_size, 0, 0, data_room_size, socket_id); + AssertFatal(ad->harq_out_mbuf_pool != NULL, + "ERROR Failed to create %u items harq output pktmbuf pool for dev %u on socket %d.", + mbuf_pool_size, + ad->dev_id, + socket_id); + + /* HARQ inputs */ + // Note: This is used as our harq buffer to store the combined outputs across iterations + data_room_size = LDPC_MAX_CB_SIZE; + ad->harq_in_mbuf_pool = + rte_pktmbuf_pool_create("harq_in_mbuf_pool", active_dev.num_harq_codeblock, 0, 0, data_room_size, socket_id); + AssertFatal(ad->harq_in_mbuf_pool != NULL, + "ERROR Failed to create %u items harq input pktmbuf pool for dev %u on socket %d.", + active_dev.num_harq_codeblock, + ad->dev_id, + socket_id); + return 0; } @@ -237,52 +272,127 @@ const char *ldpcdec_flag_bitmask[] = { "RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_FILLERS", }; -// based on DPDK BBDEV add_bbdev_dev -static int add_dev(uint8_t dev_id, struct rte_bbdev_info *info) +void debug_dev_capabilities(uint8_t dev_id, struct rte_bbdev_info *info) { - int ret; - struct active_device *ad = &active_devs[nb_active_devs]; - unsigned int nb_queues; - nb_queues = RTE_MIN(rte_lcore_count(), info->drv.max_num_queues); - nb_queues = RTE_MIN(nb_queues, (unsigned int)MAX_QUEUES); - /* Display for debug the capabilities of the card */ for (int i = 0; info->drv.capabilities[i].type != RTE_BBDEV_OP_NONE; i++) { - printf("device: %d, capability[%d]=%s\n", dev_id, i, rte_bbdev_op_type_str(info->drv.capabilities[i].type)); + LOG_D(NR_PHY, "device: %d, capability[%d]=%s\n", dev_id, i, rte_bbdev_op_type_str(info->drv.capabilities[i].type)); if (info->drv.capabilities[i].type == RTE_BBDEV_OP_LDPC_ENC) { const struct rte_bbdev_op_cap_ldpc_enc cap = info->drv.capabilities[i].cap.ldpc_enc; - printf(" buffers: src = %d, dst = %d\n capabilites: ", cap.num_buffers_src, cap.num_buffers_dst); + LOG_D(NR_PHY, " buffers: src = %d, dst = %d\n capabilites: ", cap.num_buffers_src, cap.num_buffers_dst); for (int j = 0; j < sizeof(cap.capability_flags) * 8; j++) if (cap.capability_flags & (1ULL << j)) - printf("%s ", ldpcenc_flag_bitmask[j]); - printf("\n"); + LOG_D(NR_PHY, "%s ", ldpcenc_flag_bitmask[j]); + LOG_D(NR_PHY, "\n"); } if (info->drv.capabilities[i].type == RTE_BBDEV_OP_LDPC_DEC) { const struct rte_bbdev_op_cap_ldpc_dec cap = info->drv.capabilities[i].cap.ldpc_dec; - printf(" buffers: src = %d, hard out = %d, soft_out %d, llr size %d, llr decimals %d \n capabilities: ", - cap.num_buffers_src, - cap.num_buffers_hard_out, - cap.num_buffers_soft_out, - cap.llr_size, - cap.llr_decimals); + LOG_D(NR_PHY, + " buffers: src = %d, hard out = %d, soft_out %d, llr size %d, llr decimals %d \n capabilities: ", + cap.num_buffers_src, + cap.num_buffers_hard_out, + cap.num_buffers_soft_out, + cap.llr_size, + cap.llr_decimals); for (int j = 0; j < sizeof(cap.capability_flags) * 8; j++) if (cap.capability_flags & (1ULL << j)) - printf("%s ", ldpcdec_flag_bitmask[j]); - printf("\n"); + LOG_D(NR_PHY, "%s ", ldpcdec_flag_bitmask[j]); + LOG_D(NR_PHY, "\n"); } } +} - /* setup device */ - ret = rte_bbdev_setup_queues(dev_id, nb_queues, info->socket_id); - if (ret < 0) { - printf("rte_bbdev_setup_queues(%u, %u, %d) ret %i\n", dev_id, nb_queues, info->socket_id, ret); - return -1; +void check_required_dev_capabilities(struct rte_bbdev_info *info) +{ + // check ldpc enc/ dec support + bool ldpc_enc = false; + bool ldpc_dec = false; + for (int i = 0; info->drv.capabilities[i].type != RTE_BBDEV_OP_NONE; i++) { + if (info->drv.capabilities[i].type == RTE_BBDEV_OP_LDPC_ENC) { + ldpc_enc = true; + } + if (info->drv.capabilities[i].type == RTE_BBDEV_OP_LDPC_DEC) { + ldpc_dec = true; + } } + AssertFatal(ldpc_enc, "ERROR: bbdev device does not support LDPC encoding\n"); + AssertFatal(ldpc_dec, "ERROR: bbdev device does not support LDPC decoding\n"); + + for (int i = 0; info->drv.capabilities[i].type != RTE_BBDEV_OP_NONE; i++) { + if (info->drv.capabilities[i].type == RTE_BBDEV_OP_LDPC_ENC) { + // check encoding capabilities + bool rate_match = check_bit(info->drv.capabilities[i].cap.ldpc_enc.capability_flags, RTE_BBDEV_LDPC_RATE_MATCH); + AssertFatal(rate_match, "ERROR: bbdev device does not support LDPC encoding with rate matching\n"); + } + if (info->drv.capabilities[i].type == RTE_BBDEV_OP_LDPC_DEC) { + // check decoding capabilities + bool iter_stop = check_bit(info->drv.capabilities[i].cap.ldpc_dec.capability_flags, RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE); + AssertFatal(iter_stop, "ERROR: bbdev device does not support LDPC decoding with iteration stop\n"); + + bool crc_24b_drop = check_bit(info->drv.capabilities[i].cap.ldpc_dec.capability_flags, RTE_BBDEV_LDPC_CRC_TYPE_24B_DROP); + AssertFatal(crc_24b_drop, "ERROR: bbdev device does not support LDPC decoding with CRC-24B drop\n"); + + bool crc_24b_check = check_bit(info->drv.capabilities[i].cap.ldpc_dec.capability_flags, RTE_BBDEV_LDPC_CRC_TYPE_24B_CHECK); + AssertFatal(crc_24b_check, "ERROR: bbdev device does not support LDPC decoding with CRC-24B check\n"); + } + } +} + +bool check_internal_harq_memory_capabilities(struct rte_bbdev_info *info) +{ + for (int i = 0; info->drv.capabilities[i].type != RTE_BBDEV_OP_NONE; i++) { + if (info->drv.capabilities[i].type == RTE_BBDEV_OP_LDPC_DEC) { + bool harq_in = + check_bit(info->drv.capabilities[i].cap.ldpc_dec.capability_flags, RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_IN_ENABLE); + bool harq_out = + check_bit(info->drv.capabilities[i].cap.ldpc_dec.capability_flags, RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_OUT_ENABLE); + bool internal_harq_memory_support = harq_in & harq_out; + if (internal_harq_memory_support) { + LOG_I(NR_PHY, "bbdev device supports internal HARQ memory\n"); + } + return internal_harq_memory_support; + } + } + return false; +} + +// based on DPDK BBDEV add_bbdev_dev +static int add_dev(uint8_t dev_id, uint32_t num_harq_codeblock) +{ + int ret; + unsigned int nb_queues; + + // retrieve device capabilities + rte_bbdev_info_get(dev_id, &active_dev.info); + LOG_I(NR_PHY, "using bbdev %d: %s\n", dev_id, active_dev.info.dev_name); + + active_dev.driver_name = active_dev.info.drv.driver_name; + active_dev.dev_id = dev_id; + + nb_queues = RTE_MIN(rte_lcore_count(), active_dev.info.drv.max_num_queues); + nb_queues = RTE_MIN(nb_queues, (unsigned int)MAX_QUEUES); + + // debug device capabilities + debug_dev_capabilities(dev_id, &active_dev.info); + + // check required device capabilities + check_required_dev_capabilities(&active_dev.info); + + // check internal harq memory capabilities + active_dev.support_internal_harq_memory = check_internal_harq_memory_capabilities(&active_dev.info); + + // setup harq buffers + active_dev.num_harq_codeblock = num_harq_codeblock; + active_dev.harq_buffers = malloc(sizeof(struct rte_bbdev_op_data) * active_dev.num_harq_codeblock); + + // device setup + ret = rte_bbdev_setup_queues(dev_id, nb_queues, active_dev.info.socket_id); + AssertFatal(ret == 0, "rte_bbdev_setup_queues(%u, %u, %d) ret %i\n", dev_id, nb_queues, active_dev.info.socket_id, ret); /* setup device queues */ struct rte_bbdev_queue_conf qconf = { - .socket = info->socket_id, - .queue_size = info->drv.default_queue_conf.queue_size, + .socket = active_dev.info.socket_id, + .queue_size = active_dev.info.drv.default_queue_conf.queue_size, }; // Search a queue linked to HW capability ldpc decoding @@ -291,10 +401,10 @@ static int add_dev(uint8_t dev_id, struct rte_bbdev_info *info) for (queue_id = 0; queue_id < nb_queues; ++queue_id) { ret = rte_bbdev_queue_configure(dev_id, queue_id, &qconf); if (ret == 0) { - printf("Found LDCP encoding queue (id=%u) at prio%u on dev%u\n", queue_id, qconf.priority, dev_id); + LOG_I(NR_PHY, "Found LDPC encoding queue (id=%u) at prio%u on dev%u\n", queue_id, qconf.priority, dev_id); qconf.priority++; - ad->enc_queue = queue_id; - ad->queue_ids[queue_id] = queue_id; + active_dev.enc_queue = queue_id; + active_dev.queue_ids[queue_id] = queue_id; break; } } @@ -305,15 +415,30 @@ static int add_dev(uint8_t dev_id, struct rte_bbdev_info *info) for (queue_id++; queue_id < nb_queues; ++queue_id) { ret = rte_bbdev_queue_configure(dev_id, queue_id, &qconf); if (ret == 0) { - printf("Found LDCP decoding queue (id=%u) at prio%u on dev%u\n", queue_id, qconf.priority, dev_id); + LOG_I(NR_PHY, "Found LDPC decoding queue (id=%u) at prio%u on dev%u\n", queue_id, qconf.priority, dev_id); qconf.priority++; - ad->dec_queue = queue_id; - ad->queue_ids[queue_id] = queue_id; + active_dev.dec_queue = queue_id; + active_dev.queue_ids[queue_id] = queue_id; break; } } AssertFatal(queue_id != nb_queues, "ERROR Failed to configure encoding queues on dev %u", dev_id); - ad->nb_queues = 2; + active_dev.nb_queues = 2; + return 0; +} + +static int init_op_data_objs_harq(struct rte_bbdev_op_data *bufs, struct rte_mempool *mbuf_pool) +{ + for (int i = 0; i < active_dev.num_harq_codeblock; i++) { + struct rte_mbuf *m_head = rte_pktmbuf_alloc(mbuf_pool); + AssertFatal(m_head != NULL, + "Not enough mbufs in HARQ mbuf pool (needed %u, available %u)", + active_dev.num_harq_codeblock, + mbuf_pool->size); + bufs[i].data = m_head; + bufs[i].offset = 0; + bufs[i].length = 0; + } return 0; } @@ -337,7 +462,7 @@ static int init_op_data_objs_dec(struct rte_bbdev_op_data *bufs, op_type, nb_segments_decoding(nrLDPC_slot_decoding_parameters), mbuf_pool->size); - + if (data_len > RTE_BBDEV_LDPC_E_MAX_MBUF) { printf("Warning: Larger input size than DPDK mbuf %u\n", data_len); large_input = true; @@ -393,7 +518,7 @@ static int init_op_data_objs_enc(struct rte_bbdev_op_data *bufs, op_type, nb_segments_encoding(nrLDPC_slot_encoding_parameters), mbuf_pool->size); - + if (data_len > RTE_BBDEV_LDPC_E_MAX_MBUF) { printf("Warning: Larger input size than DPDK mbuf %u\n", data_len); large_input = true; @@ -430,7 +555,6 @@ static int init_op_data_objs_enc(struct rte_bbdev_op_data *bufs, return 0; } - // DPDK BBEV copy static int allocate_buffers_on_socket(struct rte_bbdev_op_data **buffers, const int len, const int socket) { @@ -457,53 +581,96 @@ static void free_mempools(struct active_device *ad) rte_mempool_free(ad->bbdev_enc_op_pool); rte_mempool_free(ad->in_mbuf_pool); rte_mempool_free(ad->hard_out_mbuf_pool); + rte_mempool_free(ad->harq_in_mbuf_pool); + rte_mempool_free(ad->harq_out_mbuf_pool); } // based on DPDK BBDEV copy_reference_ldpc_dec_op -static void -set_ldpc_dec_op(struct rte_bbdev_dec_op **ops, - struct rte_bbdev_op_data *inputs, - struct rte_bbdev_op_data *outputs, - nrLDPC_slot_decoding_parameters_t *nrLDPC_slot_decoding_parameters) +static void set_ldpc_dec_op(struct rte_bbdev_dec_op **ops, + struct rte_bbdev_op_data *inputs, + struct rte_bbdev_op_data *outputs, + struct rte_bbdev_op_data *harq_outputs, + nrLDPC_slot_decoding_parameters_t *nrLDPC_slot_decoding_parameters) { int j = 0; +#ifdef LDPC_T2 + // The T2 only supports CB mode, and does not TB mode special case handling. + bool special_case_tb_mode = false; +#else + bool special_case_tb_mode = + (nrLDPC_slot_decoding_parameters->nb_TBs == 1) && (nb_segments_decoding(nrLDPC_slot_decoding_parameters) == 1); +#endif for (int h = 0; h < nrLDPC_slot_decoding_parameters->nb_TBs; ++h) { for (int i = 0; i < nrLDPC_slot_decoding_parameters->TBs[h].C; ++i) { - ops[j]->ldpc_dec.cb_params.e = nrLDPC_slot_decoding_parameters->TBs[h].segments[i].E; ops[j]->ldpc_dec.basegraph = nrLDPC_slot_decoding_parameters->TBs[h].BG; ops[j]->ldpc_dec.z_c = nrLDPC_slot_decoding_parameters->TBs[h].Z; ops[j]->ldpc_dec.q_m = nrLDPC_slot_decoding_parameters->TBs[h].Qm; ops[j]->ldpc_dec.n_filler = nrLDPC_slot_decoding_parameters->TBs[h].F; - ops[j]->ldpc_dec.n_cb = (nrLDPC_slot_decoding_parameters->TBs[h].BG == 1) ? (66 * nrLDPC_slot_decoding_parameters->TBs[h].Z) : (50 * nrLDPC_slot_decoding_parameters->TBs[h].Z); + ops[j]->ldpc_dec.n_cb = (nrLDPC_slot_decoding_parameters->TBs[h].BG == 1) ? (66 * nrLDPC_slot_decoding_parameters->TBs[h].Z) + : (50 * nrLDPC_slot_decoding_parameters->TBs[h].Z); ops[j]->ldpc_dec.iter_max = nrLDPC_slot_decoding_parameters->TBs[h].max_ldpc_iterations; ops[j]->ldpc_dec.rv_index = nrLDPC_slot_decoding_parameters->TBs[h].rv_index; - ops[j]->ldpc_dec.op_flags = RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE | - RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_IN_ENABLE | - RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_OUT_ENABLE | - RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE; + ops[j]->ldpc_dec.op_flags = RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE | RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE; if (*nrLDPC_slot_decoding_parameters->TBs[h].segments[i].d_to_be_cleared) { *nrLDPC_slot_decoding_parameters->TBs[h].segments[i].d_to_be_cleared = false; - *nrLDPC_slot_decoding_parameters->TBs[h].processedSegments = 0; } else { ops[j]->ldpc_dec.op_flags |= RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE; + if (active_dev.support_internal_harq_memory) { + ops[j]->ldpc_dec.op_flags |= RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_IN_ENABLE; + ops[j]->ldpc_dec.op_flags |= RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_OUT_ENABLE; + } } - if (nrLDPC_slot_decoding_parameters->TBs[h].C > 1) { - ops[j]->ldpc_dec.op_flags |= RTE_BBDEV_LDPC_CRC_TYPE_24B_DROP; - ops[j]->ldpc_dec.op_flags |= RTE_BBDEV_LDPC_CRC_TYPE_24B_CHECK; + +#ifdef LDPC_T2 + // Note: For the T2, we do not reset the processedSegments in case of HARQ. + // This is because if T2 is asked to decode a segment that as already successfully + // decoded in the previous round, the T2 reports a failure. + if (*nrLDPC_slot_decoding_parameters->TBs[h].segments[i].d_to_be_cleared) *nrLDPC_slot_decoding_parameters->TBs[h].processedSegments = 0; +#else + *nrLDPC_slot_decoding_parameters->TBs[h].processedSegments = 0; +#endif + if (!special_case_tb_mode) { + ops[j]->ldpc_dec.code_block_mode = 1; + ops[j]->ldpc_dec.cb_params.e = nrLDPC_slot_decoding_parameters->TBs[h].segments[i].E; + if (nrLDPC_slot_decoding_parameters->TBs[h].C > 1) { + ops[j]->ldpc_dec.op_flags |= RTE_BBDEV_LDPC_CRC_TYPE_24B_DROP; + ops[j]->ldpc_dec.op_flags |= RTE_BBDEV_LDPC_CRC_TYPE_24B_CHECK; + } + } else { + /** + * This is a special case when #TB = 1 and #CB = 1 + * In this case, we must use TB mode + * Quoted from: https://doc.dpdk.org/guides-23.11/prog_guide/bbdev.html#bbdev-ldpc-decode-operation + * The case when one CB belongs to TB and is being enqueued individually to BBDEV, this case is considered as a + * special case of partial TB where its number of CBs is 1. Therefore, it requires to get processed in TB-mode. + */ + ops[j]->ldpc_dec.code_block_mode = 0; + ops[j]->ldpc_dec.tb_params.c = 1; + ops[j]->ldpc_dec.tb_params.r = 0; + ops[j]->ldpc_dec.tb_params.cab = 1; + ops[j]->ldpc_dec.tb_params.ea = nrLDPC_slot_decoding_parameters->TBs[h].segments[i].E; + ops[j]->ldpc_dec.tb_params.eb = nrLDPC_slot_decoding_parameters->TBs[h].segments[i].E; } - ops[j]->ldpc_dec.code_block_mode = 1; - // Calculate offset in the HARQ combined buffers // Unique segment offset uint32_t segment_offset = (nrLDPC_slot_decoding_parameters->TBs[h].harq_unique_pid * NR_LDPC_MAX_NUM_CB) + i; // Prune to avoid shooting above maximum id - uint32_t pruned_segment_offset = segment_offset % HARQ_CODEBLOCK_ID_MAX; + uint32_t pruned_segment_offset = segment_offset % active_dev.num_harq_codeblock; // Segment offset to byte offset uint32_t harq_combined_offset = pruned_segment_offset * LDPC_MAX_CB_SIZE; - ops[j]->ldpc_dec.harq_combined_input.offset = harq_combined_offset; - ops[j]->ldpc_dec.harq_combined_output.offset = harq_combined_offset; - + if (active_dev.support_internal_harq_memory) { + // retrieve corresponding HARQ output information from previous iteration, especially the length + ops[j]->ldpc_dec.harq_combined_input = active_dev.harq_buffers[pruned_segment_offset]; + // Note: When using INTERNAL_HARQ memory, the "offset" is used to point to a particular address + // within the BBDEV's onboard memory, and the address should be multiples of 32K. + harq_outputs[j].offset = harq_combined_offset; + ops[j]->ldpc_dec.harq_combined_output = harq_outputs[j]; + } else { + // retrieve corresponding HARQ buffers from previous iteration + ops[j]->ldpc_dec.harq_combined_input = active_dev.harq_buffers[pruned_segment_offset]; + ops[j]->ldpc_dec.harq_combined_output = harq_outputs[j]; + } ops[j]->ldpc_dec.hard_output = outputs[j]; ops[j]->ldpc_dec.input = inputs[j]; ++j; @@ -512,28 +679,51 @@ set_ldpc_dec_op(struct rte_bbdev_dec_op **ops, } // based on DPDK BBDEV copy_reference_ldpc_enc_op -static void -set_ldpc_enc_op(struct rte_bbdev_enc_op **ops, - struct rte_bbdev_op_data *inputs, - struct rte_bbdev_op_data *outputs, - nrLDPC_slot_encoding_parameters_t *nrLDPC_slot_encoding_parameters) +static void set_ldpc_enc_op(struct rte_bbdev_enc_op **ops, + struct rte_bbdev_op_data *inputs, + struct rte_bbdev_op_data *outputs, + nrLDPC_slot_encoding_parameters_t *nrLDPC_slot_encoding_parameters) { int j = 0; +#ifdef LDPC_T2 + // The T2 only supports CB mode, and does not TB mode special case handling. + bool special_case_tb_mode = false; +#else + bool special_case_tb_mode = + (nrLDPC_slot_encoding_parameters->nb_TBs == 1) && (nb_segments_encoding(nrLDPC_slot_encoding_parameters) == 1); +#endif for (int h = 0; h < nrLDPC_slot_encoding_parameters->nb_TBs; ++h) { for (int i = 0; i < nrLDPC_slot_encoding_parameters->TBs[h].C; ++i) { - ops[j]->ldpc_enc.cb_params.e = nrLDPC_slot_encoding_parameters->TBs[h].segments[i].E; ops[j]->ldpc_enc.basegraph = nrLDPC_slot_encoding_parameters->TBs[h].BG; ops[j]->ldpc_enc.z_c = nrLDPC_slot_encoding_parameters->TBs[h].Z; ops[j]->ldpc_enc.q_m = nrLDPC_slot_encoding_parameters->TBs[h].Qm; ops[j]->ldpc_enc.n_filler = nrLDPC_slot_encoding_parameters->TBs[h].F; - ops[j]->ldpc_enc.n_cb = (nrLDPC_slot_encoding_parameters->TBs[h].BG == 1) ? (66 * nrLDPC_slot_encoding_parameters->TBs[h].Z) : (50 * nrLDPC_slot_encoding_parameters->TBs[h].Z); + ops[j]->ldpc_enc.n_cb = (nrLDPC_slot_encoding_parameters->TBs[h].BG == 1) ? (66 * nrLDPC_slot_encoding_parameters->TBs[h].Z) + : (50 * nrLDPC_slot_encoding_parameters->TBs[h].Z); if (nrLDPC_slot_encoding_parameters->TBs[h].tbslbrm != 0) { uint32_t Nref = 3 * nrLDPC_slot_encoding_parameters->TBs[h].tbslbrm / (2 * nrLDPC_slot_encoding_parameters->TBs[h].C); ops[j]->ldpc_enc.n_cb = min(ops[j]->ldpc_enc.n_cb, Nref); } ops[j]->ldpc_enc.rv_index = nrLDPC_slot_encoding_parameters->TBs[h].rv_index; ops[j]->ldpc_enc.op_flags = RTE_BBDEV_LDPC_RATE_MATCH; - ops[j]->ldpc_enc.code_block_mode = 1; + if (!special_case_tb_mode) { + ops[j]->ldpc_enc.code_block_mode = 1; + ops[j]->ldpc_enc.cb_params.e = nrLDPC_slot_encoding_parameters->TBs[h].segments[i].E; + } else { + /** + * This is a special case when #TB = 1 and #CB = 1 + * In this case, we must use TB mode + * Quoted from: https://doc.dpdk.org/guides-23.11/prog_guide/bbdev.html#bbdev-ldpc-decode-operation + * The case when one CB belongs to TB and is being enqueued individually to BBDEV, this case is considered as a + * special case of partial TB where its number of CBs is 1. Therefore, it requires to get processed in TB-mode. + */ + ops[j]->ldpc_enc.code_block_mode = 0; + ops[j]->ldpc_enc.tb_params.c = 1; + ops[j]->ldpc_enc.tb_params.r = 0; + ops[j]->ldpc_enc.tb_params.cab = 1; + ops[j]->ldpc_enc.tb_params.ea = nrLDPC_slot_encoding_parameters->TBs[h].segments[i].E; + ops[j]->ldpc_enc.tb_params.eb = nrLDPC_slot_encoding_parameters->TBs[h].segments[i].E; + } ops[j]->ldpc_enc.output = outputs[j]; ops[j]->ldpc_enc.input = inputs[j]; ++j; @@ -551,19 +741,30 @@ static int retrieve_ldpc_dec_op(struct rte_bbdev_dec_op **ops, nrLDPC_slot_decod uint16_t data_len = rte_pktmbuf_data_len(m) - hard_output->offset; uint8_t *data = rte_pktmbuf_mtod_offset(m, uint8_t *, hard_output->offset); memcpy(nrLDPC_slot_decoding_parameters->TBs[h].segments[i].c, data, data_len); + + uint32_t segment_offset = (nrLDPC_slot_decoding_parameters->TBs[h].harq_unique_pid * NR_LDPC_MAX_NUM_CB) + i; + uint32_t pruned_segment_offset = segment_offset % active_dev.num_harq_codeblock; + struct rte_bbdev_op_data *harq_output = &ops[j]->ldpc_dec.harq_combined_output; + if (!active_dev.support_internal_harq_memory) { + struct rte_mbuf *m_src = harq_output->data; + uint8_t *data_src = rte_pktmbuf_mtod_offset(m_src, uint8_t *, 0); + struct rte_mbuf *m_dst = active_dev.harq_buffers[pruned_segment_offset].data; + uint8_t *data_dst = rte_pktmbuf_mtod_offset(m_dst, uint8_t *, 0); + rte_memcpy(data_dst, data_src, harq_output->length); + } + active_dev.harq_buffers[pruned_segment_offset].offset = harq_output->offset; + active_dev.harq_buffers[pruned_segment_offset].length = harq_output->length; ++j; } } return 0; } -static int -retrieve_ldpc_enc_op(struct rte_bbdev_enc_op **ops, - nrLDPC_slot_encoding_parameters_t *nrLDPC_slot_encoding_parameters) +static int retrieve_ldpc_enc_op(struct rte_bbdev_enc_op **ops, nrLDPC_slot_encoding_parameters_t *nrLDPC_slot_encoding_parameters) { uint8_t *p_out = NULL; int j = 0; - for (int h = 0; h < nrLDPC_slot_encoding_parameters->nb_TBs; ++h){ + for (int h = 0; h < nrLDPC_slot_encoding_parameters->nb_TBs; ++h) { int E_sum = 0; int bit_offset = 0; int byte_offset = 0; @@ -606,8 +807,7 @@ retrieve_ldpc_enc_op(struct rte_bbdev_enc_op **ops, } // based on DPDK BBDEV throughput_pmd_lcore_ldpc_dec -static int -pmd_lcore_ldpc_dec(void *arg) +static int pmd_lcore_ldpc_dec(void *arg) { struct thread_params *tp = arg; nrLDPC_slot_decoding_parameters_t *nrLDPC_slot_decoding_parameters = tp->nrLDPC_slot_decoding_parameters; @@ -620,15 +820,12 @@ pmd_lcore_ldpc_dec(void *arg) AssertFatal((num_segments < MAX_BURST), "BURST_SIZE should be <= %u", MAX_BURST); - struct rte_bbdev_info info; - rte_bbdev_info_get(tp->dev_id, &info); - while (rte_atomic16_read(&tp->op_params->sync) == SYNC_WAIT) rte_pause(); int ret = rte_bbdev_dec_op_alloc_bulk(tp->bbdev_op_pool, ops_enq, num_segments); AssertFatal(ret == 0, "Allocation failed for %d ops", num_segments); - set_ldpc_dec_op(ops_enq, bufs->inputs, bufs->hard_outputs, nrLDPC_slot_decoding_parameters); + set_ldpc_dec_op(ops_enq, bufs->inputs, bufs->hard_outputs, bufs->harq_outputs, nrLDPC_slot_decoding_parameters); uint16_t enq = 0, deq = 0; while (enq < num_segments) { @@ -656,24 +853,19 @@ pmd_lcore_ldpc_dec(void *arg) // Check if CRC is available otherwise rely on ops_enq[j]->status to detect decoding success // CRC is NOT available if the CRC type is 24_B which is when C is greater than 1 - if (nrLDPC_slot_decoding_parameters->TBs[h].C > 1) { - *status = (ops_enq[j]->status == 0); - } else { - uint8_t *decoded_bytes = nrLDPC_slot_decoding_parameters->TBs[h].segments[i].c; uint8_t crc_type = crcType(nrLDPC_slot_decoding_parameters->TBs[h].C, nrLDPC_slot_decoding_parameters->TBs[h].A); uint32_t len_with_crc = lenWithCrc(nrLDPC_slot_decoding_parameters->TBs[h].C, nrLDPC_slot_decoding_parameters->TBs[h].A); *status = check_crc(decoded_bytes, len_with_crc, crc_type); - } if (*status) { - *nrLDPC_slot_decoding_parameters->TBs[h].processedSegments = *nrLDPC_slot_decoding_parameters->TBs[h].processedSegments + 1; + *nrLDPC_slot_decoding_parameters->TBs[h].processedSegments = + *nrLDPC_slot_decoding_parameters->TBs[h].processedSegments + 1; } - ++j; } } @@ -698,9 +890,6 @@ static int pmd_lcore_ldpc_enc(void *arg) AssertFatal((num_segments < MAX_BURST), "BURST_SIZE should be <= %u", MAX_BURST); - struct rte_bbdev_info info; - rte_bbdev_info_get(tp->dev_id, &info); - while (rte_atomic16_read(&tp->op_params->sync) == SYNC_WAIT) rte_pause(); @@ -763,7 +952,8 @@ int start_pmd_dec(struct active_device *ad, t_params[0].nrLDPC_slot_decoding_parameters = nrLDPC_slot_decoding_parameters; used_cores++; // For now, we never enter here, we don't use the DPDK thread pool - RTE_LCORE_FOREACH_WORKER(lcore_id) { + RTE_LCORE_FOREACH_WORKER(lcore_id) + { if (used_cores >= num_lcores) break; t_params[used_cores].dev_id = ad->dev_id; @@ -807,7 +997,8 @@ int32_t start_pmd_enc(struct active_device *ad, t_params[0].nrLDPC_slot_encoding_parameters = nrLDPC_slot_encoding_parameters; used_cores++; // For now, we never enter here, we don't use the DPDK thread pool - RTE_LCORE_FOREACH_WORKER(lcore_id) { + RTE_LCORE_FOREACH_WORKER(lcore_id) + { if (used_cores >= num_lcores) break; t_params[used_cores].dev_id = ad->dev_id; @@ -828,46 +1019,110 @@ int32_t start_pmd_enc(struct active_device *ad, struct test_op_params *op_params = NULL; +static int normalize_dpdk_dev(const char *input, char *output, size_t out_len) +{ + regex_t regex_full, regex_short; + int reti; + + // patterns + const char *pattern_full = "^[0]{4}:[0-9a-fA-F]{2}:[0-9a-fA-F]{2}\\.[0-7]$"; + const char *pattern_short = "^[0-9a-fA-F]{2}:[0-9a-fA-F]{2}\\.[0-7]$"; + regcomp(®ex_full, pattern_full, REG_EXTENDED); + regcomp(®ex_short, pattern_short, REG_EXTENDED); + + // check full format + reti = regexec(®ex_full, input, 0, NULL, 0); + if (reti == 0) { + // already in full format + strncpy(output, input, out_len - 1); + output[out_len - 1] = '\0'; + } else { + // check short format + reti = regexec(®ex_short, input, 0, NULL, 0); + if (reti == 0) { + // convert to full format + snprintf(output, out_len, "0000:%s", input); + } else { + // invalid format + regfree(®ex_full); + regfree(®ex_short); + return -1; + } + } + regfree(®ex_full); + regfree(®ex_short); + return 0; +} + // OAI CODE int32_t nrLDPC_coding_init() { pthread_mutex_init(&encode_mutex, NULL); pthread_mutex_init(&decode_mutex, NULL); + int ret; - int dev_id = 0; - struct rte_bbdev_info info; - struct active_device *ad = active_devs; - char *dpdk_dev = NULL; //PCI address of the card - char *dpdk_core_list = NULL; // cores used by DPDK for T2 + int dev_id = -1; + + char *dpdk_dev = NULL; // PCI address of the card + char *dpdk_core_list = NULL; // cores used by DPDK for bbdev char *dpdk_file_prefix = NULL; + char *vfio_vf_token = NULL; // vfio token for the bbdev card + uint32_t num_harq_codeblock = 0; // size of the HARQ buffer in terms of the number of 32K blocks paramdef_t LoaderParams[] = { - {"dpdk_dev", NULL, 0, .strptr = &dpdk_dev, .defstrval = NULL, TYPE_STRING, 0, NULL}, - {"dpdk_core_list", NULL, 0, .strptr = &dpdk_core_list, .defstrval = NULL, TYPE_STRING, 0, NULL}, - {"dpdk_file_prefix", NULL, 0, .strptr = &dpdk_file_prefix, .defstrval = "b6", TYPE_STRING, 0, NULL} + {"dpdk_dev", NULL, 0, .strptr = &dpdk_dev, .defstrval = NULL, TYPE_STRING, 0, NULL}, + {"dpdk_core_list", NULL, 0, .strptr = &dpdk_core_list, .defstrval = NULL, TYPE_STRING, 0, NULL}, + {"dpdk_file_prefix", NULL, 0, .strptr = &dpdk_file_prefix, .defstrval = "b6", TYPE_STRING, 0, NULL}, + {"vfio_vf_token", NULL, 0, .strptr = &vfio_vf_token, .defstrval = NULL, TYPE_STRING, 0, NULL}, + {"num_harq_codeblock", NULL, 0, .uptr = &num_harq_codeblock, .defintval = 512, TYPE_UINT32, 0, NULL}, }; config_get(config_get_if(), LoaderParams, sizeofArray(LoaderParams), "nrLDPC_coding_t2"); - AssertFatal(dpdk_dev!=NULL, "nrLDPC_coding_t2.dpdk_dev was not provided"); - AssertFatal(dpdk_core_list!=NULL, "nrLDPC_coding_t2.dpdk_core_list was not provided"); - char *argv_re[] = {"bbdev", "-a", dpdk_dev, "-l", dpdk_core_list, "--file-prefix", dpdk_file_prefix, "--"}; - // EAL initialization, if already initialized (init in xran lib) try to probe DPDK device - ret = rte_eal_init(sizeofArray(argv_re), argv_re); + AssertFatal(dpdk_dev != NULL, "nrLDPC_coding_t2.dpdk_dev was not provided"); + AssertFatal(dpdk_core_list != NULL, "nrLDPC_coding_t2.dpdk_core_list was not provided"); + + char dpdk_dev_full[32]; + if (normalize_dpdk_dev(dpdk_dev, dpdk_dev_full, sizeof(dpdk_dev_full)) != 0) { + LOG_E(NR_PHY, "invalid DPDK device format: %s\n", dpdk_dev); + return -1; + } + + int argc = 7; + char *argv[11] = {"bbdev", "-l", dpdk_core_list, "-a", dpdk_dev_full, "--file-prefix", dpdk_file_prefix, "--", "--", "--", "--"}; + if (vfio_vf_token != NULL) { + argc += 2; + argv[7] = "--vfio-vf-token"; + argv[8] = vfio_vf_token; + } + ret = rte_eal_init(argc, argv); if (ret < 0) { - printf("EAL initialization failed, probing DPDK device %s\n", dpdk_dev); - if (rte_dev_probe(dpdk_dev) != 0) { - LOG_E(PHY, "T2 card %s not found\n", dpdk_dev); + LOG_W(NR_PHY, "EAL initialization failed, probing DPDK device %s\n", dpdk_dev_full); + if (rte_dev_probe(dpdk_dev_full) != 0) { + LOG_E(NR_PHY, "bbdev %s not found\n", dpdk_dev_full); return (-1); } } - // Use only device 0 - first detected device - rte_bbdev_info_get(0, &info); - // Set number of queues based on number of initialized cores (-l option) and driver - // capabilities - AssertFatal(add_dev(dev_id, &info)== 0, "Failed to setup bbdev"); + uint16_t nb_bbdevs = rte_bbdev_count(); + AssertFatal(nb_bbdevs > 0, "no bbdev found"); + + // find the baseband device that matches the dpdk_dev specified in the configurations + struct rte_bbdev_info info; + LOG_I(NR_PHY, "detected %u bbdev.\n", nb_bbdevs); + for (uint16_t device_id = 0; device_id < nb_bbdevs; device_id++) { + rte_bbdev_info_get(device_id, &info); + // check if info matches the dpdk_dev that we are looking for + if (strcmp(info.dev_name, dpdk_dev_full) == 0) { + LOG_I(NR_PHY, "bbdev %s found.\n", info.dev_name); + dev_id = device_id; + break; + } + } + AssertFatal(dev_id != -1, "bbdev %s not found.", dpdk_dev_full); + + AssertFatal(add_dev(dev_id, num_harq_codeblock) == 0, "Failed to setup bbdev"); AssertFatal(rte_bbdev_stats_reset(dev_id) == 0, "Failed to reset stats of bbdev %u", dev_id); AssertFatal(rte_bbdev_start(dev_id) == 0, "Failed to start bbdev %u", dev_id); - //the previous calls have populated this global variable (beurk) - // One more global to remove, not thread safe global op_params + // the previous calls have populated this global variable (beurk) + // One more global to remove, not thread safe global op_params op_params = rte_zmalloc(NULL, sizeof(struct test_op_params), RTE_CACHE_LINE_SIZE); AssertFatal(op_params != NULL, "Failed to alloc %zuB for op_params", @@ -877,34 +1132,119 @@ int32_t nrLDPC_coding_init() int out_max_sz = 8448; // max code block size (for BG1), 22 * 384 int in_max_sz = LDPC_MAX_CB_SIZE; // max number of encoded bits (for BG2 and MCS0) int num_queues = 1; - int f_ret = create_mempools(ad, socket_id, num_queues, out_max_sz, in_max_sz); + int f_ret = create_mempools(&active_dev, socket_id, num_queues, out_max_sz, in_max_sz); if (f_ret != 0) { printf("Couldn't create mempools"); return -1; } + + // initialize persistent data structure to keep track of HARQ-related information + init_op_data_objs_harq(active_dev.harq_buffers, active_dev.harq_in_mbuf_pool); + op_params->num_lcores = 1; return 0; } int32_t nrLDPC_coding_shutdown() { - struct active_device *ad = active_devs; int dev_id = 0; struct rte_bbdev_stats stats; - free_mempools(ad); + free(active_dev.harq_buffers); + free_mempools(&active_dev); rte_free(op_params); rte_bbdev_stats_get(dev_id, &stats); rte_bbdev_stop(dev_id); rte_bbdev_close(dev_id); - memset(active_devs, 0, sizeof(active_devs)); - nb_active_devs = 0; + memset(&active_dev, 0, sizeof(active_dev)); return 0; } +static void llr_scaling(int16_t *llr, int llr_len, uint8_t *llr_scaled, int8_t llr_size, int8_t llr_decimal, int8_t nb_layers, int8_t Qm) +{ + const int16_t llr_max = (1 << (llr_size - 1)) - 1; + const int16_t llr_min = -llr_max; + + // Step 1: Find the max absolute LLR + int16_t max_abs = 1; // prevent divide-by-zero + // SCALAR IMPLEMENTATION + // for (int i = 0; i < llr_len; i++) { + // int16_t abs_val = abs(llr[i]); + // if (abs_val > max_abs) max_abs = abs_val; + // } + // VECTORIZED IMPLEMENTATION + simde__m128i max_vec = simde_mm_set1_epi16(1); + for (int i = 0; i < llr_len; i += 8) { + simde__m128i llr_vec = simde_mm_loadu_si128((simde__m128i *)&llr[i]); + simde__m128i abs_vec = simde_mm_abs_epi16(llr_vec); + max_vec = simde_mm_max_epi16(max_vec, abs_vec); + } + // reduce max_vec to single max_abs + int16_t temp[8]; + simde_mm_storeu_si128((simde__m128i *)temp, max_vec); + for (int i = 0; i < 8; i++) { + if (temp[i] > max_abs) + max_abs = temp[i]; + } + + // Step 2: Compute dynamic scale factor + float fixed_point_range = (float)llr_max / (1 << llr_decimal); + float scale = fixed_point_range / (float)max_abs; + if (max_abs < fixed_point_range) { + scale = 1.0f; + } + + // Step 3: Scale and saturate + // SCALAR IMPLEMENTATION + // for (int i = 0; i < llr_len; i++) { + // float scaled = (float)llr[i] * scale; // map into fixed-point domain + // scaled = (int8_t)roundf(scaled * (1 << llr_decimal)); + // // Clamp to [-128, 127] + // if (scaled > llr_max) llr_scaled[i] = llr_max; + // else if (scaled < llr_min) llr_scaled[i] = llr_min; + // } + // VECTORIZED IMPLEMENTATION + simde__m128 scale_vec = simde_mm_set1_ps(scale); + simde__m128i llr_max_vec = simde_mm_set1_epi16(llr_max); + simde__m128i llr_min_vec = simde_mm_set1_epi16(llr_min); + simde__m128i decimal_shift = simde_mm_set1_epi16(1 << llr_decimal); + for (int i = 0; i < llr_len; i += 8) { + // load LLR values + simde__m128i llr_vec = simde_mm_loadu_si128((simde__m128i *)&llr[i]); + + // convert to float for scaling + simde__m128i llr_lo = simde_mm_cvtepi16_epi32(llr_vec); + simde__m128i llr_hi = simde_mm_cvtepi16_epi32(simde_mm_srli_si128(llr_vec, 8)); + simde__m128 float_lo = simde_mm_cvtepi32_ps(llr_lo); + simde__m128 float_hi = simde_mm_cvtepi32_ps(llr_hi); + + // scale + float_lo = simde_mm_mul_ps(float_lo, scale_vec); + float_hi = simde_mm_mul_ps(float_hi, scale_vec); + + // convert back to int16 with saturation + llr_lo = simde_mm_cvtps_epi32(float_lo); + llr_hi = simde_mm_cvtps_epi32(float_hi); + simde__m128i scaled_vec = simde_mm_packs_epi32(llr_lo, llr_hi); + + scaled_vec = simde_mm_mullo_epi16(scaled_vec, decimal_shift); + + // clamp to [llr_min, llr_max] + scaled_vec = simde_mm_min_epi16(scaled_vec, llr_max_vec); + scaled_vec = simde_mm_max_epi16(scaled_vec, llr_min_vec); + + // Pack to int8 and store + simde__m128i result = simde_mm_packs_epi16(scaled_vec, simde_mm_setzero_si128()); + simde_mm_storeu_si128((simde__m128i *)&llr_scaled[i], result); + } +} + int32_t nrLDPC_coding_decoder(nrLDPC_slot_decoding_parameters_t *nrLDPC_slot_decoding_parameters) { pthread_mutex_lock(&decode_mutex); + int ret; + int socket_id = active_dev.info.socket_id; + const uint16_t num_segments = nb_segments_decoding(nrLDPC_slot_decoding_parameters); /* It is not unlikely that l_ol becomes big enough to overflow the stack @@ -913,27 +1253,41 @@ int32_t nrLDPC_coding_decoder(nrLDPC_slot_decoding_parameters_t *nrLDPC_slot_dec */ uint8_t l_ol[num_segments * LDPC_MAX_CB_SIZE] __attribute__((aligned(16))); - // hardcoded we use first device - struct active_device *ad = active_devs; - struct rte_bbdev_info info; - int ret; - rte_bbdev_info_get(ad->dev_id, &info); - int socket_id = GET_SOCKET(info.socket_id); // fill_queue_buffers -> init_op_data_objs - struct rte_mempool *mbuf_pools[DATA_NUM_TYPES] = {ad->in_mbuf_pool, ad->hard_out_mbuf_pool}; + struct rte_mempool *mbuf_pools[DATA_NUM_TYPES] = {active_dev.in_mbuf_pool, + active_dev.hard_out_mbuf_pool, + active_dev.harq_out_mbuf_pool}; struct data_buffers data_buffers; - struct rte_bbdev_op_data **queue_ops[DATA_NUM_TYPES] = {&data_buffers.inputs, &data_buffers.hard_outputs}; - + struct rte_bbdev_op_data **queue_ops[DATA_NUM_TYPES] = {&data_buffers.inputs, + &data_buffers.hard_outputs, + &data_buffers.harq_outputs}; +#ifndef LDPC_T2 + int8_t llr_size = (active_dev.info.drv.capabilities)[RTE_BBDEV_OP_LDPC_DEC].cap.ldpc_dec.llr_size; + int8_t llr_decimal = (active_dev.info.drv.capabilities)[RTE_BBDEV_OP_LDPC_DEC].cap.ldpc_dec.llr_decimals; +#endif int offset = 0; for (int h = 0; h < nrLDPC_slot_decoding_parameters->nb_TBs; ++h) { for (int r = 0; r < nrLDPC_slot_decoding_parameters->TBs[h].C; r++) { +#ifdef LDPC_T2 + // For the T2, we simply saturate the LLRs. uint16_t z_ol[LDPC_MAX_CB_SIZE] __attribute__((aligned(16))); - memcpy(z_ol, nrLDPC_slot_decoding_parameters->TBs[h].segments[r].llr, nrLDPC_slot_decoding_parameters->TBs[h].segments[r].E * sizeof(uint16_t)); + memcpy(z_ol, + nrLDPC_slot_decoding_parameters->TBs[h].segments[r].llr, + nrLDPC_slot_decoding_parameters->TBs[h].segments[r].E * sizeof(uint16_t)); simde__m128i *pv_ol128 = (simde__m128i *)z_ol; simde__m128i *pl_ol128 = (simde__m128i *)&l_ol[offset]; for (int i = 0, j = 0; j < ((nrLDPC_slot_decoding_parameters->TBs[h].segments[r].E + 15) >> 4); i += 2, j++) { pl_ol128[j] = simde_mm_packs_epi16(pv_ol128[i], pv_ol128[i + 1]); } +#else + llr_scaling(nrLDPC_slot_decoding_parameters->TBs[h].segments[r].llr, + nrLDPC_slot_decoding_parameters->TBs[h].segments[r].E, + &l_ol[offset], + llr_size, + llr_decimal, + nrLDPC_slot_decoding_parameters->TBs[h].nb_layers, + nrLDPC_slot_decoding_parameters->TBs[h].Qm); +#endif offset += LDPC_MAX_CB_SIZE; } } @@ -946,13 +1300,13 @@ int32_t nrLDPC_coding_decoder(nrLDPC_slot_decoding_parameters_t *nrLDPC_slot_dec nrLDPC_slot_decoding_parameters, mbuf_pools[type], type, - info.drv.min_alignment); + active_dev.info.drv.min_alignment); AssertFatal(ret == 0, "Couldn't init rte_bbdev_op_data structs"); } - ret = start_pmd_dec(ad, op_params, &data_buffers, nrLDPC_slot_decoding_parameters); + ret = start_pmd_dec(&active_dev, op_params, &data_buffers, nrLDPC_slot_decoding_parameters); if (ret < 0) { - LOG_E(PHY, "Couldn't start pmd dec\n"); + LOG_E(NR_PHY, "Couldn't start pmd dec\n"); } for (enum op_data_type type = DATA_INPUT; type < DATA_NUM_TYPES; ++type) { @@ -973,27 +1327,28 @@ int32_t nrLDPC_coding_encoder(nrLDPC_slot_encoding_parameters_t *nrLDPC_slot_enc const uint16_t num_segments = nb_segments_encoding(nrLDPC_slot_encoding_parameters); - // hardcoded to use the first found board - struct active_device *ad = active_devs; int ret; - struct rte_bbdev_info info; - rte_bbdev_info_get(ad->dev_id, &info); - int socket_id = GET_SOCKET(info.socket_id); - // fill_queue_buffers -> init_op_data_objs - struct rte_mempool *mbuf_pools[DATA_NUM_TYPES] = {ad->in_mbuf_pool, ad->hard_out_mbuf_pool}; - struct data_buffers data_buffers; - struct rte_bbdev_op_data **queue_ops[DATA_NUM_TYPES] = {&data_buffers.inputs, &data_buffers.hard_outputs}; + int socket_id = active_dev.info.socket_id; - for (enum op_data_type type = DATA_INPUT; type < DATA_NUM_TYPES; ++type) { + // fill_queue_buffers -> init_op_data_objs + struct rte_mempool *mbuf_pools[2] = {active_dev.in_mbuf_pool, active_dev.hard_out_mbuf_pool}; + struct data_buffers data_buffers; + struct rte_bbdev_op_data **queue_ops[2] = {&data_buffers.inputs, &data_buffers.hard_outputs}; + + for (enum op_data_type type = DATA_INPUT; type < 2; ++type) { ret = allocate_buffers_on_socket(queue_ops[type], num_segments * sizeof(struct rte_bbdev_op_data), socket_id); AssertFatal(ret == 0, "Couldn't allocate memory for rte_bbdev_op_data structs"); - ret = init_op_data_objs_enc(*queue_ops[type], nrLDPC_slot_encoding_parameters, mbuf_pools[type], type, info.drv.min_alignment); + ret = init_op_data_objs_enc(*queue_ops[type], + nrLDPC_slot_encoding_parameters, + mbuf_pools[type], + type, + active_dev.info.drv.min_alignment); AssertFatal(ret == 0, "Couldn't init rte_bbdev_op_data structs"); } - ret = start_pmd_enc(ad, op_params, &data_buffers, nrLDPC_slot_encoding_parameters); + ret = start_pmd_enc(&active_dev, op_params, &data_buffers, nrLDPC_slot_encoding_parameters); - for (enum op_data_type type = DATA_INPUT; type < DATA_NUM_TYPES; ++type) { + for (enum op_data_type type = DATA_INPUT; type < 2; ++type) { for (int segment = 0; segment < num_segments; ++segment) rte_pktmbuf_free((*queue_ops[type])[segment].data); rte_free(*queue_ops[type]); @@ -1002,4 +1357,3 @@ int32_t nrLDPC_coding_encoder(nrLDPC_slot_encoding_parameters_t *nrLDPC_slot_enc pthread_mutex_unlock(&encode_mutex); return ret; } - diff --git a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_t2/nrLDPC_coding_t2.h b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_t2/nrLDPC_coding_t2.h index 642ac8f55a..0337202b9b 100644 --- a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_t2/nrLDPC_coding_t2.h +++ b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_t2/nrLDPC_coding_t2.h @@ -2,8 +2,8 @@ * Copyright(c) 2017 Intel Corporation */ -#ifndef _MAIN_H_ -#define _MAIN_H_ +#ifndef __NRLDPC_CODING_T2_H__ +#define __NRLDPC_CODING_T2_H__ #include #include @@ -17,6 +17,7 @@ enum op_data_type { DATA_INPUT = 0, DATA_HARD_OUTPUT, + DATA_HARQ_OUTPUT, DATA_NUM_TYPES, }; From c0d797ec0e16ebb77da0cc94330c031e19c4dcf7 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 4 Aug 2025 16:47:12 +0200 Subject: [PATCH 363/964] Rename libldpc_t2 to libldpc_aal Rename the library to reflect that it's more a generic AAL driver than specifically for AAL. To this end, rename some documentation. As of this commit, the options are still called nrLDPC_coding_t2. The next commit will correct this. Co-authored-by: Xin Zhe Khooi --- ci-scripts/xml_files/gnb_usrp_build.xml | 2 +- .../xml_files/t2_offload_dec_nr_ulsim.xml | 18 ++++---- .../xml_files/t2_offload_enc_nr_dlsim.xml | 24 +++++------ cmake_targets/build_oai | 2 +- doc/BUILD.md | 2 +- ...OFFLOAD_SETUP.md => LDPC_OFFLOAD_SETUP.md} | 18 ++++---- doc/README.md | 2 +- openair1/PHY/CODING/DOC/LDPCImplementation.md | 24 +++++------ .../PHY/CODING/nrLDPC_coding/CMakeLists.txt | 2 +- .../nrLDPC_coding_aal/CMakeLists.txt | 37 +++++++++++++++++ .../README.md | 2 +- .../nrLDPC_coding_aal.c} | 9 +--- .../nrLDPC_coding_aal.h} | 0 .../nrLDPC_coding_t2/CMakeLists.txt | 41 ------------------- 14 files changed, 87 insertions(+), 96 deletions(-) rename doc/{LDPC_T2_OFFLOAD_SETUP.md => LDPC_OFFLOAD_SETUP.md} (92%) create mode 100644 openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_aal/CMakeLists.txt rename openair1/PHY/CODING/nrLDPC_coding/{nrLDPC_coding_t2 => nrLDPC_coding_aal}/README.md (99%) rename openair1/PHY/CODING/nrLDPC_coding/{nrLDPC_coding_t2/nrLDPC_coding_t2.c => nrLDPC_coding_aal/nrLDPC_coding_aal.c} (99%) rename openair1/PHY/CODING/nrLDPC_coding/{nrLDPC_coding_t2/nrLDPC_coding_t2.h => nrLDPC_coding_aal/nrLDPC_coding_aal.h} (100%) delete mode 100644 openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_t2/CMakeLists.txt diff --git a/ci-scripts/xml_files/gnb_usrp_build.xml b/ci-scripts/xml_files/gnb_usrp_build.xml index f67098116b..db6450b259 100644 --- a/ci-scripts/xml_files/gnb_usrp_build.xml +++ b/ci-scripts/xml_files/gnb_usrp_build.xml @@ -40,7 +40,7 @@ TesteNB Build_eNB Build gNB (USRP) - --gNB -w USRP --ninja -c -P --build-lib ldpc_cuda --build-lib ldpc_t2 --cmake-opt -DASN1C_EXEC=/opt/asn1c/bin/asn1c + --gNB -w USRP --ninja -c -P --build-lib ldpc_cuda --build-lib ldpc_aal --cmake-opt -DASN1C_EXEC=/opt/asn1c/bin/asn1c True
diff --git a/ci-scripts/xml_files/t2_offload_dec_nr_ulsim.xml b/ci-scripts/xml_files/t2_offload_dec_nr_ulsim.xml index 15b8921a5a..c721441907 100644 --- a/ci-scripts/xml_files/t2_offload_dec_nr_ulsim.xml +++ b/ci-scripts/xml_files/t2_offload_dec_nr_ulsim.xml @@ -62,7 +62,7 @@ true nr_ulsim 100 - -n1000 -s30 -S30.2 -m5 -r106 -R106 -C10 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -m5 -r106 -R106 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12
@@ -80,7 +80,7 @@ true nr_ulsim 150 - -n1000 -s30 -S30.2 -m15 -r106 -R106 -C10 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -m15 -r106 -R106 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 @@ -98,7 +98,7 @@ true nr_ulsim 250 - -n1000 -s30 -S30.2 -m25 -r106 -R106 -C10 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -m25 -r106 -R106 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 @@ -116,7 +116,7 @@ true nr_ulsim 150 - -n1000 -s30 -S30.2 -m5 -r273 -R273 -C10 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -m5 -r273 -R273 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 @@ -134,7 +134,7 @@ true nr_ulsim 350 - -n1000 -s30 -S30.2 -m15 -r273 -R273 -C10 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -m15 -r273 -R273 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 @@ -152,7 +152,7 @@ true nr_ulsim 550 - -n1000 -s30 -S30.2 -m25 -r273 -R273 -C10 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -m25 -r273 -R273 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 @@ -170,7 +170,7 @@ true nr_ulsim 250 - -n1000 -s30 -S30.2 -m5 -r273 -R273 -C10 -W2 -z2 -y2 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -m5 -r273 -R273 -C10 -W2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 @@ -188,7 +188,7 @@ true nr_ulsim 650 - -n1000 -s30 -S30.2 -m15 -r273 -R273 -C10 -W2 -z2 -y2 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -m15 -r273 -R273 -C10 -W2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 @@ -206,7 +206,7 @@ true nr_ulsim 1100 - -n1000 -s30 -S30.2 -m25 -r273 -R273 -C10 -W2 -z2 -y2 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -m25 -r273 -R273 -C10 -W2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 diff --git a/ci-scripts/xml_files/t2_offload_enc_nr_dlsim.xml b/ci-scripts/xml_files/t2_offload_enc_nr_dlsim.xml index 7feb93741a..14f488dc6c 100644 --- a/ci-scripts/xml_files/t2_offload_enc_nr_dlsim.xml +++ b/ci-scripts/xml_files/t2_offload_enc_nr_dlsim.xml @@ -63,7 +63,7 @@ true nr_dlsim 100 - -n1000 -s30 -S30.2 -e5 -b106 -R106 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -e5 -b106 -R106 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 @@ -81,7 +81,7 @@ true nr_dlsim 100 - -n1000 -s30 -S30.2 -e15 -b106 -R106 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -e15 -b106 -R106 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 @@ -99,7 +99,7 @@ true nr_dlsim 200 - -n1000 -s30 -S30.2 -e25 -b106 -R106 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -e25 -b106 -R106 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 @@ -117,7 +117,7 @@ true nr_dlsim 150 - -n1000 -s30 -S30.2 -e5 -b273 -R273 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -e5 -b273 -R273 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 @@ -135,7 +135,7 @@ true nr_dlsim 250 - -n1000 -s30 -S30.2 -e15 -b273 -R273 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -e15 -b273 -R273 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 @@ -153,7 +153,7 @@ true nr_dlsim 400 - -n1000 -s30 -S30.2 -e25 -b273 -R273 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -e25 -b273 -R273 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 @@ -171,7 +171,7 @@ true nr_dlsim 200 - -n1000 -s30 -S30.2 -e5 -b273 -R273 -X4,5,6,7,8,9 -x2 -z2 -y2 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -e5 -b273 -R273 -X4,5,6,7,8,9 -x2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 @@ -189,7 +189,7 @@ true nr_dlsim 500 - -n1000 -s30 -S30.2 -e15 -b273 -R273 -X4,5,6,7,8,9 -x2 -z2 -y2 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -e15 -b273 -R273 -X4,5,6,7,8,9 -x2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 @@ -207,7 +207,7 @@ true nr_dlsim 500 - -n1000 -s30 -S30.2 -e25 -b273 -R273 -X4,5,6,7,8,9 -x2 -z2 -y2 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -e25 -b273 -R273 -X4,5,6,7,8,9 -x2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 @@ -225,7 +225,7 @@ true nr_dlsim 200 - -n1000 -s30 -S30.2 -e5 -b273 -R273 -X4,5,6,7,8,9 -x2 -z4 -y4 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -e5 -b273 -R273 -X4,5,6,7,8,9 -x2 -z4 -y4 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 @@ -243,7 +243,7 @@ true nr_dlsim 300 - -n1000 -s30 -S30.2 -e15 -b273 -R273 -X4,5,6,7,8,9 -x2 -z4 -y4 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -e15 -b273 -R273 -X4,5,6,7,8,9 -x2 -z4 -y4 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 @@ -261,6 +261,6 @@ true nr_dlsim 450 - -n1000 -s30 -S30.2 -e25 -b273 -R273 -X4,5,6,7,8,9 -x2 -z4 -y4 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -e25 -b273 -R273 -X4,5,6,7,8,9 -x2 -z4 -y4 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index 0b6f31d930..292e8d0575 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -45,7 +45,7 @@ BUILD_DOXYGEN=0 DISABLE_HARDWARE_DEPENDENCY="False" CMAKE_BUILD_TYPE="RelWithDebInfo" CMAKE_CMD="$CMAKE" -OPTIONAL_LIBRARIES="telnetsrv enbscope uescope nrscope ldpc_cuda ldpc_t2 ldpc_xdma websrv oai_iqplayer imscope imscope_record" +OPTIONAL_LIBRARIES="telnetsrv enbscope uescope nrscope ldpc_cuda ldpc_aal ldpc_xdma websrv oai_iqplayer imscope imscope_record" TARGET_LIST="" BUILD_TOOL_OPT="-j$(nproc)" diff --git a/doc/BUILD.md b/doc/BUILD.md index 4d629007b0..8298204859 100644 --- a/doc/BUILD.md +++ b/doc/BUILD.md @@ -185,7 +185,7 @@ Some libraries have further dependencies and might not build on every system: - `enbscope`, `uescope`, `nrscope`: libforms/X - `ldpc_cuda`: CUDA - `websrv`: npm and others -- `ldpc_t2`: DPDK with patch +- `ldpc_aal`: DPDK with patch # Running `cmake` directly diff --git a/doc/LDPC_T2_OFFLOAD_SETUP.md b/doc/LDPC_OFFLOAD_SETUP.md similarity index 92% rename from doc/LDPC_T2_OFFLOAD_SETUP.md rename to doc/LDPC_OFFLOAD_SETUP.md index 0e9506db78..bada5c36df 100644 --- a/doc/LDPC_T2_OFFLOAD_SETUP.md +++ b/doc/LDPC_OFFLOAD_SETUP.md @@ -17,7 +17,7 @@ [[_TOC_]] This documentation describes the integration of LDPC coding for lookaside acceleration using O-RAN AAL/DPDK BBDEV in OAI, along with its usage. -For details on the implementation, please consult the [developer notes](../openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_t2/README.md). +For details on the implementation, please consult the [developer notes](../openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_aal/README.md). # Requirements @@ -209,12 +209,12 @@ cd ~/openairinterface5g/cmake_targets cd ~/openairinterface5g source oaienv cd cmake_targets -./build_oai -w USRP --ninja --gNB -P --build-lib "ldpc_t2" -C +./build_oai -w USRP --ninja --gNB -P --build-lib "ldpc_aal" -C ``` -A shared object file `libldpc_t2.so` will be created during the compilation. +A shared object file `libldpc_aal.so` will be created during the compilation. This object is conditionally compiled. -The selection of the library to compile is done using `--build-lib ldpc_t2`. +The selection of the library to compile is done using `--build-lib ldpc_aal`. > Note: The required DPDK poll mode driver has to be present on the host machine and required DPDK version has to be installed on the host, prior to building OAI. @@ -245,14 +245,14 @@ nrLDPC_coding_t2 : { loader : { ldpc : { - shlibversion : "_t2"; + shlibversion : "_aal"; }; }; ``` # Running OAI with O-RAN AAL -In general, to offload of the channel coding to the LDPC accelerator, we use use the `--loader.ldpc.shlibversion _t2` option. +In general, to offload of the channel coding to the LDPC accelerator, we use use the `--loader.ldpc.shlibversion _aal` option. ## 5G PHY simulators @@ -263,7 +263,7 @@ Example command: cd ~/openairinterface5g source oaienv cd cmake_targets/ran_build/build -sudo ./nr_ulsim -n100 -s20 -m20 -r273 -R273 --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev 0000:f7:00.1 --nrLDPC_coding_t2.dpdk_core_list 0-1 --nrLDPC_coding_t2.vfio_vf_token 00112233-4455-6677-8899-aabbccddeeff +sudo ./nr_ulsim -n100 -s20 -m20 -r273 -R273 --loader.ldpc.shlibversion _aal --nrLDPC_coding_t2.dpdk_dev 0000:f7:00.1 --nrLDPC_coding_t2.dpdk_core_list 0-1 --nrLDPC_coding_t2.vfio_vf_token 00112233-4455-6677-8899-aabbccddeeff ``` ### nr_dlsim @@ -272,7 +272,7 @@ Example command: cd ~/openairinterface5g source oaienv cd cmake_targets/ran_build/build -sudo ./nr_dlsim -n300 -s30 -R 106 -e 27 --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev 0000:f7:00.1 --nrLDPC_coding_t2.dpdk_core_list 0-1 --nrLDPC_coding_t2.vfio_vf_token 00112233-4455-6677-8899-aabbccddeeff +sudo ./nr_dlsim -n300 -s30 -R 106 -e 27 --loader.ldpc.shlibversion _aal --nrLDPC_coding_t2.dpdk_dev 0000:f7:00.1 --nrLDPC_coding_t2.dpdk_core_list 0-1 --nrLDPC_coding_t2.vfio_vf_token 00112233-4455-6677-8899-aabbccddeeff ``` ## OTA test @@ -284,7 +284,7 @@ Example command: cd ~/openairinterface5g source oaienv cd cmake_targets/ran_build/build -sudo ./nr-softmodem -O ~/gnb.conf --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev 0000:f7:00.1 --nrLDPC_coding_t2.dpdk_core_list 14-15 --nrLDPC_coding_t2.vfio_vf_token 00112233-4455-6677-8899-aabbccddeeff --nrLDPC_coding_t2.eal_init_bbdev 1 +sudo ./nr-softmodem -O ~/gnb.conf --loader.ldpc.shlibversion _aal --nrLDPC_coding_t2.dpdk_dev 0000:f7:00.1 --nrLDPC_coding_t2.dpdk_core_list 14-15 --nrLDPC_coding_t2.vfio_vf_token 00112233-4455-6677-8899-aabbccddeeff --nrLDPC_coding_t2.eal_init_bbdev 1 ``` # Known Issue(s) diff --git a/doc/README.md b/doc/README.md index 756294fb5d..0776e627c9 100644 --- a/doc/README.md +++ b/doc/README.md @@ -64,7 +64,7 @@ There is some general information in the [OpenAirInterface Gitlab Wiki](https:// - [How to run with E2 agent](../openair2/E2AP/README.md) - [How to run the physical simulators](./physical-simulators.md) - [How to setup OAI with Nvidia Aerial and Foxconn](./Aerial_FAPI_Split_Tutorial.md) -- [How to setup OAI with AMD T2 Telco card](./LDPC_T2_OFFLOAD_SETUP.md) +- [How to setup OAI with LDPC accelerators (Xilinx T2/Intel ACCs)](./LDPC_OFFLOAD_SETUP.md) - [How to do a handover](./handover-tutorial.md) - [How to setup gNB frequency](./gNB_frequency_setup.md) diff --git a/openair1/PHY/CODING/DOC/LDPCImplementation.md b/openair1/PHY/CODING/DOC/LDPCImplementation.md index dc2959bc73..956dad97bf 100644 --- a/openair1/PHY/CODING/DOC/LDPCImplementation.md +++ b/openair1/PHY/CODING/DOC/LDPCImplementation.md @@ -28,35 +28,35 @@ shlib_path libldpc.so `libldpc.so` has its decoder implemented in [nrLDPC_coding_segment_decoder.c](file://../nrLDPC_coding/nrLDPC_coding_segment/nrLDPC_coding_segment_decoder.c).\ Its encoder is implemented in [nrLDPC_coding_segment_encoder.c](file://../nrLDPC_coding/nrLDPC_coding_segment/nrLDPC_coding_segment_encoder.c). -loading `libldpc_t2.so` instead of `libldpc.so`: +loading `libldpc_aal.so` instead of `libldpc.so`: -`make ldpc_t2` +`make ldpc_aal` -This command creates the `libldpc_t2.so` shared library. +This command creates the `libldpc_aal.so` shared library. ``` -Building C object CMakeFiles/ldpc_t2.dir/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_t2/nrLDPC_coding_t2.c.o -Linking C shared module libldpc_t2.so +Building C object CMakeFiles/ldpc_aal.dir/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_aal/nrLDPC_coding_aal.c.o +Linking C shared module libldpc_aal.so ``` At runtime, to successfully use LDPC accelerators (e.g., Xilinx T2/Intel ACCs), you will need to install the corresponding drivers and tools. -Please refer to the dedicated documentation at [LDPC_T2_OFFLOAD_SETUP.md](file://../../../../doc/LDPC_T2_OFFLOAD_SETUP.md). +Please refer to the dedicated documentation at [LDPC_OFFLOAD_SETUP.md](file://../../../../doc/LDPC_OFFLOAD_SETUP.md). -`./nr-softmodem -O libconfig:gnb.band78.sa.fr1.106PRB.usrpb210.conf:dbgl5 --rfsim --rfsimulator.serveraddr server --log_config.gtpu_log_level info --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev 01:00.0 --nrLDPC_coding_t2.dpdk_core_list 0-1` +`./nr-softmodem -O libconfig:gnb.band78.sa.fr1.106PRB.usrpb210.conf:dbgl5 --rfsim --rfsimulator.serveraddr server --log_config.gtpu_log_level info --loader.ldpc.shlibversion _aal --nrLDPC_coding_t2.dpdk_dev 01:00.0 --nrLDPC_coding_t2.dpdk_core_list 0-1` ``` ....................... [CONFIG] loader.ldpc.shlibversion set to default value "" [LIBCONFIG] loader.ldpc: 2/2 parameters successfully set, (1 to default value) -[CONFIG] shlibversion set to _t2 from command line +[CONFIG] shlibversion set to _aal from command line [CONFIG] loader.ldpc 1 options set from command line -shlib_path libldpc_t2.so -[LOADER] library libldpc_t2.so successfully loaded +shlib_path libldpc_aal.so +[LOADER] library libldpc_aal.so successfully loaded ........................ ``` -`libldpc_t2.so` has its decoder and its encoder implemented in [nrLDPC_coding_t2.c](file://../nrLDPC_coding/nrLDPC_coding_t2/nrLDPC_coding_t2.c). +`libldpc_aal.so` has its decoder and its encoder implemented in [nrLDPC_coding_aal.c](file://../nrLDPC_coding/nrLDPC_coding_aal/nrLDPC_coding_aal.c). loading `libldpc_xdma.so` instead of `libldpc.so`: @@ -103,7 +103,7 @@ Libraries implementing the slotwise LDPC coding must be named `libldpc<_version> `libldpc.so` is completed. -`libldpc_t2.so` is completed. +`libldpc_aal.so` is completed. `libldpc_xdma.so` is completed. diff --git a/openair1/PHY/CODING/nrLDPC_coding/CMakeLists.txt b/openair1/PHY/CODING/nrLDPC_coding/CMakeLists.txt index e60ca479bb..356aa5f2a0 100644 --- a/openair1/PHY/CODING/nrLDPC_coding/CMakeLists.txt +++ b/openair1/PHY/CODING/nrLDPC_coding/CMakeLists.txt @@ -1,3 +1,3 @@ add_subdirectory(nrLDPC_coding_segment) add_subdirectory(nrLDPC_coding_xdma) -add_subdirectory(nrLDPC_coding_t2) +add_subdirectory(nrLDPC_coding_aal) diff --git a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_aal/CMakeLists.txt b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_aal/CMakeLists.txt new file mode 100644 index 0000000000..eeff46cd14 --- /dev/null +++ b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_aal/CMakeLists.txt @@ -0,0 +1,37 @@ +########################################################## +# LDPC offload library - O-RAN AAL/DPDK BBDEV +########################################################## + +add_boolean_option(ENABLE_LDPC_AAL OFF "Build support for LDPC Offload using O-RAN AAL library" OFF) + +if (ENABLE_LDPC_AAL) + pkg_check_modules(LIBDPDK_AAL REQUIRED libdpdk>=20.11.9) + + find_library(PMD_T2 NAMES rte_baseband_accl_ldpc HINTS ${LIBDPDK_AAL_LIBRARY_DIRS}) + if (PMD_T2) + add_compile_definitions(LDPC_T2) + message(STATUS "found poll-mode driver for AccelerComm T2 LDPC Offload (rte_baseband_accl_ldpc.so)") + else() + if (LIBDPDK_AAL_VERSION VERSION_LESS "22.11") + message(FATAL_ERROR "for non-T2 BBDEV PMDs, we support the Intel ACC100 and ACC200 (VRB1), using DPDK 22.11 or later.") + endif() + endif() + + add_library(ldpc_aal MODULE nrLDPC_coding_aal.c) + + set_target_properties(ldpc_aal PROPERTIES COMPILE_FLAGS "-DALLOW_EXPERIMENTAL_API") + set_target_properties(ldpc_aal PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) + target_include_directories(ldpc_aal PRIVATE ${LIBDPDK_AAL_INCLUDE_DIRS}) + target_link_libraries(ldpc_aal PRIVATE ldpc_gen_HEADERS ${LIBDPDK_AAL_LDFLAGS}) + if (PMD_T2) + target_link_libraries(ldpc_aal PRIVATE ${PMD_T2}) + endif() + + add_dependencies(nr-softmodem ldpc_aal) + add_dependencies(nr-uesoftmodem ldpc_aal) + add_dependencies(nr_ulsim ldpc_aal) + add_dependencies(nr_ulschsim ldpc_aal) + add_dependencies(nr_dlsim ldpc_aal) + add_dependencies(nr_dlschsim ldpc_aal) + +endif() diff --git a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_t2/README.md b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_aal/README.md similarity index 99% rename from openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_t2/README.md rename to openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_aal/README.md index ee55f7ff21..140fff5f1e 100644 --- a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_t2/README.md +++ b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_aal/README.md @@ -1,4 +1,4 @@ -This document highlights some of the key aspects of the implementation for O-RAN AAL/DPDK BBDEV; for user documentation, please consult the [setup guide](../../../../../doc/LDPC_T2_OFFLOAD_SETUP.md) instead. +This document highlights some of the key aspects of the implementation for O-RAN AAL/DPDK BBDEV; for user documentation, please consult the [setup guide](../../../../../doc/LDPC_OFFLOAD_SETUP.md) instead. ## Overview diff --git a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_t2/nrLDPC_coding_t2.c b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_aal/nrLDPC_coding_aal.c similarity index 99% rename from openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_t2/nrLDPC_coding_t2.c rename to openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_aal/nrLDPC_coding_aal.c index bd1aad254d..661fc0ce63 100644 --- a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_t2/nrLDPC_coding_t2.c +++ b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_aal/nrLDPC_coding_aal.c @@ -2,13 +2,8 @@ * Copyright(c) 2017 Intel Corporation */ -/*! \file PHY/CODING/nrLDPC_coding/nrLDPC_coding_t2/nrLDPC_coding_t2.c - * \note: based on testbbdev test_bbdev_perf.c functions. Harq buffer offset added. - * \mbuf and mempool allocated at the init step, LDPC parameters updated from OAI. - */ - -#include "PHY/CODING/nrLDPC_coding/nrLDPC_coding_interface.h" -#include "PHY/CODING/nrLDPC_coding/nrLDPC_coding_t2/nrLDPC_coding_t2.h" +#include "../nrLDPC_coding_interface.h" +#include "nrLDPC_coding_aal.h" #include "PHY/sse_intrin.h" #include #define NR_LDPC_ENABLE_PARITY_CHECK diff --git a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_t2/nrLDPC_coding_t2.h b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_aal/nrLDPC_coding_aal.h similarity index 100% rename from openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_t2/nrLDPC_coding_t2.h rename to openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_aal/nrLDPC_coding_aal.h diff --git a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_t2/CMakeLists.txt b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_t2/CMakeLists.txt deleted file mode 100644 index b6a0cacf39..0000000000 --- a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_t2/CMakeLists.txt +++ /dev/null @@ -1,41 +0,0 @@ -########################################################## -# LDPC offload library - DPDK BBDEV -########################################################## - -add_boolean_option(ENABLE_LDPC_T2 OFF "Build support for LDPC Offload to T2 library" OFF) - -if (ENABLE_LDPC_T2) - pkg_check_modules(LIBDPDK_T2 REQUIRED libdpdk>=20.11.9) - - if(LIBDPDK_T2_VERSION VERSION_LESS "21.11") - add_compile_definitions(DPDK_VER_PRE_21_11) - endif() - - find_library(PMD_T2 NAMES rte_baseband_accl_ldpc HINTS ${LIBDPDK_T2_LIBRARY_DIRS}) - if (PMD_T2) - add_compile_definitions(LDPC_T2) - message(STATUS "found poll-mode driver for AccelerComm T2 LDPC Offload (rte_baseband_accl_ldpc.so)") - else() - if (LIBDPDK_T2_VERSION VERSION_LESS "22.11") - message(FATAL_ERROR "for non-T2 BBDEV PMDs, we support the Intel ACC100 and ACC200 (VRB1), using DPDK 22.11 or later.") - endif() - endif() - - add_library(ldpc_t2 MODULE nrLDPC_coding_t2.c) - - set_target_properties(ldpc_t2 PROPERTIES COMPILE_FLAGS "-DALLOW_EXPERIMENTAL_API") - set_target_properties(ldpc_t2 PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) - target_include_directories(ldpc_t2 PRIVATE ${LIBDPDK_T2_INCLUDE_DIRS}) - target_link_libraries(ldpc_t2 PRIVATE ldpc_gen_HEADERS ${LIBDPDK_T2_LDFLAGS}) - if (PMD_T2) - target_link_libraries(ldpc_t2 PRIVATE ${PMD_T2}) - endif() - - add_dependencies(nr-softmodem ldpc_t2) - add_dependencies(nr-uesoftmodem ldpc_t2) - add_dependencies(nr_ulsim ldpc_t2) - add_dependencies(nr_ulschsim ldpc_t2) - add_dependencies(nr_dlsim ldpc_t2) - add_dependencies(nr_dlschsim ldpc_t2) - -endif() From 0d4246e3549f9b43b1811a2b62292d8b07f574eb Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 24 Jul 2025 13:53:02 +0200 Subject: [PATCH 364/964] Rename nrLDPC_coding_t2 options to nrLDPC_coding_aal --- .../xml_files/t2_offload_dec_nr_ulsim.xml | 18 ++++++------ .../xml_files/t2_offload_enc_nr_dlsim.xml | 24 ++++++++-------- doc/LDPC_OFFLOAD_SETUP.md | 28 +++++++++++-------- openair1/PHY/CODING/DOC/LDPCImplementation.md | 2 +- .../nrLDPC_coding_aal/nrLDPC_coding_aal.c | 8 ++++-- radio/fhi_72/oran-config.c | 4 +-- 6 files changed, 45 insertions(+), 39 deletions(-) diff --git a/ci-scripts/xml_files/t2_offload_dec_nr_ulsim.xml b/ci-scripts/xml_files/t2_offload_dec_nr_ulsim.xml index c721441907..5cfc1eeb72 100644 --- a/ci-scripts/xml_files/t2_offload_dec_nr_ulsim.xml +++ b/ci-scripts/xml_files/t2_offload_dec_nr_ulsim.xml @@ -62,7 +62,7 @@ true nr_ulsim 100 - -n1000 -s30 -S30.2 -m5 -r106 -R106 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -m5 -r106 -R106 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 @@ -80,7 +80,7 @@ true nr_ulsim 150 - -n1000 -s30 -S30.2 -m15 -r106 -R106 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -m15 -r106 -R106 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 @@ -98,7 +98,7 @@ true nr_ulsim 250 - -n1000 -s30 -S30.2 -m25 -r106 -R106 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -m25 -r106 -R106 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 @@ -116,7 +116,7 @@ true nr_ulsim 150 - -n1000 -s30 -S30.2 -m5 -r273 -R273 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -m5 -r273 -R273 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 @@ -134,7 +134,7 @@ true nr_ulsim 350 - -n1000 -s30 -S30.2 -m15 -r273 -R273 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -m15 -r273 -R273 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 @@ -152,7 +152,7 @@ true nr_ulsim 550 - -n1000 -s30 -S30.2 -m25 -r273 -R273 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -m25 -r273 -R273 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 @@ -170,7 +170,7 @@ true nr_ulsim 250 - -n1000 -s30 -S30.2 -m5 -r273 -R273 -C10 -W2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -m5 -r273 -R273 -C10 -W2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 @@ -188,7 +188,7 @@ true nr_ulsim 650 - -n1000 -s30 -S30.2 -m15 -r273 -R273 -C10 -W2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -m15 -r273 -R273 -C10 -W2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 @@ -206,7 +206,7 @@ true nr_ulsim 1100 - -n1000 -s30 -S30.2 -m25 -r273 -R273 -C10 -W2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -m25 -r273 -R273 -C10 -W2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 diff --git a/ci-scripts/xml_files/t2_offload_enc_nr_dlsim.xml b/ci-scripts/xml_files/t2_offload_enc_nr_dlsim.xml index 14f488dc6c..57b6afe21a 100644 --- a/ci-scripts/xml_files/t2_offload_enc_nr_dlsim.xml +++ b/ci-scripts/xml_files/t2_offload_enc_nr_dlsim.xml @@ -63,7 +63,7 @@ true nr_dlsim 100 - -n1000 -s30 -S30.2 -e5 -b106 -R106 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -e5 -b106 -R106 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 @@ -81,7 +81,7 @@ true nr_dlsim 100 - -n1000 -s30 -S30.2 -e15 -b106 -R106 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -e15 -b106 -R106 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 @@ -99,7 +99,7 @@ true nr_dlsim 200 - -n1000 -s30 -S30.2 -e25 -b106 -R106 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -e25 -b106 -R106 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 @@ -117,7 +117,7 @@ true nr_dlsim 150 - -n1000 -s30 -S30.2 -e5 -b273 -R273 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -e5 -b273 -R273 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 @@ -135,7 +135,7 @@ true nr_dlsim 250 - -n1000 -s30 -S30.2 -e15 -b273 -R273 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -e15 -b273 -R273 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 @@ -153,7 +153,7 @@ true nr_dlsim 400 - -n1000 -s30 -S30.2 -e25 -b273 -R273 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -e25 -b273 -R273 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 @@ -171,7 +171,7 @@ true nr_dlsim 200 - -n1000 -s30 -S30.2 -e5 -b273 -R273 -X4,5,6,7,8,9 -x2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -e5 -b273 -R273 -X4,5,6,7,8,9 -x2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 @@ -189,7 +189,7 @@ true nr_dlsim 500 - -n1000 -s30 -S30.2 -e15 -b273 -R273 -X4,5,6,7,8,9 -x2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -e15 -b273 -R273 -X4,5,6,7,8,9 -x2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 @@ -207,7 +207,7 @@ true nr_dlsim 500 - -n1000 -s30 -S30.2 -e25 -b273 -R273 -X4,5,6,7,8,9 -x2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -e25 -b273 -R273 -X4,5,6,7,8,9 -x2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 @@ -225,7 +225,7 @@ true nr_dlsim 200 - -n1000 -s30 -S30.2 -e5 -b273 -R273 -X4,5,6,7,8,9 -x2 -z4 -y4 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -e5 -b273 -R273 -X4,5,6,7,8,9 -x2 -z4 -y4 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 @@ -243,7 +243,7 @@ true nr_dlsim 300 - -n1000 -s30 -S30.2 -e15 -b273 -R273 -X4,5,6,7,8,9 -x2 -z4 -y4 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -e15 -b273 -R273 -X4,5,6,7,8,9 -x2 -z4 -y4 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 @@ -261,6 +261,6 @@ true nr_dlsim 450 - -n1000 -s30 -S30.2 -e25 -b273 -R273 -X4,5,6,7,8,9 -x2 -z4 -y4 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_t2.dpdk_dev af:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -e25 -b273 -R273 -X4,5,6,7,8,9 -x2 -z4 -y4 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 diff --git a/doc/LDPC_OFFLOAD_SETUP.md b/doc/LDPC_OFFLOAD_SETUP.md index bada5c36df..265a94ff71 100644 --- a/doc/LDPC_OFFLOAD_SETUP.md +++ b/doc/LDPC_OFFLOAD_SETUP.md @@ -221,23 +221,27 @@ The selection of the library to compile is done using `--build-lib ldpc_aal`. # O-RAN AAL DPDK EAL parameters To configure O-RAN AAL/DPDK BBDEV, you can set the following parameters via the command line of PHY simulators or nr-softmodem: -- `nrLDPC_coding_t2.dpdk_dev` - **mandatory** parameter, specifies the PCI address of our accelerator. It must follow the format `WWWW:XX:YY.Z`. +> Note: the group parameter name has been renamed from `nrLDPC_coding_t2` to +> `nrLDPC_coding_aal` to better reflect that it is a generic AAL accelerator +> card. -- `nrLDPC_coding_t2.dpdk_core_list` - **mandatory** parameter, specifies the CPU cores assigned to DPDK . -Ensure that the CPU cores specified in `nrLDPC_coding_t2.dpdk_core_list` are available and not used by other processes to avoid conflicts. +- `nrLDPC_coding_aal.dpdk_dev` - **mandatory** parameter, specifies the PCI address of our accelerator. It must follow the format `WWWW:XX:YY.Z`. -- `nrLDPC_coding_t2.dpdk_prefix` - optional parameter, DPDK shared data file prefix, by default set to *b6*. +- `nrLDPC_coding_aal.dpdk_core_list` - **mandatory** parameter, specifies the CPU cores assigned to DPDK . +Ensure that the CPU cores specified in `nrLDPC_coding_aal.dpdk_core_list` are available and not used by other processes to avoid conflicts. -- `nrLDPC_coding_t2.vfio_vf_token` - optional parameter, VFIO token set for the VF, if applicable. +- `nrLDPC_coding_aal.dpdk_prefix` - optional parameter, DPDK shared data file prefix, by default set to *b6*. -- `nrLDPC_coding_t2.num_harq_codeblock` - optional parameter, size of the HARQ buffer in terms of the number of 32kB blocks, by default set to *512* (maximum for the T2; as for the ACCs, this can be further increased). +- `nrLDPC_coding_aal.vfio_vf_token` - optional parameter, VFIO token set for the VF, if applicable. -- `nrLDPC_coding_t2.eal_init_bbdev` - optional parameter, set this to 1 when using with FHI72 with the Intel ACCs. For the T2, this is not required. +- `nrLDPC_coding_aal.num_harq_codeblock` - optional parameter, size of the HARQ buffer in terms of the number of 32kB blocks, by default set to *512* (maximum for the T2; as for the ACCs, this can be further increased). + +- `nrLDPC_coding_aal.eal_init_bbdev` - optional parameter, set this to 1 when using with FHI72 with the Intel ACCs. For the T2, this is not required. **Note:** These parameters can also be provided in a configuration file. Example for the ACC200: ``` -nrLDPC_coding_t2 : { +nrLDPC_coding_aal : { dpdk_dev : "0000:f7:00.1"; dpdk_core_list : "14-15"; vfio_vf_token: "00112233-4455-6677-8899-aabbccddeeff"; @@ -263,7 +267,7 @@ Example command: cd ~/openairinterface5g source oaienv cd cmake_targets/ran_build/build -sudo ./nr_ulsim -n100 -s20 -m20 -r273 -R273 --loader.ldpc.shlibversion _aal --nrLDPC_coding_t2.dpdk_dev 0000:f7:00.1 --nrLDPC_coding_t2.dpdk_core_list 0-1 --nrLDPC_coding_t2.vfio_vf_token 00112233-4455-6677-8899-aabbccddeeff +sudo ./nr_ulsim -n100 -s20 -m20 -r273 -R273 --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev 0000:f7:00.1 --nrLDPC_coding_aal.dpdk_core_list 0-1 --nrLDPC_coding_aal.vfio_vf_token 00112233-4455-6677-8899-aabbccddeeff ``` ### nr_dlsim @@ -272,7 +276,7 @@ Example command: cd ~/openairinterface5g source oaienv cd cmake_targets/ran_build/build -sudo ./nr_dlsim -n300 -s30 -R 106 -e 27 --loader.ldpc.shlibversion _aal --nrLDPC_coding_t2.dpdk_dev 0000:f7:00.1 --nrLDPC_coding_t2.dpdk_core_list 0-1 --nrLDPC_coding_t2.vfio_vf_token 00112233-4455-6677-8899-aabbccddeeff +sudo ./nr_dlsim -n300 -s30 -R 106 -e 27 --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev 0000:f7:00.1 --nrLDPC_coding_aal.dpdk_core_list 0-1 --nrLDPC_coding_aal.vfio_vf_token 00112233-4455-6677-8899-aabbccddeeff ``` ## OTA test @@ -284,14 +288,14 @@ Example command: cd ~/openairinterface5g source oaienv cd cmake_targets/ran_build/build -sudo ./nr-softmodem -O ~/gnb.conf --loader.ldpc.shlibversion _aal --nrLDPC_coding_t2.dpdk_dev 0000:f7:00.1 --nrLDPC_coding_t2.dpdk_core_list 14-15 --nrLDPC_coding_t2.vfio_vf_token 00112233-4455-6677-8899-aabbccddeeff --nrLDPC_coding_t2.eal_init_bbdev 1 +sudo ./nr-softmodem -O ~/gnb.conf --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev 0000:f7:00.1 --nrLDPC_coding_aal.dpdk_core_list 14-15 --nrLDPC_coding_aal.vfio_vf_token 00112233-4455-6677-8899-aabbccddeeff --nrLDPC_coding_aal.eal_init_bbdev 1 ``` # Known Issue(s) ## BBDEV CPU Usage -When running the E2E setup (this applies to both USRP and FHI72), BBDEV may not be using the list of CPU cores as specified by `nrLDPC_coding_t2.dpdk_core_list` accordingly. +When running the E2E setup (this applies to both USRP and FHI72), BBDEV may not be using the list of CPU cores as specified by `nrLDPC_coding_aal.dpdk_core_list` accordingly. This is an issue under investigation, and subject for future fixes. In the meantime, we recommend allocating idle, and isolated CPU cores in the configuration for BBDEV. diff --git a/openair1/PHY/CODING/DOC/LDPCImplementation.md b/openair1/PHY/CODING/DOC/LDPCImplementation.md index 956dad97bf..d537a8a299 100644 --- a/openair1/PHY/CODING/DOC/LDPCImplementation.md +++ b/openair1/PHY/CODING/DOC/LDPCImplementation.md @@ -42,7 +42,7 @@ Linking C shared module libldpc_aal.so At runtime, to successfully use LDPC accelerators (e.g., Xilinx T2/Intel ACCs), you will need to install the corresponding drivers and tools. Please refer to the dedicated documentation at [LDPC_OFFLOAD_SETUP.md](file://../../../../doc/LDPC_OFFLOAD_SETUP.md). -`./nr-softmodem -O libconfig:gnb.band78.sa.fr1.106PRB.usrpb210.conf:dbgl5 --rfsim --rfsimulator.serveraddr server --log_config.gtpu_log_level info --loader.ldpc.shlibversion _aal --nrLDPC_coding_t2.dpdk_dev 01:00.0 --nrLDPC_coding_t2.dpdk_core_list 0-1` +`./nr-softmodem -O libconfig:gnb.band78.sa.fr1.106PRB.usrpb210.conf:dbgl5 --rfsim --rfsimulator.serveraddr server --log_config.gtpu_log_level info --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev 01:00.0 --nrLDPC_coding_aal.dpdk_core_list 0-1` ``` diff --git a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_aal/nrLDPC_coding_aal.c b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_aal/nrLDPC_coding_aal.c index 661fc0ce63..71352ea887 100644 --- a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_aal/nrLDPC_coding_aal.c +++ b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_aal/nrLDPC_coding_aal.c @@ -1070,9 +1070,11 @@ int32_t nrLDPC_coding_init() {"vfio_vf_token", NULL, 0, .strptr = &vfio_vf_token, .defstrval = NULL, TYPE_STRING, 0, NULL}, {"num_harq_codeblock", NULL, 0, .uptr = &num_harq_codeblock, .defintval = 512, TYPE_UINT32, 0, NULL}, }; - config_get(config_get_if(), LoaderParams, sizeofArray(LoaderParams), "nrLDPC_coding_t2"); - AssertFatal(dpdk_dev != NULL, "nrLDPC_coding_t2.dpdk_dev was not provided"); - AssertFatal(dpdk_core_list != NULL, "nrLDPC_coding_t2.dpdk_core_list was not provided"); + config_get(config_get_if(), LoaderParams, sizeofArray(LoaderParams), "nrLDPC_coding_aal"); + if (dpdk_dev == NULL) + LOG_E(NR_PHY, "could not find mandatory --nrLDPC_coding_aal.dpdk_dev. If you used --nrLDPC_coding_t2.*, please rename all options to --nrLDPC_coding_aal.*\n"); + AssertFatal(dpdk_dev != NULL, "nrLDPC_coding_aal.dpdk_dev was not provided"); + AssertFatal(dpdk_core_list != NULL, "nrLDPC_coding_aal.dpdk_core_list was not provided"); char dpdk_dev_full[32]; if (normalize_dpdk_dev(dpdk_dev, dpdk_dev_full, sizeof(dpdk_dev_full)) != 0) { diff --git a/radio/fhi_72/oran-config.c b/radio/fhi_72/oran-config.c index ed8f37f857..58b8ea7490 100644 --- a/radio/fhi_72/oran-config.c +++ b/radio/fhi_72/oran-config.c @@ -494,10 +494,10 @@ static bool set_fh_io_cfg(struct xran_io_cfg *io_cfg, const paramdef_t *fhip, in {"dpdk_dev", NULL, 0, .strptr = &dpdk_dev, .defstrval = NULL, TYPE_STRING, 0, NULL}, {"vfio_vf_token", NULL, 0, .strptr = &vfio_vf_token, .defstrval = NULL, TYPE_STRING, 0, NULL} }; - config_get(config_get_if(), LoaderParams, sizeofArray(LoaderParams), "nrLDPC_coding_t2"); + config_get(config_get_if(), LoaderParams, sizeofArray(LoaderParams), "nrLDPC_coding_aal"); if (eal_init_bbdev != 0) { - AssertFatal(dpdk_dev!=NULL, "nrLDPC_coding_t2.dpdk_dev was not provided"); + AssertFatal(dpdk_dev!=NULL, "nrLDPC_coding_aal.dpdk_dev was not provided"); snprintf(&bbdev_dev[0], sizeof(bbdev_dev), "%s", dpdk_dev); io_cfg->bbdev_dev[0] = &bbdev_dev[0]; // BBDev dev name; max devices = 1 if(vfio_vf_token != NULL) { From f6aeb21d979d75425d83ae82b3a290043c630e79 Mon Sep 17 00:00:00 2001 From: Xin Zhe Khooi Date: Fri, 25 Jul 2025 20:29:42 +0800 Subject: [PATCH 365/964] ldpc_aal: handle T2 case in runtime --- .../xml_files/t2_offload_dec_nr_ulsim.xml | 18 ++-- .../xml_files/t2_offload_enc_nr_dlsim.xml | 24 ++--- doc/LDPC_OFFLOAD_SETUP.md | 5 +- .../nrLDPC_coding_aal/CMakeLists.txt | 1 - .../nrLDPC_coding_aal/nrLDPC_coding_aal.c | 88 +++++++++---------- radio/fhi_72/oran-config.c | 8 +- 6 files changed, 70 insertions(+), 74 deletions(-) diff --git a/ci-scripts/xml_files/t2_offload_dec_nr_ulsim.xml b/ci-scripts/xml_files/t2_offload_dec_nr_ulsim.xml index 5cfc1eeb72..f82c54e8de 100644 --- a/ci-scripts/xml_files/t2_offload_dec_nr_ulsim.xml +++ b/ci-scripts/xml_files/t2_offload_dec_nr_ulsim.xml @@ -62,7 +62,7 @@ true nr_ulsim 100 - -n1000 -s30 -S30.2 -m5 -r106 -R106 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -m5 -r106 -R106 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 @@ -80,7 +80,7 @@ true nr_ulsim 150 - -n1000 -s30 -S30.2 -m15 -r106 -R106 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -m15 -r106 -R106 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 @@ -98,7 +98,7 @@ true nr_ulsim 250 - -n1000 -s30 -S30.2 -m25 -r106 -R106 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -m25 -r106 -R106 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 @@ -116,7 +116,7 @@ true nr_ulsim 150 - -n1000 -s30 -S30.2 -m5 -r273 -R273 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -m5 -r273 -R273 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 @@ -134,7 +134,7 @@ true nr_ulsim 350 - -n1000 -s30 -S30.2 -m15 -r273 -R273 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -m15 -r273 -R273 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 @@ -152,7 +152,7 @@ true nr_ulsim 550 - -n1000 -s30 -S30.2 -m25 -r273 -R273 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -m25 -r273 -R273 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 @@ -170,7 +170,7 @@ true nr_ulsim 250 - -n1000 -s30 -S30.2 -m5 -r273 -R273 -C10 -W2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -m5 -r273 -R273 -C10 -W2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 @@ -188,7 +188,7 @@ true nr_ulsim 650 - -n1000 -s30 -S30.2 -m15 -r273 -R273 -C10 -W2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -m15 -r273 -R273 -C10 -W2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 @@ -206,7 +206,7 @@ true nr_ulsim 1100 - -n1000 -s30 -S30.2 -m25 -r273 -R273 -C10 -W2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -m25 -r273 -R273 -C10 -W2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 diff --git a/ci-scripts/xml_files/t2_offload_enc_nr_dlsim.xml b/ci-scripts/xml_files/t2_offload_enc_nr_dlsim.xml index 57b6afe21a..9b7a84c51f 100644 --- a/ci-scripts/xml_files/t2_offload_enc_nr_dlsim.xml +++ b/ci-scripts/xml_files/t2_offload_enc_nr_dlsim.xml @@ -63,7 +63,7 @@ true nr_dlsim 100 - -n1000 -s30 -S30.2 -e5 -b106 -R106 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -e5 -b106 -R106 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 @@ -81,7 +81,7 @@ true nr_dlsim 100 - -n1000 -s30 -S30.2 -e15 -b106 -R106 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -e15 -b106 -R106 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 @@ -99,7 +99,7 @@ true nr_dlsim 200 - -n1000 -s30 -S30.2 -e25 -b106 -R106 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -e25 -b106 -R106 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 @@ -117,7 +117,7 @@ true nr_dlsim 150 - -n1000 -s30 -S30.2 -e5 -b273 -R273 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -e5 -b273 -R273 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 @@ -135,7 +135,7 @@ true nr_dlsim 250 - -n1000 -s30 -S30.2 -e15 -b273 -R273 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -e15 -b273 -R273 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 @@ -153,7 +153,7 @@ true nr_dlsim 400 - -n1000 -s30 -S30.2 -e25 -b273 -R273 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -e25 -b273 -R273 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 @@ -171,7 +171,7 @@ true nr_dlsim 200 - -n1000 -s30 -S30.2 -e5 -b273 -R273 -X4,5,6,7,8,9 -x2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -e5 -b273 -R273 -X4,5,6,7,8,9 -x2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 @@ -189,7 +189,7 @@ true nr_dlsim 500 - -n1000 -s30 -S30.2 -e15 -b273 -R273 -X4,5,6,7,8,9 -x2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -e15 -b273 -R273 -X4,5,6,7,8,9 -x2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 @@ -207,7 +207,7 @@ true nr_dlsim 500 - -n1000 -s30 -S30.2 -e25 -b273 -R273 -X4,5,6,7,8,9 -x2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -e25 -b273 -R273 -X4,5,6,7,8,9 -x2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 @@ -225,7 +225,7 @@ true nr_dlsim 200 - -n1000 -s30 -S30.2 -e5 -b273 -R273 -X4,5,6,7,8,9 -x2 -z4 -y4 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -e5 -b273 -R273 -X4,5,6,7,8,9 -x2 -z4 -y4 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 @@ -243,7 +243,7 @@ true nr_dlsim 300 - -n1000 -s30 -S30.2 -e15 -b273 -R273 -X4,5,6,7,8,9 -x2 -z4 -y4 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -e15 -b273 -R273 -X4,5,6,7,8,9 -x2 -z4 -y4 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 @@ -261,6 +261,6 @@ true nr_dlsim 450 - -n1000 -s30 -S30.2 -e25 -b273 -R273 -X4,5,6,7,8,9 -x2 -z4 -y4 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 + -n1000 -s30 -S30.2 -e25 -b273 -R273 -X4,5,6,7,8,9 -x2 -z4 -y4 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 diff --git a/doc/LDPC_OFFLOAD_SETUP.md b/doc/LDPC_OFFLOAD_SETUP.md index 265a94ff71..cabac2cf39 100644 --- a/doc/LDPC_OFFLOAD_SETUP.md +++ b/doc/LDPC_OFFLOAD_SETUP.md @@ -236,7 +236,7 @@ Ensure that the CPU cores specified in `nrLDPC_coding_aal.dpdk_core_list` are av - `nrLDPC_coding_aal.num_harq_codeblock` - optional parameter, size of the HARQ buffer in terms of the number of 32kB blocks, by default set to *512* (maximum for the T2; as for the ACCs, this can be further increased). -- `nrLDPC_coding_aal.eal_init_bbdev` - optional parameter, set this to 1 when using with FHI72 with the Intel ACCs. For the T2, this is not required. +- `nrLDPC_coding_aal.is_t2` - optional parameter, set this to 1 when using the Xilinx T2 card. **Note:** These parameters can also be provided in a configuration file. Example for the ACC200: @@ -257,6 +257,7 @@ loader : { # Running OAI with O-RAN AAL In general, to offload of the channel coding to the LDPC accelerator, we use use the `--loader.ldpc.shlibversion _aal` option. +Reminder, if you are using the Xilinx T2 card, make sure to set `--nrLDPC_coding_aal.is_t2 1`. ## 5G PHY simulators @@ -288,7 +289,7 @@ Example command: cd ~/openairinterface5g source oaienv cd cmake_targets/ran_build/build -sudo ./nr-softmodem -O ~/gnb.conf --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev 0000:f7:00.1 --nrLDPC_coding_aal.dpdk_core_list 14-15 --nrLDPC_coding_aal.vfio_vf_token 00112233-4455-6677-8899-aabbccddeeff --nrLDPC_coding_aal.eal_init_bbdev 1 +sudo ./nr-softmodem -O ~/gnb.conf --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev 0000:f7:00.1 --nrLDPC_coding_aal.dpdk_core_list 14-15 --nrLDPC_coding_aal.vfio_vf_token 00112233-4455-6677-8899-aabbccddeeff ``` # Known Issue(s) diff --git a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_aal/CMakeLists.txt b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_aal/CMakeLists.txt index eeff46cd14..1bad804fba 100644 --- a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_aal/CMakeLists.txt +++ b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_aal/CMakeLists.txt @@ -9,7 +9,6 @@ if (ENABLE_LDPC_AAL) find_library(PMD_T2 NAMES rte_baseband_accl_ldpc HINTS ${LIBDPDK_AAL_LIBRARY_DIRS}) if (PMD_T2) - add_compile_definitions(LDPC_T2) message(STATUS "found poll-mode driver for AccelerComm T2 LDPC Offload (rte_baseband_accl_ldpc.so)") else() if (LIBDPDK_AAL_VERSION VERSION_LESS "22.11") diff --git a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_aal/nrLDPC_coding_aal.c b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_aal/nrLDPC_coding_aal.c index 71352ea887..62a20ef822 100644 --- a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_aal/nrLDPC_coding_aal.c +++ b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_aal/nrLDPC_coding_aal.c @@ -52,6 +52,7 @@ struct active_device { const char *driver_name; uint8_t dev_id; struct rte_bbdev_info info; + bool is_t2; uint32_t num_harq_codeblock; /* Persistent data structure to keep track of HARQ-related information */ // Note: This is used to store/keep track of the combined output information across iterations @@ -352,7 +353,7 @@ bool check_internal_harq_memory_capabilities(struct rte_bbdev_info *info) } // based on DPDK BBDEV add_bbdev_dev -static int add_dev(uint8_t dev_id, uint32_t num_harq_codeblock) +static int add_dev(uint8_t dev_id, bool is_t2, uint32_t num_harq_codeblock) { int ret; unsigned int nb_queues; @@ -380,6 +381,9 @@ static int add_dev(uint8_t dev_id, uint32_t num_harq_codeblock) active_dev.num_harq_codeblock = num_harq_codeblock; active_dev.harq_buffers = malloc(sizeof(struct rte_bbdev_op_data) * active_dev.num_harq_codeblock); + // is device T2? + active_dev.is_t2 = is_t2; + // device setup ret = rte_bbdev_setup_queues(dev_id, nb_queues, active_dev.info.socket_id); AssertFatal(ret == 0, "rte_bbdev_setup_queues(%u, %u, %d) ret %i\n", dev_id, nb_queues, active_dev.info.socket_id, ret); @@ -588,13 +592,9 @@ static void set_ldpc_dec_op(struct rte_bbdev_dec_op **ops, nrLDPC_slot_decoding_parameters_t *nrLDPC_slot_decoding_parameters) { int j = 0; -#ifdef LDPC_T2 // The T2 only supports CB mode, and does not TB mode special case handling. - bool special_case_tb_mode = false; -#else - bool special_case_tb_mode = - (nrLDPC_slot_decoding_parameters->nb_TBs == 1) && (nb_segments_decoding(nrLDPC_slot_decoding_parameters) == 1); -#endif + bool special_case_tb_mode = !active_dev.is_t2 && (nrLDPC_slot_decoding_parameters->nb_TBs == 1) + && (nb_segments_decoding(nrLDPC_slot_decoding_parameters) == 1); for (int h = 0; h < nrLDPC_slot_decoding_parameters->nb_TBs; ++h) { for (int i = 0; i < nrLDPC_slot_decoding_parameters->TBs[h].C; ++i) { ops[j]->ldpc_dec.basegraph = nrLDPC_slot_decoding_parameters->TBs[h].BG; @@ -608,6 +608,8 @@ static void set_ldpc_dec_op(struct rte_bbdev_dec_op **ops, ops[j]->ldpc_dec.op_flags = RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE | RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE; if (*nrLDPC_slot_decoding_parameters->TBs[h].segments[i].d_to_be_cleared) { *nrLDPC_slot_decoding_parameters->TBs[h].segments[i].d_to_be_cleared = false; + if (active_dev.is_t2) + *nrLDPC_slot_decoding_parameters->TBs[h].processedSegments = 0; } else { ops[j]->ldpc_dec.op_flags |= RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE; if (active_dev.support_internal_harq_memory) { @@ -615,15 +617,10 @@ static void set_ldpc_dec_op(struct rte_bbdev_dec_op **ops, ops[j]->ldpc_dec.op_flags |= RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_OUT_ENABLE; } } - -#ifdef LDPC_T2 - // Note: For the T2, we do not reset the processedSegments in case of HARQ. - // This is because if T2 is asked to decode a segment that as already successfully - // decoded in the previous round, the T2 reports a failure. - if (*nrLDPC_slot_decoding_parameters->TBs[h].segments[i].d_to_be_cleared) *nrLDPC_slot_decoding_parameters->TBs[h].processedSegments = 0; -#else - *nrLDPC_slot_decoding_parameters->TBs[h].processedSegments = 0; -#endif + + if (!active_dev.is_t2) + *nrLDPC_slot_decoding_parameters->TBs[h].processedSegments = 0; + if (!special_case_tb_mode) { ops[j]->ldpc_dec.code_block_mode = 1; ops[j]->ldpc_dec.cb_params.e = nrLDPC_slot_decoding_parameters->TBs[h].segments[i].E; @@ -680,13 +677,9 @@ static void set_ldpc_enc_op(struct rte_bbdev_enc_op **ops, nrLDPC_slot_encoding_parameters_t *nrLDPC_slot_encoding_parameters) { int j = 0; -#ifdef LDPC_T2 // The T2 only supports CB mode, and does not TB mode special case handling. - bool special_case_tb_mode = false; -#else - bool special_case_tb_mode = - (nrLDPC_slot_encoding_parameters->nb_TBs == 1) && (nb_segments_encoding(nrLDPC_slot_encoding_parameters) == 1); -#endif + bool special_case_tb_mode = !active_dev.is_t2 && (nrLDPC_slot_encoding_parameters->nb_TBs == 1) + && (nb_segments_encoding(nrLDPC_slot_encoding_parameters) == 1); for (int h = 0; h < nrLDPC_slot_encoding_parameters->nb_TBs; ++h) { for (int i = 0; i < nrLDPC_slot_encoding_parameters->TBs[h].C; ++i) { ops[j]->ldpc_enc.basegraph = nrLDPC_slot_encoding_parameters->TBs[h].BG; @@ -1063,16 +1056,20 @@ int32_t nrLDPC_coding_init() char *dpdk_file_prefix = NULL; char *vfio_vf_token = NULL; // vfio token for the bbdev card uint32_t num_harq_codeblock = 0; // size of the HARQ buffer in terms of the number of 32K blocks + uint32_t is_t2 = 0; paramdef_t LoaderParams[] = { {"dpdk_dev", NULL, 0, .strptr = &dpdk_dev, .defstrval = NULL, TYPE_STRING, 0, NULL}, {"dpdk_core_list", NULL, 0, .strptr = &dpdk_core_list, .defstrval = NULL, TYPE_STRING, 0, NULL}, {"dpdk_file_prefix", NULL, 0, .strptr = &dpdk_file_prefix, .defstrval = "b6", TYPE_STRING, 0, NULL}, {"vfio_vf_token", NULL, 0, .strptr = &vfio_vf_token, .defstrval = NULL, TYPE_STRING, 0, NULL}, {"num_harq_codeblock", NULL, 0, .uptr = &num_harq_codeblock, .defintval = 512, TYPE_UINT32, 0, NULL}, + {"is_t2", NULL, 0, .uptr = &is_t2, .defintval = 0, TYPE_UINT8, 0, NULL}, }; config_get(config_get_if(), LoaderParams, sizeofArray(LoaderParams), "nrLDPC_coding_aal"); if (dpdk_dev == NULL) - LOG_E(NR_PHY, "could not find mandatory --nrLDPC_coding_aal.dpdk_dev. If you used --nrLDPC_coding_t2.*, please rename all options to --nrLDPC_coding_aal.*\n"); + LOG_E(NR_PHY, + "could not find mandatory --nrLDPC_coding_aal.dpdk_dev. If you used --nrLDPC_coding_t2.*, please rename all options to " + "--nrLDPC_coding_aal.*\n"); AssertFatal(dpdk_dev != NULL, "nrLDPC_coding_aal.dpdk_dev was not provided"); AssertFatal(dpdk_core_list != NULL, "nrLDPC_coding_aal.dpdk_core_list was not provided"); @@ -1114,7 +1111,7 @@ int32_t nrLDPC_coding_init() } AssertFatal(dev_id != -1, "bbdev %s not found.", dpdk_dev_full); - AssertFatal(add_dev(dev_id, num_harq_codeblock) == 0, "Failed to setup bbdev"); + AssertFatal(add_dev(dev_id, is_t2, num_harq_codeblock) == 0, "Failed to setup bbdev"); AssertFatal(rte_bbdev_stats_reset(dev_id) == 0, "Failed to reset stats of bbdev %u", dev_id); AssertFatal(rte_bbdev_start(dev_id) == 0, "Failed to start bbdev %u", dev_id); @@ -1156,7 +1153,8 @@ int32_t nrLDPC_coding_shutdown() return 0; } -static void llr_scaling(int16_t *llr, int llr_len, uint8_t *llr_scaled, int8_t llr_size, int8_t llr_decimal, int8_t nb_layers, int8_t Qm) +static void +llr_scaling(int16_t *llr, int llr_len, uint8_t *llr_scaled, int8_t llr_size, int8_t llr_decimal, int8_t nb_layers, int8_t Qm) { const int16_t llr_max = (1 << (llr_size - 1)) - 1; const int16_t llr_min = -llr_max; @@ -1258,33 +1256,31 @@ int32_t nrLDPC_coding_decoder(nrLDPC_slot_decoding_parameters_t *nrLDPC_slot_dec struct rte_bbdev_op_data **queue_ops[DATA_NUM_TYPES] = {&data_buffers.inputs, &data_buffers.hard_outputs, &data_buffers.harq_outputs}; -#ifndef LDPC_T2 int8_t llr_size = (active_dev.info.drv.capabilities)[RTE_BBDEV_OP_LDPC_DEC].cap.ldpc_dec.llr_size; int8_t llr_decimal = (active_dev.info.drv.capabilities)[RTE_BBDEV_OP_LDPC_DEC].cap.ldpc_dec.llr_decimals; -#endif int offset = 0; for (int h = 0; h < nrLDPC_slot_decoding_parameters->nb_TBs; ++h) { for (int r = 0; r < nrLDPC_slot_decoding_parameters->TBs[h].C; r++) { -#ifdef LDPC_T2 - // For the T2, we simply saturate the LLRs. - uint16_t z_ol[LDPC_MAX_CB_SIZE] __attribute__((aligned(16))); - memcpy(z_ol, - nrLDPC_slot_decoding_parameters->TBs[h].segments[r].llr, - nrLDPC_slot_decoding_parameters->TBs[h].segments[r].E * sizeof(uint16_t)); - simde__m128i *pv_ol128 = (simde__m128i *)z_ol; - simde__m128i *pl_ol128 = (simde__m128i *)&l_ol[offset]; - for (int i = 0, j = 0; j < ((nrLDPC_slot_decoding_parameters->TBs[h].segments[r].E + 15) >> 4); i += 2, j++) { - pl_ol128[j] = simde_mm_packs_epi16(pv_ol128[i], pv_ol128[i + 1]); + if (active_dev.is_t2) { + // For the T2, we simply saturate the LLRs. + uint16_t z_ol[LDPC_MAX_CB_SIZE] __attribute__((aligned(16))); + memcpy(z_ol, + nrLDPC_slot_decoding_parameters->TBs[h].segments[r].llr, + nrLDPC_slot_decoding_parameters->TBs[h].segments[r].E * sizeof(uint16_t)); + simde__m128i *pv_ol128 = (simde__m128i *)z_ol; + simde__m128i *pl_ol128 = (simde__m128i *)&l_ol[offset]; + for (int i = 0, j = 0; j < ((nrLDPC_slot_decoding_parameters->TBs[h].segments[r].E + 15) >> 4); i += 2, j++) { + pl_ol128[j] = simde_mm_packs_epi16(pv_ol128[i], pv_ol128[i + 1]); + } + } else { + llr_scaling(nrLDPC_slot_decoding_parameters->TBs[h].segments[r].llr, + nrLDPC_slot_decoding_parameters->TBs[h].segments[r].E, + &l_ol[offset], + llr_size, + llr_decimal, + nrLDPC_slot_decoding_parameters->TBs[h].nb_layers, + nrLDPC_slot_decoding_parameters->TBs[h].Qm); } -#else - llr_scaling(nrLDPC_slot_decoding_parameters->TBs[h].segments[r].llr, - nrLDPC_slot_decoding_parameters->TBs[h].segments[r].E, - &l_ol[offset], - llr_size, - llr_decimal, - nrLDPC_slot_decoding_parameters->TBs[h].nb_layers, - nrLDPC_slot_decoding_parameters->TBs[h].Qm); -#endif offset += LDPC_MAX_CB_SIZE; } } diff --git a/radio/fhi_72/oran-config.c b/radio/fhi_72/oran-config.c index 58b8ea7490..4eff24aacf 100644 --- a/radio/fhi_72/oran-config.c +++ b/radio/fhi_72/oran-config.c @@ -485,18 +485,18 @@ static bool set_fh_io_cfg(struct xran_io_cfg *io_cfg, const paramdef_t *fhip, in char *shlibversion = NULL; // version of the LDPC coding library paramdef_t LoaderParams_shlibversion[] = {{"shlibversion", NULL, 0, .strptr = &shlibversion, .defstrval = NULL, TYPE_STRING, 0, NULL}}; config_get(config_get_if(), LoaderParams_shlibversion, sizeofArray(LoaderParams_shlibversion), "loader.ldpc"); - if (shlibversion != NULL && strncmp(shlibversion, "_t2", 3) == 0) { - uint32_t eal_init_bbdev = 0; // If not 0 then include the BBDEV device in the EAL init for FHI + if (shlibversion != NULL && strncmp(shlibversion, "_aal", 4) == 0) { + uint32_t is_t2 = 0; // If not 0 then include the BBDEV device in the EAL init for FHI char *dpdk_dev = NULL; // PCI address of the card char *vfio_vf_token = NULL; // vfio token for the bbdev card paramdef_t LoaderParams[] = { - {"eal_init_bbdev", NULL, 0, .uptr = &eal_init_bbdev, .defuintval = 0, TYPE_UINT, 0, NULL}, + {"is_t2", NULL, 0, .uptr = &is_t2, .defuintval = 0, TYPE_UINT, 0, NULL}, {"dpdk_dev", NULL, 0, .strptr = &dpdk_dev, .defstrval = NULL, TYPE_STRING, 0, NULL}, {"vfio_vf_token", NULL, 0, .strptr = &vfio_vf_token, .defstrval = NULL, TYPE_STRING, 0, NULL} }; config_get(config_get_if(), LoaderParams, sizeofArray(LoaderParams), "nrLDPC_coding_aal"); - if (eal_init_bbdev != 0) { + if (!is_t2) { AssertFatal(dpdk_dev!=NULL, "nrLDPC_coding_aal.dpdk_dev was not provided"); snprintf(&bbdev_dev[0], sizeof(bbdev_dev), "%s", dpdk_dev); io_cfg->bbdev_dev[0] = &bbdev_dev[0]; // BBDev dev name; max devices = 1 From eaffaf4058f6d1fdfed9551ed447c76349203fd9 Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Wed, 6 Aug 2025 11:33:59 +0200 Subject: [PATCH 366/964] time manager tests: increase some sleep The CI fails sometimes, because some processes/threads are created in unpredictable order and if the client connects before the server is ready some tests fail, as seen in the following log: [UTIL] client/server iq-samples: launch sub-processes [UTIL] threadCreate() for time client: creating thread (no affinity, default priority) [UTIL] time manager configuration: [time source: server] [mode: client] [server IP: 127.0.0.1} [server port: 7374] [UTIL] time client: connection to 127.0.0.1:7374 failed, try again in 1s [UTIL] threadCreate() for time source iq samples: creating thread (no affinity, default priority) [UTIL] threadCreate() for time server: creating thread (no affinity, default priority) [UTIL] time manager configuration: [time source: iq_samples] [mode: server] [server IP: 127.0.0.1} [server port: 7374] [UTIL] client/server: rlc ticks: 1000 pdcp ticks: 1000 x2ap ticks: 1000 CMDLINE: "/oai-ran/build/common/utils/time_manager/tests/test_time_manager_auto" "--time_management.mode" "server" "--time_management.time_source" "iq_samples" [UTIL] client/server: rlc ticks: 0 pdcp ticks: 0 x2ap ticks: 0 CMDLINE: "/oai-ran/build/common/utils/time_manager/tests/test_time_manager_auto" "--time_management.mode" "client" [UTIL] client-server iq-samples: ERROR The client/server iq-samples test is started. Then we see this log: [UTIL] time manager configuration: [time source: server] [mode: client] [server IP: 127.0.0.1} [server port: 7374] Which means that the client is running. It tries to connect to the server (not running yet), but fails, so sleeps for 1 second before attempting another connection to the server: [UTIL] time client: connection to 127.0.0.1:7374 failed, try again in 1s The sleep is done by the time_client thread, the main thread of the test program continues and does a sleep(1). Then the server arrives: [UTIL] time manager configuration: [time source: iq_samples] [mode: server] [server IP: 127.0.0.1} [server port: 7374] It sends all the ticks (to no client, since the client is still sleeping). Then the test is over, the sleep(1) of the client finishes and the program exits. The client never connected to the server. We have this log: [UTIL] client/server: rlc ticks: 0 pdcp ticks: 0 x2ap ticks: 0 And the test fails. It's complicated to write an automatic test involving several uncoordinated programs. The operating system may create processes in any order. We use some sleeping to wait, but it may be too short or too long, leading to test failure. Let's see with more sleep if the CI fails less. --- common/utils/time_manager/tests/test_auto.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/utils/time_manager/tests/test_auto.c b/common/utils/time_manager/tests/test_auto.c index 817a518c4a..0db7881bb4 100644 --- a/common/utils/time_manager/tests/test_auto.c +++ b/common/utils/time_manager/tests/test_auto.c @@ -143,7 +143,7 @@ static int client_server(char *program_name, bool iq_samples_time_source) /* wait a little bit so that server is ready to accept clients * (this is hackish) */ - usleep(100); + usleep(1000); /* start client */ client = fork(); @@ -188,7 +188,7 @@ static int run_sub_client_server(bool iq_samples_time_source) * wait a bit for client to be there otherwise server * may finish too early */ - usleep(100); + usleep(100*1000); /* let's pretend we have 2000 samples per second */ for (int i = 0; i < 1000; i++) { From a1c354bd6eb203aaa81b342e830a3aaaaa0fc381 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 31 Jul 2025 18:30:23 +0200 Subject: [PATCH 367/964] CI: Remove old tracing information It will be replaced with a new mechanism in a later commit. --- ci-scripts/ci_infra.yaml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ci-scripts/ci_infra.yaml b/ci-scripts/ci_infra.yaml index 804852c937..fd2d414a03 100644 --- a/ci-scripts/ci_infra.yaml +++ b/ci-scripts/ci_infra.yaml @@ -7,8 +7,6 @@ idefix: NetworkScript: ip a show dev wwan0 IF: wwan0 MTU: 1500 - Trace: True - LogStore: /media/usb-drive/ci_qlogs up2: Host: up2 @@ -46,7 +44,6 @@ adb_ue_1: NetworkScript: adb -s R3CM40LZPHT shell "ip address show | grep rmnet_data0" CmdPrefix: adb -s R3CM40LZPHT shell MTU: 1500 - LogStore: /media/usb-drive/ci_adb_1-logs adb_ue_2: Host: nano InitScript: /home/oaicicd/ci_ctl_adb.sh initialize 5200c00db4413517 @@ -59,7 +56,6 @@ adb_ue_2: NetworkScript: adb -s 5200c00db4413517 shell "ip address show | grep rmnet" CmdPrefix: adb -s 5200c00db4413517 shell MTU: 1500 - LogStore: /media/usb-drive/ci_adb_2-logs oc-cn5g: Host: avra From cc1b2315af6f354afb4bde5d057a5ab282a241ec Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 31 Jul 2025 16:32:23 +0200 Subject: [PATCH 368/964] CI: add simple unit test for UE handling --- .../tests/config/test_module_infra.yaml | 19 +++++++++ ci-scripts/tests/module.py | 41 +++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 ci-scripts/tests/config/test_module_infra.yaml create mode 100644 ci-scripts/tests/module.py diff --git a/ci-scripts/tests/config/test_module_infra.yaml b/ci-scripts/tests/config/test_module_infra.yaml new file mode 100644 index 0000000000..fadc721232 --- /dev/null +++ b/ci-scripts/tests/config/test_module_infra.yaml @@ -0,0 +1,19 @@ +test: + Host: localhost + InitScript: "" + TermScript: "" + AttachScript: "true" + DetachScript: "true" + NetworkScript: ip a show dev lo + IF: lo + MTU: 65536 + +test-fail: + Host: localhost + InitScript: "" + TermScript: "" + AttachScript: "false" + DetachScript: "true" + NetworkScript: ip a show dev TESTDEVICEDOESNOTEXIST + IF: TESTDEVICEDOESNOTEXIST + MTU: 123 diff --git a/ci-scripts/tests/module.py b/ci-scripts/tests/module.py new file mode 100644 index 0000000000..b6898405d4 --- /dev/null +++ b/ci-scripts/tests/module.py @@ -0,0 +1,41 @@ +import sys +import logging +logging.basicConfig( + level=logging.DEBUG, + stream=sys.stdout, + format="[%(asctime)s] %(levelname)8s: %(message)s" +) +import os + +import unittest + +sys.path.append('./') # to find OAI imports below +import cls_module +import cls_cmd + +class TestModule(unittest.TestCase): + def test_simple_module(self): + c = cls_module.Module_UE("test", filename="tests/config/test_module_infra.yaml") + success = c.initialize() + self.assertTrue(success) + ip = c.attach() + self.assertEqual(ip, "127.0.0.1") + self.assertTrue(c.checkMTU()) + c.detach() + logs = c.terminate() + self.assertEqual(logs, None) # no tracing + + @unittest.skip("this test takes long: it verifies the UE cannot attach") + def test_simple_fail(self): + c = cls_module.Module_UE("test-fail", filename="tests/config/test_module_infra.yaml") + success = c.initialize() + self.assertTrue(success) + ip = c.attach() + self.assertEqual(ip, None) + self.assertFalse(c.checkMTU()) + c.detach() + logs = c.terminate() + self.assertEqual(logs, None) # no tracing + +if __name__ == '__main__': + unittest.main() From de2d32be092774aec283b9be4465b2c27feca769 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 31 Jul 2025 18:29:19 +0200 Subject: [PATCH 369/964] CI UE Attach: add more frequent checks, improve output check for IP once before sleeping in case UE IP address exists, which should speed up the CI. With this, Only print the actual attach command once. Print errors only at the beginning. This should simplify attach command output logs. --- ci-scripts/cls_module.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/ci-scripts/cls_module.py b/ci-scripts/cls_module.py index 3fed4f3dd6..d387783bf7 100644 --- a/ci-scripts/cls_module.py +++ b/ci-scripts/cls_module.py @@ -70,11 +70,11 @@ class Module_UE: def __repr__(self): return self.__str__() - def _command(self, cmd, silent = False): + def _command(self, cmd, silent=False, reportNonZero=True): if cmd is None: raise Exception("no command provided") with cls_cmd.getConnection(self.host) as c: - response = c.run(cmd, silent=silent) + response = c.run(cmd, silent=silent, reportNonZero=reportNonZero) return response #-----------------$ @@ -109,10 +109,11 @@ class Module_UE: self._command(self.cmd_dict["attach"]) timeout = attach_timeout logging.debug("Waiting for IP address to be assigned") + ip = self.getIP(silent=False, reportNonZero=True) while timeout > 0 and not ip: - time.sleep(5) - timeout -= 5 - ip = self.getIP() + time.sleep(1) + timeout -= 1 + ip = self.getIP(silent=True, reportNonZero=False) if ip: break logging.warning(f"UE did not receive IP address after {attach_timeout} s, detaching") @@ -156,8 +157,8 @@ class Module_UE: logging.error(message) return False - def getIP(self): - output = self._command(self.cmd_dict["getNetwork"], silent=True) + def getIP(self, silent=True, reportNonZero=True): + output = self._command(self.cmd_dict["getNetwork"], silent=silent, reportNonZero=reportNonZero) result = re.search(r'inet (?P[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)', output.stdout) if result and result.group('ip'): ip = result.group('ip') From a3d46ed0e6c07343f8085d829a9cb9dc9b00043a Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 6 Aug 2025 01:03:06 +0200 Subject: [PATCH 370/964] 5g rfsim NTN LEO/GEO: remove leading undeploy step It is not necessary (the final undeploys at the end are "always_exec"), and makes the CI potentially fail since there is nothing to copy at this point. --- ci-scripts/xml_files/container_5g_rfsim_ntn_geo.xml | 1 - ci-scripts/xml_files/container_5g_rfsim_ntn_leo.xml | 1 - 2 files changed, 2 deletions(-) diff --git a/ci-scripts/xml_files/container_5g_rfsim_ntn_geo.xml b/ci-scripts/xml_files/container_5g_rfsim_ntn_geo.xml index 2cefc32722..88173b3659 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_ntn_geo.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_ntn_geo.xml @@ -26,7 +26,6 @@ wrench 111111 - 100001 800813 000001 000002 diff --git a/ci-scripts/xml_files/container_5g_rfsim_ntn_leo.xml b/ci-scripts/xml_files/container_5g_rfsim_ntn_leo.xml index 61bf4d5e48..0d2634192d 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_ntn_leo.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_ntn_leo.xml @@ -26,7 +26,6 @@ wrench 111111 - 100001 800813 000001 000002 From ce9f2c9a45ff339c96254e81ac59cc192ed4c735 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 31 Jul 2025 18:28:16 +0200 Subject: [PATCH 371/964] Add possibility to trace UEs --- ci-scripts/cls_module.py | 58 ++++++++++++++----- .../tests/config/test_module_infra.yaml | 15 +++++ ci-scripts/tests/module.py | 17 ++++++ 3 files changed, 77 insertions(+), 13 deletions(-) diff --git a/ci-scripts/cls_module.py b/ci-scripts/cls_module.py index d387783bf7..5493511bd8 100644 --- a/ci-scripts/cls_module.py +++ b/ci-scripts/cls_module.py @@ -59,11 +59,20 @@ class Module_UE: } self.interface = m.get('IF') self.MTU = m.get('MTU') - self.trace = m.get('trace') == True - self.logStore = m.get('LogStore') self.cmd_prefix = m.get('CmdPrefix') logging.info(f'initialized UE {self} from {filename}') + t = m.get('Tracing') + self.trace = t is not None + if self.trace: + if t.get('Start') is None or t.get('Stop') is None or t.get('Collect')is None : + raise ValueError("need to have Start/Stop/Collect for tracing") + self.cmd_dict["traceStart"] = t.get('Start') + self.cmd_dict["traceStop"] = t.get('Stop') + self._logCollect = t.get('Collect') + if "%%log_dir%%" not in self._logCollect: + raise ValueError(f"(At least one) LogCollect expression for {module_name} must contain \"%%log_dir%%\"") + def __str__(self): return f"{self.module_name}@{self.host}" @@ -82,25 +91,23 @@ class Module_UE: #-----------------$ def initialize(self): - if self.trace: - raise Exception("UE tracing not implemented yet") - self._enableTrace() # we first terminate to make sure the UE has been stopped if self.cmd_dict["detach"]: self._command(self.cmd_dict["detach"], silent=True) self._command(self.cmd_dict["terminate"], silent=True) ret = self._command(self.cmd_dict["initialize"]) logging.info(f'For command: {ret.args} | return output: {ret.stdout} | Code: {ret.returncode}') + if self.trace: + self._enableTrace() # Here each UE returns differently for the successful initialization, requires check based on UE return ret.returncode == 0 - def terminate(self): + def terminate(self, log_dir=None): self._command(self.cmd_dict["terminate"]) - if self.trace: - raise Exception("UE tracing not implemented yet") + if self.trace and log_dir is not None: self._disableTrace() - return self._logCollect() + return self._collectTrace(log_dir) return None def attach(self, attach_tries = 4, attach_timeout = 60): @@ -188,10 +195,35 @@ class Module_UE: return self.cmd_prefix if self.cmd_prefix else "" def _enableTrace(self): - raise Exception("not implemented") + logging.info(f'UE {self}: start UE tracing') + self._command(self.cmd_dict["traceStart"]) def _disableTrace(self): - raise Exception("not implemented") + logging.info(f'UE {self}: stop UE tracing') + self._command(self.cmd_dict["traceStop"]) - def _logCollect(self): - raise Exception("not implemented") + def _collectTrace(self, log_dir): + logging.info(f'collecting logs into (local) {log_dir}') + remote_dir = "/tmp/ue-trace-logs" + with cls_cmd.getConnection(self.host) as c: + # create a directory for log collection + c.run(f'rm -rf {remote_dir}') + ret = c.run(f'mkdir {remote_dir}') + if ret.returncode != 0: + logging.error("cannot create directory for log collection") + return [] + log_cmd = self._logCollect.replace('%%log_dir%%', remote_dir) + self._command(log_cmd) + # enumerate collected files + ret = c.run(f'ls {remote_dir}/*') + if ret.returncode != 0: + logging.error("cannot enumerate log files") + return [] + log_files = [] + # copy them to the executor one by one, and store in log_dir + for f in ret.stdout.split("\n"): + l = f.replace(remote_dir, log_dir) + c.copyin(f, l) + log_files.append(l) + c.run(f'rm -rf {remote_dir}') + return log_files diff --git a/ci-scripts/tests/config/test_module_infra.yaml b/ci-scripts/tests/config/test_module_infra.yaml index fadc721232..7bfdfc1d9d 100644 --- a/ci-scripts/tests/config/test_module_infra.yaml +++ b/ci-scripts/tests/config/test_module_infra.yaml @@ -17,3 +17,18 @@ test-fail: NetworkScript: ip a show dev TESTDEVICEDOESNOTEXIST IF: TESTDEVICEDOESNOTEXIST MTU: 123 + +test-trace: + Host: localhost + InitScript: "" + TermScript: "" + AttachScript: "true" + DetachScript: "true" + Tracing: + # tttf: temp-trace-test-file + Start: "rm -f /tmp/tttf; for i in {1..8}; do echo $i >> /tmp/tttf; sleep 1; done &" + Stop: "while [[ $(wc -l /tmp/tttf) < 4 ]]; do sleep 1; done" + Collect: "cp /tmp/tttf %%log_dir%%" + NetworkScript: ip a show dev lo + IF: lo + MTU: 65536 diff --git a/ci-scripts/tests/module.py b/ci-scripts/tests/module.py index b6898405d4..366593873c 100644 --- a/ci-scripts/tests/module.py +++ b/ci-scripts/tests/module.py @@ -1,5 +1,6 @@ import sys import logging +import tempfile logging.basicConfig( level=logging.DEBUG, stream=sys.stdout, @@ -16,6 +17,7 @@ import cls_cmd class TestModule(unittest.TestCase): def test_simple_module(self): c = cls_module.Module_UE("test", filename="tests/config/test_module_infra.yaml") + self.assertFalse(c.trace) success = c.initialize() self.assertTrue(success) ip = c.attach() @@ -37,5 +39,20 @@ class TestModule(unittest.TestCase): logs = c.terminate() self.assertEqual(logs, None) # no tracing + def test_simple_trace(self): + c = cls_module.Module_UE("test-trace", filename="tests/config/test_module_infra.yaml") + self.assertTrue(c.trace) + success = c.initialize() + self.assertTrue(success) + ip = c.attach() + self.assertEqual(ip, "127.0.0.1") + self.assertTrue(c.checkMTU()) + c.detach() + tmp = tempfile.mkdtemp() + log_file = c.terminate(log_dir=tmp) + with cls_cmd.LocalCmd() as c: + c.run(f'rm -rf {tmp}') + self.assertEqual(log_file, [f"{tmp}/tttf"]) # matches test-trace UE collection file + if __name__ == '__main__': unittest.main() From fe2cda1309155fb2bdb8c12cdb8e4ab859b1cd3b Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 31 Jul 2025 19:44:50 +0200 Subject: [PATCH 372/964] CI: log UE files in artifacts --- ci-scripts/cls_oaicitest.py | 4 ++-- ci-scripts/main.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ci-scripts/cls_oaicitest.py b/ci-scripts/cls_oaicitest.py index 53bdacaacc..0a550016d4 100644 --- a/ci-scripts/cls_oaicitest.py +++ b/ci-scripts/cls_oaicitest.py @@ -835,10 +835,10 @@ class OaiCiTest(): global_status = CONST.OAI_UE_PROCESS_COULD_NOT_SYNC return global_status - def TerminateUE(self, HTML): + def TerminateUE(self, HTML, logPath): ues = [cls_module.Module_UE(n.strip()) for n in self.ue_ids] with concurrent.futures.ThreadPoolExecutor(max_workers=64) as executor: - futures = [executor.submit(ue.terminate) for ue in ues] + futures = [executor.submit(ue.terminate, logPath) for ue in ues] archives = [f.result() for f in futures] archive_info = [f'Log at: {a}' if a else 'No log available' for a in archives] messages = [f"UE {ue.getName()}: {log}" for (ue, log) in zip(ues, archive_info)] diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 18956ae28f..fd794de22c 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -226,7 +226,7 @@ def ExecuteActionWithParam(action): elif action == 'Detach_UE': success = CiTestObj.DetachUE(HTML) elif action == 'Terminate_UE': - success = CiTestObj.TerminateUE(HTML) + success = CiTestObj.TerminateUE(HTML, logPath) elif action == 'CheckStatusUE': success = CiTestObj.CheckStatusUE(HTML) elif action == 'DataEnable_UE': From af580f3a2f012682a3b24ed0614e61cb32694271 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 31 Jul 2025 18:33:42 +0200 Subject: [PATCH 373/964] Add example tracing for Amarisoft UE sim Commented, as the resulting files are very big. --- ci-scripts/ci_infra.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ci-scripts/ci_infra.yaml b/ci-scripts/ci_infra.yaml index fd2d414a03..2f91576a60 100644 --- a/ci-scripts/ci_infra.yaml +++ b/ci-scripts/ci_infra.yaml @@ -146,6 +146,10 @@ amarisoft_ue: InitScript: /root/lteue-linux-2025-03-15/lteue /root/oaicicd/ran_sa_aw2s_asue_20MHz/aw2s-multi-00102-20.cfg & TermScript: /root/lteue-linux-2025-03-15/ws.js -t 10 127.0.0.1:9002 '{"message":"quit"}' || killall -KILL lteue-avx2 NetworkScript: ip netns exec ue1 ip a show dev pdn0 + #Tracing: + # Start: '' # nothing to be done + # Stop: '' # nothing to be done + # Collect: 'cp /tmp/ue.log %%log_dir%%' amarisoft_ue_2x2: Host: amariue InitScript: /root/lteue-linux-2025-03-15/lteue /root/oaicicd/ran_sa_aw2s_asue_20MHz_2x2/aw2s-multi-00102-2x2-v2.cfg & From 5492de0e0b92819bb0f2c58175235bf85e0630aa Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 1 Aug 2025 07:51:55 +0200 Subject: [PATCH 374/964] Example tracing for QLog Note: this does not actually work. In the pipelines, we see that for some reason, quectel-CM cannot establish a connection. Manually, it works though(?) --- ci-scripts/ci_infra.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ci-scripts/ci_infra.yaml b/ci-scripts/ci_infra.yaml index 2f91576a60..e5888ef6fe 100644 --- a/ci-scripts/ci_infra.yaml +++ b/ci-scripts/ci_infra.yaml @@ -5,6 +5,10 @@ idefix: AttachScript: sudo python3 ci_ctl_qtel.py /dev/ttyUSB2 wup DetachScript: sudo python3 ci_ctl_qtel.py /dev/ttyUSB2 detach NetworkScript: ip a show dev wwan0 + #Tracing: + # Start: 'sudo rm -f ci_qlog/*; nohup sudo -b QLog/QLog -s ci_qlog -f NR5G.cfg &' + # Stop: 'sudo killall QLog' + # Collect: 'sudo mv ci_qlog/* %%log_dir%%/' IF: wwan0 MTU: 1500 From 5c16fc6189b3669c8b409d3c4a99ec42d8bd671c Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 4 Aug 2025 09:25:11 +0200 Subject: [PATCH 375/964] Fix Python "invalid escape sequence" warnings cls_containerize.py:139: SyntaxWarning: invalid escape sequence '\.' lineHasCommit = re.search(f'COMMIT [a-zA-Z0-9\.:/\-]*{image}', str(line)) is not None cls_containerize.py:441: SyntaxWarning: invalid escape sequence '\-' result = re.search('Size *= *(?P[0-9\-]+) *bytes', cmd.getBefore()) cls_containerize.py:493: SyntaxWarning: invalid escape sequence '\-' result = re.search('Size *= *(?P[0-9\-]+) *bytes', cmd.getBefore()) cls_containerize.py:616: SyntaxWarning: invalid escape sequence '\-' result = re.search('Size *= *(?P[0-9\-]+) *bytes', ret.stdout) --- ci-scripts/cls_containerize.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index b878e82caa..3d63de0834 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -136,7 +136,7 @@ def AnalyzeBuildLogs(buildRoot, images, globalStatus): lineHasTag2 = re.search(f'naming to docker.io/library/{image}:', str(line)) is not None tagged = tagged or lineHasTag or lineHasTag2 # the OpenShift Cluster builder prepends image registry URL - lineHasCommit = re.search(f'COMMIT [a-zA-Z0-9\.:/\-]*{image}', str(line)) is not None + lineHasCommit = re.search(r'COMMIT [a-zA-Z0-9\.:/\-]*' + image, str(line)) is not None committed = committed or lineHasCommit errorandwarnings['errors'] = 0 if committed or tagged else 1 errorandwarnings['warnings'] = 0 @@ -441,7 +441,7 @@ class Containerize(): HTML.CreateHtmlTabFooter(False) return False else: - result = re.search('Size *= *(?P[0-9\-]+) *bytes', cmd.getBefore()) + result = re.search(r'Size *= *(?P[0-9\-]+) *bytes', cmd.getBefore()) if result is not None: size = float(result.group("size")) / 1000000 imageSizeStr = f'{size:.1f}' @@ -493,7 +493,7 @@ class Containerize(): allImagesSize[name] = 'N/A -- Build Failed' break else: - result = re.search('Size *= *(?P[0-9\-]+) *bytes', cmd.getBefore()) + result = re.search(r'Size *= *(?P[0-9\-]+) *bytes', cmd.getBefore()) if result is not None: size = float(result.group("size")) / 1000000 # convert to MB imageSizeStr = f'{size:.1f}' @@ -616,7 +616,7 @@ class Containerize(): collectInfo = {} collectInfo['proxy'] = files ret = ssh.run(f'docker image inspect --format=\'Size = {{{{.Size}}}} bytes\' proxy:{tag}') - result = re.search('Size *= *(?P[0-9\-]+) *bytes', ret.stdout) + result = re.search(r'Size *= *(?P[0-9\-]+) *bytes', ret.stdout) # Cleaning any created tmp volume ssh.run('docker volume prune --force') ssh.close() From f766b21b5776ab94755292c4101e83cb5d29c83c Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 5 Aug 2025 08:16:48 +0200 Subject: [PATCH 376/964] Add CI helper class This class provides a generic "context" for individual tasks about the current task step, and where to log results. It's used by archiveArtifact() that would automatically log files in the right directory, based on a directory in the context, and in a way that order of files is preserved for long-running pipelines. --- ci-scripts/cls_ci_helper.py | 44 +++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 ci-scripts/cls_ci_helper.py diff --git a/ci-scripts/cls_ci_helper.py b/ci-scripts/cls_ci_helper.py new file mode 100644 index 0000000000..eb47a32892 --- /dev/null +++ b/ci-scripts/cls_ci_helper.py @@ -0,0 +1,44 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (the "License"); you may not use this file +# * except in compliance with the License. +# * You may obtain a copy of the License at +# * +# * http://www.openairinterface.org/?page_id=698 +# * +# * Unless required by applicable law or agreed to in writing, software +# * distributed under the License is distributed on an "AS IS" BASIS, +# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# * See the License for the specific language governing permissions and +# * limitations under the License. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ + +import os +from typing import NamedTuple +import logging + +class TestCaseCtx(NamedTuple): + count: int + test_id: int + logPath: str + + def Default(logPath): + return TestCaseCtx(123, 112233, logPath) + def baseFilename(self): + # typically, the test ID is of form 001234 (6 digits) + return f"{self.logPath}/{self.count}-{self.test_id:06d}" + +def archiveArtifact(cmd, ctx, remote_path): + base = os.path.basename(remote_path) + local = f"{ctx.baseFilename()}-{base}" + logging.info(f"Archive artifact '{local}'") + success = cmd.copyin(remote_path, local) + if success: + cmd.run(f'rm {remote_path}', silent=True) + return local if success else None From 28ce0dc444fa206b21cbfe3655639ab7d2954d25 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 5 Aug 2025 09:42:06 +0200 Subject: [PATCH 377/964] Main: pass in ctx Set the context for each task step. Set the artifact result path based on the XML, so it is harmonized; currently, most pipelines use the "YAML path" of docker-compose, but that does not always make sense. For instance, Ping/Iperf() needs to look up this path, but does not inherently belong to one specific YAML path (there might even be more). --- ci-scripts/main.py | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/ci-scripts/main.py b/ci-scripts/main.py index fd794de22c..3cc550eba5 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -43,8 +43,10 @@ import cls_containerize #class Containerize for all container-based operations import cls_static_code_analysis #class for static code analysis import cls_cluster # class for building/deploying on cluster import cls_native # class for all native/source-based operations +from cls_ci_helper import TestCaseCtx import ran +import cls_cmd import cls_oai_html @@ -91,7 +93,7 @@ def AssignParams(params_dict): setattr(RAN, key, value) setattr(HTML, key, value) -def ExecuteActionWithParam(action): +def ExecuteActionWithParam(action, ctx): global RAN global HTML global CONTAINERS @@ -565,6 +567,16 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re else: xml_test_file = cwd + "/" + CiTestObj.testXMLfiles[0] + # directory where all log artifacts will be placed + logPath = f"{cwd}/../cmake_targets/log/{CiTestObj.testXMLfiles[0].split('/')[-1]}.d" + # we run from within ci-scripts, but the logPath is absolute, so replace + # the ci-scripts/..; if it does not exist, nothing will happen + logPath = logPath.replace(r'/ci-scripts/..', '') + logging.info(f"placing all artifacts for this run in {logPath}/") + with cls_cmd.LocalCmd() as c: + c.run(f"rm -rf {logPath}") + c.run(f"mkdir -p {logPath}") + xmlTree = ET.parse(xml_test_file) xmlRoot = xmlTree.getroot() @@ -615,12 +627,15 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re task_set_succeeded = True HTML.startTime=int(round(time.time() * 1000)) + i = 0 for test_case_id in todo_tests: for test in all_tests: id = test.get('id') if test_case_id != id: continue + i += 1 CiTestObj.testCase_id = id + ctx = TestCaseCtx(i, int(id), logPath) HTML.testCase_id=CiTestObj.testCase_id CiTestObj.desc = test.findtext('desc') always_exec = test.findtext('always_exec') in ['True', 'true', 'Yes', 'yes'] @@ -637,7 +652,7 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re HTML.CreateHtmlTestRowQueue(msg, "SKIP", []) break try: - test_succeeded = ExecuteActionWithParam(action) + test_succeeded = ExecuteActionWithParam(action, ctx) 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: From dcbb3369e19d8cf6f20e6ac8e67ea1a01a923b84 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 5 Aug 2025 09:58:06 +0200 Subject: [PATCH 378/964] Simplify ShowTestID() make it a non-class function, stateless, more information on the current CI step (the number). --- ci-scripts/cls_oaicitest.py | 7 ------- ci-scripts/main.py | 15 ++++++++------- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/ci-scripts/cls_oaicitest.py b/ci-scripts/cls_oaicitest.py index 0a550016d4..b2972b667d 100644 --- a/ci-scripts/cls_oaicitest.py +++ b/ci-scripts/cls_oaicitest.py @@ -258,7 +258,6 @@ class OaiCiTest(): self.testCase_id = '' self.testXMLfiles = [] - self.desc = '' self.ping_args = '' self.ping_packetloss_threshold = '' self.ping_rttavg_threshold ='' @@ -891,9 +890,3 @@ class OaiCiTest(): d = f'{SourceCodePath}/cmake_targets' cmd.run(f'rm -f {d}/build.log.zip') cmd.run(f'cd {d} && zip -r build.log.zip build_log_*/*') - - def ShowTestID(self): - logging.info(f'\u001B[1m----------------------------------------\u001B[0m') - logging.info(f'\u001B[1m Test ID: {self.testCase_id} \u001B[0m') - logging.info(f'\u001B[1m {self.desc} \u001B[0m') - logging.info(f'\u001B[1m----------------------------------------\u001B[0m') diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 3cc550eba5..275686abec 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -409,10 +409,11 @@ def test_in_list(test, list): def receive_signal(signum, frame): sys.exit(1) - - - - +def ShowTestID(ctx, desc): + logging.info(f'\u001B[1m----------------------------------------\u001B[0m') + logging.info(f'\u001B[1m Test ID: {ctx.test_id} (#{ctx.count}) \u001B[0m') + logging.info(f'\u001B[1m {desc} \u001B[0m') + logging.info(f'\u001B[1m----------------------------------------\u001B[0m') #----------------------------------------------------------- # MAIN PART @@ -637,15 +638,15 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re CiTestObj.testCase_id = id ctx = TestCaseCtx(i, int(id), logPath) HTML.testCase_id=CiTestObj.testCase_id - CiTestObj.desc = test.findtext('desc') + 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 + HTML.desc = desc action = test.findtext('class') if (CheckClassValidity(xml_class_list, action, id) == False): task_set_succeeded = False continue - CiTestObj.ShowTestID() + ShowTestID(ctx, desc) if not task_set_succeeded and not always_exec: msg = f"skipping test due to prior error" logging.warning(msg) From 2b4e0e5244601a7b895b4cc4d1a735813750141f Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 5 Aug 2025 09:41:40 +0200 Subject: [PATCH 379/964] Use archiveArtifact() for CN undeploy --- ci-scripts/cls_corenetwork.py | 17 ++++++++--------- ci-scripts/cls_oaicitest.py | 14 ++++---------- ci-scripts/main.py | 2 +- ci-scripts/tests/corenetwork.py | 18 +++++++++++++----- 4 files changed, 26 insertions(+), 25 deletions(-) diff --git a/ci-scripts/cls_corenetwork.py b/ci-scripts/cls_corenetwork.py index 579bad585b..ad83eae622 100644 --- a/ci-scripts/cls_corenetwork.py +++ b/ci-scripts/cls_corenetwork.py @@ -29,6 +29,7 @@ import yaml import re import cls_cmd +from cls_ci_helper import archiveArtifact def listify(s): if s is None: @@ -114,8 +115,7 @@ class CoreNetwork: logging.info(f'deployed core network {self}, pingable IP address {ip}') return True, output - def _collect_logs(self, log_dir): - logging.info(f'collecting logs into (local) {log_dir}') + def _collect_logs(self, ctx): remote_dir = "/tmp/cn-undeploy-logs" with cls_cmd.getConnection(self._host) as c: # create a directory for log collection @@ -134,18 +134,17 @@ class CoreNetwork: logging.error("cannot enumerate log files") return [] log_files = [] - # copy them to the executor one by one, and store in log_dir + # copy them to the executor one by one for f in ret.stdout.split("\n"): - l = f.replace(remote_dir, log_dir) - c.copyin(f, l) - log_files.append(l) + name = archiveArtifact(c, ctx, f) + log_files.append(name) c.run(f'rm -rf {remote_dir}') return log_files - def undeploy(self, log_dir=None): + def undeploy(self, ctx=None): log_files = [] - if log_dir is not None: - log_files = self._collect_logs(log_dir) + if ctx is not None: + log_files = self._collect_logs(ctx) else: logging.warning("no directory for log collection specified, cannot retrieve core network logs") logging.info(f'undeploy core network {self}') diff --git a/ci-scripts/cls_oaicitest.py b/ci-scripts/cls_oaicitest.py index b2972b667d..290ad38598 100644 --- a/ci-scripts/cls_oaicitest.py +++ b/ci-scripts/cls_oaicitest.py @@ -844,7 +844,7 @@ class OaiCiTest(): HTML.CreateHtmlTestRowQueue(f'N/A', 'OK', messages) return True - def DeployCoreNetwork(cn_id, HTML): + def DeployCoreNetwork(cn_id, ctx, HTML): core_name = cn_id.strip() cn = cls_corenetwork.CoreNetwork(core_name) success, output = cn.deploy() @@ -858,18 +858,12 @@ class OaiCiTest(): HTML.CreateHtmlTestRowQueue(core_name, 'KO', [msg]) return success - def UndeployCoreNetwork(cn_id, HTML): - # Ping, Iperf, DeployObject put logs into a path based on YAML. We - # can't do this here (because there is no yaml), so hardcode a path for - # "cn_logs" for the moment - logPath = f'{os.getcwd()}/../cmake_targets/log/cn_logs' - with cls_cmd.getConnection('localhost') as local: - local.run(f'mkdir -p {logPath}', silent=True) + def UndeployCoreNetwork(cn_id, ctx, HTML): core_name = cn_id.strip() cn = cls_corenetwork.CoreNetwork(core_name) - logs, output = cn.undeploy(log_dir=logPath) + logs, output = cn.undeploy(ctx=ctx) logging.info(f"undeployed core network {core_name}, logs {logs}, output:\n{output}") - message = "Log files: " + ", ".join([os.path.basename(l) for l in logs]) + message = "Log files:\n" + "\n".join([os.path.basename(l) for l in logs]) HTML.CreateHtmlTestRowQueue(core_name, 'OK', [message]) return True diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 275686abec..a6da7b399d 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -302,7 +302,7 @@ def ExecuteActionWithParam(action, ctx): elif action == 'DeployCoreNetwork' or action == 'UndeployCoreNetwork': cn_id = test.findtext('cn_id') core_op = getattr(cls_oaicitest.OaiCiTest, action) - success = core_op(cn_id, HTML) + success = core_op(cn_id, ctx, HTML) elif action == 'Deploy_Object' or action == 'Undeploy_Object' or action == "Create_Workspace": eNB_instance=test.findtext('eNB_instance') diff --git a/ci-scripts/tests/corenetwork.py b/ci-scripts/tests/corenetwork.py index 77e5c7629e..7bc1603305 100644 --- a/ci-scripts/tests/corenetwork.py +++ b/ci-scripts/tests/corenetwork.py @@ -6,14 +6,22 @@ logging.basicConfig( format="[%(asctime)s] %(levelname)8s: %(message)s" ) import os +import tempfile import unittest sys.path.append('./') # to find OAI imports below import cls_corenetwork +from cls_ci_helper import TestCaseCtx import cls_cmd class TestCoreNetwork(unittest.TestCase): + def setUp(self): + self.ctx = TestCaseCtx.Default(tempfile.mkdtemp()) + def tearDown(self): + with cls_cmd.LocalCmd() as c: + c.run(f'rm -rf {self.ctx.logPath}') + def test_simple_core(self): c = cls_corenetwork.CoreNetwork("test", filename="tests/config/test_core_infra.yaml") success, output = c.deploy() @@ -22,14 +30,14 @@ class TestCoreNetwork(unittest.TestCase): # should not have it set in config self.assertTrue(c.runIperf3Server()) self.assertEqual(c.getIP(), "127.0.0.1") - log_files, output = c.undeploy(log_dir="/tmp") + log_files, output = c.undeploy(self.ctx) self.assertEqual(output, "undeploy") with cls_cmd.LocalCmd() as cmd: # there must be one log file for this (test) core self.assertEqual(len(log_files), 1) - # test core writes to %%log_dir%%/logs, which expands to /tmp/logs + # undeploy uses archiveArtifact(), which writes to {prefix}-logs l = log_files[0] - self.assertEqual(l, "/tmp/logs") + self.assertEqual(l, f"{self.ctx.baseFilename()}-logs") ret = cmd.run(f"cat {l}") self.assertEqual(ret.returncode, 0) # command must succeed self.assertEqual(ret.stdout, "logs") # output should be "logs" @@ -39,14 +47,14 @@ class TestCoreNetwork(unittest.TestCase): success, _ = c.deploy() self.assertTrue(success) self.assertFalse(c.runIperf3Server()) - c.undeploy(log_dir="/tmp") + c.undeploy(None) def test_core_fail(self): c = cls_corenetwork.CoreNetwork("test_fail", filename="tests/config/test_core_infra.yaml") success, _ = c.deploy() self.assertFalse(success) # undeployment should still work - c.undeploy(log_dir="/tmp") + c.undeploy(None) def test_core_script(self): c = cls_corenetwork.CoreNetwork("test_script", filename="tests/config/test_core_infra.yaml") From fa5c91e03f4c73455cfb7217f4e000ae7f313e39 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 5 Aug 2025 09:40:28 +0200 Subject: [PATCH 380/964] Use archiveArtifact() for (Un-)DeployObject() --- ci-scripts/cls_containerize.py | 45 ++++++++++++++-------------------- ci-scripts/main.py | 4 +-- ci-scripts/tests/deployment.py | 32 ++++++++++++++---------- 3 files changed, 40 insertions(+), 41 deletions(-) diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index 3d63de0834..591d6d413d 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -46,6 +46,7 @@ import cls_cmd import helpreadme as HELP import constants as CONST import cls_oaicitest +from cls_ci_helper import archiveArtifact #----------------------------------------------------------- # Helper functions used here and in other classes @@ -202,12 +203,10 @@ def GetServices(ssh, requested, file): else: return requested -def CopyinServiceLog(ssh, lSourcePath, yaml, svcName, wd_yaml, filename): - remote_filename = f"{lSourcePath}/cmake_targets/log/{filename}" +def CopyinServiceLog(ssh, lSourcePath, svcName, wd_yaml, ctx): + remote_filename = f"{lSourcePath}/cmake_targets/log/{svcName}.logs" ssh.run(f'docker compose -f {wd_yaml} logs {svcName} --no-log-prefix &> {remote_filename}') - local_dir = f"{os.getcwd()}/../cmake_targets/log/{yaml}" - local_filename = f"{local_dir}/{filename}" - return ssh.copyin(remote_filename, local_filename) + return archiveArtifact(ssh, ctx, remote_filename) def GetRunningServices(ssh, file): ret = ssh.run(f'docker compose -f {file} config --services') @@ -229,14 +228,13 @@ def GetRunningServices(ssh, file): logging.info(f'stopping services: {running_services}') return running_services -def CheckLogs(self, yaml, service_name, HTML, RAN): - logPath = f'{os.getcwd()}/../cmake_targets/log/{yaml}' - filename = f'{logPath}/{service_name}-{HTML.testCase_id}.log' +def CheckLogs(self, filename, HTML, RAN): success = True - if (any(sub in service_name for sub in ['oai_ue','oai-nr-ue','lte_ue'])): + name = os.path.basename(filename) + if (any(sub in name for sub in ['oai_ue','oai-nr-ue','lte_ue'])): logging.debug(f'\u001B[1m Analyzing UE logfile {filename} \u001B[0m') logStatus = cls_oaicitest.OaiCiTest().AnalyzeLogFile_UE(filename, HTML, RAN) - opt = f"UE log analysis for service {service_name}" + opt = f"UE log analysis ({name})" # usage of htmlUEFailureMsg/htmleNBFailureMsg is because Analyze log files # abuse HTML to store their reports, and we here want to put custom options, # which is not possible with CreateHtmlTestRow @@ -247,13 +245,13 @@ def CheckLogs(self, yaml, service_name, HTML, RAN): else: HTML.CreateHtmlTestRowQueue(opt, 'OK', [HTML.htmlUEFailureMsg]) HTML.htmlUEFailureMsg = "" - elif service_name == 'nv-cubb': + elif 'nv-cubb' in name: msg = 'Undeploy PNF/Nvidia CUBB' HTML.CreateHtmlTestRow(msg, 'OK', CONST.ALL_PROCESSES_OK) - elif (any(sub in service_name for sub in ['enb','rru','rcc','cu','du','gnb'])): + elif (any(sub in name for sub in ['enb','rru','rcc','cu','du','gnb'])): logging.debug(f'\u001B[1m Analyzing XnB logfile {filename}\u001B[0m') logStatus = RAN.AnalyzeLogFile_eNB(filename, HTML, self.ran_checkers) - opt = f"xNB log analysis for service {service_name}" + opt = f"xNB log analysis ({name})" if (logStatus < 0): HTML.CreateHtmlTestRowQueue(opt, 'KO', [HTML.htmleNBFailureMsg]) success = False @@ -261,9 +259,9 @@ def CheckLogs(self, yaml, service_name, HTML, RAN): HTML.CreateHtmlTestRowQueue(opt, 'OK', [HTML.htmleNBFailureMsg]) HTML.htmleNBFailureMsg = "" else: - logging.info(f'Skipping to analyze log for service name {service_name}') - HTML.CreateHtmlTestRowQueue(f"service {service_name}", 'OK', ["no analysis function"]) - logging.debug(f"log check: service {service_name} passed analysis {success}") + logging.info(f"Skipping analysis of log '{filename}': no submatch for xNB/UE") + HTML.CreateHtmlTestRowQueue(f"file {name}", 'OK', ["no analysis function"]) + logging.debug(f"log check: file {filename} passed analysis {success}") return success #----------------------------------------------------------- @@ -823,18 +821,14 @@ class Containerize(): HTML.CreateHtmlTestRowQueue('N/A', 'KO', ["cannot create workspace"]) return success - def DeployObject(self, HTML): + def DeployObject(self, ctx, HTML): svr = self.eNB_serverId[self.eNB_instance] num_attempts = self.num_attempts lIpAddr, lSourcePath = self.GetCredentials(svr) logging.debug(f'Deploying OAI Object on server: {lIpAddr}') yaml = self.yamlPath[self.eNB_instance].strip('/') - # creating the log folder by default - local_dir = f"{os.getcwd()}/../cmake_targets/log/{yaml.split('/')[-1]}" - os.system(f'mkdir -p {local_dir}') wd = f'{lSourcePath}/{yaml}' wd_yaml = f'{wd}/docker-compose.y*ml' - yaml_dir = yaml.split('/')[-1] with cls_cmd.getConnection(lIpAddr) as ssh: services = GetServices(ssh, self.services[self.eNB_instance], wd_yaml) if services == [] or services == ' ' or services == None: @@ -861,7 +855,7 @@ class Containerize(): logging.warning(warning_msg) HTML.CreateHtmlTestRowQueue('N/A', 'NOK', [warning_msg]) for svc in services.split(): - CopyinServiceLog(ssh, lSourcePath, yaml_dir, svc, wd_yaml, f'{svc}-{HTML.testCase_id}-attempt{attempt}.log') + CopyinServiceLog(ssh, lSourcePath, svc, wd_yaml, ctx) ssh.run(f'docker compose -f {wd_yaml} down -- {services}') imagesInfo = info.stdout.splitlines()[1:] logging.debug(f'{info.stdout.splitlines()[1:]}') @@ -871,13 +865,12 @@ class Containerize(): HTML.CreateHtmlTestRowQueue('N/A', 'KO', ['\n'.join(imagesInfo)]) return deployed - def UndeployObject(self, HTML, RAN): + def UndeployObject(self, ctx, HTML, RAN): svr = self.eNB_serverId[self.eNB_instance] lIpAddr, lSourcePath = self.GetCredentials(svr) logging.debug(f'\u001B[1m Undeploying OAI Object from server: {lIpAddr}\u001B[0m') yaml = self.yamlPath[self.eNB_instance].strip('/') wd = f'{lSourcePath}/{yaml}' - yaml_dir = yaml.split('/')[-1] with cls_cmd.getConnection(lIpAddr) as ssh: ExistEnvFilePrint(ssh, wd) services = GetRunningServices(ssh, f"{wd}/docker-compose.y*ml") @@ -885,7 +878,7 @@ class Containerize(): if services is not None: all_serv = " ".join([s for s, _ in services]) ssh.run(f'docker compose -f {wd}/docker-compose.y*ml stop -- {all_serv}') - copyin_res = all(CopyinServiceLog(ssh, lSourcePath, yaml_dir, s, f"{wd}/docker-compose.y*ml", f'{s}-{HTML.testCase_id}.log') for s, c in services) + copyin_res = [CopyinServiceLog(ssh, lSourcePath, s, f"{wd}/docker-compose.y*ml", ctx) for s, _ in services] else: logging.warning('could not identify services to stop => no log file') ssh.run(f'docker compose -f {wd}/docker-compose.y*ml down -v') @@ -894,7 +887,7 @@ class Containerize(): HTML.CreateHtmlTestRowQueue('N/A', 'KO', ['Could not copy logfile(s)']) return False else: - log_results = [CheckLogs(self, yaml_dir, s, HTML, RAN) for s, _ in services] + log_results = [CheckLogs(self, f, HTML, RAN) for f in copyin_res] success = all(log_results) if success: logging.info('\u001B[1m Undeploying OAI Object Pass\u001B[0m') diff --git a/ci-scripts/main.py b/ci-scripts/main.py index a6da7b399d..7f5efefc34 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -330,9 +330,9 @@ def ExecuteActionWithParam(action, ctx): CONTAINERS.num_attempts = int(test.findtext('num_attempts') or 1) CONTAINERS.deploymentTag = cls_containerize.CreateTag(CONTAINERS.ranCommitID, CONTAINERS.ranBranch, CONTAINERS.ranAllowMerge) if action == 'Deploy_Object': - success = CONTAINERS.DeployObject(HTML) + success = CONTAINERS.DeployObject(ctx, HTML) elif action == 'Undeploy_Object': - success = CONTAINERS.UndeployObject(HTML, RAN) + success = CONTAINERS.UndeployObject(ctx, HTML, RAN) elif action == 'Create_Workspace': if force_local: # Do not create a working directory when running locally. Current repo directory will be used diff --git a/ci-scripts/tests/deployment.py b/ci-scripts/tests/deployment.py index a7337f6e52..d2fb0cda57 100644 --- a/ci-scripts/tests/deployment.py +++ b/ci-scripts/tests/deployment.py @@ -6,6 +6,7 @@ logging.basicConfig( format="[%(asctime)s] %(levelname)8s: %(message)s" ) import os +import tempfile os.system(f'rm -rf cmake_targets') os.system(f'mkdir -p cmake_targets/log') import unittest @@ -14,6 +15,7 @@ sys.path.append('./') # to find OAI imports below import cls_oai_html import cls_oaicitest import cls_containerize +from cls_ci_helper import TestCaseCtx import ran import cls_cmd @@ -48,12 +50,16 @@ class TestDeploymentMethods(unittest.TestCase): self.cont.eNBPassword = None self.cont.eNBSourceCodePath = os.getcwd() self.cont.num_attempts = 3 + self.ctx = TestCaseCtx.Default(tempfile.mkdtemp()) + def tearDown(self): + with cls_cmd.LocalCmd() as c: + c.run(f'rm -rf {self.ctx.logPath}') def test_deploy(self): self.cont.yamlPath[0] = 'tests/simple-dep/' self.cont.deploymentTag = "noble" - deploy = self.cont.DeployObject(self.html) - undeploy = self.cont.UndeployObject(self.html, self.ran) + deploy = self.cont.DeployObject(self.ctx, self.html) + undeploy = self.cont.UndeployObject(self.ctx, self.html, self.ran) self.assertTrue(deploy) self.assertTrue(undeploy) @@ -61,8 +67,8 @@ class TestDeploymentMethods(unittest.TestCase): # fails reliably old = self.cont.yamlPath self.cont.yamlPath[0] = 'tests/simple-fail/' - deploy = self.cont.DeployObject(self.html) - self.cont.UndeployObject(self.html, self.ran) + deploy = self.cont.DeployObject(self.ctx, self.html) + self.cont.UndeployObject(self.ctx, self.html, self.ran) self.assertFalse(deploy) self.cont.yamlPath = old @@ -70,8 +76,8 @@ class TestDeploymentMethods(unittest.TestCase): # fails reliably old = self.cont.yamlPath self.cont.yamlPath[0] = 'tests/simple-fail-2svc/' - deploy = self.cont.DeployObject(self.html) - self.cont.UndeployObject(self.html, self.ran) + deploy = self.cont.DeployObject(self.ctx, self.html) + self.cont.UndeployObject(self.ctx, self.html, self.ran) self.assertFalse(deploy) self.cont.yamlPath = old @@ -79,8 +85,8 @@ class TestDeploymentMethods(unittest.TestCase): self.cont.yamlPath[0] = 'yaml_files/5g_rfsimulator_tdd_dora' self.cont.services[0] = "oai-gnb" self.cont.deploymentTag = 'develop-12345678' - deploy = self.cont.DeployObject(self.html) - undeploy = self.cont.UndeployObject(self.html, self.ran) + deploy = self.cont.DeployObject(self.ctx, self.html) + undeploy = self.cont.UndeployObject(self.ctx, self.html, self.ran) self.assertTrue(deploy) self.assertTrue(undeploy) @@ -88,8 +94,8 @@ class TestDeploymentMethods(unittest.TestCase): self.cont.yamlPath[0] = 'yaml_files/5g_rfsimulator_tdd_dora' self.cont.services[0] = "oai-gnb oai-nr-ue" self.cont.deploymentTag = 'develop-12345678' - deploy = self.cont.DeployObject(self.html) - undeploy = self.cont.UndeployObject(self.html, self.ran) + deploy = self.cont.DeployObject(self.ctx, self.html) + undeploy = self.cont.UndeployObject(self.ctx, self.html, self.ran) self.assertTrue(deploy) self.assertTrue(undeploy) @@ -97,10 +103,10 @@ class TestDeploymentMethods(unittest.TestCase): self.cont.yamlPath[0] = 'yaml_files/5g_rfsimulator_tdd_dora' self.cont.services[0] = "oai-gnb" self.cont.deploymentTag = 'develop-12345678' - deploy1 = self.cont.DeployObject(self.html) + deploy1 = self.cont.DeployObject(self.ctx, self.html) self.cont.services[0] = "oai-nr-ue" - deploy2 = self.cont.DeployObject(self.html) - undeploy = self.cont.UndeployObject(self.html, self.ran) + deploy2 = self.cont.DeployObject(self.ctx, self.html) + undeploy = self.cont.UndeployObject(self.ctx, self.html, self.ran) self.assertTrue(deploy1) self.assertTrue(deploy2) self.assertTrue(undeploy) From 62ae72925b9b14a9effe6a88a84482548b31b07a Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 5 Aug 2025 09:27:18 +0200 Subject: [PATCH 381/964] Use archiveArtifact() for module_UE --- ci-scripts/cls_module.py | 15 +++++++-------- ci-scripts/cls_oaicitest.py | 4 ++-- ci-scripts/main.py | 2 +- ci-scripts/tests/module.py | 14 ++++++++++---- 4 files changed, 20 insertions(+), 15 deletions(-) diff --git a/ci-scripts/cls_module.py b/ci-scripts/cls_module.py index 5493511bd8..cfdd96477f 100644 --- a/ci-scripts/cls_module.py +++ b/ci-scripts/cls_module.py @@ -32,6 +32,7 @@ import re import yaml import cls_cmd +from cls_ci_helper import archiveArtifact class Module_UE: @@ -103,11 +104,11 @@ class Module_UE: return ret.returncode == 0 - def terminate(self, log_dir=None): + def terminate(self, ctx=None): self._command(self.cmd_dict["terminate"]) - if self.trace and log_dir is not None: + if self.trace and ctx is not None: self._disableTrace() - return self._collectTrace(log_dir) + return self._collectTrace(ctx) return None def attach(self, attach_tries = 4, attach_timeout = 60): @@ -202,8 +203,7 @@ class Module_UE: logging.info(f'UE {self}: stop UE tracing') self._command(self.cmd_dict["traceStop"]) - def _collectTrace(self, log_dir): - logging.info(f'collecting logs into (local) {log_dir}') + def _collectTrace(self, ctx): remote_dir = "/tmp/ue-trace-logs" with cls_cmd.getConnection(self.host) as c: # create a directory for log collection @@ -222,8 +222,7 @@ class Module_UE: log_files = [] # copy them to the executor one by one, and store in log_dir for f in ret.stdout.split("\n"): - l = f.replace(remote_dir, log_dir) - c.copyin(f, l) - log_files.append(l) + name = archiveArtifact(c, ctx, f) + log_files.append(name) c.run(f'rm -rf {remote_dir}') return log_files diff --git a/ci-scripts/cls_oaicitest.py b/ci-scripts/cls_oaicitest.py index 290ad38598..52cea6a3c4 100644 --- a/ci-scripts/cls_oaicitest.py +++ b/ci-scripts/cls_oaicitest.py @@ -834,10 +834,10 @@ class OaiCiTest(): global_status = CONST.OAI_UE_PROCESS_COULD_NOT_SYNC return global_status - def TerminateUE(self, HTML, logPath): + def TerminateUE(self, ctx, HTML): ues = [cls_module.Module_UE(n.strip()) for n in self.ue_ids] with concurrent.futures.ThreadPoolExecutor(max_workers=64) as executor: - futures = [executor.submit(ue.terminate, logPath) for ue in ues] + futures = [executor.submit(ue.terminate, ctx) for ue in ues] archives = [f.result() for f in futures] archive_info = [f'Log at: {a}' if a else 'No log available' for a in archives] messages = [f"UE {ue.getName()}: {log}" for (ue, log) in zip(ues, archive_info)] diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 7f5efefc34..509cd19109 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -228,7 +228,7 @@ def ExecuteActionWithParam(action, ctx): elif action == 'Detach_UE': success = CiTestObj.DetachUE(HTML) elif action == 'Terminate_UE': - success = CiTestObj.TerminateUE(HTML, logPath) + success = CiTestObj.TerminateUE(ctx, HTML) elif action == 'CheckStatusUE': success = CiTestObj.CheckStatusUE(HTML) elif action == 'DataEnable_UE': diff --git a/ci-scripts/tests/module.py b/ci-scripts/tests/module.py index 366593873c..47760cfa27 100644 --- a/ci-scripts/tests/module.py +++ b/ci-scripts/tests/module.py @@ -12,9 +12,16 @@ import unittest sys.path.append('./') # to find OAI imports below import cls_module +from cls_ci_helper import TestCaseCtx import cls_cmd class TestModule(unittest.TestCase): + def setUp(self): + self.ctx = TestCaseCtx.Default(tempfile.mkdtemp()) + def tearDown(self): + with cls_cmd.LocalCmd() as c: + c.run(f'rm -rf {self.ctx.logPath}') + def test_simple_module(self): c = cls_module.Module_UE("test", filename="tests/config/test_module_infra.yaml") self.assertFalse(c.trace) @@ -49,10 +56,9 @@ class TestModule(unittest.TestCase): self.assertTrue(c.checkMTU()) c.detach() tmp = tempfile.mkdtemp() - log_file = c.terminate(log_dir=tmp) - with cls_cmd.LocalCmd() as c: - c.run(f'rm -rf {tmp}') - self.assertEqual(log_file, [f"{tmp}/tttf"]) # matches test-trace UE collection file + log_file = c.terminate(self.ctx) + # undeploy uses archiveArtifact(), which writes to {prefix}-logs + self.assertEqual(log_file, [f"{self.ctx.baseFilename()}-tttf"]) # matches test-trace UE collection file if __name__ == '__main__': unittest.main() From da9cec0bfffcbf899f35ca8e992a498a23b37019 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 5 Aug 2025 09:41:31 +0200 Subject: [PATCH 382/964] Use archiveArtifact() for Ping+IPerf --- ci-scripts/cls_oaicitest.py | 61 +++++++++++----------------------- ci-scripts/main.py | 6 ++-- ci-scripts/tests/ping-iperf.py | 15 ++++++--- 3 files changed, 33 insertions(+), 49 deletions(-) diff --git a/ci-scripts/cls_oaicitest.py b/ci-scripts/cls_oaicitest.py index 52cea6a3c4..ba322ca608 100644 --- a/ci-scripts/cls_oaicitest.py +++ b/ci-scripts/cls_oaicitest.py @@ -47,6 +47,7 @@ import constants as CONST import cls_module import cls_corenetwork import cls_cmd +from cls_ci_helper import archiveArtifact #----------------------------------------------------------- # Helper functions used here and in other classes @@ -256,7 +257,6 @@ class OaiCiTest(): self.ranAllowMerge = False self.ranTargetBranch = '' - self.testCase_id = '' self.testXMLfiles = [] self.ping_args = '' self.ping_packetloss_threshold = '' @@ -351,7 +351,7 @@ class OaiCiTest(): HTML.CreateHtmlTestRowQueue('NA', 'OK', messages) return True - def Ping_common(self, cn, ue, logPath): + def Ping_common(self, ctx, cn, ue): ping_status = 0 ueIP = ue.getIP() if not ueIP: @@ -359,13 +359,12 @@ class OaiCiTest(): svrIP = cn.getIP() if not svrIP: return (False, f"CN {cn.getName()} has no IP address") - ping_log_file = f'ping_{self.testCase_id}_{ue.getName()}.log' + ping_log_file = f'/tmp/ping_{ue.getName()}.log' ping_time = re.findall(r"-c *(\d+)",str(self.ping_args)) - local_ping_log_file = f'{logPath}/{ping_log_file}' if re.search('%cn_ip%', self.ping_args) or re.search(r'[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+', self.ping_args): raise Exception(f"ping_args should not have IP address: {self.ping_args}") interface = f'-I {ue.getIFName()}' if ue.getIFName() else '' - ping_cmd = f'{ue.getCmdPrefix()} ping {interface} {self.ping_args} {svrIP} 2>&1 | tee /tmp/{ping_log_file}' + ping_cmd = f'{ue.getCmdPrefix()} ping {interface} {self.ping_args} {svrIP} 2>&1 | tee {ping_log_file}' cmd = cls_cmd.getConnection(ue.getHost()) response = cmd.run(ping_cmd, timeout=int(ping_time[0])*1.5) ue_header = f'UE {ue.getName()} ({ueIP})' @@ -373,8 +372,7 @@ class OaiCiTest(): message = ue_header + ': ping crashed: TIMEOUT?' return (False, message) - #copy the ping log file to have it locally for analysis (ping stats) - cmd.copyin(src=f'/tmp/{ping_log_file}', tgt=local_ping_log_file) + local_ping_log_file = archiveArtifact(cmd, ctx, ping_log_file) cmd.close() with open(local_ping_log_file, 'r') as f: @@ -414,18 +412,13 @@ class OaiCiTest(): return (True, message) - def Ping(self, HTML, CONTAINERS, infra_file="ci_infra.yaml"): + def Ping(self, ctx, HTML, infra_file="ci_infra.yaml"): if self.ue_ids == [] or self.svr_id == None: raise Exception("no module names in self.ue_ids or/and self.svr_id provided") - # Creating destination log folder if needed on the python executor workspace - with cls_cmd.getConnection('localhost') as local: - ymlPath = CONTAINERS.yamlPath[0].split('/') - logPath = f'{os.getcwd()}/../cmake_targets/log/{ymlPath[-1]}' - local.run(f'mkdir -p {logPath}', silent=True) ues = [cls_module.Module_UE(ue_id, server_name, infra_file) for ue_id, server_name in zip(self.ue_ids, self.nodes)] cn = cls_corenetwork.CoreNetwork(self.svr_id, self.svr_node, filename=infra_file) with concurrent.futures.ThreadPoolExecutor(max_workers=64) as executor: - futures = [executor.submit(self.Ping_common, cn, ue, logPath) for ue in ues] + futures = [executor.submit(self.Ping_common, ctx, cn, ue) for ue in ues] results = [f.result() for f in futures] # each result in results is a tuple, first member goes to successes, second to messages successes, messages = map(list, zip(*results)) @@ -446,7 +439,7 @@ class OaiCiTest(): HTML.CreateHtmlTestRowQueue(self.ping_args, 'KO', messages) return success - def Iperf_Module(self, cn, ue, idx, ue_num, logPath): + def Iperf_Module(self, ctx, cn, ue, idx, ue_num): ueIP = ue.getIP() if not ueIP: return (False, f"UE {ue.getName()} has no IP address") @@ -459,7 +452,7 @@ class OaiCiTest(): serverReport = "" udpIperf = re.search('-u', iperf_opt) is not None bidirIperf = re.search('--bidir', iperf_opt) is not None - client_filename = f'iperf_client_{self.testCase_id}_{ue.getName()}.log' + client_filename = f'/tmp/iperf_client_{ue.getName()}.log' if udpIperf: target_bitrate, iperf_opt = Iperf_ComputeModifiedBW(idx, ue_num, self.iperf_profile, self.iperf_args) # note: for UDP testing we don't want to use json report - reports 0 Mbps received bitrate @@ -474,14 +467,11 @@ class OaiCiTest(): port = 5002 + idx # note: some core setups start an iperf3 server automatically, indicated in ci_infra by runIperf3Server: False` t = iperf_time * 2.5 - cmd_ue.run(f'rm /tmp/{client_filename}', reportNonZero=False, silent=True) + cmd_ue.run(f'rm {client_filename}', reportNonZero=False, silent=True) if cn.runIperf3Server(): cmd_svr.run(f'{cn.getCmdPrefix()} timeout -vk3 {t} iperf3 -s -B {svrIP} -p {port} -1 {jsonReport} >> /dev/null &', timeout=t) - cmd_ue.run(f'{ue.getCmdPrefix()} timeout -vk3 {t} {iperf_ue} -B {ueIP} -c {svrIP} -p {port} {iperf_opt} {jsonReport} {serverReport} -O 5 >> /tmp/{client_filename}', timeout=t) - # note: copy iperf3 log to the current directory for log analysis and log collection - dest_filename = f'{logPath}/{client_filename}' - cmd_ue.copyin(f'/tmp/{client_filename}', dest_filename) - cmd_ue.run(f'rm /tmp/{client_filename}', reportNonZero=False, silent=True) + cmd_ue.run(f'{ue.getCmdPrefix()} timeout -vk3 {t} {iperf_ue} -B {ueIP} -c {svrIP} -p {port} {iperf_opt} {jsonReport} {serverReport} -O 5 >> {client_filename}', timeout=t) + dest_filename = archiveArtifact(cmd_ue, ctx, client_filename) if udpIperf: status, msg = Iperf_analyzeV3UDP(dest_filename, self.iperf_bitrate_threshold, self.iperf_packetloss_threshold, target_bitrate) elif bidirIperf: @@ -491,20 +481,15 @@ class OaiCiTest(): return (status, f'{ue_header}\n{msg}') - def Iperf(self, HTML, CONTAINERS, infra_file="ci_infra.yaml"): + def Iperf(self, ctx, HTML, infra_file="ci_infra.yaml"): logging.debug(f'Iperf: iperf_args "{self.iperf_args}" iperf_packetloss_threshold "{self.iperf_packetloss_threshold}" iperf_bitrate_threshold "{self.iperf_bitrate_threshold}" iperf_profile "{self.iperf_profile}" iperf_options "{self.iperf_options}"') if self.ue_ids == [] or self.svr_id == None: raise Exception("no module names in self.ue_ids or/and self.svr_id provided") - # create log directory on executor node - with cls_cmd.getConnection('localhost') as local: - ymlPath = CONTAINERS.yamlPath[0].split('/') - logPath = f'{os.getcwd()}/../cmake_targets/log/{ymlPath[-1]}' - local.run(f'mkdir -p {logPath}', silent=True) ues = [cls_module.Module_UE(ue_id, server_name, infra_file) for ue_id, server_name in zip(self.ue_ids, self.nodes)] cn = cls_corenetwork.CoreNetwork(self.svr_id, self.svr_node, filename=infra_file) with concurrent.futures.ThreadPoolExecutor(max_workers=64) as executor: - futures = [executor.submit(self.Iperf_Module, cn, ue, i, len(ues), logPath) for i, ue in enumerate(ues)] + futures = [executor.submit(self.Iperf_Module, ctx, cn, ue, i, len(ues)) for i, ue in enumerate(ues)] results = [f.result() for f in futures] # each result in results is a tuple, first member goes to successes, second to messages successes, messages = map(list, zip(*results)) @@ -525,7 +510,7 @@ class OaiCiTest(): HTML.CreateHtmlTestRowQueue(self.iperf_args, 'KO', messages) return success - def Iperf2_Unidir(self, HTML, CONTAINERS, infra_file="ci_infra.yaml"): + def Iperf2_Unidir(self, ctx, HTML, infra_file="ci_infra.yaml"): if self.ue_ids == [] or self.svr_id == None or len(self.ue_ids) != 1: raise Exception("no module names in self.ue_ids or/and self.svr_id provided, multi UE scenario not supported") ue = cls_module.Module_UE(self.ue_ids[0].strip(),self.nodes[0].strip(), infra_file) @@ -536,23 +521,17 @@ class OaiCiTest(): svrIP = cn.getIP() if not svrIP: return False - server_filename = f'iperf_server_{self.testCase_id}_{ue.getName()}.log' - ymlPath = CONTAINERS.yamlPath[0].split('/') - logPath = f'{os.getcwd()}/../cmake_targets/log/{ymlPath[-1]}' + server_filename = f'/tmp/iperf_server_{ue.getName()}.log' iperf_time = Iperf_ComputeTime(self.iperf_args) target_bitrate, iperf_opt = Iperf_ComputeModifiedBW(0, 1, self.iperf_profile, self.iperf_args) t = iperf_time*2.5 - with cls_cmd.getConnection('localhost') as local: - local.run(f'mkdir -p {logPath}') with cls_cmd.getConnection(ue.getHost()) as cmd_ue, cls_cmd.getConnection(cn.getHost()) as cmd_svr: - cmd_ue.run(f'rm /tmp/{server_filename}', reportNonZero=False) - cmd_ue.run(f'{ue.getCmdPrefix()} timeout -vk3 {t} iperf -B {ueIP} -s -u -i1 >> /tmp/{server_filename} &', timeout=t) + cmd_ue.run(f'rm {server_filename}', reportNonZero=False) + cmd_ue.run(f'{ue.getCmdPrefix()} timeout -vk3 {t} iperf -B {ueIP} -s -u -i1 >> {server_filename} &', timeout=t) cmd_svr.run(f'{cn.getCmdPrefix()} timeout -vk3 {t} iperf -c {ueIP} -B {svrIP} {iperf_opt} -i1 >> /dev/null', timeout=t) localPath = f'{os.getcwd()}' - # note: copy iperf2 log to the directory for log collection - cmd_ue.copyin(f'/tmp/{server_filename}', f'{logPath}/{server_filename}') - cmd_ue.run(f'rm /tmp/{server_filename}', reportNonZero=False) - success, msg = Iperf_analyzeV2UDP(f'{logPath}/{server_filename}', self.iperf_bitrate_threshold, self.iperf_packetloss_threshold, target_bitrate) + local = archiveArtifact(cmd_ue, ctx, server_filename) + success, msg = Iperf_analyzeV2UDP(local, self.iperf_bitrate_threshold, self.iperf_packetloss_threshold, target_bitrate) ue_header = f'UE {ue.getName()} ({ueIP})' logging.info(f'\u001B[1;37;45m iperf result for {ue_header}\u001B[0m') for l in msg.split('\n'): diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 509cd19109..7ec30aa477 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -255,7 +255,7 @@ def ExecuteActionWithParam(action, ctx): else: CiTestObj.nodes = [None] * len(CiTestObj.ue_ids) ping_rttavg_threshold = test.findtext('ping_rttavg_threshold') or '' - success = CiTestObj.Ping(HTML, CONTAINERS) + success = CiTestObj.Ping(ctx, HTML) elif action == 'Iperf' or action == 'Iperf2_Unidir': CiTestObj.iperf_args = test.findtext('iperf_args') @@ -286,9 +286,9 @@ def ExecuteActionWithParam(action, ctx): logging.error('test-case has wrong option ' + CiTestObj.iperf_options) CiTestObj.iperf_options = 'check' if action == 'Iperf': - success = CiTestObj.Iperf(HTML, CONTAINERS) + success = CiTestObj.Iperf(ctx, HTML) elif action == 'Iperf2_Unidir': - success = CiTestObj.Iperf2_Unidir(HTML, CONTAINERS) + success = CiTestObj.Iperf2_Unidir(ctx, HTML) elif action == 'IdleSleep': st = test.findtext('idle_sleep_time_in_sec') or "5" diff --git a/ci-scripts/tests/ping-iperf.py b/ci-scripts/tests/ping-iperf.py index 225fe4e868..9d50567a07 100644 --- a/ci-scripts/tests/ping-iperf.py +++ b/ci-scripts/tests/ping-iperf.py @@ -9,11 +9,13 @@ import os os.system(f'rm -rf cmake_targets') os.system(f'mkdir -p cmake_targets/log') import unittest +import tempfile sys.path.append('./') # to find OAI imports below import cls_oai_html +from cls_ci_helper import TestCaseCtx import cls_oaicitest -import cls_containerize +import cls_cmd class TestPingIperf(unittest.TestCase): def setUp(self): @@ -22,7 +24,10 @@ class TestPingIperf(unittest.TestCase): self.ci = cls_oaicitest.OaiCiTest() self.ci.ue_ids = ["test"] self.ci.nodes = ["localhost"] - self.cont = cls_containerize.Containerize() + self.ctx = TestCaseCtx.Default(tempfile.mkdtemp()) + def tearDown(self): + with cls_cmd.LocalCmd() as c: + c.run(f'rm -rf {self.ctx.logPath}') def test_ping(self): self.ci.ping_args = "-c3" @@ -30,7 +35,7 @@ class TestPingIperf(unittest.TestCase): self.ci.svr_id = "test" infra_file = "tests/config/infra_ping_iperf.yaml" # TODO Should need nothing but options and UE(s) to use - success = self.ci.Ping(self.html, self.cont, infra_file=infra_file) + success = self.ci.Ping(self.ctx, self.html, infra_file=infra_file) self.assertTrue(success) def test_iperf(self): @@ -45,7 +50,7 @@ class TestPingIperf(unittest.TestCase): self.ci.iperf_profile = "balanced" infra_file = "tests/config/infra_ping_iperf.yaml" # TODO Should need nothing but options and UE(s) to use - success = self.ci.Iperf(self.html, self.cont, infra_file=infra_file) + success = self.ci.Iperf(self.ctx, self.html, infra_file=infra_file) self.assertTrue(success) def test_iperf2_unidir(self): @@ -57,7 +62,7 @@ class TestPingIperf(unittest.TestCase): self.ci.iperf_profile = "balanced" infra_file = "tests/config/infra_ping_iperf.yaml" # TODO Should need nothing but options and UE(s) to use - success = self.ci.Iperf2_Unidir(self.html, self.cont, infra_file=infra_file) + success = self.ci.Iperf2_Unidir(self.ctx, self.html, infra_file=infra_file) self.assertTrue(success) if __name__ == '__main__': From 1d3e795c0cbe5e1fca282a5b6a05028fd22a0c92 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 5 Aug 2025 09:40:42 +0200 Subject: [PATCH 383/964] Use archiveArtifact() for deploy_oc_physim() --- ci-scripts/cls_analysis.py | 4 ++-- ci-scripts/cls_cluster.py | 18 +++++++----------- ci-scripts/main.py | 2 +- 3 files changed, 10 insertions(+), 14 deletions(-) diff --git a/ci-scripts/cls_analysis.py b/ci-scripts/cls_analysis.py index ac591b52fb..236a4743a1 100644 --- a/ci-scripts/cls_analysis.py +++ b/ci-scripts/cls_analysis.py @@ -84,7 +84,7 @@ class Analysis(): return success,msg - def analyze_oc_physim(result_junit, details_json): + def analyze_oc_physim(result_junit, details_json, logPath): try: tree = ET.parse(result_junit) root = tree.getroot() @@ -124,7 +124,7 @@ class Analysis(): output = test.findtext("system-out") output_check = "exceeds the threshold" not in output # collect logs - log_dir = f'../cmake_targets/log/{test_exec}' + log_dir = f'{logPath}/{test_exec}' os.makedirs(log_dir, exist_ok=True) with open(f'{log_dir}/{test_name}.log', 'w') as f: f.write(output) diff --git a/ci-scripts/cls_cluster.py b/ci-scripts/cls_cluster.py index 7e88c6b07b..7d41e9d9cc 100644 --- a/ci-scripts/cls_cluster.py +++ b/ci-scripts/cls_cluster.py @@ -460,7 +460,7 @@ class Cluster: return status - def deploy_oc_physim(self, HTML, oc_release, svr_id): + def deploy_oc_physim(self, ctx, HTML, oc_release, svr_id): if self.ranRepository == '' or self.ranBranch == '' or self.ranCommitID == '': HELP.GenericHelp(CONST.Version) raise ValueError(f'Insufficient Parameter: ranRepository {self.ranRepository} ranBranch {self.ranBranch} ranCommitID {self.ranCommitID}') @@ -470,17 +470,13 @@ class Cluster: options = f"oaicicd-core-for-ci-ran {oc_release} {image_tag} {self.eNBSourceCodePath}" ret = cls_cmd.runScript(svr_id, script, 600, options) logging.debug(f'"{script}" finished with code {ret.returncode}, output:\n{ret.stdout}') - log_dir = f'{os.getcwd()}/../cmake_targets/log' - os.makedirs(log_dir, exist_ok=True) - result_junit = f'{oc_release}-run.xml' - details_json = f'{oc_release}-tests.json' with cls_cmd.getConnection(svr_id) as ssh: - ssh.copyin(src=f'{self.eNBSourceCodePath}/ci-scripts/{details_json}', tgt=f'{log_dir}/{details_json}') - ssh.copyin(src=f'{self.eNBSourceCodePath}/ci-scripts/{result_junit}', tgt=f'{log_dir}/{result_junit}') - ssh.copyin(src=f'{self.eNBSourceCodePath}/ci-scripts/physim_log.txt', tgt=f'{log_dir}/physim_log.txt') - ssh.copyin(src=f'{self.eNBSourceCodePath}/ci-scripts/physim_pods_summary.txt', tgt=f'{log_dir}/physim_pods_summary.txt') - ssh.copyin(src=f'{self.eNBSourceCodePath}/ci-scripts/LastTestsFailed.log', tgt=f'{log_dir}/LastTestsFailed.log') - test_status, test_summary, test_result = cls_analysis.Analysis.analyze_oc_physim(f'{log_dir}/{result_junit}', f'{log_dir}/{details_json}') + details_json = archiveArtifact(ssh, ctx, f'{self.eNBSourceCodePath}/ci-scripts/{oc_release}-tests.json') + result_junit = archiveArtifact(ssh, ctx, f'{self.eNBSourceCodePath}/ci-scripts/{oc_release}-run.xml') + archiveArtifact(ssh, ctx, f'{self.eNBSourceCodePath}/ci-scripts/physim_log.txt') + archiveArtifact(ssh, ctx, f'{self.eNBSourceCodePath}/ci-scripts/physim_pods_summary.txt') + archiveArtifact(ssh, ctx, f'{self.eNBSourceCodePath}/ci-scripts/LastTestsFailed.log') + test_status, test_summary, test_result = cls_analysis.Analysis.analyze_oc_physim(result_junit, details_json, ctx.logPath) if test_summary: if test_status: HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 7ec30aa477..035437ac8a 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -297,7 +297,7 @@ def ExecuteActionWithParam(action, ctx): elif action == 'Deploy_Run_PhySim': oc_release = test.findtext('oc_release') svr_id = test.findtext('svr_id') or None - success = CLUSTER.deploy_oc_physim(HTML, oc_release, svr_id) + success = CLUSTER.deploy_oc_physim(ctx, HTML, oc_release, svr_id) elif action == 'DeployCoreNetwork' or action == 'UndeployCoreNetwork': cn_id = test.findtext('cn_id') From 7ef8829167a342466342bc5a67a09830e310e989 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 5 Aug 2025 09:41:01 +0200 Subject: [PATCH 384/964] Use archiveArtifact() for cls_native.Build() --- ci-scripts/cls_native.py | 13 +++++-------- ci-scripts/main.py | 2 +- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/ci-scripts/cls_native.py b/ci-scripts/cls_native.py index fe508b84e3..86268a7dc1 100644 --- a/ci-scripts/cls_native.py +++ b/ci-scripts/cls_native.py @@ -28,27 +28,24 @@ import cls_cmd import cls_oai_html import cls_analysis import constants as CONST +from cls_ci_helper import archiveArtifact -LOG_PATH_PHYSIM = 'phy_sim_logs' DPDK_PATH = '/opt/dpdk-t2-22.11.0' class Native(): - def Build(test_case, HTML, host, directory, options): + def Build(ctx, test_case, HTML, host, directory, options): logging.debug(f'Building on server: {host}') HTML.testCase_id = test_case with cls_cmd.getConnection(host) as ssh: base = f"{directory}/cmake_targets" - ret = ssh.run(f"C_INCLUDE_PATH={DPDK_PATH}/include/ PKG_CONFIG_PATH={DPDK_PATH}/lib64/pkgconfig/ {base}/build_oai {options} > {base}/log/build_oai.log", timeout=900) + ret = ssh.run(f"C_INCLUDE_PATH={DPDK_PATH}/include/ PKG_CONFIG_PATH={DPDK_PATH}/lib64/pkgconfig/ {base}/build_oai {options} > {base}/build_oai.log", timeout=900) success = ret.returncode == 0 - logs = ssh.run(f"cat {base}/log/build_oai.log", silent=True) + logs = ssh.run(f"cat {base}/build_oai.log", silent=True) logging.debug(f"build finished with code {ret.returncode}, output:\n{logs.stdout}") - # create log directory, and copy build logs - target = f"{base}/build_log_{test_case}/" - ssh.run(f"mkdir -p {target}") - ssh.run(f"mv {base}/log/* {target}") + archiveArtifact(ssh, ctx, f'{base}/build_oai.log') # check if build artifacts are there # NOTE: build_oai should fail with exit code if it could not build, but it does not diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 035437ac8a..317b32b0f9 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -136,7 +136,7 @@ def ExecuteActionWithParam(action, ctx): if proxy_commit is not None: CONTAINERS.proxyCommit = proxy_commit if action == 'Build_eNB': - success = cls_native.Native.Build(HTML.testCase_id, HTML, RAN.eNBIPAddress, RAN.eNBSourceCodePath, RAN.Build_eNB_args) + success = cls_native.Native.Build(ctx, HTML.testCase_id, HTML, RAN.eNBIPAddress, RAN.eNBSourceCodePath, RAN.Build_eNB_args) elif action == 'Build_Image': success = CONTAINERS.BuildImage(HTML) elif action == 'Build_Proxy': From 83d037057bbfb0828cc4d5b870dfeab3af1d2b83 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 5 Aug 2025 09:41:08 +0200 Subject: [PATCH 385/964] Use archiveArtifact() for cls_native.run_physim() --- ci-scripts/cls_native.py | 11 +++++------ ci-scripts/main.py | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/ci-scripts/cls_native.py b/ci-scripts/cls_native.py index 86268a7dc1..3dde286c3a 100644 --- a/ci-scripts/cls_native.py +++ b/ci-scripts/cls_native.py @@ -65,15 +65,14 @@ class Native(): HTML.CreateHtmlTestRow(options, 'KO', CONST.ALL_PROCESSES_OK) return success - def Run_Physim(HTML, host, directory, options, physim_test, threshold): + def Run_Physim(ctx, HTML, host, directory, options, physim_test, threshold): logging.debug(f'Runnin {physim_test} on server: {host}') workSpacePath = f'{directory}/cmake_targets' - os.system(f'mkdir -p ./{LOG_PATH_PHYSIM}') - runLogFile=f'physim_{HTML.testCase_id}.log' + runLogFile=f'{workSpacePath}/physim.log' with cls_cmd.getConnection(host) as cmd: - cmd.run(f'sudo LD_LIBRARY_PATH=.:{DPDK_PATH}/lib64/ {workSpacePath}/ran_build/build/{physim_test} {options} >> {workSpacePath}/{runLogFile}') - cmd.copyin(src=f'{workSpacePath}/{runLogFile}', tgt=f'{LOG_PATH_PHYSIM}/{runLogFile}') - success, msg = cls_analysis.Analysis.analyze_physim(f'{LOG_PATH_PHYSIM}/{runLogFile}', physim_test, options, threshold) + cmd.run(f'sudo LD_LIBRARY_PATH=.:{DPDK_PATH}/lib64/ {workSpacePath}/ran_build/build/{physim_test} {options} >> {runLogFile}') + physim_file = archiveArtifact(cmd, ctx, runLogFile) + success, msg = cls_analysis.Analysis.analyze_physim(physim_file, physim_test, options, threshold) if success: HTML.CreateHtmlTestRowQueue(options, 'OK', [msg]) else: diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 317b32b0f9..34f0946de0 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -343,7 +343,7 @@ def ExecuteActionWithParam(action, ctx): physim_options = test.findtext('physim_run_args') physim_test = test.findtext('physim_test') physim_threshold = test.findtext('physim_time_threshold') or 'inf' - success = cls_native.Native.Run_Physim(HTML, RAN.eNBIPAddress, RAN.eNBSourceCodePath, physim_options, physim_test, physim_threshold) + success = cls_native.Native.Run_Physim(ctx, HTML, RAN.eNBIPAddress, RAN.eNBSourceCodePath, physim_options, physim_test, physim_threshold) elif action == 'LicenceAndFormattingCheck': success = SCA.LicenceAndFormattingCheck(HTML) From 1ffbba525de7c3c77fd0451659752d3268bf20d8 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 5 Aug 2025 17:41:56 +0200 Subject: [PATCH 386/964] Use archiveArtifact() for BuildRunTests() Collect also unit test logs, so that developers could see the reason for failed logs. --- ci-scripts/cls_containerize.py | 22 +++++++++++++--------- ci-scripts/main.py | 2 +- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index 591d6d413d..4b84b9ab86 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -636,7 +636,7 @@ class Containerize(): HTML.CreateHtmlTabFooter(False) return False - def BuildRunTests(self, HTML): + def BuildRunTests(self, ctx, HTML): svr = self.eNB_serverId[self.eNB_instance] lIpAddr, lSourcePath = self.GetCredentials(svr) logging.debug('Building on server: ' + lIpAddr) @@ -653,7 +653,6 @@ class Containerize(): if self.forcedWorkspaceCleanup: cmd.run(f'sudo -S rm -Rf {lSourcePath}') - self.testCase_id = HTML.testCase_id # check that ran-base image exists as we expect it baseImage = 'ran-base' @@ -673,10 +672,10 @@ class Containerize(): # build ran-unittests image dockerfile = "ci-scripts/docker/Dockerfile.unittest.ubuntu22" - ret = cmd.run(f'docker build --progress=plain --tag ran-unittests:{baseTag} --file {dockerfile} . &> {lSourcePath}/cmake_targets/log/unittest-build.log') + logfile = f'{lSourcePath}/cmake_targets/log/unittest-build.log' + ret = cmd.run(f'docker build --progress=plain --tag ran-unittests:{baseTag} --file {dockerfile} . &> {logfile}') + archiveArtifact(cmd, ctx, logfile) if ret.returncode != 0: - build_log_name = f'build_log_{self.testCase_id}' - CopyLogsToExecutor(cmd, lSourcePath, build_log_name) logging.error(f'Cannot build unit tests') HTML.CreateHtmlTestRow("Unit test build failed", 'KO', [dockerfile]) HTML.CreateHtmlTabFooter(False) @@ -685,10 +684,15 @@ class Containerize(): HTML.CreateHtmlTestRowQueue("Build unit tests", 'OK', [dockerfile]) # it worked, build and execute tests, and close connection - ret = cmd.run(f'docker run -a STDOUT --workdir /oai-ran/build/ --env LD_LIBRARY_PATH=/oai-ran/build/ --rm ran-unittests:{baseTag} ctest --no-label-summary -j$(nproc)') - cmd.run(f'docker rmi ran-unittests:{baseTag}') - build_log_name = f'build_log_{self.testCase_id}' - CopyLogsToExecutor(cmd, lSourcePath, build_log_name) + # I would like to run it with --rm and mount the ctest result directory to avoid 'docker cp' + # below, but then permissions are messed up and we can't remove the directory without sudo + # making the next pipeline fail + ret = cmd.run(f'docker run -a STDOUT --workdir /oai-ran/build/ --env LD_LIBRARY_PATH=/oai-ran/build/ --name ran-unittests ran-unittests:{baseTag} ctest --no-label-summary -j$(nproc)') + cmd.run('docker cp ran-unittests:/oai-ran/build/Testing/Temporary/LastTest.log .') + archiveArtifact(cmd, ctx, f'{lSourcePath}/LastTest.log') + cmd.run('docker cp ran-unittests:/oai-ran/build/Testing/Temporary/LastTestsFailed.log .') + archiveArtifact(cmd, ctx, f'{lSourcePath}/LastTestsFailed.log') + cmd.run('docker rm ran-unittests') cmd.close() if ret.returncode == 0: diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 34f0946de0..4a8e63f8cb 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -144,7 +144,7 @@ def ExecuteActionWithParam(action, ctx): elif action == 'Build_Cluster_Image': success = CLUSTER.BuildClusterImage(HTML) elif action == 'Build_Run_Tests': - success = CONTAINERS.BuildRunTests(HTML) + success = CONTAINERS.BuildRunTests(ctx, HTML) elif action == 'Initialize_eNB': datalog_rt_stats_file=test.findtext('rt_stats_cfg') From 63f6368ca7c0c363f8dcd0329bdf16fa33908c67 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 5 Aug 2025 17:41:40 +0200 Subject: [PATCH 387/964] use archiveArtifact() for BuildProxy() --- ci-scripts/cls_containerize.py | 11 +++-------- ci-scripts/main.py | 2 +- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index 4b84b9ab86..381e955127 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -534,7 +534,7 @@ class Containerize(): HTML.CreateHtmlTabFooter(False) return False - def BuildProxy(self, HTML): + def BuildProxy(self, ctx, HTML): svr = self.eNB_serverId[self.eNB_instance] lIpAddr, lSourcePath = self.GetCredentials(svr) logging.debug('Building on server: ' + lIpAddr) @@ -566,15 +566,10 @@ class Containerize(): if not success: raise Exception("could not clone proxy repository") - filename = f'build_log_{self.testCase_id}' - fullpath = f'{lSourcePath}/{filename}' + fullpath = f'{lSourcePath}/proxy_build.log' ssh.run(f'docker build --target oai-lte-multi-ue-proxy --tag proxy:{tag} --file {lSourcePath}/docker/Dockerfile.ubuntu18.04 {lSourcePath} > {fullpath} 2>&1') - ssh.run(f'zip -r -qq {fullpath}.zip {fullpath}') - local_file = f"{os.getcwd()}/../cmake_targets/log/{filename}.zip" - ssh.copyin(f'{fullpath}.zip', local_file) - # don't delete such that we might recover the zips - #ssh.run(f'rm -f {fullpath}.zip') + archiveArtifact(ssh, ctx, fullpath) ssh.run('docker image prune --force') ret = ssh.run(f'docker image inspect --format=\'Size = {{{{.Size}}}} bytes\' proxy:{tag}') diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 4a8e63f8cb..f201bdbcc6 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -140,7 +140,7 @@ def ExecuteActionWithParam(action, ctx): elif action == 'Build_Image': success = CONTAINERS.BuildImage(HTML) elif action == 'Build_Proxy': - success = CONTAINERS.BuildProxy(HTML) + success = CONTAINERS.BuildProxy(ctx, HTML) elif action == 'Build_Cluster_Image': success = CLUSTER.BuildClusterImage(HTML) elif action == 'Build_Run_Tests': From 5ffa4315141d8dc689b7ceddcdc09d81909f09c2 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 5 Aug 2025 17:41:34 +0200 Subject: [PATCH 388/964] Use archiveArtifact() for Build()/BuildCluster() I have to make both together, since they both depend on AnalyzeBuildLogs(). - remove mkdir for legacy sub-logfiles in build_oai, that does not exist anymore; also, remove corresponding log analysis, I think we don't use it and it is overkill (either build works or not) - manually try to copy "all.txt" - explicitly list log files to copy, then analyze - AnalyzeBuildLogs(): pass log files to inspect explicitly --- ci-scripts/cls_cluster.py | 91 ++++++++++++++------------ ci-scripts/cls_containerize.py | 116 +++++++++++---------------------- ci-scripts/main.py | 4 +- 3 files changed, 91 insertions(+), 120 deletions(-) diff --git a/ci-scripts/cls_cluster.py b/ci-scripts/cls_cluster.py index 7d41e9d9cc..185e90a13e 100644 --- a/ci-scripts/cls_cluster.py +++ b/ci-scripts/cls_cluster.py @@ -39,6 +39,7 @@ import constants as CONST import helpreadme as HELP import cls_containerize import cls_cmd +from cls_ci_helper import archiveArtifact IMAGE_REGISTRY_SERVICE_NAME = "image-registry.openshift-image-registry.svc" NAMESPACE = "oaicicd-ran" @@ -207,7 +208,12 @@ class Cluster: HTML.CreateHtmlTestRowQueue(param, 'KO', [msg]) return success - def BuildClusterImage(self, HTML): + def _retrieveOCLog(self, ctx, job, lSourcePath, image): + fn = f'{lSourcePath}/cmake_targets/log/{image}.log' + self.cmd.run(f'oc logs {job} &> {fn}') + return (image, archiveArtifact(self.cmd, ctx, fn)) + + def BuildClusterImage(self, ctx, HTML): if self.ranRepository == '' or self.ranBranch == '' or self.ranCommitID == '': HELP.GenericHelp(CONST.Version) raise ValueError(f'Insufficient Parameter: ranRepository {self.ranRepository} ranBranch {ranBranch} ranCommitID {self.ranCommitID}') @@ -280,22 +286,27 @@ class Cluster: self._recreate_entitlements() status = True # flag to abandon compiling if any image fails - attemptedImages = [] + log_files = [] + build_metrics = f"{lSourcePath}/cmake_targets/log/build-metrics.log" if forceBaseImageBuild: self._recreate_is_tag('ran-base', baseTag, 'openshift/ran-base-is.yaml') self._recreate_bc('ran-base', baseTag, 'openshift/ran-base-bc.yaml') ranbase_job = self._start_build('ran-base') - attemptedImages += ['ran-base'] status = ranbase_job is not None and self._wait_build_end([ranbase_job], 1000) if not status: logging.error('failure during build of ran-base') - self.cmd.run(f'oc logs {ranbase_job} &> cmake_targets/log/ran-base.log') # cannot use cmd.run because of redirect + log_files.append(self._retrieveOCLog(ctx, ranbase_job, lSourcePath, 'ran-base')) + # recover logs by mounting image self._retag_image_statement('ran-base', 'ran-base', baseTag, 'openshift/ran-base-log-retrieval.yaml') pod = self._deploy_pod('openshift/ran-base-log-retrieval.yaml') if pod is not None: - self.cmd.run(f'mkdir -p cmake_targets/log/ran-base') - self.cmd.run(f'oc rsync {pod}:/oai-ran/cmake_targets/log/ cmake_targets/log/ran-base') + logdir = f'{lSourcePath}/cmake_targets/log/ran-base' + self.cmd.run(f'mkdir -p {logdir}') + self.cmd.run(f'oc rsync {pod}:/oai-ran/cmake_targets/log/ {logdir}') self._undeploy_pod('openshift/ran-base-log-retrieval.yaml') + ret = self.cmd.run(f'ls {logdir}') + for f in ret.stdout.splitlines(): + archiveArtifact(self.cmd, ctx, f"{logdir}/{f}") else: status = False @@ -304,27 +315,24 @@ class Cluster: self._recreate_bc('oai-physim', imageTag, 'openshift/oai-physim-bc.yaml') self._retag_image_statement('ran-base', 'image-registry.openshift-image-registry.svc:5000/oaicicd-ran/ran-base', baseTag, 'docker/Dockerfile.phySim.rhel9') physim_job = self._start_build('oai-physim') - attemptedImages += ['oai-physim'] self._recreate_is_tag('ran-build', imageTag, 'openshift/ran-build-is.yaml') self._recreate_bc('ran-build', imageTag, 'openshift/ran-build-bc.yaml') self._retag_image_statement('ran-base', 'image-registry.openshift-image-registry.svc:5000/oaicicd-ran/ran-base', baseTag, 'docker/Dockerfile.build.rhel9') ranbuild_job = self._start_build('ran-build') - attemptedImages += ['ran-build'] self._recreate_is_tag('oai-clang', imageTag, 'openshift/oai-clang-is.yaml') self._recreate_bc('oai-clang', imageTag, 'openshift/oai-clang-bc.yaml') self._retag_image_statement('ran-base', 'image-registry.openshift-image-registry.svc:5000/oaicicd-ran/ran-base', baseTag, 'docker/Dockerfile.clang.rhel9') clang_job = self._start_build('oai-clang') - attemptedImages += ['oai-clang'] wait = ranbuild_job is not None and physim_job is not None and clang_job is not None and self._wait_build_end([ranbuild_job, physim_job, clang_job], 1200) if not wait: logging.error('error during build of ranbuild_job or physim_job or clang_job') status = status and wait - self.cmd.run(f'oc logs {ranbuild_job} &> cmake_targets/log/ran-build.log') - self.cmd.run(f'oc logs {physim_job} &> cmake_targets/log/oai-physim.log') - self.cmd.run(f'oc logs {clang_job} &> cmake_targets/log/oai-clang.log') - self.cmd.run(f'oc get pods.metrics.k8s.io &>> cmake_targets/log/build-metrics.log') + log_files.append(self._retrieveOCLog(ctx, ranbuild_job, lSourcePath, 'ran-build')) + log_files.append(self._retrieveOCLog(ctx, physim_job, lSourcePath, 'oai-physim')) + log_files.append(self._retrieveOCLog(ctx, clang_job, lSourcePath, 'oai-clang')) + self.cmd.run(f'oc get pods.metrics.k8s.io &>> {build_metrics}') if status: self._recreate_is_tag('oai-enb', imageTag, 'openshift/oai-enb-is.yaml') @@ -332,72 +340,66 @@ class Cluster: self._retag_image_statement('ran-base', 'image-registry.openshift-image-registry.svc:5000/oaicicd-ran/ran-base', baseTag, 'docker/Dockerfile.eNB.rhel9') self._retag_image_statement('ran-build', 'image-registry.openshift-image-registry.svc:5000/oaicicd-ran/ran-build', imageTag, 'docker/Dockerfile.eNB.rhel9') enb_job = self._start_build('oai-enb') - attemptedImages += ['oai-enb'] self._recreate_is_tag('oai-gnb', imageTag, 'openshift/oai-gnb-is.yaml') self._recreate_bc('oai-gnb', imageTag, 'openshift/oai-gnb-bc.yaml') self._retag_image_statement('ran-base', 'image-registry.openshift-image-registry.svc:5000/oaicicd-ran/ran-base', baseTag, 'docker/Dockerfile.gNB.rhel9') self._retag_image_statement('ran-build', 'image-registry.openshift-image-registry.svc:5000/oaicicd-ran/ran-build', imageTag, 'docker/Dockerfile.gNB.rhel9') gnb_job = self._start_build('oai-gnb') - attemptedImages += ['oai-gnb'] self._recreate_is_tag('oai-gnb-aw2s', imageTag, 'openshift/oai-gnb-aw2s-is.yaml') self._recreate_bc('oai-gnb-aw2s', imageTag, 'openshift/oai-gnb-aw2s-bc.yaml') self._retag_image_statement('ran-base', 'image-registry.openshift-image-registry.svc:5000/oaicicd-ran/ran-base', baseTag, 'docker/Dockerfile.gNB.aw2s.rhel9') self._retag_image_statement('ran-build', 'image-registry.openshift-image-registry.svc:5000/oaicicd-ran/ran-build', imageTag, 'docker/Dockerfile.gNB.aw2s.rhel9') gnb_aw2s_job = self._start_build('oai-gnb-aw2s') - attemptedImages += ['oai-gnb-aw2s'] wait = enb_job is not None and gnb_job is not None and gnb_aw2s_job is not None and self._wait_build_end([enb_job, gnb_job, gnb_aw2s_job], 800) if not wait: logging.error('error during build of eNB/gNB') status = status and wait # recover logs - self.cmd.run(f'oc logs {enb_job} &> cmake_targets/log/oai-enb.log') - self.cmd.run(f'oc logs {gnb_job} &> cmake_targets/log/oai-gnb.log') - self.cmd.run(f'oc logs {gnb_aw2s_job} &> cmake_targets/log/oai-gnb-aw2s.log') + log_files.append(self._retrieveOCLog(ctx, enb_job, lSourcePath, 'oai-enb')) + log_files.append(self._retrieveOCLog(ctx, gnb_job, lSourcePath, 'oai-gnb')) + log_files.append(self._retrieveOCLog(ctx, gnb_aw2s_job, lSourcePath, 'oai-gnb-aw2s')) + self.cmd.run(f'oc get pods.metrics.k8s.io &>> {build_metrics}') self._recreate_is_tag('oai-nr-cuup', imageTag, 'openshift/oai-nr-cuup-is.yaml') self._recreate_bc('oai-nr-cuup', imageTag, 'openshift/oai-nr-cuup-bc.yaml') self._retag_image_statement('ran-base', 'image-registry.openshift-image-registry.svc:5000/oaicicd-ran/ran-base', baseTag, 'docker/Dockerfile.nr-cuup.rhel9') self._retag_image_statement('ran-build', 'image-registry.openshift-image-registry.svc:5000/oaicicd-ran/ran-build', imageTag, 'docker/Dockerfile.nr-cuup.rhel9') nr_cuup_job = self._start_build('oai-nr-cuup') - attemptedImages += ['oai-nr-cuup'] self._recreate_is_tag('oai-lte-ue', imageTag, 'openshift/oai-lte-ue-is.yaml') self._recreate_bc('oai-lte-ue', imageTag, 'openshift/oai-lte-ue-bc.yaml') self._retag_image_statement('ran-base', 'image-registry.openshift-image-registry.svc:5000/oaicicd-ran/ran-base', baseTag, 'docker/Dockerfile.lteUE.rhel9') self._retag_image_statement('ran-build', 'image-registry.openshift-image-registry.svc:5000/oaicicd-ran/ran-build', imageTag, 'docker/Dockerfile.lteUE.rhel9') lteue_job = self._start_build('oai-lte-ue') - attemptedImages += ['oai-lte-ue'] self._recreate_is_tag('oai-nr-ue', imageTag, 'openshift/oai-nr-ue-is.yaml') self._recreate_bc('oai-nr-ue', imageTag, 'openshift/oai-nr-ue-bc.yaml') self._retag_image_statement('ran-base', 'image-registry.openshift-image-registry.svc:5000/oaicicd-ran/ran-base', baseTag, 'docker/Dockerfile.nrUE.rhel9') self._retag_image_statement('ran-build', 'image-registry.openshift-image-registry.svc:5000/oaicicd-ran/ran-build', imageTag, 'docker/Dockerfile.nrUE.rhel9') nrue_job = self._start_build('oai-nr-ue') - attemptedImages += ['oai-nr-ue'] wait = nr_cuup_job is not None and lteue_job is not None and nrue_job is not None and self._wait_build_end([nr_cuup_job, lteue_job, nrue_job], 800) if not wait: logging.error('error during build of nr-cuup/lteUE/nrUE') status = status and wait # recover logs - self.cmd.run(f'oc logs {nr_cuup_job} &> cmake_targets/log/oai-nr-cuup.log') - self.cmd.run(f'oc logs {lteue_job} &> cmake_targets/log/oai-lte-ue.log') - self.cmd.run(f'oc logs {nrue_job} &> cmake_targets/log/oai-nr-ue.log') - self.cmd.run(f'oc get pods.metrics.k8s.io &>> cmake_targets/log/build-metrics.log') + log_files.append(self._retrieveOCLog(ctx, nr_cuup_job, lSourcePath, 'oai-nr-cuup')) + log_files.append(self._retrieveOCLog(ctx, lteue_job, lSourcePath, 'oai-lte-ue')) + log_files.append(self._retrieveOCLog(ctx, nrue_job, lSourcePath, 'oai-nr-ue')) + self.cmd.run(f'oc get pods.metrics.k8s.io &>> {build_metrics}') if status: self._recreate_is_tag('ran-build-fhi72', imageTag, 'openshift/ran-build-fhi72-is.yaml') self._recreate_bc('ran-build-fhi72', imageTag, 'openshift/ran-build-fhi72-bc.yaml') self._retag_image_statement('ran-base', 'image-registry.openshift-image-registry.svc:5000/oaicicd-ran/ran-base', baseTag, 'docker/Dockerfile.build.fhi72.rhel9') ranbuildfhi72_job = self._start_build('ran-build-fhi72') - attemptedImages += ['ran-build-fhi72'] wait = ranbuildfhi72_job is not None and self._wait_build_end([ranbuildfhi72_job], 1200) if not wait: logging.error('error during build of ranbuildfhi72_job') status = status and wait - self.cmd.run(f'oc logs {ranbuildfhi72_job} &> cmake_targets/log/ran-build-fhi72.log') - self.cmd.run(f'oc get pods.metrics.k8s.io &>> cmake_targets/log/build-metrics.log') + log_files.append(self._retrieveOCLog(ctx, ranbuildfhi72_job, lSourcePath, 'ran-build-fhi72')) + self.cmd.run(f'oc get pods.metrics.k8s.io &>> {build_metrics}') if status: self._recreate_is_tag('oai-gnb-fhi72', imageTag, 'openshift/oai-gnb-fhi72-is.yaml') @@ -405,19 +407,17 @@ class Cluster: self._retag_image_statement('ran-base', 'image-registry.openshift-image-registry.svc:5000/oaicicd-ran/ran-base', baseTag, 'docker/Dockerfile.gNB.fhi72.rhel9') self._retag_image_statement('ran-build-fhi72', 'image-registry.openshift-image-registry.svc:5000/oaicicd-ran/ran-build-fhi72', imageTag, 'docker/Dockerfile.gNB.fhi72.rhel9') gnb_fhi72_job = self._start_build('oai-gnb-fhi72') - attemptedImages += ['oai-gnb-fhi72'] wait = gnb_fhi72_job is not None and self._wait_build_end([gnb_fhi72_job], 600) if not wait: logging.error('error during build of gNB-fhi72') status = status and wait # recover logs - self.cmd.run(f'oc logs {gnb_fhi72_job} &> cmake_targets/log/oai-gnb-fhi72.log') - self.cmd.run(f'oc get pods.metrics.k8s.io &>> cmake_targets/log/build-metrics.log') + log_files.append(self._retrieveOCLog(ctx, gnb_fhi72_job, lSourcePath, 'oai-gnb-fhi72')) + self.cmd.run(f'oc get pods.metrics.k8s.io &>> {build_metrics}') # split and analyze logs imageSize = {} - for image in attemptedImages: - self.cmd.run(f'mkdir -p cmake_targets/log/{image}') + for image, _ in log_files: tag = imageTag if image != 'ran-base' else baseTag size = self._get_image_size(image, tag) if size <= 0: @@ -428,12 +428,14 @@ class Cluster: imageSize[image] = f'{sizeMb:.1f} Mbytes (uncompressed: ~{sizeMb*2.5:.1f} Mbytes)' logging.info(f'\u001B[1m{image} size is {imageSize[image]}\u001B[0m') - grep_exp = r"\|".join(attemptedImages) - self.cmd.run(f'oc get images | grep -e \'{grep_exp}\' &> cmake_targets/log/image_registry.log'); - self.cmd.run(f'for pod in $(oc get pods | tail -n +2 | awk \'{{print $1}}\'); do oc get pod $pod -o json &>> cmake_targets/log/build_pod_summary.log; done') - - build_log_name = f'build_log_{self.testCase_id}' - cls_containerize.CopyLogsToExecutor(self.cmd, lSourcePath, build_log_name) + archiveArtifact(self.cmd, ctx, build_metrics) + logfile = f'{lSourcePath}/cmake_targets/log/image_registry.log' + grep_exp = r"\|".join([i for i,f in log_files]) + self.cmd.run(f'oc get images | grep -e \'{grep_exp}\' &> {logfile}'); + archiveArtifact(self.cmd, ctx, logfile) + logfile = f'{lSourcePath}/cmake_targets/log/build_pod_summary.log' + self.cmd.run(f'for pod in $(oc get pods | tail -n +2 | awk \'{{print $1}}\'); do oc get pod $pod -o json &>> {logfile}; done') + archiveArtifact(self.cmd, ctx, logfile) self.cmd.run('for pod in $(oc get pods | tail -n +2 | awk \'{print $1}\'); do oc delete pod ${pod}; done') @@ -442,7 +444,7 @@ class Cluster: self.cmd.close() # Analyze the logs - collectInfo = cls_containerize.AnalyzeBuildLogs(build_log_name, attemptedImages, status) + collectInfo = cls_containerize.AnalyzeBuildLogs(log_files, status) for img in collectInfo: for f in collectInfo[img]: status = status and collectInfo[img][f]['status'] @@ -458,6 +460,13 @@ class Cluster: HTML.CreateHtmlNextTabHeaderTestRow(collectInfo, imageSize) + # TODO fix groovy script, remove the following. + # the groovy scripts expects all logs in + # //ci-scripts, so copy it there + with cls_cmd.LocalCmd() as c: + c.run(f'mkdir -p {os.getcwd()}/test_log_{ctx.test_id}/') + c.run(f'cp -r {ctx.logPath} {os.getcwd()}/test_log_{ctx.test_id}/') + return status def deploy_oc_physim(self, ctx, HTML, oc_release, svr_id): diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index 381e955127..3af34dca14 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -82,67 +82,25 @@ def CreateTag(ranCommitID, ranBranch, ranAllowMerge): tagToUse = f'develop-{shortCommit}' return tagToUse -def CopyLogsToExecutor(cmd, sourcePath, log_name): - cmd.cd(f'{sourcePath}/cmake_targets') - cmd.run(f'rm -f {log_name}.zip') - cmd.run(f'mkdir -p {log_name}') - cmd.run(f'mv log/* {log_name}') - cmd.run(f'zip -r -qq {log_name}.zip {log_name}') - - # copy zip to executor for analysis - if (os.path.isfile(f'./{log_name}.zip')): - os.remove(f'./{log_name}.zip') - if (os.path.isdir(f'./{log_name}')): - shutil.rmtree(f'./{log_name}') - cmd.copyin(src=f'{sourcePath}/cmake_targets/{log_name}.zip', tgt=f'{os.getcwd()}/{log_name}.zip') - cmd.run(f'rm -f {log_name}.zip') - ZipFile(f'{log_name}.zip').extractall('.') - -def AnalyzeBuildLogs(buildRoot, images, globalStatus): +def AnalyzeBuildLogs(logfiles, globalStatus): collectInfo = {} - for image in images: + for image, lf in logfiles: files = {} - file_list = [f for f in os.listdir(f'{buildRoot}/{image}') if os.path.isfile(os.path.join(f'{buildRoot}/{image}', f)) and f.endswith('.txt')] - # Analyze the "sub-logs" of every target image - for fil in file_list: - errorandwarnings = {} - warningsNo = 0 - errorsNo = 0 - with open(f'{buildRoot}/{image}/{fil}', mode='r') as inputfile: - for line in inputfile: - result = re.search(' ERROR ', str(line)) - if result is not None: - errorsNo += 1 - result = re.search(' error:', str(line)) - if result is not None: - errorsNo += 1 - result = re.search(' WARNING ', str(line)) - if result is not None: - warningsNo += 1 - result = re.search(' warning:', str(line)) - if result is not None: - warningsNo += 1 - errorandwarnings['errors'] = errorsNo - errorandwarnings['warnings'] = warningsNo - errorandwarnings['status'] = globalStatus - files[fil] = errorandwarnings - # Analyze the target image - if os.path.isfile(f'{buildRoot}/{image}.log'): - errorandwarnings = {} - committed = False - tagged = False - with open(f'{buildRoot}/{image}.log', mode='r') as inputfile: - for line in inputfile: - lineHasTag = re.search(f'Successfully tagged {image}:', str(line)) is not None - lineHasTag2 = re.search(f'naming to docker.io/library/{image}:', str(line)) is not None - tagged = tagged or lineHasTag or lineHasTag2 - # the OpenShift Cluster builder prepends image registry URL - lineHasCommit = re.search(r'COMMIT [a-zA-Z0-9\.:/\-]*' + image, str(line)) is not None - committed = committed or lineHasCommit - errorandwarnings['errors'] = 0 if committed or tagged else 1 - errorandwarnings['warnings'] = 0 - errorandwarnings['status'] = committed or tagged - files['Target Image Creation'] = errorandwarnings + errorandwarnings = {} + committed = False + tagged = False + with open(lf, mode='r') as inputfile: + for line in inputfile: + lineHasTag = re.search(f'Successfully tagged {image}:', str(line)) is not None + lineHasTag2 = re.search(f'naming to docker.io/library/{image}:', str(line)) is not None + tagged = tagged or lineHasTag or lineHasTag2 + # the OpenShift Cluster builder prepends image registry URL + lineHasCommit = re.search(r'COMMIT [a-zA-Z0-9\.:/\-]*' + image, str(line)) is not None + committed = committed or lineHasCommit + errorandwarnings['errors'] = 0 if committed or tagged else 1 + errorandwarnings['warnings'] = 0 + errorandwarnings['status'] = committed or tagged + files['Target Image Creation'] = errorandwarnings collectInfo[image] = files return collectInfo @@ -328,11 +286,12 @@ class Containerize(): raise ValueError(f'Insufficient Parameter: IP/node {ip}, path {path}') return (ip, path) - def BuildImage(self, HTML): + def BuildImage(self, ctx, HTML): svr = self.eNB_serverId[self.eNB_instance] lIpAddr, lSourcePath = self.GetCredentials(svr) logging.debug('Building on server: ' + lIpAddr) cmd = cls_cmd.getConnection(lIpAddr) + log_files = [] # Checking the hostname to get adapted on cli and dockerfileprefixes cmd.run('hostnamectl') @@ -424,7 +383,18 @@ class Containerize(): # On when the base image docker file is being modified. if forceBaseImageBuild: cmd.run(f"{self.cli} image rm {baseImage}:{baseTag}") - cmd.run(f"{self.cli} build {self.cliBuildOptions} --target {baseImage} --tag {baseImage}:{baseTag} --file docker/Dockerfile.base{self.dockerfileprefix} . &> cmake_targets/log/ran-base.log", timeout=1600) + logfile = f'{lSourcePath}/cmake_targets/log/ran-base.docker.log' + cmd.run(f"{self.cli} build {self.cliBuildOptions} --target {baseImage} --tag {baseImage}:{baseTag} --file docker/Dockerfile.base{self.dockerfileprefix} . &> {logfile}", timeout=1600) + t = ("ran-base", archiveArtifact(cmd, ctx, logfile)) + log_files.append(t) + + # Recover build logs, for the moment only possible when build is successful + cmd.run(f"{self.cli} create --name test {baseImage}:{baseTag}") + cmd.run("mkdir -p cmake_targets/log/ran-base") + logfile = f'{lSourcePath}/cmake_targets/log/ran-base.log' + cmd.run(f"{self.cli} cp test:/oai-ran/cmake_targets/log/all.txt {logfile}") + cmd.run(f"{self.cli} rm -f test") + archiveArtifact(cmd, ctx, logfile) # First verify if the base image was properly created. ret = cmd.run(f"{self.cli} image inspect --format=\'Size = {{{{.Size}}}} bytes\' {baseImage}:{baseTag}") allImagesSize = {} @@ -448,17 +418,9 @@ class Containerize(): else: logging.debug('ran-base size is unknown') - # Recover build logs, for the moment only possible when build is successful - cmd.run(f"{self.cli} create --name test {baseImage}:{baseTag}") - cmd.run("mkdir -p cmake_targets/log/ran-base") - cmd.run(f"{self.cli} cp test:/oai-ran/cmake_targets/log/. cmake_targets/log/ran-base") - cmd.run(f"{self.cli} rm -f test") - # Build the target image(s) status = True - attemptedImages = ['ran-base'] for image,pattern,name,option in imageNames: - attemptedImages += [name] # the archived Dockerfiles have "ran-base:latest" as base image # we need to update them with proper tag cmd.run(f'git checkout -- docker/Dockerfile.{pattern}{self.dockerfileprefix}') @@ -472,15 +434,18 @@ class Containerize(): cmd.run(f'sed -i -e "s#ran-build:latest#ran-build:{imageTag}#" docker/Dockerfile.{pattern}{self.dockerfileprefix}') if image == 'oai-gnb-aerial': cmd.run('cp -f /opt/nvidia-ipc/nvipc.src.2025.05.20.tar.gz .') - ret = cmd.run(f'{self.cli} build {self.cliBuildOptions} --target {image} --tag {name}:{imageTag} --file docker/Dockerfile.{pattern}{self.dockerfileprefix} {option} . > cmake_targets/log/{name}.log 2>&1', timeout=1200) + logfile = f'{lSourcePath}/cmake_targets/log/{name}.docker.log' + ret = cmd.run(f'{self.cli} build {self.cliBuildOptions} --target {image} --tag {name}:{imageTag} --file docker/Dockerfile.{pattern}{self.dockerfileprefix} {option} . > {logfile} 2>&1', timeout=1200) + t = (name, archiveArtifact(cmd, ctx, logfile)) + log_files.append(t) if image == 'oai-gnb-aerial': cmd.run('rm -f nvipc.src.2025.05.20.tar.gz') if image == 'ran-build' and ret.returncode == 0: cmd.run(f"docker run --name test-log -d {name}:{imageTag} /bin/true") - cmd.run(f"docker cp test-log:/oai-ran/cmake_targets/log/ cmake_targets/log/{name}/") + logfile = f'{lSourcePath}/{image}.log' + cmd.run(f"docker cp test-log:/oai-ran/cmake_targets/log/all.txt {logfile}") cmd.run(f"docker rm -f test-log") - else: - cmd.run(f"mkdir -p cmake_targets/log/{name}") + archiveArtifact(cmd, ctx, logfile) # check the status of the build ret = cmd.run(f"{self.cli} image inspect --format=\'Size = {{{{.Size}}}} bytes\' {name}:{imageTag}") if ret.returncode != 0: @@ -514,13 +479,10 @@ class Containerize(): logging.debug(cmd.run("df -h").stdout) logging.debug(cmd.run("docker system df").stdout) - # create a zip with all logs - build_log_name = f'build_log_{self.testCase_id}' - CopyLogsToExecutor(cmd, lSourcePath, build_log_name) cmd.close() # Analyze the logs - collectInfo = AnalyzeBuildLogs(build_log_name, attemptedImages, status) + collectInfo = AnalyzeBuildLogs(log_files, status) if status: logging.info('\u001B[1m Building OAI Image(s) Pass\u001B[0m') diff --git a/ci-scripts/main.py b/ci-scripts/main.py index f201bdbcc6..dcca9b521f 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -138,11 +138,11 @@ def ExecuteActionWithParam(action, ctx): if action == 'Build_eNB': success = cls_native.Native.Build(ctx, HTML.testCase_id, HTML, RAN.eNBIPAddress, RAN.eNBSourceCodePath, RAN.Build_eNB_args) elif action == 'Build_Image': - success = CONTAINERS.BuildImage(HTML) + success = CONTAINERS.BuildImage(ctx, HTML) elif action == 'Build_Proxy': success = CONTAINERS.BuildProxy(ctx, HTML) elif action == 'Build_Cluster_Image': - success = CLUSTER.BuildClusterImage(HTML) + success = CLUSTER.BuildClusterImage(ctx, HTML) elif action == 'Build_Run_Tests': success = CONTAINERS.BuildRunTests(ctx, HTML) From 810dad97ae0a3016ea0f1d65347bd326eaffb3ca Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 5 Aug 2025 17:53:28 +0200 Subject: [PATCH 389/964] Collect the ninja logs for various ran-build images --- ci-scripts/cls_containerize.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index 3af34dca14..e632349960 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -440,9 +440,9 @@ class Containerize(): log_files.append(t) if image == 'oai-gnb-aerial': cmd.run('rm -f nvipc.src.2025.05.20.tar.gz') - if image == 'ran-build' and ret.returncode == 0: + if image == 'ran-build' or image == 'ran-build-asan' or image == 'ran-build-fhi72': cmd.run(f"docker run --name test-log -d {name}:{imageTag} /bin/true") - logfile = f'{lSourcePath}/{image}.log' + logfile = f'{lSourcePath}/{image}.ninja.log' cmd.run(f"docker cp test-log:/oai-ran/cmake_targets/log/all.txt {logfile}") cmd.run(f"docker rm -f test-log") archiveArtifact(cmd, ctx, logfile) From 65ec00c5fdf3a1fe87ffdf3fabd8f708ffc76748 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 5 Aug 2025 14:30:05 +0200 Subject: [PATCH 390/964] No need for all the useless docker image rm --- ci-scripts/cls_containerize.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index e632349960..0c1bcb530e 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -377,7 +377,7 @@ class Containerize(): # Let's remove any previous run artifacts if still there cmd.run(f"{self.cli} image prune --force") for image,pattern,name,option in imageNames: - cmd.run(f"{self.cli} image rm {name}:{imageTag}") + cmd.run(f"{self.cli} image rm {name}:{imageTag}", reportNonZero=False) # Build the base image only on Push Events (not on Merge Requests) # On when the base image docker file is being modified. From 025a6dbd1dd57ace93715abebb975066d5dbe28e Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 5 Aug 2025 17:43:05 +0200 Subject: [PATCH 391/964] Remove unused testCase_Id --- ci-scripts/cls_containerize.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index 0c1bcb530e..306f9a9a47 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -255,8 +255,6 @@ class Containerize(): self.services = ['', '', ''] self.deploymentTag = '' - self.testCase_id = '' - self.cli = '' self.cliBuildOptions = '' self.dockerfileprefix = '' @@ -347,7 +345,6 @@ class Containerize(): imageNames.append(('oai-nr-ue', 'nrUE', 'oai-nr-ue', '')) imageNames.append(('oai-gnb-aerial', 'gNB.aerial', 'oai-gnb-aerial', '')) - self.testCase_id = HTML.testCase_id cmd.cd(lSourcePath) # if asterix, copy the entitlement and subscription manager configurations if self.host == 'Red Hat': @@ -502,7 +499,6 @@ class Containerize(): logging.debug('Building on server: ' + lIpAddr) ssh = cls_cmd.getConnection(lIpAddr) - self.testCase_id = HTML.testCase_id oldRanCommidID = self.ranCommitID oldRanRepository = self.ranRepository oldRanAllowMerge = self.ranAllowMerge From 27e37a4181feda612ea7c879baf192b90808f910 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 5 Aug 2025 16:14:53 +0200 Subject: [PATCH 392/964] Use archiveArtifact() for LicenceAndFormattingCheck() --- ci-scripts/cls_static_code_analysis.py | 12 ++++++------ ci-scripts/main.py | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/ci-scripts/cls_static_code_analysis.py b/ci-scripts/cls_static_code_analysis.py index f2951b0528..33337a4700 100644 --- a/ci-scripts/cls_static_code_analysis.py +++ b/ci-scripts/cls_static_code_analysis.py @@ -43,6 +43,7 @@ from pathlib import Path import helpreadme as HELP import constants as CONST import cls_cmd +from cls_ci_helper import archiveArtifact #----------------------------------------------------------- # Class Declaration @@ -213,7 +214,7 @@ class StaticCodeAnalysis(): return True - def LicenceAndFormattingCheck(self, HTML): + def LicenceAndFormattingCheck(self, ctx, HTML): # Workspace is no longer recreated from scratch. # It implies that this method shall be called last within a build pipeline # where workspace is already created @@ -238,7 +239,7 @@ class StaticCodeAnalysis(): else: check_options += f' --build-arg TARGET_BRANCH={self.ranTargetBranch}' - logDir = f'{lSourcePath}/cmake_targets/build_log_{self.testCase_id}' + logDir = f'{lSourcePath}/cmake_targets/log/' cmd.run(f'mkdir -p {logDir}') cmd.run('docker image rm oai-formatting-check:latest') cmd.run(f'docker build --target oai-formatting-check --tag oai-formatting-check:latest {check_options} --file {lSourcePath}/ci-scripts/docker/Dockerfile.formatting.bionic {lSourcePath} > {logDir}/oai-formatting-check.txt 2>&1') @@ -247,12 +248,11 @@ class StaticCodeAnalysis(): cmd.run('docker image prune --force') cmd.run('docker volume prune --force') - # Analyzing the logs - cmd.copyin(f'{logDir}/oai-formatting-check.txt', 'oai-formatting-check.txt') + file = archiveArtifact(cmd, ctx, f'{logDir}/oai-formatting-check.txt') cmd.close() finalStatus = 0 - if (os.path.isfile('./oai-formatting-check.txt')): + if (os.path.isfile(file)): analyzed = False nbFilesNotFormatted = 0 listFiles = False @@ -263,7 +263,7 @@ class StaticCodeAnalysis(): gnuGplLicenceFiles = [] suspectLicence = False suspectLicenceFiles = [] - with open('./oai-formatting-check.txt', 'r') as logfile: + with open(file, 'r') as logfile: for line in logfile: ret = re.search('./ci-scripts/checkCodingFormattingRules.sh', str(line)) if ret is not None: diff --git a/ci-scripts/main.py b/ci-scripts/main.py index dcca9b521f..d4ef09668a 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -346,7 +346,7 @@ def ExecuteActionWithParam(action, ctx): success = cls_native.Native.Run_Physim(ctx, HTML, RAN.eNBIPAddress, RAN.eNBSourceCodePath, physim_options, physim_test, physim_threshold) elif action == 'LicenceAndFormattingCheck': - success = SCA.LicenceAndFormattingCheck(HTML) + success = SCA.LicenceAndFormattingCheck(ctx, HTML) elif action == 'Cppcheck_Analysis': success = SCA.CppCheckAnalysis(HTML) From 03a47721896bb76a57118b0a7bc9a6f8311b2ac7 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 6 Aug 2025 01:23:25 +0200 Subject: [PATCH 393/964] Remove cppcheck reference file: nobody knows about it, nobody checks --- ci-scripts/cls_static_code_analysis.py | 33 -------------------------- 1 file changed, 33 deletions(-) diff --git a/ci-scripts/cls_static_code_analysis.py b/ci-scripts/cls_static_code_analysis.py index 33337a4700..bdfb308a09 100644 --- a/ci-scripts/cls_static_code_analysis.py +++ b/ci-scripts/cls_static_code_analysis.py @@ -122,19 +122,6 @@ class StaticCodeAnalysis(): CCR_ref = CppCheckResults() vId = 0 for variant in CCR.variants: - refAvailable = False - if self.ranAllowMerge: - refFolder = str(Path.home()) + '/cppcheck-references' - if (os.path.isfile(refFolder + '/cppcheck-'+ variant + '.txt')): - refAvailable = True - with open(refFolder + '/cppcheck-'+ variant + '.txt', 'r') as refFile: - for line in refFile: - ret = re.search(' (?P[0-9\.]+) errors', str(line)) - if ret is not None: - CCR_ref.nbErrors[vId] = int(ret.group('nb_errors')) - ret = re.search(' (?P[0-9\.]+) warnings', str(line)) - if ret is not None: - CCR_ref.nbWarnings[vId] = int(ret.group('nb_warnings')) if (os.path.isfile('./cppcheck-'+ variant + '.txt')): xmlStart = False with open('./cppcheck-'+ variant + '.txt', 'r') as logfile: @@ -186,26 +173,6 @@ class StaticCodeAnalysis(): vMsg += ' Wrong Scanf Nb Args: ' + str(CCR.nbWrongScanfArg[vId]) + '\n' for vLine in vMsg.split('\n'): logging.debug(vLine) - if self.ranAllowMerge and refAvailable: - if CCR_ref.nbErrors[vId] == CCR.nbErrors[vId]: - logging.debug(' No change in number of errors') - elif CCR_ref.nbErrors[vId] > CCR.nbErrors[vId]: - logging.debug(' Good! Decrease in number of errors') - else: - logging.debug(' Bad! increase in number of errors') - if CCR_ref.nbWarnings[vId] == CCR.nbWarnings[vId]: - logging.debug(' No change in number of warnings') - elif CCR_ref.nbWarnings[vId] > CCR.nbWarnings[vId]: - logging.debug(' Good! Decrease in number of warnings') - else: - logging.debug(' Bad! increase in number of warnings') - # Create new reference file - if not self.ranAllowMerge: - refFolder = str(Path.home()) + '/cppcheck-references' - if not os.path.isdir(refFolder): - os.mkdir(refFolder) - with open(refFolder + '/cppcheck-'+ variant + '.txt', 'w') as refFile: - refFile.write(vMsg) vId += 1 HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) From 14389235dfa1e713d3ba1907c3030d8893894f66 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 5 Aug 2025 16:19:36 +0200 Subject: [PATCH 394/964] Use archiveArtifact() for SCA.CppCheckAnalysis() --- ci-scripts/cls_static_code_analysis.py | 17 ++++++++++------- ci-scripts/main.py | 2 +- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/ci-scripts/cls_static_code_analysis.py b/ci-scripts/cls_static_code_analysis.py index bdfb308a09..8b0ec05352 100644 --- a/ci-scripts/cls_static_code_analysis.py +++ b/ci-scripts/cls_static_code_analysis.py @@ -81,7 +81,7 @@ class StaticCodeAnalysis(): self.eNBPassword = '' self.eNBSourceCodePath = '' - def CppCheckAnalysis(self, HTML): + def CppCheckAnalysis(self, ctx, HTML): if self.ranRepository == '' or self.ranBranch == '' or self.ranCommitID == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') @@ -104,7 +104,7 @@ class StaticCodeAnalysis(): full_ran_repo_name = self.ranRepository + '.git' cmd.cd(lSourcePath) - logDir = f'{lSourcePath}/cmake_targets/build_log_{self.testCase_id}' + logDir = f'{lSourcePath}/cmake_targets/log' cmd.run(f'mkdir -p {logDir}') cmd.run('docker image rm oai-cppcheck:bionic oai-cppcheck:focal') cmd.run(f'sed -e "s@xenial@bionic@" {lSourcePath}/ci-scripts/docker/Dockerfile.cppcheck.xenial > {lSourcePath}/ci-scripts/docker/Dockerfile.cppcheck.bionic') @@ -113,18 +113,21 @@ class StaticCodeAnalysis(): cmd.run(f'docker build --tag oai-cppcheck:focal --file {lSourcePath}/ci-scripts/docker/Dockerfile.cppcheck.focal . > {logDir}/cppcheck-focal.txt 2>&1') cmd.run('docker image rm oai-cppcheck:bionic oai-cppcheck:focal') - # Analyzing the logs - cmd.copyin(f'{logDir}/cppcheck-bionic.txt', 'cppcheck-bionic.txt') - cmd.copyin(f'{logDir}/cppcheck-focal.txt', 'cppcheck-focal.txt') + bionic = archiveArtifact(cmd, ctx, f'{logDir}/cppcheck-bionic.txt') + focal = archiveArtifact(cmd, ctx, f'{logDir}/cppcheck-focal.txt') cmd.close() CCR = CppCheckResults() CCR_ref = CppCheckResults() vId = 0 for variant in CCR.variants: - if (os.path.isfile('./cppcheck-'+ variant + '.txt')): + filename = ctx.baseFilename() + '-cppcheck-'+ variant + '.txt' + logging.info(f"will check file '{filename}'") + if not os.path.isfile(filename): + raise FileNotFoundError(f"{filename} is not a file") + else: xmlStart = False - with open('./cppcheck-'+ variant + '.txt', 'r') as logfile: + with open(filename, 'r') as logfile: for line in logfile: ret = re.search('cppcheck version="(?P[0-9\.]+)"', str(line)) if ret is not None: diff --git a/ci-scripts/main.py b/ci-scripts/main.py index d4ef09668a..836f6aee3b 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -349,7 +349,7 @@ def ExecuteActionWithParam(action, ctx): success = SCA.LicenceAndFormattingCheck(ctx, HTML) elif action == 'Cppcheck_Analysis': - success = SCA.CppCheckAnalysis(HTML) + success = SCA.CppCheckAnalysis(ctx, HTML) elif action == 'Push_Local_Registry': svr_id = test.findtext('svr_id') From 8c2b356c1d3170c6423edb92da335fe6a9ec9a02 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 6 Aug 2025 01:29:30 +0200 Subject: [PATCH 395/964] Remove unused function --- ci-scripts/ran.py | 35 ----------------------------------- 1 file changed, 35 deletions(-) diff --git a/ci-scripts/ran.py b/ci-scripts/ran.py index 46711b1b73..5c5513a317 100644 --- a/ci-scripts/ran.py +++ b/ci-scripts/ran.py @@ -248,41 +248,6 @@ class RANManagement(): logging.debug('\u001B[1m Initialize eNB/gNB Completed\u001B[0m') return enbDidSync - def CheckeNBProcess(self, status_queue): - # At least the instance 0 SHALL be on! - if self.eNBstatuses[0] == 0: - lIpAddr = self.eNBIPAddress - lUserName = self.eNBUserName - lPassWord = self.eNBPassword - elif self.eNBstatuses[0] == 1: - lIpAddr = self.eNB1IPAddress - lUserName = self.eNB1UserName - lPassWord = self.eNB1Password - elif self.eNBstatuses[0] == 2: - lIpAddr = self.eNB2IPAddress - lUserName = self.eNB2UserName - lPassWord = self.eNB2Password - else: - lIpAddr = self.eNBIPAddress - lUserName = self.eNBUserName - lPassWord = self.eNBPassword - mySSH = SSH.SSHConnection() - mySSH.open(lIpAddr, lUserName, lPassWord) - if self.air_interface[self.eNB_instance] == '': - pattern = 'softmodem' - else: - pattern = self.air_interface[self.eNB_instance] - mySSH.command('stdbuf -o0 ps -aux | grep --color=never ' + pattern + ' | grep -v grep', '\$', 5) - result = re.search(pattern, mySSH.getBefore()) - success = result is not None - if not success: - logging.debug('\u001B[1;37;41m eNB Process Not Found! \u001B[0m') - status_queue.put(CONST.ENB_PROCESS_FAILED) - else: - status_queue.put(CONST.ENB_PROCESS_OK) - mySSH.close() - return success - def TerminateeNB(self, HTML): if self.eNB_serverId[self.eNB_instance] == '0': lIpAddr = self.eNBIPAddress From 5090ce6f0abd4a863928cece4ff02cf55a147be2 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 6 Aug 2025 01:45:02 +0200 Subject: [PATCH 396/964] Ignore main.py TerminateeNB mode No pipeline uses it. With the changes in the next commit, pipelines would start to fail. Remove it for simplicity. --- ci-scripts/main.py | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 836f6aee3b..8a52b7cf18 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -469,15 +469,7 @@ if py_param_file_present == True: cwd = os.getcwd() if re.match('^TerminateeNB$', mode, re.IGNORECASE): - if RAN.eNBIPAddress == '' or RAN.eNBUserName == '' or RAN.eNBPassword == '': - HELP.GenericHelp(CONST.Version) - sys.exit('Insufficient Parameter') - if RAN.eNBIPAddress == 'none': - sys.exit(0) - RAN.eNB_instance=0 - RAN.eNB_serverId[0]='0' - RAN.eNBSourceCodePath='/tmp/' - RAN.TerminateeNB(HTML) + logging.warning("Option TerminateeNB ignored") elif re.match('^TerminateHSS$', mode, re.IGNORECASE): logging.warning("Option TerminateHSS ignored") elif re.match('^TerminateMME$', mode, re.IGNORECASE): From 244ea8fc22048051fd7a3f5a28bb6a4a7a5c50e6 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 6 Aug 2025 01:37:47 +0200 Subject: [PATCH 397/964] Use archiveArtifact() for TerminateeNB() --- ci-scripts/main.py | 2 +- ci-scripts/ran.py | 32 ++++++++++++++++++-------------- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 8a52b7cf18..1b06539a2c 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -206,7 +206,7 @@ def ExecuteActionWithParam(action, ctx): RAN.air_interface[RAN.eNB_instance] = 'lte-softmodem' else: RAN.air_interface[RAN.eNB_instance] = air_interface.lower() +'-softmodem' - success = RAN.TerminateeNB(HTML) + success = RAN.TerminateeNB(ctx, HTML) elif action == 'Initialize_UE' or action == 'Attach_UE' or action == 'Detach_UE' or action == 'Terminate_UE' or action == 'CheckStatusUE' or action == 'DataEnable_UE' or action == 'DataDisable_UE': CiTestObj.ue_ids = test.findtext('id').split(' ') diff --git a/ci-scripts/ran.py b/ci-scripts/ran.py index 5c5513a317..48039aa2e7 100644 --- a/ci-scripts/ran.py +++ b/ci-scripts/ran.py @@ -46,6 +46,7 @@ import cls_cmd import sshconnection as SSH import helpreadme as HELP import constants as CONST +from cls_ci_helper import archiveArtifact #----------------------------------------------------------- # Class Declaration @@ -248,7 +249,7 @@ class RANManagement(): logging.debug('\u001B[1m Initialize eNB/gNB Completed\u001B[0m') return enbDidSync - def TerminateeNB(self, HTML): + def TerminateeNB(self, ctx, HTML): if self.eNB_serverId[self.eNB_instance] == '0': lIpAddr = self.eNBIPAddress lUserName = self.eNBUserName @@ -320,13 +321,11 @@ class RANManagement(): fileToAnalyze = self.eNBLogFiles[int(self.eNB_instance)] self.eNBLogFiles[int(self.eNB_instance)] = '' if analyzeFile: - #*stats.log files + pickle + png - mySSH.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/*stats.log', '.') - mySSH.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/*.pickle', '.') - mySSH.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/*.png', '.') - # - copyin_res = mySSH.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/' + fileToAnalyze, '.') - if (copyin_res == -1): + with cls_cmd.getConnection(lIpAddr) as cmd: + file = archiveArtifact(cmd, ctx, lSourcePath + '/cmake_targets/' + fileToAnalyze) + archiveArtifact(cmd, ctx, lSourcePath + '/cmake_targets/nrL1_stats.log') + archiveArtifact(cmd, ctx, lSourcePath + '/cmake_targets/nrMAC_stats.log') + if file is None: logging.debug('\u001B[1;37;41m Could not copy ' + nodeB_prefix + 'NB logfile to analyze it! \u001B[0m') HTML.htmleNBFailureMsg='Could not copy ' + nodeB_prefix + 'NB logfile to analyze it!' HTML.CreateHtmlTestRow('N/A', 'KO', CONST.ENB_PROCESS_NOLOGFILE_TO_ANALYZE) @@ -339,8 +338,8 @@ class RANManagement(): mySSH.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, './nrL1_stats.log', self.eNBSourceCodePath + '/cmake_targets/') mySSH.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, './nrMAC_stats.log', self.eNBSourceCodePath + '/cmake_targets/') mySSH.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, './' + fileToAnalyze, self.eNBSourceCodePath + '/cmake_targets/') - logging.debug('\u001B[1m Analyzing ' + nodeB_prefix + 'NB logfile \u001B[0m ' + fileToAnalyze) - logStatus = self.AnalyzeLogFile_eNB(fileToAnalyze, HTML, self.ran_checkers) + logging.debug('\u001B[1m Analyzing ' + nodeB_prefix + 'NB logfile \u001B[0m ' + file) + logStatus = self.AnalyzeLogFile_eNB(file, HTML, self.ran_checkers) if (logStatus < 0): HTML.CreateHtmlTestRow('N/A', 'KO', logStatus) #display rt stats for gNB only @@ -698,11 +697,16 @@ class RANManagement(): datalog_rt_stats = yaml.load(f,Loader=yaml.FullLoader) rt_keys = datalog_rt_stats['Ref'] #we use the keys from the Ref field - if os.path.isfile('./nrL1_stats.log') and os.path.isfile('./nrMAC_stats.log'): + # nrL1_stats.log/nrMAC_stats.log should be in the same directory as main log file + # currently the link is only implicit as below based on pattern matching + # I will rework this to give the file explicitly + l1_stats_fn = re.sub(r'enb_[0-9]+', 'nrL1_stats', eNBlogFile) + mac_stats_fn = re.sub(r'enb_[0-9]+', 'nrMAC_stats', eNBlogFile) + if os.path.isfile(l1_stats_fn) and os.path.isfile(mac_stats_fn): # don't use CI-nrL1_stats.log, as this will increase the processing time for # no reason, we just need the last occurence - nrL1_stats = open('./nrL1_stats.log', 'r') - nrMAC_stats = open('./nrMAC_stats.log', 'r') + nrL1_stats = open(l1_stats_fn, 'r') + nrMAC_stats = open(mac_stats_fn, 'r') for line in nrL1_stats.readlines(): for k in rt_keys: result = re.search(k, line) @@ -722,7 +726,7 @@ class RANManagement(): nrL1_stats.close() nrMAC_stats.close() else: - logging.debug("NR Stats files for RT analysis not found") + logging.debug(f"NR Stats files for RT analysis not found: {l1_stats_fn}, {mac_stats_fn}") #stdout log file and stat log files analysis completed logging.debug(' File analysis (stdout, stats) completed') From cc0d0ae0ab044f5827a2bde09822e8ef1785dc7d Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 6 Aug 2025 12:07:01 +0200 Subject: [PATCH 398/964] gNB caracal USRP build: don't stop if we can't reboot Sometimes the connection fails because of the reboot. Without may_fail, it would stop the build, which will then run the wrong code, possibly. Instead, continue; if there is a problem with USRP, it will be visible when starting nr-softmodem. --- ci-scripts/xml_files/gnb_usrp_build.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/ci-scripts/xml_files/gnb_usrp_build.xml b/ci-scripts/xml_files/gnb_usrp_build.xml index f67098116b..cd5e91b02f 100644 --- a/ci-scripts/xml_files/gnb_usrp_build.xml +++ b/ci-scripts/xml_files/gnb_usrp_build.xml @@ -47,6 +47,7 @@ Custom_Command Reboot USRP + true caracal ssh root@192.168.20.2 reboot From 40efa2a545dcb5766748d8a2624cd611daf2e558 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 6 Aug 2025 00:51:35 +0200 Subject: [PATCH 399/964] Remove LogCollectBuild step: not used by any pipeline --- ci-scripts/Jenkinsfile-tmp-full-ran | 18 ------------------ ci-scripts/Jenkinsfile-tmp-multi-enb | 18 ------------------ ci-scripts/Jenkinsfile-tmp-multi-enb-nsa | 18 ------------------ ci-scripts/Jenkinsfile-tmp-ran | 18 ------------------ ci-scripts/cls_oaicitest.py | 18 ------------------ ci-scripts/main.py | 7 +------ 6 files changed, 1 insertion(+), 96 deletions(-) diff --git a/ci-scripts/Jenkinsfile-tmp-full-ran b/ci-scripts/Jenkinsfile-tmp-full-ran index f1baa5b04d..3bc1d6ad8e 100644 --- a/ci-scripts/Jenkinsfile-tmp-full-ran +++ b/ci-scripts/Jenkinsfile-tmp-full-ran @@ -216,24 +216,6 @@ pipeline { } stage('Log Collection') { parallel { - stage('Log Collection (eNB - Build)') { - steps { - withCredentials([ - [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password'] - ]) { - echo '\u2705 \u001B[32mLog Collection (eNB - Build)\u001B[0m' - sh "python3 ci-scripts/main.py --mode=LogCollectBuild --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password} --eNBSourceCodePath=${params.eNB_SourceCodePath}" - - echo '\u2705 \u001B[32mLog Transfer (eNB - Build)\u001B[0m' - sh "sshpass -p \'${eNB_Password}\' scp -o 'StrictHostKeyChecking no' -o 'ConnectTimeout 10' ${eNB_Username}@${params.eNB_IPAddress}:${eNB_SourceCodePath}/cmake_targets/build.log.zip ./build.log.${env.BUILD_ID}.zip || true" - } - script { - if(fileExists("build.log.${env.BUILD_ID}.zip")) { - archiveArtifacts "build.log.${env.BUILD_ID}.zip" - } - } - } - } stage('Log Collection (eNB - Run)') { steps { withCredentials([ diff --git a/ci-scripts/Jenkinsfile-tmp-multi-enb b/ci-scripts/Jenkinsfile-tmp-multi-enb index 2680fbe863..7c7397f30b 100644 --- a/ci-scripts/Jenkinsfile-tmp-multi-enb +++ b/ci-scripts/Jenkinsfile-tmp-multi-enb @@ -222,24 +222,6 @@ pipeline { } stage('Log Collection') { parallel { - stage('Log Collection (eNB - Build)') { - steps { - withCredentials([ - [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password'] - ]) { - echo '\u2705 \u001B[32mLog Collection (eNB - Build)\u001B[0m' - sh "python3 ci-scripts/main.py --mode=LogCollectBuild --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password} --eNBSourceCodePath=${params.eNB_SourceCodePath}" - - echo '\u2705 \u001B[32mLog Transfer (eNB - Build)\u001B[0m' - sh "sshpass -p \'${eNB_Password}\' scp -o 'StrictHostKeyChecking no' -o 'ConnectTimeout 10' ${eNB_Username}@${params.eNB_IPAddress}:${eNB_SourceCodePath}/cmake_targets/build.log.zip ./build.log.${env.BUILD_ID}.zip || true" - } - script { - if(fileExists("build.log.${env.BUILD_ID}.zip")) { - archiveArtifacts "build.log.${env.BUILD_ID}.zip" - } - } - } - } stage('Log Collection (eNB - Run)') { steps { withCredentials([ diff --git a/ci-scripts/Jenkinsfile-tmp-multi-enb-nsa b/ci-scripts/Jenkinsfile-tmp-multi-enb-nsa index 5e60b199b4..89daaec8c1 100644 --- a/ci-scripts/Jenkinsfile-tmp-multi-enb-nsa +++ b/ci-scripts/Jenkinsfile-tmp-multi-enb-nsa @@ -210,24 +210,6 @@ pipeline { } stage('Log Collection') { parallel { - stage('Log Collection (eNB - Build)') { - steps { - withCredentials([ - [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password'] - ]) { - echo '\u2705 \u001B[32mLog Collection (eNB - Build)\u001B[0m' - sh "python3 ci-scripts/main.py --mode=LogCollectBuild --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password} --eNBSourceCodePath=${params.eNB_SourceCodePath}" - - echo '\u2705 \u001B[32mLog Transfer (eNB - Build)\u001B[0m' - sh "sshpass -p \'${eNB_Password}\' scp -o 'StrictHostKeyChecking no' -o 'ConnectTimeout 10' ${eNB_Username}@${params.eNB_IPAddress}:${eNB_SourceCodePath}/cmake_targets/build.log.zip ./build.log.${env.BUILD_ID}.zip || true" - } - script { - if(fileExists("build.log.${env.BUILD_ID}.zip")) { - archiveArtifacts "build.log.${env.BUILD_ID}.zip" - } - } - } - } stage('Log Collection (eNB - Run)') { steps { withCredentials([ diff --git a/ci-scripts/Jenkinsfile-tmp-ran b/ci-scripts/Jenkinsfile-tmp-ran index 03c0f9a0cb..82db6641e3 100644 --- a/ci-scripts/Jenkinsfile-tmp-ran +++ b/ci-scripts/Jenkinsfile-tmp-ran @@ -227,24 +227,6 @@ pipeline { } stage('Log Collection') { parallel { - stage('Log Collection (eNB - Build)') { - steps { - withCredentials([ - [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password'] - ]) { - echo '\u2705 \u001B[32mLog Collection (eNB - Build)\u001B[0m' - sh "python3 ci-scripts/main.py --mode=LogCollectBuild --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password} --eNBSourceCodePath=${params.eNB_SourceCodePath}" - - echo '\u2705 \u001B[32mLog Transfer (eNB - Build)\u001B[0m' - sh "sshpass -p \'${eNB_Password}\' scp -o 'StrictHostKeyChecking no' -o 'ConnectTimeout 10' ${eNB_Username}@${params.eNB_IPAddress}:${eNB_SourceCodePath}/cmake_targets/build.log.zip ./build.log.${env.BUILD_ID}.zip || true" - } - script { - if(fileExists("build.log.${env.BUILD_ID}.zip")) { - archiveArtifacts "build.log.${env.BUILD_ID}.zip" - } - } - } - } stage('Log Collection (eNB - Run)') { steps { withCredentials([ diff --git a/ci-scripts/cls_oaicitest.py b/ci-scripts/cls_oaicitest.py index ba322ca608..efdb589cff 100644 --- a/ci-scripts/cls_oaicitest.py +++ b/ci-scripts/cls_oaicitest.py @@ -845,21 +845,3 @@ class OaiCiTest(): message = "Log files:\n" + "\n".join([os.path.basename(l) for l in logs]) HTML.CreateHtmlTestRowQueue(core_name, 'OK', [message]) return True - - def LogCollectBuild(self,RAN): - # Some pipelines are using "none" IP / Credentials - # In that case, just forget about it - if RAN.eNBIPAddress == 'none': - sys.exit(0) - - if (RAN.eNBIPAddress != '' and RAN.eNBUserName != '' and RAN.eNBPassword != ''): - IPAddress = RAN.eNBIPAddress - UserName = RAN.eNBUserName - Password = RAN.eNBPassword - SourceCodePath = RAN.eNBSourceCodePath - else: - sys.exit('Insufficient Parameter') - with cls_cmd.getConnection(IPAddress) as cmd: - d = f'{SourceCodePath}/cmake_targets' - cmd.run(f'rm -f {d}/build.log.zip') - cmd.run(f'cd {d} && zip -r build.log.zip build_log_*/*') diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 1b06539a2c..0fdf538052 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -477,12 +477,7 @@ elif re.match('^TerminateMME$', mode, re.IGNORECASE): elif re.match('^TerminateSPGW$', mode, re.IGNORECASE): logging.warning("Option TerminateSPGW ignored") elif re.match('^LogCollectBuild$', mode, re.IGNORECASE): - if RAN.eNBIPAddress == '' or RAN.eNBUserName == '' or RAN.eNBPassword == '' or RAN.eNBSourceCodePath == '': - logging.warning("nothing to collect (eNBIPAddress/eNBUserName/eNBPassword/eNBSourceCodePath is '')") - sys.exit(0) - if RAN.eNBIPAddress == 'none': - sys.exit(0) - CiTestObj.LogCollectBuild(RAN) + logging.warning("Option LogCollectBuild ignored") elif re.match('^LogCollecteNB$', mode, re.IGNORECASE): if RAN.eNBIPAddress == '' or RAN.eNBUserName == '' or RAN.eNBPassword == '' or RAN.eNBSourceCodePath == '': HELP.GenericHelp(CONST.Version) From 43e2fd57d4054dcc384028e1ea6dc068ef1129da Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 7 Aug 2025 09:01:55 +0200 Subject: [PATCH 400/964] Use Ninja for FHI72 builds --- docker/Dockerfile.build.fhi72.native_arm.ubuntu22 | 2 +- docker/Dockerfile.build.fhi72.rhel9 | 2 +- docker/Dockerfile.build.fhi72.ubuntu22 | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docker/Dockerfile.build.fhi72.native_arm.ubuntu22 b/docker/Dockerfile.build.fhi72.native_arm.ubuntu22 index 4ea1bcd7bb..b796122bf3 100644 --- a/docker/Dockerfile.build.fhi72.native_arm.ubuntu22 +++ b/docker/Dockerfile.build.fhi72.native_arm.ubuntu22 @@ -78,7 +78,7 @@ RUN /bin/sh oaienv && \ cd cmake_targets && \ mkdir -p log && \ ./build_oai \ - --gNB \ + --ninja --gNB \ --build-lib "telnetsrv enbscope uescope nrscope" \ -t oran_fhlib_5g --cmake-opt -Dxran_LOCATION=/opt/phy/fhi_lib/lib \ --build-e2 --cmake-opt -DXAPP_MULTILANGUAGE=OFF --cmake-opt -DKPM_VERSION=$KPM_VERSION --cmake-opt -DE2AP_VERSION=$E2AP_VERSION \ diff --git a/docker/Dockerfile.build.fhi72.rhel9 b/docker/Dockerfile.build.fhi72.rhel9 index b8ad1560ba..472378935d 100644 --- a/docker/Dockerfile.build.fhi72.rhel9 +++ b/docker/Dockerfile.build.fhi72.rhel9 @@ -58,7 +58,7 @@ RUN /bin/sh oaienv && \ mkdir -p log && \ scl enable gcc-toolset-13 "\ ./build_oai \ - --gNB \ + --ninja --gNB \ --build-lib 'telnetsrv enbscope uescope nrscope' \ -t oran_fhlib_5g --cmake-opt -Dxran_LOCATION=/opt/phy/fhi_lib/lib \ --build-e2 --cmake-opt -DKPM_VERSION=$KPM_VERSION --cmake-opt -DE2AP_VERSION=$E2AP_VERSION" &&\ diff --git a/docker/Dockerfile.build.fhi72.ubuntu22 b/docker/Dockerfile.build.fhi72.ubuntu22 index 5da6d0b608..4674648285 100644 --- a/docker/Dockerfile.build.fhi72.ubuntu22 +++ b/docker/Dockerfile.build.fhi72.ubuntu22 @@ -68,7 +68,7 @@ RUN /bin/sh oaienv && \ cd cmake_targets && \ mkdir -p log && \ ./build_oai \ - --gNB \ + --ninja --gNB \ --build-lib "telnetsrv enbscope uescope nrscope" \ -t oran_fhlib_5g --cmake-opt -Dxran_LOCATION=/opt/phy/fhi_lib/lib \ --build-e2 --cmake-opt -DKPM_VERSION=$KPM_VERSION --cmake-opt -DE2AP_VERSION=$E2AP_VERSION \ From 667bcf920c0b384019f6bf57650dc751bd9bcf47 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 7 Aug 2025 15:15:34 +0200 Subject: [PATCH 401/964] Trace analysis results --- ci-scripts/cls_containerize.py | 1 + 1 file changed, 1 insertion(+) diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index 306f9a9a47..34522d9eef 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -100,6 +100,7 @@ def AnalyzeBuildLogs(logfiles, globalStatus): errorandwarnings['errors'] = 0 if committed or tagged else 1 errorandwarnings['warnings'] = 0 errorandwarnings['status'] = committed or tagged + logging.info(f"Analyzing {image}, file {lf}: {errorandwarnings}") files['Target Image Creation'] = errorandwarnings collectInfo[image] = files return collectInfo From 4b8359f11c71e827aa745a94a74e9323664bb1a0 Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 7 Aug 2025 17:57:10 +0200 Subject: [PATCH 402/964] fix for UECAP F1 handling in dora/phytest mode --- openair2/RRC/NR/rrc_gNB_nsa.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/openair2/RRC/NR/rrc_gNB_nsa.c b/openair2/RRC/NR/rrc_gNB_nsa.c index d0cc63062b..aa97a026e0 100644 --- a/openair2/RRC/NR/rrc_gNB_nsa.c +++ b/openair2/RRC/NR/rrc_gNB_nsa.c @@ -77,7 +77,7 @@ // and put it into a CG-ConfigInfo field static int cg_config_info_from_ue_cap_file(uint32_t maxlen, uint8_t buf[maxlen]) { - OCTET_STRING_t *os_cap = NULL; + OCTET_STRING_t *list_buf = NULL; if (uecap_file != NULL) { LOG_I(NR_RRC, "creating CG-ConfigInfo from UE capability file %s\n", uecap_file); @@ -98,8 +98,17 @@ static int cg_config_info_from_ue_cap_file(uint32_t maxlen, uint8_t buf[maxlen]) DevAssert(dec_rval.code == RC_OK); //xer_fprint(stdout, &asn_DEF_NR_UE_NR_Capability, cap); - os_cap = calloc_or_fail(1, sizeof(*os_cap)); - os_cap->size = uper_encode_to_new_buffer(&asn_DEF_NR_UE_NR_Capability, NULL, cap, (void **)&os_cap->buf); + uint8_t *buf = NULL; + int sizebuf = uper_encode_to_new_buffer(&asn_DEF_NR_UE_NR_Capability, NULL, cap, (void **)&buf); + NR_UE_CapabilityRAT_Container_t *cont = calloc_or_fail(1, sizeof(*cont)); + cont->rat_Type = NR_RAT_Type_nr; + cont->ue_CapabilityRAT_Container.buf = buf; + cont->ue_CapabilityRAT_Container.size = sizebuf; + NR_UE_CapabilityRAT_ContainerList_t *clist = calloc_or_fail(1, sizeof(*clist)); + asn1cSeqAdd(&clist->list, cont); + list_buf = calloc_or_fail(1, sizeof(*list_buf)); + list_buf->size = uper_encode_to_new_buffer(&asn_DEF_NR_UE_CapabilityRAT_ContainerList, NULL, clist, (void **)&list_buf->buf); + ASN_STRUCT_FREE(asn_DEF_NR_UE_CapabilityRAT_ContainerList, clist); } NR_CG_ConfigInfo_t *cgci = calloc_or_fail(1, sizeof(*cgci)); @@ -108,7 +117,7 @@ static int cg_config_info_from_ue_cap_file(uint32_t maxlen, uint8_t buf[maxlen]) cgci->criticalExtensions.choice.c1->present = NR_CG_ConfigInfo__criticalExtensions__c1_PR_cg_ConfigInfo; NR_CG_ConfigInfo_IEs_t *cgci_ies = calloc_or_fail(1, sizeof(*cgci_ies)); cgci->criticalExtensions.choice.c1->choice.cg_ConfigInfo = cgci_ies; - cgci_ies->ue_CapabilityInfo = os_cap; + cgci_ies->ue_CapabilityInfo = list_buf; //xer_fprint(stdout, &asn_DEF_NR_CG_ConfigInfo, cgci); asn_enc_rval_t rval = uper_encode_to_buffer(&asn_DEF_NR_CG_ConfigInfo, NULL, cgci, buf, maxlen); From f23b6541322f667fecd919a6ad2e470ed006a106 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 7 Aug 2025 10:56:20 +0200 Subject: [PATCH 403/964] Remove auto-test options in build_oai --- cmake_targets/build_oai | 36 +----------------------------------- 1 file changed, 1 insertion(+), 35 deletions(-) diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index 292e8d0575..a5eee3fe23 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -38,8 +38,6 @@ conf_nvram_path=$OPENAIR_DIR/openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf HW="" VERBOSE_COMPILE=0 -RUN_GROUP=0 -TEST_CASE_GROUP="" BUILD_DIR=ran_build BUILD_DOXYGEN=0 DISABLE_HARDWARE_DEPENDENCY="False" @@ -99,10 +97,6 @@ Options: Selects the transport protocol type, options: None, Ethernet, benetel4g, benetel5g, oran_fhlib_5g, oran_fhlib_5g_mplane, WLS -P | --phy_simulators Makes the unitary tests Layer 1 simulators --s | --check - runs a set of auto-tests based on simulators and several compilation tests ---run-group - runs only specified test cases specified here. This flag is only valid with -s -V | --vcd Adds a debgging facility to the binary files: GUI with major internal synchronization events --verbose-compile @@ -319,15 +313,6 @@ function main() { TARGET_LIST="$TARGET_LIST dlsim ulsim ldpctest polartest smallblocktest nr_pbchsim nr_dlschsim nr_ulschsim nr_dlsim nr_ulsim nr_pucchsim nr_prachsim nr_psbchsim" echo_info "Will compile dlsim, ulsim, ..." shift;; - -s | --check) - OAI_TEST=1 - echo_info "Will run auto-tests" - shift;; - --run-group) - RUN_GROUP=1 - TEST_CASE_GROUP=$2 - echo_info "executing test cases only in group: $TEST_CASE_GROUP" - shift 2;; -V | --vcd) echo_info "Setting gtk-wave output" CMAKE_CMD="$CMAKE_CMD -DENABLE_VCD_FIFO=True" @@ -517,26 +502,7 @@ function main() { fi fi - - ############## - # Auto-tests # - ############## - if [ "$OAI_TEST" = "1" ] ; then - echo_info "The log file for the autotest script for debugging is located here: $OPENAIR_DIR/cmake_targets/autotests/log/autotests.log " - echo_info "The results of autotests results is located here: $OPENAIR_DIR/cmake_targets/autotests/log/results_autotests.xml " - echo_info "You can hit CTRL-C at any time to terminate the autotests..." - rm -fr $OPENAIR_DIR/cmake_targets/autotests/log - mkdir -p $OPENAIR_DIR/cmake_targets/autotests/log - if [ "$RUN_GROUP" -eq "1" ]; then - $OPENAIR_DIR/cmake_targets/autotests/run_exec_autotests.bash -g "$TEST_CASE_GROUP" >& $OPENAIR_DIR/cmake_targets/autotests/log/autotests.log - else - $OPENAIR_DIR/cmake_targets/autotests/run_exec_autotests.bash >& $OPENAIR_DIR/cmake_targets/autotests/log/autotests.log - fi - wait - else - echo_success "BUILD SHOULD BE SUCCESSFUL" - fi - + echo_success "BUILD SHOULD BE SUCCESSFUL" } main "$@" From 20f938d5ae069edd04a3ffb73f90920daa9dbaef Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 7 Aug 2025 11:34:58 +0200 Subject: [PATCH 404/964] Remove useless Doxygen variable --- cmake_targets/build_oai | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index a5eee3fe23..a6112cbf85 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -39,7 +39,6 @@ conf_nvram_path=$OPENAIR_DIR/openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf HW="" VERBOSE_COMPILE=0 BUILD_DIR=ran_build -BUILD_DOXYGEN=0 DISABLE_HARDWARE_DEPENDENCY="False" CMAKE_BUILD_TYPE="RelWithDebInfo" CMAKE_CMD="$CMAKE" @@ -323,9 +322,8 @@ function main() { shift;; --build-doxygen) CMAKE_CMD="$CMAKE_CMD -DGENERATE_DOXYGEN=ON" - TARGET_LIST="$TARGET_LIST doc" - BUILD_DOXYGEN=1 - echo_info "Will build doxygen support" + TARGET_LIST="$TARGET_LIST doc" + echo_info "Will build Doxygen documentation: $DIR/$BUILD_DIR/build/doc/html/index.html" shift;; --enable-LTTNG) CMAKE_CMD="$CMAKE_CMD -DENABLE_LTTNG=ON -DT_TRACER=OFF" @@ -484,12 +482,6 @@ function main() { echo_info "Running \"$CMAKE_CMD\"" eval $CMAKE_CMD compilations $BUILD_DIR all.txt "$TARGET_LIST" "${BUILD_TOOL_OPT}" - ################### - # Doxygen Support # - ################### - if [ "$BUILD_DOXYGEN" = "1" ] ; then - echo_info "Built Doxygen based documentation. The documentation file is located here: $DIR/$BUILD_DIR/build/doc/html/index.html" - fi if [ "$UE" = 1 ] ; then echo_info "Generate LTE USIM default sim content UE specific part" From f3dab10de66198efb04185e4b17885da85b98bbe Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 7 Aug 2025 11:39:07 +0200 Subject: [PATCH 405/964] Remove UE_AUTOTEST_TRACE CMake option This only triggers the build of some dedicated logs that contain information that is logged already, anyways. --- CMakeLists.txt | 1 - cmake_targets/build_oai | 6 ------ openair1/PHY/LTE_UE_TRANSPORT/initial_sync.c | 7 ------- openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 7 ------- openair1/SCHED_UE/phy_procedures_lte_ue.c | 7 ------- 5 files changed, 28 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 667ad2a8b3..898b387237 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -280,7 +280,6 @@ endif() add_boolean_option(TRACE_ASN1C_ENC_DEC OFF "Enable ASN1 encoder/decoder debug traces via OAI logging system" ON) add_boolean_option(T_TRACER True "Activate the T tracer, a debugging/monitoring framework" ON) add_boolean_option(ENABLE_LTTNG False "Activate the LTTNG tracer, a debugging/monitoring framework" ON) -add_boolean_option(UE_AUTOTEST_TRACE False "Activate UE autotest specific logs" ON) add_boolean_option(UE_DEBUG_TRACE False "Activate UE debug trace" ON) add_boolean_option(UE_TIMING_TRACE False "Activate UE timing trace" ON) diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index a6112cbf85..3b43d69911 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -110,8 +110,6 @@ Options: Disables the T tracer. --disable-hardware-dependency Disable HW dependency during installation ---ue-autotest-trace - Enable specific traces for UE autotest framework --ue-trace Enable traces for UE debugging --ue-timing @@ -338,10 +336,6 @@ function main() { echo_info "Disabling hardware dependency for compiling software" DISABLE_HARDWARE_DEPENDENCY="True" shift 1;; - --ue-autotest-trace) - CMAKE_CMD="$CMAKE_CMD -DUE_AUTOTEST_TRACE=True" - echo_info "Enabling autotest specific trace for UE" - shift 1;; --ue-trace) CMAKE_CMD="$CMAKE_CMD -DUE_DEBUG_TRACE=False" echo_info "Enabling UE trace for debug" diff --git a/openair1/PHY/LTE_UE_TRANSPORT/initial_sync.c b/openair1/PHY/LTE_UE_TRANSPORT/initial_sync.c index 2b8a725787..e4a34eb376 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/initial_sync.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/initial_sync.c @@ -482,13 +482,6 @@ int initial_sync(PHY_VARS_UE *ue, runmode_t mode) { LOG_I(PHY, "[UE%d] In synch, rx_offset %d samples\n",ue->Mod_id, ue->rx_offset); if (ue->UE_scan_carrier == 0) { -#if UE_AUTOTEST_TRACE - LOG_I(PHY,"[UE %d] AUTOTEST Cell Sync : frame = %d, rx_offset %d, freq_offset %d \n", - ue->Mod_id, - ue->proc.proc_rxtx[0].frame_rx, - ue->rx_offset, - ue->common_vars.freq_offset ); -#endif // send sync status to higher layers later when timing offset converge to target timing generate_pcfich_reg_mapping(frame_parms); generate_phich_reg_mapping(frame_parms); diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index e31d0491bc..b95c7b8f79 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -1205,13 +1205,6 @@ void pdsch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_ LOG_D(PHY,"[UE %d] Calculating bitrate Frame %d: total_TBS = %d, total_TBS_last = %d, bitrate %f kbits\n", ue->Mod_id,frame_rx,ue->total_TBS[gNB_id], ue->total_TBS_last[gNB_id],(float) ue->bitrate[gNB_id]/1000.0); - -#if UE_AUTOTEST_TRACE - if ((frame_rx % 100 == 0)) { - LOG_I(PHY,"[UE %d] AUTOTEST Metric : UE_DLSCH_BITRATE = %5.2f kbps (frame = %d) \n", ue->Mod_id, (float) ue->bitrate[gNB_id]/1000.0, frame_rx); - } -#endif - } #ifdef EMOS diff --git a/openair1/SCHED_UE/phy_procedures_lte_ue.c b/openair1/SCHED_UE/phy_procedures_lte_ue.c index 0b336fdce6..0e4c59dc0e 100644 --- a/openair1/SCHED_UE/phy_procedures_lte_ue.c +++ b/openair1/SCHED_UE/phy_procedures_lte_ue.c @@ -4320,13 +4320,6 @@ int phy_procedures_slot_parallelization_UE_RX(PHY_VARS_UE *ue, LOG_D(PHY,"[UE %d] Calculating bitrate Frame %d: total_TBS = %d, total_TBS_last = %d, bitrate %f kbits\n", ue->Mod_id,frame_rx,ue->total_TBS[eNB_id], ue->total_TBS_last[eNB_id],(float) ue->bitrate[eNB_id]/1000.0); -#if UE_AUTOTEST_TRACE - - if ((frame_rx % 100 == 0)) { - LOG_I(PHY,"[UE %d] AUTOTEST Metric : UE_DLSCH_BITRATE = %5.2f kbps (frame = %d) \n", ue->Mod_id, (float) ue->bitrate[eNB_id]/1000.0, frame_rx); - } - -#endif } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_OUT); From a42d8183ca34ec3255a93ec73c94f39e1a50a10e Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Fri, 8 Aug 2025 12:32:14 +0200 Subject: [PATCH 406/964] fix a T trace --- openair2/LAYER2/MAC/eNB_scheduler_ulsch.c | 1 + 1 file changed, 1 insertion(+) diff --git a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c index 216ab788d3..1fe2b6967b 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c @@ -1635,6 +1635,7 @@ schedule_ulsch_rnti(module_id_t module_idP, T_INT(subframeP), T_INT(harq_pid), T_INT(mcs), + T_INT(UE_template_ptr->pre_first_nb_rb_ul), T_INT(rb_table[rb_table_index]), T_INT(UE_template_ptr->TBS_UL[harq_pid]), T_INT(ndi)); From a6ccdd1340ae439fe04a7f679f77cc6c36105535 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Fri, 8 Aug 2025 14:58:14 +0200 Subject: [PATCH 407/964] NR UE: fix pdcch llr_size calculation in nr_rx_pdcch() --- openair1/PHY/NR_UE_TRANSPORT/dci_nr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c index bf2d91bdc8..ba641f1d0d 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c @@ -348,7 +348,7 @@ void nr_rx_pdcch(PHY_VARS_NR_UE *ue, const int antRx = frame_parms->nb_antennas_rx; // Pointer to llrs, 4-bit resolution. - int32_t llr_size = (rel15->coreset.duration-rel15->coreset.StartSymbolIndex) * n_rb * RE_PER_RB_OUT_DMRS; + int32_t llr_size = (rel15->coreset.duration + rel15->coreset.StartSymbolIndex) * n_rb * RE_PER_RB_OUT_DMRS; c16_t llr[llr_size]; LOG_D(NR_PHY_DCI, From cb5de9afbba9bb0b863a11ed7735284129f05375 Mon Sep 17 00:00:00 2001 From: Romain Beurdouche Date: Tue, 5 Aug 2025 08:21:49 +0000 Subject: [PATCH 408/964] fix(LDPCImplementation.md): Remove libconfig logs libconfig log do not display anymore by default so we may better not show them in the documentation to avoid any misunderstanding. --- openair1/PHY/CODING/DOC/LDPCImplementation.md | 86 +++---------------- 1 file changed, 13 insertions(+), 73 deletions(-) diff --git a/openair1/PHY/CODING/DOC/LDPCImplementation.md b/openair1/PHY/CODING/DOC/LDPCImplementation.md index d537a8a299..deaf0d16b1 100644 --- a/openair1/PHY/CODING/DOC/LDPCImplementation.md +++ b/openair1/PHY/CODING/DOC/LDPCImplementation.md @@ -17,12 +17,6 @@ loading default `libldpc.so`: ``` ./nr-softmodem -O libconfig:gnb.band78.tm1.106PRB.usrpx300.conf:dbgl5 -....................... -[CONFIG] loader.ldpc.shlibversion set to default value "" -[LIBCONFIG] loader.ldpc: 2/2 parameters successfully set, (2 to default value) -shlib_path libldpc.so -[LOADER] library libldpc.so successfully loaded -........................ ``` `libldpc.so` has its decoder implemented in [nrLDPC_coding_segment_decoder.c](file://../nrLDPC_coding/nrLDPC_coding_segment/nrLDPC_coding_segment_decoder.c).\ @@ -42,18 +36,9 @@ Linking C shared module libldpc_aal.so At runtime, to successfully use LDPC accelerators (e.g., Xilinx T2/Intel ACCs), you will need to install the corresponding drivers and tools. Please refer to the dedicated documentation at [LDPC_OFFLOAD_SETUP.md](file://../../../../doc/LDPC_OFFLOAD_SETUP.md). -`./nr-softmodem -O libconfig:gnb.band78.sa.fr1.106PRB.usrpb210.conf:dbgl5 --rfsim --rfsimulator.serveraddr server --log_config.gtpu_log_level info --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev 01:00.0 --nrLDPC_coding_aal.dpdk_core_list 0-1` - -``` - -....................... -[CONFIG] loader.ldpc.shlibversion set to default value "" -[LIBCONFIG] loader.ldpc: 2/2 parameters successfully set, (1 to default value) -[CONFIG] shlibversion set to _aal from command line -[CONFIG] loader.ldpc 1 options set from command line -shlib_path libldpc_aal.so -[LOADER] library libldpc_aal.so successfully loaded -........................ +<<<<<<< HEAD +``` +./nr-softmodem -O libconfig:gnb.band78.sa.fr1.106PRB.usrpb210.conf:dbgl5 --rfsim --rfsimulator.serveraddr server --log_config.gtpu_log_level info --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev 01:00.0 --nrLDPC_coding_aal.dpdk_core_list 0-1 ``` `libldpc_aal.so` has its decoder and its encoder implemented in [nrLDPC_coding_aal.c](file://../nrLDPC_coding/nrLDPC_coding_aal/nrLDPC_coding_aal.c). @@ -72,18 +57,9 @@ ninja ldpc_xdma At runtime, to successfully use the xdma, you need to install vendor specific drivers and tools.\ Please refer to the dedicated documentation at [LDPC_XDMA_OFFLOAD_SETUP.md](file://../../../../doc/LDPC_XDMA_OFFLOAD_SETUP.md). -`./nr-softmodem -O libconfig:gnb.band78.sa.fr1.106PRB.usrpb210.conf:dbgl5 --rfsim --rfsimulator.serveraddr server --log_config.gtpu_log_level info --loader.ldpc.shlibversion _xdma --nrLDPC_coding_xdma.num_threads_prepare 2` - -``` -....................... -[CONFIG] loader.ldpc.shlibversion set to default value "" -[LIBCONFIG] loader.ldpc: 2/2 parameters successfully set, (1 to default value) -[CONFIG] shlibversion set to _xdma from command line -[CONFIG] loader.ldpc 1 options set from command line -shlib_path libldpc_xdma.so -[LOADER] library libldpc_xdma.so successfully loaded -........................ -``` +``` +./nr-softmodem -O libconfig:gnb.band78.sa.fr1.106PRB.usrpb210.conf:dbgl5 --rfsim --rfsimulator.serveraddr server --log_config.gtpu_log_level info --loader.ldpc.shlibversion _xdma --nrLDPC_coding_xdma.num_threads_prepare 2 +``` `libldpc_xdma.so` has its decoder implemented in [nrLDPC_coding_xdma.c](file://../nrLDPC_coding/nrLDPC_coding_xdma/nrLDPC_coding_xdma.c).\ Its encoder is implemented in [nrLDPC_coding_segment_encoder.c](file://../nrLDPC_coding/nrLDPC_coding_segment/nrLDPC_coding_segment_encoder.c). @@ -125,13 +101,6 @@ loading `libldpc_orig.so` instead of `libldpc.so`: ``` ./nr-softmodem -O libconfig:gnb.band78.tm1.106PRB.usrpx300.conf:dbgl5 --loader.ldpc.shlibversion _orig -....................... -[CONFIG] loader.ldpc.shlibversion set to default value "" -[LIBCONFIG] loader.ldpc: 2/2 parameters successfully set, (1 to default value) -[CONFIG] shlibversion set to _orig from command line -[CONFIG] loader.ldpc 1 options set from command line -[LOADER] library libldpc_orig.so successfully loaded -........................ ``` loading `libldpc_cl.so` instead of `libldpc.so`: @@ -160,11 +129,12 @@ Built target ldpc_cl At runtime, to successfully use hardware acceleration via OpenCL, you need to install vendor specific packages which deliver the required drivers and tools to make use of their GPU (Nvidia, Intel...) , fpga (Xilinx, Intel) or CPU (Intel, AMD, ARM...) through OpenCL. -`./nr-softmodem -O libconfig:gnb.band78.sa.fr1.106PRB.usrpb210.conf:dbgl5 --rfsim --rfsimulator.serveraddr server --log_config.gtpu_log_level info --loader.ldpc.shlibversion _cl` +``` +./nr-softmodem -O libconfig:gnb.band78.sa.fr1.106PRB.usrpb210.conf:dbgl5 --rfsim --rfsimulator.serveraddr server --log_config.gtpu_log_level info --loader.ldpc.shlibversion _cl +``` ``` ------------------------------------------------ -[LOADER] library libldpc_cl.so successfully loaded [HW] Platform 0, OpenCL profile FULL_PROFILE [HW] Platform 0, OpenCL version OpenCL 2.1 LINUX [HW] Device 0 is available @@ -195,13 +165,12 @@ At runtime, to successfully use hardware acceleration via OpenCL, you need to in ----------------------------------------------------------------- ``` -`./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --rfsim -O libconfig:/usr/local/oai/conf/nrue_sim.conf:dbgl5 --loader.ldpc.shlibversion _cl --log_config.hw_log_level info` +``` +./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --rfsim -O libconfig:/usr/local/oai/conf/nrue_sim.conf:dbgl5 --loader.ldpc.shlibversion _cl --log_config.hw_log_level inf +``` ``` ............................................................ -[CONFIG] segment_shlibversion set to _cl from command line -[CONFIG] loader.ldpc 1 options set from command line -[LOADER] library libldpc_cl.so successfully loaded [HW] Platform 0, OpenCL profile FULL_PROFILE [HW] Platform 0, OpenCL version OpenCL 2.1 LINUX [HW] Device 0 is available @@ -240,22 +209,6 @@ Loading libldpc_cuda.so, the cuda implementation of the ldpc decoder: ``` $ ./ldpctest -v _cuda -ldpctest -v _cuda -Initializing random number generator, seed 0 -block length 8448: -n_trials 1: -SNR0 -2.000000: -[CONFIG] get parameters from cmdline , debug flags: 0x00400000 -[CONFIG] log_config: 2/3 parameters successfully set -[CONFIG] log_config: 53/53 parameters successfully set -[CONFIG] log_config: 53/53 parameters successfully set -[CONFIG] log_config: 16/16 parameters successfully set -[CONFIG] log_config: 16/16 parameters successfully set -log init done -[CONFIG] loader: 2/2 parameters successfully set -[CONFIG] loader.ldpc: 2/2 parameters successfully set -[LOADER] library libldpc_cuda.so successfully loaded -................................... ``` @@ -266,20 +219,7 @@ Loading libldpc_cl.so, the opencl implementation of the ldpc decoder: ``` $ ./ldpctest -v _cl -Initializing random number generator, seed 0 -block length 8448: -n_trials 1: -SNR0 -2.000000: -[CONFIG] get parameters from cmdline , debug flags: 0x00400000 -[CONFIG] log_config: 2/3 parameters successfully set -[CONFIG] log_config: 53/53 parameters successfully set -[CONFIG] log_config: 53/53 parameters successfully set -[CONFIG] log_config: 16/16 parameters successfully set -[CONFIG] log_config: 16/16 parameters successfully set -log init done -[CONFIG] loader: 2/2 parameters successfully set -[CONFIG] loader.ldpc: 1/2 parameters successfully set -[LOADER] library libldpc_cl.so successfully loaded +................................ [HW] Platform 0, OpenCL profile FULL_PROFILE [HW] Platform 0, OpenCL version OpenCL 2.1 LINUX [HW] Device 0 is available From eb3bd33fd4a8e120d20f4c46c67989bdcd3495ae Mon Sep 17 00:00:00 2001 From: Romain Beurdouche Date: Tue, 5 Aug 2025 08:26:30 +0000 Subject: [PATCH 409/964] feat(LDPCImplementation.md): Remove ldpc_cl logs Recommended: Remove logs of a library that is not working as far as we know. Pop this commit if this seems not necessary. --- openair1/PHY/CODING/DOC/LDPCImplementation.md | 88 ------------------- 1 file changed, 88 deletions(-) diff --git a/openair1/PHY/CODING/DOC/LDPCImplementation.md b/openair1/PHY/CODING/DOC/LDPCImplementation.md index deaf0d16b1..8a2237f3e6 100644 --- a/openair1/PHY/CODING/DOC/LDPCImplementation.md +++ b/openair1/PHY/CODING/DOC/LDPCImplementation.md @@ -133,74 +133,10 @@ At runtime, to successfully use hardware acceleration via OpenCL, you need to in ./nr-softmodem -O libconfig:gnb.band78.sa.fr1.106PRB.usrpb210.conf:dbgl5 --rfsim --rfsimulator.serveraddr server --log_config.gtpu_log_level info --loader.ldpc.shlibversion _cl ``` -``` ------------------------------------------------- -[HW] Platform 0, OpenCL profile FULL_PROFILE -[HW] Platform 0, OpenCL version OpenCL 2.1 LINUX -[HW] Device 0 is available -[HW] Device 0, type 2 = 0x00000002: cpu -[HW] Device 0, number of Compute Units: 8 -[HW] Device 0, max Work Items dimension: 3 -[HW] Device 0, max Work Items size for dimension: 0 8192 -[HW] Device 0, max Work Items size for dimension: 1 8192 -[HW] Device 0, max Work Items size for dimension: 2 8192 -[New Thread 0x7fffcc258700 (LWP 3945123)] -[New Thread 0x7fffc3e57700 (LWP 3945124)] -[New Thread 0x7fffcbe57700 (LWP 3945125)] -[New Thread 0x7fffcba56700 (LWP 3945126)] -[New Thread 0x7fffcb254700 (LWP 3945128)] -[New Thread 0x7fffcb655700 (LWP 3945127)] -[New Thread 0x7fffcae53700 (LWP 3945129)] -[HW] Platform 1, OpenCL profile FULL_PROFILE -[HW] Platform 1, OpenCL version OpenCL 2.0 beignet 1.3 -[New Thread 0x7fffc965a700 (LWP 3945130)] -[Thread 0x7fffc965a700 (LWP 3945130) exited] -[HW] Device 0 is available -[HW] Device 0, type 4 = 0x00000004: gpu -[HW] Device 0, number of Compute Units: 20 -[HW] Device 0, max Work Items dimension: 3 -[HW] Device 0, max Work Items size for dimension: 0 512 -[HW] Device 0, max Work Items size for dimension: 1 512 -[HW] Device 0, max Work Items size for dimension: 2 512 ------------------------------------------------------------------ -``` - ``` ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --rfsim -O libconfig:/usr/local/oai/conf/nrue_sim.conf:dbgl5 --loader.ldpc.shlibversion _cl --log_config.hw_log_level inf ``` -``` -............................................................ -[HW] Platform 0, OpenCL profile FULL_PROFILE -[HW] Platform 0, OpenCL version OpenCL 2.1 LINUX -[HW] Device 0 is available -[HW] Device 0, type 2 = 0x00000002: cpu -[HW] Device 0, number of Compute Units: 8 -[HW] Device 0, max Work Items dimension: 3 -[HW] Device 0, max Work Items size for dimension: 0 8192 -[HW] Device 0, max Work Items size for dimension: 1 8192 -[HW] Device 0, max Work Items size for dimension: 2 8192 -[New Thread 0x7fffecccc700 (LWP 3945413)] -[New Thread 0x7fffec8cb700 (LWP 3945415)] -[New Thread 0x7fffec4ca700 (LWP 3945414)] -[New Thread 0x7fffdf7fd700 (LWP 3945417)] -[New Thread 0x7fffdfbfe700 (LWP 3945418)] -[New Thread 0x7fffdffff700 (LWP 3945416)] -[New Thread 0x7fffd73fc700 (LWP 3945419)] -[HW] Platform 1, OpenCL profile FULL_PROFILE -[HW] Platform 1, OpenCL version OpenCL 2.0 beignet 1.3 -[New Thread 0x7fffde105700 (LWP 3945420)] -[Thread 0x7fffde105700 (LWP 3945420) exited] -[HW] Device 0 is available -[HW] Device 0, type 4 = 0x00000004: gpu -[HW] Device 0, number of Compute Units: 20 -[HW] Device 0, max Work Items dimension: 3 -[HW] Device 0, max Work Items size for dimension: 0 512 -[HW] Device 0, max Work Items size for dimension: 1 512 -[HW] Device 0, max Work Items size for dimension: 2 512 ------------------------------------------------------------- -``` - A mechanism to select ldpc implementation is also available in the `ldpctest` phy simulator via the `-v` option, which can be used to specify the version of the ldpc shared library to be used. #### Examples of ldpc shared lib selection when running ldpctest: @@ -211,38 +147,14 @@ Loading libldpc_cuda.so, the cuda implementation of the ldpc decoder: $ ./ldpctest -v _cuda ``` - Loading libldpc_cl.so, the opencl implementation of the ldpc decoder: `make ldpc_cl` - ``` $ ./ldpctest -v _cl -................................ -[HW] Platform 0, OpenCL profile FULL_PROFILE -[HW] Platform 0, OpenCL version OpenCL 2.1 LINUX -[HW] Device 0 is available -[HW] Device 0, type 2 = 0x00000002: cpu -[HW] Device 0, number of Compute Units: 8 -[HW] Device 0, max Work Items dimension: 3 -[HW] Device 0, max Work Items size for dimension: 0 8192 -[HW] Device 0, max Work Items size for dimension: 1 8192 -[HW] Device 0, max Work Items size for dimension: 2 8192 -[HW] Platform 1, OpenCL profile FULL_PROFILE -[HW] Platform 1, OpenCL version OpenCL 2.0 beignet 1.3 -[HW] Device 0 is available -[HW] Device 0, type 4 = 0x00000004: gpu -[HW] Device 0, number of Compute Units: 20 -[HW] Device 0, max Work Items dimension: 3 -[HW] Device 0, max Work Items size for dimension: 0 512 -[HW] Device 0, max Work Items size for dimension: 1 512 -[HW] Device 0, max Work Items size for dimension: 2 512 -................................ ``` - - ### LDPC libraries The prototypes for the functions of the interface are defined in [nrLDPC_defs.h](file://nrLDPC_defs.h) as typedefs. Libraries implementing the LDPC algorithms must be named `libldpc<_version>.so`, they must implement four functions with the names and types: From d702bcd657370fe2de01c7529084d2c968f7e586 Mon Sep 17 00:00:00 2001 From: Romain Beurdouche Date: Thu, 7 Aug 2025 09:06:51 +0000 Subject: [PATCH 410/964] fix(LDPCdecoder): Cleanup segment decoder interface Variables 'harq_pid', 'ulsch_id' and 'C' of the segment decoder interface were not used any more by the implementations and set to zero by all the callers. Then it is more relevant and compliant to remove them. --- openair1/PHY/CODING/TESTBENCH/ldpctest.c | 3 --- .../nrLDPC_coding_segment_decoder.c | 3 +-- .../PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c | 3 --- .../CODING/nrLDPC_decoder/nrLDPC_decoder_CL.c | 3 --- .../nrLDPC_decoder_LYC/nrLDPC_decoder_LYC.cu | 3 --- openair1/PHY/CODING/nrLDPC_defs.h | 16 +++++++--------- 6 files changed, 8 insertions(+), 23 deletions(-) diff --git a/openair1/PHY/CODING/TESTBENCH/ldpctest.c b/openair1/PHY/CODING/TESTBENCH/ldpctest.c index 0e0493dcc6..97b39beaf8 100644 --- a/openair1/PHY/CODING/TESTBENCH/ldpctest.c +++ b/openair1/PHY/CODING/TESTBENCH/ldpctest.c @@ -352,9 +352,6 @@ one_measurement_t test_ldpc(short max_iterations, set_abort(&dec_abort, false); n_iter = ldpc_toCompare.LDPCdecoder(&decParams[j], - 0, - 0, - 0, (int8_t *)channel_output_fixed[j], (int8_t *)estimated_output[j], &decoder_profiler, diff --git a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nrLDPC_coding_segment_decoder.c b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nrLDPC_coding_segment_decoder.c index c7bb47c581..3fece46ac8 100644 --- a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nrLDPC_coding_segment_decoder.c +++ b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nrLDPC_coding_segment_decoder.c @@ -215,8 +215,7 @@ static void nr_process_decode_segment(void *arg) ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////// pl =====> llrProcBuf ////////////////////////////////// - int decodeIterations = - LDPCdecoder(p_decoderParms, 0, 0, 0, l, llrProcBuf, p_procTime, rdata->abort_decode); + int decodeIterations = LDPCdecoder(p_decoderParms, l, llrProcBuf, p_procTime, rdata->abort_decode); if (decodeIterations < p_decoderParms->numMaxIter) { memcpy(rdata->c, llrProcBuf, K >> 3); diff --git a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c index e2ed7fce10..d3b9a58da1 100644 --- a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c +++ b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c @@ -170,9 +170,6 @@ int32_t LDPCshutdown() } int32_t LDPCdecoder(t_nrLDPC_dec_params* p_decParams, - uint8_t harq_pid, - uint8_t ulsch_id, - uint8_t C, int8_t* p_llr, int8_t* p_out, t_nrLDPC_time_stats* p_profiler, diff --git a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_CL.c b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_CL.c index 1766c0f072..49e3c80791 100644 --- a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_CL.c +++ b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_CL.c @@ -339,9 +339,6 @@ int32_t LDPCinit() } int32_t LDPCdecoder(t_nrLDPC_dec_params *p_decParams, - uint8_t harq_pid, - uint8_t ulsch_id, - uint8_t C, int8_t *p_llr, int8_t *p_out, t_nrLDPC_time_stats *time_decoder, diff --git a/openair1/PHY/CODING/nrLDPC_decoder_LYC/nrLDPC_decoder_LYC.cu b/openair1/PHY/CODING/nrLDPC_decoder_LYC/nrLDPC_decoder_LYC.cu index aa85716947..9752631fb8 100644 --- a/openair1/PHY/CODING/nrLDPC_decoder_LYC/nrLDPC_decoder_LYC.cu +++ b/openair1/PHY/CODING/nrLDPC_decoder_LYC/nrLDPC_decoder_LYC.cu @@ -506,9 +506,6 @@ extern "C" void LDPCshutdown() } extern "C" int32_t LDPCdecoder(t_nrLDPC_dec_params *p_decParams, - uint8_t harq_pid, - uint8_t ulsch_id, - uint8_t C, int8_t *p_llr, int8_t *p_out, t_nrLDPC_time_stats *, diff --git a/openair1/PHY/CODING/nrLDPC_defs.h b/openair1/PHY/CODING/nrLDPC_defs.h index 2298400078..9abb048d83 100644 --- a/openair1/PHY/CODING/nrLDPC_defs.h +++ b/openair1/PHY/CODING/nrLDPC_defs.h @@ -29,7 +29,7 @@ \brief LDPC encoder parameter structure \var n_segments number of segments in the transport block \var first_seg index of the first segment of the subset to encode - within the transport block + within the transport block \var gen_code flag to generate parity check code 0 -> encoding 1 -> generate parity check code with AVX2 @@ -52,8 +52,8 @@ */ typedef struct { unsigned int n_segments; // optim8seg - unsigned int first_seg; // optim8segmulti - unsigned char gen_code; //orig + unsigned int first_seg; // optim8segmulti + unsigned char gen_code; // orig time_stats_t *tinput; time_stats_t *tprep; time_stats_t *tparity; @@ -75,22 +75,20 @@ typedef struct { typedef int32_t(LDPC_initfunc_t)(void); typedef int32_t(LDPC_shutdownfunc_t)(void); + // decoder interface /** \brief LDPC decoder API type definition \param p_decParams LDPC decoder parameters \param p_llr Input LLRs \param p_llrOut Output vector - \param p_profiler LDPC profiler statistics + \param time_stats time statistics + \param ab structure shared between tasks to stop all the tasks if one fails */ - typedef int32_t(LDPC_decoderfunc_t)(t_nrLDPC_dec_params *p_decParams, - uint8_t harq_pid, - uint8_t ulsch_id, - uint8_t C, int8_t *p_llr, int8_t *p_out, - t_nrLDPC_time_stats *, + t_nrLDPC_time_stats *time_stats, decode_abort_t *ab); typedef int32_t(LDPC_encoderfunc_t)(uint8_t **, uint8_t *, encoder_implemparams_t *); From 8d2df31d7b75a6ddbbec57d3987ffbe8fc132b9e Mon Sep 17 00:00:00 2001 From: Romain Beurdouche Date: Thu, 7 Aug 2025 09:48:02 +0000 Subject: [PATCH 411/964] feat(LDPCImplementation.md): Add short introduction and TOC --- openair1/PHY/CODING/DOC/LDPCImplementation.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openair1/PHY/CODING/DOC/LDPCImplementation.md b/openair1/PHY/CODING/DOC/LDPCImplementation.md index 8a2237f3e6..dd820b2a9b 100644 --- a/openair1/PHY/CODING/DOC/LDPCImplementation.md +++ b/openair1/PHY/CODING/DOC/LDPCImplementation.md @@ -1,4 +1,8 @@ # LDPC coding implementation +This document gives an overview of the different LDPC coding implementations (functional or not) available with Open Air Interface. + +[[_TOC_]] + The LDPC encoder and decoder are implemented in a shared library, dynamically loaded at run-time using the [oai shared library loader](file://../../../../common/utils/DOC/loader.md). Two types of library are available with two different interfaces. There are libraries implementing the encoder and decoder of slots and libraries implementing the encoder and decoder of code segments. From 37bf1deb7d07113702e5886f4202693f9a8a417c Mon Sep 17 00:00:00 2001 From: Romain Beurdouche Date: Thu, 7 Aug 2025 09:49:19 +0000 Subject: [PATCH 412/964] fix(nrLDPC_decoder_LYC): apply clang-format --- .../nrLDPC_decoder_LYC/nrLDPC_decoder_LYC.cu | 64 +++++++++---------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/openair1/PHY/CODING/nrLDPC_decoder_LYC/nrLDPC_decoder_LYC.cu b/openair1/PHY/CODING/nrLDPC_decoder_LYC/nrLDPC_decoder_LYC.cu index 9752631fb8..961fa36579 100644 --- a/openair1/PHY/CODING/nrLDPC_decoder_LYC/nrLDPC_decoder_LYC.cu +++ b/openair1/PHY/CODING/nrLDPC_decoder_LYC/nrLDPC_decoder_LYC.cu @@ -32,10 +32,13 @@ #include "bgs/BG2_I6" #include "bgs/BG2_I7" #define MAX_ITERATION 2 -#define MC 1 +#define MC 1 typedef void decode_abort_t; -#define cudaCheck(ans) { cudaAssert((ans), __FILE__, __LINE__); } +#define cudaCheck(ans) \ + { \ + cudaAssert((ans), __FILE__, __LINE__); \ + } inline void cudaAssert(cudaError_t code, const char *file, int line) { if (code != cudaSuccess) { @@ -44,23 +47,23 @@ inline void cudaAssert(cudaError_t code, const char *file, int line) } } -typedef struct{ +typedef struct { char x; char y; short value; } h_element; #include "bgs/BG1_compact_in_C.h" -__device__ char dev_const_llr[68*384]; -__device__ char dev_dt [46*68*384]; -__device__ char dev_llr[68*384]; -__device__ unsigned char dev_tmp[68*384]; +__device__ char dev_const_llr[68 * 384]; +__device__ char dev_dt[46 * 68 * 384]; +__device__ char dev_llr[68 * 384]; +__device__ unsigned char dev_tmp[68 * 384]; -h_element h_compact1 [46*23] = {}; -h_element h_compact2 [68*30] = {}; +h_element h_compact1[46 * 23] = {}; +h_element h_compact2[68 * 30] = {}; -__device__ h_element dev_h_compact1[46*23]; // used in kernel 1 -__device__ h_element dev_h_compact2[68*30]; // used in kernel 2 +__device__ h_element dev_h_compact1[46 * 23]; // used in kernel 1 +__device__ h_element dev_h_compact2[68 * 30]; // used in kernel 2 // __device__ __constant__ h_element dev_h_compact1[46*23]; // used in kernel 1 // __device__ __constant__ h_element dev_h_compact2[68*30]; // used in kernel 2 @@ -82,13 +85,13 @@ __global__ void warmup() // warm up gpu for time measurement } -extern "C" -void warmup_for_GPU(){ +extern "C" void warmup_for_GPU() +{ warmup<<<20, 1024>>>(); } -extern "C" -void set_compact_BG(int Zc,short BG){ +extern "C" void set_compact_BG(int Zc, short BG) +{ int row, col; if (BG == 1) { row = 46; @@ -162,7 +165,6 @@ void set_compact_BG(int Zc,short BG){ // return 0; } - // Kernel 1 __global__ void ldpc_cnp_kernel_1st_iter(/*char * dev_llr,*/ int BG, int row, int col, int Zc) { @@ -303,8 +305,7 @@ __global__ void ldpc_cnp_kernel(/*char * dev_llr, char * dev_dt,*/ int BG, int r } // Kernel 2: VNP processing -__global__ void -ldpc_vnp_kernel_normal(/*char * dev_llr, char * dev_dt, char * dev_const_llr,*/ int BG, int row, int col, int Zc) +__global__ void ldpc_vnp_kernel_normal(/*char * dev_llr, char * dev_dt, char * dev_const_llr,*/ int BG, int row, int col, int Zc) { int iMCW = blockIdx.y; int iBlkCol = blockIdx.x; @@ -344,7 +345,6 @@ ldpc_vnp_kernel_normal(/*char * dev_llr, char * dev_dt, char * dev_const_llr,*/ dev_llr[iMCW * col * Zc + iCol] = APP; } - __global__ void pack_decoded_bit(/*char *dev, unsigned char *host,*/ int col, int Zc) { __shared__ unsigned char tmp[128]; @@ -440,8 +440,8 @@ void read_BG(int BG, int *h, int row, int col) */ } -extern "C" -void init_LLR_DMA(t_nrLDPC_dec_params* p_decParams, int8_t* p_llr, int8_t* p_out){ +extern "C" void init_LLR_DMA(t_nrLDPC_dec_params *p_decParams, int8_t *p_llr, int8_t *p_out) +{ uint16_t Zc = p_decParams->Z; uint8_t BG = p_decParams->BG; uint8_t col; @@ -456,11 +456,11 @@ void init_LLR_DMA(t_nrLDPC_dec_params* p_decParams, int8_t* p_llr, int8_t* p_out cudaDeviceSynchronize(); } -using namespace std ; +using namespace std; /* from here: entry points in decoder shared lib */ -extern "C" -int ldpc_autoinit(void) { // called by the library loader +extern "C" int ldpc_autoinit(void) +{ // called by the library loader /*int devices = 0; cudaError_t err = cudaGetDeviceCount(&devices); @@ -493,7 +493,7 @@ int ldpc_autoinit(void) { // called by the library loader } */ warmup_for_GPU(); - return 0; + return 0; } extern "C" int32_t LDPCinit() @@ -505,11 +505,11 @@ extern "C" void LDPCshutdown() { } -extern "C" int32_t LDPCdecoder(t_nrLDPC_dec_params *p_decParams, - int8_t *p_llr, - int8_t *p_out, - t_nrLDPC_time_stats *, - decode_abort_t *ab) +extern "C" int32_t LDPCdecoder(t_nrLDPC_dec_params *p_decParams, + int8_t *p_llr, + int8_t *p_out, + t_nrLDPC_time_stats *, + decode_abort_t *ab) { set_compact_BG(p_decParams->Z, p_decParams->BG); init_LLR_DMA(p_decParams, p_llr, p_out); @@ -526,7 +526,7 @@ extern "C" int32_t LDPCdecoder(t_nrLDPC_dec_params *p_decParams, } // alloc memory - unsigned char* hard_decision = (unsigned char*)p_out; + unsigned char *hard_decision = (unsigned char *)p_out; // gpu int memorySize_llr_cuda = col * Zc * sizeof(char) * MC; cudaCheck(cudaMemcpyToSymbol(dev_const_llr, p_llr, memorySize_llr_cuda)); @@ -560,7 +560,7 @@ extern "C" int32_t LDPCdecoder(t_nrLDPC_dec_params *p_decParams, dim3 pack_block(pack, MC, 1); pack_decoded_bit<<>>(/*dev_llr,*/ /*dev_tmp,*/ col, Zc); - cudaCheck(cudaMemcpyFromSymbol((void*)hard_decision, (const void*)dev_tmp, (block_length / 8) * sizeof(unsigned char))); + cudaCheck(cudaMemcpyFromSymbol((void *)hard_decision, (const void *)dev_tmp, (block_length / 8) * sizeof(unsigned char))); cudaDeviceSynchronize(); return MAX_ITERATION; From a2c03f26e9999e0bfc560b79993aaba5af96fd96 Mon Sep 17 00:00:00 2001 From: Romain Beurdouche Date: Thu, 7 Aug 2025 09:50:20 +0000 Subject: [PATCH 413/964] fix(nrLDPC_decoder_CL): Apply clang-format --- .../CODING/nrLDPC_decoder/nrLDPC_decoder_CL.c | 746 ++++++++++-------- 1 file changed, 416 insertions(+), 330 deletions(-) diff --git a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_CL.c b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_CL.c index 49e3c80791..c8d83479a7 100644 --- a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_CL.c +++ b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_CL.c @@ -18,22 +18,21 @@ * For more information about the OpenAirInterface (OAI) Software Alliance: * contact@openairinterface.org */ - /*! \file nrLDPC_decoder_CL.c -* \brief ldpc decoder, openCL implementaion -* \author Francois TABURET -* \date 2021 -* \version 1.0 -* \note initial implem - translation of cuda version -*/ - +/*! \file nrLDPC_decoder_CL.c + * \brief ldpc decoder, openCL implementaion + * \author Francois TABURET + * \date 2021 + * \version 1.0 + * \note initial implem - translation of cuda version + */ #define MAX_ITERATION 2 -#define MC 1 +#define MC 1 -#define MAX_OCLDEV 10 +#define MAX_OCLDEV 10 #define MAX_OCLRUNTIME 5 -typedef struct{ +typedef struct { char x; char y; short value; @@ -51,16 +50,16 @@ typedef struct{ #include "assertions.h" #include "common/utils/LOG/log.h" -#define CLSETKERNELARG(A,B,C,D) \ -rt=clSetKernelArg(A,B,C,D) ;\ -AssertFatal(rt == CL_SUCCESS, "Error %d setting kernel argument index %d\n" , (int)rt, B); +#define CLSETKERNELARG(A, B, C, D) \ + rt = clSetKernelArg(A, B, C, D); \ + AssertFatal(rt == CL_SUCCESS, "Error %d setting kernel argument index %d\n", (int)rt, B); #include "../nrLDPC_decoder_LYC/bgs/BG1_compact_in_C.h" -typedef struct{ +typedef struct { cl_uint max_CU; cl_uint max_WID; - size_t *max_WIS; + size_t *max_WIS; } ocldev_t; typedef struct { @@ -70,7 +69,7 @@ typedef struct { cl_kernel pack_decoded_bit; } oclkernels_t; -typedef struct{ +typedef struct { cl_uint num_devices; cl_device_id devices[MAX_OCLDEV]; ocldev_t ocldev[MAX_OCLDEV]; @@ -81,250 +80,305 @@ typedef struct{ cl_mem dev_const_llr; cl_mem dev_llr; cl_mem dev_dt; - cl_mem dev_tmp; + cl_mem dev_tmp; oclkernels_t kernels[MAX_OCLDEV]; cl_command_queue queue[MAX_OCLDEV]; } oclruntime_t; -typedef struct{ +typedef struct { oclruntime_t runtime[MAX_OCLRUNTIME]; } ocl_t; - - ocl_t ocl; +void set_compact_BG(int Zc, short BG) +{ + cl_uint rt; + int row, col; + if (BG == 1) { + row = 46; + col = 68; + } else { + row = 42; + col = 52; + } + int compact_row = 30; + int compact_col = 19; + if (BG == 2) { + compact_row = 10, compact_col = 23; + } + int memorySize_h_compact1 = row * compact_col * sizeof(h_element); + int memorySize_h_compact2 = compact_row * col * sizeof(h_element); + int lift_index = 0; + short lift_set[][9] = {{2, 4, 8, 16, 32, 64, 128, 256}, + {3, 6, 12, 24, 48, 96, 192, 384}, + {5, 10, 20, 40, 80, 160, 320}, + {7, 14, 28, 56, 112, 224}, + {9, 18, 36, 72, 144, 288}, + {11, 22, 44, 88, 176, 352}, + {13, 26, 52, 104, 208}, + {15, 30, 60, 120, 240}, + {0}}; -void set_compact_BG(int Zc,short BG){ - cl_uint rt; - int row,col; - if(BG == 1){ - row = 46; - col = 68; - } - else{ - row = 42; - col = 52; - } - int compact_row = 30; - int compact_col = 19; - if(BG==2){compact_row = 10, compact_col = 23;} - int memorySize_h_compact1 = row * compact_col * sizeof(h_element); - int memorySize_h_compact2 = compact_row * col * sizeof(h_element); - int lift_index = 0; - short lift_set[][9] = { - {2,4,8,16,32,64,128,256}, - {3,6,12,24,48,96,192,384}, - {5,10,20,40,80,160,320}, - {7,14,28,56,112,224}, - {9,18,36,72,144,288}, - {11,22,44,88,176,352}, - {13,26,52,104,208}, - {15,30,60,120,240}, - {0} - }; - - for(int i = 0; lift_set[i][0] != 0; i++){ - for(int j = 0; lift_set[i][j] != 0; j++){ - if(Zc == lift_set[i][j]){ - lift_index = i; - break; - } - } - } - printf("\nZc = %d BG = %d\n",Zc,BG); - ocl.runtime[0].dev_h_compact1 = clCreateBuffer(ocl.runtime[0].context, CL_MEM_READ_ONLY|CL_MEM_HOST_WRITE_ONLY, memorySize_h_compact1, NULL, (cl_int *)&rt); - AssertFatal(rt == CL_SUCCESS, "Error %d creating buffer dev_h_compact1 for platform %i \n" , (int)rt, 0); - ocl.runtime[0].dev_h_compact2 = clCreateBuffer(ocl.runtime[0].context, CL_MEM_READ_ONLY|CL_MEM_HOST_WRITE_ONLY, memorySize_h_compact2, NULL, (cl_int *)&rt); - AssertFatal(rt == CL_SUCCESS, "Error %d creating buffer dev_h_compact2 for platform %i \n" , (int)rt, 0); - h_element *h1; - h_element *h2; - switch(lift_index){ - case 0: - h1 = host_h_compact1_I0; - h2 = host_h_compact2_I0; - break; - case 1: - h1 = host_h_compact1_I1; - h2 = host_h_compact2_I1; - break; - case 2: - h1 = host_h_compact1_I2; - h2 = host_h_compact2_I2; - break; - case 3: - h1 = host_h_compact1_I3; - h2 = host_h_compact2_I3; - break; - case 4: - h1 = host_h_compact1_I4; - h2 = host_h_compact2_I4; - break; - case 5: - h1 = host_h_compact1_I5; - h2 = host_h_compact2_I5; - break; - case 6: - h1 = host_h_compact1_I6; - h2 = host_h_compact2_I6; - break; - case 7: - h1 = host_h_compact1_I7; - h2 = host_h_compact2_I7; - break; - default: - AssertFatal(0, "Invalid lift_index value %i\n" , lift_index); - break; - } - rt = clEnqueueWriteBuffer(ocl.runtime[0].queue[0], ocl.runtime[0].dev_h_compact1, CL_TRUE, 0,memorySize_h_compact1, h1, 0, NULL, NULL); - AssertFatal(rt == CL_SUCCESS, "Error %d moving h_compact1 memory to pltf %i dev %i\n" , (int)rt, 0,0); - rt = clEnqueueWriteBuffer(ocl.runtime[0].queue[0], ocl.runtime[0].dev_h_compact2, CL_TRUE, 0,memorySize_h_compact2, h2, 0, NULL, NULL); - AssertFatal(rt == CL_SUCCESS, "Error %d moving h_compact2 memory to pltf %i dev %i\n" , (int)rt, 0,0); - // return 0; + for (int i = 0; lift_set[i][0] != 0; i++) { + for (int j = 0; lift_set[i][j] != 0; j++) { + if (Zc == lift_set[i][j]) { + lift_index = i; + break; + } + } + } + printf("\nZc = %d BG = %d\n", Zc, BG); + ocl.runtime[0].dev_h_compact1 = + clCreateBuffer(ocl.runtime[0].context, CL_MEM_READ_ONLY | CL_MEM_HOST_WRITE_ONLY, memorySize_h_compact1, NULL, (cl_int *)&rt); + AssertFatal(rt == CL_SUCCESS, "Error %d creating buffer dev_h_compact1 for platform %i \n", (int)rt, 0); + ocl.runtime[0].dev_h_compact2 = + clCreateBuffer(ocl.runtime[0].context, CL_MEM_READ_ONLY | CL_MEM_HOST_WRITE_ONLY, memorySize_h_compact2, NULL, (cl_int *)&rt); + AssertFatal(rt == CL_SUCCESS, "Error %d creating buffer dev_h_compact2 for platform %i \n", (int)rt, 0); + h_element *h1; + h_element *h2; + switch (lift_index) { + case 0: + h1 = host_h_compact1_I0; + h2 = host_h_compact2_I0; + break; + case 1: + h1 = host_h_compact1_I1; + h2 = host_h_compact2_I1; + break; + case 2: + h1 = host_h_compact1_I2; + h2 = host_h_compact2_I2; + break; + case 3: + h1 = host_h_compact1_I3; + h2 = host_h_compact2_I3; + break; + case 4: + h1 = host_h_compact1_I4; + h2 = host_h_compact2_I4; + break; + case 5: + h1 = host_h_compact1_I5; + h2 = host_h_compact2_I5; + break; + case 6: + h1 = host_h_compact1_I6; + h2 = host_h_compact2_I6; + break; + case 7: + h1 = host_h_compact1_I7; + h2 = host_h_compact2_I7; + break; + default: + AssertFatal(0, "Invalid lift_index value %i\n", lift_index); + break; + } + rt = clEnqueueWriteBuffer(ocl.runtime[0].queue[0], + ocl.runtime[0].dev_h_compact1, + CL_TRUE, + 0, + memorySize_h_compact1, + h1, + 0, + NULL, + NULL); + AssertFatal(rt == CL_SUCCESS, "Error %d moving h_compact1 memory to pltf %i dev %i\n", (int)rt, 0, 0); + rt = clEnqueueWriteBuffer(ocl.runtime[0].queue[0], + ocl.runtime[0].dev_h_compact2, + CL_TRUE, + 0, + memorySize_h_compact2, + h2, + 0, + NULL, + NULL); + AssertFatal(rt == CL_SUCCESS, "Error %d moving h_compact2 memory to pltf %i dev %i\n", (int)rt, 0, 0); + // return 0; } -void cl_error_callback(const char* errinfo, const void* private_info, size_t cb, void* user_data) { +void cl_error_callback(const char *errinfo, const void *private_info, size_t cb, void *user_data) +{ oclruntime_t *runtime = (oclruntime_t *)user_data; - LOG_E(HW,"OpenCL accelerator error %s\n", errinfo ); + LOG_E(HW, "OpenCL accelerator error %s\n", errinfo); } -char *clutil_getstrdev(int intdev) { - static char retstring[255]=""; - char *retptr=retstring; - retptr+=sprintf(retptr,"0x%08x: ",(uint32_t)intdev); +char *clutil_getstrdev(int intdev) +{ + static char retstring[255] = ""; + char *retptr = retstring; + retptr += sprintf(retptr, "0x%08x: ", (uint32_t)intdev); if (intdev & CL_DEVICE_TYPE_CPU) - retptr+=sprintf(retptr,"%s","cpu "); + retptr += sprintf(retptr, "%s", "cpu "); if (intdev & CL_DEVICE_TYPE_GPU) - retptr+=sprintf(retptr,"%s","gpu "); + retptr += sprintf(retptr, "%s", "gpu "); if (intdev & CL_DEVICE_TYPE_ACCELERATOR) - retptr+=sprintf(retptr,"%s","acc "); + retptr += sprintf(retptr, "%s", "acc "); return retstring; } -void get_CompilErr(cl_program program, int pltf) { - - // Determine the size of the log - size_t log_size; - for(int i=0; i0 , "clGetPlatformIDs: no cl compatible platform found\n"); - for (int i=0 ; i<(int)num_platforms_found ; i++) { - char stringval[255]; - rt = clGetPlatformInfo(platforms[i],CL_PLATFORM_PROFILE, sizeof(stringval),stringval,NULL); - AssertFatal(rt == CL_SUCCESS, "clGetPlatformInfo PROFILE error %d\n" , (int)rt); - LOG_I(HW,"Platform %i, OpenCL profile %s\n", i,stringval ); - rt = clGetPlatformInfo(platforms[i],CL_PLATFORM_VERSION, sizeof(stringval),stringval,NULL); - AssertFatal(rt == CL_SUCCESS, "clGetPlatformInfo VERSION error %d\n" , (int)rt); - LOG_I(HW,"Platform %i, OpenCL version %s\n", i,stringval ); - rt = clGetDeviceIDs(platforms[i],CL_DEVICE_TYPE_ALL, sizeof(ocl.runtime[i].devices)/sizeof(cl_device_id),ocl.runtime[i].devices,&(ocl.runtime[i].num_devices)); - AssertFatal(rt == CL_SUCCESS, "clGetDeviceIDs error %d\n" , (int)rt); - int devok=0; - for (int j=0; j 0, "clGetPlatformIDs: no cl compatible platform found\n"); + for (int i = 0; i < (int)num_platforms_found; i++) { + char stringval[255]; + rt = clGetPlatformInfo(platforms[i], CL_PLATFORM_PROFILE, sizeof(stringval), stringval, NULL); + AssertFatal(rt == CL_SUCCESS, "clGetPlatformInfo PROFILE error %d\n", (int)rt); + LOG_I(HW, "Platform %i, OpenCL profile %s\n", i, stringval); + rt = clGetPlatformInfo(platforms[i], CL_PLATFORM_VERSION, sizeof(stringval), stringval, NULL); + AssertFatal(rt == CL_SUCCESS, "clGetPlatformInfo VERSION error %d\n", (int)rt); + LOG_I(HW, "Platform %i, OpenCL version %s\n", i, stringval); + rt = clGetDeviceIDs(platforms[i], + CL_DEVICE_TYPE_ALL, + sizeof(ocl.runtime[i].devices) / sizeof(cl_device_id), + ocl.runtime[i].devices, + &(ocl.runtime[i].num_devices)); + AssertFatal(rt == CL_SUCCESS, "clGetDeviceIDs error %d\n", (int)rt); + int devok = 0; + for (int j = 0; j < ocl.runtime[i].num_devices; j++) { + cl_bool abool; + rt = clGetDeviceInfo(ocl.runtime[i].devices[j], CL_DEVICE_AVAILABLE, sizeof(abool), &abool, NULL); + AssertFatal(rt == CL_SUCCESS, "clGetDeviceInfo DEVICE_AVAILABLE error %d\n", (int)rt); + LOG_I(HW, "Device %i is %s available\n", j, (abool == CL_TRUE ? "" : "not")); + cl_device_type devtype; + rt = clGetDeviceInfo(ocl.runtime[i].devices[j], CL_DEVICE_TYPE, sizeof(cl_device_type), &devtype, NULL); + AssertFatal(rt == CL_SUCCESS, "clGetDeviceInfo DEVICE_TYPE error %d\n", (int)rt); + LOG_I(HW, "Device %i, type %d = %s\n", j, (int)devtype, clutil_getstrdev(devtype)); + rt = clGetDeviceInfo(ocl.runtime[i].devices[j], + CL_DEVICE_MAX_COMPUTE_UNITS, + sizeof(ocl.runtime[i].ocldev[j].max_CU), + &(ocl.runtime[i].ocldev[j].max_CU), + NULL); + AssertFatal(rt == CL_SUCCESS, "clGetDeviceInfo MAX_COMPUTE_UNITS error %d\n", (int)rt); + LOG_I(HW, "Device %i, number of Compute Units: %d\n", j, ocl.runtime[i].ocldev[j].max_CU); + rt = clGetDeviceInfo(ocl.runtime[i].devices[j], + CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, + sizeof(ocl.runtime[i].ocldev[j].max_WID), + &(ocl.runtime[i].ocldev[j].max_WID), + NULL); + AssertFatal(rt == CL_SUCCESS, "clGetDeviceInfo MAX_WORK_ITEM_DIMENSIONS error %d\n", (int)rt); + LOG_I(HW, "Device %i, max Work Items dimension: %d\n", j, ocl.runtime[i].ocldev[j].max_WID); + ocl.runtime[i].ocldev[j].max_WIS = (size_t *)malloc(ocl.runtime[i].ocldev[j].max_WID * sizeof(size_t)); + rt = clGetDeviceInfo(ocl.runtime[i].devices[j], + CL_DEVICE_MAX_WORK_ITEM_SIZES, + sizeof(ocl.runtime[i].ocldev[j].max_WID) * sizeof(size_t), + ocl.runtime[i].ocldev[j].max_WIS, + NULL); + AssertFatal(rt == CL_SUCCESS, "clGetDeviceInfo MAX_WORK_ITEM_SIZES error %d\n", (int)rt); + for (int k = 0; k < ocl.runtime[i].ocldev[j].max_WID; k++) + LOG_I(HW, "Device %i, max Work Items size for dimension: %d %u\n", j, k, (uint32_t)ocl.runtime[i].ocldev[j].max_WIS[k]); + devok++; + } + if (devok > 0) { + ocl.runtime[i].context = clCreateContext(NULL, + ocl.runtime[i].num_devices, + ocl.runtime[i].devices, + cl_error_callback, + &(ocl.runtime[i]), + (cl_int *)&rt); + AssertFatal(rt == CL_SUCCESS, "Error %d creating context for platform %i\n", (int)rt, i); + for (int dev = 0; dev < ocl.runtime[i].num_devices; dev++) { + ocl.runtime[i].queue[dev] = + clCreateCommandQueueWithProperties(ocl.runtime[i].context, ocl.runtime[i].devices[dev], 0, (cl_int *)&rt); + AssertFatal(rt == CL_SUCCESS, "Error %d creating command queue for platform %i device %i\n", (int)rt, i, dev); } - if (devok >0) { - ocl.runtime[i].context = clCreateContext(NULL, ocl.runtime[i].num_devices, ocl.runtime[i].devices, cl_error_callback, &(ocl.runtime[i]), (cl_int *)&rt); - AssertFatal(rt == CL_SUCCESS, "Error %d creating context for platform %i\n" , (int)rt, i); - for(int dev=0; dev0, "No openCL device available to accelerate ldpc\n"); - return 0; + AssertFatal(context_ok > 0, "No openCL device available to accelerate ldpc\n"); + return 0; } int32_t LDPCshutdown() @@ -344,119 +398,151 @@ int32_t LDPCdecoder(t_nrLDPC_dec_params *p_decParams, t_nrLDPC_time_stats *time_decoder, decode_abort_t *ab) { - uint16_t Zc = p_decParams->Z; - uint8_t BG = p_decParams->BG; -// uint8_t numMaxIter = p_decParams->numMaxIter; - int block_length = p_decParams->Kprime; -// e_nrLDPC_outMode outMode = p_decParams->outMode; - uint8_t row,col; - if(BG == 1){ - row = 46; - col = 68; - } - else{ - row = 42; - col = 52; - } + uint16_t Zc = p_decParams->Z; + uint8_t BG = p_decParams->BG; + // uint8_t numMaxIter = p_decParams->numMaxIter; + int block_length = p_decParams->Kprime; + // e_nrLDPC_outMode outMode = p_decParams->outMode; + uint8_t row, col; + if (BG == 1) { + row = 46; + col = 68; + } else { + row = 42; + col = 52; + } -// alloc memory -// unsigned char *hard_decision = (unsigned char*)p_out; -// gpu - int memorySize_llr = col * Zc * sizeof(char) * MC; -// cudaCheck( cudaMemcpyToSymbol(dev_const_llr, p_llr, memorySize_llr_cuda) ); -// cudaCheck( cudaMemcpyToSymbol(dev_llr, p_llr, memorySize_llr_cuda) ); + // alloc memory + // unsigned char *hard_decision = (unsigned char*)p_out; + // gpu + int memorySize_llr = col * Zc * sizeof(char) * MC; + // cudaCheck( cudaMemcpyToSymbol(dev_const_llr, p_llr, memorySize_llr_cuda) ); + // cudaCheck( cudaMemcpyToSymbol(dev_llr, p_llr, memorySize_llr_cuda) ); set_compact_BG(p_decParams->Z, p_decParams->BG); int rt = clEnqueueWriteBuffer(ocl.runtime[0].queue[0], ocl.runtime[0].dev_const_llr, CL_TRUE, 0, memorySize_llr, p_llr, 0, NULL, NULL); - AssertFatal(rt == CL_SUCCESS, "Error %d moving p_llr data to read only memory in pltf %i dev %i\n" , (int)rt, 0,0); - rt = clEnqueueWriteBuffer(ocl.runtime[0].queue[0], ocl.runtime[0].dev_llr, CL_TRUE, 0, - memorySize_llr, p_llr, 0, NULL, NULL); - AssertFatal(rt == CL_SUCCESS, "Error %d moving p_llr data to read-write memory in pltf %i dev %i\n" , (int)rt, 0,0); -// Define CUDA kernel dimension -// int blockSizeX = Zc; -// dim3 dimGridKernel1(row, MC, 1); // dim of the thread blocks -// dim3 dimBlockKernel1(blockSizeX, 1, 1); + AssertFatal(rt == CL_SUCCESS, "Error %d moving p_llr data to read only memory in pltf %i dev %i\n", (int)rt, 0, 0); + rt = clEnqueueWriteBuffer(ocl.runtime[0].queue[0], ocl.runtime[0].dev_llr, CL_TRUE, 0, memorySize_llr, p_llr, 0, NULL, NULL); + AssertFatal(rt == CL_SUCCESS, "Error %d moving p_llr data to read-write memory in pltf %i dev %i\n", (int)rt, 0, 0); + // Define CUDA kernel dimension + // int blockSizeX = Zc; + // dim3 dimGridKernel1(row, MC, 1); // dim of the thread blocks + // dim3 dimBlockKernel1(blockSizeX, 1, 1); -// dim3 dimGridKernel2(col, MC, 1); -// dim3 dimBlockKernel2(blockSizeX, 1, 1); -// cudaDeviceSynchronize(); + // dim3 dimGridKernel2(col, MC, 1); + // dim3 dimBlockKernel2(blockSizeX, 1, 1); + // cudaDeviceSynchronize(); -// lauch kernel - size_t global_item_sizek0[2] = {row*Zc,MC}; // Process the entire lists - size_t global_item_sizek1[2] = {col*Zc,MC}; // Process the entire lists - size_t local_item_sizek[2] = {128,1}; // Divide work items into groups of 128 - - for(int ii = 0; ii < MAX_ITERATION; ii++){ - // first kernel - if(ii == 0){ -// ldpc_cnp_kernel_1st_iter -// <<>> -// ( BG, row, col, Zc); - CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel_1st, 0, sizeof(cl_mem), (void *)&(ocl.runtime[0].dev_llr)); - CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel_1st, 1, sizeof(cl_mem), (void *)&(ocl.runtime[0].dev_dt)); - CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel_1st, 2, sizeof(cl_mem), (void *)&(ocl.runtime[0].dev_h_compact1)); - CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel_1st, 3, sizeof(int), (void *)&(BG)); - CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel_1st, 4, sizeof(int), (void *)&(row)); - CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel_1st, 5, sizeof(int), (void *)&(col)); - CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel_1st, 6, sizeof(int), (void *)&(Zc)); - rt = clEnqueueNDRangeKernel(ocl.runtime[0].queue[0], ocl.runtime[0].kernels[0].cnp_kernel_1st, 2, NULL, - global_item_sizek0, local_item_sizek, 0, NULL, NULL); - AssertFatal(rt == CL_SUCCESS, "Error %d enqueing cnp_kernel_1st \n" , (int)rt); - }else{ -// ldpc_cnp_kernel -// <<>> -// ( BG, row, col, Zc); - CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel, 0, sizeof(cl_mem), (void *)&(ocl.runtime[0].dev_llr)); - CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel, 1, sizeof(cl_mem), (void *)&(ocl.runtime[0].dev_dt)); - CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel, 2, sizeof(cl_mem), (void *)&(ocl.runtime[0].dev_h_compact1)); - CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel, 3, sizeof(int), (void *)&(BG)); - CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel, 4, sizeof(int), (void *)&(row)); - CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel, 5, sizeof(int), (void *)&(col)); - CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel, 6, sizeof(int), (void *)&(Zc)); - rt = clEnqueueNDRangeKernel(ocl.runtime[0].queue[0], ocl.runtime[0].kernels[0].cnp_kernel, 2, NULL, - global_item_sizek0, local_item_sizek, 0, NULL, NULL); - AssertFatal(rt == CL_SUCCESS, "Error %d enqueing cnp_kernel\n" , (int)rt); - } - // second kernel -// ldpc_vnp_kernel_normal -// <<>> -// // (dev_llr, dev_const_llr,BG, row, col, Zc); -// (BG, row, col, Zc); - CLSETKERNELARG(ocl.runtime[0].kernels[0].vnp_kernel_normal, 0, sizeof(cl_mem), (void *)&(ocl.runtime[0].dev_llr)); - CLSETKERNELARG(ocl.runtime[0].kernels[0].vnp_kernel_normal, 1, sizeof(cl_mem), (void *)&(ocl.runtime[0].dev_dt)); - CLSETKERNELARG(ocl.runtime[0].kernels[0].vnp_kernel_normal, 2, sizeof(cl_mem), (void *)&(ocl.runtime[0].dev_const_llr)); - CLSETKERNELARG(ocl.runtime[0].kernels[0].vnp_kernel_normal, 3, sizeof(cl_mem), (void *)&(ocl.runtime[0].dev_h_compact2)); - CLSETKERNELARG(ocl.runtime[0].kernels[0].vnp_kernel_normal, 4, sizeof(int), (void *)&(BG)); - CLSETKERNELARG(ocl.runtime[0].kernels[0].vnp_kernel_normal, 5, sizeof(int), (void *)&(row)); - CLSETKERNELARG(ocl.runtime[0].kernels[0].vnp_kernel_normal, 6, sizeof(int), (void *)&(col)); - CLSETKERNELARG(ocl.runtime[0].kernels[0].vnp_kernel_normal, 7, sizeof(int), (void *)&(Zc)); - rt = clEnqueueNDRangeKernel(ocl.runtime[0].queue[0], ocl.runtime[0].kernels[0].vnp_kernel_normal, 2, NULL, - global_item_sizek1, local_item_sizek, 0, NULL, NULL); - AssertFatal(rt == CL_SUCCESS, "Error %d enqueing vnp_kernel_normal \n" , (int)rt); - } - -// int pack = (block_length/128)+1; -// dim3 pack_block(pack, MC, 1); -// pack_decoded_bit<<>>( col, Zc); - CLSETKERNELARG(ocl.runtime[0].kernels[0].pack_decoded_bit, 0, sizeof(cl_mem), (void *)&(ocl.runtime[0].dev_llr)); - CLSETKERNELARG(ocl.runtime[0].kernels[0].pack_decoded_bit, 1, sizeof(cl_mem), (void *)&(ocl.runtime[0].dev_tmp)); - CLSETKERNELARG(ocl.runtime[0].kernels[0].pack_decoded_bit, 2, sizeof(int), (void *)&(col)); - CLSETKERNELARG(ocl.runtime[0].kernels[0].pack_decoded_bit, 3, sizeof(int), (void *)&(Zc)); - - // Execute the OpenCL kernel on the list - size_t global_item_size[2] = {block_length,MC}; // Process the entire lists - size_t local_item_size[2] = {128,1}; // Divide work items into groups of 128 - rt = clEnqueueNDRangeKernel(ocl.runtime[0].queue[0], ocl.runtime[0].kernels[0].pack_decoded_bit, 2, NULL, - global_item_size, local_item_size, 0, NULL, NULL); - AssertFatal(rt == CL_SUCCESS, "Error %d enqueing pack_decoded_bit \n" , (int)rt); -// cudaCheck( cudaMemcpyFromSymbol((void*)hard_decision, (const void*)dev_tmp, (block_length/8)*sizeof(unsigned char)) ); -// cudaDeviceSynchronize(); - - rt = clEnqueueReadBuffer(ocl.runtime[0].queue[0], ocl.runtime[0].dev_tmp, CL_TRUE, 0, - (block_length/8)*sizeof(unsigned char) , p_llr, 0, NULL, NULL); - AssertFatal(rt == CL_SUCCESS, "Error %d moving p_llr data to pltf %i dev %i\n" , (int)rt, 0,0); - return MAX_ITERATION; - + // lauch kernel + size_t global_item_sizek0[2] = {row * Zc, MC}; // Process the entire lists + size_t global_item_sizek1[2] = {col * Zc, MC}; // Process the entire lists + size_t local_item_sizek[2] = {128, 1}; // Divide work items into groups of 128 + + for (int ii = 0; ii < MAX_ITERATION; ii++) { + // first kernel + if (ii == 0) { + // ldpc_cnp_kernel_1st_iter + // <<>> + // ( BG, row, col, Zc); + CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel_1st, 0, sizeof(cl_mem), (void *)&(ocl.runtime[0].dev_llr)); + CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel_1st, 1, sizeof(cl_mem), (void *)&(ocl.runtime[0].dev_dt)); + CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel_1st, 2, sizeof(cl_mem), (void *)&(ocl.runtime[0].dev_h_compact1)); + CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel_1st, 3, sizeof(int), (void *)&(BG)); + CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel_1st, 4, sizeof(int), (void *)&(row)); + CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel_1st, 5, sizeof(int), (void *)&(col)); + CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel_1st, 6, sizeof(int), (void *)&(Zc)); + rt = clEnqueueNDRangeKernel(ocl.runtime[0].queue[0], + ocl.runtime[0].kernels[0].cnp_kernel_1st, + 2, + NULL, + global_item_sizek0, + local_item_sizek, + 0, + NULL, + NULL); + AssertFatal(rt == CL_SUCCESS, "Error %d enqueing cnp_kernel_1st \n", (int)rt); + } else { + // ldpc_cnp_kernel + // <<>> + // ( BG, row, col, Zc); + CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel, 0, sizeof(cl_mem), (void *)&(ocl.runtime[0].dev_llr)); + CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel, 1, sizeof(cl_mem), (void *)&(ocl.runtime[0].dev_dt)); + CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel, 2, sizeof(cl_mem), (void *)&(ocl.runtime[0].dev_h_compact1)); + CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel, 3, sizeof(int), (void *)&(BG)); + CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel, 4, sizeof(int), (void *)&(row)); + CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel, 5, sizeof(int), (void *)&(col)); + CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel, 6, sizeof(int), (void *)&(Zc)); + rt = clEnqueueNDRangeKernel(ocl.runtime[0].queue[0], + ocl.runtime[0].kernels[0].cnp_kernel, + 2, + NULL, + global_item_sizek0, + local_item_sizek, + 0, + NULL, + NULL); + AssertFatal(rt == CL_SUCCESS, "Error %d enqueing cnp_kernel\n", (int)rt); + } + // second kernel + // ldpc_vnp_kernel_normal + // <<>> + // // (dev_llr, dev_const_llr,BG, row, col, Zc); + // (BG, row, col, Zc); + CLSETKERNELARG(ocl.runtime[0].kernels[0].vnp_kernel_normal, 0, sizeof(cl_mem), (void *)&(ocl.runtime[0].dev_llr)); + CLSETKERNELARG(ocl.runtime[0].kernels[0].vnp_kernel_normal, 1, sizeof(cl_mem), (void *)&(ocl.runtime[0].dev_dt)); + CLSETKERNELARG(ocl.runtime[0].kernels[0].vnp_kernel_normal, 2, sizeof(cl_mem), (void *)&(ocl.runtime[0].dev_const_llr)); + CLSETKERNELARG(ocl.runtime[0].kernels[0].vnp_kernel_normal, 3, sizeof(cl_mem), (void *)&(ocl.runtime[0].dev_h_compact2)); + CLSETKERNELARG(ocl.runtime[0].kernels[0].vnp_kernel_normal, 4, sizeof(int), (void *)&(BG)); + CLSETKERNELARG(ocl.runtime[0].kernels[0].vnp_kernel_normal, 5, sizeof(int), (void *)&(row)); + CLSETKERNELARG(ocl.runtime[0].kernels[0].vnp_kernel_normal, 6, sizeof(int), (void *)&(col)); + CLSETKERNELARG(ocl.runtime[0].kernels[0].vnp_kernel_normal, 7, sizeof(int), (void *)&(Zc)); + rt = clEnqueueNDRangeKernel(ocl.runtime[0].queue[0], + ocl.runtime[0].kernels[0].vnp_kernel_normal, + 2, + NULL, + global_item_sizek1, + local_item_sizek, + 0, + NULL, + NULL); + AssertFatal(rt == CL_SUCCESS, "Error %d enqueing vnp_kernel_normal \n", (int)rt); + } + + // int pack = (block_length/128)+1; + // dim3 pack_block(pack, MC, 1); + // pack_decoded_bit<<>>( col, Zc); + CLSETKERNELARG(ocl.runtime[0].kernels[0].pack_decoded_bit, 0, sizeof(cl_mem), (void *)&(ocl.runtime[0].dev_llr)); + CLSETKERNELARG(ocl.runtime[0].kernels[0].pack_decoded_bit, 1, sizeof(cl_mem), (void *)&(ocl.runtime[0].dev_tmp)); + CLSETKERNELARG(ocl.runtime[0].kernels[0].pack_decoded_bit, 2, sizeof(int), (void *)&(col)); + CLSETKERNELARG(ocl.runtime[0].kernels[0].pack_decoded_bit, 3, sizeof(int), (void *)&(Zc)); + + // Execute the OpenCL kernel on the list + size_t global_item_size[2] = {block_length, MC}; // Process the entire lists + size_t local_item_size[2] = {128, 1}; // Divide work items into groups of 128 + rt = clEnqueueNDRangeKernel(ocl.runtime[0].queue[0], + ocl.runtime[0].kernels[0].pack_decoded_bit, + 2, + NULL, + global_item_size, + local_item_size, + 0, + NULL, + NULL); + AssertFatal(rt == CL_SUCCESS, "Error %d enqueing pack_decoded_bit \n", (int)rt); + // cudaCheck( cudaMemcpyFromSymbol((void*)hard_decision, (const void*)dev_tmp, (block_length/8)*sizeof(unsigned char)) ); + // cudaDeviceSynchronize(); + + rt = clEnqueueReadBuffer(ocl.runtime[0].queue[0], + ocl.runtime[0].dev_tmp, + CL_TRUE, + 0, + (block_length / 8) * sizeof(unsigned char), + p_llr, + 0, + NULL, + NULL); + AssertFatal(rt == CL_SUCCESS, "Error %d moving p_llr data to pltf %i dev %i\n", (int)rt, 0, 0); + return MAX_ITERATION; } -#endif //NRLDPC_KERNEL_SOURCE +#endif // NRLDPC_KERNEL_SOURCE From 4de0e54a3a51c716b5af17e90ebac0cafc36efb8 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Fri, 8 Aug 2025 17:40:29 +0200 Subject: [PATCH 414/964] NR UE: further simplify and optimize the usage of the PDCCH LLR array The initial version of this patch was provided by "Laurent THOMAS " --- openair1/PHY/NR_UE_TRANSPORT/dci_nr.c | 35 ++++++++++++--------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c index ba641f1d0d..b4e2c413cf 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c @@ -70,11 +70,10 @@ // after removing the 3 DMRS RE, the RB contains 9 RE with PDCCH #define RE_PER_RB_OUT_DMRS 9 -static void nr_pdcch_demapping_deinterleaving(c16_t *llr, +static void nr_pdcch_demapping_deinterleaving(uint32_t coreset_nbr_rb, + c16_t llr[][coreset_nbr_rb * RE_PER_RB_OUT_DMRS], c16_t *e_rx, uint8_t coreset_time_dur, - uint8_t start_symbol, - uint32_t coreset_nbr_rb, uint8_t reg_bundle_size_L, uint8_t coreset_interleaver_size_R, uint8_t n_shift, @@ -168,15 +167,14 @@ static void nr_pdcch_demapping_deinterleaving(c16_t *llr, } int rb_count = 0; - const int data_sc = RE_PER_RB_OUT_DMRS; // 9 sub-carriers with data per PRB for (int c_id = 0; c_id < number_of_candidates; c_id++) { - for (int symbol_idx = start_symbol; symbol_idx < start_symbol + coreset_time_dur; symbol_idx++) { + for (int symbol_idx = 0; symbol_idx < coreset_time_dur; symbol_idx++) { for (int cce_count = 0; cce_count < L[c_id]; cce_count++) { for (int k = 0; k < NR_NB_REG_PER_CCE / reg_bundle_size_L; k++) { // loop over REG bundles int f = f_bundle_j_list_ord[c_id][k + NR_NB_REG_PER_CCE * cce_count / reg_bundle_size_L]; - c16_t *in = llr + (f * B_rb + symbol_idx * coreset_nbr_rb) * data_sc; + c16_t *in = llr[symbol_idx] + f * B_rb * RE_PER_RB_OUT_DMRS; // loop over the RBs of the bundle - memcpy(e_rx + data_sc * rb_count, in, B_rb * data_sc * sizeof(*e_rx)); + memcpy(e_rx + RE_PER_RB_OUT_DMRS * rb_count, in, B_rb * RE_PER_RB_OUT_DMRS * sizeof(*e_rx)); rb_count += B_rb; } } @@ -347,18 +345,18 @@ void nr_rx_pdcch(PHY_VARS_NR_UE *ue, get_coreset_rballoc(rel15->coreset.frequency_domain_resource,&n_rb,&rb_offset); const int antRx = frame_parms->nb_antennas_rx; - // Pointer to llrs, 4-bit resolution. - int32_t llr_size = (rel15->coreset.duration + rel15->coreset.StartSymbolIndex) * n_rb * RE_PER_RB_OUT_DMRS; - c16_t llr[llr_size]; + // Pointer to llrs + const int symb_size = n_rb * RE_PER_RB_OUT_DMRS; + c16_t llr[rel15->coreset.duration][symb_size]; LOG_D(NR_PHY_DCI, "pdcch coreset: freq %x, n_rb %d, rb_offset %d\n", rel15->coreset.frequency_domain_resource[0], n_rb, rb_offset); - for (int s = rel15->coreset.StartSymbolIndex; s < rel15->coreset.StartSymbolIndex + rel15->coreset.duration; s++) { + for (int s = 0; s < rel15->coreset.duration; s++) { LOG_D(NR_PHY_DCI, "in nr_pdcch_extract_rbs_single(rxdataF -> rxdataF_ext || dl_ch_estimates -> dl_ch_estimates_ext)\n"); - const int arraySz = ceil_mod(n_rb * RE_PER_RB_OUT_DMRS, 32); + const int arraySz = ceil_mod(symb_size, 32); __attribute__((aligned(32))) c16_t rxdataF_ext[antRx][arraySz]; __attribute__((aligned(32))) c16_t pdcch_dl_ch_estimates_ext[antRx][arraySz]; nr_pdcch_extract_rbs_single(ue->frame_parms.samples_per_slot_wCP, @@ -369,7 +367,7 @@ void nr_rx_pdcch(PHY_VARS_NR_UE *ue, arraySz, rxdataF_ext, pdcch_dl_ch_estimates_ext, - s, + rel15->coreset.StartSymbolIndex + s, frame_parms, rel15->coreset.frequency_domain_resource, rel15->BWPStart); @@ -396,20 +394,19 @@ void nr_rx_pdcch(PHY_VARS_NR_UE *ue, antRx, log2_maxh); // log2_maxh+I0_shift - UEscopeCopy(ue, pdcchRxdataF_comp, rxdataF_comp, sizeof(struct complex16), antRx, n_rb * RE_PER_RB_OUT_DMRS, 0); + UEscopeCopy(ue, pdcchRxdataF_comp, rxdataF_comp, sizeof(struct complex16), antRx, symb_size, 0); if (antRx > 1) nr_pdcch_detection_mrc(arraySz, rxdataF_comp); - nr_pdcch_llr(n_rb * RE_PER_RB_OUT_DMRS, rxdataF_comp[0], llr + s * n_rb * RE_PER_RB_OUT_DMRS); + nr_pdcch_llr(symb_size, rxdataF_comp[0], llr[s]); } - UEscopeCopy(ue, pdcchLlr, llr, sizeof(c16_t), 1, llr_size, 0); + UEscopeCopy(ue, pdcchLlr, llr, sizeof(c16_t), 1, rel15->coreset.duration * symb_size, 0); - nr_pdcch_demapping_deinterleaving(llr, + nr_pdcch_demapping_deinterleaving(n_rb, + llr, pdcch_e_rx, rel15->coreset.duration, - rel15->coreset.StartSymbolIndex, - n_rb, rel15->coreset.RegBundleSize, rel15->coreset.InterleaverSize, rel15->coreset.ShiftIndex, From eb6c195c9b12ccde3475a68d065877026336f08b Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Sat, 9 Aug 2025 07:37:35 +0200 Subject: [PATCH 415/964] NR UE NTN: consider acceleration on orbital path to calculate N_UE_TA_drift_variant MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The acceleration magnitude on the orbital path can be calculated as: t = 2 * pi * r / v omega = 2 * pi / t = v / r acceleration = omega² * r = v² / r Where t is the orbital period, r is the orbital radius, v is the orbital velocity, omega is the angular velocity. The acceleration direction is from the SAT position towards the earth center. To calculate the acceleration towards the UE, this is projected on the direction from the SAT to the UE. --- openair2/LAYER2/NR_MAC_UE/config_ue.c | 17 +++++++++++++++-- openair2/LAYER2/NR_MAC_UE/mac_defs.h | 7 +++++++ openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 2 +- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index f79a5628b7..73bb02a575 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -289,8 +289,17 @@ static void calculate_ue_sat_ta(const position_t *position_params, // calculate SAT velocity towards UE double velocity = (vel_sat.X * dir_sat_ue.X + vel_sat.Y * dir_sat_ue.Y + vel_sat.Z * dir_sat_ue.Z) / distance; + // calculate SAT acceleration towards UE + const double radius_2 = pos_sat.X * pos_sat.X + pos_sat.Y * pos_sat.Y + pos_sat.Z * pos_sat.Z; + const double vel_sat_2 = vel_sat.X * vel_sat.X + vel_sat.Y * vel_sat.Y + vel_sat.Z * vel_sat.Z; + const double acceleration = + -(pos_sat.X * dir_sat_ue.X + pos_sat.Y * dir_sat_ue.Y + pos_sat.Z * dir_sat_ue.Z) * vel_sat_2 / (radius_2 * distance); + + LOG_D(NR_MAC, "Satellite velocity towards UE: %f m/s, acceleration towards UE: %f m/s²\n", velocity, acceleration); + ntn_ta->N_UE_TA_adj = (2 * distance / SPEED_OF_LIGHT) * 1e3; // in ms ntn_ta->N_UE_TA_drift = (2 * -velocity / SPEED_OF_LIGHT) * 1e6; // in µs/s + ntn_ta->N_UE_TA_drift_variant = (2 * acceleration / SPEED_OF_LIGHT) * 1e6; // in µs/s² } // populate ntn_ta structure from mac @@ -321,10 +330,12 @@ static void configure_ntn_ta(module_id_t module_id, LOG_W(NR_MAC, "NR UE currently supports only ephemerisInfo_r17 of type positionVelocity_r17\n"); ntn_ta->N_UE_TA_adj = 0; ntn_ta->N_UE_TA_drift = 0; + ntn_ta->N_UE_TA_drift_variant = 0; } } else { // Need R - Release if not present ntn_ta->N_UE_TA_adj = 0; ntn_ta->N_UE_TA_drift = 0; + ntn_ta->N_UE_TA_drift_variant = 0; } // handle cellSpecificKoffset_r17 @@ -356,7 +367,8 @@ static void configure_ntn_ta(module_id_t module_id, ntn_ta->ntn_params_changed = true; LOG_D(NR_MAC, - "SIB19 Rxd. Epoch SFN: %d, Epoch Subframe: %d, k_offset: %ldms, N_Common_Ta: %fms, drift: %fµs/s, variant %fµs/s², N_UE_TA: %fms, drift: %fµs/s\n", + "SIB19 Rxd. Epoch SFN: %d, Epoch Subframe: %d, k_offset: %ldms, N_Common_Ta: %fms, drift: %fµs/s, variant %fµs/s², " + "N_UE_TA: %fms, drift: %fµs/s, variant %fµs/s²\n", ntn_ta->epoch_sfn, ntn_ta->epoch_subframe, ntn_ta->cell_specific_k_offset, @@ -364,7 +376,8 @@ static void configure_ntn_ta(module_id_t module_id, ntn_ta->N_common_ta_drift, ntn_ta->N_common_ta_drift_variant, ntn_ta->N_UE_TA_adj, - ntn_ta->N_UE_TA_drift); + ntn_ta->N_UE_TA_drift, + ntn_ta->N_UE_TA_drift_variant); } static void config_common_ue(NR_UE_MAC_INST_t *mac, NR_ServingCellConfigCommon_t *scc, int cc_idP) diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index 9abe9751cb..2d88708bfe 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -541,6 +541,8 @@ typedef struct ntn_timing_advance_components { double N_UE_TA_adj; // drift rate of N_UE_TA in µs/s double N_UE_TA_drift; + // change rate of N_UE_TA drift in µs/s² + double N_UE_TA_drift_variant; // cell scheduling offset expressed in terms of 15kHz SCS long cell_specific_k_offset; @@ -674,5 +676,10 @@ static inline double get_total_TA_drift(const ntn_timing_advance_componets_t *nt return ntn_ta->N_common_ta_drift + ntn_ta->N_UE_TA_drift; } +static inline double get_total_TA_drift_variant(const ntn_timing_advance_componets_t *ntn_ta) +{ + return ntn_ta->N_common_ta_drift_variant + ntn_ta->N_UE_TA_drift_variant; +} + /*@}*/ #endif /*__LAYER2_MAC_DEFS_H__ */ diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 76836834f0..b95597a0ba 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -2854,7 +2854,7 @@ static void schedule_ntn_config_command(fapi_nr_dl_config_request_t *dl_config, ntn_config_command_pdu->cell_specific_k_offset = mac->ntn_ta.cell_specific_k_offset; ntn_config_command_pdu->ntn_total_time_advance_ms = get_total_TA_ms(&mac->ntn_ta); ntn_config_command_pdu->ntn_total_time_advance_drift = get_total_TA_drift(&mac->ntn_ta); - ntn_config_command_pdu->ntn_total_time_advance_drift_variant = mac->ntn_ta.N_common_ta_drift_variant; + ntn_config_command_pdu->ntn_total_time_advance_drift_variant = get_total_TA_drift_variant(&mac->ntn_ta); dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_NTN_CONFIG_PARAMS; dl_config->number_pdus += 1; From 0f61fac4a6c0dfa7936ce4a4a24974ea9bd5ba57 Mon Sep 17 00:00:00 2001 From: alexjiao Date: Sun, 6 Jul 2025 19:43:11 +0800 Subject: [PATCH 416/964] NR UE: add support for PDSCH rate matching with NZP CSI-RS Currently only ZP CSI-RS is considered in function configure_ratematching_csi, add support for NZP CSI-RS. --- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 43 ++++++++++++++++++-- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 783ae0489f..a41182daf4 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -284,7 +284,8 @@ static void configure_ratematching_csi(fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsc int slot, int mu, int slots_per_frame, - const NR_PDSCH_Config_t *pdsch_config) + const NR_PDSCH_Config_t *pdsch_config, + NR_CSI_MeasConfig_t *csi_MeasConfig) { // only for C-RNTI, MCS-C-RNTI, CS-RNTI (and only C-RNTI is supported for now) if (rnti_type != TYPE_C_RNTI_) @@ -319,6 +320,25 @@ static void configure_ratematching_csi(fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsc } } + // Handle NZP CSI-RS for rate matching + if (csi_MeasConfig && csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList) { + for (int i = 0; i < csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList->list.count; i++) { + NR_NZP_CSI_RS_Resource_t *nzp_res = csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList->list.array[i]; + if (nzp_res->periodicityAndOffset) { + int period, offset; + csi_period_offset(NULL, nzp_res->periodicityAndOffset, &period, &offset); + if ((frame * slots_per_frame + slot - offset) % period != 0) + continue; + AssertFatal(dlsch_pdu->numCsiRsForRateMatching < NFAPI_MAX_NUM_CSI_RATEMATCH, "csiRsForRateMatching out of bounds\n"); + fapi_nr_dl_config_csirs_pdu_rel15_t *csi_pdu = &dlsch_pdu->csiRsForRateMatching[dlsch_pdu->numCsiRsForRateMatching]; + csi_pdu->csi_type = 1; // NZP CSI-RS + csi_pdu->subcarrier_spacing = mu; + configure_csi_resource_mapping(csi_pdu, &nzp_res->resourceMapping, dlsch_pdu->BWPSize, dlsch_pdu->BWPStart); + dlsch_pdu->numCsiRsForRateMatching++; + } + } + } + for (int i = 0; i < dl_config->number_pdus; i++) { // This assumes that CSI-RS are scheduled before this moment which is true in current implementation const fapi_nr_dl_config_request_pdu_t *csi_req = &dl_config->dl_config_list[i]; @@ -764,8 +784,15 @@ static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac, dlsch_pdu->numCsiRsForRateMatching = 0; int slots_frame = mac->frame_structure.numb_slots_frame; - configure_ratematching_csi(dlsch_pdu, dl_config, rnti_type, frame, slot, dlsch_pdu->SubcarrierSpacing, slots_frame, pdsch_config); - + configure_ratematching_csi(dlsch_pdu, + dl_config, + rnti_type, + frame, + slot, + dlsch_pdu->SubcarrierSpacing, + slots_frame, + pdsch_config, + mac->sc_info.csi_MeasConfig); /* IDENTIFIER_DCI_FORMATS */ /* FREQ_DOM_RESOURCE_ASSIGNMENT_DL */ @@ -1100,7 +1127,15 @@ static int nr_ue_process_dci_dl_11(NR_UE_MAC_INST_t *mac, nr_rnti_type_t rnti_type = get_rnti_type(mac, dci_ind->rnti); dlsch_pdu->numCsiRsForRateMatching = 0; int slots_frame = mac->frame_structure.numb_slots_frame; - configure_ratematching_csi(dlsch_pdu, dl_config, rnti_type, frame, slot, current_DL_BWP->scs, slots_frame, pdsch_Config); + configure_ratematching_csi(dlsch_pdu, + dl_config, + rnti_type, + frame, + slot, + current_DL_BWP->scs, + slots_frame, + pdsch_Config, + mac->sc_info.csi_MeasConfig); /* IDENTIFIER_DCI_FORMATS */ /* CARRIER_IND */ From b9bed5838e5bd64cdf6770fda7f9db24e09bfe45 Mon Sep 17 00:00:00 2001 From: Romain Beurdouche Date: Mon, 11 Aug 2025 08:38:06 +0000 Subject: [PATCH 417/964] feat(ldpc_cl): Remove ldpc_cl --- openair1/PHY/CODING/CMakeLists.txt | 13 - openair1/PHY/CODING/DOC/LDPCImplementation.md | 44 -- .../CODING/nrLDPC_decoder/nrLDPC_decoder_CL.c | 548 ------------------ .../nrLDPC_decoder_kernels_CL.c | 292 ---------- 4 files changed, 897 deletions(-) delete mode 100644 openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_CL.c delete mode 100644 openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_kernels_CL.c diff --git a/openair1/PHY/CODING/CMakeLists.txt b/openair1/PHY/CODING/CMakeLists.txt index e31857a4d5..5b7508fc29 100644 --- a/openair1/PHY/CODING/CMakeLists.txt +++ b/openair1/PHY/CODING/CMakeLists.txt @@ -32,19 +32,6 @@ add_dependencies(nr_ulschsim ldpc ldpc_orig) add_dependencies(nr_dlsim ldpc ldpc_orig) add_dependencies(nr_dlschsim ldpc ldpc_orig) -add_custom_target(nrLDPC_decoder_kernels_CL - COMMAND gcc nrLDPC_decoder/nrLDPC_decoder_CL.c -dD -DNRLDPC_KERNEL_SOURCE -E -o ${CMAKE_CURRENT_BINARY_DIR}/nrLDPC_decoder_kernels_CL.clc - SOURCES nrLDPC_decoder/nrLDPC_decoder_CL.c - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} -) -add_library(ldpc_cl MODULE - nrLDPC_decoder/nrLDPC_decoder_CL.c - nrLDPC_encoder/ldpc_encoder_optim8segmulti.c -) -set_target_properties(ldpc_cl PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) -target_link_libraries(ldpc_cl PRIVATE ldpc_segment OpenCL) -add_dependencies(ldpc_cl nrLDPC_decoder_kernels_CL) - ############################################## # Base CUDA setting ############################################## diff --git a/openair1/PHY/CODING/DOC/LDPCImplementation.md b/openair1/PHY/CODING/DOC/LDPCImplementation.md index dd820b2a9b..0e4a630f4b 100644 --- a/openair1/PHY/CODING/DOC/LDPCImplementation.md +++ b/openair1/PHY/CODING/DOC/LDPCImplementation.md @@ -107,40 +107,6 @@ loading `libldpc_orig.so` instead of `libldpc.so`: ./nr-softmodem -O libconfig:gnb.band78.tm1.106PRB.usrpx300.conf:dbgl5 --loader.ldpc.shlibversion _orig ``` -loading `libldpc_cl.so` instead of `libldpc.so`: - -`make ldpc_cl` - -This command creates the `libldpc_cl.so` shared library. To perform this build successfully, only the OpenCL header `/usr/include/CL/opencl.h` and library `/usr/lib/x86_64-linux-gnu/libOpenCL.so` are required, they implement OpenCL API support which is not hardware dependent. - -``` -Scanning dependencies of target nrLDPC_decoder_kernels_CL -Built target nrLDPC_decoder_kernels_CL -Scanning dependencies of target ldpc_cl -Building C object CMakeFiles/ldpc_cl.dir/usr/local/oai/oai-develop/openairinterface5g/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_CL.c.o -In file included from /usr/include/CL/cl.h:32, - from /usr/include/CL/opencl.h:38, - from /usr/local/oai/oai-develop/openairinterface5g/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_CL.c:49: -/usr/include/CL/cl_version.h:34:9: note: #pragma message: cl_version.h: CL_TARGET_OPENCL_VERSION is not defined. Defaulting to 220 (OpenCL 2.2) - #pragma message("cl_version.h: CL_TARGET_OPENCL_VERSION is not defined. Defaulting to 220 (OpenCL 2.2)") - ^~~~~~~ - -Building C object CMakeFiles/ldpc_cl.dir/usr/local/oai/oai-develop/openairinterface5g/openair1/PHY/CODING/nrLDPC_encoder/ldpc_encoder_optim8segmulti.c.o -Linking C shared module libldpc_cl.so -Built target ldpc_cl - -``` - -At runtime, to successfully use hardware acceleration via OpenCL, you need to install vendor specific packages which deliver the required drivers and tools to make use of their GPU (Nvidia, Intel...) , fpga (Xilinx, Intel) or CPU (Intel, AMD, ARM...) through OpenCL. - -``` -./nr-softmodem -O libconfig:gnb.band78.sa.fr1.106PRB.usrpb210.conf:dbgl5 --rfsim --rfsimulator.serveraddr server --log_config.gtpu_log_level info --loader.ldpc.shlibversion _cl -``` - -``` -./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --rfsim -O libconfig:/usr/local/oai/conf/nrue_sim.conf:dbgl5 --loader.ldpc.shlibversion _cl --log_config.hw_log_level inf -``` - A mechanism to select ldpc implementation is also available in the `ldpctest` phy simulator via the `-v` option, which can be used to specify the version of the ldpc shared library to be used. #### Examples of ldpc shared lib selection when running ldpctest: @@ -151,14 +117,6 @@ Loading libldpc_cuda.so, the cuda implementation of the ldpc decoder: $ ./ldpctest -v _cuda ``` -Loading libldpc_cl.so, the opencl implementation of the ldpc decoder: - -`make ldpc_cl` - -``` -$ ./ldpctest -v _cl -``` - ### LDPC libraries The prototypes for the functions of the interface are defined in [nrLDPC_defs.h](file://nrLDPC_defs.h) as typedefs. Libraries implementing the LDPC algorithms must be named `libldpc<_version>.so`, they must implement four functions with the names and types: @@ -169,6 +127,4 @@ Libraries implementing the LDPC algorithms must be named `libldpc<_version>.so`, `libldpc_cuda.so` has been tested with the `ldpctest` executable, usage from the softmodem's has to be tested. -`libldpc_cl.so` is under development. - [oai Wikis home](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/home) diff --git a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_CL.c b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_CL.c deleted file mode 100644 index c8d83479a7..0000000000 --- a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_CL.c +++ /dev/null @@ -1,548 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.0 (the "License"); you may not use this file - * except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.openairinterface.org/?page_id=698 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ -/*! \file nrLDPC_decoder_CL.c - * \brief ldpc decoder, openCL implementaion - * \author Francois TABURET - * \date 2021 - * \version 1.0 - * \note initial implem - translation of cuda version - */ - -#define MAX_ITERATION 2 -#define MC 1 - -#define MAX_OCLDEV 10 -#define MAX_OCLRUNTIME 5 - -typedef struct { - char x; - char y; - short value; -} h_element; - -#ifdef NRLDPC_KERNEL_SOURCE -#include "nrLDPC_decoder_kernels_CL.c" -#else -/* uses HW component id for log messages ( --log_config.hw_log_level ) */ -#include -#include -#include -#include -#include "openair1/PHY/CODING/nrLDPC_extern.h" -#include "assertions.h" -#include "common/utils/LOG/log.h" - -#define CLSETKERNELARG(A, B, C, D) \ - rt = clSetKernelArg(A, B, C, D); \ - AssertFatal(rt == CL_SUCCESS, "Error %d setting kernel argument index %d\n", (int)rt, B); - -#include "../nrLDPC_decoder_LYC/bgs/BG1_compact_in_C.h" - -typedef struct { - cl_uint max_CU; - cl_uint max_WID; - size_t *max_WIS; -} ocldev_t; - -typedef struct { - cl_kernel cnp_kernel_1st; - cl_kernel cnp_kernel; - cl_kernel vnp_kernel_normal; - cl_kernel pack_decoded_bit; -} oclkernels_t; - -typedef struct { - cl_uint num_devices; - cl_device_id devices[MAX_OCLDEV]; - ocldev_t ocldev[MAX_OCLDEV]; - cl_context context; - cl_program program; - cl_mem dev_h_compact1; - cl_mem dev_h_compact2; - cl_mem dev_const_llr; - cl_mem dev_llr; - cl_mem dev_dt; - cl_mem dev_tmp; - oclkernels_t kernels[MAX_OCLDEV]; - cl_command_queue queue[MAX_OCLDEV]; -} oclruntime_t; - -typedef struct { - oclruntime_t runtime[MAX_OCLRUNTIME]; -} ocl_t; - -ocl_t ocl; - -void set_compact_BG(int Zc, short BG) -{ - cl_uint rt; - int row, col; - if (BG == 1) { - row = 46; - col = 68; - } else { - row = 42; - col = 52; - } - int compact_row = 30; - int compact_col = 19; - if (BG == 2) { - compact_row = 10, compact_col = 23; - } - int memorySize_h_compact1 = row * compact_col * sizeof(h_element); - int memorySize_h_compact2 = compact_row * col * sizeof(h_element); - int lift_index = 0; - short lift_set[][9] = {{2, 4, 8, 16, 32, 64, 128, 256}, - {3, 6, 12, 24, 48, 96, 192, 384}, - {5, 10, 20, 40, 80, 160, 320}, - {7, 14, 28, 56, 112, 224}, - {9, 18, 36, 72, 144, 288}, - {11, 22, 44, 88, 176, 352}, - {13, 26, 52, 104, 208}, - {15, 30, 60, 120, 240}, - {0}}; - - for (int i = 0; lift_set[i][0] != 0; i++) { - for (int j = 0; lift_set[i][j] != 0; j++) { - if (Zc == lift_set[i][j]) { - lift_index = i; - break; - } - } - } - printf("\nZc = %d BG = %d\n", Zc, BG); - ocl.runtime[0].dev_h_compact1 = - clCreateBuffer(ocl.runtime[0].context, CL_MEM_READ_ONLY | CL_MEM_HOST_WRITE_ONLY, memorySize_h_compact1, NULL, (cl_int *)&rt); - AssertFatal(rt == CL_SUCCESS, "Error %d creating buffer dev_h_compact1 for platform %i \n", (int)rt, 0); - ocl.runtime[0].dev_h_compact2 = - clCreateBuffer(ocl.runtime[0].context, CL_MEM_READ_ONLY | CL_MEM_HOST_WRITE_ONLY, memorySize_h_compact2, NULL, (cl_int *)&rt); - AssertFatal(rt == CL_SUCCESS, "Error %d creating buffer dev_h_compact2 for platform %i \n", (int)rt, 0); - h_element *h1; - h_element *h2; - switch (lift_index) { - case 0: - h1 = host_h_compact1_I0; - h2 = host_h_compact2_I0; - break; - case 1: - h1 = host_h_compact1_I1; - h2 = host_h_compact2_I1; - break; - case 2: - h1 = host_h_compact1_I2; - h2 = host_h_compact2_I2; - break; - case 3: - h1 = host_h_compact1_I3; - h2 = host_h_compact2_I3; - break; - case 4: - h1 = host_h_compact1_I4; - h2 = host_h_compact2_I4; - break; - case 5: - h1 = host_h_compact1_I5; - h2 = host_h_compact2_I5; - break; - case 6: - h1 = host_h_compact1_I6; - h2 = host_h_compact2_I6; - break; - case 7: - h1 = host_h_compact1_I7; - h2 = host_h_compact2_I7; - break; - default: - AssertFatal(0, "Invalid lift_index value %i\n", lift_index); - break; - } - rt = clEnqueueWriteBuffer(ocl.runtime[0].queue[0], - ocl.runtime[0].dev_h_compact1, - CL_TRUE, - 0, - memorySize_h_compact1, - h1, - 0, - NULL, - NULL); - AssertFatal(rt == CL_SUCCESS, "Error %d moving h_compact1 memory to pltf %i dev %i\n", (int)rt, 0, 0); - rt = clEnqueueWriteBuffer(ocl.runtime[0].queue[0], - ocl.runtime[0].dev_h_compact2, - CL_TRUE, - 0, - memorySize_h_compact2, - h2, - 0, - NULL, - NULL); - AssertFatal(rt == CL_SUCCESS, "Error %d moving h_compact2 memory to pltf %i dev %i\n", (int)rt, 0, 0); - // return 0; -} -void cl_error_callback(const char *errinfo, const void *private_info, size_t cb, void *user_data) -{ - oclruntime_t *runtime = (oclruntime_t *)user_data; - LOG_E(HW, "OpenCL accelerator error %s\n", errinfo); -} - -char *clutil_getstrdev(int intdev) -{ - static char retstring[255] = ""; - char *retptr = retstring; - retptr += sprintf(retptr, "0x%08x: ", (uint32_t)intdev); - if (intdev & CL_DEVICE_TYPE_CPU) - retptr += sprintf(retptr, "%s", "cpu "); - if (intdev & CL_DEVICE_TYPE_GPU) - retptr += sprintf(retptr, "%s", "gpu "); - if (intdev & CL_DEVICE_TYPE_ACCELERATOR) - retptr += sprintf(retptr, "%s", "acc "); - return retstring; -} - -void get_CompilErr(cl_program program, int pltf) -{ - // Determine the size of the log - size_t log_size; - for (int i = 0; i < ocl.runtime[pltf].num_devices; i++) { - clGetProgramBuildInfo(program, ocl.runtime[pltf].devices[i], CL_PROGRAM_BUILD_LOG, 0, NULL, &log_size); - // Allocate memory for the log - char *log = (char *)malloc(log_size); - // Get the log - clGetProgramBuildInfo(program, ocl.runtime[pltf].devices[i], CL_PROGRAM_BUILD_LOG, log_size, log, NULL); - // Print the log - printf("%s\n", log); - free(log); - } -} - -size_t load_source(char **source_str, char *filename) -{ - FILE *fp; - struct stat st; - size_t source_size; - char *src = NULL; - - if (filename == NULL) { - src = "nrLDPC_decoder_kernels_CL.clc"; - } else { - src = filename; - } - fp = fopen(src, "r"); - AssertFatal(fp, "failed to open cl source %s: %s\n", src, strerror(errno)); - - fstat(fileno(fp), &st); - source_size = st.st_size; - *source_str = (char *)malloc(source_size); - source_size = fread(*source_str, 1, source_size, fp); - fclose(fp); - LOG_I(HW, "Loaded kernel sources from %s %u bytes\n", (filename == NULL) ? "embedded cl code" : src, (unsigned int)source_size); - return source_size; -} - -/* from here: entry points in decoder shared lib */ -int ldpc_autoinit(void) -{ // called by the library loader - cl_platform_id platforms[10]; - cl_uint num_platforms_found; - int context_ok = 0; - cl_uint rt = clGetPlatformIDs(sizeof(platforms) / sizeof(cl_platform_id), platforms, &num_platforms_found); - AssertFatal(rt == CL_SUCCESS, "clGetPlatformIDs error %d\n", (int)rt); - AssertFatal(num_platforms_found > 0, "clGetPlatformIDs: no cl compatible platform found\n"); - for (int i = 0; i < (int)num_platforms_found; i++) { - char stringval[255]; - rt = clGetPlatformInfo(platforms[i], CL_PLATFORM_PROFILE, sizeof(stringval), stringval, NULL); - AssertFatal(rt == CL_SUCCESS, "clGetPlatformInfo PROFILE error %d\n", (int)rt); - LOG_I(HW, "Platform %i, OpenCL profile %s\n", i, stringval); - rt = clGetPlatformInfo(platforms[i], CL_PLATFORM_VERSION, sizeof(stringval), stringval, NULL); - AssertFatal(rt == CL_SUCCESS, "clGetPlatformInfo VERSION error %d\n", (int)rt); - LOG_I(HW, "Platform %i, OpenCL version %s\n", i, stringval); - rt = clGetDeviceIDs(platforms[i], - CL_DEVICE_TYPE_ALL, - sizeof(ocl.runtime[i].devices) / sizeof(cl_device_id), - ocl.runtime[i].devices, - &(ocl.runtime[i].num_devices)); - AssertFatal(rt == CL_SUCCESS, "clGetDeviceIDs error %d\n", (int)rt); - int devok = 0; - for (int j = 0; j < ocl.runtime[i].num_devices; j++) { - cl_bool abool; - rt = clGetDeviceInfo(ocl.runtime[i].devices[j], CL_DEVICE_AVAILABLE, sizeof(abool), &abool, NULL); - AssertFatal(rt == CL_SUCCESS, "clGetDeviceInfo DEVICE_AVAILABLE error %d\n", (int)rt); - LOG_I(HW, "Device %i is %s available\n", j, (abool == CL_TRUE ? "" : "not")); - cl_device_type devtype; - rt = clGetDeviceInfo(ocl.runtime[i].devices[j], CL_DEVICE_TYPE, sizeof(cl_device_type), &devtype, NULL); - AssertFatal(rt == CL_SUCCESS, "clGetDeviceInfo DEVICE_TYPE error %d\n", (int)rt); - LOG_I(HW, "Device %i, type %d = %s\n", j, (int)devtype, clutil_getstrdev(devtype)); - rt = clGetDeviceInfo(ocl.runtime[i].devices[j], - CL_DEVICE_MAX_COMPUTE_UNITS, - sizeof(ocl.runtime[i].ocldev[j].max_CU), - &(ocl.runtime[i].ocldev[j].max_CU), - NULL); - AssertFatal(rt == CL_SUCCESS, "clGetDeviceInfo MAX_COMPUTE_UNITS error %d\n", (int)rt); - LOG_I(HW, "Device %i, number of Compute Units: %d\n", j, ocl.runtime[i].ocldev[j].max_CU); - rt = clGetDeviceInfo(ocl.runtime[i].devices[j], - CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, - sizeof(ocl.runtime[i].ocldev[j].max_WID), - &(ocl.runtime[i].ocldev[j].max_WID), - NULL); - AssertFatal(rt == CL_SUCCESS, "clGetDeviceInfo MAX_WORK_ITEM_DIMENSIONS error %d\n", (int)rt); - LOG_I(HW, "Device %i, max Work Items dimension: %d\n", j, ocl.runtime[i].ocldev[j].max_WID); - ocl.runtime[i].ocldev[j].max_WIS = (size_t *)malloc(ocl.runtime[i].ocldev[j].max_WID * sizeof(size_t)); - rt = clGetDeviceInfo(ocl.runtime[i].devices[j], - CL_DEVICE_MAX_WORK_ITEM_SIZES, - sizeof(ocl.runtime[i].ocldev[j].max_WID) * sizeof(size_t), - ocl.runtime[i].ocldev[j].max_WIS, - NULL); - AssertFatal(rt == CL_SUCCESS, "clGetDeviceInfo MAX_WORK_ITEM_SIZES error %d\n", (int)rt); - for (int k = 0; k < ocl.runtime[i].ocldev[j].max_WID; k++) - LOG_I(HW, "Device %i, max Work Items size for dimension: %d %u\n", j, k, (uint32_t)ocl.runtime[i].ocldev[j].max_WIS[k]); - devok++; - } - if (devok > 0) { - ocl.runtime[i].context = clCreateContext(NULL, - ocl.runtime[i].num_devices, - ocl.runtime[i].devices, - cl_error_callback, - &(ocl.runtime[i]), - (cl_int *)&rt); - AssertFatal(rt == CL_SUCCESS, "Error %d creating context for platform %i\n", (int)rt, i); - for (int dev = 0; dev < ocl.runtime[i].num_devices; dev++) { - ocl.runtime[i].queue[dev] = - clCreateCommandQueueWithProperties(ocl.runtime[i].context, ocl.runtime[i].devices[dev], 0, (cl_int *)&rt); - AssertFatal(rt == CL_SUCCESS, "Error %d creating command queue for platform %i device %i\n", (int)rt, i, dev); - } - ocl.runtime[i].dev_const_llr = - clCreateBuffer(ocl.runtime[i].context, CL_MEM_READ_ONLY | CL_MEM_HOST_WRITE_ONLY, 68 * 384, NULL, (cl_int *)&rt); - AssertFatal(rt == CL_SUCCESS, "Error %d creating buffer dev_const_llr for platform %i \n", (int)rt, i); - ocl.runtime[i].dev_llr = - clCreateBuffer(ocl.runtime[i].context, CL_MEM_READ_WRITE | CL_MEM_HOST_WRITE_ONLY, 68 * 384, NULL, (cl_int *)&rt); - AssertFatal(rt == CL_SUCCESS, "Error %d creating buffer dev_llr for platform %i \n", (int)rt, i); - ocl.runtime[i].dev_dt = - clCreateBuffer(ocl.runtime[i].context, CL_MEM_READ_WRITE | CL_MEM_HOST_NO_ACCESS, 46 * 68 * 384, NULL, (cl_int *)&rt); - AssertFatal(rt == CL_SUCCESS, "Error %d creating buffer dev_dt for platform %i \n", (int)rt, i); - ocl.runtime[i].dev_tmp = - clCreateBuffer(ocl.runtime[i].context, CL_MEM_READ_ONLY | CL_MEM_HOST_WRITE_ONLY, 68 * 384, NULL, (cl_int *)&rt); - AssertFatal(rt == CL_SUCCESS, "Error %d creating buffer dev_tmp for platform %i \n", (int)rt, i); - char *source_str; - size_t source_size = load_source(&source_str, "nrLDPC_decoder_kernels_CL.clc"); - cl_program program = clCreateProgramWithSource(ocl.runtime[i].context, - 1, - (const char **)&source_str, - (const size_t *)&source_size, - (cl_int *)&rt); - AssertFatal(rt == CL_SUCCESS, "Error %d creating program for platform %i \n", (int)rt, i); - rt = clBuildProgram(program, ocl.runtime[i].num_devices, ocl.runtime[i].devices, NULL /* compile options */, NULL, NULL); - if (rt == CL_BUILD_PROGRAM_FAILURE) { - get_CompilErr(program, i); - } - AssertFatal(rt == CL_SUCCESS, "Error %d buildding program for platform %i \n", rt, i); - - for (int dev = 0; dev < ocl.runtime[i].num_devices; dev++) { - ocl.runtime[i].kernels[dev].cnp_kernel_1st = clCreateKernel(program, "ldpc_cnp_kernel_1st_iter", (cl_int *)&rt); - AssertFatal(rt == CL_SUCCESS, - "Error %d creating kernel %s platform %i, dev %i\n", - (int)rt, - "ldpc_cnp_kernel_1st_iter", - i, - dev); - ocl.runtime[i].kernels[dev].cnp_kernel = clCreateKernel(program, "ldpc_cnp_kernel", (cl_int *)&rt); - AssertFatal(rt == CL_SUCCESS, "Error %d creating kernel %s platform %i, dev %i\n", (int)rt, "ldpc_cnp_kernel", i, dev); - ocl.runtime[i].kernels[dev].vnp_kernel_normal = clCreateKernel(program, "ldpc_vnp_kernel_normal", (cl_int *)&rt); - AssertFatal(rt == CL_SUCCESS, - "Error %d creating kernel %s platform %i, dev %i\n", - (int)rt, - "ldpc_vnp_kernel_normal", - i, - dev); - ocl.runtime[i].kernels[dev].pack_decoded_bit = clCreateKernel(program, "pack_decoded_bit", (cl_int *)&rt); - AssertFatal(rt == CL_SUCCESS, "Error %d creating kernel %s platform %i, dev %i\n", (int)rt, "pack_decoded_bit", i, dev); - } - context_ok++; - } - devok = 0; - } - AssertFatal(context_ok > 0, "No openCL device available to accelerate ldpc\n"); - return 0; -} - -int32_t LDPCshutdown() -{ - return 0; -} - -int32_t LDPCinit() -{ - // init_LLR_DMA(p_decParams, p_llr, p_out); - return 0; -} - -int32_t LDPCdecoder(t_nrLDPC_dec_params *p_decParams, - int8_t *p_llr, - int8_t *p_out, - t_nrLDPC_time_stats *time_decoder, - decode_abort_t *ab) -{ - uint16_t Zc = p_decParams->Z; - uint8_t BG = p_decParams->BG; - // uint8_t numMaxIter = p_decParams->numMaxIter; - int block_length = p_decParams->Kprime; - // e_nrLDPC_outMode outMode = p_decParams->outMode; - uint8_t row, col; - if (BG == 1) { - row = 46; - col = 68; - } else { - row = 42; - col = 52; - } - - // alloc memory - // unsigned char *hard_decision = (unsigned char*)p_out; - // gpu - int memorySize_llr = col * Zc * sizeof(char) * MC; - // cudaCheck( cudaMemcpyToSymbol(dev_const_llr, p_llr, memorySize_llr_cuda) ); - // cudaCheck( cudaMemcpyToSymbol(dev_llr, p_llr, memorySize_llr_cuda) ); - set_compact_BG(p_decParams->Z, p_decParams->BG); - - int rt = - clEnqueueWriteBuffer(ocl.runtime[0].queue[0], ocl.runtime[0].dev_const_llr, CL_TRUE, 0, memorySize_llr, p_llr, 0, NULL, NULL); - AssertFatal(rt == CL_SUCCESS, "Error %d moving p_llr data to read only memory in pltf %i dev %i\n", (int)rt, 0, 0); - rt = clEnqueueWriteBuffer(ocl.runtime[0].queue[0], ocl.runtime[0].dev_llr, CL_TRUE, 0, memorySize_llr, p_llr, 0, NULL, NULL); - AssertFatal(rt == CL_SUCCESS, "Error %d moving p_llr data to read-write memory in pltf %i dev %i\n", (int)rt, 0, 0); - // Define CUDA kernel dimension - // int blockSizeX = Zc; - // dim3 dimGridKernel1(row, MC, 1); // dim of the thread blocks - // dim3 dimBlockKernel1(blockSizeX, 1, 1); - - // dim3 dimGridKernel2(col, MC, 1); - // dim3 dimBlockKernel2(blockSizeX, 1, 1); - // cudaDeviceSynchronize(); - - // lauch kernel - size_t global_item_sizek0[2] = {row * Zc, MC}; // Process the entire lists - size_t global_item_sizek1[2] = {col * Zc, MC}; // Process the entire lists - size_t local_item_sizek[2] = {128, 1}; // Divide work items into groups of 128 - - for (int ii = 0; ii < MAX_ITERATION; ii++) { - // first kernel - if (ii == 0) { - // ldpc_cnp_kernel_1st_iter - // <<>> - // ( BG, row, col, Zc); - CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel_1st, 0, sizeof(cl_mem), (void *)&(ocl.runtime[0].dev_llr)); - CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel_1st, 1, sizeof(cl_mem), (void *)&(ocl.runtime[0].dev_dt)); - CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel_1st, 2, sizeof(cl_mem), (void *)&(ocl.runtime[0].dev_h_compact1)); - CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel_1st, 3, sizeof(int), (void *)&(BG)); - CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel_1st, 4, sizeof(int), (void *)&(row)); - CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel_1st, 5, sizeof(int), (void *)&(col)); - CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel_1st, 6, sizeof(int), (void *)&(Zc)); - rt = clEnqueueNDRangeKernel(ocl.runtime[0].queue[0], - ocl.runtime[0].kernels[0].cnp_kernel_1st, - 2, - NULL, - global_item_sizek0, - local_item_sizek, - 0, - NULL, - NULL); - AssertFatal(rt == CL_SUCCESS, "Error %d enqueing cnp_kernel_1st \n", (int)rt); - } else { - // ldpc_cnp_kernel - // <<>> - // ( BG, row, col, Zc); - CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel, 0, sizeof(cl_mem), (void *)&(ocl.runtime[0].dev_llr)); - CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel, 1, sizeof(cl_mem), (void *)&(ocl.runtime[0].dev_dt)); - CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel, 2, sizeof(cl_mem), (void *)&(ocl.runtime[0].dev_h_compact1)); - CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel, 3, sizeof(int), (void *)&(BG)); - CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel, 4, sizeof(int), (void *)&(row)); - CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel, 5, sizeof(int), (void *)&(col)); - CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel, 6, sizeof(int), (void *)&(Zc)); - rt = clEnqueueNDRangeKernel(ocl.runtime[0].queue[0], - ocl.runtime[0].kernels[0].cnp_kernel, - 2, - NULL, - global_item_sizek0, - local_item_sizek, - 0, - NULL, - NULL); - AssertFatal(rt == CL_SUCCESS, "Error %d enqueing cnp_kernel\n", (int)rt); - } - // second kernel - // ldpc_vnp_kernel_normal - // <<>> - // // (dev_llr, dev_const_llr,BG, row, col, Zc); - // (BG, row, col, Zc); - CLSETKERNELARG(ocl.runtime[0].kernels[0].vnp_kernel_normal, 0, sizeof(cl_mem), (void *)&(ocl.runtime[0].dev_llr)); - CLSETKERNELARG(ocl.runtime[0].kernels[0].vnp_kernel_normal, 1, sizeof(cl_mem), (void *)&(ocl.runtime[0].dev_dt)); - CLSETKERNELARG(ocl.runtime[0].kernels[0].vnp_kernel_normal, 2, sizeof(cl_mem), (void *)&(ocl.runtime[0].dev_const_llr)); - CLSETKERNELARG(ocl.runtime[0].kernels[0].vnp_kernel_normal, 3, sizeof(cl_mem), (void *)&(ocl.runtime[0].dev_h_compact2)); - CLSETKERNELARG(ocl.runtime[0].kernels[0].vnp_kernel_normal, 4, sizeof(int), (void *)&(BG)); - CLSETKERNELARG(ocl.runtime[0].kernels[0].vnp_kernel_normal, 5, sizeof(int), (void *)&(row)); - CLSETKERNELARG(ocl.runtime[0].kernels[0].vnp_kernel_normal, 6, sizeof(int), (void *)&(col)); - CLSETKERNELARG(ocl.runtime[0].kernels[0].vnp_kernel_normal, 7, sizeof(int), (void *)&(Zc)); - rt = clEnqueueNDRangeKernel(ocl.runtime[0].queue[0], - ocl.runtime[0].kernels[0].vnp_kernel_normal, - 2, - NULL, - global_item_sizek1, - local_item_sizek, - 0, - NULL, - NULL); - AssertFatal(rt == CL_SUCCESS, "Error %d enqueing vnp_kernel_normal \n", (int)rt); - } - - // int pack = (block_length/128)+1; - // dim3 pack_block(pack, MC, 1); - // pack_decoded_bit<<>>( col, Zc); - CLSETKERNELARG(ocl.runtime[0].kernels[0].pack_decoded_bit, 0, sizeof(cl_mem), (void *)&(ocl.runtime[0].dev_llr)); - CLSETKERNELARG(ocl.runtime[0].kernels[0].pack_decoded_bit, 1, sizeof(cl_mem), (void *)&(ocl.runtime[0].dev_tmp)); - CLSETKERNELARG(ocl.runtime[0].kernels[0].pack_decoded_bit, 2, sizeof(int), (void *)&(col)); - CLSETKERNELARG(ocl.runtime[0].kernels[0].pack_decoded_bit, 3, sizeof(int), (void *)&(Zc)); - - // Execute the OpenCL kernel on the list - size_t global_item_size[2] = {block_length, MC}; // Process the entire lists - size_t local_item_size[2] = {128, 1}; // Divide work items into groups of 128 - rt = clEnqueueNDRangeKernel(ocl.runtime[0].queue[0], - ocl.runtime[0].kernels[0].pack_decoded_bit, - 2, - NULL, - global_item_size, - local_item_size, - 0, - NULL, - NULL); - AssertFatal(rt == CL_SUCCESS, "Error %d enqueing pack_decoded_bit \n", (int)rt); - // cudaCheck( cudaMemcpyFromSymbol((void*)hard_decision, (const void*)dev_tmp, (block_length/8)*sizeof(unsigned char)) ); - // cudaDeviceSynchronize(); - - rt = clEnqueueReadBuffer(ocl.runtime[0].queue[0], - ocl.runtime[0].dev_tmp, - CL_TRUE, - 0, - (block_length / 8) * sizeof(unsigned char), - p_llr, - 0, - NULL, - NULL); - AssertFatal(rt == CL_SUCCESS, "Error %d moving p_llr data to pltf %i dev %i\n", (int)rt, 0, 0); - return MAX_ITERATION; -} -#endif // NRLDPC_KERNEL_SOURCE diff --git a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_kernels_CL.c b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_kernels_CL.c deleted file mode 100644 index 42b25e41c0..0000000000 --- a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_kernels_CL.c +++ /dev/null @@ -1,292 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.0 (the "License"); you may not use this file - * except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.openairinterface.org/?page_id=698 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -/*! \file PHY/CODING/nrLDPC_decoder_kernels_CL.cl -* \brief kernel functions for ldpc decoder accelerated via openCL -* \author Francois TABURET -* \date 2021 -* \version 1.0 -* \company Nokia BellLabs France -* \email: francois.taburet@nokia-bell-labs.com -* \note initial implem - translation of cuda version -* \warning -*/ - - -//__global char dev_dt [46*68*384]; -//__local char *dev_t; -//__global char dev_llr[68*384]; -//__global unsigned char dev_tmp[68*384]; - - -#define INT32_MAX 2147483647 - -//__constant h_element dev_h_compact1[46*19] = {}; // used in kernel 1 -//__constant h_element dev_h_compact2[68*30] = {}; // used in kernel 2 - -// __device__ __constantant__ h_element dev_h_compact1[46*19]; // used in kernel 1 -// __device__ __constantant__ h_element dev_h_compact2[68*30]; // used in kernel 2 - -// row and col element count -__constant char h_ele_row_bg1_count[46] = { - 19, 19, 19, 19, 3, 8, 9, 7, 10, 9, - 7, 8, 7, 6, 7, 7, 6, 6, 6, 6, - 6, 6, 5, 5, 6, 5, 5, 4, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 4, 5, 5, - 4, 5, 4, 5, 5, 4}; -__constant char h_ele_col_bg1_count[68] = { - 30, 28, 7, 11, 9, 4, 8, 12, 8, 7, - 12, 10, 12, 11, 10, 7, 10, 10, 13, 7, - 8, 11, 12, 5, 6, 6, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1}; -__constant char h_ele_row_bg2_count[42] = { - 8, 10, 8, 10, 4, 6, 6, 6, 4, 5, - 5, 5, 4, 5, 5, 4, 5, 5, 4, 4, - 4, 4, 3, 4, 4, 3, 5, 3, 4, 3, - 5, 3, 4, 4, 4, 4, 4, 3, 4, 4, - 4, 4}; -__constant char h_ele_col_bg2_count[52] = { - 22, 23, 10, 5, 5, 14, 7, 13, 6, 8, - 9, 16, 9, 12, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1}; - - - -// Kernel 1 -__kernel void ldpc_cnp_kernel_1st_iter( __global char * dev_llr, __global char * dev_dt, __local h_element *dev_h_compact1, int BG, int row, int col, int Zc) -{ -// int iMCW = blockIdx.y; // codeword id -// int iBlkRow = blockIdx.x; // block row in h_base -// int iSubRow = threadIdx.x; // row index in sub_block of h_base -// if(blockIdx.x == 0 && threadIdx.x == 1) printf("cnp %d\n", threadIdx.x); - int iMCW = get_group_id(1); // codeword id - int iBlkRow = get_group_id(0); // block row in h_base - int iBlkCol; // block col in h_base - int iSubRow = get_local_id(0);; // row index in sub_block of h_base - int iCol; // overall col index in h_base - int offsetR; - int shift_t; - -// For 2-min algorithm. - int Q_sign = 0; - int sq; - int Q, Q_abs; - int R_temp; - - int sign = 1; - int rmin1 = INT32_MAX; - int rmin2 = INT32_MAX; - char idx_min = 0; - - h_element h_element_t; - int s = (BG==1)? h_ele_row_bg1_count[iBlkRow]:h_ele_row_bg2_count[iBlkRow]; - offsetR = (iMCW * row*col*Zc) + iBlkRow * Zc + iSubRow; // row*col*Zc = size of dev_dt -// if(blockIdx.x == 0 && threadIdx.x == 1) printf("s: %d, offset %d\n", s, offsetR); -// The 1st recursion - for(int i = 0; i < s; i++) // loop through all the ZxZ sub-blocks in a row - { - h_element_t = dev_h_compact1[i*row+iBlkRow]; // compact_col == row - - iBlkCol = h_element_t.y; - shift_t = h_element_t.value; - - shift_t = (iSubRow + shift_t) % Zc; - iCol = (iMCW * col*Zc) + iBlkCol * Zc + shift_t; // col*Zc = size of llr - Q = dev_llr[iCol]; - Q_abs = (Q>0)? Q : -Q; - sq = Q < 0; -// if(blockIdx.x == 0 && threadIdx.x == 1) printf("i %d, icol %d, Q: %d\n", i, iCol, Q); - // quick version - sign = sign * (1 - sq * 2); - Q_sign |= sq << i; - - if (Q_abs < rmin1){ - rmin2 = rmin1; - rmin1 = Q_abs; - idx_min = i; - } else if (Q_abs < rmin2){ - rmin2 = Q_abs; - } - } - -// if(blockIdx.x == 0 && threadIdx.x == 1)printf("min1 %d, min2 %d, min1_idx %d\n", rmin1, rmin2, idx_min); - -// The 2nd recursion - for(int i = 0; i < s; i++){ - // v0: Best performance so far. 0.75f is the value of alpha. - sq = 1 - 2 * ((Q_sign >> i) & 0x01); - R_temp = 0.75f * sign * sq * (i != idx_min ? rmin1 : rmin2); - // write results to global memory - h_element_t = dev_h_compact1[i*row+iBlkRow]; - int addr_temp = offsetR + h_element_t.y * row * Zc; - dev_dt[addr_temp] = R_temp; -// if(blockIdx.x == 0 && threadIdx.x == 1)printf("R_temp %d, temp_addr %d\n", R_temp, addr_temp); - } -} - -// Kernel_1 -__kernel void ldpc_cnp_kernel( __global char * dev_llr, __global char * dev_dt, __local h_element *dev_h_compact1, int BG, int row, int col, int Zc) -{ -// if(blockIdx.x == 0 && threadIdx.x == 1) printf("cnp\n"); -// int iMCW = blockIdx.y; -// int iBlkRow = blockIdx.x; // block row in h_base // block col in h_base -// int iSubRow = threadIdx.x; // row index in sub_block of h_base - int iMCW = get_group_id(1); - int iBlkRow = get_group_id(0); // block row in h_base - int iBlkCol; // block col in h_base - int iSubRow = get_local_id(0);; // row index in sub_block of h_base - int iCol; // overall col index in h_base - int offsetR; - int shift_t; - -// For 2-min algorithm. - int Q_sign = 0; - int sq; - int Q, Q_abs; - int R_temp; - - int sign = 1; - int rmin1 = INT32_MAX; - int rmin2 = INT32_MAX; - char idx_min = 0; - - h_element h_element_t; - int s = (BG==1)? h_ele_row_bg1_count[iBlkRow]: h_ele_row_bg2_count[iBlkRow]; - offsetR = (iMCW *row*col*Zc) + iBlkRow * Zc + iSubRow; // row * col * Zc = size of dev_dt -// if(blockIdx.x == 0 && threadIdx.x == 1) printf("s: %d, offset %d\n", s, offsetR); -// The 1st recursion - for(int i = 0; i < s; i++) // loop through all the ZxZ sub-blocks in a row - { - h_element_t = dev_h_compact1[i*row+iBlkRow]; - - iBlkCol = h_element_t.y; - shift_t = h_element_t.value; - shift_t = (iSubRow + shift_t) % Zc; - iCol = iBlkCol * Zc + shift_t; - - R_temp = dev_dt[offsetR + iBlkCol * row * Zc]; - - Q = dev_llr[iMCW * (col*Zc) + iCol] - R_temp; - Q_abs = (Q>0)? Q : -Q; -// if(blockIdx.x == 0 && threadIdx.x == 1) printf("i %d, icol %d, Q: %d\n", i, iCol, Q); - sq = Q < 0; - sign = sign * (1 - sq * 2); - Q_sign |= sq << i; - - if (Q_abs < rmin1){ - rmin2 = rmin1; - rmin1 = Q_abs; - idx_min = i; - } else if (Q_abs < rmin2){ - rmin2 = Q_abs; - } - - } - -// if(blockIdx.x == 0 && threadIdx.x == 1)printf("min1 %d, min2 %d, min1_idx %d\n", rmin1, rmin2, idx_min); - -// The 2nd recursion - for(int i = 0; i < s; i ++){ - sq = 1 - 2 * ((Q_sign >> i) & 0x01); - R_temp = 0.75f * sign * sq * (i != idx_min ? rmin1 : rmin2); - - - // write results to global memory - h_element_t = dev_h_compact1[i*row+iBlkRow]; - int addr_temp = h_element_t.y * row * Zc + offsetR; - dev_dt[addr_temp] = R_temp; -// if(blockIdx.x == 0 && threadIdx.x == 1)printf("R_temp %d, temp_addr %d\n", R_temp, addr_temp); - } -} - -// Kernel 2: VNP processing -__kernel void -ldpc_vnp_kernel_normal(__global char * dev_llr, __global char * dev_dt, __global char * dev_const_llr, __local h_element *dev_h_compact2, int BG, int row, int col, int Zc) -{ -// int iMCW = blockIdx.y; -// int iBlkCol = blockIdx.x; -// int iSubCol = threadIdx.x; - int iMCW = get_group_id(1); - int iBlkCol = get_group_id(0); - int iBlkRow; - int iSubCol = get_local_id(0); - int iRow; - int iCol; - - int shift_t, sf; - int APP; - - h_element h_element_t; - - // update all the llr values - iCol = iBlkCol * Zc + iSubCol; - APP = dev_const_llr[iMCW *col*Zc + iCol]; - int offsetDt = iMCW *row*col*Zc + iBlkCol * row * Zc; - int s = (BG==1)? h_ele_col_bg1_count[iBlkCol]:h_ele_col_bg2_count[iBlkCol]; - - for(int i = 0; i < s; i++) - { - h_element_t = dev_h_compact2[i*col+iBlkCol]; - - shift_t = h_element_t.value%Zc; - iBlkRow = h_element_t.x; - - sf = iSubCol - shift_t; - sf = (sf + Zc) % Zc; - - iRow = iBlkRow * Zc + sf; - APP = APP + dev_dt[offsetDt + iRow]; - } - if(APP > SCHAR_MAX) APP = SCHAR_MAX; - if(APP < SCHAR_MIN) APP = SCHAR_MIN; - // write back to device global memory - dev_llr[iMCW *col*Zc + iCol] = APP; -} - - -__kernel void pack_decoded_bit(__global unsigned char * dev_llr, __global unsigned char * dev_tmp, int col, int Zc) -{ -// int iMCW = blockIdx.y; -// int btid = threadIdx.x; - unsigned char tmp[128]; - int iMCW = get_group_id(1); - int btid = get_local_id(0); - int tid = iMCW * col*Zc + get_group_id(0)*128 + btid; - tmp[btid] = 0; - - if(dev_llr[tid] < 0){ - tmp[btid] = 1 << (7-(btid&7)); - } -// __syncthreads(); - - if(btid < 16){ - dev_tmp[iMCW * col*Zc + get_group_id(0)*16+btid] = 0; - for(int i = 0; i < 8; i++){ - dev_tmp[iMCW * col*Zc + get_group_id(0)*16+btid] += tmp[btid*8+i]; - } - } -} From 35361db76b9181f0dde4c38fd93623ac74793d80 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 7 Aug 2025 13:11:12 +0200 Subject: [PATCH 418/964] build_oai: don't redirect compilations to a file Redirecting to a file has the problem that it is difficult in the CI to recover these files. Furthermore, at least with ninja, when running build_oai interactively, the build output will only take some lines (because ninja rewrites lines), so the change should not be that big to users. One CI function would print the entire output from build_oai to the console. Since that output might be long now, do not do this. The file is archived, anyway. --- ci-scripts/cls_native.py | 2 +- cmake_targets/build_oai | 12 +++---- cmake_targets/tools/build_helper | 59 -------------------------------- 3 files changed, 5 insertions(+), 68 deletions(-) diff --git a/ci-scripts/cls_native.py b/ci-scripts/cls_native.py index 3dde286c3a..83c1b14b37 100644 --- a/ci-scripts/cls_native.py +++ b/ci-scripts/cls_native.py @@ -43,7 +43,7 @@ class Native(): ret = ssh.run(f"C_INCLUDE_PATH={DPDK_PATH}/include/ PKG_CONFIG_PATH={DPDK_PATH}/lib64/pkgconfig/ {base}/build_oai {options} > {base}/build_oai.log", timeout=900) success = ret.returncode == 0 logs = ssh.run(f"cat {base}/build_oai.log", silent=True) - logging.debug(f"build finished with code {ret.returncode}, output:\n{logs.stdout}") + logging.debug(f"build finished with code {ret.returncode}") archiveArtifact(ssh, ctx, f'{base}/build_oai.log') diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index 3b43d69911..b1b305c596 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -37,7 +37,6 @@ set_openair_env conf_nvram_path=$OPENAIR_DIR/openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf HW="" -VERBOSE_COMPILE=0 BUILD_DIR=ran_build DISABLE_HARDWARE_DEPENDENCY="False" CMAKE_BUILD_TYPE="RelWithDebInfo" @@ -98,8 +97,6 @@ Options: Makes the unitary tests Layer 1 simulators -V | --vcd Adds a debgging facility to the binary files: GUI with major internal synchronization events ---verbose-compile - Shows detailed compilation instructions in makefile --build-doxygen Builds doxygen based documentation. --trace-asn1c-enc-dec @@ -314,10 +311,6 @@ function main() { echo_info "Setting gtk-wave output" CMAKE_CMD="$CMAKE_CMD -DENABLE_VCD_FIFO=True" shift;; - --verbose-compile) - VERBOSE_COMPILE=1 - echo_info "Will compile with verbose instructions" - shift;; --build-doxygen) CMAKE_CMD="$CMAKE_CMD -DGENERATE_DOXYGEN=ON" TARGET_LIST="$TARGET_LIST doc" @@ -475,7 +468,10 @@ function main() { CMAKE_CMD="$CMAKE_CMD ../../.." echo_info "Running \"$CMAKE_CMD\"" eval $CMAKE_CMD - compilations $BUILD_DIR all.txt "$TARGET_LIST" "${BUILD_TOOL_OPT}" + cmd="$CMAKE --build . --target ${TARGET_LIST} -- ${BUILD_TOOL_OPT}" + echo_info "Running \"${cmd}\"" $green + eval $cmd + ret=$? if [ "$UE" = 1 ] ; then echo_info "Generate LTE USIM default sim content UE specific part" diff --git a/cmake_targets/tools/build_helper b/cmake_targets/tools/build_helper index f13dd314ef..2c79659991 100755 --- a/cmake_targets/tools/build_helper +++ b/cmake_targets/tools/build_helper @@ -181,65 +181,6 @@ clean_all_files() { rm -rf $dir/autotests/bin $dir/autotests/log $dir/autotests/*/build } -################################### -# Compilers -################################### - -#check_warnings: -# print error message if the compilation had warnings -#argument: -# $1: log file -check_warnings() { - #we look for 'warning:' in the compilation log file - #this is how gcc starts a warning - #this is not perfect, we may get false positive - warning_count=`grep "warning:" "$1" | grep -E -v "jobserver unavailable|disabling jobserver mode" | wc -l` - if [ $warning_count -gt 0 ]; then - echo_error "WARNING: $warning_count warnings. See $1" - fi -} - -#check_errors: -# print error message if the compilation had errors -#argument: -# $1: log file -check_errors() { - #we look for 'error:' in the compilation log file - error_count=`grep -c "error:" "$1"` - if [ $error_count -gt 0 ]; then - echo_error "ERROR: $error_count error. See $1" - fi -} - -compilations() { - [[ $# -eq 4 ]] || echo_fatal "compilations " - local dir=$1 - local logfile=$2 - local targets=$3 - local build_tool_opt=$4 - local verbose=$([ "$VERBOSE_COMPILE" == "1" ] && echo "-v" || echo "") - echo cd $OPENAIR_DIR/cmake_targets/$dir/build - cd $OPENAIR_DIR/cmake_targets/$dir/build - cmd="$CMAKE --build . ${verbose} --target ${targets} -- ${build_tool_opt}" - echo_info "Running \"${cmd}\"" $green - echo "Log file for compilation is being written to: $dlog/$logfile" - set +e - { - eval ${cmd} - ret=$? - } > $dlog/$logfile 2>&1 - # Print the errors and warnings for CI purposes - grep -E -A5 -B5 "warning:|error:| Error " $dlog/$logfile || true - check_warnings "$dlog/$logfile" - if [[ $ret -eq 0 ]]; then - echo_success "$targets compiled" - else - check_errors "$dlog/$logfile" - echo_error "compilation of $targets failed" - exit 1 - fi -} - ############################################ # External packages installers ############################################ From b3675be33a8cbc3f31addb911f2740499b49bf0b Mon Sep 17 00:00:00 2001 From: calvin_peyron Date: Fri, 8 Aug 2025 14:10:33 +0200 Subject: [PATCH 419/964] Upgrade CI images to Ubuntu 24 Libboost went from 1.74.0 to 1.83.0 alongside Ubuntu update. GCC version is set as default to be more practical. In Ubuntu22, apt sources were in .list files, in Ubuntu24 they are in .sources files. Add --break-system-packages for pip installation to use same logic as before, see the pip update 23.0.1 (2023-02-17). With Ubuntu24 liboai_device requires libpython3.12 --- ci-scripts/cls_containerize.py | 4 +- ....bionic => Dockerfile.formatting.ubuntu24} | 4 +- ....ubuntu22 => Dockerfile.unittest.ubuntu24} | 2 +- cmake_targets/cross-arm.cmake | 4 +- cmake_targets/tools/build_helper | 2 +- doc/cross-compile.md | 4 +- ...base.ubuntu22 => Dockerfile.base.ubuntu24} | 11 ++---- ...4 => Dockerfile.base.ubuntu24.cross-arm64} | 25 ++++++------ ...ockerfile.build.fhi72.native_arm.ubuntu24} | 6 +-- ...untu22 => Dockerfile.build.fhi72.ubuntu24} | 6 +-- ...ild.ubuntu22 => Dockerfile.build.ubuntu24} | 6 +-- ... => Dockerfile.build.ubuntu24.cross-arm64} | 2 +- ...e.eNB.ubuntu22 => Dockerfile.eNB.ubuntu24} | 28 ++++++------- ...buntu22 => Dockerfile.gNB.aerial.ubuntu24} | 4 +- ...file.gNB.aerial.ubuntu24.sanitize-address} | 4 +- ....ubuntu22 => Dockerfile.gNB.aw2s.ubuntu24} | 4 +- ...ubuntu22 => Dockerfile.gNB.fhi72.ubuntu24} | 6 +-- ...e.gNB.ubuntu22 => Dockerfile.gNB.ubuntu24} | 39 ++++++------------- ...eRU.ubuntu22 => Dockerfile.lteRU.ubuntu24} | 21 +++++----- ...eUE.ubuntu22 => Dockerfile.lteUE.ubuntu24} | 30 ++++++-------- ...p.ubuntu22 => Dockerfile.nr-cuup.ubuntu24} | 22 ++--------- ...nrUE.ubuntu22 => Dockerfile.nrUE.ubuntu24} | 39 ++++++------------- 22 files changed, 101 insertions(+), 172 deletions(-) rename ci-scripts/docker/{Dockerfile.formatting.bionic => Dockerfile.formatting.ubuntu24} (97%) rename ci-scripts/docker/{Dockerfile.unittest.ubuntu22 => Dockerfile.unittest.ubuntu24} (98%) rename docker/{Dockerfile.base.ubuntu22 => Dockerfile.base.ubuntu24} (89%) rename docker/{Dockerfile.base.ubuntu22.cross-arm64 => Dockerfile.base.ubuntu24.cross-arm64} (81%) rename docker/{Dockerfile.build.fhi72.native_arm.ubuntu22 => Dockerfile.build.fhi72.native_arm.ubuntu24} (95%) rename docker/{Dockerfile.build.fhi72.ubuntu22 => Dockerfile.build.fhi72.ubuntu24} (95%) rename docker/{Dockerfile.build.ubuntu22 => Dockerfile.build.ubuntu24} (94%) rename docker/{Dockerfile.build.ubuntu22.cross-arm64 => Dockerfile.build.ubuntu24.cross-arm64} (98%) rename docker/{Dockerfile.eNB.ubuntu22 => Dockerfile.eNB.ubuntu24} (87%) rename docker/{Dockerfile.gNB.aerial.ubuntu22 => Dockerfile.gNB.aerial.ubuntu24} (98%) rename docker/{Dockerfile.gNB.aerial.ubuntu22.sanitize-address => Dockerfile.gNB.aerial.ubuntu24.sanitize-address} (98%) rename docker/{Dockerfile.gNB.aw2s.ubuntu22 => Dockerfile.gNB.aw2s.ubuntu24} (98%) rename docker/{Dockerfile.gNB.fhi72.ubuntu22 => Dockerfile.gNB.fhi72.ubuntu24} (98%) rename docker/{Dockerfile.gNB.ubuntu22 => Dockerfile.gNB.ubuntu24} (79%) rename docker/{Dockerfile.lteRU.ubuntu22 => Dockerfile.lteRU.ubuntu24} (86%) rename docker/{Dockerfile.lteUE.ubuntu22 => Dockerfile.lteUE.ubuntu24} (85%) rename docker/{Dockerfile.nr-cuup.ubuntu22 => Dockerfile.nr-cuup.ubuntu24} (73%) rename docker/{Dockerfile.nrUE.ubuntu22 => Dockerfile.nrUE.ubuntu24} (78%) diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index 34522d9eef..d3168f60a3 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -298,7 +298,7 @@ class Containerize(): self.host = result.group(0) if self.host == 'Ubuntu': self.cli = 'docker' - self.dockerfileprefix = '.ubuntu22' + self.dockerfileprefix = '.ubuntu24' self.cliBuildOptions = '' elif self.host == 'Red Hat': self.cli = 'sudo podman' @@ -625,7 +625,7 @@ class Containerize(): return False # build ran-unittests image - dockerfile = "ci-scripts/docker/Dockerfile.unittest.ubuntu22" + dockerfile = "ci-scripts/docker/Dockerfile.unittest.ubuntu24" logfile = f'{lSourcePath}/cmake_targets/log/unittest-build.log' ret = cmd.run(f'docker build --progress=plain --tag ran-unittests:{baseTag} --file {dockerfile} . &> {logfile}') archiveArtifact(cmd, ctx, logfile) diff --git a/ci-scripts/docker/Dockerfile.formatting.bionic b/ci-scripts/docker/Dockerfile.formatting.ubuntu24 similarity index 97% rename from ci-scripts/docker/Dockerfile.formatting.bionic rename to ci-scripts/docker/Dockerfile.formatting.ubuntu24 index a8d58f511c..2f99a69026 100644 --- a/ci-scripts/docker/Dockerfile.formatting.bionic +++ b/ci-scripts/docker/Dockerfile.formatting.ubuntu24 @@ -21,11 +21,11 @@ #--------------------------------------------------------------------- # # Dockerfile for the Open-Air-Interface BUILD service -# Valid for Ubuntu 22.04 +# Valid for Ubuntu 24.04 # #--------------------------------------------------------------------- -FROM ubuntu:bionic AS oai-formatting-check +FROM ubuntu:noble AS oai-formatting-check ARG MERGE_REQUEST ARG SRC_BRANCH diff --git a/ci-scripts/docker/Dockerfile.unittest.ubuntu22 b/ci-scripts/docker/Dockerfile.unittest.ubuntu24 similarity index 98% rename from ci-scripts/docker/Dockerfile.unittest.ubuntu22 rename to ci-scripts/docker/Dockerfile.unittest.ubuntu24 index 627b0d07f7..eb18bc24c4 100644 --- a/ci-scripts/docker/Dockerfile.unittest.ubuntu22 +++ b/ci-scripts/docker/Dockerfile.unittest.ubuntu24 @@ -21,7 +21,7 @@ #--------------------------------------------------------------------- # # Dockerfile for the Open-Air-Interface BUILD service -# Valid for Ubuntu 22.04 +# Valid for Ubuntu 24.04 # #--------------------------------------------------------------------- diff --git a/cmake_targets/cross-arm.cmake b/cmake_targets/cross-arm.cmake index 9480fc0fe0..09d6b25e70 100644 --- a/cmake_targets/cross-arm.cmake +++ b/cmake_targets/cross-arm.cmake @@ -1,8 +1,8 @@ set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR arm) -set(CMAKE_C_COMPILER /usr/bin/aarch64-linux-gnu-gcc-11) -set(CMAKE_CXX_COMPILER /usr/bin/aarch64-linux-gnu-g++-11) +set(CMAKE_C_COMPILER /usr/bin/aarch64-linux-gnu-gcc) +set(CMAKE_CXX_COMPILER /usr/bin/aarch64-linux-gnu-g++) set(ENV{PKG_CONFIG_LIBDIR} "/usr/lib/aarch64-linux-gnu/pkgconfig") diff --git a/cmake_targets/tools/build_helper b/cmake_targets/tools/build_helper index f13dd314ef..dc9678263b 100755 --- a/cmake_targets/tools/build_helper +++ b/cmake_targets/tools/build_helper @@ -323,7 +323,7 @@ check_install_usrp_uhd_driver(){ $SUDO apt-get remove libuhd3.14.1 -y || true $SUDO apt-get remove libuhd3.15.0 -y || true local distribution=$(get_distribution_release) - if [[ "$distribution" == "ubuntu20.04" || "$distribution" == "ubuntu22.04" ]]; then + if [[ "$distribution" == "ubuntu20.04" || "$distribution" == "ubuntu22.04" || "$distribution" == "ubuntu24.04" ]]; then $SUDO apt-get remove libuhd4.?.? -y || true fi v=$(lsb_release -cs) diff --git a/doc/cross-compile.md b/doc/cross-compile.md index 0a0ce3b1ba..ae8dbe5209 100644 --- a/doc/cross-compile.md +++ b/doc/cross-compile.md @@ -36,8 +36,8 @@ sudo cp /etc/apt/sources.list "/etc/apt/sources.list.`date`.backup" sudo sed -i -E "s/(deb)\ (http:.+)/\1\ [arch=amd64]\ \2/" /etc/apt/sources.list sudo apt update -sudo apt install -y gcc-11-aarch64-linux-gnu \ - g++-11-aarch64-linux-gnu +sudo apt install -y gcc-aarch64-linux-gnu \ + g++-aarch64-linux-gnu sudo apt-get install -y \ libblas-dev:arm64 \ diff --git a/docker/Dockerfile.base.ubuntu22 b/docker/Dockerfile.base.ubuntu24 similarity index 89% rename from docker/Dockerfile.base.ubuntu22 rename to docker/Dockerfile.base.ubuntu24 index ba8707d4db..a1f6daa3c3 100644 --- a/docker/Dockerfile.base.ubuntu22 +++ b/docker/Dockerfile.base.ubuntu24 @@ -21,12 +21,12 @@ #--------------------------------------------------------------------- # # Dockerfile for the Open-Air-Interface BUILD service -# Valid for Ubuntu 22.04 +# Valid for Ubuntu 24.04 # #--------------------------------------------------------------------- -FROM ubuntu:jammy AS ran-base +FROM ubuntu:noble AS ran-base ARG NEEDED_GIT_PROXY ARG TARGETARCH ENV DEBIAN_FRONTEND=noninteractive @@ -43,9 +43,6 @@ RUN apt-get update && \ ccache \ psmisc \ git \ - #use gcc-12 to avoid problems of default gcc-11 in FlexRIC - gcc-12 \ - g++-12 \ xxd \ libpcre2-dev \ python3-dev \ @@ -55,8 +52,8 @@ RUN apt-get update && \ # python3-pip for conf template generation 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 + # --break-system-packages allows externally managed environment in pip + pip3 install --ignore-installed pyyaml --break-system-packages # 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 diff --git a/docker/Dockerfile.base.ubuntu22.cross-arm64 b/docker/Dockerfile.base.ubuntu24.cross-arm64 similarity index 81% rename from docker/Dockerfile.base.ubuntu22.cross-arm64 rename to docker/Dockerfile.base.ubuntu24.cross-arm64 index 1bcba7bdd6..00c7290f5b 100644 --- a/docker/Dockerfile.base.ubuntu22.cross-arm64 +++ b/docker/Dockerfile.base.ubuntu24.cross-arm64 @@ -21,12 +21,12 @@ #--------------------------------------------------------------------- # # Dockerfile for the Open-Air-Interface BUILD service -# Valid for Ubuntu 22.04 to cross-compile for ARM64 +# Valid for Ubuntu 24.04 to cross-compile for ARM64 # #--------------------------------------------------------------------- -# Very important, the jammy image shall not be using mirrors. A lot of them do NOT support ARM64. -FROM ubuntu:jammy AS ran-base +# Very important, the noble image shall not be using mirrors. A lot of them do NOT support ARM64. +FROM ubuntu:noble AS ran-base ENV DEBIAN_FRONTEND=noninteractive ENV TZ=Europe/Paris # Specifying a working version of SIMDE for ARM: @@ -37,16 +37,17 @@ RUN apt-get update && \ DEBIAN_FRONTEND=noninteractive apt-get upgrade --yes && \ #enabling arm64 architecture dpkg --add-architecture arm64 && \ - echo "deb [arch=arm64] http://ports.ubuntu.com/ jammy main restricted\n" \ - "deb [arch=arm64] http://ports.ubuntu.com/ jammy-updates main restricted\n" \ - "deb [arch=arm64] http://ports.ubuntu.com/ jammy universe\n" \ - "deb [arch=arm64] http://ports.ubuntu.com/ jammy-updates universe\n" \ - "deb [arch=arm64] http://ports.ubuntu.com/ jammy multiverse\n" \ - "deb [arch=arm64] http://ports.ubuntu.com/ jammy-updates multiverse\n" \ - "deb [arch=arm64] http://ports.ubuntu.com/ jammy-backports main restricted universe multiverse" \ + echo "deb [arch=arm64] http://ports.ubuntu.com/ noble main restricted\n" \ + "deb [arch=arm64] http://ports.ubuntu.com/ noble-updates main restricted\n" \ + "deb [arch=arm64] http://ports.ubuntu.com/ noble universe\n" \ + "deb [arch=arm64] http://ports.ubuntu.com/ noble-updates universe\n" \ + "deb [arch=arm64] http://ports.ubuntu.com/ noble multiverse\n" \ + "deb [arch=arm64] http://ports.ubuntu.com/ noble-updates multiverse\n" \ + "deb [arch=arm64] http://ports.ubuntu.com/ noble-backports main restricted universe multiverse" \ | tee /etc/apt/sources.list.d/arm-cross-compile-sources.list && \ cp /etc/apt/sources.list "/etc/apt/sources.list.`date`.backup" && \ sed -i -E "s/(deb)\ (http:.+)/\1\ [arch=amd64]\ \2/" /etc/apt/sources.list && \ + sed -i '/^Components:/a Architectures: amd64' /etc/apt/sources.list.d/ubuntu.sources && \ apt-get update && \ DEBIAN_FRONTEND=noninteractive apt-get upgrade --yes && \ DEBIAN_FRONTEND=noninteractive apt-get install --yes \ @@ -69,8 +70,8 @@ RUN apt-get update && \ libyaml-cpp-dev:arm64 \ # cross build libs and compilers libc6-dev-i386 \ - gcc-11-aarch64-linux-gnu \ - g++-11-aarch64-linux-gnu && \ + gcc-aarch64-linux-gnu \ + g++-aarch64-linux-gnu && \ apt-get clean # Add "Tini - A tiny but valid init for containers", https://github.com/krallin/tini diff --git a/docker/Dockerfile.build.fhi72.native_arm.ubuntu22 b/docker/Dockerfile.build.fhi72.native_arm.ubuntu24 similarity index 95% rename from docker/Dockerfile.build.fhi72.native_arm.ubuntu22 rename to docker/Dockerfile.build.fhi72.native_arm.ubuntu24 index b796122bf3..f9f3dc3a8f 100644 --- a/docker/Dockerfile.build.fhi72.native_arm.ubuntu22 +++ b/docker/Dockerfile.build.fhi72.native_arm.ubuntu24 @@ -21,7 +21,7 @@ #--------------------------------------------------------------------- # # Dockerfile for the Open-Air-Interface RAN Build for FHI 7.2 -# Valid for UBUNTU 22.04 +# Valid for UBUNTU 24.04 # #--------------------------------------------------------------------- @@ -94,8 +94,6 @@ RUN mkdir -p openair2/E2AP/flexric/build && \ cmake -GNinja -DCMAKE_BUILD_TYPE=Release \ -DXAPP_MULTILANGUAGE=OFF \ -DKPM_VERSION=$KPM_VERSION \ - -DE2AP_VERSION=$E2AP_VERSION \ - -DCMAKE_C_COMPILER=gcc-12 \ - -DCMAKE_CXX_COMPILER=g++-12 .. && \ + -DE2AP_VERSION=$E2AP_VERSION .. && \ ninja && \ ninja install diff --git a/docker/Dockerfile.build.fhi72.ubuntu22 b/docker/Dockerfile.build.fhi72.ubuntu24 similarity index 95% rename from docker/Dockerfile.build.fhi72.ubuntu22 rename to docker/Dockerfile.build.fhi72.ubuntu24 index 4674648285..b60553dc1c 100644 --- a/docker/Dockerfile.build.fhi72.ubuntu22 +++ b/docker/Dockerfile.build.fhi72.ubuntu24 @@ -21,7 +21,7 @@ #--------------------------------------------------------------------- # # Dockerfile for the Open-Air-Interface RAN Build for FHI 7.2 -# Valid for UBUNTU 22.04 +# Valid for UBUNTU 24.04 # #--------------------------------------------------------------------- @@ -83,8 +83,6 @@ RUN mkdir -p openair2/E2AP/flexric/build && \ cd openair2/E2AP/flexric/build && \ cmake -GNinja -DCMAKE_BUILD_TYPE=Release \ -DKPM_VERSION=$KPM_VERSION \ - -DE2AP_VERSION=$E2AP_VERSION \ - -DCMAKE_C_COMPILER=gcc-12 \ - -DCMAKE_CXX_COMPILER=g++-12 .. && \ + -DE2AP_VERSION=$E2AP_VERSION .. && \ ninja && \ ninja install diff --git a/docker/Dockerfile.build.ubuntu22 b/docker/Dockerfile.build.ubuntu24 similarity index 94% rename from docker/Dockerfile.build.ubuntu22 rename to docker/Dockerfile.build.ubuntu24 index c11946ecdb..b2cc9c6888 100644 --- a/docker/Dockerfile.build.ubuntu22 +++ b/docker/Dockerfile.build.ubuntu24 @@ -21,7 +21,7 @@ #--------------------------------------------------------------------- # # Dockerfile for the Open-Air-Interface BUILD service -# Valid for Ubuntu 22.04 +# Valid for Ubuntu 24.04 # #--------------------------------------------------------------------- @@ -66,8 +66,6 @@ RUN \ cd openair2/E2AP/flexric/build && \ cmake -GNinja -DCMAKE_BUILD_TYPE=Release \ -DKPM_VERSION=$KPM_VERSION \ - -DE2AP_VERSION=$E2AP_VERSION \ - -DCMAKE_C_COMPILER=gcc-12 \ - -DCMAKE_CXX_COMPILER=g++-12 .. && \ + -DE2AP_VERSION=$E2AP_VERSION .. && \ ninja && \ ninja install diff --git a/docker/Dockerfile.build.ubuntu22.cross-arm64 b/docker/Dockerfile.build.ubuntu24.cross-arm64 similarity index 98% rename from docker/Dockerfile.build.ubuntu22.cross-arm64 rename to docker/Dockerfile.build.ubuntu24.cross-arm64 index 78c7a64f64..a7978bb6fa 100644 --- a/docker/Dockerfile.build.ubuntu22.cross-arm64 +++ b/docker/Dockerfile.build.ubuntu24.cross-arm64 @@ -21,7 +21,7 @@ #--------------------------------------------------------------------- # # Dockerfile for the Open-Air-Interface BUILD service -# Valid for Ubuntu 22.04 to cross-compile for ARM64 +# Valid for Ubuntu 24.04 to cross-compile for ARM64 # #--------------------------------------------------------------------- diff --git a/docker/Dockerfile.eNB.ubuntu22 b/docker/Dockerfile.eNB.ubuntu24 similarity index 87% rename from docker/Dockerfile.eNB.ubuntu22 rename to docker/Dockerfile.eNB.ubuntu24 index 44797cd7f5..0071d3abef 100644 --- a/docker/Dockerfile.eNB.ubuntu22 +++ b/docker/Dockerfile.eNB.ubuntu24 @@ -21,7 +21,7 @@ #--------------------------------------------------------------------- # # Dockerfile for the Open-Air-Interface BUILD service -# Valid for Ubuntu 22.04 +# Valid for Ubuntu 24.04 # #--------------------------------------------------------------------- @@ -31,7 +31,7 @@ FROM ran-build:latest AS enb-build #start from scratch for target executable -FROM ubuntu:jammy AS oai-enb +FROM ubuntu:noble AS oai-enb ARG BUILD_OPTION ENV DEBIAN_FRONTEND=noninteractive ENV TZ=Europe/Paris @@ -42,14 +42,14 @@ RUN apt-get update && \ software-properties-common \ procps \ libsctp1 \ - libboost-chrono1.74.0 \ - libboost-date-time1.74.0 \ - libboost-filesystem1.74.0 \ - libboost-regex1.74.0 \ - libboost-serialization1.74.0 \ - libboost-thread1.74.0 \ - libboost-system1.74.0 \ - libboost-program-options1.74.0 \ + libboost-chrono1.83.0 \ + libboost-date-time1.83.0 \ + libboost-filesystem1.83.0 \ + libboost-regex1.83.0 \ + libboost-serialization1.83.0 \ + libboost-thread1.83.0 \ + libboost-system1.83.0 \ + libboost-program-options1.83.0 \ tzdata \ libblas3 \ libconfig9 \ @@ -73,18 +73,12 @@ RUN apt-get update && \ apt-get remove -y wget && \ # if the --sanitize option was used to build, additional packages are required /bin/bash -c 'if [[ "$BUILD_OPTION" = "--sanitize" ]]; then DEBIAN_FRONTEND=noninteractive apt-get install --yes \ - #libasan5 \ # see below + libasan8 \ libubsan1 \ liblapacke; fi' && \ apt-get clean -y && \ rm -rf /var/lib/apt/lists/* -# we select another compile (gcc-12) for compilation, requiring another libasan -# library version. Installing it above would install the wrong version. Hence, -# copy the right version from ran-build. When upgrading to Ubuntu24, install -# the correct one above! -COPY --from=enb-build /usr/lib/x86_64-linux-gnu/libasan.so.8.0.0 /usr/lib/x86_64-linux-gnu/ - WORKDIR /opt/oai-enb/bin COPY --from=enb-build \ /oai-ran/cmake_targets/ran_build/build/lte-softmodem ./ diff --git a/docker/Dockerfile.gNB.aerial.ubuntu22 b/docker/Dockerfile.gNB.aerial.ubuntu24 similarity index 98% rename from docker/Dockerfile.gNB.aerial.ubuntu22 rename to docker/Dockerfile.gNB.aerial.ubuntu24 index 07bc569586..40cfbcf185 100644 --- a/docker/Dockerfile.gNB.aerial.ubuntu22 +++ b/docker/Dockerfile.gNB.aerial.ubuntu24 @@ -21,7 +21,7 @@ #--------------------------------------------------------------------- # # Dockerfile for the Open-Air-Interface BUILD service -# Valid for Ubuntu 22.04 +# Valid for Ubuntu 24.04 # #--------------------------------------------------------------------- @@ -59,7 +59,7 @@ RUN /bin/sh oaienv && \ #start from scratch for target executable -FROM ubuntu:jammy AS oai-gnb-aerial +FROM ubuntu:noble AS oai-gnb-aerial ENV DEBIAN_FRONTEND=noninteractive ENV TZ=Europe diff --git a/docker/Dockerfile.gNB.aerial.ubuntu22.sanitize-address b/docker/Dockerfile.gNB.aerial.ubuntu24.sanitize-address similarity index 98% rename from docker/Dockerfile.gNB.aerial.ubuntu22.sanitize-address rename to docker/Dockerfile.gNB.aerial.ubuntu24.sanitize-address index c8d35aee55..998b7bdd0c 100644 --- a/docker/Dockerfile.gNB.aerial.ubuntu22.sanitize-address +++ b/docker/Dockerfile.gNB.aerial.ubuntu24.sanitize-address @@ -21,7 +21,7 @@ #--------------------------------------------------------------------- # # Dockerfile for the Open-Air-Interface BUILD service -# Valid for Ubuntu 22.04 +# Valid for Ubuntu 24.04 # #--------------------------------------------------------------------- @@ -58,7 +58,7 @@ RUN /bin/sh oaienv && \ #start from scratch for target executable -FROM ubuntu:jammy AS oai-gnb-aerial +FROM ubuntu:noble AS oai-gnb-aerial ENV DEBIAN_FRONTEND=noninteractive ENV TZ=Europe diff --git a/docker/Dockerfile.gNB.aw2s.ubuntu22 b/docker/Dockerfile.gNB.aw2s.ubuntu24 similarity index 98% rename from docker/Dockerfile.gNB.aw2s.ubuntu22 rename to docker/Dockerfile.gNB.aw2s.ubuntu24 index 11893171db..ca87176258 100644 --- a/docker/Dockerfile.gNB.aw2s.ubuntu22 +++ b/docker/Dockerfile.gNB.aw2s.ubuntu24 @@ -21,7 +21,7 @@ #--------------------------------------------------------------------- # # Dockerfile for the Open-Air-Interface BUILD service -# Valid for Ubuntu 22.04 +# Valid for Ubuntu 24.04 # #--------------------------------------------------------------------- @@ -38,7 +38,7 @@ RUN /bin/sh oaienv && \ ./build_oai -w AW2SORI -t Ethernet #start from scratch for target executable -FROM ubuntu:jammy as oai-gnb-aw2s +FROM ubuntu:noble as oai-gnb-aw2s ENV DEBIAN_FRONTEND=noninteractive ENV TZ=Europe diff --git a/docker/Dockerfile.gNB.fhi72.ubuntu22 b/docker/Dockerfile.gNB.fhi72.ubuntu24 similarity index 98% rename from docker/Dockerfile.gNB.fhi72.ubuntu22 rename to docker/Dockerfile.gNB.fhi72.ubuntu24 index eb781281ec..c83da9004a 100644 --- a/docker/Dockerfile.gNB.fhi72.ubuntu22 +++ b/docker/Dockerfile.gNB.fhi72.ubuntu24 @@ -21,7 +21,7 @@ #--------------------------------------------------------------------- # # Dockerfile for the Open-Air-Interface 7.2 Fronthaul -# Valid for Ubuntu22.04 +# Valid for Ubuntu24.04 # #--------------------------------------------------------------------- @@ -31,7 +31,7 @@ FROM ran-build-fhi72:latest AS gnb-build #start from scratch for target executable -FROM ubuntu:jammy AS oai-gnb +FROM ubuntu:noble AS oai-gnb ARG BUILD_OPTION ENV DEBIAN_FRONTEND=noninteractive ENV TZ=Europe @@ -62,7 +62,7 @@ RUN apt-get update && \ libyaml-cpp-dev && \ # if the --sanitize option was used to build, additional packages are required /bin/bash -c 'if [[ "$BUILD_OPTION" = "--sanitize" ]]; then DEBIAN_FRONTEND=noninteractive apt-get install --yes \ - libasan5 \ + libasan8 \ libubsan1 \ liblapacke; fi' && \ rm -rf /var/lib/apt/lists/* diff --git a/docker/Dockerfile.gNB.ubuntu22 b/docker/Dockerfile.gNB.ubuntu24 similarity index 79% rename from docker/Dockerfile.gNB.ubuntu22 rename to docker/Dockerfile.gNB.ubuntu24 index ea7b538c41..977c53083d 100644 --- a/docker/Dockerfile.gNB.ubuntu22 +++ b/docker/Dockerfile.gNB.ubuntu24 @@ -21,7 +21,7 @@ #--------------------------------------------------------------------- # # Dockerfile for the Open-Air-Interface BUILD service -# Valid for Ubuntu20.04 +# Valid for Ubuntu24.04 # #--------------------------------------------------------------------- @@ -31,7 +31,7 @@ FROM ran-build:latest AS gnb-build #start from scratch for target executable -FROM ubuntu:jammy AS oai-gnb +FROM ubuntu:noble AS oai-gnb ARG BUILD_OPTION ENV DEBIAN_FRONTEND=noninteractive ENV TZ=Europe/Paris @@ -42,14 +42,14 @@ RUN apt-get update && \ software-properties-common \ procps \ libsctp1 \ - libboost-chrono1.74.0 \ - libboost-date-time1.74.0 \ - libboost-filesystem1.74.0 \ - libboost-regex1.74.0 \ - libboost-serialization1.74.0 \ - libboost-thread1.74.0 \ - libboost-system1.74.0 \ - libboost-program-options1.74.0 \ + libboost-chrono1.83.0 \ + libboost-date-time1.83.0 \ + libboost-filesystem1.83.0 \ + libboost-regex1.83.0 \ + libboost-serialization1.83.0 \ + libboost-thread1.83.0 \ + libboost-system1.83.0 \ + libboost-program-options1.83.0 \ tzdata \ libblas3 \ libconfig9 \ @@ -67,29 +67,12 @@ RUN apt-get update && \ libyaml-cpp-dev && \ # if the --sanitize option was used to build, additional packages are required /bin/bash -c 'if [[ "$BUILD_OPTION" = "--sanitize" ]]; then DEBIAN_FRONTEND=noninteractive apt-get install --yes \ - #libasan5 \ # see below + libasan8 \ libubsan1 \ liblapacke; fi' && \ apt-get clean -y && \ rm -rf /var/lib/apt/lists/* -# we select another compile (gcc-12) for compilation, requiring another libasan -# library version. Installing it above would install the wrong version. Hence, -# copy the right version from ran-build. When upgrading to Ubuntu24, install -# the correct one above! -# note: this dockerfile should work for both x86 and arm, hence the glob below -# which should either match "x86_64" (x86) or "aarch64" (ARM); since the target -# directory needs to be also one of those two, but globs don't work in target -# directories, work around this with mv -COPY --from=gnb-build /usr/lib/*-linux-gnu/libasan.so.8.0.0 /usr/lib/ -ARG TARGETPLATFORM -RUN case "${TARGETPLATFORM}" in \ - "linux/amd64") TARGET_DIR=x86_64-linux-gnu ;; \ - "linux/arm64") TARGET_DIR=aarch64-linux-gnu ;; \ - *) exit 1 ;; \ - esac; \ - mv /usr/lib/libasan.so.8.0.0 /usr/lib/$TARGET_DIR/libasan.so.8.0.0 - WORKDIR /opt/oai-gnb/bin COPY --from=gnb-build \ /oai-ran/cmake_targets/ran_build/build/nr-softmodem ./ diff --git a/docker/Dockerfile.lteRU.ubuntu22 b/docker/Dockerfile.lteRU.ubuntu24 similarity index 86% rename from docker/Dockerfile.lteRU.ubuntu22 rename to docker/Dockerfile.lteRU.ubuntu24 index 0f5f68932a..80bdaafa9d 100644 --- a/docker/Dockerfile.lteRU.ubuntu22 +++ b/docker/Dockerfile.lteRU.ubuntu24 @@ -21,7 +21,7 @@ #--------------------------------------------------------------------- # # Dockerfile for the Open-Air-Interface BUILD service -# Valid for Ubuntu 22.04 +# Valid for Ubuntu 24.04 # #--------------------------------------------------------------------- @@ -31,7 +31,7 @@ FROM ran-build:latest AS ru-build #start from scratch for target executable -FROM ubuntu:jammy AS oai-lte-ru +FROM ubuntu:noble AS oai-lte-ru ENV DEBIAN_FRONTEND=noninteractive ENV TZ=Europe/Paris @@ -41,6 +41,14 @@ RUN apt-get update && \ tzdata \ procps \ software-properties-common \ + libboost-chrono1.83.0 \ + libboost-date-time1.83.0 \ + libboost-filesystem1.83.0 \ + libboost-regex1.83.0 \ + libboost-serialization1.83.0 \ + libboost-thread1.83.0 \ + libboost-system1.83.0 \ + libboost-program-options1.83.0 \ libblas3 \ libconfig9 \ net-tools \ @@ -71,15 +79,6 @@ COPY --from=ru-base /usr/local/bin/uhd_find_devices /usr/local/bin COPY --from=ru-base /usr/local/lib/libuhd.so.4.4.0 /usr/local/lib COPY --from=ru-base /usr/local/lib/uhd/utils/uhd_images_downloader.py /opt/oai-lte-ru/bin -COPY --from=ru-base \ - /usr/lib/x86_64-linux-gnu/libboost_chrono.so.1.74.0 \ - /usr/lib/x86_64-linux-gnu/libboost_date_time.so.1.74.0 \ - /usr/lib/x86_64-linux-gnu/libboost_filesystem.so.1.74.0 \ - /usr/lib/x86_64-linux-gnu/libboost_regex.so.1.74.0 \ - /usr/lib/x86_64-linux-gnu/libboost_serialization.so.1.74.0 \ - /usr/lib/x86_64-linux-gnu/libboost_thread.so.1.74.0 \ - /usr/lib/x86_64-linux-gnu/libboost_system.so.1.74.0 \ - /usr/lib/x86_64-linux-gnu/ RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so /usr/local/lib/liboai_device.so" && \ ldconfig && \ diff --git a/docker/Dockerfile.lteUE.ubuntu22 b/docker/Dockerfile.lteUE.ubuntu24 similarity index 85% rename from docker/Dockerfile.lteUE.ubuntu22 rename to docker/Dockerfile.lteUE.ubuntu24 index 27623dbd33..5faa43f0ab 100644 --- a/docker/Dockerfile.lteUE.ubuntu22 +++ b/docker/Dockerfile.lteUE.ubuntu24 @@ -21,7 +21,7 @@ #--------------------------------------------------------------------- # # Dockerfile for the Open-Air-Interface BUILD service -# Valid for Ubuntu20.04 +# Valid for Ubuntu24.04 # #--------------------------------------------------------------------- @@ -31,7 +31,7 @@ FROM ran-build:latest AS lte-ue-build #start from scratch for target executable -FROM ubuntu:jammy AS oai-lte-ue +FROM ubuntu:noble AS oai-lte-ue ARG BUILD_OPTION ENV DEBIAN_FRONTEND=noninteractive ENV TZ=Europe/Paris @@ -42,14 +42,14 @@ RUN apt-get update && \ software-properties-common \ procps \ libsctp1 \ - libboost-chrono1.74.0 \ - libboost-date-time1.74.0 \ - libboost-filesystem1.74.0 \ - libboost-regex1.74.0 \ - libboost-serialization1.74.0 \ - libboost-thread1.74.0 \ - libboost-system1.74.0 \ - libboost-program-options1.74.0 \ + libboost-chrono1.83.0 \ + libboost-date-time1.83.0 \ + libboost-filesystem1.83.0 \ + libboost-regex1.83.0 \ + libboost-serialization1.83.0 \ + libboost-thread1.83.0 \ + libboost-system1.83.0 \ + libboost-program-options1.83.0 \ tzdata \ liblapacke \ libblas3 \ @@ -59,7 +59,7 @@ RUN apt-get update && \ python3 \ python3-six \ python3-requests \ - libpython3.10 \ + libpython3.12 \ libusb-1.0-0 \ iputils-ping \ iproute2 \ @@ -74,18 +74,12 @@ RUN apt-get update && \ apt-get remove -y wget && \ # if the --sanitize option was used to build, additional packages are required /bin/bash -c 'if [[ "$BUILD_OPTION" = "--sanitize" ]]; then DEBIAN_FRONTEND=noninteractive apt-get install --yes \ - #libasan5 \ # see below + libasan8 \ libubsan1 \ liblapacke; fi' && \ apt-get clean -y && \ rm -rf /var/lib/apt/lists/* -# we select another compile (gcc-12) for compilation, requiring another libasan -# library version. Installing it above would install the wrong version. Hence, -# copy the right version from ran-build. When upgrading to Ubuntu24, install -# the correct one above! -COPY --from=lte-ue-build /usr/lib/x86_64-linux-gnu/libasan.so.8.0.0 /usr/lib/x86_64-linux-gnu/ - WORKDIR /opt/oai-lte-ue/bin COPY --from=lte-ue-build \ /oai-ran/cmake_targets/ran_build/build/lte-uesoftmodem \ diff --git a/docker/Dockerfile.nr-cuup.ubuntu22 b/docker/Dockerfile.nr-cuup.ubuntu24 similarity index 73% rename from docker/Dockerfile.nr-cuup.ubuntu22 rename to docker/Dockerfile.nr-cuup.ubuntu24 index 2952afa34b..e33fc508d0 100644 --- a/docker/Dockerfile.nr-cuup.ubuntu22 +++ b/docker/Dockerfile.nr-cuup.ubuntu24 @@ -21,7 +21,7 @@ #--------------------------------------------------------------------- # # Dockerfile for the Open-Air-Interface BUILD service -# Valid for Ubuntu20.04 +# Valid for Ubuntu24.04 # #--------------------------------------------------------------------- @@ -30,7 +30,7 @@ FROM ran-base:latest AS gnb-base FROM ran-build:latest AS gnb-build -FROM ubuntu:jammy AS oai-nr-cuup +FROM ubuntu:noble AS oai-nr-cuup ARG BUILD_OPTION ENV DEBIAN_FRONTEND=noninteractive ENV TZ=Europe @@ -45,27 +45,11 @@ RUN apt-get update && \ openssl && \ # if the --sanitize option was used to build, additional packages are required /bin/bash -c 'if [[ "$BUILD_OPTION" = "--sanitize" ]]; then DEBIAN_FRONTEND=noninteractive apt-get install --yes \ - #libasan5 \ see below + libasan8 \ libubsan1 \ liblapacke; fi' && \ rm -rf /var/lib/apt/lists/* -# we select another compile (gcc-12) for compilation, requiring another libasan -# library version. Installing it above would install the wrong version. Hence, -# copy the right version from ran-build. When upgrading to Ubuntu24, install -# the correct one above! -# note: this dockerfile should work for both x86 and arm, hence the glob below -# which should either match "x86_64" (x86) or "aarch64" (ARM); since the target -# directory needs to be also one of those two, but globs don't work in target -# directories, work around this with mv -COPY --from=gnb-build /usr/lib/*-linux-gnu/libasan.so.8.0.0 /usr/lib/ -ARG TARGETPLATFORM -RUN case "${TARGETPLATFORM}" in \ - "linux/amd64") TARGET_DIR=x86_64-linux-gnu ;; \ - "linux/arm64") TARGET_DIR=aarch64-linux-gnu ;; \ - *) exit 1 ;; \ - esac; \ - mv /usr/lib/libasan.so.8.0.0 /usr/lib/$TARGET_DIR/libasan.so.8.0.0 ## Copy E2 SM models COPY --from=gnb-build /usr/local/lib/flexric /usr/local/lib/flexric diff --git a/docker/Dockerfile.nrUE.ubuntu22 b/docker/Dockerfile.nrUE.ubuntu24 similarity index 78% rename from docker/Dockerfile.nrUE.ubuntu22 rename to docker/Dockerfile.nrUE.ubuntu24 index c3b6592753..061587f04b 100644 --- a/docker/Dockerfile.nrUE.ubuntu22 +++ b/docker/Dockerfile.nrUE.ubuntu24 @@ -21,7 +21,7 @@ #--------------------------------------------------------------------- # # Dockerfile for the Open-Air-Interface BUILD service -# Valid for Ubuntu 22.04 +# Valid for Ubuntu 24.04 # #--------------------------------------------------------------------- @@ -31,7 +31,7 @@ FROM ran-build:latest AS nr-ue-build #start from scratch for target executable -FROM ubuntu:jammy AS oai-nr-ue +FROM ubuntu:noble AS oai-nr-ue ARG BUILD_OPTION ENV DEBIAN_FRONTEND=noninteractive ENV TZ=Europe/Paris @@ -42,14 +42,14 @@ RUN apt-get update && \ software-properties-common \ procps \ libsctp1 \ - libboost-chrono1.74.0 \ - libboost-date-time1.74.0 \ - libboost-filesystem1.74.0 \ - libboost-regex1.74.0 \ - libboost-serialization1.74.0 \ - libboost-thread1.74.0 \ - libboost-system1.74.0 \ - libboost-program-options1.74.0 \ + libboost-chrono1.83.0 \ + libboost-date-time1.83.0 \ + libboost-filesystem1.83.0 \ + libboost-regex1.83.0 \ + libboost-serialization1.83.0 \ + libboost-thread1.83.0 \ + libboost-system1.83.0 \ + libboost-program-options1.83.0 \ tzdata \ liblapacke \ libblas3 \ @@ -68,28 +68,11 @@ RUN apt-get update && \ libyaml-cpp-dev && \ # if the --sanitize option was used to build, additional packages are required /bin/bash -c 'if [[ "$BUILD_OPTION" = "--sanitize" ]]; then DEBIAN_FRONTEND=noninteractive apt-get install --yes \ - #libasan5 \ # see below + libasan8 \ libubsan1; fi' && \ apt-get clean -y && \ rm -rf /var/lib/apt/lists/* -# we select another compile (gcc-12) for compilation, requiring another libasan -# library version. Installing it above would install the wrong version. Hence, -# copy the right version from ran-build. When upgrading to Ubuntu24, install -# the correct one above! -# note: this dockerfile should work for both x86 and arm, hence the glob below -# which should either match "x86_64" (x86) or "aarch64" (ARM); since the target -# directory needs to be also one of those two, but globs don't work in target -# directories, work around this with mv -COPY --from=nr-ue-build /usr/lib/*-linux-gnu/libasan.so.8.0.0 /usr/lib/ -ARG TARGETPLATFORM -RUN case "${TARGETPLATFORM}" in \ - "linux/amd64") TARGET_DIR=x86_64-linux-gnu ;; \ - "linux/arm64") TARGET_DIR=aarch64-linux-gnu ;; \ - *) exit 1 ;; \ - esac; \ - mv /usr/lib/libasan.so.8.0.0 /usr/lib/$TARGET_DIR/libasan.so.8.0.0 - WORKDIR /opt/oai-nr-ue/bin COPY --from=nr-ue-build \ /oai-ran/cmake_targets/ran_build/build/nr-uesoftmodem \ From bc9ae55723407df2e35fc4bf3d4c2a878ac0884a Mon Sep 17 00:00:00 2001 From: calvin_peyron Date: Fri, 8 Aug 2025 14:11:37 +0200 Subject: [PATCH 420/964] Remove redundancy As DEBIAN_FRONTEND has been set as environment variable, there is no need to use DEBIAN_FRONTEND=noninteractive inside RUN lines, it is redundant, hence it has been removed. --- ci-scripts/docker/Dockerfile.cppcheck.xenial | 4 ++-- ci-scripts/docker/Dockerfile.formatting.ubuntu24 | 4 ++-- docker/Dockerfile.base.ubuntu24 | 4 ++-- docker/Dockerfile.base.ubuntu24.cross-arm64 | 6 +++--- docker/Dockerfile.build.fhi72.native_arm.ubuntu24 | 4 ++-- docker/Dockerfile.build.fhi72.ubuntu24 | 4 ++-- docker/Dockerfile.eNB.ubuntu24 | 4 ++-- docker/Dockerfile.gNB.aerial.ubuntu24 | 4 ++-- docker/Dockerfile.gNB.aerial.ubuntu24.sanitize-address | 4 ++-- docker/Dockerfile.gNB.aw2s.ubuntu24 | 4 ++-- docker/Dockerfile.gNB.fhi72.ubuntu24 | 4 ++-- docker/Dockerfile.gNB.ubuntu24 | 4 ++-- docker/Dockerfile.lteRU.ubuntu24 | 4 ++-- docker/Dockerfile.lteUE.ubuntu24 | 4 ++-- docker/Dockerfile.nr-cuup.ubuntu24 | 4 ++-- docker/Dockerfile.nrUE.ubuntu24 | 4 ++-- 16 files changed, 33 insertions(+), 33 deletions(-) diff --git a/ci-scripts/docker/Dockerfile.cppcheck.xenial b/ci-scripts/docker/Dockerfile.cppcheck.xenial index 5a61532346..f2c5856358 100644 --- a/ci-scripts/docker/Dockerfile.cppcheck.xenial +++ b/ci-scripts/docker/Dockerfile.cppcheck.xenial @@ -30,8 +30,8 @@ FROM ubuntu:xenial AS oai-cppcheck ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update && \ - DEBIAN_FRONTEND=noninteractive apt-get upgrade --yes && \ - DEBIAN_FRONTEND=noninteractive apt-get install --yes \ + apt-get upgrade --yes && \ + apt-get install --yes \ build-essential \ vim \ cppcheck diff --git a/ci-scripts/docker/Dockerfile.formatting.ubuntu24 b/ci-scripts/docker/Dockerfile.formatting.ubuntu24 index 2f99a69026..382dcb3514 100644 --- a/ci-scripts/docker/Dockerfile.formatting.ubuntu24 +++ b/ci-scripts/docker/Dockerfile.formatting.ubuntu24 @@ -33,8 +33,8 @@ ARG TARGET_BRANCH ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update && \ - DEBIAN_FRONTEND=noninteractive apt-get upgrade --yes && \ - DEBIAN_FRONTEND=noninteractive apt-get install --yes \ + apt-get upgrade --yes && \ + apt-get install --yes \ gawk \ git diff --git a/docker/Dockerfile.base.ubuntu24 b/docker/Dockerfile.base.ubuntu24 index a1f6daa3c3..959b863368 100644 --- a/docker/Dockerfile.base.ubuntu24 +++ b/docker/Dockerfile.base.ubuntu24 @@ -36,8 +36,8 @@ ENV UHD_VERSION=4.4.0.0 #install developers pkg/repo RUN apt-get update && \ - DEBIAN_FRONTEND=noninteractive apt-get upgrade --yes && \ - DEBIAN_FRONTEND=noninteractive apt-get install --yes \ + apt-get upgrade --yes && \ + apt-get install --yes \ #gcc needed for build_oai build-essential \ ccache \ diff --git a/docker/Dockerfile.base.ubuntu24.cross-arm64 b/docker/Dockerfile.base.ubuntu24.cross-arm64 index 00c7290f5b..1365df71fe 100644 --- a/docker/Dockerfile.base.ubuntu24.cross-arm64 +++ b/docker/Dockerfile.base.ubuntu24.cross-arm64 @@ -34,7 +34,7 @@ ENV SIMDE_VERSION=389f360a66d4a3bec62b7d71ad8be877487809ba #install developers pkg/repo RUN apt-get update && \ - DEBIAN_FRONTEND=noninteractive apt-get upgrade --yes && \ + apt-get upgrade --yes && \ #enabling arm64 architecture dpkg --add-architecture arm64 && \ echo "deb [arch=arm64] http://ports.ubuntu.com/ noble main restricted\n" \ @@ -49,8 +49,8 @@ RUN apt-get update && \ sed -i -E "s/(deb)\ (http:.+)/\1\ [arch=amd64]\ \2/" /etc/apt/sources.list && \ sed -i '/^Components:/a Architectures: amd64' /etc/apt/sources.list.d/ubuntu.sources && \ apt-get update && \ - DEBIAN_FRONTEND=noninteractive apt-get upgrade --yes && \ - DEBIAN_FRONTEND=noninteractive apt-get install --yes \ + apt-get upgrade --yes && \ + apt-get install --yes \ build-essential \ psmisc \ git \ diff --git a/docker/Dockerfile.build.fhi72.native_arm.ubuntu24 b/docker/Dockerfile.build.fhi72.native_arm.ubuntu24 index f9f3dc3a8f..96f50fa485 100644 --- a/docker/Dockerfile.build.fhi72.native_arm.ubuntu24 +++ b/docker/Dockerfile.build.fhi72.native_arm.ubuntu24 @@ -32,8 +32,8 @@ ARG KPM_VERSION=KPM_V3_00 ENV DEBIAN_FRONTEND=noninteractive ENV TZ=Europe RUN apt-get update && \ - DEBIAN_FRONTEND=noninteractive apt-get upgrade --yes && \ - DEBIAN_FRONTEND=noninteractive apt-get install --yes \ + apt-get upgrade --yes && \ + apt-get install --yes \ meson \ wget \ xz-utils \ diff --git a/docker/Dockerfile.build.fhi72.ubuntu24 b/docker/Dockerfile.build.fhi72.ubuntu24 index b60553dc1c..7b3ade05b0 100644 --- a/docker/Dockerfile.build.fhi72.ubuntu24 +++ b/docker/Dockerfile.build.fhi72.ubuntu24 @@ -32,8 +32,8 @@ ARG KPM_VERSION=KPM_V3_00 ENV DEBIAN_FRONTEND=noninteractive ENV TZ=Europe RUN apt-get update && \ - DEBIAN_FRONTEND=noninteractive apt-get upgrade --yes && \ - DEBIAN_FRONTEND=noninteractive apt-get install --yes \ + apt-get upgrade --yes && \ + apt-get install --yes \ meson \ wget \ xz-utils \ diff --git a/docker/Dockerfile.eNB.ubuntu24 b/docker/Dockerfile.eNB.ubuntu24 index 0071d3abef..31e0adce30 100644 --- a/docker/Dockerfile.eNB.ubuntu24 +++ b/docker/Dockerfile.eNB.ubuntu24 @@ -37,8 +37,8 @@ ENV DEBIAN_FRONTEND=noninteractive ENV TZ=Europe/Paris RUN apt-get update && \ - DEBIAN_FRONTEND=noninteractive apt-get upgrade --yes && \ - DEBIAN_FRONTEND=noninteractive apt-get install --yes \ + apt-get upgrade --yes && \ + apt-get install --yes \ software-properties-common \ procps \ libsctp1 \ diff --git a/docker/Dockerfile.gNB.aerial.ubuntu24 b/docker/Dockerfile.gNB.aerial.ubuntu24 index 40cfbcf185..c31025e039 100644 --- a/docker/Dockerfile.gNB.aerial.ubuntu24 +++ b/docker/Dockerfile.gNB.aerial.ubuntu24 @@ -64,8 +64,8 @@ ENV DEBIAN_FRONTEND=noninteractive ENV TZ=Europe RUN apt-get update && \ - DEBIAN_FRONTEND=noninteractive apt-get upgrade --yes && \ - DEBIAN_FRONTEND=noninteractive apt-get install --yes \ + apt-get upgrade --yes && \ + apt-get install --yes \ software-properties-common \ procps \ libsctp1 \ diff --git a/docker/Dockerfile.gNB.aerial.ubuntu24.sanitize-address b/docker/Dockerfile.gNB.aerial.ubuntu24.sanitize-address index 998b7bdd0c..c2bbe7ac88 100644 --- a/docker/Dockerfile.gNB.aerial.ubuntu24.sanitize-address +++ b/docker/Dockerfile.gNB.aerial.ubuntu24.sanitize-address @@ -63,8 +63,8 @@ ENV DEBIAN_FRONTEND=noninteractive ENV TZ=Europe RUN apt-get update && \ - DEBIAN_FRONTEND=noninteractive apt-get upgrade --yes && \ - DEBIAN_FRONTEND=noninteractive apt-get install --yes \ + apt-get upgrade --yes && \ + apt-get install --yes \ software-properties-common \ procps \ libsctp1 \ diff --git a/docker/Dockerfile.gNB.aw2s.ubuntu24 b/docker/Dockerfile.gNB.aw2s.ubuntu24 index ca87176258..70c3046508 100644 --- a/docker/Dockerfile.gNB.aw2s.ubuntu24 +++ b/docker/Dockerfile.gNB.aw2s.ubuntu24 @@ -43,8 +43,8 @@ ENV DEBIAN_FRONTEND=noninteractive ENV TZ=Europe RUN apt-get update && \ - DEBIAN_FRONTEND=noninteractive apt-get upgrade --yes && \ - DEBIAN_FRONTEND=noninteractive apt-get install --yes \ + apt-get upgrade --yes && \ + apt-get install --yes \ procps \ libsctp1 \ tzdata \ diff --git a/docker/Dockerfile.gNB.fhi72.ubuntu24 b/docker/Dockerfile.gNB.fhi72.ubuntu24 index c83da9004a..fb9d1d43f7 100644 --- a/docker/Dockerfile.gNB.fhi72.ubuntu24 +++ b/docker/Dockerfile.gNB.fhi72.ubuntu24 @@ -37,8 +37,8 @@ ENV DEBIAN_FRONTEND=noninteractive ENV TZ=Europe RUN apt-get update && \ - DEBIAN_FRONTEND=noninteractive apt-get upgrade --yes && \ - DEBIAN_FRONTEND=noninteractive apt-get install --yes \ + apt-get upgrade --yes && \ + apt-get install --yes \ software-properties-common \ procps \ pkg-config \ diff --git a/docker/Dockerfile.gNB.ubuntu24 b/docker/Dockerfile.gNB.ubuntu24 index 977c53083d..86fa6d8cbe 100644 --- a/docker/Dockerfile.gNB.ubuntu24 +++ b/docker/Dockerfile.gNB.ubuntu24 @@ -37,8 +37,8 @@ ENV DEBIAN_FRONTEND=noninteractive ENV TZ=Europe/Paris RUN apt-get update && \ - DEBIAN_FRONTEND=noninteractive apt-get upgrade --yes && \ - DEBIAN_FRONTEND=noninteractive apt-get install --yes \ + apt-get upgrade --yes && \ + apt-get install --yes \ software-properties-common \ procps \ libsctp1 \ diff --git a/docker/Dockerfile.lteRU.ubuntu24 b/docker/Dockerfile.lteRU.ubuntu24 index 80bdaafa9d..de7107f7fd 100644 --- a/docker/Dockerfile.lteRU.ubuntu24 +++ b/docker/Dockerfile.lteRU.ubuntu24 @@ -36,8 +36,8 @@ ENV DEBIAN_FRONTEND=noninteractive ENV TZ=Europe/Paris RUN apt-get update && \ - DEBIAN_FRONTEND=noninteractive apt-get upgrade --yes && \ - DEBIAN_FRONTEND=noninteractive apt-get install --yes \ + apt-get upgrade --yes && \ + apt-get install --yes \ tzdata \ procps \ software-properties-common \ diff --git a/docker/Dockerfile.lteUE.ubuntu24 b/docker/Dockerfile.lteUE.ubuntu24 index 5faa43f0ab..2b088ddf55 100644 --- a/docker/Dockerfile.lteUE.ubuntu24 +++ b/docker/Dockerfile.lteUE.ubuntu24 @@ -37,8 +37,8 @@ ENV DEBIAN_FRONTEND=noninteractive ENV TZ=Europe/Paris RUN apt-get update && \ - DEBIAN_FRONTEND=noninteractive apt-get upgrade --yes && \ - DEBIAN_FRONTEND=noninteractive apt-get install --yes \ + apt-get upgrade --yes && \ + apt-get install --yes \ software-properties-common \ procps \ libsctp1 \ diff --git a/docker/Dockerfile.nr-cuup.ubuntu24 b/docker/Dockerfile.nr-cuup.ubuntu24 index e33fc508d0..2c3c58e7e3 100644 --- a/docker/Dockerfile.nr-cuup.ubuntu24 +++ b/docker/Dockerfile.nr-cuup.ubuntu24 @@ -36,8 +36,8 @@ ENV DEBIAN_FRONTEND=noninteractive ENV TZ=Europe RUN apt-get update && \ - DEBIAN_FRONTEND=noninteractive apt-get upgrade --yes && \ - DEBIAN_FRONTEND=noninteractive apt-get install --yes \ + apt-get upgrade --yes && \ + apt-get install --yes \ libsctp1 \ libconfig9 \ iproute2 \ diff --git a/docker/Dockerfile.nrUE.ubuntu24 b/docker/Dockerfile.nrUE.ubuntu24 index 061587f04b..94876e9e14 100644 --- a/docker/Dockerfile.nrUE.ubuntu24 +++ b/docker/Dockerfile.nrUE.ubuntu24 @@ -37,8 +37,8 @@ ENV DEBIAN_FRONTEND=noninteractive ENV TZ=Europe/Paris RUN apt-get update && \ - DEBIAN_FRONTEND=noninteractive apt-get upgrade --yes && \ - DEBIAN_FRONTEND=noninteractive apt-get install --yes \ + apt-get upgrade --yes && \ + apt-get install --yes \ software-properties-common \ procps \ libsctp1 \ From 52107508837d762196f83354c0c936bba346f539 Mon Sep 17 00:00:00 2001 From: Calvin Peyron Date: Wed, 25 Jun 2025 10:40:52 +0200 Subject: [PATCH 421/964] Fix warning tmp may be uninitialized leads to error --- openair1/PHY/CODING/3gpplte_turbo_decoder_sse_16bit.c | 2 +- openair1/PHY/CODING/3gpplte_turbo_decoder_sse_8bit.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openair1/PHY/CODING/3gpplte_turbo_decoder_sse_16bit.c b/openair1/PHY/CODING/3gpplte_turbo_decoder_sse_16bit.c index 12cbe867a4..5a80f04a21 100644 --- a/openair1/PHY/CODING/3gpplte_turbo_decoder_sse_16bit.c +++ b/openair1/PHY/CODING/3gpplte_turbo_decoder_sse_16bit.c @@ -997,7 +997,7 @@ uint8_t phy_threegpplte_turbo_decoder16(int16_t *y, #elif defined(__arm__) || defined(__aarch64__) int16x8_t *yp128; // int16x8_t tmp128[(n+8)>>3]; - int16x8_t tmp, zeros=vdupq_n_s16(0); + int16x8_t tmp = {}, zeros = {}; const uint16_t __attribute__ ((aligned (16))) _Powers[8]= { 1, 2, 4, 8, 16, 32, 64, 128}; uint16x8_t Powers= vld1q_u16(_Powers); diff --git a/openair1/PHY/CODING/3gpplte_turbo_decoder_sse_8bit.c b/openair1/PHY/CODING/3gpplte_turbo_decoder_sse_8bit.c index 0180bed149..63ec8ade8e 100644 --- a/openair1/PHY/CODING/3gpplte_turbo_decoder_sse_8bit.c +++ b/openair1/PHY/CODING/3gpplte_turbo_decoder_sse_8bit.c @@ -930,7 +930,7 @@ uint8_t phy_threegpplte_turbo_decoder8(int16_t *y, #elif defined(__arm__) || defined(__aarch64__) int8x16_t *yp128; int8x16_t tmp128[(n+8)>>3]; - int8x16_t tmp, zeros=vdupq_n_s8(0); + int8x16_t tmp = {}, zeros = {}; const uint8_t __attribute__ ((aligned (16))) _Powers[16]= { 1, 2, 4, 8, 16, 32, 64, 128, 1, 2, 4, 8, 16, 32, 64, 128 }; // Set the powers of 2 (do it once for all, if applicable) From 3a1be4895f655db815971e644583885a9c499157 Mon Sep 17 00:00:00 2001 From: Calvin Peyron Date: Thu, 26 Jun 2025 08:48:14 +0200 Subject: [PATCH 422/964] Rename ubuntuXX to ubuntu --- ci-scripts/cls_containerize.py | 6 +-- ci-scripts/cls_static_code_analysis.py | 2 +- ....ubuntu24 => Dockerfile.formatting.ubuntu} | 0 ...st.ubuntu24 => Dockerfile.unittest.ubuntu} | 0 .../local_common_overrides/build_images.yaml | 8 ++-- doc/Aerial_FAPI_Split_Tutorial.md | 4 +- doc/README.md | 2 +- doc/TESTBenches.md | 42 +++++++++---------- doc/cross-compile.md | 4 +- ...e.base.ubuntu24 => Dockerfile.base.ubuntu} | 0 ...m64 => Dockerfile.base.ubuntu.cross-arm64} | 0 ... Dockerfile.build.fhi72.native_arm.ubuntu} | 0 ...ubuntu24 => Dockerfile.build.fhi72.ubuntu} | 0 ...build.ubuntu24 => Dockerfile.build.ubuntu} | 0 ...64 => Dockerfile.build.ubuntu.cross-arm64} | 0 ...ile.eNB.ubuntu24 => Dockerfile.eNB.ubuntu} | 0 ....ubuntu24 => Dockerfile.gNB.aerial.ubuntu} | 0 ...erfile.gNB.aerial.ubuntu.sanitize-address} | 0 ...2s.ubuntu24 => Dockerfile.gNB.aw2s.ubuntu} | 0 ...2.ubuntu24 => Dockerfile.gNB.fhi72.ubuntu} | 0 ...ile.gNB.ubuntu24 => Dockerfile.gNB.ubuntu} | 0 ...lteRU.ubuntu24 => Dockerfile.lteRU.ubuntu} | 0 ...lteUE.ubuntu24 => Dockerfile.lteUE.ubuntu} | 0 ...uup.ubuntu24 => Dockerfile.nr-cuup.ubuntu} | 0 ...e.nrUE.ubuntu24 => Dockerfile.nrUE.ubuntu} | 0 docker/README.md | 16 +++---- tools/docker-dev-env/README.md | 2 +- tools/docker-dev-env/bootstrap.sh | 2 +- 28 files changed, 44 insertions(+), 44 deletions(-) rename ci-scripts/docker/{Dockerfile.formatting.ubuntu24 => Dockerfile.formatting.ubuntu} (100%) rename ci-scripts/docker/{Dockerfile.unittest.ubuntu24 => Dockerfile.unittest.ubuntu} (100%) rename docker/{Dockerfile.base.ubuntu24 => Dockerfile.base.ubuntu} (100%) rename docker/{Dockerfile.base.ubuntu24.cross-arm64 => Dockerfile.base.ubuntu.cross-arm64} (100%) rename docker/{Dockerfile.build.fhi72.native_arm.ubuntu24 => Dockerfile.build.fhi72.native_arm.ubuntu} (100%) rename docker/{Dockerfile.build.fhi72.ubuntu24 => Dockerfile.build.fhi72.ubuntu} (100%) rename docker/{Dockerfile.build.ubuntu24 => Dockerfile.build.ubuntu} (100%) rename docker/{Dockerfile.build.ubuntu24.cross-arm64 => Dockerfile.build.ubuntu.cross-arm64} (100%) rename docker/{Dockerfile.eNB.ubuntu24 => Dockerfile.eNB.ubuntu} (100%) rename docker/{Dockerfile.gNB.aerial.ubuntu24 => Dockerfile.gNB.aerial.ubuntu} (100%) rename docker/{Dockerfile.gNB.aerial.ubuntu24.sanitize-address => Dockerfile.gNB.aerial.ubuntu.sanitize-address} (100%) rename docker/{Dockerfile.gNB.aw2s.ubuntu24 => Dockerfile.gNB.aw2s.ubuntu} (100%) rename docker/{Dockerfile.gNB.fhi72.ubuntu24 => Dockerfile.gNB.fhi72.ubuntu} (100%) rename docker/{Dockerfile.gNB.ubuntu24 => Dockerfile.gNB.ubuntu} (100%) rename docker/{Dockerfile.lteRU.ubuntu24 => Dockerfile.lteRU.ubuntu} (100%) rename docker/{Dockerfile.lteUE.ubuntu24 => Dockerfile.lteUE.ubuntu} (100%) rename docker/{Dockerfile.nr-cuup.ubuntu24 => Dockerfile.nr-cuup.ubuntu} (100%) rename docker/{Dockerfile.nrUE.ubuntu24 => Dockerfile.nrUE.ubuntu} (100%) diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index d3168f60a3..a4e1ddea8b 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -298,7 +298,7 @@ class Containerize(): self.host = result.group(0) if self.host == 'Ubuntu': self.cli = 'docker' - self.dockerfileprefix = '.ubuntu24' + self.dockerfileprefix = '.ubuntu' self.cliBuildOptions = '' elif self.host == 'Red Hat': self.cli = 'sudo podman' @@ -337,7 +337,7 @@ class Containerize(): imageNames.append(('oai-gnb', 'gNB.fhi72', 'oai-gnb-fhi72', '')) result = re.search('build_cross_arm64', self.imageKind) if result is not None: - self.dockerfileprefix = '.ubuntu22.cross-arm64' + self.dockerfileprefix = '.ubuntu.cross-arm64' result = re.search('native_arm', self.imageKind) if result is not None: imageNames.append(('oai-gnb', 'gNB', 'oai-gnb', '')) @@ -625,7 +625,7 @@ class Containerize(): return False # build ran-unittests image - dockerfile = "ci-scripts/docker/Dockerfile.unittest.ubuntu24" + dockerfile = "ci-scripts/docker/Dockerfile.unittest.ubuntu" logfile = f'{lSourcePath}/cmake_targets/log/unittest-build.log' ret = cmd.run(f'docker build --progress=plain --tag ran-unittests:{baseTag} --file {dockerfile} . &> {logfile}') archiveArtifact(cmd, ctx, logfile) diff --git a/ci-scripts/cls_static_code_analysis.py b/ci-scripts/cls_static_code_analysis.py index 8b0ec05352..62e9416082 100644 --- a/ci-scripts/cls_static_code_analysis.py +++ b/ci-scripts/cls_static_code_analysis.py @@ -212,7 +212,7 @@ class StaticCodeAnalysis(): logDir = f'{lSourcePath}/cmake_targets/log/' cmd.run(f'mkdir -p {logDir}') cmd.run('docker image rm oai-formatting-check:latest') - cmd.run(f'docker build --target oai-formatting-check --tag oai-formatting-check:latest {check_options} --file {lSourcePath}/ci-scripts/docker/Dockerfile.formatting.bionic {lSourcePath} > {logDir}/oai-formatting-check.txt 2>&1') + cmd.run(f'docker build --target oai-formatting-check --tag oai-formatting-check:latest {check_options} --file {lSourcePath}/ci-scripts/docker/Dockerfile.formatting.ubuntu {lSourcePath} > {logDir}/oai-formatting-check.txt 2>&1') cmd.run('docker image rm oai-formatting-check:latest') cmd.run('docker image prune --force') diff --git a/ci-scripts/docker/Dockerfile.formatting.ubuntu24 b/ci-scripts/docker/Dockerfile.formatting.ubuntu similarity index 100% rename from ci-scripts/docker/Dockerfile.formatting.ubuntu24 rename to ci-scripts/docker/Dockerfile.formatting.ubuntu diff --git a/ci-scripts/docker/Dockerfile.unittest.ubuntu24 b/ci-scripts/docker/Dockerfile.unittest.ubuntu similarity index 100% rename from ci-scripts/docker/Dockerfile.unittest.ubuntu24 rename to ci-scripts/docker/Dockerfile.unittest.ubuntu diff --git a/ci-scripts/yaml_files/local_common_overrides/build_images.yaml b/ci-scripts/yaml_files/local_common_overrides/build_images.yaml index a771289ae4..d738ccb2ff 100644 --- a/ci-scripts/yaml_files/local_common_overrides/build_images.yaml +++ b/ci-scripts/yaml_files/local_common_overrides/build_images.yaml @@ -3,7 +3,7 @@ services: image: ran-base build: context: ../../../ - dockerfile: docker/Dockerfile.base.ubuntu22 + dockerfile: docker/Dockerfile.base.ubuntu tags: - ran-base @@ -11,7 +11,7 @@ services: image: ran-build build: context: ../../../ - dockerfile: docker/Dockerfile.build.ubuntu22 + dockerfile: docker/Dockerfile.build.ubuntu tags: - ran-build depends_on: @@ -22,7 +22,7 @@ services: image: gnb-local build: context: ../../../ - dockerfile: docker/Dockerfile.gNB.ubuntu22 + dockerfile: docker/Dockerfile.gNB.ubuntu tags: - gnb-local depends_on: @@ -35,7 +35,7 @@ services: image: ue-local build: context: ../../../ - dockerfile: docker/Dockerfile.nrUE.ubuntu22 + dockerfile: docker/Dockerfile.nrUE.ubuntu tags: - ue-local depends_on: diff --git a/doc/Aerial_FAPI_Split_Tutorial.md b/doc/Aerial_FAPI_Split_Tutorial.md index 1d8132e38d..4192a8689f 100644 --- a/doc/Aerial_FAPI_Split_Tutorial.md +++ b/doc/Aerial_FAPI_Split_Tutorial.md @@ -213,8 +213,8 @@ With the nvIPC sources in the project directory, the docker image can be built. In order to build the target image (`oai-gnb-aerial`), first you should build a common shared image (`ran-base`) ```bash ~$ cd ~/openairinterface5g/ -~/openairinterface5g$ docker build . -f docker/Dockerfile.base.ubuntu22 --tag ran-base:latest -~/openairinterface5g$ docker build . -f docker/Dockerfile.gNB.aerial.ubuntu22 --tag oai-gnb-aerial:latest +~/openairinterface5g$ docker build . -f docker/Dockerfile.base.ubuntu --tag ran-base:latest +~/openairinterface5g$ docker build . -f docker/Dockerfile.gNB.aerial.ubuntu --tag oai-gnb-aerial:latest ``` diff --git a/doc/README.md b/doc/README.md index 40f838750a..f3e30b57ce 100644 --- a/doc/README.md +++ b/doc/README.md @@ -138,4 +138,4 @@ The other SDRs (AW2S, LimeSDR, ...) have no READMEs. - [formatting](../tools/formatting/README.md) is a clang-format error detection tool - [iwyu](../tools/iwyu/README.md) is a tool to detect `#include` errors -- [docker-dev-env](../tools/docker-dev-env/README.md) is a ubuntu22 docker development environment +- [docker-dev-env](../tools/docker-dev-env/README.md) is a ubuntu24 docker development environment diff --git a/doc/TESTBenches.md b/doc/TESTBenches.md index 2e0a26b2f9..f6a77c2d09 100644 --- a/doc/TESTBenches.md +++ b/doc/TESTBenches.md @@ -88,8 +88,8 @@ information on how the images are built. - [RAN-ARM-Cross-Compile-Builder](https://jenkins-oai.eurecom.fr/job/RAN-ARM-Cross-Compile-Builder/) ~BUILD-ONLY ~4G-LTE ~5G-NR ~nrUE - orion: Cross-compilation from Intel to ARM - - base image from `Dockerfile.base.ubuntu22.cross-arm64` - - build image from `Dockerfile.build.ubuntu22.cross-arm64` (no target images) + - base image from `Dockerfile.base.ubuntu.cross-arm64` + - build image from `Dockerfile.build.ubuntu.cross-arm64` (no target images) - [RAN-cppcheck](https://jenkins-oai.eurecom.fr/job/RAN-cppcheck/) ~BUILD-ONLY ~4G-LTE ~5G-NR ~nrUE - bellatrix @@ -112,29 +112,29 @@ information on how the images are built. - build image from `Dockerfile.clang.rhel9` (compilation only, artifacts not used currently) - [RAN-Ubuntu18-Image-Builder](https://jenkins-oai.eurecom.fr/job/RAN-Ubuntu18-Image-Builder/) ~BUILD-ONLY ~4G-LTE ~5G-NR ~nrUE - - run formatting check from `ci-scripts/docker/Dockerfile.formatting.bionic` + - run formatting check from `ci-scripts/docker/Dockerfile.formatting.ubuntu` - obelix: Ubuntu 22 image build using docker (Note: builds U22 images while pipeline is named U18!) - - base image from `Dockerfile.base.ubuntu22` - - build image from `Dockerfile.build.ubuntu22`, followed by - - target image from `Dockerfile.eNB.ubuntu22` - - target image from `Dockerfile.gNB.ubuntu22` - - target image from `Dockerfile.nr-cuup.ubuntu22` - - target image from `Dockerfile.nrUE.ubuntu22` - - target image from `Dockerfile.lteUE.ubuntu22` - - target image from `Dockerfile.lteRU.ubuntu22` - - target image from `Dockerfile.gNB.aerial.ubuntu22` - - build image from `Dockerfile.build.fhi72.ubuntu22`, followed by - - target image from `Dockerfile.gNB.fhi72.ubuntu22` - - build unit tests from `ci-scripts/docker/Dockerfile.unittest.ubuntu22`, and run them + - base image from `Dockerfile.base.ubuntu` + - build image from `Dockerfile.build.ubuntu`, followed by + - target image from `Dockerfile.eNB.ubuntu` + - target image from `Dockerfile.gNB.ubuntu` + - target image from `Dockerfile.nr-cuup.ubuntu` + - target image from `Dockerfile.nrUE.ubuntu` + - target image from `Dockerfile.lteUE.ubuntu` + - target image from `Dockerfile.lteRU.ubuntu` + - target image from `Dockerfile.gNB.aerial.ubuntu` + - build image from `Dockerfile.build.fhi72.ubuntu`, followed by + - target image from `Dockerfile.gNB.fhi72.ubuntu` + - build unit tests from `ci-scripts/docker/Dockerfile.unittest.ubuntu`, and run them - [RAN-Ubuntu-ARM-Image-Builder](https://jenkins-oai.eurecom.fr/job/RAN-Ubuntu-ARM-Image-Builder/) ~BUILD-ONLY ~4G-LTE ~5G-NR - gracehopper3-oai: ARM Ubuntu 22 image build using docker - - base image from `Dockerfile.base.ubuntu22` - - build image from `Dockerfile.build.ubuntu22`, followed by - - target image from `Dockerfile.gNB.ubuntu22` - - target image from `Dockerfile.nr-cuup.ubuntu22` - - target image from `Dockerfile.nrUE.ubuntu22` - - target image from `Dockerfile.gNB.aerial.ubuntu22` + - base image from `Dockerfile.base.ubuntu` + - build image from `Dockerfile.build.ubuntu`, followed by + - target image from `Dockerfile.gNB.ubuntu` + - target image from `Dockerfile.nr-cuup.ubuntu` + - target image from `Dockerfile.nrUE.ubuntu` + - target image from `Dockerfile.gNB.aerial.ubuntu` #### Image Test pipelines diff --git a/doc/cross-compile.md b/doc/cross-compile.md index ae8dbe5209..79c4bae761 100644 --- a/doc/cross-compile.md +++ b/doc/cross-compile.md @@ -97,5 +97,5 @@ ninja params_libconfig coding rfsimulator # Further information You can do the above steps using docker, see dockerfiles -`docker/Dockerfile.base.ubuntu22.cross-arm64` and -`docker/Dockerfile.build.ubuntu22.cross-arm64` for more information. +`docker/Dockerfile.base.ubuntu.cross-arm64` and +`docker/Dockerfile.build.ubuntu.cross-arm64` for more information. diff --git a/docker/Dockerfile.base.ubuntu24 b/docker/Dockerfile.base.ubuntu similarity index 100% rename from docker/Dockerfile.base.ubuntu24 rename to docker/Dockerfile.base.ubuntu diff --git a/docker/Dockerfile.base.ubuntu24.cross-arm64 b/docker/Dockerfile.base.ubuntu.cross-arm64 similarity index 100% rename from docker/Dockerfile.base.ubuntu24.cross-arm64 rename to docker/Dockerfile.base.ubuntu.cross-arm64 diff --git a/docker/Dockerfile.build.fhi72.native_arm.ubuntu24 b/docker/Dockerfile.build.fhi72.native_arm.ubuntu similarity index 100% rename from docker/Dockerfile.build.fhi72.native_arm.ubuntu24 rename to docker/Dockerfile.build.fhi72.native_arm.ubuntu diff --git a/docker/Dockerfile.build.fhi72.ubuntu24 b/docker/Dockerfile.build.fhi72.ubuntu similarity index 100% rename from docker/Dockerfile.build.fhi72.ubuntu24 rename to docker/Dockerfile.build.fhi72.ubuntu diff --git a/docker/Dockerfile.build.ubuntu24 b/docker/Dockerfile.build.ubuntu similarity index 100% rename from docker/Dockerfile.build.ubuntu24 rename to docker/Dockerfile.build.ubuntu diff --git a/docker/Dockerfile.build.ubuntu24.cross-arm64 b/docker/Dockerfile.build.ubuntu.cross-arm64 similarity index 100% rename from docker/Dockerfile.build.ubuntu24.cross-arm64 rename to docker/Dockerfile.build.ubuntu.cross-arm64 diff --git a/docker/Dockerfile.eNB.ubuntu24 b/docker/Dockerfile.eNB.ubuntu similarity index 100% rename from docker/Dockerfile.eNB.ubuntu24 rename to docker/Dockerfile.eNB.ubuntu diff --git a/docker/Dockerfile.gNB.aerial.ubuntu24 b/docker/Dockerfile.gNB.aerial.ubuntu similarity index 100% rename from docker/Dockerfile.gNB.aerial.ubuntu24 rename to docker/Dockerfile.gNB.aerial.ubuntu diff --git a/docker/Dockerfile.gNB.aerial.ubuntu24.sanitize-address b/docker/Dockerfile.gNB.aerial.ubuntu.sanitize-address similarity index 100% rename from docker/Dockerfile.gNB.aerial.ubuntu24.sanitize-address rename to docker/Dockerfile.gNB.aerial.ubuntu.sanitize-address diff --git a/docker/Dockerfile.gNB.aw2s.ubuntu24 b/docker/Dockerfile.gNB.aw2s.ubuntu similarity index 100% rename from docker/Dockerfile.gNB.aw2s.ubuntu24 rename to docker/Dockerfile.gNB.aw2s.ubuntu diff --git a/docker/Dockerfile.gNB.fhi72.ubuntu24 b/docker/Dockerfile.gNB.fhi72.ubuntu similarity index 100% rename from docker/Dockerfile.gNB.fhi72.ubuntu24 rename to docker/Dockerfile.gNB.fhi72.ubuntu diff --git a/docker/Dockerfile.gNB.ubuntu24 b/docker/Dockerfile.gNB.ubuntu similarity index 100% rename from docker/Dockerfile.gNB.ubuntu24 rename to docker/Dockerfile.gNB.ubuntu diff --git a/docker/Dockerfile.lteRU.ubuntu24 b/docker/Dockerfile.lteRU.ubuntu similarity index 100% rename from docker/Dockerfile.lteRU.ubuntu24 rename to docker/Dockerfile.lteRU.ubuntu diff --git a/docker/Dockerfile.lteUE.ubuntu24 b/docker/Dockerfile.lteUE.ubuntu similarity index 100% rename from docker/Dockerfile.lteUE.ubuntu24 rename to docker/Dockerfile.lteUE.ubuntu diff --git a/docker/Dockerfile.nr-cuup.ubuntu24 b/docker/Dockerfile.nr-cuup.ubuntu similarity index 100% rename from docker/Dockerfile.nr-cuup.ubuntu24 rename to docker/Dockerfile.nr-cuup.ubuntu diff --git a/docker/Dockerfile.nrUE.ubuntu24 b/docker/Dockerfile.nrUE.ubuntu similarity index 100% rename from docker/Dockerfile.nrUE.ubuntu24 rename to docker/Dockerfile.nrUE.ubuntu diff --git a/docker/README.md b/docker/README.md index 36ec65698a..2249fb9c25 100644 --- a/docker/README.md +++ b/docker/README.md @@ -78,7 +78,7 @@ Targets can be: The currently-supported OS are: - `rhel9` for Red Hat Enterprise Linux and Openshift Universal Base Image -- `ubuntu22` for Ubuntu 22.04 LTS +- `ubuntu` for Ubuntu 24.04 LTS - `rocky` for Rocky-Linux 9 For more details regarding the build on an Openshift Cluster, see [OpenShift README](../openshift/README.md). @@ -99,11 +99,11 @@ There are two shared images: one that has all dependencies, and a second that co git clone https://gitlab.eurecom.fr/oai/openairinterface5g.git cd openairinterface5g # default branch is develop, to change use git checkout -docker build --target ran-base --tag ran-base:latest --file docker/Dockerfile.base.ubuntu22 . +docker build --target ran-base --tag ran-base:latest --file docker/Dockerfile.base.ubuntu . # if you want use USRP, AW2S and RFSimulator radios -docker build --target ran-build --tag ran-build:latest --file docker/Dockerfile.build.ubuntu22 . +docker build --target ran-build --tag ran-build:latest --file docker/Dockerfile.build.ubuntu . # if you want to use front-haul 7.2 and RFSimulator radios -docker build --tag ran-build-fhi72:latest --file docker/Dockerfile.build.fhi72.ubuntu22 . +docker build --tag ran-build-fhi72:latest --file docker/Dockerfile.build.fhi72.ubuntu . ``` After building: @@ -126,7 +126,7 @@ This is only available for the Ubuntu version of Dockerfiles. You can, for example, create a `sanitizer` version of the ran-build image. ```bash -docker build --target ran-build --tag ran-build:latest --file docker/Dockerfile.build.ubuntu22 --build-arg "BUILD_OPTION=--sanitize" . +docker build --target ran-build --tag ran-build:latest --file docker/Dockerfile.build.ubuntu --build-arg "BUILD_OPTION=--sanitize" . ``` Currently the `--sanitize` option for `build_oai` enables: @@ -152,13 +152,13 @@ You can also use this docker build arguments to pass any available option(s) on For example, the eNB: ```bash -docker build --target oai-enb --tag oai-enb:latest --file docker/Dockerfile.eNB.ubuntu22 . +docker build --target oai-enb --tag oai-enb:latest --file docker/Dockerfile.eNB.ubuntu . ``` To build gNB/DU with 7.2 fronthaul support: ```bash -docker build --target oai-gnb-fhi72 --tag oai-gnb-fhi72:latest --file docker/Dockerfile.gNB.fhi72.ubuntu22 . +docker build --target oai-gnb-fhi72 --tag oai-gnb-fhi72:latest --file docker/Dockerfile.gNB.fhi72.ubuntu . ``` After a while: @@ -182,7 +182,7 @@ Note that the steps are identical for `rocky-linux`. If you have used the sanitizer option, then you should also pass it when building the target image: ```bash -docker build --target oai-gnb --tag oai-gnb:latest --file docker/Dockerfile.gNB.ubuntu22 --build-arg "BUILD_OPTION=--sanitize" . +docker build --target oai-gnb --tag oai-gnb:latest --file docker/Dockerfile.gNB.ubuntu --build-arg "BUILD_OPTION=--sanitize" . ``` Normally the target image will be around 200 Mbytes bigger. diff --git a/tools/docker-dev-env/README.md b/tools/docker-dev-env/README.md index 5dcb15eb5c..63bd598725 100644 --- a/tools/docker-dev-env/README.md +++ b/tools/docker-dev-env/README.md @@ -2,7 +2,7 @@ ## Description -This contains bash scripts for managing a ubuntu22 dockerized development enviroment for OAI. No need to install any +This contains bash scripts for managing a ubuntu24 dockerized development enviroment for OAI. No need to install any tools on host machines except for docker - `bootstrap.sh` - build development environment image and install the following bash aliases in `~/.bash_aliases`: diff --git a/tools/docker-dev-env/bootstrap.sh b/tools/docker-dev-env/bootstrap.sh index 8c21554dcf..e56be3fa91 100755 --- a/tools/docker-dev-env/bootstrap.sh +++ b/tools/docker-dev-env/bootstrap.sh @@ -11,7 +11,7 @@ fi if ! docker images | grep -q "ran-base"; then echo "ran-base:latest image not found. Building the image..." - docker build -f ../../docker/Dockerfile.base.ubuntu22 -t ran-base:latest ../../ + docker build -f ../../docker/Dockerfile.base.ubuntu -t ran-base:latest ../../ else echo "ran-base:latest image found." fi From 12cf0155251bd96cd58fe85cc0f5ee75c48f76bf Mon Sep 17 00:00:00 2001 From: calvin_peyron Date: Thu, 24 Jul 2025 14:37:42 +0200 Subject: [PATCH 423/964] "as" should be in capital letters --- docker/Dockerfile.gNB.aw2s.ubuntu | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/Dockerfile.gNB.aw2s.ubuntu b/docker/Dockerfile.gNB.aw2s.ubuntu index 70c3046508..b55977dfab 100644 --- a/docker/Dockerfile.gNB.aw2s.ubuntu +++ b/docker/Dockerfile.gNB.aw2s.ubuntu @@ -38,7 +38,7 @@ RUN /bin/sh oaienv && \ ./build_oai -w AW2SORI -t Ethernet #start from scratch for target executable -FROM ubuntu:noble as oai-gnb-aw2s +FROM ubuntu:noble AS oai-gnb-aw2s ENV DEBIAN_FRONTEND=noninteractive ENV TZ=Europe From c137020ca2199ed76af064a4de67f3c6fd4a614a Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 22 Apr 2025 12:34:53 +0200 Subject: [PATCH 424/964] remove fixed size H_awgn_mimo that may cause segfault in simulator in case of more than 4 antennas --- radio/rfsimulator/simulator.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/radio/rfsimulator/simulator.c b/radio/rfsimulator/simulator.c index ebc4f5016f..f7e035d375 100644 --- a/radio/rfsimulator/simulator.c +++ b/radio/rfsimulator/simulator.c @@ -991,15 +991,15 @@ static int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimest if (t->poll_telnetcmdq) t->poll_telnetcmdq(t->telnetcmd_qid, t); - for (int a = 0; a < nbAnt; a++) { // loop over number of Rx antennas + for (int a_rx = 0; a_rx < nbAnt; a_rx++) { // loop over number of Rx antennas if (ptr->channel_model != NULL) { // apply a channel model if (num_chanmod_channels == 0) { memset(temp_array, 0, sizeof(temp_array)); } num_chanmod_channels++; rxAddInput(ptr->circularBuf, - temp_array[a], - a, + temp_array[a_rx], + a_rx, ptr->channel_model, nsamps, t->nextRxTstamp, @@ -1008,7 +1008,7 @@ static int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimest } else { // no channel modeling int nbAnt_tx = ptr->th.nbAnt; // number of Tx antennas int firstIndex = (CirSize + t->nextRxTstamp - t->chan_offset) % CirSize; - sample_t *out = (sample_t *)samplesVoid[a]; + sample_t *out = (sample_t *)samplesVoid[a_rx]; if (nbAnt_tx == 1 && t->nb_cnx == 1) { // optimized for 1 Tx and 1 UE sample_t *firstSample = (sample_t *)&(ptr->circularBuf[firstIndex]); if (firstIndex + nsamps > CirSize) { @@ -1020,16 +1020,16 @@ static int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimest } } else { // SIMD (with simde) optimization might be added here later - double H_awgn_mimo[4][4] = {{1.0, 0.2, 0.1, 0.05}, // rx 0 - {0.2, 1.0, 0.2, 0.1}, // rx 1 - {0.1, 0.2, 1.0, 0.2}, // rx 2 - {0.05, 0.1, 0.2, 1.0}}; // rx 3 - - LOG_D(HW, "nbAnt_tx %d\n", nbAnt_tx); + LOG_D(HW, "nbAnt_tx %d nbAnt %d\n", nbAnt_tx, nbAnt); + double H_awgn_mimo_coeff[nbAnt_tx]; + for (int a_tx = 0; a_tx < nbAnt_tx; a_tx++) { + uint32_t ant_diff = abs(a_tx - a_rx); + H_awgn_mimo_coeff[a_tx] = ant_diff ? (0.2 / ant_diff) : 1.0; + } for (int i = 0; i < nsamps; i++) { // loop over nsamps for (int a_tx = 0; a_tx < nbAnt_tx; a_tx++) { // sum up signals from nbAnt_tx antennas - out[i].r += (short)(ptr->circularBuf[((firstIndex + i) * nbAnt_tx + a_tx) % CirSize].r * H_awgn_mimo[a][a_tx]); - out[i].i += (short)(ptr->circularBuf[((firstIndex + i) * nbAnt_tx + a_tx) % CirSize].i * H_awgn_mimo[a][a_tx]); + out[i].r += (short)(ptr->circularBuf[((firstIndex + i) * nbAnt_tx + a_tx) % CirSize].r * H_awgn_mimo_coeff[a_tx]); + out[i].i += (short)(ptr->circularBuf[((firstIndex + i) * nbAnt_tx + a_tx) % CirSize].i * H_awgn_mimo_coeff[a_tx]); } // end for a_tx } // end for i (number of samps) } // end of 1 tx antenna optimization From e2c4033b577c1848a22d8f4ddee91ad64e18ca3a Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Thu, 7 Aug 2025 12:16:11 +0200 Subject: [PATCH 425/964] When a client connects, we need to start the send/receive loop but the first reception is void data --- radio/rfsimulator/simulator.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/radio/rfsimulator/simulator.c b/radio/rfsimulator/simulator.c index f7e035d375..1a5c94f698 100644 --- a/radio/rfsimulator/simulator.c +++ b/radio/rfsimulator/simulator.c @@ -181,7 +181,7 @@ static buffer_t *allocCirBuf(rfsimulator_state_t *bridge, int sock) ptr->conn_sock = sock; ptr->lastReceivedTS = 0; ptr->headerMode = true; - ptr->trashingPacket = false; + ptr->trashingPacket = true; ptr->transferPtr = (char *)&ptr->th; ptr->remainToTransfer = sizeof(samplesBlockHeader_t); int sendbuff = SEND_BUFF_SIZE; @@ -980,7 +980,7 @@ static int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimest for (int sock = 0; sock < MAX_FD_RFSIMU; sock++) { buffer_t *ptr = &t->buf[sock]; - if (ptr->circularBuf) { + if (ptr->circularBuf && !ptr->trashingPacket) { bool reGenerateChannel = false; // fixme: when do we regenerate From c3e7fe47e6ab45a8c708b4c84a02f77f8594f2e3 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 6 Aug 2025 18:37:32 +0200 Subject: [PATCH 426/964] Remove unused Amarisoft CI XML file --- ci-scripts/xml_files/sa_cn5g_asue_start.xml | 47 --------------------- 1 file changed, 47 deletions(-) delete mode 100644 ci-scripts/xml_files/sa_cn5g_asue_start.xml diff --git a/ci-scripts/xml_files/sa_cn5g_asue_start.xml b/ci-scripts/xml_files/sa_cn5g_asue_start.xml deleted file mode 100644 index a9d3a88d5d..0000000000 --- a/ci-scripts/xml_files/sa_cn5g_asue_start.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - cn5g-start-tab - CN5G-Start - log-in - -100000 -000100 - - - - - - Initialize_5GCN - Initialize 5G Core - --type start-mini-as-ue --scenario 1 --capture /tmp/oai-cn5g-v1.5.pcap - - - - Custom_Command - Reboot USRP - asterix - ssh root@172.21.19.14 reboot ; sleep 45 - - - From 08428381d61253b05749eec58d9d51654b81db3d Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 6 Aug 2025 13:44:36 +0200 Subject: [PATCH 427/964] CI AW2S: modify configuration to have RedCap UEs connect --- ci-scripts/conf_files/gnb.sa.band78.51prb.aw2s.ddsuu.conf | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ci-scripts/conf_files/gnb.sa.band78.51prb.aw2s.ddsuu.conf b/ci-scripts/conf_files/gnb.sa.band78.51prb.aw2s.ddsuu.conf index 3bfe9ede51..c56f0e51b5 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.51prb.aw2s.ddsuu.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.51prb.aw2s.ddsuu.conf @@ -153,6 +153,11 @@ gNBs = ); + RedCap: { + cellBarredRedCap1Rx_r17 = 1; + cellBarredRedCap2Rx_r17 = 1; + intraFreqReselectionRedCap_r17 = 0; + } # ------- SCTP definitions SCTP : From 4a41df2788f2182baf8d8aebd18906ec7311db04 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 6 Aug 2025 13:52:34 +0200 Subject: [PATCH 428/964] Make some Amarisoft UEs RedCap UEs Change the parameters to be redcap (release: 17, redcap: "redcap") on some UEs, and modify the path to the updated configuration. Specifically, make UE 1 normal (no RedCap), UE 2 RedCap, UEs 3&4 normal, UEs 5&6 RedCap, etc. RedCap UEs should now only be able to connect if the gNB is handling Redcap UEs, which is done in the parent commit. --- ci-scripts/as_ue/aw2s-multi-00102-20.cfg | 40 ++++++++++++++---------- ci-scripts/ci_infra.yaml | 2 +- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/ci-scripts/as_ue/aw2s-multi-00102-20.cfg b/ci-scripts/as_ue/aw2s-multi-00102-20.cfg index c02a6b357d..5c8872d9ae 100644 --- a/ci-scripts/as_ue/aw2s-multi-00102-20.cfg +++ b/ci-scripts/as_ue/aw2s-multi-00102-20.cfg @@ -46,7 +46,7 @@ allow dynamic UE creation from remote API */ "sim_algo":"milenage", "op": "1006020f0a478bf6b699f15c062e42b3", - as_release: 15, + as_release: 17, ue_category: "nr", apn:"oai", attach_pdn_type:"ipv4", @@ -61,8 +61,9 @@ allow dynamic UE creation from remote API */ "sim_algo":"milenage", "op": "1006020f0a478bf6b699f15c062e42b3", - as_release: 15, + as_release: 17, ue_category: "nr", + redcap: "redcap", apn:"oai", attach_pdn_type:"ipv4", default_nssai: [ { sst: 1, }, ], @@ -76,7 +77,7 @@ allow dynamic UE creation from remote API */ "sim_algo":"milenage", "op": "1006020f0a478bf6b699f15c062e42b3", - as_release: 15, + as_release: 17, ue_category: "nr", apn:"oai", attach_pdn_type:"ipv4", @@ -91,7 +92,7 @@ allow dynamic UE creation from remote API */ "sim_algo":"milenage", "op": "1006020f0a478bf6b699f15c062e42b3", - as_release: 15, + as_release: 17, ue_category: "nr", apn:"oai", attach_pdn_type:"ipv4", @@ -106,8 +107,9 @@ allow dynamic UE creation from remote API */ "sim_algo":"milenage", "op": "1006020f0a478bf6b699f15c062e42b3", - as_release: 15, + as_release: 17, ue_category: "nr", + redcap: "redcap", apn:"oai", attach_pdn_type:"ipv4", default_nssai: [ { sst: 1, }, ], @@ -121,8 +123,9 @@ allow dynamic UE creation from remote API */ "sim_algo":"milenage", "op": "1006020f0a478bf6b699f15c062e42b3", - as_release: 15, + as_release: 17, ue_category: "nr", + redcap: "redcap", apn:"oai", attach_pdn_type:"ipv4", default_nssai: [ { sst: 1, }, ], @@ -136,7 +139,7 @@ allow dynamic UE creation from remote API */ "sim_algo":"milenage", "op": "1006020f0a478bf6b699f15c062e42b3", - as_release: 15, + as_release: 17, ue_category: "nr", apn:"oai", attach_pdn_type:"ipv4", @@ -151,7 +154,7 @@ allow dynamic UE creation from remote API */ "sim_algo":"milenage", "op": "1006020f0a478bf6b699f15c062e42b3", - as_release: 15, + as_release: 17, ue_category: "nr", apn:"oai", attach_pdn_type:"ipv4", @@ -166,7 +169,7 @@ allow dynamic UE creation from remote API */ "sim_algo":"milenage", "op": "1006020f0a478bf6b699f15c062e42b3", - as_release: 15, + as_release: 17, ue_category: "nr", apn:"oai", attach_pdn_type:"ipv4", @@ -181,8 +184,9 @@ allow dynamic UE creation from remote API */ "sim_algo":"milenage", "op": "1006020f0a478bf6b699f15c062e42b3", - as_release: 15, + as_release: 17, ue_category: "nr", + redcap: "redcap", apn:"oai", attach_pdn_type:"ipv4", default_nssai: [ { sst: 1, }, ], @@ -196,8 +200,9 @@ allow dynamic UE creation from remote API */ "sim_algo":"milenage", "op": "1006020f0a478bf6b699f15c062e42b3", - as_release: 15, + as_release: 17, ue_category: "nr", + redcap: "redcap", apn:"oai", attach_pdn_type:"ipv4", default_nssai: [ { sst: 1, }, ], @@ -211,8 +216,9 @@ allow dynamic UE creation from remote API */ "sim_algo":"milenage", "op": "1006020f0a478bf6b699f15c062e42b3", - as_release: 15, + as_release: 17, ue_category: "nr", + redcap: "redcap", apn:"oai", attach_pdn_type:"ipv4", default_nssai: [ { sst: 1, }, ], @@ -226,7 +232,7 @@ allow dynamic UE creation from remote API */ "sim_algo":"milenage", "op": "1006020f0a478bf6b699f15c062e42b3", - as_release: 15, + as_release: 17, ue_category: "nr", apn:"oai", attach_pdn_type:"ipv4", @@ -241,7 +247,7 @@ allow dynamic UE creation from remote API */ "sim_algo":"milenage", "op": "1006020f0a478bf6b699f15c062e42b3", - as_release: 15, + as_release: 17, ue_category: "nr", apn:"oai", attach_pdn_type:"ipv4", @@ -256,8 +262,9 @@ allow dynamic UE creation from remote API */ "sim_algo":"milenage", "op": "1006020f0a478bf6b699f15c062e42b3", - as_release: 15, + as_release: 17, ue_category: "nr", + redcap: "redcap", apn:"oai", attach_pdn_type:"ipv4", default_nssai: [ { sst: 1, }, ], @@ -271,8 +278,9 @@ allow dynamic UE creation from remote API */ "sim_algo":"milenage", "op": "1006020f0a478bf6b699f15c062e42b3", - as_release: 15, + as_release: 17, ue_category: "nr", + redcap: "redcap", apn:"oai", attach_pdn_type:"ipv4", default_nssai: [ { sst: 1, }, ], diff --git a/ci-scripts/ci_infra.yaml b/ci-scripts/ci_infra.yaml index 804852c937..9d39e9a781 100644 --- a/ci-scripts/ci_infra.yaml +++ b/ci-scripts/ci_infra.yaml @@ -147,7 +147,7 @@ ltebox-nepes: amarisoft_ue: Host: amariue - InitScript: /root/lteue-linux-2025-03-15/lteue /root/oaicicd/ran_sa_aw2s_asue_20MHz/aw2s-multi-00102-20.cfg & + InitScript: /root/lteue-linux-2025-03-15/lteue /root/oaicicd/ran_sa_aw2s_asue_20MHz_redcap/aw2s-multi-00102-20.cfg & TermScript: /root/lteue-linux-2025-03-15/ws.js -t 10 127.0.0.1:9002 '{"message":"quit"}' || killall -KILL lteue-avx2 NetworkScript: ip netns exec ue1 ip a show dev pdn0 amarisoft_ue_2x2: From 3b573798878839a5ae7ef65a05b8ed1eea880ce8 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 6 Aug 2025 17:12:03 +0200 Subject: [PATCH 429/964] CI AW2S-Amarisoft: verify RedCap'edness of a UE Since the parent commit, UE 1 is normal (no RedCap), UE 2 is RedCap. Verify that the gNB agrees with that and detects the second UE as RedCap by analyzing some logs. The first check is a bit elaborate, but basically is [ $(docker logs | grep XYZ | wc -l) -eq 0 ] ^ ^ ^ ^ ^ 1 2 3 4 5 (1) is the if statement, that compares (4) the number of occurrences (3) of "RedCap" in the (2) docker logs (5) to being equal to Note for all UEs which number, and whether it is RedCap (so this need to be kept in sync with the Amarisoft UE sim configuration file in use!). --- .../xml_files/container_sa_aw2s_asue.xml | 48 ++++++++++++------- 1 file changed, 32 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 88ab941e31..f6a2bde823 100644 --- a/ci-scripts/xml_files/container_sa_aw2s_asue.xml +++ b/ci-scripts/xml_files/container_sa_aw2s_asue.xml @@ -32,7 +32,9 @@ 120000 102000 102001 + 302001 102002 + 302002 102003 102004 102005 @@ -92,91 +94,105 @@ Attach_UE - Attach UE + Attach UE 1 amarisoft_ue_1 + + Custom_Command + Verify UE 1 is normal (no RedCap) + avra + [ $(docker logs oai-gnb-aw2s | grep -E "UE with RNTI [0-9a-f]{4} is RedCap" | wc -l) -eq 0 ] + + Attach_UE - Attach UE + Attach (RedCap) UE 2 amarisoft_ue_2 + + Custom_Command + Verify UE 2 is RedCap + avra + [ $(docker logs oai-gnb-aw2s | grep -m1 -E "UE with RNTI [0-9a-f]{4} is RedCap" | wc -l) -eq 1 ] + + Attach_UE - Attach UE + Attach UE 3 amarisoft_ue_3 Attach_UE - Attach UE + Attach UE 4 amarisoft_ue_4 Attach_UE - Attach UE + Attach (RedCap) UE 5 amarisoft_ue_5 Attach_UE - Attach UE + Attach (RedCap) UE 6 amarisoft_ue_6 Attach_UE - Attach UE + Attach UE 7 amarisoft_ue_7 Attach_UE - Attach UE + Attach UE 8 amarisoft_ue_8 Attach_UE - Attach UE + Attach UE 9 amarisoft_ue_9 Attach_UE - Attach UE + Attach (RedCap) UE 10 amarisoft_ue_10 Attach_UE - Attach UE + Attach (RedCap) UE 11 amarisoft_ue_11 Attach_UE - Attach UE + Attach (RedCap) UE 12 amarisoft_ue_12 Attach_UE - Attach UE + Attach UE 13 amarisoft_ue_13 Attach_UE - Attach UE + Attach UE 14 amarisoft_ue_14 Attach_UE - Attach UE + Attach (RedCap) UE 15 amarisoft_ue_15 @@ -233,7 +249,7 @@ Attach_UE - Attach UE + Attach (RedCap) UE 16 amarisoft_ue_16 From 4b85f353694ded16ba13d92ef14758e3bcfe7395 Mon Sep 17 00:00:00 2001 From: francescomani Date: Sat, 26 Jul 2025 11:36:31 +0200 Subject: [PATCH 430/964] add option to directly send the beam index to L1 via FAPI without look-up table (for 7.2 split) --- doc/analog_beamforming.md | 4 +++- openair2/GNB_APP/MACRLC_nr_paramdef.h | 2 +- openair2/GNB_APP/gnb_config.c | 7 +++++-- openair2/LAYER2/NR_MAC_gNB/config.c | 12 +++++------- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c | 4 ++-- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 18 +++++++++++------- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 2 +- openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 7 +++++++ 8 files changed, 35 insertions(+), 21 deletions(-) diff --git a/doc/analog_beamforming.md b/doc/analog_beamforming.md index 4ff208343e..45f93bf44c 100644 --- a/doc/analog_beamforming.md +++ b/doc/analog_beamforming.md @@ -17,11 +17,13 @@ Analog beamforming implementation also allows to enable distributed antenna syst A set of parameters in configuration files controls the implementation of analog beamforming and instructs the scheduler on how to behave in such scenarios. Since most notably this technique in 5G is employed in FR2, the configuration file example currently available is a RFsim one for band 261. [Config file example](../ci-scripts/conf_files/gnb.sa.band261.u3.32prb.rfsim.conf) In the `MACRLC` section of configuration files, there are three new parameters: `set_analog_beamforming`, `beam_duration` and `beams_per_period`. The explanation of these parameters is here provided: -- `set_analog_beamforming` can be set to 1 or 0 to activate or desactivate analog beamforming (default value is 0) +- `set_analog_beamforming` can be set a value equal to 1 or 2 to activate or 0 to desactivate analog beamforming (default value is 0) - `beam_duration` is the number of slots (currently minimum duration of a beam) the scheduler is tied to a beam (default value is 1) - `beams_per_period` is the number of concurrent beams the RU can handle in the beam duration (default value is 1) - `beam_weights` is a vector field containing the set of beam indices to be provided by the OAI L1 to the RU is also required. In current implementation, the number of beam indices should be equal to the number of SSBs transmitted +Setting analog beamforming to 1 or 2 changes the way FAPI beam index is treated. By setting 1, we instruct L1 to look up in Hi-PHY preconfigured DBM beam index. By setting 2, we instruct L2 to directly signal to Lo-PHY the beam index (e.g. over 7.2x fronthaul). + DAS is enabled by setting to 1 the parameter `enable_das` in the L1 section of the configuration file. In case of DAS enabled, the field `beam_weights` in `MACRLC` section can be omitted. # Implementation in OAI scheduler diff --git a/openair2/GNB_APP/MACRLC_nr_paramdef.h b/openair2/GNB_APP/MACRLC_nr_paramdef.h index c1382d7b70..a6299b10cc 100644 --- a/openair2/GNB_APP/MACRLC_nr_paramdef.h +++ b/openair2/GNB_APP/MACRLC_nr_paramdef.h @@ -141,7 +141,7 @@ {CONFIG_STRING_MACRLC_LOCAL_N_ADDRESS_F1U, NULL, 0, .strptr=NULL, .defstrval=NULL, TYPE_STRING, 0}, \ {CONFIG_STRING_MACRLC_TRANSPORT_S_SHM_PREFIX, NULL, 0, .strptr=NULL, .defstrval="nvipc", TYPE_STRING, 0}, \ {CONFIG_STRING_MACRLC_TRANSPORT_S_POLL_CORE, NULL, 0, .i8ptr=NULL, .defintval=-1, TYPE_INT8, 0}, \ - {CONFIG_STRING_MACRLC_ANALOG_BEAMFORMING, HLP_MACRLC_AB, PARAMFLAG_BOOL, .u8ptr=NULL, .defintval=0, TYPE_UINT8, 0}, \ + {CONFIG_STRING_MACRLC_ANALOG_BEAMFORMING, HLP_MACRLC_AB, 0, .u8ptr=NULL, .defintval=0, TYPE_UINT8, 0}, \ {CONFIG_STRING_MACRLC_BEAM_DURATION, HLP_MACRLC_BEAM_DURATION, 0, .u8ptr=NULL, .defintval=1, TYPE_UINT8, 0}, \ {CONFIG_STRING_MACRLC_BEAMS_PERIOD, HLP_MACRLC_BEAMS_PERIOD, 0, .u8ptr=NULL, .defintval=1, TYPE_UINT8, 0}, \ {CONFIG_STRING_MACRLC_BEAM_WEIGHTS_LIST, NULL, 0, .iptr=NULL, .defintarrayval=0, TYPE_INTARRAY,0}, \ diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 68d34a437a..e2a5f69ce4 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -1787,8 +1787,8 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg) LOG_I(NR_PHY, "Copying %d blacklisted PRB to L1 context\n", num_ulprbbl); memcpy(RC.nrmac[j]->ulprbbl, prbbl, MAX_BWP_SIZE * sizeof(prbbl[0])); } - bool ab = *MacRLC_ParamList.paramarray[j][MACRLC_ANALOG_BEAMFORMING_IDX].u8ptr; - if (ab) { + int ab = *MacRLC_ParamList.paramarray[j][MACRLC_ANALOG_BEAMFORMING_IDX].u8ptr; + if (ab > 0) { AssertFatal(NFAPI_MODE == NFAPI_MONOLITHIC, "Analog beamforming only supported for monolithic scenario\n"); NR_beam_info_t *beam_info = &RC.nrmac[j]->beam_info; int beams_per_period = *MacRLC_ParamList.paramarray[j][MACRLC_ANALOG_BEAMS_PERIOD_IDX].u8ptr; @@ -1796,6 +1796,9 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg) beam_info->beam_duration = *MacRLC_ParamList.paramarray[j][MACRLC_ANALOG_BEAM_DURATION_IDX].u8ptr; beam_info->beams_per_period = beams_per_period; beam_info->beam_allocation_size = -1; // to be initialized once we have information on frame configuration + beam_info->beam_mode = ab == 1 ? PRECONFIGURED_BEAM_IDX : LOPHY_BEAM_IDX; + } else { + RC.nrmac[j]->beam_info.beam_mode = NO_BEAM_MODE; } // TODO config_isparamset doesn't seem to work for array types, checking numelt instead int n = MacRLC_ParamList.paramarray[j][MACRLC_BEAMWEIGHTS_IDX].numelt; diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c index 99e4249bb2..54306c7f35 100644 --- a/openair2/LAYER2/NR_MAC_gNB/config.c +++ b/openair2/LAYER2/NR_MAC_gNB/config.c @@ -393,9 +393,7 @@ int get_ul_slot_offset(const frame_structure_t *fs, int idx, bool count_mixed) return ul_slot_idxs[ul_slot_idx_in_period] + period_idx * fs->numb_slots_period; } -static void config_common(gNB_MAC_INST *nrmac, - const nr_mac_config_t *config, - NR_ServingCellConfigCommon_t *scc) +static void config_common(gNB_MAC_INST *nrmac, const nr_mac_config_t *config, NR_ServingCellConfigCommon_t *scc) { nfapi_nr_config_request_scf_t *cfg = &nrmac->config[0]; nrmac->common_channels[0].ServingCellConfigCommon = scc; @@ -713,7 +711,7 @@ static void config_common(gNB_MAC_INST *nrmac, cfg->pmi_list = init_DL_MIMO_codebook(nrmac, pdsch_AntennaPorts); int nb_beams = config->nb_bfw[1]; // number of beams - if (nrmac->beam_info.beam_allocation) { + if (nrmac->beam_info.beam_mode == PRECONFIGURED_BEAM_IDX) { LOG_I(NR_MAC, "Configuring analog beamforming in config_request message\n"); cfg->analog_beamforming_ve.num_beams_period_vendor_ext.tl.tag = NFAPI_NR_FAPI_NUM_BEAMS_PERIOD_VENDOR_EXTENSION_TAG; cfg->analog_beamforming_ve.num_beams_period_vendor_ext.value = nrmac->beam_info.beams_per_period; @@ -740,7 +738,7 @@ static void config_common(gNB_MAC_INST *nrmac, static void initialize_beam_information(NR_beam_info_t *beam_info, int mu, int slots_per_frame) { - if (!beam_info->beam_allocation) + if (beam_info->beam_mode == NO_BEAM_MODE) return; int size = mu == 0 ? slots_per_frame << 1 : slots_per_frame; @@ -817,7 +815,7 @@ void nr_mac_config_scc(gNB_MAC_INST *nrmac, NR_ServingCellConfigCommon_t *scc, c nrmac->vrb_map_UL_size = size; int num_beams = 1; - if(nrmac->beam_info.beam_allocation) + if(nrmac->beam_info.beam_mode != NO_BEAM_MODE) num_beams = nrmac->beam_info.beams_per_period; for (int i = 0; i < num_beams; i++) { nrmac->common_channels[0].vrb_map_UL[i] = calloc(size * MAX_BWP_SIZE, sizeof(uint16_t)); @@ -834,7 +832,7 @@ void nr_mac_config_scc(gNB_MAC_INST *nrmac, NR_ServingCellConfigCommon_t *scc, c LOG_D(NR_MAC, "Configuring common parameters from NR ServingCellConfig\n"); config_common(nrmac, config, scc); - fapi_beam_index_allocation(scc, nrmac); + fapi_beam_index_allocation(scc, config, nrmac); if (NFAPI_MODE == NFAPI_MONOLITHIC) { // nothing to be sent in the other cases diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c index faaa00ea3f..46ad8069da 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c @@ -108,7 +108,7 @@ static void clear_beam_information(NR_beam_info_t *beam_info, int frame, int slo { // for now we use the same logic of UL_tti_req_ahead // reset after 1 frame with the exception of 15kHz - if(!beam_info->beam_allocation) + if (beam_info->beam_mode == NO_BEAM_MODE) return; // initialization done only once AssertFatal(beam_info->beam_allocation_size >= 0, "Beam information not initialized\n"); @@ -179,7 +179,7 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frame, slot_t slo for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { int num_beams = 1; - if(gNB->beam_info.beam_allocation) + if(gNB->beam_info.beam_mode != NO_BEAM_MODE) num_beams = gNB->beam_info.beams_per_period; // clear vrb_maps for (int i = 0; i < num_beams; i++) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index f8c842706c..61d393090c 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -3346,8 +3346,10 @@ int get_fapi_beamforming_index(gNB_MAC_INST *mac, int ssb_idx) // TODO this is a placeholder for a possibly more complex function // for now the fapi beam index is the number of SSBs transmitted before ssb_index i -void fapi_beam_index_allocation(NR_ServingCellConfigCommon_t *scc, gNB_MAC_INST *mac) +void fapi_beam_index_allocation(NR_ServingCellConfigCommon_t *scc, const nr_mac_config_t *config, gNB_MAC_INST *mac) { + if (mac->beam_info.beam_mode == NO_BEAM_MODE) + return; int len = 0; uint8_t* buf = NULL; switch (scc->ssb_PositionsInBurst->present) { @@ -3366,11 +3368,13 @@ void fapi_beam_index_allocation(NR_ServingCellConfigCommon_t *scc, gNB_MAC_INST default : AssertFatal(false, "Invalid configuration\n"); } - int fapi_index = 0; + int index = 0; for (int i = 0; i < len; ++i) { - if ((buf[i / 8] >> (7 - i % 8)) & 0x1) - mac->fapi_beam_index[i] = fapi_index++; - else + if ((buf[i / 8] >> (7 - i % 8)) & 0x1) { + int fapi_index = mac->beam_info.beam_mode == LOPHY_BEAM_IDX ? config->bw_list[index] : index; + mac->fapi_beam_index[i] = fapi_index; + index++; + } else mac->fapi_beam_index[i] = -1; } } @@ -3383,7 +3387,7 @@ static inline int get_beam_index(const NR_beam_info_t *beam_info, int frame, int NR_beam_alloc_t beam_allocation_procedure(NR_beam_info_t *beam_info, int frame, int slot, int beam_index, int slots_per_frame) { // if no beam allocation for analog beamforming we always return beam index 0 (no multiple beams) - if (!beam_info->beam_allocation) + if (beam_info->beam_mode == NO_BEAM_MODE) return (NR_beam_alloc_t) {.new_beam = false, .idx = 0}; const int index = get_beam_index(beam_info, frame, slot, slots_per_frame); @@ -3417,7 +3421,7 @@ void reset_beam_status(NR_beam_info_t *beam_info, int frame, int slot, int beam_ void beam_selection_procedures(gNB_MAC_INST *mac, NR_UE_info_t *UE) { // do not perform beam procedures if there is no beam information - if (!mac->beam_info.beam_allocation) + if (mac->beam_info.beam_mode == NO_BEAM_MODE) return; RSRP_report_t *rsrp_report = &UE->UE_sched_ctrl.CSI_report.ssb_rsrp_report; // simple beam switching algorithm -> we select beam with highest RSRP from CSI report diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 66a9262f22..8789906ae0 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -451,7 +451,7 @@ int get_mcs_from_bler(const NR_bler_options_t *bler_options, int ul_buffer_index(int frame, int slot, int slots_per_frame, int size); void UL_tti_req_ahead_initialization(gNB_MAC_INST *gNB, int n, int CCid, frame_t frameP, int slotP); -void fapi_beam_index_allocation(NR_ServingCellConfigCommon_t *scc, gNB_MAC_INST *mac); +void fapi_beam_index_allocation(NR_ServingCellConfigCommon_t *scc, const nr_mac_config_t *config, gNB_MAC_INST *mac); int get_fapi_beamforming_index(gNB_MAC_INST *mac, int ssb_idx); NR_beam_alloc_t beam_allocation_procedure(NR_beam_info_t *beam_info, int frame, int slot, int beam_index, int slots_per_frame); void reset_beam_status(NR_beam_info_t *beam_info, int frame, int slot, int beam_index, int slots_per_frame, bool new_beam); diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 84be6f4b5a..1a65d8582a 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -787,12 +787,19 @@ typedef struct { uid_allocator_t uid_allocator; } NR_UEs_t; +typedef enum { + NO_BEAM_MODE, + PRECONFIGURED_BEAM_IDX, + LOPHY_BEAM_IDX, +} nr_beam_mode_t; + typedef struct { /// list of allocated beams per period int **beam_allocation; int beam_duration; // in slots int beams_per_period; int beam_allocation_size; + nr_beam_mode_t beam_mode; } NR_beam_info_t; #define UE_iterator(BaSe, VaR) NR_UE_info_t ** VaR##pptr=BaSe, *VaR; while ((VaR=*(VaR##pptr++))) From 8f79abed2e74166abfc453efef864d2b131e5771 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Tue, 12 Aug 2025 15:40:13 +0200 Subject: [PATCH 431/964] CI: Update UHD version to 4.8 --- cmake_targets/tools/build_helper | 2 +- docker/Dockerfile.base.rhel9 | 2 +- docker/Dockerfile.base.rocky | 2 +- docker/Dockerfile.base.ubuntu22 | 2 +- docker/Dockerfile.eNB.rhel9 | 4 ++-- docker/Dockerfile.eNB.rocky | 4 ++-- docker/Dockerfile.eNB.ubuntu22 | 4 ++-- docker/Dockerfile.gNB.rhel9 | 4 ++-- docker/Dockerfile.gNB.rocky | 4 ++-- docker/Dockerfile.gNB.ubuntu22 | 4 ++-- docker/Dockerfile.lteRU.rhel9 | 4 ++-- docker/Dockerfile.lteRU.ubuntu22 | 4 ++-- docker/Dockerfile.lteUE.rhel9 | 4 ++-- docker/Dockerfile.lteUE.rocky | 4 ++-- docker/Dockerfile.lteUE.ubuntu22 | 4 ++-- docker/Dockerfile.nrUE.rhel9 | 4 ++-- docker/Dockerfile.nrUE.rocky | 4 ++-- docker/Dockerfile.nrUE.ubuntu22 | 4 ++-- 18 files changed, 32 insertions(+), 32 deletions(-) diff --git a/cmake_targets/tools/build_helper b/cmake_targets/tools/build_helper index f13dd314ef..03f9f76eb5 100755 --- a/cmake_targets/tools/build_helper +++ b/cmake_targets/tools/build_helper @@ -263,7 +263,7 @@ install_usrp_uhd_driver_from_source(){ # - 3.15.0.0 git apply $OPENAIR_DIR/cmake_targets/tools/uhd-3.15-tdd-patch.diff ret=$?;[[ $ret -ne 0 ]] && echo_fatal "Could not apply the TDD patch" - elif [[ "$UHD_VERSION" == "4.7.0.0" || "$UHD_VERSION" == "4.6.0.0" || "$UHD_VERSION" == "4.5.0.0" ]]; then + elif [[ "$UHD_VERSION" == "4.8.0.0" || "$UHD_VERSION" == "4.7.0.0" || "$UHD_VERSION" == "4.6.0.0" || "$UHD_VERSION" == "4.5.0.0" ]]; then # Tested that patch for the following versions: # - 4.7.0.0 cp $OPENAIR_DIR/cmake_targets/tools/uhd-4.x-tdd-patch.diff $OPENAIR_DIR/cmake_targets/tools/uhd-4.5plus-tdd-patch.diff diff --git a/docker/Dockerfile.base.rhel9 b/docker/Dockerfile.base.rhel9 index 28992918e2..dde540556b 100644 --- a/docker/Dockerfile.base.rhel9 +++ b/docker/Dockerfile.base.rhel9 @@ -32,7 +32,7 @@ ARG NEEDED_GIT_PROXY ARG TARGETARCH ENV TZ=Europe/Paris ENV BUILD_UHD_FROM_SOURCE=True -ENV UHD_VERSION=4.4.0.0 +ENV UHD_VERSION=4.8.0.0 # Copy the entitlements COPY ./etc-pki-entitlement /etc/pki/entitlement diff --git a/docker/Dockerfile.base.rocky b/docker/Dockerfile.base.rocky index 2d83389418..98a9ef703a 100644 --- a/docker/Dockerfile.base.rocky +++ b/docker/Dockerfile.base.rocky @@ -30,7 +30,7 @@ FROM $BASE_IMAGE AS ran-base ARG TARGETARCH ENV TZ=Europe/Paris ENV BUILD_UHD_FROM_SOURCE=True -ENV UHD_VERSION=4.4.0.0 +ENV UHD_VERSION=4.8.0.0 RUN dnf install 'dnf-command(config-manager)' -y && \ dnf install epel-release -y && crb enable && \ diff --git a/docker/Dockerfile.base.ubuntu22 b/docker/Dockerfile.base.ubuntu22 index ba8707d4db..2ea1ace533 100644 --- a/docker/Dockerfile.base.ubuntu22 +++ b/docker/Dockerfile.base.ubuntu22 @@ -32,7 +32,7 @@ ARG TARGETARCH ENV DEBIAN_FRONTEND=noninteractive ENV TZ=Europe/Paris ENV BUILD_UHD_FROM_SOURCE=True -ENV UHD_VERSION=4.4.0.0 +ENV UHD_VERSION=4.8.0.0 #install developers pkg/repo RUN apt-get update && \ diff --git a/docker/Dockerfile.eNB.rhel9 b/docker/Dockerfile.eNB.rhel9 index 391f2a6594..3cd1018634 100644 --- a/docker/Dockerfile.eNB.rhel9 +++ b/docker/Dockerfile.eNB.rhel9 @@ -90,7 +90,7 @@ COPY --from=enb-base \ # Now we are copying from builder-image the UHD files. COPY --from=enb-base /usr/local/bin/uhd_find_devices /usr/local/bin -COPY --from=enb-base /usr/local/lib64/libuhd.so.4.4.0 /usr/local/lib64 +COPY --from=enb-base /usr/local/lib64/libuhd.so.4.8.0 /usr/local/lib64 COPY --from=enb-base /usr/local/lib64/uhd/utils/uhd_images_downloader.py /opt/oai-enb/bin WORKDIR /usr/local/share/uhd/rfnoc @@ -111,7 +111,7 @@ RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so /usr/local/lib/liboai /usr/local/lib/liboai_iqplayer.so \ /usr/local/lib/libtelnetsrv.so \ /usr/local/lib/libtelnetsrv_enb.so \ - /usr/local/lib64/libuhd.so.4.4.0 + /usr/local/lib64/libuhd.so.4.8.0 WORKDIR /opt/oai-enb diff --git a/docker/Dockerfile.eNB.rocky b/docker/Dockerfile.eNB.rocky index eee61a7dda..1ff2b42e7a 100644 --- a/docker/Dockerfile.eNB.rocky +++ b/docker/Dockerfile.eNB.rocky @@ -91,7 +91,7 @@ COPY --from=enb-base \ # Now we are copying from builder-image the UHD files. COPY --from=enb-base /usr/local/bin/uhd_find_devices /usr/local/bin -COPY --from=enb-base /usr/local/lib64/libuhd.so.4.4.0 /usr/local/lib64 +COPY --from=enb-base /usr/local/lib64/libuhd.so.4.8.0 /usr/local/lib64 COPY --from=enb-base /usr/local/lib64/uhd/utils/uhd_images_downloader.py /opt/oai-enb/bin WORKDIR /usr/local/share/uhd/rfnoc @@ -112,7 +112,7 @@ RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so /usr/local/lib/liboai /usr/local/lib/liboai_iqplayer.so \ /usr/local/lib/libtelnetsrv.so \ /usr/local/lib/libtelnetsrv_enb.so \ - /usr/local/lib64/libuhd.so.4.4.0 + /usr/local/lib64/libuhd.so.4.8.0 WORKDIR /opt/oai-enb diff --git a/docker/Dockerfile.eNB.ubuntu22 b/docker/Dockerfile.eNB.ubuntu22 index 44797cd7f5..51dd3e445e 100644 --- a/docker/Dockerfile.eNB.ubuntu22 +++ b/docker/Dockerfile.eNB.ubuntu22 @@ -104,7 +104,7 @@ COPY --from=enb-build \ # Now we are copying from builder-image the UHD files. COPY --from=enb-base /usr/local/bin/uhd_find_devices /usr/local/bin -COPY --from=enb-base /usr/local/lib/libuhd.so.4.4.0 /usr/local/lib +COPY --from=enb-base /usr/local/lib/libuhd.so.4.8.0 /usr/local/lib COPY --from=enb-base /usr/local/lib/uhd/utils/uhd_images_downloader.py /opt/oai-enb/bin RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so /usr/local/lib/liboai_device.so" && \ @@ -121,7 +121,7 @@ RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so /usr/local/lib/liboai /usr/local/lib/liboai_iqplayer.so \ /usr/local/lib/libtelnetsrv.so \ /usr/local/lib/libtelnetsrv_enb.so \ - /usr/local/lib/libuhd.so.4.4.0 + /usr/local/lib/libuhd.so.4.8.0 WORKDIR /opt/oai-enb diff --git a/docker/Dockerfile.gNB.rhel9 b/docker/Dockerfile.gNB.rhel9 index d02b6907d7..1c201eeeab 100644 --- a/docker/Dockerfile.gNB.rhel9 +++ b/docker/Dockerfile.gNB.rhel9 @@ -97,7 +97,7 @@ COPY --from=gnb-base \ # Now we are copying from builder-image the UHD files. COPY --from=gnb-base /usr/local/bin/uhd_find_devices /usr/local/bin -COPY --from=gnb-base /usr/local/lib64/libuhd.so.4.4.0 /usr/local/lib64 +COPY --from=gnb-base /usr/local/lib64/libuhd.so.4.8.0 /usr/local/lib64 COPY --from=gnb-base /usr/local/lib64/uhd/utils/uhd_images_downloader.py /opt/oai-gnb/bin ## Copy E2 SM models @@ -120,7 +120,7 @@ RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so /usr/local/lib/liboai /usr/local/lib/libldpc*.so \ /usr/local/lib/libtelnetsrv.so \ /usr/local/lib/libtelnetsrv_ci.so \ - /usr/local/lib64/libuhd.so.4.4.0 + /usr/local/lib64/libuhd.so.4.8.0 WORKDIR /opt/oai-gnb #EXPOSE 2152/udp # S1U, GTP/UDP diff --git a/docker/Dockerfile.gNB.rocky b/docker/Dockerfile.gNB.rocky index 912de17ede..d005c36c9f 100644 --- a/docker/Dockerfile.gNB.rocky +++ b/docker/Dockerfile.gNB.rocky @@ -94,7 +94,7 @@ COPY --from=gnb-base \ # Now we are copying from builder-image the UHD files. COPY --from=gnb-base /usr/local/bin/uhd_find_devices /usr/local/bin -COPY --from=gnb-base /usr/local/lib64/libuhd.so.4.4.0 /usr/local/lib64 +COPY --from=gnb-base /usr/local/lib64/libuhd.so.4.8.0 /usr/local/lib64 COPY --from=gnb-base /usr/local/lib64/uhd/utils/uhd_images_downloader.py /opt/oai-gnb/bin WORKDIR /usr/local/share/uhd/rfnoc @@ -114,7 +114,7 @@ RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so /usr/local/lib/liboai /usr/local/lib/libldpc*.so \ /usr/local/lib/libtelnetsrv.so \ /usr/local/lib/libtelnetsrv_ci.so \ - /usr/local/lib64/libuhd.so.4.4.0 + /usr/local/lib64/libuhd.so.4.8.0 WORKDIR /opt/oai-gnb #EXPOSE 2152/udp # S1U, GTP/UDP diff --git a/docker/Dockerfile.gNB.ubuntu22 b/docker/Dockerfile.gNB.ubuntu22 index ea7b538c41..7b6425de59 100644 --- a/docker/Dockerfile.gNB.ubuntu22 +++ b/docker/Dockerfile.gNB.ubuntu22 @@ -116,7 +116,7 @@ COPY --from=gnb-build \ # Now we are copying from builder-image the UHD files. COPY --from=gnb-base /usr/local/bin/uhd_find_devices /usr/local/bin -COPY --from=gnb-base /usr/local/lib/libuhd.so.4.4.0 /usr/local/lib +COPY --from=gnb-base /usr/local/lib/libuhd.so.4.8.0 /usr/local/lib COPY --from=gnb-base /usr/local/lib/uhd/utils/uhd_images_downloader.py /opt/oai-gnb/bin ## Copy E2 SM models COPY --from=gnb-build /usr/local/lib/flexric /usr/local/lib/flexric @@ -135,7 +135,7 @@ RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so /usr/local/lib/liboai /usr/local/lib/libldpc*.so \ /usr/local/lib/libtelnetsrv.so \ /usr/local/lib/libtelnetsrv_ci.so \ - /usr/local/lib/libuhd.so.4.4.0 + /usr/local/lib/libuhd.so.4.8.0 WORKDIR /opt/oai-gnb #EXPOSE 2152/udp # S1U, GTP/UDP diff --git a/docker/Dockerfile.lteRU.rhel9 b/docker/Dockerfile.lteRU.rhel9 index 18ef1e8cfd..736ae2a884 100644 --- a/docker/Dockerfile.lteRU.rhel9 +++ b/docker/Dockerfile.lteRU.rhel9 @@ -80,7 +80,7 @@ COPY --from=ru-base \ # Copying from the ran-build image the USRP needed packages COPY --from=ru-base /usr/local/bin/uhd_find_devices /usr/local/bin -COPY --from=ru-base /usr/local/lib64/libuhd.so.4.4.0 /usr/local/lib64 +COPY --from=ru-base /usr/local/lib64/libuhd.so.4.8.0 /usr/local/lib64 COPY --from=ru-base /usr/local/lib64/uhd/utils/uhd_images_downloader.py /opt/oai-lte-ru/bin WORKDIR /usr/local/share/uhd/rfnoc @@ -96,7 +96,7 @@ RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so /usr/local/lib/liboai /usr/local/lib/liboai_usrpdevif.so \ /usr/local/lib/libparams_libconfig.so \ /usr/local/lib/libdfts.so \ - /usr/local/lib64/libuhd.so.4.4.0 + /usr/local/lib64/libuhd.so.4.8.0 WORKDIR /opt/oai-lte-ru diff --git a/docker/Dockerfile.lteRU.ubuntu22 b/docker/Dockerfile.lteRU.ubuntu22 index 0f5f68932a..71d99aa239 100644 --- a/docker/Dockerfile.lteRU.ubuntu22 +++ b/docker/Dockerfile.lteRU.ubuntu22 @@ -68,7 +68,7 @@ COPY --from=ru-build \ # Now we are copying from builder-image the UHD files. COPY --from=ru-base /usr/local/bin/uhd_find_devices /usr/local/bin -COPY --from=ru-base /usr/local/lib/libuhd.so.4.4.0 /usr/local/lib +COPY --from=ru-base /usr/local/lib/libuhd.so.4.8.0 /usr/local/lib COPY --from=ru-base /usr/local/lib/uhd/utils/uhd_images_downloader.py /opt/oai-lte-ru/bin COPY --from=ru-base \ @@ -91,7 +91,7 @@ RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so /usr/local/lib/liboai /usr/local/lib/liboai_usrpdevif.so \ /usr/local/lib/libparams_libconfig.so \ /usr/local/lib/libdfts.so \ - /usr/local/lib/libuhd.so.4.4.0 + /usr/local/lib/libuhd.so.4.8.0 WORKDIR /opt/oai-lte-ru diff --git a/docker/Dockerfile.lteUE.rhel9 b/docker/Dockerfile.lteUE.rhel9 index 56b7266331..7f1199c897 100644 --- a/docker/Dockerfile.lteUE.rhel9 +++ b/docker/Dockerfile.lteUE.rhel9 @@ -95,7 +95,7 @@ COPY --from=lte-ue-base \ # Now we are copying from builder-image the UHD files. COPY --from=lte-ue-base /usr/local/bin/uhd_find_devices /usr/local/bin -COPY --from=lte-ue-base /usr/local/lib64/libuhd.so.4.4.0 /usr/local/lib64 +COPY --from=lte-ue-base /usr/local/lib64/libuhd.so.4.8.0 /usr/local/lib64 COPY --from=lte-ue-base /usr/local/lib64/uhd/utils/uhd_images_downloader.py /opt/oai-lte-ue/bin WORKDIR /usr/local/share/uhd/rfnoc @@ -113,7 +113,7 @@ RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so /usr/local/lib/liboai /usr/local/lib/libparams_libconfig.so \ /usr/local/lib/libdfts.so \ /usr/local/lib/libtelnetsrv.so \ - /usr/local/lib64/libuhd.so.4.4.0 + /usr/local/lib64/libuhd.so.4.8.0 WORKDIR /opt/oai-lte-ue COPY --from=lte-ue-base /tini /tini diff --git a/docker/Dockerfile.lteUE.rocky b/docker/Dockerfile.lteUE.rocky index 39b99f4e0e..5f968b266a 100644 --- a/docker/Dockerfile.lteUE.rocky +++ b/docker/Dockerfile.lteUE.rocky @@ -96,7 +96,7 @@ COPY --from=lte-ue-base \ # Now we are copying from builder-image the UHD files. COPY --from=lte-ue-base /usr/local/bin/uhd_find_devices /usr/local/bin -COPY --from=lte-ue-base /usr/local/lib64/libuhd.so.4.4.0 /usr/local/lib64 +COPY --from=lte-ue-base /usr/local/lib64/libuhd.so.4.8.0 /usr/local/lib64 COPY --from=lte-ue-base /usr/local/lib64/uhd/utils/uhd_images_downloader.py /opt/oai-lte-ue/bin WORKDIR /usr/local/share/uhd/rfnoc @@ -114,7 +114,7 @@ RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so /usr/local/lib/liboai /usr/local/lib/libparams_libconfig.so \ /usr/local/lib/libdfts.so \ /usr/local/lib/libtelnetsrv.so \ - /usr/local/lib64/libuhd.so.4.4.0 + /usr/local/lib64/libuhd.so.4.8.0 WORKDIR /opt/oai-lte-ue COPY --from=lte-ue-base /tini /tini diff --git a/docker/Dockerfile.lteUE.ubuntu22 b/docker/Dockerfile.lteUE.ubuntu22 index 27623dbd33..9173228d7f 100644 --- a/docker/Dockerfile.lteUE.ubuntu22 +++ b/docker/Dockerfile.lteUE.ubuntu22 @@ -107,7 +107,7 @@ COPY --from=lte-ue-build \ # Now we are copying from builder-image the UHD files. COPY --from=lte-ue-base /usr/local/bin/uhd_find_devices /usr/local/bin -COPY --from=lte-ue-base /usr/local/lib/libuhd.so.4.4.0 /usr/local/lib +COPY --from=lte-ue-base /usr/local/lib/libuhd.so.4.8.0 /usr/local/lib COPY --from=lte-ue-base /usr/local/lib/uhd/utils/uhd_images_downloader.py /opt/oai-lte-ue/bin RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so /usr/local/lib/liboai_device.so" && \ @@ -122,7 +122,7 @@ RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so /usr/local/lib/liboai /usr/local/lib/libparams_libconfig.so \ /usr/local/lib/libdfts.so \ /usr/local/lib/libtelnetsrv.so \ - /usr/local/lib/libuhd.so.4.4.0 + /usr/local/lib/libuhd.so.4.8.0 WORKDIR /opt/oai-lte-ue COPY --from=lte-ue-base /tini /tini diff --git a/docker/Dockerfile.nrUE.rhel9 b/docker/Dockerfile.nrUE.rhel9 index 3a2900da27..0929ab3df0 100644 --- a/docker/Dockerfile.nrUE.rhel9 +++ b/docker/Dockerfile.nrUE.rhel9 @@ -99,7 +99,7 @@ COPY --from=nr-ue-base \ # Now we are copying from builder-image the UHD files. COPY --from=nr-ue-base /usr/local/bin/uhd_find_devices /usr/local/bin -COPY --from=nr-ue-base /usr/local/lib64/libuhd.so.4.4.0 /usr/local/lib64 +COPY --from=nr-ue-base /usr/local/lib64/libuhd.so.4.8.0 /usr/local/lib64 COPY --from=nr-ue-base /usr/local/lib64/uhd/utils/uhd_images_downloader.py /opt/oai-nr-ue/bin WORKDIR /usr/local/share/uhd/rfnoc @@ -119,7 +119,7 @@ RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so /usr/local/lib/liboai /usr/local/lib/libldpc*.so \ /usr/local/lib/libtelnetsrv.so \ /usr/local/lib/libtelnetsrv_5Gue.so \ - /usr/local/lib64/libuhd.so.4.4.0 + /usr/local/lib64/libuhd.so.4.8.0 WORKDIR /opt/oai-nr-ue COPY --from=nr-ue-base /tini /tini diff --git a/docker/Dockerfile.nrUE.rocky b/docker/Dockerfile.nrUE.rocky index 7f112af53a..bfe84dc011 100644 --- a/docker/Dockerfile.nrUE.rocky +++ b/docker/Dockerfile.nrUE.rocky @@ -96,7 +96,7 @@ COPY --from=nr-ue-base \ # Now we are copying from builder-image the UHD files. COPY --from=nr-ue-base /usr/local/bin/uhd_find_devices /usr/local/bin -COPY --from=nr-ue-base /usr/local/lib64/libuhd.so.4.4.0 /usr/local/lib64 +COPY --from=nr-ue-base /usr/local/lib64/libuhd.so.4.8.0 /usr/local/lib64 COPY --from=nr-ue-base /usr/local/lib64/uhd/utils/uhd_images_downloader.py /opt/oai-nr-ue/bin WORKDIR /usr/local/share/uhd/rfnoc @@ -116,7 +116,7 @@ RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so /usr/local/lib/liboai /usr/local/lib/libldpc*.so \ /usr/local/lib/libtelnetsrv.so \ /usr/local/lib/libtelnetsrv_5Gue.so \ - /usr/local/lib64/libuhd.so.4.4.0 + /usr/local/lib64/libuhd.so.4.8.0 WORKDIR /opt/oai-nr-ue COPY --from=nr-ue-base /tini /tini diff --git a/docker/Dockerfile.nrUE.ubuntu22 b/docker/Dockerfile.nrUE.ubuntu22 index c3b6592753..bdd5ab9693 100644 --- a/docker/Dockerfile.nrUE.ubuntu22 +++ b/docker/Dockerfile.nrUE.ubuntu22 @@ -115,7 +115,7 @@ COPY --from=nr-ue-build \ # Now we are copying from builder-image the UHD files. COPY --from=nr-ue-base /usr/local/bin/uhd_find_devices /usr/local/bin -COPY --from=nr-ue-base /usr/local/lib/libuhd.so.4.4.0 /usr/local/lib +COPY --from=nr-ue-base /usr/local/lib/libuhd.so.4.8.0 /usr/local/lib COPY --from=nr-ue-base /usr/local/lib/uhd/utils/uhd_images_downloader.py /opt/oai-nr-ue/bin RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so /usr/local/lib/liboai_device.so" && \ @@ -133,7 +133,7 @@ RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so /usr/local/lib/liboai /usr/local/lib/libtelnetsrv.so \ /usr/local/lib/libtelnetsrv_ciUE.so \ /usr/local/lib/libtelnetsrv_5Gue.so \ - /usr/local/lib/libuhd.so.4.4.0 + /usr/local/lib/libuhd.so.4.8.0 WORKDIR /opt/oai-nr-ue COPY --from=nr-ue-base /tini /tini From 071d28b3c9f2ab05142e0fc62e68bccb972141d0 Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 12 Aug 2025 12:28:10 +0200 Subject: [PATCH 432/964] print UE command line parameters also at MAC --- openair2/LAYER2/NR_MAC_gNB/config.c | 37 ++++++++++++++++++++++++++--- openair2/LAYER2/NR_MAC_gNB/main.c | 9 +++---- 2 files changed, 37 insertions(+), 9 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c index 99e4249bb2..69b139cb6e 100644 --- a/openair2/LAYER2/NR_MAC_gNB/config.c +++ b/openair2/LAYER2/NR_MAC_gNB/config.c @@ -393,9 +393,7 @@ int get_ul_slot_offset(const frame_structure_t *fs, int idx, bool count_mixed) return ul_slot_idxs[ul_slot_idx_in_period] + period_idx * fs->numb_slots_period; } -static void config_common(gNB_MAC_INST *nrmac, - const nr_mac_config_t *config, - NR_ServingCellConfigCommon_t *scc) +static void config_common(gNB_MAC_INST *nrmac, const nr_mac_config_t *config, NR_ServingCellConfigCommon_t *scc) { nfapi_nr_config_request_scf_t *cfg = &nrmac->config[0]; nrmac->common_channels[0].ServingCellConfigCommon = scc; @@ -736,6 +734,39 @@ static void config_common(gNB_MAC_INST *nrmac, cfg->num_tlv++; } } + + if (IS_SA_MODE(get_softmodem_params())) { + int bw = frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth; + uint64_t bw_khz = (12 * bw) * (15 << mu); + uint64_t carr_dl = (cfg->carrier_config.dl_frequency.value + bw_khz / 2) * 1000; + uint64_t carr_ul = (cfg->carrier_config.uplink_frequency.value + bw_khz / 2) * 1000; + int prb_offset = (frequency_range == FR1) ? + cfg->ssb_table.ssb_offset_point_a.value >> scs : + cfg->ssb_table.ssb_offset_point_a.value >> (scs - 2); + int sc_offset = (frequency_range == FR1) ? + cfg->ssb_table.ssb_subcarrier_offset.value >> scs : + cfg->ssb_table.ssb_subcarrier_offset.value; + if (cfg->carrier_config.dl_frequency.value != cfg->carrier_config.uplink_frequency.value) { + LOG_I(NR_MAC, + "Command line parameters for OAI UE: -C %lu --CO %ld -r %d --numerology %d --band %ld --ssb %d %s\n", + carr_dl, + carr_ul - carr_dl, + bw, + mu, + band, + 12 * prb_offset + sc_offset, + get_softmodem_params()->threequarter_fs ? "-E" : ""); + } else { + LOG_I(NR_MAC, + "Command line parameters for OAI UE: -C %lu -r %d --numerology %d --band %ld --ssb %d %s\n", + carr_dl, + bw, + mu, + band, + 12 * prb_offset + sc_offset, + get_softmodem_params()->threequarter_fs ? "-E" : ""); + } + } } static void initialize_beam_information(NR_beam_info_t *beam_info, int mu, int slots_per_frame) diff --git a/openair2/LAYER2/NR_MAC_gNB/main.c b/openair2/LAYER2/NR_MAC_gNB/main.c index c4f0fad659..3a8ed58e85 100644 --- a/openair2/LAYER2/NR_MAC_gNB/main.c +++ b/openair2/LAYER2/NR_MAC_gNB/main.c @@ -242,9 +242,6 @@ void mac_top_init_gNB(ngran_node_t node_type, const nr_mac_config_t *config, const nr_rlc_configuration_t *default_rlc_config) { - module_id_t i; - gNB_MAC_INST *nrmac; - AssertFatal(RC.nb_nr_macrlc_inst == 1, "what is the point of calling %s() if you don't need exactly one MAC?\n", __func__); if (RC.nb_nr_macrlc_inst > 0) { @@ -255,7 +252,7 @@ void mac_top_init_gNB(ngran_node_t node_type, RC.nb_nr_macrlc_inst * sizeof(gNB_MAC_INST *), RC.nb_nr_macrlc_inst, sizeof(gNB_MAC_INST)); - for (i = 0; i < RC.nb_nr_macrlc_inst; i++) { + for (module_id_t i = 0; i < RC.nb_nr_macrlc_inst; i++) { RC.nrmac[i] = (gNB_MAC_INST *) malloc16(sizeof(gNB_MAC_INST)); @@ -315,8 +312,8 @@ void mac_top_init_gNB(ngran_node_t node_type, } // Initialize Linked-List for Active UEs - for (i = 0; i < RC.nb_nr_macrlc_inst; i++) { - nrmac = RC.nrmac[i]; + for (module_id_t i = 0; i < RC.nb_nr_macrlc_inst; i++) { + gNB_MAC_INST *nrmac = RC.nrmac[i]; nrmac->if_inst = NR_IF_Module_init(i); memset(&nrmac->UE_info, 0, sizeof(nrmac->UE_info)); } From 748684df05750301246bbd65d4b415e7e0601d81 Mon Sep 17 00:00:00 2001 From: Romain Beurdouche Date: Tue, 29 Apr 2025 12:46:28 +0000 Subject: [PATCH 433/964] feat(time_meas): Standard deviation & merge `diff_square` was not merged in `merge_meas` so that calculation of the standard deviation was not working with merged timers. --- common/utils/time_meas.h | 1 + 1 file changed, 1 insertion(+) diff --git a/common/utils/time_meas.h b/common/utils/time_meas.h index f7c2810b60..de79a0252d 100644 --- a/common/utils/time_meas.h +++ b/common/utils/time_meas.h @@ -193,6 +193,7 @@ static inline void merge_meas(time_stats_t *dst_ts, const time_stats_t *src_ts) return; dst_ts->trials += src_ts->trials; dst_ts->diff += src_ts->diff; + dst_ts->diff_square += src_ts->diff_square; if (src_ts->max > dst_ts->max) dst_ts->max = src_ts->max; } From e79221b05b6d1bbd1d3850264b4ca6b360ba8291 Mon Sep 17 00:00:00 2001 From: Romain Beurdouche Date: Tue, 29 Apr 2025 12:51:10 +0000 Subject: [PATCH 434/964] feat(nr_ulsim): detailed ULSCH decoding timers Add timers to provide ULSCH decoding time split between decoding, rate recovery and deinterleaving. --- openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c | 4 ++++ openair1/PHY/defs_gNB.h | 3 +++ openair1/SIMULATION/NR_PHY/dlsim.c | 2 +- openair1/SIMULATION/NR_PHY/ulsim.c | 6 ++++++ 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c index 667c7146b0..239b6f2f29 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c @@ -305,6 +305,10 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, LOG_D(PHY, "ULSCH %d in error\n", ULSCH_id); } offset += ((harq_process->K >> 3) - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0)); + + merge_meas(&phy_vars_gNB->ts_deinterleave, &nrLDPC_segment_decoding_parameters.ts_deinterleave); + merge_meas(&phy_vars_gNB->ts_rate_unmatch, &nrLDPC_segment_decoding_parameters.ts_rate_unmatch); + merge_meas(&phy_vars_gNB->ts_ldpc_decode, &nrLDPC_segment_decoding_parameters.ts_ldpc_decode); } } diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h index ad17c243ae..987f77d953 100644 --- a/openair1/PHY/defs_gNB.h +++ b/openair1/PHY/defs_gNB.h @@ -521,6 +521,9 @@ typedef struct PHY_VARS_gNB_s { time_stats_t slot_indication_stats; time_stats_t schedule_response_stats; time_stats_t ulsch_decoding_stats; + time_stats_t ts_deinterleave; + time_stats_t ts_rate_unmatch; + time_stats_t ts_ldpc_decode; time_stats_t ulsch_deinterleaving_stats; time_stats_t ulsch_channel_estimation_stats; time_stats_t pusch_channel_estimation_antenna_processing_stats; diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index e355ca51c2..0f21fdb145 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -1341,7 +1341,7 @@ printf("%d\n", slot); printStatIndent3(&gNB->tprep,"DLSCH LDPC input preparation time"); printStatIndent3(&gNB->tparity,"DLSCH LDPC parity generation time"); printStatIndent3(&gNB->toutput,"DLSCH LDPC output generation time"); - printStatIndent3(&gNB->dlsch_rate_matching_stats,"DLSCH Rate Mataching time"); + printStatIndent3(&gNB->dlsch_rate_matching_stats,"DLSCH Rate Matching time"); printStatIndent3(&gNB->dlsch_interleaving_stats, "DLSCH Interleaving time"); printStatIndent2(&gNB->dlsch_modulation_stats,"DLSCH modulation time"); printStatIndent2(&gNB->dlsch_scrambling_stats, "DLSCH scrambling time"); diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index b2b2dc38bb..82500d1e32 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -1026,6 +1026,9 @@ int main(int argc, char *argv[]) reset_meas(&gNB->rx_pusch_init_stats); reset_meas(&gNB->rx_pusch_symbol_processing_stats); reset_meas(&gNB->ulsch_decoding_stats); + reset_meas(&gNB->ts_deinterleave); + reset_meas(&gNB->ts_rate_unmatch); + reset_meas(&gNB->ts_ldpc_decode); reset_meas(&gNB->ulsch_channel_estimation_stats); reset_meas(&gNB->pusch_channel_estimation_antenna_processing_stats); reset_meas(&gNB->rx_srs_stats); @@ -1587,6 +1590,9 @@ int main(int argc, char *argv[]) printStatIndent2(&gNB->rx_pusch_init_stats, "RX PUSCH Initialization time"); printStatIndent2(&gNB->rx_pusch_symbol_processing_stats, "RX PUSCH Symbol Processing time"); printStatIndent(&gNB->ulsch_decoding_stats,"ULSCH total decoding time"); + printStatIndent2(&gNB->ts_deinterleave, "ULSCH segment deinterleaving time"); + printStatIndent2(&gNB->ts_rate_unmatch, "ULSCH segment rate recovery time"); + printStatIndent2(&gNB->ts_ldpc_decode, "ULSCH segments decoding time"); printf("\nUE TX\n"); for (int i = PHY_PROC_TX; i <= OFDM_MOD_STATS; i++) { From ad8b76a8ef5cb189d295d13c296cf5a9c6f57ff5 Mon Sep 17 00:00:00 2001 From: Romain Beurdouche Date: Thu, 7 Aug 2025 13:55:56 +0200 Subject: [PATCH 435/964] feat(nr-gnb): Log decoding timers in the gNB Log the LDPC reversed interleaving, reversed rate matching and decoding time stats in nrL1_stats.log for the gNB. --- executables/nr-gnb.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index 345b58df7e..24870544b8 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -231,6 +231,9 @@ static size_t dump_L1_meas_stats(PHY_VARS_gNB *gNB, RU_t *ru, char *output, size output += print_meas_log(&gNB->dlsch_resource_mapping_stats, "DLSCH resource mapping", NULL, NULL, output,end-output); output += print_meas_log(&gNB->dlsch_precoding_stats, "DLSCH precoding", NULL, NULL, output,end-output); output += print_meas_log(&gNB->phy_proc_rx, "L1 Rx processing", NULL, NULL, output, end - output); + output += print_meas_log(&gNB->ts_deinterleave, "UL segment deinterleaving", NULL, NULL, output, end - output); + output += print_meas_log(&gNB->ts_rate_unmatch, "UL segment rate recovery", NULL, NULL, output, end - output); + output += print_meas_log(&gNB->ts_ldpc_decode, "UL segments decoding", NULL, NULL, output, end - output); output += print_meas_log(&gNB->ul_indication_stats, "UL Indication", NULL, NULL, output, end - output); output += print_meas_log(&gNB->slot_indication_stats, "Slot Indication", NULL, NULL, output, end - output); output += print_meas_log(&gNB->rx_pusch_stats, "PUSCH inner-receiver", NULL, NULL, output, end - output); @@ -288,6 +291,9 @@ void *nrL1_stats_thread(void *param) { reset_meas(&gNB->phy_proc_tx); reset_meas(&gNB->dlsch_encoding_stats); reset_meas(&gNB->phy_proc_rx); + reset_meas(&gNB->ts_deinterleave); + reset_meas(&gNB->ts_rate_unmatch); + reset_meas(&gNB->ts_ldpc_decode); reset_meas(&gNB->ul_indication_stats); reset_meas(&gNB->slot_indication_stats); reset_meas(&gNB->rx_pusch_stats); From e2c89f36eab4ae13e0f1e34c14d1e714449b0445 Mon Sep 17 00:00:00 2001 From: Romain Beurdouche Date: Thu, 7 Aug 2025 13:19:54 +0000 Subject: [PATCH 436/964] feat(ldpc_aal): add decoding timer --- .../nrLDPC_coding/nrLDPC_coding_aal/nrLDPC_coding_aal.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_aal/nrLDPC_coding_aal.c b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_aal/nrLDPC_coding_aal.c index 62a20ef822..815ec9ce26 100644 --- a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_aal/nrLDPC_coding_aal.c +++ b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_aal/nrLDPC_coding_aal.c @@ -815,6 +815,10 @@ static int pmd_lcore_ldpc_dec(void *arg) AssertFatal(ret == 0, "Allocation failed for %d ops", num_segments); set_ldpc_dec_op(ops_enq, bufs->inputs, bufs->hard_outputs, bufs->harq_outputs, nrLDPC_slot_decoding_parameters); + // Start timer + // We report timing only once in (0,0) since the timers are merged at the end + start_meas(&nrLDPC_slot_decoding_parameters->TBs[0].segments[0].ts_ldpc_decode); + uint16_t enq = 0, deq = 0; while (enq < num_segments) { uint16_t num_to_enq = num_segments - enq; @@ -828,6 +832,10 @@ static int pmd_lcore_ldpc_dec(void *arg) DevAssert(time_out <= TIME_OUT_POLL); } + // Stop timer + // We report timing only once in (0,0) since the timers are merged at the end + stop_meas(&nrLDPC_slot_decoding_parameters->TBs[0].segments[0].ts_ldpc_decode); + if (deq == enq) { ret = retrieve_ldpc_dec_op(ops_deq, nrLDPC_slot_decoding_parameters); AssertFatal(ret == 0, "LDPC offload decoder failed!"); From efccad956ac2ae60f14c0a3241f452285a81c812 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Tue, 12 Aug 2025 11:31:08 +0200 Subject: [PATCH 437/964] add gtpu error packet parsing and display --- openair3/ocp-gtpu/gtp_itf.cpp | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/openair3/ocp-gtpu/gtp_itf.cpp b/openair3/ocp-gtpu/gtp_itf.cpp index fec0f035eb..9e07a44747 100644 --- a/openair3/ocp-gtpu/gtp_itf.cpp +++ b/openair3/ocp-gtpu/gtp_itf.cpp @@ -77,6 +77,14 @@ typedef struct Gtpv1uExtHeader { uint8_t NextExtHeaderType; } __attribute__((packed)) Gtpv1uExtHeaderT; + typedef struct Gtpv1Error { + Gtpv1uMsgHeaderT h; + uint8_t teid_data_i; + teid_t teid; + uint8_t addr_data_i; + uint16_t addr_len; + } __attribute__((packed)) Gtpv1uError; + #pragma pack() // TS 29.281, fig 5.2.1-3 @@ -949,7 +957,21 @@ static int Gtpv1uHandleEchoReq(int h, uint8_t *msgBuf, uint32_t msgBufLen, const static int Gtpv1uHandleError(int h, uint8_t *msgBuf, uint32_t msgBufLen, const struct sockaddr_in *addr) { - LOG_E(GTPU, "Received GTP error indication (error handling is missing/not implemented)\n"); + if (msgBufLen < sizeof(Gtpv1uError)) + LOG_E(GTPU, "Received GTP error indication with truncated size %u (mini size: %lu)\n", msgBufLen,sizeof(Gtpv1uError)+4); + Gtpv1uError *msg = ( Gtpv1uError *)msgBuf; + LOG_E(GTPU, "Received GTP error indication: \n" + " TEID %u (must be 0 from TS 29.281)\n" + " TV id for TEID %u (must be 16)\n" + " TEID in error %u (should be a TEID we sent)\n" + " TV id for GTP addr %u (should be 133)\n" + " len for addr of UPF %u (should be IPv4 or IPv6 len)" + " (TS 29.281 Sec 7.3.1 Error Handling not implemented)\n", + msg->h.teid, + msg->teid_data_i, + msg->teid, + msg->addr_data_i, + msg->addr_len); int rc = GTPNOK; return rc; } From ce06099a99f0d142ecfb6d3d3f0e8ff70cac6062 Mon Sep 17 00:00:00 2001 From: Gabriele Gemmi Date: Tue, 8 Jul 2025 16:28:30 +0000 Subject: [PATCH 438/964] Configuration of FAPI Beamforming PDU for Aerial PBBF --- openair1/PHY/INIT/nr_init.c | 1 + openair2/GNB_APP/gnb_config.c | 3 ++- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 4 ++-- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c | 2 +- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 6 +++--- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c | 10 +++++----- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c | 2 +- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 4 ++-- 8 files changed, 17 insertions(+), 15 deletions(-) diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c index 7a706f61bf..dcdc4ee433 100644 --- a/openair1/PHY/INIT/nr_init.c +++ b/openair1/PHY/INIT/nr_init.c @@ -110,6 +110,7 @@ void phy_init_nr_gNB(PHY_VARS_gNB *gNB) common_vars->analog_bf = cfg->analog_beamforming_ve.analog_bf_vendor_ext.value; LOG_I(PHY, "L1 configured with%s analog beamforming\n", common_vars->analog_bf ? "" : "out"); if (common_vars->analog_bf) { + // True only if nrmac->beam_info.beam_mode == FAPI_ANALOG_BEAM, thus analog_beamforming=2 common_vars->num_beams_period = cfg->analog_beamforming_ve.num_beams_period_vendor_ext.value; LOG_I(PHY, "Max number of concurrent beams: %d\n", common_vars->num_beams_period); } else diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index e2a5f69ce4..5e1914d8ff 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -1789,7 +1789,8 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg) } int ab = *MacRLC_ParamList.paramarray[j][MACRLC_ANALOG_BEAMFORMING_IDX].u8ptr; if (ab > 0) { - AssertFatal(NFAPI_MODE == NFAPI_MONOLITHIC, "Analog beamforming only supported for monolithic scenario\n"); + if (ab == 1) + AssertFatal(NFAPI_MODE == NFAPI_MONOLITHIC, "Analog beamforming only supported for monolithic scenario\n"); NR_beam_info_t *beam_info = &RC.nrmac[j]->beam_info; int beams_per_period = *MacRLC_ParamList.paramarray[j][MACRLC_ANALOG_BEAMS_PERIOD_IDX].u8ptr; beam_info->beam_allocation = malloc16(beams_per_period * sizeof(int *)); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 55856c0738..916b96a6b1 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -505,8 +505,8 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, slot_t slotP) } } prach_pdu->num_prach_ocas = num_td_occ; - prach_pdu->beamforming.num_prgs = 0; - prach_pdu->beamforming.prg_size = 0; + prach_pdu->beamforming.num_prgs = 1; + prach_pdu->beamforming.prg_size = 273; //n_ra_rb This value doesn't work with Aerial as it bugs prach_pdu->beamforming.dig_bf_interface = num_td_occ; prach_pdu->beamforming.prgs_list[0].dig_bf_interface_list[num_td_occ - 1].beam_idx = beam_index; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c index 134b43f583..8a81d8ae4f 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c @@ -79,7 +79,7 @@ static void schedule_ssb(frame_t frame, dl_config_pdu->ssb_pdu.ssb_pdu_rel15.bchPayloadFlag = 1; dl_config_pdu->ssb_pdu.ssb_pdu_rel15.bchPayload = payload; dl_config_pdu->ssb_pdu.ssb_pdu_rel15.precoding_and_beamforming.num_prgs = 1; - dl_config_pdu->ssb_pdu.ssb_pdu_rel15.precoding_and_beamforming.prg_size = 275; //1 PRG of max size for analogue beamforming + dl_config_pdu->ssb_pdu.ssb_pdu_rel15.precoding_and_beamforming.prg_size = 20; //SSB is always 20RBs dl_config_pdu->ssb_pdu.ssb_pdu_rel15.precoding_and_beamforming.dig_bf_interfaces = 1; dl_config_pdu->ssb_pdu.ssb_pdu_rel15.precoding_and_beamforming.prgs_list[0].pm_idx = 0; dl_config_pdu->ssb_pdu.ssb_pdu_rel15.precoding_and_beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = beam_index; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index dad58f52f0..ed87d12cd9 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -993,10 +993,10 @@ nfapi_nr_dl_tti_pdsch_pdu_rel15_t *prepare_pdsch_pdu(nfapi_nr_dl_tti_request_pdu pdsch_pdu->maintenance_parms_v3.tbSizeLbrmBytes = nr_compute_tbslbrm(pdsch_pdu->mcsTable[0], dl_bw_tbslbrm, nl_tbslbrm); pdsch_pdu->maintenance_parms_v3.ldpcBaseGraph = get_BG(sched_pdsch->tb_size << 3, sched_pdsch->R); // Precoding and beamforming - pdsch_pdu->precodingAndBeamforming.num_prgs = 0; + pdsch_pdu->precodingAndBeamforming.num_prgs = 1; pdsch_pdu->precodingAndBeamforming.prg_size = pdsch_pdu->rbSize; - pdsch_pdu->precodingAndBeamforming.dig_bf_interfaces = 0; - pdsch_pdu->precodingAndBeamforming.prgs_list[0].pm_idx = sched_pdsch->pm_index; + pdsch_pdu->precodingAndBeamforming.dig_bf_interfaces = 1; + pdsch_pdu->precodingAndBeamforming.prgs_list[0].pm_idx = sched_pdsch->pm_index; pdsch_pdu->precodingAndBeamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = beam_index; return pdsch_pdu; } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 61d393090c..c1056906ac 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -824,8 +824,8 @@ nfapi_nr_dl_dci_pdu_t *prepare_dci_pdu(nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_ } dci_pdu->beta_PDCCH_1_0 = 0; dci_pdu->powerControlOffsetSS = 1; - dci_pdu->precodingAndBeamforming.num_prgs = 0; - dci_pdu->precodingAndBeamforming.prg_size = 0; + dci_pdu->precodingAndBeamforming.num_prgs = 1; + dci_pdu->precodingAndBeamforming.prg_size = 273; dci_pdu->precodingAndBeamforming.dig_bf_interfaces = 1; dci_pdu->precodingAndBeamforming.prgs_list[0].pm_idx = 0; dci_pdu->precodingAndBeamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = beam_index; @@ -1249,9 +1249,9 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t *pucch_pdu, pucch_pdu->prb_size=1; } // Beamforming - pucch_pdu->beamforming.num_prgs = 0; - pucch_pdu->beamforming.prg_size = 0; // pucch_pdu->prb_size; - pucch_pdu->beamforming.dig_bf_interface = 0; + pucch_pdu->beamforming.num_prgs = 1; + pucch_pdu->beamforming.prg_size = pucch_pdu->prb_size; + pucch_pdu->beamforming.dig_bf_interface = 1; pucch_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = UE->UE_beam_index; } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c index c3ebb5ab9b..d63cea64b6 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c @@ -465,7 +465,7 @@ static void nr_configure_srs(gNB_MAC_INST *nrmac, if (srs_resource_set->usage == NR_SRS_ResourceSet__usage_beamManagement) { srs_pdu->beamforming.trp_scheme = 0; srs_pdu->beamforming.num_prgs = m_SRS[srs_pdu->config_index]; - srs_pdu->beamforming.prg_size = 1; + srs_pdu->beamforming.prg_size = srs_pdu->srs_parameters_v4.srs_bandwidth_size; } srs_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = UE->UE_beam_index; NR_beam_alloc_t beam = beam_allocation_procedure(&nrmac->beam_info, frame, slot, UE->UE_beam_index, slots_per_frame); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index e0638e97cf..708f19d0e9 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -2311,8 +2311,8 @@ nfapi_nr_pusch_pdu_t *prepare_pusch_pdu(nfapi_nr_ul_tti_request_t *future_ul_tti pusch_pdu->pusch_data.tb_size = sched_pusch->tb_size; pusch_pdu->pusch_data.num_cb = 0; // CBG not supported // Beamforming - pusch_pdu->beamforming.num_prgs = 0; - pusch_pdu->beamforming.prg_size = 0; // bwp_size; + pusch_pdu->beamforming.num_prgs = 1; + pusch_pdu->beamforming.prg_size = pusch_pdu->bwp_size; pusch_pdu->beamforming.dig_bf_interface = 1; pusch_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = UE->UE_beam_index; /* TRANSFORM PRECODING --------------------------------------------------------*/ From 9e34a8ebed62cff3b64cd0bab44284a85f04c1f3 Mon Sep 17 00:00:00 2001 From: Gabriele Gemmi Date: Thu, 31 Jul 2025 03:53:26 +0000 Subject: [PATCH 439/964] Compute DCI prgsize from Coreset --- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 44 ++++++++++++------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index c1056906ac..5c7edc3111 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -424,6 +424,27 @@ static NR_SearchSpace_t *get_searchspace(NR_ServingCellConfigCommon_t *scc, AssertFatal(false, "Couldn't find an adequate SearchSpace for target SearchSpace %d in ServingCellConfigCommon\n", target_ss); } +/// @brief Get CORESET resource block parameters from frequency domain resources bitmap. +/// @param coreset Pointer to the CORESET configuratio +/// @param n_rb Output parameter for total # of RBs in the CORESET +/// @param rb_start Output parameter for the starting resource block index of the CORESET +static void get_coreset_rb_params(const NR_ControlResourceSet_t *coreset, uint16_t *n_rb, uint16_t *rb_start) +{ + *n_rb = 0; + *rb_start = 0; + + for (int i = 0; i < 6; i++) { + for (int t = 0; t < 8; t++) { + if ((coreset->frequencyDomainResources.buf[i] >> (7 - t)) & 1) { + if (*n_rb == 0) { + *rb_start = 48 * i + t * 6; + } + *n_rb += 6; // Each bit represents 6 RBs + } + } + } +} + NR_sched_pdcch_t set_pdcch_structure(gNB_MAC_INST *gNB_mac, NR_SearchSpace_t *ss, NR_ControlResourceSet_t *coreset, @@ -496,21 +517,7 @@ NR_sched_pdcch_t set_pdcch_structure(gNB_MAC_INST *gNB_mac, pdcch.ShiftIndex = 0; } - uint16_t N_rb = 0; // nb of rbs of coreset per symbol - uint16_t rb_start = 0; - for (int i = 0; i < 6; i++) { - for (int t = 0; t < 8; t++) { - if (coreset->frequencyDomainResources.buf[i] >> (7 - t) & 1) { - if (N_rb == 0) { - rb_start = 48 * i + t * 6; - } - N_rb++; - } - } - } - - pdcch.rb_start = rb_start; - pdcch.n_rb = N_rb *= 6; // each bit of frequencyDomainResources represents 6 PRBs + get_coreset_rb_params(coreset, &pdcch.n_rb, &pdcch.rb_start); return pdcch; } @@ -822,10 +829,15 @@ nfapi_nr_dl_dci_pdu_t *prepare_dci_pdu(nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_ dci_pdu->ScramblingId = *scc->physCellId; dci_pdu->ScramblingRNTI = 0; } + + uint16_t N_rb = 0; + uint16_t rb_start = 0; + get_coreset_rb_params(coreset, &N_rb, &rb_start); + dci_pdu->beta_PDCCH_1_0 = 0; dci_pdu->powerControlOffsetSS = 1; dci_pdu->precodingAndBeamforming.num_prgs = 1; - dci_pdu->precodingAndBeamforming.prg_size = 273; + dci_pdu->precodingAndBeamforming.prg_size = N_rb; dci_pdu->precodingAndBeamforming.dig_bf_interfaces = 1; dci_pdu->precodingAndBeamforming.prgs_list[0].pm_idx = 0; dci_pdu->precodingAndBeamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = beam_index; From 8beb382277a55ca00498317e6a5cdeb9f26bea00 Mon Sep 17 00:00:00 2001 From: Gabriele Gemmi Date: Fri, 1 Aug 2025 07:42:04 +0000 Subject: [PATCH 440/964] Removed TRP-scheme byte from UL BF PDU to Interop with Aerial 25-1 (FAPI 10.02) --- nfapi/open-nFAPI/fapi/src/nr_fapi_p7.c | 4 ++-- nfapi/open-nFAPI/fapi/src/nr_fapi_p7_utils.c | 6 +++--- nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h | 2 +- nfapi/tests/p7/nr_fapi_ul_tti_request_test.c | 2 +- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/nfapi/open-nFAPI/fapi/src/nr_fapi_p7.c b/nfapi/open-nFAPI/fapi/src/nr_fapi_p7.c index 4945e6da45..fa0ed1bd8f 100644 --- a/nfapi/open-nFAPI/fapi/src/nr_fapi_p7.c +++ b/nfapi/open-nFAPI/fapi/src/nr_fapi_p7.c @@ -708,7 +708,7 @@ static uint8_t pack_nr_rx_beamforming_pdu(const nfapi_nr_ul_beamforming_t *beamf uint8_t **ppWritePackedMsg, uint8_t *end) { // Pack RX Beamforming PDU - if (!(push8(beamforming_pdu->trp_scheme, ppWritePackedMsg, end) && push16(beamforming_pdu->num_prgs, ppWritePackedMsg, end) + if (!(push16(beamforming_pdu->num_prgs, ppWritePackedMsg, end) && push16(beamforming_pdu->prg_size, ppWritePackedMsg, end) && push8(beamforming_pdu->dig_bf_interface, ppWritePackedMsg, end))) { return 0; @@ -1033,7 +1033,7 @@ uint8_t pack_ul_tti_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, static uint8_t unpack_nr_rx_beamforming_pdu(nfapi_nr_ul_beamforming_t *beamforming_pdu, uint8_t **ppReadPackedMsg, uint8_t *end) { // Unpack RX Beamforming PDU - if (!(pull8(ppReadPackedMsg, &beamforming_pdu->trp_scheme, end) && pull16(ppReadPackedMsg, &beamforming_pdu->num_prgs, end) + if (!(pull16(ppReadPackedMsg, &beamforming_pdu->num_prgs, end) && pull16(ppReadPackedMsg, &beamforming_pdu->prg_size, end) && pull8(ppReadPackedMsg, &beamforming_pdu->dig_bf_interface, end))) { return 0; 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 fb645707ad..0a858e0be9 100644 --- a/nfapi/open-nFAPI/fapi/src/nr_fapi_p7_utils.c +++ b/nfapi/open-nFAPI/fapi/src/nr_fapi_p7_utils.c @@ -214,7 +214,7 @@ bool eq_dl_tti_request(const nfapi_nr_dl_tti_request_t *a, const nfapi_nr_dl_tti static bool eq_ul_tti_beamforming(const nfapi_nr_ul_beamforming_t *a, const nfapi_nr_ul_beamforming_t *b) { - EQ(a->trp_scheme, b->trp_scheme); + // EQ(a->trp_scheme, b->trp_scheme); EQ(a->num_prgs, b->num_prgs); EQ(a->prg_size, b->prg_size); EQ(a->dig_bf_interface, b->dig_bf_interface); @@ -1174,7 +1174,7 @@ void copy_dl_tti_request(const nfapi_nr_dl_tti_request_t *src, nfapi_nr_dl_tti_r static void copy_ul_tti_beamforming(const nfapi_nr_ul_beamforming_t *src, nfapi_nr_ul_beamforming_t *dst) { - dst->trp_scheme = src->trp_scheme; + // dst->trp_scheme = src->trp_scheme; dst->num_prgs = src->num_prgs; dst->prg_size = src->prg_size; dst->dig_bf_interface = src->dig_bf_interface; @@ -2201,7 +2201,7 @@ void dump_dl_tti_request(const nfapi_nr_dl_tti_request_t *msg) static void dump_ul_tti_beamforming(const nfapi_nr_ul_beamforming_t *pdu, int depth) { - INDENTED_PRINTF("TRP Scheme = %d\n", pdu->trp_scheme); + // INDENTED_PRINTF("TRP Scheme = %d\n", pdu->trp_scheme); INDENTED_PRINTF("numPRGs = %d\n", pdu->num_prgs); INDENTED_PRINTF("prgSize = %d\n", pdu->prg_size); INDENTED_PRINTF("digBFInterface = %d\n", pdu->dig_bf_interface); 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 e19dab108c..5bcc551000 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 @@ -1212,7 +1212,7 @@ typedef struct typedef struct { - uint8_t trp_scheme; // This field shall be set to 0, to identify that this table is used. + // uint8_t trp_scheme; // This field shall be set to 0, to identify that this table is used. Not part of FAPI 10.02, thus removed uint16_t num_prgs; // Number of PRGs spanning this allocation. Value : 1->275 uint16_t prg_size; // Size in RBs of a precoding resource block group (PRG) – to which the same digital beamforming gets applied. Value: 1->275 uint8_t dig_bf_interface; // Number of logical antenna ports (parallel streams) resulting from the Rx combining. Value: 0->255 diff --git a/nfapi/tests/p7/nr_fapi_ul_tti_request_test.c b/nfapi/tests/p7/nr_fapi_ul_tti_request_test.c index f7087c92ef..90b1625a7e 100644 --- a/nfapi/tests/p7/nr_fapi_ul_tti_request_test.c +++ b/nfapi/tests/p7/nr_fapi_ul_tti_request_test.c @@ -24,7 +24,7 @@ static void fill_ul_tti_request_beamforming(nfapi_nr_ul_beamforming_t *beamforming_pdu) { - beamforming_pdu->trp_scheme = rand8(); + // beamforming_pdu->trp_scheme = rand8(); // not part of 10.02 beamforming_pdu->num_prgs = rand16_range(1, NFAPI_MAX_NUM_PRGS); beamforming_pdu->prg_size = rand16_range(1, 275); beamforming_pdu->dig_bf_interface = rand8_range(1,NFAPI_MAX_NUM_BG_IF); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c index d63cea64b6..cabf85f522 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c @@ -463,7 +463,7 @@ static void nr_configure_srs(gNB_MAC_INST *nrmac, srs_pdu->srs_parameters_v4.prg_size = 1; srs_pdu->srs_parameters_v4.num_total_ue_antennas = 1 << srs_pdu->num_ant_ports; if (srs_resource_set->usage == NR_SRS_ResourceSet__usage_beamManagement) { - srs_pdu->beamforming.trp_scheme = 0; + // srs_pdu->beamforming.trp_scheme = 0; srs_pdu->beamforming.num_prgs = m_SRS[srs_pdu->config_index]; srs_pdu->beamforming.prg_size = srs_pdu->srs_parameters_v4.srs_bandwidth_size; } From 61a7b6b80e2c52135b2c164adbf73a36f85ecb2a Mon Sep 17 00:00:00 2001 From: Gabriele Gemmi Date: Sat, 2 Aug 2025 21:30:56 +0000 Subject: [PATCH 441/964] compute prgsize from number of RA RB --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 916b96a6b1..e4762c3263 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -368,6 +368,8 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, slot_t slotP) // prach is scheduled according to configuration index and tables 6.3.3.2.2 to 6.3.3.2.4 uint16_t RA_sfn_index = -1; frequency_range_t freq_range = get_freq_range_from_arfcn(scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA); + const int mu_pusch = scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; + const int16_t n_ra_rb = get_N_RA_RB(cfg->prach_config.prach_sub_c_spacing.value, mu_pusch); if (get_nr_prach_sched_from_info(cc->prach_info, config_index, frameP, slotP, mu, freq_range, &RA_sfn_index, cc->frame_type)) { uint16_t format0 = cc->prach_info.format & 0xff; // first column of format from table uint16_t format1 = (cc->prach_info.format >> 8) & 0xff; // second column of format from table @@ -506,7 +508,7 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, slot_t slotP) } prach_pdu->num_prach_ocas = num_td_occ; prach_pdu->beamforming.num_prgs = 1; - prach_pdu->beamforming.prg_size = 273; //n_ra_rb This value doesn't work with Aerial as it bugs + prach_pdu->beamforming.prg_size = n_ra_rb; prach_pdu->beamforming.dig_bf_interface = num_td_occ; prach_pdu->beamforming.prgs_list[0].dig_bf_interface_list[num_td_occ - 1].beam_idx = beam_index; @@ -527,8 +529,6 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, slot_t slotP) } // block resources in vrb_map_UL - const int mu_pusch = scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; - const int16_t n_ra_rb = get_N_RA_RB(cfg->prach_config.prach_sub_c_spacing.value, mu_pusch); // mark PRBs as occupied for current and future slots if prach extends beyond current slot int total_prach_slots; uint32_t N_dur = cc->prach_info.N_dur; From 1719375ceafea62734d2ad2f7e28bf7b1245ce71 Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 30 Jun 2025 17:44:47 +0200 Subject: [PATCH 442/964] minor refactoring in nfapi_nr_interface_scf --- .../nfapi/public_inc/nfapi_nr_interface_scf.h | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) 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 5bcc551000..5b84f9f1d4 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 @@ -743,31 +743,31 @@ typedef struct { // 3.4.2 -//for pdcch_pdu: +typedef struct { + // Index of the digital beam weight vector pre-stored at cell configuration. + // The vector maps this input port to output TXRUs. Value: 0->65535 + uint16_t beam_idx; +} nfapi_nr_dig_bf_interface_t; -typedef struct -{ - uint16_t beam_idx;//Index of the digital beam weight vector pre-stored at cell configuration. The vector maps this input port to output TXRUs. Value: 0->65535 - -}nfapi_nr_dig_bf_interface_t; - -typedef struct -{ - uint16_t pm_idx;//Index to precoding matrix (PM) pre-stored at cell configuration. Note: If precoding is not used this parameter should be set to 0. Value: 0->65535. - nfapi_nr_dig_bf_interface_t dig_bf_interface_list[NFAPI_MAX_NUM_BG_IF];//max dig_bf_interfaces - -}nfapi_nr_tx_precoding_and_beamforming_number_of_prgs_t; +typedef struct { + // Index to precoding matrix (PM) pre-stored at cell configuration. + // Note: If precoding is not used this parameter should be set to 0. Value: 0->65535. + uint16_t pm_idx; + nfapi_nr_dig_bf_interface_t dig_bf_interface_list[NFAPI_MAX_NUM_BG_IF]; // max dig_bf_interfaces +} nfapi_nr_tx_precoding_and_beamforming_number_of_prgs_t; //table 3-43 -typedef struct -{ - uint16_t num_prgs;//Number of PRGs spanning this allocation. Value : 1->275 - uint16_t prg_size;//Size in RBs of a precoding resource block group (PRG) – to which same precoding and digital beamforming gets applied. Value: 1->275 - //watchout: dig_bf_interfaces here, in table 3-53 it's dig_bf_interface - uint8_t dig_bf_interfaces;//Number of STD ant ports (parallel streams) feeding into the digBF Value: 0->255 - nfapi_nr_tx_precoding_and_beamforming_number_of_prgs_t prgs_list[NFAPI_MAX_NUM_PRGS];//max prg_size - -}nfapi_nr_tx_precoding_and_beamforming_t; +typedef struct { + // Number of PRGs spanning this allocation. Value : 1->275 + uint16_t num_prgs; + // Size in RBs of a precoding resource block group (PRG) to which same precoding and digital beamforming gets applied. + // Value: 1->275 + uint16_t prg_size; + // watchout: dig_bf_interfaces here, in table 3-53 it's dig_bf_interface + uint8_t dig_bf_interfaces; + // Number of STD ant ports (parallel streams) feeding into the digBF Value: 0->255 + nfapi_nr_tx_precoding_and_beamforming_number_of_prgs_t prgs_list[NFAPI_MAX_NUM_PRGS]; // max prg_size +} nfapi_nr_tx_precoding_and_beamforming_t; //table 3-37 From ff9a6d97ea94bed9c2600e428a816d59a31aeef1 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 14 Aug 2025 08:43:34 +0200 Subject: [PATCH 443/964] gNB MAC doc: add dl/ul_min_mcs Previous commits removed min_grant_mcs and instead introduced dl/ul_min_mcs as a more generic replacement. Fixes: 96b0cae63e61 ("Drop 'min_grant_mcs' configuration parameter ") Fixes: 699afafc6ff7 ("Add support for 'dl_min_mcs' and 'ul_min_mcs' configuration parameters") --- doc/MAC/mac-usage.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/MAC/mac-usage.md b/doc/MAC/mac-usage.md index ae4f3a626b..6619f8789c 100644 --- a/doc/MAC/mac-usage.md +++ b/doc/MAC/mac-usage.md @@ -205,17 +205,17 @@ In the `MACRLCs` section of the gNB/DU configuration file: retransmission over initial transmission) to decrease MCS by 1 * `dl_bler_target_lower` (default 0.05): lower threshold of BLER (first round retransmission over initial transmission) to increase MCS by 1 -* `dl_max_mcs` (default 28): maximum MCS to use +* `dl_min_mcs` (default 0): minimum MCS to use for any UE +* `dl_max_mcs` (default 28): maximum MCS to use for any UE * `ul_bler_target_upper` (default 0.15): as `dl_bler_target_upper` * `ul_bler_target_lower` (default 0.05): as `dl_bler_target_lower` +* `ul_min_mcs` (default 0): as `dl_min_mcs` * `ul_max_mcs` (default 28): as `dl_max_mcs` * `dl_harq_round_max` (default 4): maximum number of HARQ rounds, i.e., retransmissions to perform, in DL * `ul_harq_round_max` (default 4): as `dl_harq_round_max` * `min_grant_prb` (default 5): number of PRBs to schedule for UE after activity (see `ulsch_max_frame_inactivity`) or after scheduling request (SR) -* `min_grant_mcs` (default 9): MCS to use for UE after activity (see - `ulsch_max_frame_inactivity`) or after scheduling request (SR) * `identity_precoding_matrix` (default 0=false): flag to enable to use only the identity precoding matrix in DL precoding * `set_analog_beamforming` (default 0=false): flag to enable analog From 3ee41c3fec5ca1b70222ca48c19fb9df88116c52 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 14 Aug 2025 09:13:01 +0200 Subject: [PATCH 444/964] Explain steps to build Dockerfiles without BuildKit The Dockerfiles are reused for building on different architectures (amd64/arm64). They differ, though, on some steps for downloading or installing platform-specific utilities. This is handled automatically when using BuildKit, which is the default in docker versions v23.0+. Older docker versions require some special settings. Explain this in the README. Closes: #973 --- docker/README.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/docker/README.md b/docker/README.md index 36ec65698a..ecd0a043a1 100644 --- a/docker/README.md +++ b/docker/README.md @@ -91,6 +91,24 @@ For more details regarding the build on an Openshift Cluster, see [OpenShift REA * `docker-ce` installed * Pulling `ubuntu:jammy` from DockerHub +The docker files in this directory rely on [automatic Docker platform +arguments](https://docs.docker.com/reference/dockerfile/#automatic-platform-args-in-the-global-scope) +`TARGETARCH` and `TARGETPLATFORM` to be defined. This is the case when using +[BuildKit](https://docs.docker.com/build/buildkit/), which is automatically +enabled in newer (v23.0+) docker versions. + +If you are running an older version of docker that does not have BuildKit +enabled and do not wish to upgrade to a newer docker version, you have two +possibilities: + +1. [Enable BuildKit](https://docs.docker.com/build/buildkit/#getting-started) + when building: `DOCKER_BUILDKIT=1 docker build ...` +2. You should be able to define these variables manually. + - x86: `docker build --build-arg TARGETARCH=amd64 --build-arg + TARGETPLATFORM=linux/amd64 ...` + - arm: `docker build --build-arg TARGETARCH=arm64 --build-arg + TARGETPLATFORM=linux/arm64 ...` + ## 3.2. Building the shared images ## There are two shared images: one that has all dependencies, and a second that compiles all targets (eNB, gNB, [nr]UE). From c94db4adec69028b42a6f69e29f1e0a84b8bd082 Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 17 Dec 2024 13:31:24 +0100 Subject: [PATCH 445/964] separate computation of size and value for DCI precoding information --- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 292 +++--------------- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h | 61 +++- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 284 ++++++++++++++++- 3 files changed, 359 insertions(+), 278 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index cd51f6a48f..1a5431bdd2 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -1972,49 +1972,6 @@ static const int32_t table_6_4_1_1_3_4_pusch_dmrs_positions_l[12][8] = { {0, 3072, -1, -1, 3, 1539, -1, -1}, // 14 // (DMRS l' position) }; -// TS 38.212 -static const uint16_t table_7_3_1_1_2_2_1layer[28] = {0, 1, 2, 3, 12, 13, 14, 15, 16, 17, 18, 19, 32, 33, - 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47}; -static const uint16_t table_7_3_1_1_2_2_2layers[22] = {4, 5, 6, 7, 8, 9, 20, 21, 22, 23, 24, - 25, 26, 27, 48, 49, 50, 51, 52, 53, 54, 55}; -static const uint16_t table_7_3_1_1_2_2_3layers[7] = {10, 28, 29, 56, 57, 58, 59}; -static const uint16_t table_7_3_1_1_2_2_4layers[5] = {11, 30, 31, 60, 61}; -static const uint16_t table_7_3_1_1_2_2B_1layer[16] = {0, 1, 2, 3, 15, 16, 17, 18, 19, 20, 21, 22, 23, 12, 24, 25}; -static const uint16_t table_7_3_1_1_2_2B_2layers[14] = {4, 5, 6, 7, 8, 9, 13, 26, 27, 28, 29, 30, 31, 32}; -static const uint16_t table_7_3_1_1_2_2B_3layers[3] = {10, 14, 33}; -static const uint16_t table_7_3_1_1_2_2B_4layers[3] = {11, 34, 35}; -static const uint16_t table_7_3_1_1_2_2A_1layer[16] = {0, 1, 2, 3, 12, 13, 14, 15, 16, 17, 18, 19, 20, 10, 21, 22}; -static const uint16_t table_7_3_1_1_2_2A_2layers[14] = {4, 5, 6, 7, 8, 9, 11, 23, 24, 25, 26, 27, 28, 29}; -static const uint16_t table_7_3_1_1_2_3A[16] = {0, 1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 4, 14, 15}; -static const uint16_t table_7_3_1_1_2_4_1layer_fullyAndPartialAndNonCoherent[6] = {0, 1, 3, 4, 5, 6}; -static const uint16_t table_7_3_1_1_2_4_2layers_fullyAndPartialAndNonCoherent[3] = {2, 7, 8}; -static const uint16_t table_7_3_1_1_2_4A_1layer[3] = {0, 1, 3}; -static const uint16_t table_7_3_1_1_2_28[3][15] = { - {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -}; -static const uint16_t table_7_3_1_1_2_29[3][15] = { - {0, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 1, 2, 0, 3, 4, 0, 5, 0, 0, 0, 0, 0, 0, 0}, - {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0}, -}; -static const uint16_t table_7_3_1_1_2_30[3][15] = { - {0, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 1, 2, 0, 3, 4, 0, 5, 0, 0, 6, 0, 0, 0, 0}, - {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0}, -}; -static const uint16_t table_7_3_1_1_2_31[3][15] = { - {0, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 1, 2, 0, 3, 4, 0, 5, 0, 0, 6, 0, 0, 0, 0}, - {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, -}; -static const uint16_t table_7_3_1_1_2_32[3][15] = { - {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -}; - // the following tables contain 10 times the value reported in 214 (in line with SCF specification and to avoid fractional values) //Table 5.1.3.1-1 of 38.214 static const uint16_t Table_51311[32][2] = {{2, 1200}, {2, 1570}, {2, 1930}, {2, 2510}, {2, 3080}, {2, 3790}, {2, 4490}, {2, 5260}, @@ -2503,61 +2460,61 @@ static int binomial(int n, int k) return c; } +int srs_codebook_nb_res(NR_SRS_Config_t *srs_config) +{ + int count = 0; + for (int i = 0; i < srs_config->srs_ResourceSetToAddModList->list.count; i++) { + if (srs_config->srs_ResourceSetToAddModList->list.array[i]->usage == NR_SRS_ResourceSet__usage_codebook) + count++; + } + return count; +} + +int srs_non_codebook_nb_res(NR_SRS_Config_t *srs_config) +{ + int count = 0; + for (int i = 0; i < srs_config->srs_ResourceSetToAddModList->list.count; i++) { + if (srs_config->srs_ResourceSetToAddModList->list.array[i]->usage == NR_SRS_ResourceSet__usage_nonCodebook) + count++; + } + return count; +} + +int srs_binomial_sum(int count, int Lmax) +{ + int lmin = 0; + int lsum = 0; + lmin = count < Lmax ? count : Lmax; + for (int k = 1; k <= lmin; k++) + lsum += binomial(count, k); + return lsum; +} + // #define DEBUG_SRS_RESOURCE_IND -uint8_t compute_srs_resource_indicator(long *maxMIMO_Layers, - NR_PUSCH_Config_t *pusch_Config, - NR_SRS_Config_t *srs_config, - nr_srs_feedback_t *srs_feedback, - uint32_t *val) + +static uint8_t compute_srs_resource_indicator_size(long *maxMIMO_Layers, NR_PUSCH_Config_t *pusch_Config, NR_SRS_Config_t *srs_config) { uint8_t nbits = 0; - - // SRI occupies a number of bits which is dependent upon the uplink transmission scheme, and it is used to determine - // the antenna ports and uplink transmission beam to use for PUSCH transmission. In the case of codebook based - // transmission, the SRI is used to select between SRS Resources belonging to different antenna panels - // (kind of directional antenna). There can be up to 2 SRS Resources (2 antenna panels). In the case of non-codebook - // based transmission, the SRI is used to select one or more SRS Resources from a set of N_SRS resources. The number - // of SRS Resources selected corresponds to the number of layers (rank) to be transmitted. - if (val) { - *val = 0; - } - if (srs_config && pusch_Config && pusch_Config->txConfig != NULL) { - if (*pusch_Config->txConfig == NR_PUSCH_Config__txConfig_codebook) { - #ifdef DEBUG_SRS_RESOURCE_IND LOG_I(NR_MAC, "*pusch_Config->txConfig = NR_PUSCH_Config__txConfig_codebook\n"); #endif - // TS 38.212 - Section 7.3.1.1.2: SRS resource indicator has ceil(log2(N_SRS)) bits according to // Tables 7.3.1.1.2-32, 7.3.1.1.2-32A and 7.3.1.1.2-32B if the higher layer parameter txConfig = codebook, // where N_SRS is the number of configured SRS resources in the SRS resource set configured by higher layer // parameter srs-ResourceSetToAddModList, and associated with the higher layer parameter usage of value codeBook. - int count = 0; - for (int i=0; isrs_ResourceSetToAddModList->list.count; i++) { - if (srs_config->srs_ResourceSetToAddModList->list.array[i]->usage == NR_SRS_ResourceSet__usage_codebook) { - count++; - } - } - if (count>0) { + int count = srs_codebook_nb_res(srs_config); + if (count > 0) nbits = ceil(log2(count)); - if (val && srs_feedback && count > 1) { - *val = table_7_3_1_1_2_32[count-2][srs_feedback->sri]; - } - } - #ifdef DEBUG_SRS_RESOURCE_IND LOG_I(NR_MAC, "srs_config->srs_ResourceSetToAddModList->list.count = %i\n", srs_config->srs_ResourceSetToAddModList->list.count); LOG_I(NR_MAC, "count = %i\n", count); #endif - } else { - #ifdef DEBUG_SRS_RESOURCE_IND LOG_I(NR_MAC, "*pusch_Config->txConfig = NR_PUSCH_Config__txConfig_nonCodebook\n"); #endif - // TS 38.212 - Section 7.3.1.1.2: SRS resource indicator has ceil(log2(sum(k = 1 until min(Lmax,N_SRS) of binomial(N_SRS,k)))) // bits according to Tables 7.3.1.1.2-28/29/30/31 if the higher layer parameter txConfig = nonCodebook, where // N_SRS is the number of configured SRS resources in the SRS resource set configured by higher layer parameter @@ -2572,68 +2529,29 @@ uint8_t compute_srs_resource_indicator(long *maxMIMO_Layers, if (maxMIMO_Layers != NULL) Lmax = *maxMIMO_Layers; else - AssertFatal(1 == 0, "MIMO on PUSCH not supported, maxMIMO_Layers needs to be set to 1\n"); - int lmin = 0; - int lsum = 0; - int count = 0; - for (int i = 0; i < srs_config->srs_ResourceSetToAddModList->list.count; i++) { - if (srs_config->srs_ResourceSetToAddModList->list.array[i]->usage == NR_SRS_ResourceSet__usage_nonCodebook) { - count++; - } - } - lmin = count < Lmax ? count : Lmax; - for (int k=1;k<=lmin;k++) { - lsum += binomial(count,k); - } - if (lsum>0) { + AssertFatal(false, "MIMO on PUSCH not supported, maxMIMO_Layers needs to be set to 1\n"); + int count = srs_non_codebook_nb_res(srs_config); + int lsum = srs_binomial_sum(count, Lmax); + if (lsum > 0) nbits = ceil(log2(lsum)); - if (val && srs_feedback && nbits > 0) { - switch(Lmax) { - case 1: - *val = table_7_3_1_1_2_28[count-2][srs_feedback->sri]; - break; - case 2: - *val = table_7_3_1_1_2_29[count-2][srs_feedback->sri]; - break; - case 3: - *val = table_7_3_1_1_2_30[count-2][srs_feedback->sri]; - break; - case 4: - *val = table_7_3_1_1_2_31[count-2][srs_feedback->sri]; - break; - default: - LOG_E(NR_MAC, "%s (%d) - Invalid Lmax %d\n", __FUNCTION__, __LINE__, Lmax); - } - } - } - #ifdef DEBUG_SRS_RESOURCE_IND LOG_I(NR_MAC, "srs_config->srs_ResourceSetToAddModList->list.count = %i\n", srs_config->srs_ResourceSetToAddModList->list.count); LOG_I(NR_MAC, "count = %i\n", count); LOG_I(NR_MAC, "Lmax = %i\n", Lmax); LOG_I(NR_MAC, "lsum = %i\n", lsum); #endif - } } - return nbits; } -uint8_t compute_precoding_information(NR_PUSCH_Config_t *pusch_Config, - NR_SRS_Config_t *srs_config, - dci_field_t srs_resource_indicator, - nr_srs_feedback_t *srs_feedback, - const uint8_t *nrOfLayers, - int *tpmi, - uint32_t *val) +static uint8_t compute_precoding_info_size(NR_PUSCH_Config_t *pusch_Config, + NR_SRS_Config_t *srs_config, + dci_field_t srs_resource_indicator) { // It is only applicable to codebook based transmission. This field occupies 0 bits for non-codebook based // transmission. It also occupies 0 bits for codebook based transmission using a single antenna port. uint8_t nbits = 0; - if (val) { - *val = 0; - } uint8_t pusch_antenna_ports = get_pusch_nb_antenna_ports(pusch_Config, srs_config, srs_resource_indicator); if (!pusch_Config @@ -2645,7 +2563,6 @@ uint8_t compute_precoding_information(NR_PUSCH_Config_t *pusch_Config, long max_rank = *pusch_Config->maxRank; long *ul_FullPowerTransmission = pusch_Config->ext1 ? pusch_Config->ext1->ul_FullPowerTransmission_r16 : NULL; long *codebookSubset = pusch_Config->codebookSubset; - int ul_tpmi = tpmi ? *tpmi : srs_feedback ? srs_feedback->tpmi : -1; if (pusch_antenna_ports == 2) { @@ -2658,23 +2575,11 @@ uint8_t compute_precoding_information(NR_PUSCH_Config_t *pusch_Config, // of higher layer parameter codebookSubset; if (ul_FullPowerTransmission && *ul_FullPowerTransmission == NR_PUSCH_Config__ext1__ul_FullPowerTransmission_r16_fullpowerMode1) { nbits = 2; - if (val && srs_feedback) { - AssertFatal(ul_tpmi <= 2,"TPMI %d is invalid!\n", ul_tpmi); - *val = ul_tpmi; - } } else { if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) { nbits = 1; - if (val && srs_feedback) { - AssertFatal(ul_tpmi <= 1,"TPMI %d is invalid!\n", ul_tpmi); - *val = ul_tpmi; - } } else { nbits = 3; - if (val && srs_feedback) { - AssertFatal(ul_tpmi <= 5,"TPMI %d is invalid!\n", ul_tpmi); - *val = ul_tpmi; - } } } } else { @@ -2685,27 +2590,11 @@ uint8_t compute_precoding_information(NR_PUSCH_Config_t *pusch_Config, // fullpowerMode1, transform precoder is disabled, maxRank=2, and codebookSubset=nonCoherent; if (ul_FullPowerTransmission && *ul_FullPowerTransmission == NR_PUSCH_Config__ext1__ul_FullPowerTransmission_r16_fullpowerMode1) { nbits = 2; - if (val && srs_feedback) { - AssertFatal((*nrOfLayers==1 && ul_tpmi <= 2) || (*nrOfLayers==2 && ul_tpmi == 0), - "TPMI %d is invalid!\n", ul_tpmi); - *val = *nrOfLayers==1 ? table_7_3_1_1_2_4A_1layer[ul_tpmi] : 2; - } } else { if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) { nbits = 2; - if (val && srs_feedback) { - AssertFatal((*nrOfLayers==1 && ul_tpmi <= 1) || (*nrOfLayers==2 && ul_tpmi == 0), - "TPMI %d is invalid!\n", ul_tpmi); - *val = *nrOfLayers==1 ? ul_tpmi : 2; - } } else { nbits = 4; - if (val && srs_feedback) { - AssertFatal((*nrOfLayers==1 && ul_tpmi <= 5) || (*nrOfLayers==2 && ul_tpmi <= 2), - "TPMI %d is invalid!\n", ul_tpmi); - *val = *nrOfLayers==1 ? table_7_3_1_1_2_4_1layer_fullyAndPartialAndNonCoherent[ul_tpmi] : - table_7_3_1_1_2_4_2layers_fullyAndPartialAndNonCoherent[ul_tpmi]; - } } } } @@ -2722,37 +2611,16 @@ uint8_t compute_precoding_information(NR_PUSCH_Config_t *pusch_Config, if (ul_FullPowerTransmission && *ul_FullPowerTransmission == NR_PUSCH_Config__ext1__ul_FullPowerTransmission_r16_fullpowerMode1) { if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) { nbits = 3; - if (val && srs_feedback) { - AssertFatal(ul_tpmi <= 3 || ul_tpmi == 13, "TPMI %d is invalid!\n", ul_tpmi); - } } else { nbits = 4; - if (val && srs_feedback) { - AssertFatal(ul_tpmi <= 15, "TPMI %d is invalid!\n", ul_tpmi); - } - } - if (val && srs_feedback) { - *val = table_7_3_1_1_2_3A[ul_tpmi]; } } else { if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) { nbits = 2; - if (val && srs_feedback) { - AssertFatal(ul_tpmi <= 3, "TPMI %d is invalid!\n", ul_tpmi); - } } else if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_partialAndNonCoherent) { nbits = 4; - if (val && srs_feedback) { - AssertFatal(ul_tpmi <= 11, "TPMI %d is invalid!\n", ul_tpmi); - } } else { nbits = 5; - if (val && srs_feedback) { - AssertFatal(ul_tpmi <= 27, "TPMI %d is invalid!\n", ul_tpmi); - } - } - if (val && srs_feedback) { - *val = ul_tpmi; } } } else { @@ -2769,99 +2637,26 @@ uint8_t compute_precoding_information(NR_PUSCH_Config_t *pusch_Config, if (max_rank == 2) { if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) { nbits = 4; - if (val && srs_feedback) { - AssertFatal((*nrOfLayers==1 && (ul_tpmi <= 3 || ul_tpmi==13)) || (*nrOfLayers==2 && ul_tpmi <= 6), - "TPMI %d is invalid!\n", ul_tpmi); - } } else { nbits = 5; - if (val && srs_feedback) { - AssertFatal((*nrOfLayers==1 && ul_tpmi <= 15) || (*nrOfLayers==2 && ul_tpmi <= 13), - "TPMI %d is invalid!\n", ul_tpmi); - } - } - if (val && srs_feedback) { - *val = *nrOfLayers==1 ? table_7_3_1_1_2_2A_1layer[ul_tpmi] : table_7_3_1_1_2_2A_2layers[ul_tpmi]; } } else { if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) { nbits = 4; - if (val && srs_feedback) { - AssertFatal((*nrOfLayers==1 && (ul_tpmi <= 3 || ul_tpmi == 13)) || (*nrOfLayers==2 && ul_tpmi <= 6) || - (*nrOfLayers==3 && ul_tpmi <= 1) || (*nrOfLayers==4 && ul_tpmi == 0), - "TPMI %d is invalid!\n", ul_tpmi); - } } else { nbits = 6; - if (val && srs_feedback) { - AssertFatal((*nrOfLayers==1 && ul_tpmi <= 15) || (*nrOfLayers==2 && ul_tpmi <= 13) || - (*nrOfLayers==3 && ul_tpmi <= 2) || (*nrOfLayers==4 && ul_tpmi <= 2), - "TPMI %d is invalid!\n", ul_tpmi); - } - } - if (val && srs_feedback) { - switch (*nrOfLayers) { - case 1: - *val = table_7_3_1_1_2_2B_1layer[ul_tpmi]; - break; - case 2: - *val = table_7_3_1_1_2_2B_2layers[ul_tpmi]; - break; - case 3: - *val = table_7_3_1_1_2_2B_3layers[ul_tpmi]; - break; - case 4: - *val = table_7_3_1_1_2_2B_4layers[ul_tpmi]; - break; - default: - LOG_E(NR_MAC,"Number of layers %d is invalid!\n", *nrOfLayers); - } } } } else { if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) { nbits = 4; - if (val && srs_feedback) { - AssertFatal((*nrOfLayers==1 && ul_tpmi <= 3) || (*nrOfLayers==2 && ul_tpmi <= 5) || - (*nrOfLayers==3 && ul_tpmi == 0) || (*nrOfLayers==4 && ul_tpmi == 0), - "TPMI %d is invalid!\n", ul_tpmi); - } } else if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_partialAndNonCoherent) { nbits = 5; - if (val && srs_feedback) { - AssertFatal((*nrOfLayers==1 && ul_tpmi <= 11) || (*nrOfLayers==2 && ul_tpmi <= 13) || - (*nrOfLayers==3 && ul_tpmi <= 2) || (*nrOfLayers==4 && ul_tpmi <= 2), - "TPMI %d is invalid!\n", ul_tpmi); - } } else { nbits = 6; - if (val && srs_feedback) { - AssertFatal((*nrOfLayers==1 && ul_tpmi <= 28) || (*nrOfLayers==2 && ul_tpmi <= 22) || - (*nrOfLayers==3 && ul_tpmi <= 7) || (*nrOfLayers==4 && ul_tpmi <= 5), - "TPMI %d is invalid!\n", ul_tpmi); - } - } - if (val && srs_feedback) { - switch (*nrOfLayers) { - case 1: - *val = table_7_3_1_1_2_2_1layer[ul_tpmi]; - break; - case 2: - *val = table_7_3_1_1_2_2_2layers[ul_tpmi]; - break; - case 3: - *val = table_7_3_1_1_2_2_3layers[ul_tpmi]; - break; - case 4: - *val = table_7_3_1_1_2_2_4layers[ul_tpmi]; - break; - default: - LOG_E(NR_MAC,"Number of layers %d is invalid!\n", *nrOfLayers); - } } } } - } return nbits; } @@ -3100,12 +2895,11 @@ uint16_t nr_dci_size(const NR_UE_DL_BWP_t *DL_BWP, } // SRS resource indicator dci_pdu->srs_resource_indicator.nbits = - compute_srs_resource_indicator(sc_info->maxMIMO_Layers_PUSCH, pusch_Config, srs_config, NULL, NULL); + compute_srs_resource_indicator_size(sc_info->maxMIMO_Layers_PUSCH, pusch_Config, srs_config); size += dci_pdu->srs_resource_indicator.nbits; LOG_D(NR_MAC, "dci_pdu->srs_resource_indicator.nbits %d\n", dci_pdu->srs_resource_indicator.nbits); // Precoding info and number of layers - dci_pdu->precoding_information.nbits = - compute_precoding_information(pusch_Config, srs_config, dci_pdu->srs_resource_indicator, NULL, NULL, NULL, NULL); + dci_pdu->precoding_information.nbits = compute_precoding_info_size(pusch_Config, srs_config, dci_pdu->srs_resource_indicator); size += dci_pdu->precoding_information.nbits; LOG_D(NR_MAC, "dci_pdu->precoding_informaiton.nbits=%d\n", dci_pdu->precoding_information.nbits); // Antenna ports diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h index 3770d2c6ec..915fadb03b 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h @@ -41,6 +41,49 @@ #define NB_SRS_PERIOD (18) static const uint16_t srs_period[NB_SRS_PERIOD] = { 0, 1, 2, 4, 5, 8, 10, 16, 20, 32, 40, 64, 80, 160, 320, 640, 1280, 2560}; +// TS 38.212 +static const uint16_t table_7_3_1_1_2_2_1layer[28] = {0, 1, 2, 3, 12, 13, 14, 15, 16, 17, 18, 19, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47}; +static const uint16_t table_7_3_1_1_2_2_2layers[22] = {4, 5, 6, 7, 8, 9, 20, 21, 22, 23, 24, + 25, 26, 27, 48, 49, 50, 51, 52, 53, 54, 55}; +static const uint16_t table_7_3_1_1_2_2_3layers[7] = {10, 28, 29, 56, 57, 58, 59}; +static const uint16_t table_7_3_1_1_2_2_4layers[5] = {11, 30, 31, 60, 61}; +static const uint16_t table_7_3_1_1_2_2B_1layer[16] = {0, 1, 2, 3, 15, 16, 17, 18, 19, 20, 21, 22, 23, 12, 24, 25}; +static const uint16_t table_7_3_1_1_2_2B_2layers[14] = {4, 5, 6, 7, 8, 9, 13, 26, 27, 28, 29, 30, 31, 32}; +static const uint16_t table_7_3_1_1_2_2B_3layers[3] = {10, 14, 33}; +static const uint16_t table_7_3_1_1_2_2B_4layers[3] = {11, 34, 35}; +static const uint16_t table_7_3_1_1_2_2A_1layer[16] = {0, 1, 2, 3, 12, 13, 14, 15, 16, 17, 18, 19, 20, 10, 21, 22}; +static const uint16_t table_7_3_1_1_2_2A_2layers[14] = {4, 5, 6, 7, 8, 9, 11, 23, 24, 25, 26, 27, 28, 29}; +static const uint16_t table_7_3_1_1_2_3A[16] = {0, 1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 4, 14, 15}; +static const uint16_t table_7_3_1_1_2_4_1layer_fullyAndPartialAndNonCoherent[6] = {0, 1, 3, 4, 5, 6}; +static const uint16_t table_7_3_1_1_2_4_2layers_fullyAndPartialAndNonCoherent[3] = {2, 7, 8}; +static const uint16_t table_7_3_1_1_2_4A_1layer[3] = {0, 1, 3}; +static const uint16_t table_7_3_1_1_2_28[3][15] = { + {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +}; +static const uint16_t table_7_3_1_1_2_29[3][15] = { + {0, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 1, 2, 0, 3, 4, 0, 5, 0, 0, 0, 0, 0, 0, 0}, + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0}, +}; +static const uint16_t table_7_3_1_1_2_30[3][15] = { + {0, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 1, 2, 0, 3, 4, 0, 5, 0, 0, 6, 0, 0, 0, 0}, + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0}, +}; +static const uint16_t table_7_3_1_1_2_31[3][15] = { + {0, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 1, 2, 0, 3, 4, 0, 5, 0, 0, 6, 0, 0, 0, 0}, + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, +}; +static const uint16_t table_7_3_1_1_2_32[3][15] = { + {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +}; + typedef enum { pusch_dmrs_pos0 = 0, pusch_dmrs_pos1 = 1, @@ -81,20 +124,6 @@ void config_frame_structure(int mu, uint8_t frame_type, frame_structure_t *fs); -uint8_t compute_srs_resource_indicator(long *maxMIMO_Layers, - NR_PUSCH_Config_t *pusch_Config, - NR_SRS_Config_t *srs_config, - nr_srs_feedback_t *srs_feedback, - uint32_t *val); - -uint8_t compute_precoding_information(NR_PUSCH_Config_t *pusch_Config, - NR_SRS_Config_t *srs_config, - dci_field_t srs_resource_indicator, - nr_srs_feedback_t *srs_feedback, - const uint8_t *nrOfLayers, - int *tpmi, - uint32_t *val); - NR_PDSCH_TimeDomainResourceAllocationList_t *get_dl_tdalist(const NR_UE_DL_BWP_t *DL_BWP, int controlResourceSetId, int ss_type, @@ -197,7 +226,9 @@ uint32_t nr_get_code_rate_dl(uint8_t Imcs, uint8_t table_idx); /** \brief Computes Q based on I_MCS PDSCH and table_idx for uplink. Implements MCS Tables from 38.214. */ uint8_t nr_get_Qm_ul(uint8_t Imcs, uint8_t table_idx); uint32_t nr_get_code_rate_ul(uint8_t Imcs, uint8_t table_idx); - +int srs_binomial_sum(int count, int Lmax); +int srs_codebook_nb_res(NR_SRS_Config_t *srs_config); +int srs_non_codebook_nb_res(NR_SRS_Config_t *srs_config); uint16_t get_nr_srs_offset(NR_SRS_PeriodicityAndOffset_t periodicityAndOffset); void get_monitoring_period_offset(const NR_SearchSpace_t *ss, int *period, int *offset); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index f8c842706c..2366708f3c 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -887,6 +887,265 @@ dci_pdu_rel15_t prepare_dci_dl_payload(const gNB_MAC_INST *gNB_mac, return dci_payload; } +static uint32_t compute_srs_resource_indicator(long *maxMIMO_Layers, + NR_PUSCH_Config_t *pusch_Config, + NR_SRS_Config_t *srs_config, + nr_srs_feedback_t *srs_feedback) +{ + uint32_t val = 0; + if (srs_config && pusch_Config && pusch_Config->txConfig != NULL) { + if (*pusch_Config->txConfig == NR_PUSCH_Config__txConfig_codebook) { + + // TS 38.212 - Section 7.3.1.1.2: SRS resource indicator has ceil(log2(N_SRS)) bits according to + // Tables 7.3.1.1.2-32, 7.3.1.1.2-32A and 7.3.1.1.2-32B if the higher layer parameter txConfig = codebook, + // where N_SRS is the number of configured SRS resources in the SRS resource set configured by higher layer + // parameter srs-ResourceSetToAddModList, and associated with the higher layer parameter usage of value codeBook. + int count = srs_codebook_nb_res(srs_config); + if (count > 1) + val = table_7_3_1_1_2_32[count - 2][srs_feedback->sri]; + } else { + // TS 38.212 - Section 7.3.1.1.2: SRS resource indicator has ceil(log2(sum(k = 1 until min(Lmax,N_SRS) of binomial(N_SRS,k)))) + // bits according to Tables 7.3.1.1.2-28/29/30/31 if the higher layer parameter txConfig = nonCodebook, where + // N_SRS is the number of configured SRS resources in the SRS resource set configured by higher layer parameter + // srs-ResourceSetToAddModList, and associated with the higher layer parameter usage of value nonCodeBook and: + // + // - if UE supports operation with maxMIMO-Layers and the higher layer parameter maxMIMO-Layers of + // PUSCH-ServingCellConfig of the serving cell is configured, Lmax is given by that parameter; + // + // - otherwise, Lmax is given by the maximum number of layers for PUSCH supported by the UE for the serving cell + // for non-codebook based operation. + int Lmax = 0; + if (maxMIMO_Layers != NULL) + Lmax = *maxMIMO_Layers; + else + AssertFatal(false, "MIMO on PUSCH not supported, maxMIMO_Layers needs to be set to 1\n"); + int count = srs_non_codebook_nb_res(srs_config); + int lsum = srs_binomial_sum(count, Lmax); + if (lsum > 0 && ceil(log2(lsum)) > 0) { + switch(Lmax) { + case 1: + val = table_7_3_1_1_2_28[count-2][srs_feedback->sri]; + break; + case 2: + val = table_7_3_1_1_2_29[count-2][srs_feedback->sri]; + break; + case 3: + val = table_7_3_1_1_2_30[count-2][srs_feedback->sri]; + break; + case 4: + val = table_7_3_1_1_2_31[count-2][srs_feedback->sri]; + break; + default: + LOG_E(NR_MAC, "%s (%d) - Invalid Lmax %d\n", __FUNCTION__, __LINE__, Lmax); + } + } + } + } + return val; +} + +static uint32_t compute_precoding_information(NR_PUSCH_Config_t *pusch_Config, + NR_SRS_Config_t *srs_config, + dci_field_t srs_resource_indicator, + nr_srs_feedback_t *srs_feedback, + const uint8_t *nrOfLayers, + int *tpmi) +{ + uint32_t val = 0; + + uint8_t pusch_antenna_ports = get_pusch_nb_antenna_ports(pusch_Config, srs_config, srs_resource_indicator); + if (!pusch_Config + || (pusch_Config->txConfig != NULL && *pusch_Config->txConfig == NR_PUSCH_Config__txConfig_nonCodebook) + || pusch_antenna_ports == 1) { + return val; + } + + long max_rank = *pusch_Config->maxRank; + long *ul_FullPowerTransmission = pusch_Config->ext1 ? pusch_Config->ext1->ul_FullPowerTransmission_r16 : NULL; + long *codebookSubset = pusch_Config->codebookSubset; + int ul_tpmi = tpmi ? *tpmi : srs_feedback ? srs_feedback->tpmi : -1; + + if (pusch_antenna_ports == 2) { + + if (max_rank == 1) { + // - 1 or 3 bits according to Table 7.3.1.1.2-5 for 2 antenna ports, if txConfig = codebook, ul-FullPowerTransmission + // is not configured or configured to fullpowerMode2 or configured to fullpower, and according to whether transform + // precoder is enabled or disabled, and the values of higher layer parameters maxRank and codebookSubset; + // - 2 bits according to Table 7.3.1.1.2-5A for 2 antenna ports, if txConfig = codebook, ul-FullPowerTransmission = + // fullpowerMode1, maxRank=1, and according to whether transform precoder is enabled or disabled, and the values + // of higher layer parameter codebookSubset; + if (ul_FullPowerTransmission && *ul_FullPowerTransmission == NR_PUSCH_Config__ext1__ul_FullPowerTransmission_r16_fullpowerMode1) { + AssertFatal(ul_tpmi <= 2,"TPMI %d is invalid!\n", ul_tpmi); + val = ul_tpmi; + } else { + if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) { + AssertFatal(ul_tpmi <= 1,"TPMI %d is invalid!\n", ul_tpmi); + val = ul_tpmi; + } else { + AssertFatal(ul_tpmi <= 5,"TPMI %d is invalid!\n", ul_tpmi); + val = ul_tpmi; + } + } + } else { + // - 2 or 4 bits according to Table 7.3.1.1.2-4 for 2 antenna ports, if txConfig = codebook, ul-FullPowerTransmission + // is not configured or configured to fullpowerMode2 or configured to fullpower, and according to whether transform + // precoder is enabled or disabled, and the values of higher layer parameters maxRank and codebookSubset; + // - 2 bits according to Table 7.3.1.1.2-4A for 2 antenna ports, if txConfig = codebook, ul-FullPowerTransmission = + // fullpowerMode1, transform precoder is disabled, maxRank=2, and codebookSubset=nonCoherent; + if (ul_FullPowerTransmission && *ul_FullPowerTransmission == NR_PUSCH_Config__ext1__ul_FullPowerTransmission_r16_fullpowerMode1) { + AssertFatal((*nrOfLayers==1 && ul_tpmi <= 2) + || (*nrOfLayers==2 && ul_tpmi == 0), + "TPMI %d is invalid!\n", + ul_tpmi); + val = *nrOfLayers == 1 ? table_7_3_1_1_2_4A_1layer[ul_tpmi] : 2; + } else { + if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) { + AssertFatal((*nrOfLayers==1 && ul_tpmi <= 1) + || (*nrOfLayers==2 && ul_tpmi == 0), + "TPMI %d is invalid!\n", + ul_tpmi); + val = *nrOfLayers == 1 ? ul_tpmi : 2; + } else { + AssertFatal((*nrOfLayers==1 && ul_tpmi <= 5) + || (*nrOfLayers==2 && ul_tpmi <= 2), + "TPMI %d is invalid!\n", + ul_tpmi); + val = *nrOfLayers == 1 ? table_7_3_1_1_2_4_1layer_fullyAndPartialAndNonCoherent[ul_tpmi] : + table_7_3_1_1_2_4_2layers_fullyAndPartialAndNonCoherent[ul_tpmi]; + } + } + } + + } else if (pusch_antenna_ports == 4) { + + if (max_rank == 1) { + // - 2, 4, or 5 bits according to Table 7.3.1.1.2-3 for 4 antenna ports, if txConfig = codebook, ul-FullPowerTransmission + // is not configured or configured to fullpowerMode2 or configured to fullpower, and according to whether transform + // precoder is enabled or disabled, and the values of higher layer parameters maxRank, and codebookSubset; + // - 3 or 4 bits according to Table 7.3.1.1.2-3A for 4 antenna ports, if txConfig = codebook, ul-FullPowerTransmission = + // fullpowerMode1, maxRank=1, and according to whether transform precoder is enabled or disabled, and the values + // of higher layer parameter codebookSubset; + if (ul_FullPowerTransmission && *ul_FullPowerTransmission == NR_PUSCH_Config__ext1__ul_FullPowerTransmission_r16_fullpowerMode1) { + if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) { + AssertFatal(ul_tpmi <= 3 || ul_tpmi == 13, "TPMI %d is invalid!\n", ul_tpmi); + } else { + AssertFatal(ul_tpmi <= 15, "TPMI %d is invalid!\n", ul_tpmi); + } + val = table_7_3_1_1_2_3A[ul_tpmi]; + } else { + if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) { + AssertFatal(ul_tpmi <= 3, "TPMI %d is invalid!\n", ul_tpmi); + } else if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_partialAndNonCoherent) { + AssertFatal(ul_tpmi <= 11, "TPMI %d is invalid!\n", ul_tpmi); + } else { + AssertFatal(ul_tpmi <= 27, "TPMI %d is invalid!\n", ul_tpmi); + } + val = ul_tpmi; + } + } else { + // - 4, 5, or 6 bits according to Table 7.3.1.1.2-2 for 4 antenna ports, if txConfig = codebook, ul-FullPowerTransmission + // is not configured or configured to fullpowerMode2 or configured to fullpower, and according to whether transform + // precoder is enabled or disabled, and the values of higher layer parameters maxRank, and codebookSubset; + // - 4 or 5 bits according to Table 7.3.1.1.2-2A for 4 antenna ports, if txConfig = codebook, ul-FullPowerTransmission = + // fullpowerMode1, maxRank=2, transform precoder is disabled, and according to the values of higher layer parameter + // codebookSubset; + // - 4 or 6 bits according to Table 7.3.1.1.2-2B for 4 antenna ports, if txConfig = codebook, ul-FullPowerTransmission = + // fullpowerMode1, maxRank=3 or 4, transform precoder is disabled, and according to the values of higher layer + // parameter codebookSubset; + if (ul_FullPowerTransmission && *ul_FullPowerTransmission == NR_PUSCH_Config__ext1__ul_FullPowerTransmission_r16_fullpowerMode1) { + if (max_rank == 2) { + if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) { + AssertFatal((*nrOfLayers==1 + && (ul_tpmi <= 3 || ul_tpmi == 13)) + || (*nrOfLayers == 2 && ul_tpmi <= 6), + "TPMI %d is invalid!\n", + ul_tpmi); + } else { + AssertFatal((*nrOfLayers == 1 && ul_tpmi <= 15) + || (*nrOfLayers == 2 && ul_tpmi <= 13), + "TPMI %d is invalid!\n", + ul_tpmi); + } + val = *nrOfLayers == 1 ? table_7_3_1_1_2_2A_1layer[ul_tpmi] : table_7_3_1_1_2_2A_2layers[ul_tpmi]; + } else { + if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) { + AssertFatal((*nrOfLayers == 1 + && (ul_tpmi <= 3 || ul_tpmi == 13)) + || (*nrOfLayers == 2 && ul_tpmi <= 6) + || (*nrOfLayers == 3 && ul_tpmi <= 1) + || (*nrOfLayers == 4 && ul_tpmi == 0), + "TPMI %d is invalid!\n", + ul_tpmi); + } else { + AssertFatal((*nrOfLayers == 1 && ul_tpmi <= 15) + || (*nrOfLayers == 2 && ul_tpmi <= 13) + || (*nrOfLayers == 3 && ul_tpmi <= 2) + || (*nrOfLayers == 4 && ul_tpmi <= 2), + "TPMI %d is invalid!\n", + ul_tpmi); + } + switch (*nrOfLayers) { + case 1: + val = table_7_3_1_1_2_2B_1layer[ul_tpmi]; + break; + case 2: + val = table_7_3_1_1_2_2B_2layers[ul_tpmi]; + break; + case 3: + val = table_7_3_1_1_2_2B_3layers[ul_tpmi]; + break; + case 4: + val = table_7_3_1_1_2_2B_4layers[ul_tpmi]; + break; + default: + LOG_E(NR_MAC,"Number of layers %d is invalid!\n", *nrOfLayers); + } + } + } else { + if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) { + AssertFatal((*nrOfLayers == 1 && ul_tpmi <= 3) + || (*nrOfLayers == 2 && ul_tpmi <= 5) + || (*nrOfLayers == 3 && ul_tpmi == 0) + || (*nrOfLayers == 4 && ul_tpmi == 0), + "TPMI %d is invalid!\n", + ul_tpmi); + } else if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_partialAndNonCoherent) { + AssertFatal((*nrOfLayers == 1 && ul_tpmi <= 11) + || (*nrOfLayers == 2 && ul_tpmi <= 13) + || (*nrOfLayers == 3 && ul_tpmi <= 2) + || (*nrOfLayers == 4 && ul_tpmi <= 2), + "TPMI %d is invalid!\n", + ul_tpmi); + } else { + AssertFatal((*nrOfLayers == 1 && ul_tpmi <= 28) + || (*nrOfLayers == 2 && ul_tpmi <= 22) + || (*nrOfLayers == 3 && ul_tpmi <= 7) + || (*nrOfLayers == 4 && ul_tpmi <= 5), + "TPMI %d is invalid!\n", + ul_tpmi); + } + switch (*nrOfLayers) { + case 1: + val = table_7_3_1_1_2_2_1layer[ul_tpmi]; + break; + case 2: + val = table_7_3_1_1_2_2_2layers[ul_tpmi]; + break; + case 3: + val = table_7_3_1_1_2_2_3layers[ul_tpmi]; + break; + case 4: + val = table_7_3_1_1_2_2_4layers[ul_tpmi]; + break; + default: + LOG_E(NR_MAC,"Number of layers %d is invalid!\n", *nrOfLayers); + } + } + } + } + return val; +} + void config_uldci(const NR_UE_ServingCell_Info_t *sc_info, const nfapi_nr_pusch_pdu_t *pusch_pdu, dci_pdu_rel15_t *dci_pdu_rel15, @@ -932,23 +1191,20 @@ void config_uldci(const NR_UE_ServingCell_Info_t *sc_info, // bwp indicator as per table 7.3.1.1.2-1 in 38.212 dci_pdu_rel15->bwp_indicator.val = sc_info->n_ul_bwp < 4 ? bwp_id : bwp_id - 1; // SRS resource indicator - if (pusch_Config && - pusch_Config->txConfig != NULL) { + if (pusch_Config && pusch_Config->txConfig != NULL) { AssertFatal(*pusch_Config->txConfig == NR_PUSCH_Config__txConfig_codebook, "Non Codebook configuration non supported\n"); - compute_srs_resource_indicator(sc_info->maxMIMO_Layers_PUSCH, - pusch_Config, - ul_bwp->srs_Config, - srs_feedback, - &dci_pdu_rel15->srs_resource_indicator.val); + dci_pdu_rel15->srs_resource_indicator.val = compute_srs_resource_indicator(sc_info->maxMIMO_Layers_PUSCH, + pusch_Config, + ul_bwp->srs_Config, + srs_feedback); } - compute_precoding_information(pusch_Config, - ul_bwp->srs_Config, - dci_pdu_rel15->srs_resource_indicator, - srs_feedback, - &pusch_pdu->nrOfLayers, - tpmi, - &dci_pdu_rel15->precoding_information.val); + dci_pdu_rel15->precoding_information.val = compute_precoding_information(pusch_Config, + ul_bwp->srs_Config, + dci_pdu_rel15->srs_resource_indicator, + srs_feedback, + &pusch_pdu->nrOfLayers, + tpmi); // antenna_ports.val = 0 for transform precoder is disabled, dmrs-Type=1, maxLength=1, Rank=1/2/3/4 // Antenna Ports From 5e734238c185fdcfefe710a0382639ddeccfe109 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 3 Jul 2025 17:44:03 +0200 Subject: [PATCH 446/964] pf_ul(): report if UEs scheduled For the multi-UL slot scheduling functionality in a follow-up commit, it would be important to know if the scheduler allocated any UEs. If pf_ul() allocated for some UEs, we might run it again on a different slot. If on the other hand, no UEs were allocated, there is no point in running it again. --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index bbbd72c378..6589d613a6 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -1866,7 +1866,7 @@ static int comparator(const void *p, const void *q) return 0; } -static void pf_ul(gNB_MAC_INST *nrmac, +static int pf_ul(gNB_MAC_INST *nrmac, post_process_pusch_t *pp_pusch, frame_t sched_frame, int sched_slot, @@ -1887,6 +1887,7 @@ static void pf_ul(gNB_MAC_INST *nrmac, for (int i = 0; i < num_beams; i++) remainUEs[i] = max_num_ue; int numUE = 0; + bool scheduled_something = false; /* Loop UE_list to calculate throughput and coeff */ UE_iterator(UE_list, UE) { @@ -1955,6 +1956,7 @@ static void pf_ul(gNB_MAC_INST *nrmac, /* reduce max_num_ue once we are sure UE can be allocated, i.e., has CCE */ remainUEs[beam.idx]--; + scheduled_something = true; continue; } DevAssert(ul_harq_pid == -1); // all other allocations must be new ones @@ -2207,7 +2209,13 @@ static void pf_ul(gNB_MAC_INST *nrmac, /* reduce max_num_ue once we are sure UE can be allocated, i.e., has CCE */ remainUEs[beam.idx]--; iterator++; + scheduled_something = true; } + int num_ue_sched = num_beams * max_num_ue; + for (int i = 0; i < num_beams; i++) + num_ue_sched -= remainUEs[i]; + DevAssert((num_ue_sched == 0 && !scheduled_something) || (num_ue_sched > 0 && scheduled_something)); + return num_ue_sched; } nfapi_nr_pusch_pdu_t *prepare_pusch_pdu(nfapi_nr_ul_tti_request_t *future_ul_tti_req, From 948c0d5d2c3c3a6799df886654a6a7c6d9a0e56e Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 23 Jul 2025 11:22:11 +0200 Subject: [PATCH 447/964] Count and print failed CCE allocations for UL/DL --- doc/MAC/mac-usage.md | 7 +++++-- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 2 ++ openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 2 ++ openair2/LAYER2/NR_MAC_gNB/main.c | 10 ++++++---- openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 1 + 5 files changed, 16 insertions(+), 6 deletions(-) diff --git a/doc/MAC/mac-usage.md b/doc/MAC/mac-usage.md index ae4f3a626b..1ed71d30b4 100644 --- a/doc/MAC/mac-usage.md +++ b/doc/MAC/mac-usage.md @@ -79,8 +79,8 @@ Example: UE RNTI 2460 CU-UE-ID 2 in-sync PH 28 dB PCMAX 24 dBm, average RSRP -74 (8 meas) UE 2460: CQI 15, RI 2, PMI (14,1) UE 2460: UL-RI 2 TPMI 0 -UE 2460: dlsch_rounds 32917/5113/1504/560, dlsch_errors 211, pucch0_DTX 1385, BLER 0.19557 MCS (1) 23 -UE 2460: ulsch_rounds 3756/353/182/179, ulsch_errors 170, ulsch_DTX 285, BLER 0.33021 MCS (1) 27 (Qm 8 dB) NPRB 5 SNR 31.0 dB +UE 2460: dlsch_rounds 32917/5113/1504/560, dlsch_errors 211, pucch0_DTX 1385, BLER 0.19557 MCS (1) 23 CCE fail 3 +UE 2460: ulsch_rounds 3756/353/182/179, ulsch_errors 170, ulsch_DTX 285, BLER 0.33021 MCS (1) 27 (Qm 8 dB) NPRB 5 SNR 31.0 dB CCE fail 0 UE 2460: MAC: TX 1530943191 RX 194148 bytes UE 2460: LCID 1: TX 651 RX 3031 bytes UE 2460: LCID 2: TX 0 RX 0 bytes @@ -159,6 +159,9 @@ The fourth and fifth line show HARQ-related information: should be close to the target in the gNB configuration file, `pusch_TargetSNRx10`, which should be around 10 times the value shown in the log +* Both ULSCH/DLSCH `CCE fail`: lists the number of failed CCE attempts. If this + number gets high, it signifies that the scheduler tried to scheduled this UE, + but could not allocate the DCI. In the last lines: * `MAC` shows the amount of MAC PDU bytes scheduled in transmit (`TX`, diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index dad58f52f0..186e67f10d 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -554,6 +554,7 @@ static bool allocate_dl_retransmission(module_id_t module_id, false, sched_ctrl->pdcch_cl_adjust); if (CCEIndex<0) { + sched_ctrl->dl_cce_fail++; LOG_D(NR_MAC, "[UE %04x][%4d.%2d] could not find free CCE for DL DCI retransmission\n", UE->rnti, frame, slot); return false; } @@ -806,6 +807,7 @@ static void pf_dl(module_id_t module_id, false, sched_ctrl->pdcch_cl_adjust); if (CCEIndex < 0) { + sched_ctrl->dl_cce_fail++; LOG_D(NR_MAC, "[UE %04x][%4d.%2d] could not find free CCE for DL DCI\n", rnti, frame, slot); reset_beam_status(&mac->beam_info, frame, slot, iterator->UE->UE_beam_index, slots_per_frame, beam.new_beam); iterator++; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 6589d613a6..41fa85b9ec 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -1816,6 +1816,7 @@ static bool allocate_ul_retransmission(gNB_MAC_INST *nrmac, sched_ctrl->pdcch_cl_adjust); if (CCEIndex<0) { LOG_D(NR_MAC, "[UE %04x][%4d.%2d] no free CCE for retransmission UL DCI UE\n", UE->rnti, frame, slot); + sched_ctrl->ul_cce_fail++; return false; } @@ -2058,6 +2059,7 @@ static int pf_ul(gNB_MAC_INST *nrmac, sched_ctrl->pdcch_cl_adjust); if (CCEIndex < 0) { + sched_ctrl->ul_cce_fail++; reset_beam_status(&nrmac->beam_info, frame, slot, iterator->UE->UE_beam_index, slots_per_frame, dci_beam.new_beam); reset_beam_status(&nrmac->beam_info, sched_frame, sched_slot, iterator->UE->UE_beam_index, slots_per_frame, beam.new_beam); LOG_D(NR_MAC, "[UE %04x][%4d.%2d] no free CCE for UL DCI\n", iterator->UE->rnti, frame, slot); diff --git a/openair2/LAYER2/NR_MAC_gNB/main.c b/openair2/LAYER2/NR_MAC_gNB/main.c index c4f0fad659..d40fbe84c7 100644 --- a/openair2/LAYER2/NR_MAC_gNB/main.c +++ b/openair2/LAYER2/NR_MAC_gNB/main.c @@ -168,12 +168,13 @@ size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset output += snprintf(output, end - output, - ", dlsch_errors %"PRIu64", pucch0_DTX %d, BLER %.5f MCS (%d) %d\n", + ", dlsch_errors %"PRIu64", pucch0_DTX %d, BLER %.5f MCS (%d) %d CCE fail %d\n", stats->dl.errors, stats->pucch0_DTX, sched_ctrl->dl_bler_stats.bler, UE->current_DL_BWP.mcsTableIdx, - sched_ctrl->dl_bler_stats.mcs); + sched_ctrl->dl_bler_stats.mcs, + sched_ctrl->dl_cce_fail); if (reset_rsrp) { stats->num_rsrp_meas = 0; stats->cumul_rsrp = 0; @@ -187,7 +188,7 @@ size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset output += snprintf(output, end - output, - ", ulsch_errors %"PRIu64", ulsch_DTX %d, BLER %.5f MCS (%d) %d (Qm %d deltaMCS %d dB) NPRB %d SNR %d.%d dB\n", + ", ulsch_errors %"PRIu64", ulsch_DTX %d, BLER %.5f MCS (%d) %d (Qm %d deltaMCS %d dB) NPRB %d SNR %d.%d dB CCE fail %d\n", stats->ul.errors, stats->ulsch_DTX, sched_ctrl->ul_bler_stats.bler, @@ -197,7 +198,8 @@ size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset UE->mac_stats.deltaMCS, UE->mac_stats.NPRB, sched_ctrl->pusch_snrx10 / 10, - sched_ctrl->pusch_snrx10 % 10); + sched_ctrl->pusch_snrx10 % 10, + sched_ctrl->ul_cce_fail); output += snprintf(output, end - output, "UE %04x: MAC: TX %14"PRIu64" RX %14"PRIu64" bytes\n", diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 1778d0507f..36221906b0 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -591,6 +591,7 @@ typedef struct { /// corresponding to the sched_pusch/sched_pdsch structures below int cce_index; uint8_t aggregation_level; + uint32_t dl_cce_fail, ul_cce_fail; /// Array of PUCCH scheduling information /// Its size depends on TDD configuration and max feedback time From 90406c101e6d9c6efa2ca1296435c78c3f66f53e Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 1 Jul 2025 13:36:17 +0200 Subject: [PATCH 448/964] Introduce dedicated ul_tda array --- openair2/LAYER2/NR_MAC_gNB/config.c | 25 +++++++++++++++++++++++++ openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 4 ++++ 2 files changed, 29 insertions(+) diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c index 99e4249bb2..f13567b747 100644 --- a/openair2/LAYER2/NR_MAC_gNB/config.c +++ b/openair2/LAYER2/NR_MAC_gNB/config.c @@ -801,6 +801,28 @@ static void config_sched_ctrlCommon(gNB_MAC_INST *nr_mac) nr_mac->cset0_bwp_size = type0_PDCCH_CSS_config.num_rbs; } +/** + * \brief Initializes the UL TDA information at the scheduler, as used for + * every UE in UL. This just copies the information from the SCC into a smaller + * list. Note that this list should not be modified, as get_ul_tda() and + * nr_rrc_config_ul_tda() are designed to work in sync (get_ul_tda() assumes an + * ordering, output by nr_rrc_config_ul_tda()). + */ +static void init_ul_tda_info(const NR_PUSCH_TimeDomainResourceAllocationList_t *l, seq_arr_t *sa_tda) +{ + DevAssert(l->list.count > 0 && l->list.count <= 16); + DevAssert(seq_arr_size(sa_tda) == 0); + + for (int i = 0; i < l->list.count; ++i) { + NR_PUSCH_TimeDomainResourceAllocation_t *t = l->list.array[i]; + DevAssert(t->k2); + NR_tda_info_t tda = { .mapping_type = typeB, .k2 = *t->k2, .valid_tda = true }; + SLIV2SL(t->startSymbolAndLength, &tda.startSymbolIndex, &tda.nrOfSymbols); + LOG_I(NR_MAC, "TDA index %d: start %d length %d k2 %ld\n", i, tda.startSymbolIndex, tda.nrOfSymbols, tda.k2); + seq_arr_push_back(sa_tda, &tda, sizeof(tda)); + } +} + void nr_mac_config_scc(gNB_MAC_INST *nrmac, NR_ServingCellConfigCommon_t *scc, const nr_mac_config_t *config) { DevAssert(nrmac != NULL); @@ -847,6 +869,9 @@ void nr_mac_config_scc(gNB_MAC_INST *nrmac, NR_ServingCellConfigCommon_t *scc, c if (IS_SA_MODE(get_softmodem_params())) config_sched_ctrlCommon(nrmac); + + seq_arr_init(&nrmac->ul_tda, sizeof(NR_tda_info_t)); + init_ul_tda_info(scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList, &nrmac->ul_tda); } bool nr_mac_configure_other_sib(gNB_MAC_INST *nrmac, int num_cu_sib, const f1ap_sib_msg_t cu_sib[num_cu_sib]) diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 36221906b0..9dcddcef4d 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -929,6 +929,10 @@ typedef struct gNB_MAC_INST_s { bool identity_pm; int precoding_matrix_size[NR_MAX_NB_LAYERS]; int fapi_beam_index[MAX_NUM_OF_SSB]; + + /// dedicate UL TDA, common for all UEs + seq_arr_t ul_tda; + nr_mac_rrc_ul_if_t mac_rrc; f1_config_t f1_config; int16_t frame; From 9059c0290ef6438a0b54c181c294223c00262525 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 30 Jun 2025 15:05:11 +0200 Subject: [PATCH 449/964] Provide selected TDA to pf_ul() --- .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 73 +++++++++---------- 1 file changed, 34 insertions(+), 39 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 41fa85b9ec..50c4f8c596 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -1709,7 +1709,8 @@ static bool allocate_ul_retransmission(gNB_MAC_INST *nrmac, NR_UE_info_t *UE, int harq_pid, const NR_ServingCellConfigCommon_t *scc, - const int tda) + const int tda, + const NR_tda_info_t *tda_info) { const int CC_id = 0; int frame = pp_pusch->frame; @@ -1726,22 +1727,15 @@ static bool allocate_ul_retransmission(gNB_MAC_INST *nrmac, const uint32_t bwpStart = bwp_info.bwpStart; const uint8_t nrOfLayers = retInfo->nrOfLayers; LOG_D(NR_MAC,"retInfo->time_domain_allocation = %d, tda = %d\n", retInfo->time_domain_allocation, tda); - NR_tda_info_t tda_info = get_ul_tda_info(ul_bwp, - sched_ctrl->coreset->controlResourceSetId, - sched_ctrl->search_space->searchSpaceType->present, - TYPE_C_RNTI_, - tda); - if (!tda_info.valid_tda) - return false; /* mark when retransmission will happen */ int slots_frame = nrmac->frame_structure.numb_slots_frame; - new_sched.frame = (frame + (slot + tda_info.k2 + get_NTN_Koffset(scc)) / slots_frame) % MAX_FRAME_NUMBER; - new_sched.slot = (slot + tda_info.k2 + get_NTN_Koffset(scc)) % slots_frame; + new_sched.frame = (frame + (slot + tda_info->k2 + get_NTN_Koffset(scc)) / slots_frame) % MAX_FRAME_NUMBER; + new_sched.slot = (slot + tda_info->k2 + get_NTN_Koffset(scc)) % slots_frame; new_sched.bwp_info = bwp_info; DevAssert(new_sched.ul_harq_pid == harq_pid); - bool reuse_old_tda = (retInfo->tda_info.startSymbolIndex == tda_info.startSymbolIndex) && (retInfo->tda_info.nrOfSymbols <= tda_info.nrOfSymbols); + bool reuse_old_tda = (retInfo->tda_info.startSymbolIndex == tda_info->startSymbolIndex) && (retInfo->tda_info.nrOfSymbols <= tda_info->nrOfSymbols); if (reuse_old_tda && nrOfLayers == retInfo->nrOfLayers) { /* Check the resource is enough for retransmission */ const uint16_t slbitmap = SL_to_bitmap(retInfo->tda_info.startSymbolIndex, retInfo->tda_info.nrOfSymbols); @@ -1760,10 +1754,10 @@ static bool allocate_ul_retransmission(gNB_MAC_INST *nrmac, new_sched.rbStart = rbStart; LOG_D(NR_MAC, "Retransmission keeping TDA %d and TBS %d\n", tda, retInfo->tb_size); } else { - NR_pusch_dmrs_t dmrs_info = get_ul_dmrs_params(scc, ul_bwp, &tda_info, nrOfLayers); + NR_pusch_dmrs_t dmrs_info = get_ul_dmrs_params(scc, ul_bwp, tda_info, nrOfLayers); /* the retransmission will use a different time domain allocation, check * that we have enough resources */ - const uint16_t slbitmap = SL_to_bitmap(tda_info.startSymbolIndex, tda_info.nrOfSymbols); + const uint16_t slbitmap = SL_to_bitmap(tda_info->startSymbolIndex, tda_info->nrOfSymbols); while (rbStart < bwpSize && (rballoc_mask[rbStart + bwpStart] & slbitmap)) rbStart++; int rbSize = 0; @@ -1775,7 +1769,7 @@ static bool allocate_ul_retransmission(gNB_MAC_INST *nrmac, retInfo->R, UE->current_UL_BWP.transform_precoding, nrOfLayers, - tda_info.nrOfSymbols, + tda_info->nrOfSymbols, dmrs_info.N_PRB_DMRS * dmrs_info.num_dmrs_symb, retInfo->tb_size, 1, /* minimum of 1RB: need to find exact TBS, don't preclude any number */ @@ -1798,7 +1792,7 @@ static bool allocate_ul_retransmission(gNB_MAC_INST *nrmac, new_sched.rbStart = rbStart; new_sched.tb_size = new_tbs; new_sched.time_domain_allocation = tda; - new_sched.tda_info = tda_info; + new_sched.tda_info = *tda_info; new_sched.dmrs_info = dmrs_info; } @@ -1869,8 +1863,8 @@ static int comparator(const void *p, const void *q) static int pf_ul(gNB_MAC_INST *nrmac, post_process_pusch_t *pp_pusch, - frame_t sched_frame, - int sched_slot, + int tda, + const NR_tda_info_t *tda_info, NR_UE_info_t *UE_list[], int max_num_ue, int num_beams, @@ -1881,6 +1875,12 @@ static int pf_ul(gNB_MAC_INST *nrmac, int slot = pp_pusch->slot; NR_ServingCellConfigCommon_t *scc = nrmac->common_channels[CC_id].ServingCellConfigCommon; int slots_per_frame = nrmac->frame_structure.numb_slots_frame; + DevAssert(tda_info->valid_tda); + const int k2 = tda_info->k2 + get_NTN_Koffset(scc); + const int sched_frame = (frame + (slot + k2) / slots_per_frame) % MAX_FRAME_NUMBER; + const int sched_slot = (slot + k2) % slots_per_frame; + DevAssert(is_ul_slot(sched_slot, &nrmac->frame_structure)); + const int min_rb = nrmac->min_grant_prb; // UEs that could be scheduled UEsched_t UE_sched[MAX_MOBILES_PER_GNB + 1] = {0}; @@ -1936,7 +1936,6 @@ static int pf_ul(gNB_MAC_INST *nrmac, LOG_D(NR_MAC,"pf_ul: UE %04x harq_pid %d\n", UE->rnti, ul_harq_pid); if (ul_harq_pid >= 0) { /* Allocate retransmission*/ - const int tda = get_ul_tda(nrmac, sched_frame, sched_slot); bool r = allocate_ul_retransmission(nrmac, pp_pusch, rballoc_mask, @@ -1945,7 +1944,8 @@ static int pf_ul(gNB_MAC_INST *nrmac, UE, ul_harq_pid, scc, - tda); + tda, + tda_info); if (!r) { LOG_D(NR_MAC, "[UE %04x][%4d.%2d] UL retransmission could not be allocated\n", UE->rnti, frame, slot); reset_beam_status(&nrmac->beam_info, sched_frame, sched_slot, UE->UE_beam_index, slots_per_frame, beam.new_beam); @@ -2069,21 +2069,12 @@ static int pf_ul(gNB_MAC_INST *nrmac, else LOG_D(NR_MAC, "%4d.%2d free CCE for UL DCI UE %04x\n", frame, slot, iterator->UE->rnti); - - int tda = get_ul_tda(nrmac, sched_frame, sched_slot); - NR_tda_info_t tda_info = get_ul_tda_info(current_BWP, - sched_ctrl->coreset->controlResourceSetId, - sched_ctrl->search_space->searchSpaceType->present, - TYPE_C_RNTI_, - tda); - AssertFatal(tda_info.valid_tda, "Invalid TDA from get_ul_tda_info\n"); - const int index = ul_buffer_index(sched_frame, sched_slot, slots_per_frame, nrmac->vrb_map_UL_size); uint16_t *rballoc_mask = &nrmac->common_channels[CC_id].vrb_map_UL[beam.idx][index * MAX_BWP_SIZE]; /* find maximum amount of RBs that we can schedule starting from first free RB */ int rbStart = 0; - const uint16_t slbitmap = SL_to_bitmap(tda_info.startSymbolIndex, tda_info.nrOfSymbols); + const uint16_t slbitmap = SL_to_bitmap(tda_info->startSymbolIndex, tda_info->nrOfSymbols); bwp_info_t bi = get_pusch_bwp_start_size(iterator->UE); while (rbStart < bi.bwpSize && (rballoc_mask[rbStart + bi.bwpStart] & slbitmap)) rbStart++; @@ -2127,8 +2118,8 @@ static int pf_ul(gNB_MAC_INST *nrmac, .nrOfLayers = nrOfLayers, // tpmi in post-process .time_domain_allocation = tda, - .tda_info = tda_info, - .dmrs_info = get_ul_dmrs_params(scc, current_BWP, &tda_info, nrOfLayers), + .tda_info = *tda_info, + .dmrs_info = get_ul_dmrs_params(scc, current_BWP, tda_info, nrOfLayers), .bwp_info = bi, // phr_txpower_calc below }; @@ -2542,11 +2533,10 @@ static void nr_ulsch_preprocessor(gNB_MAC_INST *nr_mac, post_process_pusch_t *pp NR_COMMON_channels_t *cc = nr_mac->common_channels; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; - const NR_SIB1_t *sib1 = nr_mac->common_channels[0].sib1 ? nr_mac->common_channels[0].sib1->message.choice.c1->choice.systemInformationBlockType1 : NULL; - NR_ServingCellConfigCommonSIB_t *scc_sib1 = sib1 ? sib1->servingCellConfigCommon : NULL; - AssertFatal(scc || scc_sib1, "We need one serving cell config common\n"); + AssertFatal(scc, "We need one serving cell config common\n"); + const int slots_frame = nr_mac->frame_structure.numb_slots_frame; - // TODO we assume the same K2 for all UEs + // we assume the same K2 for all UEs const int K2 = nr_mac->radio_config.minRXTXTIME + get_NTN_Koffset(scc); const int sched_frame = (frame + (slot + K2) / slots_frame) % MAX_FRAME_NUMBER; const int sched_slot = (slot + K2) % slots_frame; @@ -2555,9 +2545,6 @@ static void nr_ulsch_preprocessor(gNB_MAC_INST *nr_mac, post_process_pusch_t *pp int num_beams = nr_mac->beam_info.beam_allocation ? nr_mac->beam_info.beams_per_period : 1; int bw = scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth; - int len[num_beams]; - for (int i = 0; i < num_beams; i++) - len[i] = bw; int average_agg_level = 4; // TODO find a better estimation int max_sched_ues = bw / (average_agg_level * NR_NB_REG_PER_CCE); @@ -2565,8 +2552,16 @@ static void nr_ulsch_preprocessor(gNB_MAC_INST *nr_mac, post_process_pusch_t *pp // FAPI cannot handle more than MAX_DCI_CORESET DCIs max_sched_ues = min(max_sched_ues, MAX_DCI_CORESET); + int tda = get_ul_tda(nr_mac, sched_frame, sched_slot); + /* TODO: iterate over all available UL slots if there are more than DL */ + /* the following supposes that the TDA is the same across all BWPs */ + NR_tda_info_t *tda_info = seq_arr_at(&nr_mac->ul_tda, tda); + + int len[num_beams]; + for (int i = 0; i < num_beams; i++) + len[i] = bw; /* proportional fair scheduling algorithm */ - pf_ul(nr_mac, pp_pusch, sched_frame, sched_slot, nr_mac->UE_info.connected_ue_list, max_sched_ues, num_beams, len); + pf_ul(nr_mac, pp_pusch, tda, tda_info, nr_mac->UE_info.connected_ue_list, max_sched_ues, num_beams, len); } nr_pp_impl_ul nr_init_ulsch_preprocessor(int CC_id) From 4aea866b6aac83f2056f5abf3ae733b3d6d8eb8d Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 3 Jul 2025 10:27:34 +0200 Subject: [PATCH 450/964] Use k2 to decide which TDA to use For scheduling multiple ULSCH ahead, we will have to use different k2. Hence, we will need to check for k2 in the TDA selection as well. The function get_ul_tda() is renamed to get_num_ul_tda() to reflect that it might return multiple TDAs (not done in this commit, but in a follow-up MR). get_num_ul_tda() also returns a pointer to the first suitable TDA. In the phy-test scheduler, simplify the selection of the TDA to use: do not hardcode a specific K2, but rather, use the first one (with any k2). --- openair2/LAYER2/NR_MAC_gNB/config.c | 6 ++-- .../LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c | 35 ++++++------------- .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 33 ++++++++++++----- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 2 +- 4 files changed, 38 insertions(+), 38 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c index f13567b747..2866900f5e 100644 --- a/openair2/LAYER2/NR_MAC_gNB/config.c +++ b/openair2/LAYER2/NR_MAC_gNB/config.c @@ -804,9 +804,9 @@ static void config_sched_ctrlCommon(gNB_MAC_INST *nr_mac) /** * \brief Initializes the UL TDA information at the scheduler, as used for * every UE in UL. This just copies the information from the SCC into a smaller - * list. Note that this list should not be modified, as get_ul_tda() and - * nr_rrc_config_ul_tda() are designed to work in sync (get_ul_tda() assumes an - * ordering, output by nr_rrc_config_ul_tda()). + * list. Note that this list should not be modified, as get_num_ul_tda() and + * nr_rrc_config_ul_tda() are designed to work in sync (get_num_ul_tda() + * assumes an ordering, output by nr_rrc_config_ul_tda()). */ static void init_ul_tda_info(const NR_PUSCH_TimeDomainResourceAllocationList_t *l, seq_arr_t *sa_tda) { diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c index 6323ab4c6a..00872ade89 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c @@ -239,26 +239,19 @@ void nr_ul_preprocessor_phytest(gNB_MAC_INST *nr_mac, post_process_pusch_t *pp_p uint16_t rbStart = 0; uint16_t rbSize = min(bw, target_ul_bw); - NR_PUSCH_TimeDomainResourceAllocationList_t *tdaList = get_ul_tdalist(ul_bwp, - sched_ctrl->coreset->controlResourceSetId, - sched_ctrl->search_space->searchSpaceType->present, - TYPE_C_RNTI_); - const int temp_tda = get_ul_tda(nr_mac, frame, slot); - if (temp_tda < 0) - return; - AssertFatal(temp_tda < tdaList->list.count, "time domain assignment %d >= %d\n", temp_tda, tdaList->list.count); - const int mu = ul_bwp->scs; - int K2 = get_K2(tdaList, temp_tda, mu, scc); + DevAssert(seq_arr_size(&nr_mac->ul_tda) > 0); + const int tda = 0; + NR_tda_info_t tda_info = get_ul_tda_info(ul_bwp, + sched_ctrl->coreset->controlResourceSetId, + sched_ctrl->search_space->searchSpaceType->present, + TYPE_C_RNTI_, + tda); + DevAssert(tda_info.valid_tda); + + int K2 = tda_info.k2 + get_NTN_Koffset(scc); int slots_frame = nr_mac->frame_structure.numb_slots_frame; const int sched_frame = (frame + (slot + K2) / slots_frame) % MAX_FRAME_NUMBER; const int sched_slot = (slot + K2) % slots_frame; - const int tda = get_ul_tda(nr_mac, sched_frame, sched_slot); - if (tda < 0) - return; - AssertFatal(tda < tdaList->list.count, - "time domain assignment %d >= %d\n", - tda, - tdaList->list.count); /* check if slot is UL, and that slot is 8 (assuming K2=6 because of UE * limitations). Note that if K2 or the TDD configuration is changed, below @@ -267,14 +260,6 @@ void nr_ul_preprocessor_phytest(gNB_MAC_INST *nr_mac, post_process_pusch_t *pp_p if (!is_xlsch_in_slot(ulsch_slot_bitmap, slot_period)) return; - NR_tda_info_t tda_info = get_ul_tda_info(ul_bwp, - sched_ctrl->coreset->controlResourceSetId, - sched_ctrl->search_space->searchSpaceType->present, - TYPE_C_RNTI_, - tda); - if (!tda_info.valid_tda) - return; - // TODO implement beam procedures for phy-test mode int beam = 0; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 50c4f8c596..40d9457a23 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -38,9 +38,10 @@ //#define SRS_IND_DEBUG -/* \brief Get the UL TDA for given frame and slot. It identifies the index of - * TDA in the TDA list, as hardcoded in nr_rrc_config_ul_tda(). */ -int get_ul_tda(gNB_MAC_INST *nrmac, int frame, int slot) +/* \brief Get the number of UL TDAs that could be used in frame and slot, reachable + * via specific k2. The output parameter first_idx is a pointer to the first + * suitable TDA, and the function returns the number of suitable TDAs, or 0. */ +int get_num_ul_tda(gNB_MAC_INST *nrmac, int frame, int slot, int k2, const NR_tda_info_t **first_idx) { /* we assume that this function is mutex-protected from outside */ NR_SCHED_ENSURE_LOCKED(&nrmac->sched_lock); @@ -48,23 +49,34 @@ int get_ul_tda(gNB_MAC_INST *nrmac, int frame, int slot) /* there is a mixed slot only when in TDD */ frame_structure_t *fs = &nrmac->frame_structure; + /* TODO: we assume currently that all UL TDA have same k2, check below */ + NR_tda_info_t *tda_info = seq_arr_at(&nrmac->ul_tda, 0); + if (!tda_info->valid_tda || tda_info->k2 != k2) + return 0; + if (fs->frame_type == TDD) { // if there is uplink symbols in mixed slot int s = get_slot_idx_in_period(slot, fs); tdd_bitmap_t *tdd_slot_bitmap = fs->period_cfg.tdd_slot_bitmap; if ((tdd_slot_bitmap[s].num_ul_symbols > 1) && is_mixed_slot(s, fs)) { - return 2; // mixed slot, all symbols of mixed minus last + *first_idx = seq_arr_at(&nrmac->ul_tda, 2); // mixed slot, all symbols of mixed minus last + return 1; } } // Avoid slots with the SRS UE_iterator(nrmac->UE_info.connected_ue_list, UE) { NR_sched_srs_t sched_srs = UE->UE_sched_ctrl.sched_srs; - if(sched_srs.srs_scheduled && sched_srs.frame == frame && sched_srs.slot == slot) - return 1; // symbols 0--12 + if(sched_srs.srs_scheduled && sched_srs.frame == frame && sched_srs.slot == slot) { + *first_idx = seq_arr_at(&nrmac->ul_tda, 1); // symbols 0--12 + return 1; + } } - return 0; // symbols 0--13, // if FDD or not mixed slot in TDD, for now use default TDA (TODO handle CSI-RS slots) + // symbols 0--13, if FDD or not mixed slot in TDD, for now use default TDA + // (TODO handle CSI-RS slots) + *first_idx = seq_arr_at(&nrmac->ul_tda, 0); + return 1; } bwp_info_t get_pusch_bwp_start_size(NR_UE_info_t *UE) @@ -2552,10 +2564,13 @@ static void nr_ulsch_preprocessor(gNB_MAC_INST *nr_mac, post_process_pusch_t *pp // FAPI cannot handle more than MAX_DCI_CORESET DCIs max_sched_ues = min(max_sched_ues, MAX_DCI_CORESET); - int tda = get_ul_tda(nr_mac, sched_frame, sched_slot); + const NR_tda_info_t *tda_info = NULL; + int n_tda = get_num_ul_tda(nr_mac, sched_frame, sched_slot, nr_mac->radio_config.minRXTXTIME, &tda_info); + DevAssert(n_tda == 1); + int tda = seq_arr_dist(&nr_mac->ul_tda, seq_arr_front(&nr_mac->ul_tda), tda_info); + AssertFatal(tda >= 0 && tda < 16, "illegal TDA index %d\n", tda); /* TODO: iterate over all available UL slots if there are more than DL */ /* the following supposes that the TDA is the same across all BWPs */ - NR_tda_info_t *tda_info = seq_arr_at(&nr_mac->ul_tda, tda); int len[num_beams]; for (int i = 0; i < num_beams; i++) diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 2c9e1a2a43..91c0969dde 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -417,7 +417,7 @@ void free_sched_pucch_list(NR_UE_sched_ctrl_t *sched_ctrl); bool add_UE_to_list(int list_size, NR_UE_info_t *list[list_size], NR_UE_info_t *UE); NR_UE_info_t *remove_UE_from_list(int list_size, NR_UE_info_t *list[list_size], rnti_t rnti); int get_dl_tda(const gNB_MAC_INST *nrmac, int slot); -int get_ul_tda(gNB_MAC_INST *nrmac, int frame, int slot); +int get_num_ul_tda(gNB_MAC_INST *nrmac, int frame, int slot, int k2, const NR_tda_info_t **first_idx); int get_cce_index(const gNB_MAC_INST *nrmac, const int CC_id, From 3102068e71264de3c1fb2db96f2f031da20edaca Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 3 Jul 2025 12:16:11 +0200 Subject: [PATCH 451/964] Add ULSCH preprocessor slot logic for scheduling multiple slots Add a loop to advance slots as determined by current ("DL") slot, and advance further into the future (for "UL" slots) if TDAs allow. Ensure to schedule all TDAs if it's the last DL slot, to guarantee a previously scheduled TDA will also reoccur (i.e., for guaranteeing that retransmissions can be made). Note that the check for number of UE being zero is removed, as this allows to keep "ul_next" close to the "min_next" slot. This way, we can use fs_get_max(); otherwise, if we did not always execute this loop, they might diverge far from each other, making the logic inside the loop more complicated. This commit introduces a new type "fsn_t" (frame-slot number) that encapsulates a single frame-slot combination in a single struct. The helper functions (in gNB_scheduler_ulsch.c) should be moved to a new file under common/, but we don't do this here to limit the amount of code changes. --- .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 108 +++++++++++++----- openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 10 ++ 2 files changed, 88 insertions(+), 30 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 40d9457a23..93db0d1945 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -2534,49 +2534,103 @@ void post_process_ulsch(gNB_MAC_INST *nr_mac, post_process_pusch_t *pusch, NR_UE nr_mac->cset0_bwp_size); } +fsn_t fs_add_delta(const frame_structure_t *fs, uint32_t delta, fsn_t fsn) +{ + const int slots_frame = fs->numb_slots_frame; + fsn_t res = { + .f = (fsn.f + (fsn.s + delta) / slots_frame) % MAX_FRAME_NUMBER, + .s = (fsn.s + delta) % slots_frame, + }; + return res; +} +int fs_get_diff(const frame_structure_t *fs, fsn_t a, fsn_t b) +{ + const int slots_frame = fs->numb_slots_frame; + int diff = (a.f * slots_frame + a.s) - (b.f * slots_frame + b.s); + if (diff < -512 * slots_frame) + diff += 1024 * slots_frame; + else if (diff > 512 * slots_frame) + diff -= 1024 * slots_frame; + return diff; +} +fsn_t fs_get_max(const frame_structure_t *fs, fsn_t a, fsn_t b) +{ + if (fs_get_diff(fs, a, b) <= 0) { + return b; + } else { + return a; + } +} + static void nr_ulsch_preprocessor(gNB_MAC_INST *nr_mac, post_process_pusch_t *pp_pusch) { int frame = pp_pusch->frame; int slot = pp_pusch->slot; - // no UEs - if (nr_mac->UE_info.connected_ue_list[0] == NULL) - return; - NR_COMMON_channels_t *cc = nr_mac->common_channels; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; AssertFatal(scc, "We need one serving cell config common\n"); + const frame_structure_t *fs = &nr_mac->frame_structure; - const int slots_frame = nr_mac->frame_structure.numb_slots_frame; // we assume the same K2 for all UEs - const int K2 = nr_mac->radio_config.minRXTXTIME + get_NTN_Koffset(scc); - const int sched_frame = (frame + (slot + K2) / slots_frame) % MAX_FRAME_NUMBER; - const int sched_slot = (slot + K2) % slots_frame; - if (!is_ul_slot(sched_slot, &nr_mac->frame_structure)) - return; + const int koffset = get_NTN_Koffset(scc); + const int min_rxtx = nr_mac->radio_config.minRXTXTIME + koffset; int num_beams = nr_mac->beam_info.beam_allocation ? nr_mac->beam_info.beams_per_period : 1; int bw = scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth; int average_agg_level = 4; // TODO find a better estimation - int max_sched_ues = bw / (average_agg_level * NR_NB_REG_PER_CCE); + int max_dci = bw / (average_agg_level * NR_NB_REG_PER_CCE); // FAPI cannot handle more than MAX_DCI_CORESET DCIs - max_sched_ues = min(max_sched_ues, MAX_DCI_CORESET); + max_dci = min(max_dci, MAX_DCI_CORESET); - const NR_tda_info_t *tda_info = NULL; - int n_tda = get_num_ul_tda(nr_mac, sched_frame, sched_slot, nr_mac->radio_config.minRXTXTIME, &tda_info); - DevAssert(n_tda == 1); - int tda = seq_arr_dist(&nr_mac->ul_tda, seq_arr_front(&nr_mac->ul_tda), tda_info); - AssertFatal(tda >= 0 && tda < 16, "illegal TDA index %d\n", tda); - /* TODO: iterate over all available UL slots if there are more than DL */ - /* the following supposes that the TDA is the same across all BWPs */ + fsn_t current = {frame, slot}; + fsn_t min_next = fs_add_delta(fs, min_rxtx, current); + /* if it's the last DL slot, we should try all TDAs to make sure that the + * scheduler can reach e.g. the next mixed slot. Otherwise, if we don't, we + * might starve HARQ processes that need a retransmission in a specific slot + * but we might not necessarily reach it */ + bool last_dl = (current.s % fs->numb_slots_period) == (fs->period_cfg.num_dl_slots - 1); + fsn_t *next = &nr_mac->ul_next; + while (max_dci > 0) { + /* go to the next UL slot, skipping DL if necessary */ + *next = fs_get_max(fs, *next, min_next); + while (!is_ul_slot(next->s, fs)) + *next = fs_add_delta(fs, 1, *next); + if (!is_dl_slot(current.s, fs)) // if current slot is not DL, nothing to do + break; - int len[num_beams]; - for (int i = 0; i < num_beams; i++) - len[i] = bw; - /* proportional fair scheduling algorithm */ - pf_ul(nr_mac, pp_pusch, tda, tda_info, nr_mac->UE_info.connected_ue_list, max_sched_ues, num_beams, len); + /* get a TDA so that next UL scheduling slot can be reached from current, + * and exit if there is no such TDA. Remove koffset, as it is + * "cell-specific", i.e., the UE will add it on the computation. */ + int k2 = fs_get_diff(fs, *next, current) - koffset; + DevAssert(k2 > 0); + const NR_tda_info_t *tda_info = NULL; + int n_tda = get_num_ul_tda(nr_mac, next->f, next->s, k2, &tda_info); + if (n_tda == 0) /* no TDA fulfills this */ + break; + /* TODO: get_num_ul_tda() might indicate multiple TDAs to use (e.g., one + * handling SRS), this will be fixed in a follow-up commit. */ + DevAssert(tda_info->valid_tda); + int tda = seq_arr_dist(&nr_mac->ul_tda, seq_arr_front(&nr_mac->ul_tda), tda_info); + AssertFatal(tda >= 0 && tda < 16, "illegal TDA index %d\n", tda); + + int len[num_beams]; + for (int i = 0; i < num_beams; i++) + len[i] = bw; + /* proportional fair scheduling algorithm */ + int sched = pf_ul(nr_mac, pp_pusch, tda, tda_info, nr_mac->UE_info.connected_ue_list, max_dci, num_beams, len); + LOG_D(NR_MAC, "run pf_ul() at %4d.%2d with tda %d k2 %d (ULSCH at %4d.%2d) scheduled %d last_dl %d\n", frame, slot, tda, k2, next->f, next->s, sched, last_dl); + /* if we did not schedule anything, and it's not the last slot, break. In + * the case we did schedule or it's the last slot (see above!), continue + * advancing till there is no TDA anymore */ + if (sched == 0 && !last_dl) + break; + max_dci -= sched; + + *next = fs_add_delta(fs, 1, *next); + } } nr_pp_impl_ul nr_init_ulsch_preprocessor(int CC_id) @@ -2620,11 +2674,5 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, slot_t slot, nfapi_ ul_dci_req->Slot = slot; post_process_pusch_t pusch = { .frame = frame, .slot = slot, .ul_dci_req = ul_dci_req, .pdcch_pdu_coreset = {NULL}, }; - /* Uplink data ONLY can be scheduled when the current slot is downlink slot, - * because we have to schedule the DCI0 first before schedule uplink data */ - if (!is_dl_slot(slot, &nr_mac->frame_structure)) { - LOG_D(NR_MAC, "Current slot %d is NOT DL slot, cannot schedule DCI0 for UL data\n", slot); - return; - } nr_mac->pre_processor_ul(nr_mac, &pusch); } diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 9dcddcef4d..aea5724056 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -828,6 +828,14 @@ typedef struct { uint64_t used_prb_aggregate; } mac_stats_t; +/// helper type to encapsulate a frame/slot combination in a single type. +/// Currently only used in the UL preprocessor. Note: if you use this type +/// further, please refactor it into a common type first. +typedef struct fsn { + frame_t f; + slot_t s; +} fsn_t; + /*! \brief top level eNB MAC structure */ typedef struct gNB_MAC_INST_s { /// Ethernet parameters for northbound midhaul interface @@ -932,6 +940,8 @@ typedef struct gNB_MAC_INST_s { /// dedicate UL TDA, common for all UEs seq_arr_t ul_tda; + /// next UL slot to schedule + fsn_t ul_next; nr_mac_rrc_ul_if_t mac_rrc; f1_config_t f1_config; From cf8099fab19c242996bc32bf0f551d943429245b Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 23 Jul 2025 10:50:45 +0200 Subject: [PATCH 452/964] Refactor TDA allocation: scheduler can take advantage of multiple k2 Add multiple TDAs with k2 larger than the min_rxtxtime, to potentially allow to allocate all available slots. For this, nr_rrc_config_ul_tda() inspects the TDD pattern, and allocates as many TDAs as necessary. It also sorts the TDA list, with smaller k2 and larger symbol lengths first. This in turn is now used by get_num_ul_tda() to use a k2 and the slot configuration to find a suitable TDA, assuming a list as sorted in nr_rrc_config_ul_tda(). Note that since get_num_ul_tda() does only inspect the available UL slots, there might be overlap (e.g., when scheduling SRS), which will be fixed in a follow-up commit. Also, TDD pattern 2 is not handled here yet, and a follow-up commit will fix it. --- .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 71 +++++++++++-------- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 2 +- openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c | 55 +++++++++++++- 3 files changed, 96 insertions(+), 32 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 93db0d1945..4f55f73db1 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -38,45 +38,58 @@ //#define SRS_IND_DEBUG -/* \brief Get the number of UL TDAs that could be used in frame and slot, reachable +/* \brief Get the number of UL TDAs that could be used in slot, reachable * via specific k2. The output parameter first_idx is a pointer to the first * suitable TDA, and the function returns the number of suitable TDAs, or 0. */ -int get_num_ul_tda(gNB_MAC_INST *nrmac, int frame, int slot, int k2, const NR_tda_info_t **first_idx) +int get_num_ul_tda(gNB_MAC_INST *nrmac, int slot, int k2, const NR_tda_info_t **first_idx) { /* we assume that this function is mutex-protected from outside */ NR_SCHED_ENSURE_LOCKED(&nrmac->sched_lock); - /* there is a mixed slot only when in TDD */ - frame_structure_t *fs = &nrmac->frame_structure; + const frame_structure_t *fs = &nrmac->frame_structure; + const int slot_period = slot % fs->numb_slots_period; + const tdd_bitmap_t *bm = &fs->period_cfg.tdd_slot_bitmap[slot_period]; + /* For some reason, we only store the number of symbols if it's mixed */ + const int num_ul_symbols = bm->slot_type == TDD_NR_MIXED_SLOT ? bm->num_ul_symbols : 14; + const uint16_t ul_bitmap = SL_to_bitmap(14 - num_ul_symbols, num_ul_symbols); - /* TODO: we assume currently that all UL TDA have same k2, check below */ - NR_tda_info_t *tda_info = seq_arr_at(&nrmac->ul_tda, 0); - if (!tda_info->valid_tda || tda_info->k2 != k2) + *first_idx = NULL; + FOR_EACH_SEQ_ARR(NR_tda_info_t *, tda, &nrmac->ul_tda) { + DevAssert(tda->valid_tda); + // nr_rrc_config_ul_tda() orders by k2, so skip smaller and return for + // bigger ones + if (tda->k2 < k2) + continue; + if (tda->k2 > k2) + break; // there won't be a suitable k2 anymore + + uint16_t tda_bitmap = SL_to_bitmap(tda->startSymbolIndex, tda->nrOfSymbols); + // nr_rrc_config_ul_tda() assures TDAs are from largest to smallest symbol number. + // check that this TDA fits entirely into this slot's mask (slot might be + // smaller in mixed slots)., A mixed slot TDA would be checked last, so a + // full slot TDA will be used for a full UL slot. + if ((tda_bitmap & ul_bitmap) == tda_bitmap) { // if TDA fits entiry + *first_idx = tda; + break; + } + } + if (*first_idx == NULL) /* nothing fit */ return 0; - if (fs->frame_type == TDD) { - // if there is uplink symbols in mixed slot - int s = get_slot_idx_in_period(slot, fs); - tdd_bitmap_t *tdd_slot_bitmap = fs->period_cfg.tdd_slot_bitmap; - if ((tdd_slot_bitmap[s].num_ul_symbols > 1) && is_mixed_slot(s, fs)) { - *first_idx = seq_arr_at(&nrmac->ul_tda, 2); // mixed slot, all symbols of mixed minus last - return 1; - } + NR_tda_info_t *end_it = seq_arr_next(&nrmac->ul_tda, *first_idx); + while (end_it != seq_arr_end(&nrmac->ul_tda) && end_it->k2 == k2) { + /* the following TDAs should all fit as long as the k2 is the same */ + uint16_t tda_bitmap = SL_to_bitmap(end_it->startSymbolIndex, end_it->nrOfSymbols); + AssertFatal((tda_bitmap & ul_bitmap) == tda_bitmap, + "TDA should fit inside slot, but is not the case for k2 %ld bitmap 0x%04x\n", + end_it->k2, + tda_bitmap); + end_it = seq_arr_next(&nrmac->ul_tda, end_it); } - // Avoid slots with the SRS - UE_iterator(nrmac->UE_info.connected_ue_list, UE) { - NR_sched_srs_t sched_srs = UE->UE_sched_ctrl.sched_srs; - if(sched_srs.srs_scheduled && sched_srs.frame == frame && sched_srs.slot == slot) { - *first_idx = seq_arr_at(&nrmac->ul_tda, 1); // symbols 0--12 - return 1; - } - } - - // symbols 0--13, if FDD or not mixed slot in TDD, for now use default TDA - // (TODO handle CSI-RS slots) - *first_idx = seq_arr_at(&nrmac->ul_tda, 0); - return 1; + ptrdiff_t diff = seq_arr_dist(&nrmac->ul_tda, *first_idx, end_it); + AssertFatal(diff > 0 && diff <= seq_arr_size(&nrmac->ul_tda), "dist %ld\n", diff); + return diff; } bwp_info_t get_pusch_bwp_start_size(NR_UE_info_t *UE) @@ -2607,7 +2620,7 @@ static void nr_ulsch_preprocessor(gNB_MAC_INST *nr_mac, post_process_pusch_t *pp int k2 = fs_get_diff(fs, *next, current) - koffset; DevAssert(k2 > 0); const NR_tda_info_t *tda_info = NULL; - int n_tda = get_num_ul_tda(nr_mac, next->f, next->s, k2, &tda_info); + int n_tda = get_num_ul_tda(nr_mac, next->s, k2, &tda_info); if (n_tda == 0) /* no TDA fulfills this */ break; /* TODO: get_num_ul_tda() might indicate multiple TDAs to use (e.g., one diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 91c0969dde..9caa78bf7e 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -417,7 +417,7 @@ void free_sched_pucch_list(NR_UE_sched_ctrl_t *sched_ctrl); bool add_UE_to_list(int list_size, NR_UE_info_t *list[list_size], NR_UE_info_t *UE); NR_UE_info_t *remove_UE_from_list(int list_size, NR_UE_info_t *list[list_size], rnti_t rnti); int get_dl_tda(const gNB_MAC_INST *nrmac, int slot); -int get_num_ul_tda(gNB_MAC_INST *nrmac, int frame, int slot, int k2, const NR_tda_info_t **first_idx); +int get_num_ul_tda(gNB_MAC_INST *nrmac, int slot, int k2, const NR_tda_info_t **first_idx); int get_cce_index(const gNB_MAC_INST *nrmac, const int CC_id, diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c index d780cf4fe7..22d3b55fa4 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c @@ -1058,6 +1058,29 @@ static struct NR_PUSCH_TimeDomainResourceAllocation *set_TimeDomainResourceAlloc return puschTdrAlloc; } +static int tda_cmp(const void *tda_a, const void *tda_b) +{ + const NR_PUSCH_TimeDomainResourceAllocation_t *a = *(const NR_PUSCH_TimeDomainResourceAllocation_t **)tda_a; + const NR_PUSCH_TimeDomainResourceAllocation_t *b = *(const NR_PUSCH_TimeDomainResourceAllocation_t **)tda_b; + DevAssert(a->k2 && b->k2); + if (*a->k2 < *b->k2) + return -1; // smaller first + if (*a->k2 > *b->k2) + return 1; + // same k2: order from big to small TDA number + int as, al, bs, bl; + SLIV2SL(a->startSymbolAndLength, &as, &al); + SLIV2SL(b->startSymbolAndLength, &bs, &bl); + if (al < bl) + return 1; // bigger first + if (al > bl) + return -1; + return 0; +} + +/* \brief Set up a list of time domain allocations as suitable for the TDD + * pattern. This will be used by get_num_ul_tda(), which requires a specific + * ordering, hence we qsort() the list at the end according to tda_cmp(). */ void nr_rrc_config_ul_tda(NR_ServingCellConfigCommon_t *scc, int min_fb_delay) { NR_PUSCH_TimeDomainResourceAllocationList_t *tda_list = @@ -1065,6 +1088,7 @@ void nr_rrc_config_ul_tda(NR_ServingCellConfigCommon_t *scc, int min_fb_delay) AssertFatal(tda_list->list.count == 0, "already have pusch_TimeDomainAllocationList members\n"); const int k2 = min_fb_delay; + const int mu = scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing; // UL TDA index 0 is basic slot configuration starting in symbol 0 til the last but one symbol NR_PUSCH_TimeDomainResourceAllocation_t *tda; @@ -1089,13 +1113,40 @@ void nr_rrc_config_ul_tda(NR_ServingCellConfigCommon_t *scc, int min_fb_delay) } else if (p2) { ul_symb = p1->nrofUplinkSymbols; } - if (ul_symb>1) { + + DevAssert(p2 == NULL); + int N_dl = p1->nrofDownlinkSlots; + int N_ul = p1->nrofUplinkSlots; + int tdd_period_idx = get_tdd_period_idx(scc->tdd_UL_DL_ConfigurationCommon); + int nb_periods_per_frame = get_nb_periods_per_frame(tdd_period_idx); + int nb_slots_per_period = ((1 << mu) * 10) / nb_periods_per_frame; + + // make TDA for the mixed slot + if (ul_symb > 1 && k2 <= N_dl) { // UL TDA index 2 for mixed slot (TDD) long sliv = get_SLIV(NR_NUMBER_OF_SYMBOLS_PER_SLOT - ul_symb, ul_symb - 1); - tda = set_TimeDomainResourceAllocation(k2, sliv); + tda = set_TimeDomainResourceAllocation(k2, sliv); // to be reached from suitable DL slot + asn1cSeqAdd(&tda_list->list, tda); + } else if (ul_symb > 1) { // k2 > N_Dl + long sliv = get_SLIV(NR_NUMBER_OF_SYMBOLS_PER_SLOT - ul_symb, ul_symb - 1); + tda = set_TimeDomainResourceAllocation(nb_slots_per_period, sliv); // to be reached from last DL (mixed) slot, if any asn1cSeqAdd(&tda_list->list, tda); } + + // make TDA for UL slots that are not reachable within k2/min_rxtxtime + if (N_ul > k2) { + // enforce that with k2, we could reach all but one slot (which is mixed + // and taken into account above + AssertFatal(N_dl >= k2 - 1, "cannot fulfil TDD pattern: N_dl %d, k2 %d\n", N_dl, k2); + for (int i = k2 + 1; i <= N_ul; ++i) { + tda = set_TimeDomainResourceAllocation(i, get_SLIV(0, 13)); + asn1cSeqAdd(&tda_list->list, tda); + } + } } + + AssertFatal(tda_list->list.count <= 16, "cannot reach all UL slots with current TDD configuration\n"); + qsort(tda_list->list.array, tda_list->list.count, sizeof(tda_list->list.array), tda_cmp); } static void set_dl_DataToUL_ACK(NR_PUCCH_Config_t *pucch_Config, int min_feedback_time, NR_SubcarrierSpacing_t subcarrierSpacing) From 6ef8dadd886e5ce6874e71dad1acf2718fe2c547 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 4 Aug 2025 11:23:36 +0200 Subject: [PATCH 453/964] Only add SRS TDA if SRS is activated Since the parent commit, the TDA for UL scheduling is dynamically selected, instead of being hardcoded to specific indices. We can thus also omit the SRS TDA if no SRS is configured. Also add SRS-specific TDAs if we schedule further into the future. --- openair2/GNB_APP/gnb_config.c | 6 +++--- openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c | 12 +++++++++--- openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h | 2 +- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 8f162ff1ce..57086db62a 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -1165,7 +1165,7 @@ bool is_pattern2_config(paramdef_t *param) return true; } -static NR_ServingCellConfigCommon_t *get_scc_config(configmodule_interface_t *cfg, int minRXTXTIME) +static NR_ServingCellConfigCommon_t *get_scc_config(configmodule_interface_t *cfg, int minRXTXTIME, int do_SRS) { NR_ServingCellConfigCommon_t *scc = calloc_or_fail(1, sizeof(*scc)); uint64_t ssb_bitmap=0xff; @@ -1231,7 +1231,7 @@ static NR_ServingCellConfigCommon_t *get_scc_config(configmodule_interface_t *cf check_ssb_raster(ssb_freq, *frequencyInfoDL->frequencyBandList.list.array[0], *scc->ssbSubcarrierSpacing); fix_scc(scc, ssb_bitmap); } - nr_rrc_config_ul_tda(scc, minRXTXTIME); + nr_rrc_config_ul_tda(scc, minRXTXTIME, do_SRS); // the gNB uses the servingCellConfigCommon everywhere, even when it should use the servingCellConfigCommonSIB. // previously (before this commit), the following fields were indirectly populated through get_SIB1_NR(). @@ -1695,7 +1695,7 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg) config.num_agg_level_candidates[PDCCH_AGG_LEVEL8], config.num_agg_level_candidates[PDCCH_AGG_LEVEL16]); - NR_ServingCellConfigCommon_t *scc = get_scc_config(cfg, config.minRXTXTIME); + NR_ServingCellConfigCommon_t *scc = get_scc_config(cfg, config.minRXTXTIME, config.do_SRS); //xer_fprint(stdout, &asn_DEF_NR_ServingCellConfigCommon, scc); NR_ServingCellConfig_t *scd = get_scd_config(cfg); diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c index 22d3b55fa4..2203c0b2b7 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c @@ -1081,7 +1081,7 @@ static int tda_cmp(const void *tda_a, const void *tda_b) /* \brief Set up a list of time domain allocations as suitable for the TDD * pattern. This will be used by get_num_ul_tda(), which requires a specific * ordering, hence we qsort() the list at the end according to tda_cmp(). */ -void nr_rrc_config_ul_tda(NR_ServingCellConfigCommon_t *scc, int min_fb_delay) +void nr_rrc_config_ul_tda(NR_ServingCellConfigCommon_t *scc, int min_fb_delay, int do_SRS) { NR_PUSCH_TimeDomainResourceAllocationList_t *tda_list = scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList; @@ -1096,8 +1096,10 @@ void nr_rrc_config_ul_tda(NR_ServingCellConfigCommon_t *scc, int min_fb_delay) asn1cSeqAdd(&tda_list->list, tda); // UL TDA index 1 in case of SRS - tda = set_TimeDomainResourceAllocation(k2, get_SLIV(0, 12)); - asn1cSeqAdd(&tda_list->list, tda); + if (do_SRS) { + tda = set_TimeDomainResourceAllocation(k2, get_SLIV(0, 12)); + asn1cSeqAdd(&tda_list->list, tda); + } if (scc->tdd_UL_DL_ConfigurationCommon) { int ul_symb = 0; @@ -1141,6 +1143,10 @@ void nr_rrc_config_ul_tda(NR_ServingCellConfigCommon_t *scc, int min_fb_delay) for (int i = k2 + 1; i <= N_ul; ++i) { tda = set_TimeDomainResourceAllocation(i, get_SLIV(0, 13)); asn1cSeqAdd(&tda_list->list, tda); + if (do_SRS) { + tda = set_TimeDomainResourceAllocation(k2, get_SLIV(0, 12)); + asn1cSeqAdd(&tda_list->list, tda); + } } } } diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h index 51c30c38b6..28993e13cf 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h @@ -51,7 +51,7 @@ void nr_rrc_config_dl_tda(struct NR_PDSCH_TimeDomainResourceAllocationList *pdsc frame_type_t frame_type, NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon, int curr_bwp); -void nr_rrc_config_ul_tda(NR_ServingCellConfigCommon_t *scc, int min_fb_delay); +void nr_rrc_config_ul_tda(NR_ServingCellConfigCommon_t *scc, int min_fb_delay, int do_SRS); NR_SearchSpace_t *rrc_searchspace_config(bool is_common, int searchspaceid, int coresetid, From 98cc36430b80d43ba5e1f9d1c9531aed939fb745 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 15 Jul 2025 19:02:28 +0200 Subject: [PATCH 454/964] Schedule SRS longer in advance, cleanup Schedule SRS longer in advance, so that it would also be enough even with big k2 for UL TDA. Remove useless types: we do not use the information on sched_srs anymore, so remove it. Check that the VRB map is free before making allocations. --- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 2 - .../LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c | 46 ++++++------------- .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 19 -------- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 5 -- openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 9 ---- 5 files changed, 14 insertions(+), 67 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index a6de5b987d..8a739e4bc1 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -2766,8 +2766,6 @@ bool add_connected_nr_ue(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE) NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; sched_ctrl->dl_max_mcs = 28; /* do not limit MCS for individual UEs */ - sched_ctrl->sched_srs.frame = -1; - sched_ctrl->sched_srs.slot = -1; sched_ctrl->pdcch_cl_adjust = 0; reset_srs_stats(UE); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c index c3ebb5ab9b..a93b0cb051 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c @@ -471,9 +471,13 @@ static void nr_configure_srs(gNB_MAC_INST *nrmac, NR_beam_alloc_t beam = beam_allocation_procedure(&nrmac->beam_info, frame, slot, UE->UE_beam_index, slots_per_frame); AssertFatal(beam.idx >= 0, "Cannot allocate SRS in any available beam\n"); uint16_t *vrb_map_UL = &nrmac->common_channels[CC_id].vrb_map_UL[beam.idx][buffer_index * MAX_BWP_SIZE]; - uint64_t mask = SL_to_bitmap(srs_pdu->time_start_position, srs_pdu->num_symbols); - for (int i = 0; i < srs_pdu->bwp_size; ++i) - vrb_map_UL[i + srs_pdu->bwp_start] |= mask; + uint16_t mask = SL_to_bitmap(srs_pdu->time_start_position, srs_pdu->num_symbols); + for (int i = 0; i < srs_pdu->bwp_size; ++i) { + int rb = i + srs_pdu->bwp_start; + uint16_t alloc = vrb_map_UL[rb] & mask; + AssertFatal(nrmac->ulprbbl[rb] != 0 || alloc == 0, "RB %d not free for SRS: alloc 0x%02x for mask 0x%02x\n", rb, alloc, mask); + vrb_map_UL[rb] |= mask; + } } static void nr_fill_nfapi_srs(gNB_MAC_INST *nrmac, @@ -512,9 +516,7 @@ static void nr_fill_nfapi_srs(gNB_MAC_INST *nrmac, *********************************************************************/ void nr_schedule_srs(int module_id, frame_t frame, int slot) { - const int CC_id = 0; gNB_MAC_INST *nrmac = RC.nrmac[module_id]; - const NR_ServingCellConfigCommon_t *scc = nrmac->common_channels[CC_id].ServingCellConfigCommon; /* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */ NR_SCHED_ENSURE_LOCKED(&nrmac->sched_lock); @@ -526,12 +528,6 @@ void nr_schedule_srs(int module_id, frame_t frame, int slot) NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; NR_UE_UL_BWP_t *current_BWP = &UE->current_UL_BWP; - if(sched_ctrl->sched_srs.srs_scheduled && sched_ctrl->sched_srs.frame == frame && sched_ctrl->sched_srs.slot == slot) { - sched_ctrl->sched_srs.frame = -1; - sched_ctrl->sched_srs.slot = -1; - sched_ctrl->sched_srs.srs_scheduled = false; - } - if ((sched_ctrl->ul_failure && !get_softmodem_params()->phy_test) || nr_timer_is_active(&sched_ctrl->transm_interrupt)) { continue; } @@ -566,34 +562,20 @@ void nr_schedule_srs(int module_id, frame_t frame, int slot) continue; } - NR_PUSCH_TimeDomainResourceAllocationList_t *tdaList = get_ul_tdalist(current_BWP, - sched_ctrl->coreset->controlResourceSetId, - sched_ctrl->search_space->searchSpaceType->present, - TYPE_C_RNTI_); - const int num_tda = tdaList->list.count; - int max_k2 = 0; - // avoid last one in the list (for msg3) - for (int i = 0; i < num_tda - 1; i++) { - int k2 = get_K2(tdaList, i, current_BWP->scs, scc); - max_k2 = k2 > max_k2 ? k2 : max_k2; - } - // we are sheduling SRS max_k2 slot in advance for the presence of SRS to be taken into account when scheduling PUSCH const int n_slots_frame = nrmac->frame_structure.numb_slots_frame; - const int sched_slot = (slot + max_k2) % n_slots_frame; - const int sched_frame = (frame + (slot + max_k2) / n_slots_frame) % MAX_FRAME_NUMBER; + const int n_ahead = n_slots_frame - 1 + get_NTN_Koffset(nrmac->common_channels[0].ServingCellConfigCommon); + const int sched_slot = (slot + n_ahead) % n_slots_frame; + const int sched_frame = (frame + (slot + n_ahead) / n_slots_frame) % MAX_FRAME_NUMBER; const uint16_t period = srs_period[srs_resource->resourceType.choice.periodic->periodicityAndOffset_p.present]; const uint16_t offset = get_nr_srs_offset(srs_resource->resourceType.choice.periodic->periodicityAndOffset_p); // Check if UE will transmit the SRS in this frame - if ((sched_frame * n_slots_frame + sched_slot - offset) % period == 0) { - LOG_D(NR_MAC," %d.%d Scheduling SRS reception for %d.%d\n", frame, slot, sched_frame, sched_slot); - nr_fill_nfapi_srs(nrmac, CC_id, UE, sched_frame, sched_slot, srs_resource_set, srs_resource); - sched_ctrl->sched_srs.frame = sched_frame; - sched_ctrl->sched_srs.slot = sched_slot; - sched_ctrl->sched_srs.srs_scheduled = true; - } + if ((sched_frame * n_slots_frame + sched_slot - offset) % period != 0) + continue; + LOG_D(NR_MAC," %d.%d Scheduling SRS reception for %d.%d\n", frame, slot, sched_frame, sched_slot); + nr_fill_nfapi_srs(nrmac, CC_id, UE, sched_frame, sched_slot, srs_resource_set, srs_resource); } } } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 4f55f73db1..da6eab799c 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -1585,25 +1585,6 @@ void handle_nr_srs_measurements(const module_id_t module_id, NR_SCHED_UNLOCK(&nrmac->sched_lock); } -long get_K2(NR_PUSCH_TimeDomainResourceAllocationList_t *tdaList, - int time_domain_assignment, - int mu, - const NR_ServingCellConfigCommon_t *scc) -{ - /* we assume that this function is mutex-protected from outside */ - NR_PUSCH_TimeDomainResourceAllocation_t *tda = tdaList->list.array[time_domain_assignment]; - const int NTN_gNB_Koffset = get_NTN_Koffset(scc); - - if (tda->k2) - return *tda->k2 + NTN_gNB_Koffset; - else if (mu < 2) - return 1 + NTN_gNB_Koffset; - else if (mu == 2) - return 2 + NTN_gNB_Koffset; - else - return 3 + NTN_gNB_Koffset; -} - static bool nr_UE_is_to_be_scheduled(const frame_structure_t *fs, NR_UE_info_t *UE, frame_t frame, diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 9caa78bf7e..4cd3a6dd7e 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -286,11 +286,6 @@ NR_ControlResourceSet_t *get_coreset(gNB_MAC_INST *nrmac, NR_BWP_DownlinkDedicated_t *bwp_dedicated, NR_ControlResourceSetId_t coreset_id); -long get_K2(NR_PUSCH_TimeDomainResourceAllocationList_t *tdaList, - int time_domain_assignment, - int mu, - const NR_ServingCellConfigCommon_t *scc); - const NR_DMRS_UplinkConfig_t *get_DMRS_UplinkConfig(const NR_PUSCH_Config_t *pusch_Config, const NR_tda_info_t *tda_info); NR_pusch_dmrs_t get_ul_dmrs_params(const NR_ServingCellConfigCommon_t *scc, diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index aea5724056..a4e50bc7cb 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -429,12 +429,6 @@ typedef struct NR_sched_pusch { int phr_txpower_calc; } NR_sched_pusch_t; -typedef struct NR_sched_srs { - int frame; - int slot; - bool srs_scheduled; -} NR_sched_srs_t; - typedef struct NR_pdsch_dmrs { uint8_t dmrs_ports_id; uint8_t N_PRB_DMRS; @@ -599,9 +593,6 @@ typedef struct { NR_sched_pucch_t *sched_pucch; int sched_pucch_size; - /// Sched SRS: scheduling decisions - NR_sched_srs_t sched_srs; - /// uplink bytes that are currently scheduled int sched_ul_bytes; /// estimation of the UL buffer size From 71e01bbaa975edc916eef351c2db0c8d1672f95f Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 18 Jul 2025 16:41:44 +0200 Subject: [PATCH 455/964] Correctly interpret SRS numberOfSymbols A length of 0 is to be interpreted as 1 symbol, a length of 1 is 2, etc. --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c index a93b0cb051..d9e656dec9 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c @@ -471,7 +471,9 @@ static void nr_configure_srs(gNB_MAC_INST *nrmac, NR_beam_alloc_t beam = beam_allocation_procedure(&nrmac->beam_info, frame, slot, UE->UE_beam_index, slots_per_frame); AssertFatal(beam.idx >= 0, "Cannot allocate SRS in any available beam\n"); uint16_t *vrb_map_UL = &nrmac->common_channels[CC_id].vrb_map_UL[beam.idx][buffer_index * MAX_BWP_SIZE]; - uint16_t mask = SL_to_bitmap(srs_pdu->time_start_position, srs_pdu->num_symbols); + uint16_t num = 1 << srs_pdu->num_symbols; // 0,1,2 means 1,2,4 symbols, see 222.10.04 table 3-105 + uint16_t mask = SL_to_bitmap(srs_pdu->time_start_position, num); + DevAssert(mask != 0); for (int i = 0; i < srs_pdu->bwp_size; ++i) { int rb = i + srs_pdu->bwp_start; uint16_t alloc = vrb_map_UL[rb] & mask; From 6981783ee188cc3517f6d004f4f66954118ec56f Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 7 Aug 2025 12:44:21 +0200 Subject: [PATCH 456/964] Select best out of multiple TDAs A new function get_best_ul_tda() allows to select the "best" TDA out of a number of TDA. Specifically, get_best_ul_tda() considers in how many RBs a given TDA might be allocated, and multiplies this number of RBs with the number of symbols in the TDA to form a "score". The TDA with the best "score" is selected, considering it maximizes resource usage. In phytest scheduler, we use this function to verify that the given TDA can be really allocated in all selected slots. --- .../LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c | 7 ++ .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 72 ++++++++++++++++++- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 8 +++ 3 files changed, 84 insertions(+), 3 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c index 00872ade89..26b48ab998 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c @@ -262,6 +262,13 @@ void nr_ul_preprocessor_phytest(gNB_MAC_INST *nr_mac, post_process_pusch_t *pp_p // TODO implement beam procedures for phy-test mode int beam = 0; + const NR_tda_info_t *tda_p; + const int n_tda = get_num_ul_tda(nr_mac, sched_slot, tda_info.k2, &tda_p); + DevAssert(n_tda > 0); + /* check only the first TDA: we are only interested in finding out if this TDA fits completely */ + int rb_s = rbStart, rb_l = rbSize; + get_best_ul_tda(nr_mac, beam, tda_p, 1, sched_frame, sched_slot, &rb_s, &rb_l); + DevAssert(rb_s == rbStart && rb_l == rbSize); const int buffer_index = ul_buffer_index(sched_frame, sched_slot, slots_frame, nr_mac->vrb_map_UL_size); uint16_t *vrb_map_UL = &nr_mac->common_channels[CC_id].vrb_map_UL[beam][buffer_index * MAX_BWP_SIZE]; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index da6eab799c..33a0ad650e 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -92,6 +92,65 @@ int get_num_ul_tda(gNB_MAC_INST *nrmac, int slot, int k2, const NR_tda_info_t ** return diff; } +static void get_max_rb_range(const uint16_t *vrb_map_ul, const uint16_t *ulprbbl, uint16_t mask, int *rb_start, int *rb_len) +{ + int best_start = *rb_start; + int best_len = 0; + int current_start = *rb_start; + int current_len = 0; + for (int rb = *rb_start; rb < *rb_len; ++rb) { + if (ulprbbl[rb] == 0 && (mask & vrb_map_ul[rb]) == 0) { + current_len++; + continue; + } + + /* this RB is blocked for UL, or already in use */ + if (current_len > best_len) { + best_start = current_start; + best_len = current_len; + } + current_start = rb + 1; /* will start in next RB, or updated later */ + current_len = 0; + } + if (current_len > best_len) { + best_start = current_start; + best_len = current_len; + } + *rb_start = best_start; + *rb_len = best_len; +} + +const NR_tda_info_t *get_best_ul_tda(const gNB_MAC_INST *nrmac, int beam, const NR_tda_info_t *tdas, int n_tda, int frame, int slot, int *rb_start, int *rb_len) +{ + /* there is a mixed slot only when in TDD */ + const frame_structure_t *fs = &nrmac->frame_structure; + const int index = ul_buffer_index(frame, slot, fs->numb_slots_frame, nrmac->vrb_map_UL_size); + uint16_t *vrb_map_UL = &nrmac->common_channels[0].vrb_map_UL[beam][index * MAX_BWP_SIZE]; + + DevAssert(n_tda <= 16); + const NR_tda_info_t *best_tda = tdas; + uint64_t score = 0; + int check_rb_start = *rb_start; + int check_rb_len = *rb_len; + + for (int i = 0; i < n_tda; ++i, tdas++) { + int start = check_rb_start; + int len = check_rb_len; + uint16_t tda_mask = SL_to_bitmap(tdas->startSymbolIndex, tdas->nrOfSymbols); + get_max_rb_range(vrb_map_UL, nrmac->ulprbbl, tda_mask, &start, &len); + uint64_t s = (uint64_t)tdas->nrOfSymbols * len; + if (s > score) { + best_tda = tdas; + score = s; + *rb_start = start; + *rb_len = len; + } + LOG_D(NR_MAC, "%4d.%2d tda k2 %ld mask 0x%04x has PRB start/len %d/%d score %ld\n", frame, slot, tdas->k2, tda_mask, start, len, s); + } + + return best_tda; +} + bwp_info_t get_pusch_bwp_start_size(NR_UE_info_t *UE) { NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP; @@ -2600,19 +2659,26 @@ static void nr_ulsch_preprocessor(gNB_MAC_INST *nr_mac, post_process_pusch_t *pp * "cell-specific", i.e., the UE will add it on the computation. */ int k2 = fs_get_diff(fs, *next, current) - koffset; DevAssert(k2 > 0); + // we assume that all beams have the same symbol utilization in all RBs for + // simplification (but this might not be true). Otherwise, we would need to + // check it separately for all beams and give a list of TDAs (one for each + // beam) in pf_ul(), which is complex. We should rewrite pf_ul() to + // schedule for one beam only instead (and for one BWP). + int beam = 0; const NR_tda_info_t *tda_info = NULL; int n_tda = get_num_ul_tda(nr_mac, next->s, k2, &tda_info); if (n_tda == 0) /* no TDA fulfills this */ break; - /* TODO: get_num_ul_tda() might indicate multiple TDAs to use (e.g., one - * handling SRS), this will be fixed in a follow-up commit. */ + int rb_start = 0; + int rb_len = bw; + tda_info = get_best_ul_tda(nr_mac, beam, tda_info, n_tda, next->f, next->s, &rb_start, &rb_len); DevAssert(tda_info->valid_tda); int tda = seq_arr_dist(&nr_mac->ul_tda, seq_arr_front(&nr_mac->ul_tda), tda_info); AssertFatal(tda >= 0 && tda < 16, "illegal TDA index %d\n", tda); int len[num_beams]; for (int i = 0; i < num_beams; i++) - len[i] = bw; + len[i] = rb_len; /* proportional fair scheduling algorithm */ int sched = pf_ul(nr_mac, pp_pusch, tda, tda_info, nr_mac->UE_info.connected_ue_list, max_dci, num_beams, len); LOG_D(NR_MAC, "run pf_ul() at %4d.%2d with tda %d k2 %d (ULSCH at %4d.%2d) scheduled %d last_dl %d\n", frame, slot, tda, k2, next->f, next->s, sched, last_dl); diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 4cd3a6dd7e..584b294806 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -413,6 +413,14 @@ bool add_UE_to_list(int list_size, NR_UE_info_t *list[list_size], NR_UE_info_t * NR_UE_info_t *remove_UE_from_list(int list_size, NR_UE_info_t *list[list_size], rnti_t rnti); int get_dl_tda(const gNB_MAC_INST *nrmac, int slot); int get_num_ul_tda(gNB_MAC_INST *nrmac, int slot, int k2, const NR_tda_info_t **first_idx); +const NR_tda_info_t *get_best_ul_tda(const gNB_MAC_INST *nrmac, + int beam, + const NR_tda_info_t *tdas, + int n_tda, + int frame, + int slot, + int *rb_start, + int *rb_len); int get_cce_index(const gNB_MAC_INST *nrmac, const int CC_id, From 135525c17a7cd39f5ba6c582b474d537b464bde7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Soares=20Silva?= Date: Wed, 9 Jul 2025 07:11:25 +0200 Subject: [PATCH 457/964] P5 Config: Pack/Unpack TDD table with 10.02 and 10.04 formats Adds the capability to pack/unpack the TDD table in CONFIG.request following both SCF222.10.02 (Tag 0x1027) and SCF222.10.04 (Tag 0x1035) formats In the case of Aerial, the TDD table is packed following the 10.04 format, but with the 10.02 tag Prevent the packing of Digital Beamforming table and Precoding Matrix table for Aerial --- nfapi/open-nFAPI/fapi/CMakeLists.txt | 4 +- nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c | 139 ++++++++++++++++-- .../nfapi/public_inc/nfapi_nr_interface_scf.h | 7 + 3 files changed, 138 insertions(+), 12 deletions(-) diff --git a/nfapi/open-nFAPI/fapi/CMakeLists.txt b/nfapi/open-nFAPI/fapi/CMakeLists.txt index cf7f85052f..0cddd9d82f 100644 --- a/nfapi/open-nFAPI/fapi/CMakeLists.txt +++ b/nfapi/open-nFAPI/fapi/CMakeLists.txt @@ -19,8 +19,10 @@ target_include_directories(nr_fapi_p7 PUBLIC inc) target_link_libraries(nr_fapi_p7 PUBLIC nr_fapi_common) if (OAI_AERIAL) - target_compile_definitions(nr_fapi_p5 PRIVATE ENABLE_AERIAL) + target_compile_definitions(nr_fapi_p5 PRIVATE ENABLE_AERIAL ENABLE_10_04) target_compile_definitions(nr_fapi_p7 PRIVATE ENABLE_AERIAL) +else() + target_compile_definitions(nr_fapi_p5 PRIVATE ENABLE_10_02) endif () if(OAI_WLS) diff --git a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c index 6936d8b8fa..a7cb729f6c 100644 --- a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c +++ b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c @@ -721,7 +721,7 @@ uint8_t unpack_nr_param_response(uint8_t **ppReadPackedMsg, uint8_t *end, void * config, &pNfapiMsg->vendor_extension)); } - +#ifndef ENABLE_AERIAL 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; @@ -768,7 +768,27 @@ static uint8_t pack_pm_table_tlv_value(void *tlv, uint8_t **ppWritePackedMsg, ui } return 1; } - +#endif +#ifdef ENABLE_10_04 +static uint8_t pack_nr_tdd_table_10_04(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_tdd_table_tlv_t *tdd_table_tlv = (nfapi_nr_tdd_table_tlv_t *)tlv; + nfapi_nr_tdd_table_t *tdd_table = tdd_table_tlv->value; +#ifndef ENABLE_AERIAL + if (!push8(tdd_table->tdd_period.value, ppWritePackedMsg, end)) { + return 0; + } +#endif + for (int i = 0; i < tdd_table_tlv->slots_per_frame; i++) { + for (int k = 0; k < tdd_table_tlv->symbols_per_slot; k++) { + if (!push8(tdd_table->max_tdd_periodicity_list[i].max_num_of_symbol_per_slot_list[k].slot_config.value, ppWritePackedMsg, end)) { + return 0; + } + } + } + return 1; +} +#endif 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; @@ -1050,18 +1070,23 @@ uint8_t pack_nr_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *e &pack_uint8_tlv_value); numTLVs++; } - // END SSB Table +#endif + // START TDD Table if (pNfapiMsg->cell_config.frame_duplex_type.value == 1 /* TDD */) { - retval &= - pack_nr_tlv(NFAPI_NR_CONFIG_TDD_PERIOD_TAG, &(pNfapiMsg->tdd_table.tdd_period), ppWritePackedMsg, end, &pack_uint8_tlv_value); - numTLVs++; 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; +#ifdef ENABLE_10_02 + retval &= pack_nr_tlv(NFAPI_NR_CONFIG_TDD_PERIOD_TAG, + &(pNfapiMsg->tdd_table.tdd_period), + ppWritePackedMsg, + end, + &pack_uint8_tlv_value); + numTLVs++; for (int i = 0; i < slotsperframe[pNfapiMsg->ssb_config.scs_common.value]; i++) { // TODO check right number of slots for (int k = 0; k < number_of_symbols_per_slot; k++) { // TODO can change? retval &= pack_nr_tlv(NFAPI_NR_CONFIG_SLOT_CONFIG_TAG, @@ -1072,10 +1097,37 @@ uint8_t pack_nr_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *e numTLVs++; } } - } - - // END TDD Table #endif + +#ifdef ENABLE_10_04 +#ifdef ENABLE_AERIAL + retval &= pack_nr_tlv(NFAPI_NR_CONFIG_TDD_PERIOD_TAG, + &(pNfapiMsg->tdd_table.tdd_period), + ppWritePackedMsg, + end, + &pack_uint8_tlv_value); + numTLVs++; + + nfapi_nr_tdd_table_tlv_t tdd_table_tlv = {.tl.tag = NFAPI_NR_CONFIG_SLOT_CONFIG_TAG, .value = &pNfapiMsg->tdd_table, .slots_per_frame = slotsperframe[pNfapiMsg->ssb_config.scs_common.value], .symbols_per_slot = number_of_symbols_per_slot }; + retval &= pack_nr_tlv(NFAPI_NR_CONFIG_SLOT_CONFIG_TAG, + &tdd_table_tlv, + ppWritePackedMsg, + end, + &pack_nr_tdd_table_10_04); + numTLVs++; +#else + nfapi_nr_tdd_table_tlv_t tdd_table_tlv = {.tl.tag = NFAPI_NR_CONFIG_TDD_TABLE, .value = &pNfapiMsg->tdd_table, .slots_per_frame = slotsperframe[pNfapiMsg->ssb_config.scs_common.value], .symbols_per_slot = number_of_symbols_per_slot }; + retval &= pack_nr_tlv(NFAPI_NR_CONFIG_TDD_TABLE, + &tdd_table_tlv, + ppWritePackedMsg, + end, + &pack_nr_tdd_table_10_04); + numTLVs++; +#endif +#endif + } + // END TDD Table + // START Measurement Config // SCF222.10.02 Table 3-27 : Contains only one TLV and is currently unused pNfapiMsg->measurement_config.rssi_measurement.tl.tag = NFAPI_NR_CONFIG_RSSI_MEASUREMENT_TAG; @@ -1087,7 +1139,7 @@ uint8_t pack_nr_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *e &pack_uint8_tlv_value); numTLVs++; // END Measurement Config - +#ifndef ENABLE_AERIAL // START Digital Beam Table (DBT) PDU 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}; @@ -1103,7 +1155,7 @@ uint8_t pack_nr_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *e numTLVs++; } // is 0xA011 END Precoding Matrix (PM) PDU -#ifndef ENABLE_AERIAL + // START nFAPI TLVs included in CONFIG.request for IDLE and CONFIGURED states retval &= pack_nr_tlv(NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv4), @@ -1264,7 +1316,37 @@ static uint8_t unpack_pm_table_tlv_value(void *tlv, uint8_t **ppReadPackedMsg, u } return 1; } +#ifdef ENABLE_10_04 +static uint8_t unpack_nr_tdd_table_10_04(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_tdd_table_tlv_t *tdd_table_tlv = (nfapi_nr_tdd_table_tlv_t *)tlv; + nfapi_nr_tdd_table_t *tdd_table = tdd_table_tlv->value; + if (!(pull8(ppReadPackedMsg, &tdd_table->tdd_period.value, end))) { + return 0; + } + tdd_table->tdd_period.tl.tag = NFAPI_NR_CONFIG_TDD_PERIOD_TAG; + const int slots = tdd_table_tlv->slots_per_frame; + const int symbols = tdd_table_tlv->symbols_per_slot; + if (!tdd_table->max_tdd_periodicity_list) { + tdd_table->max_tdd_periodicity_list = calloc(slots, sizeof(*tdd_table->max_tdd_periodicity_list)); + } + for (int slot = 0; slot < slots; slot++) { + nfapi_nr_max_tdd_periodicity_t* list = &tdd_table->max_tdd_periodicity_list[slot]; + if (!list->max_num_of_symbol_per_slot_list) { + list->max_num_of_symbol_per_slot_list = calloc(symbols, sizeof(*list->max_num_of_symbol_per_slot_list)); + } + for (int sym = 0; sym < symbols; sym++) { + if (!(pull8(ppReadPackedMsg, &list->max_num_of_symbol_per_slot_list[sym].slot_config.value, end))) { + return 0; + } + list->max_num_of_symbol_per_slot_list[sym].slot_config.tl.tag = NFAPI_NR_CONFIG_SLOT_CONFIG_TAG; + } + } + + return 1; +} +#endif 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 @@ -1272,8 +1354,10 @@ uint8_t unpack_nr_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void * int unused_root_seq_idx = 0; int ssb_mask_idx = 0; int config_beam_idx = 0; +#ifdef ENABLE_10_02 int tdd_periodicity_idx = 0; int symbol_per_slot_idx = 0; +#endif int beam_ve_idx = 0; nfapi_nr_config_request_scf_t *pNfapiMsg = (nfapi_nr_config_request_scf_t *)msg; // unpack TLVs @@ -1324,7 +1408,16 @@ uint8_t unpack_nr_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void * &(pNfapiMsg->ssb_table.multiple_cells_ss_pbch_in_a_carrier), &unpack_uint8_tlv_value}, {NFAPI_NR_CONFIG_TDD_PERIOD_TAG, &(pNfapiMsg->tdd_table.tdd_period), &unpack_uint8_tlv_value}, +#ifdef ENABLE_10_02 {NFAPI_NR_CONFIG_SLOT_CONFIG_TAG, NULL, &unpack_uint8_tlv_value}, +#endif +#ifdef ENABLE_10_04 +#ifdef ENABLE_AERIAL + {NFAPI_NR_CONFIG_SLOT_CONFIG_TAG, NULL, &unpack_nr_tdd_table_10_04}, +#else + {NFAPI_NR_CONFIG_TDD_TABLE, NULL, &unpack_nr_tdd_table_10_04}, +#endif +#endif {NFAPI_NR_FAPI_NUM_BEAMS_PERIOD_VENDOR_EXTENSION_TAG, &(pNfapiMsg->analog_beamforming_ve.num_beams_period_vendor_ext), &unpack_uint8_tlv_value}, {NFAPI_NR_FAPI_ANALOG_BF_VENDOR_EXTENSION_TAG, &(pNfapiMsg->analog_beamforming_ve.analog_bf_vendor_ext), &unpack_uint8_tlv_value}, {NFAPI_NR_FAPI_TOTAL_NUM_BEAMS_VENDOR_EXTENSION_TAG, &(pNfapiMsg->analog_beamforming_ve.total_num_beams_vendor_ext), &unpack_uint8_tlv_value}, @@ -1341,6 +1434,13 @@ uint8_t unpack_nr_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void * {NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV6_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_address_ipv6), &unpack_ipv6_address_value}, {NFAPI_NR_NFAPI_P7_PNF_PORT_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_port), &unpack_uint16_tlv_value}}; +#ifdef ENABLE_10_04 +#ifdef ENABLE_AERIAL + nfapi_nr_tdd_table_tlv_t tdd_table_tlv = {.tl.tag = NFAPI_NR_CONFIG_SLOT_CONFIG_TAG}; +#else + nfapi_nr_tdd_table_tlv_t tdd_table_tlv = {.tl.tag = NFAPI_NR_CONFIG_TDD_TABLE}; +#endif +#endif pull8(ppReadPackedMsg, &pNfapiMsg->num_tlv, end); pNfapiMsg->vendor_extension = malloc(sizeof(&(pNfapiMsg->vendor_extension))); @@ -1387,6 +1487,16 @@ 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->pmi_list, ppReadPackedMsg, end); break; +#ifdef ENABLE_10_04 +#ifdef ENABLE_AERIAL + case NFAPI_NR_CONFIG_SLOT_CONFIG_TAG: +#else + case NFAPI_NR_CONFIG_TDD_TABLE: +#endif + unpack_fns[idx].tlv = &generic_tl; + result = (*unpack_fns[idx].unpack_func)(&tdd_table_tlv, ppReadPackedMsg, end); + break; +#endif 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; @@ -1413,6 +1523,11 @@ uint8_t unpack_nr_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void * pNfapiMsg->tdd_table.max_tdd_periodicity_list[i].max_num_of_symbol_per_slot_list = calloc(number_of_symbols_per_slot, sizeof(nfapi_nr_max_num_of_symbol_per_slot_t)); } +#ifdef ENABLE_10_04 + tdd_table_tlv.slots_per_frame = slotsperframe[pNfapiMsg->ssb_config.scs_common.value]; + tdd_table_tlv.symbols_per_slot = number_of_symbols_per_slot; + tdd_table_tlv.value = &pNfapiMsg->tdd_table; +#endif } break; case NFAPI_NR_CONFIG_PRACH_ROOT_SEQUENCE_INDEX_TAG: @@ -1531,6 +1646,7 @@ uint8_t unpack_nr_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void * end); config_beam_idx++; break; +#ifdef ENABLE_10_02 case NFAPI_NR_CONFIG_SLOT_CONFIG_TAG: unpack_fns[idx].tlv = &(pNfapiMsg->tdd_table.max_tdd_periodicity_list[tdd_periodicity_idx] .max_num_of_symbol_per_slot_list[symbol_per_slot_idx] @@ -1551,6 +1667,7 @@ uint8_t unpack_nr_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void * tdd_periodicity_idx++; } break; +#endif default: result = (*unpack_fns[idx].unpack_func)(tl, ppReadPackedMsg, end); break; 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 e19dab108c..e966b0a57b 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 @@ -447,6 +447,13 @@ typedef struct } nfapi_nr_tdd_table_t; +typedef struct { + nfapi_tl_t tl; + nfapi_nr_tdd_table_t *value; + uint8_t slots_per_frame; + uint8_t symbols_per_slot; +} nfapi_nr_tdd_table_tlv_t; + //table 3-27 typedef struct { From c24673798a3cfd26c5481a9c488c16a7e269a604 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 23 Jul 2025 11:54:23 +0200 Subject: [PATCH 458/964] Handle TDD pattern 2 in UL TDA allocation Add the possibility to use UL slots in TDD pattern 2. For simplicity, we require the mixed slot to be of the same symbols in pattern 1 & 2. For UL slots, simply use the right amount of UL TDAs, depending on which number of UL slots among pattern 1 & 2 is bigger. One complication is the TDA for the mixed slot. The current code assumes that k2 has to be equal or larger than (number of DL slots +1) (because the spec says min k2=2, but we might want to schedule DSUUU). Then, there could be for instance the following cases: - only pattern 1: DSUUU DSUUU ...: the mixed slot has to be reached an entire period in advance - pattern 1 & 2: DSUUU DDDDD: normal mixed slot k2, e.g., like for 7DS2U - pattern 1 & 2: DSUUU DDDSU: the mixed slot has to be reached N_ul2+N_dl1+1 slots in advance I can't think of more cases right now. To avoid unscheduled slots, I put an assertion (which could also trivially be taken out). --- openair2/GNB_APP/gnb_config.c | 4 -- openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c | 45 +++++++++++--------- 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 57086db62a..c2e56e7eb2 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -1206,10 +1206,6 @@ static NR_ServingCellConfigCommon_t *get_scc_config(configmodule_interface_t *cf struct NR_TDD_UL_DL_ConfigCommon *tdd = scc->tdd_UL_DL_ConfigurationCommon; tdd->pattern2 = calloc_or_fail(1, sizeof(*tdd->pattern2)); *scc->tdd_UL_DL_ConfigurationCommon->pattern2 = p2; - AssertFatal(p2.nrofUplinkSlots ^ scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots, - "UL slots in pattern1 (%ld) and pattern2 (%ld) are mutually exclusive (e.g. DDDFUU DDDD, DDDD DDDFUU)\n", - scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots, - p2.nrofUplinkSlots); } struct NR_FrequencyInfoDL *frequencyInfoDL = scc->downlinkConfigCommon->frequencyInfoDL; LOG_I(RRC, diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c index 2203c0b2b7..e4becc1da3 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c @@ -1102,44 +1102,49 @@ void nr_rrc_config_ul_tda(NR_ServingCellConfigCommon_t *scc, int min_fb_delay, i } if (scc->tdd_UL_DL_ConfigurationCommon) { - int ul_symb = 0; NR_TDD_UL_DL_Pattern_t *p1 = &scc->tdd_UL_DL_ConfigurationCommon->pattern1; + int ul_symb = p1->nrofUplinkSymbols; NR_TDD_UL_DL_Pattern_t *p2 = scc->tdd_UL_DL_ConfigurationCommon->pattern2; if (p2 && p2->nrofUplinkSymbols) - AssertFatal(p2->nrofUplinkSymbols == p1->nrofUplinkSymbols, - "nrofDownlinkSymbols in pattern1 %ld and pattern2 %ld must be the same in current implementation\n", - p1->nrofUplinkSymbols, + AssertFatal(p2->nrofUplinkSymbols == ul_symb, + "nrofDownlinkSymbols in pattern1 %d and pattern2 %ld must be the same in current implementation\n", + ul_symb, p2->nrofUplinkSymbols); - if (p1->nrofUplinkSymbols) { - ul_symb = p1->nrofUplinkSymbols; - } else if (p2) { - ul_symb = p1->nrofUplinkSymbols; - } + AssertFatal(!p2 || p2->nrofDownlinkSlots >= p2->nrofUplinkSlots, + "nrofDownlinkSlots must be larger than nrofUplinkSlots for pattern2 in current implementation\n"); - DevAssert(p2 == NULL); - int N_dl = p1->nrofDownlinkSlots; - int N_ul = p1->nrofUplinkSlots; + int N_dl1 = p1->nrofDownlinkSlots; + int N_ul1 = p1->nrofUplinkSlots; + int N_dl2 = p2 ? p2->nrofDownlinkSlots : 0; + int N_ul2 = p2 ? p2->nrofUplinkSlots : 0; int tdd_period_idx = get_tdd_period_idx(scc->tdd_UL_DL_ConfigurationCommon); int nb_periods_per_frame = get_nb_periods_per_frame(tdd_period_idx); int nb_slots_per_period = ((1 << mu) * 10) / nb_periods_per_frame; // make TDA for the mixed slot - if (ul_symb > 1 && k2 <= N_dl) { - // UL TDA index 2 for mixed slot (TDD) - long sliv = get_SLIV(NR_NUMBER_OF_SYMBOLS_PER_SLOT - ul_symb, ul_symb - 1); - tda = set_TimeDomainResourceAllocation(k2, sliv); // to be reached from suitable DL slot + long mixed_sliv = get_SLIV(NR_NUMBER_OF_SYMBOLS_PER_SLOT - ul_symb, ul_symb - 1); + if (ul_symb > 1 && (k2 <= N_dl1 || (p2 && N_ul2 == 0))) { + // UL TDA index 2 for mixed slot (TDD) (no pattern 2 and enough DL slots, or pattern2 only DL) + tda = set_TimeDomainResourceAllocation(k2, mixed_sliv); // to be reached from suitable DL slot asn1cSeqAdd(&tda_list->list, tda); - } else if (ul_symb > 1) { // k2 > N_Dl - long sliv = get_SLIV(NR_NUMBER_OF_SYMBOLS_PER_SLOT - ul_symb, ul_symb - 1); - tda = set_TimeDomainResourceAllocation(nb_slots_per_period, sliv); // to be reached from last DL (mixed) slot, if any + } else if (ul_symb > 1 && !p2 && k2 > N_dl1) { // k2 > N_Dl1 + // UL TDA for mixed slot without pattern 2 and less DL slots than k2 + tda = set_TimeDomainResourceAllocation(nb_slots_per_period, mixed_sliv); // to be reached from last DL (mixed) slot, if any asn1cSeqAdd(&tda_list->list, tda); + } else if (ul_symb > 1 && N_ul2 > 0 && k2 > N_dl1) { + // we have pattern 2 with UL, and less p1 DL slots than k2 + tda = set_TimeDomainResourceAllocation(N_dl1 + N_ul2 + 1, mixed_sliv); + asn1cSeqAdd(&tda_list->list, tda); + } else { + AssertFatal(ul_symb == 0, "unhandled case of mixed slot: N_dl1 %d N_ul1 %d N_dl2 %d N_ul2 %d\n", N_dl1, N_ul1, N_dl2, N_ul2); } // make TDA for UL slots that are not reachable within k2/min_rxtxtime + int N_ul = max(N_ul1, N_ul2); if (N_ul > k2) { // enforce that with k2, we could reach all but one slot (which is mixed // and taken into account above - AssertFatal(N_dl >= k2 - 1, "cannot fulfil TDD pattern: N_dl %d, k2 %d\n", N_dl, k2); + AssertFatal(N_dl1 >= k2 - 1, "cannot fulfil TDD pattern: N_dl1 %d, k2 %d\n", N_dl1, k2); for (int i = k2 + 1; i <= N_ul; ++i) { tda = set_TimeDomainResourceAllocation(i, get_SLIV(0, 13)); asn1cSeqAdd(&tda_list->list, tda); From ba6bad5eb3454efdc538e7ad2609f97730141873 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 14 Aug 2025 12:55:51 +0200 Subject: [PATCH 459/964] Fix AL candidate documentation to right default The default aggregation level candidate numbers in gnb_config.c (search "uess_num_agg_level_candidates") is 0,2,0,0,0, so write that instead. --- doc/MAC/mac-usage.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/doc/MAC/mac-usage.md b/doc/MAC/mac-usage.md index 1ed71d30b4..2f4b849d4d 100644 --- a/doc/MAC/mac-usage.md +++ b/doc/MAC/mac-usage.md @@ -49,9 +49,11 @@ The value of `pdcch_cl_adjust` is clamped to range <0,1>, the increment value is the decrement value is 0.01. These values are selected to ensure PDCCH success rate is high. See Examples below for futher explaination. -The possible values of aggregation level on UE SS can be configured via `uess_agg_levels` configuration -option. By default the gNB uses only aggregation level 2 which translates to `uess_agg_levels` set to -`[0, 1, 0, 0, 0]`. For example, to enable aggregation level 2 and 4 set `uess_agg_levels` to `[0, 1, 1, 0, 0]`. +The possible values of aggregation level on UE SS can be configured via +`uess_agg_levels` configuration option. By default the gNB uses two candidates +in aggregation level 2 which translates to `uess_agg_levels` set to `[0, 2, 0, +0, 0]`. For example, to enable one candidate on aggregation levels 2 and 4 set +`uess_agg_levels` to `[0, 1, 1, 0, 0]`. ### Examples: #### Example 1: From e0c1f8d920be82e3379f1bae0b5001aa61faf0aa Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 14 Aug 2025 13:00:09 +0200 Subject: [PATCH 460/964] Increase AL candidates count on AW2S pipeline Increase the number of aggregration level candidates. Since we have many UEs with concurrent traffic in that pipeline, we should ensure that we can allocate many DCIs to not waste resources (e.g., not all RBs used because could not find DCIs for specific UEs). --- ci-scripts/conf_files/gnb.sa.band78.51prb.aw2s.ddsuu.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/ci-scripts/conf_files/gnb.sa.band78.51prb.aw2s.ddsuu.conf b/ci-scripts/conf_files/gnb.sa.band78.51prb.aw2s.ddsuu.conf index 4b46b8ca33..02dfd2f5fe 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.51prb.aw2s.ddsuu.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.51prb.aw2s.ddsuu.conf @@ -25,6 +25,7 @@ gNBs = pusch_AntennaPorts = 1; do_CSIRS = 1; do_SRS = 0; + uess_agg_levels = [2, 2, 2, 0, 0]; servingCellConfigCommon = ( { From 6c4e5dccea40eaf40e10d284a4612477debb590c Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 7 Aug 2025 13:22:40 +0200 Subject: [PATCH 461/964] Don't redirect installation log files to a file Similarly to the parent, don't redirect log files to a file. It makes the CI more complicated, and also raises user awareness of what is being installed. --- cmake_targets/tools/build_helper | 26 +++++--------------------- 1 file changed, 5 insertions(+), 21 deletions(-) diff --git a/cmake_targets/tools/build_helper b/cmake_targets/tools/build_helper index 2c79659991..7d438e6e5f 100755 --- a/cmake_targets/tools/build_helper +++ b/cmake_targets/tools/build_helper @@ -186,9 +186,7 @@ clean_all_files() { ############################################ install_usrp_uhd_driver_from_source(){ - uhd_install_log=$OPENAIR_DIR/cmake_targets/log/uhd_install_log.txt - echo_info "\nInstalling UHD driver from sources. The log file for UHD driver installation is here: $uhd_install_log " - ( + echo_info "\nInstalling UHD driver from sources." pushd /tmp echo "Cloning UHD driver repository" rm -rf /tmp/uhd @@ -248,7 +246,6 @@ install_usrp_uhd_driver_from_source(){ fi popd rm -rf /tmp/uhd - ) >& $uhd_install_log } check_install_usrp_uhd_driver(){ @@ -345,9 +342,7 @@ install_usrp_uhd_driver() { } install_bladerf_driver_from_source(){ - bladerf_install_log=$OPENAIR_DIR/cmake_targets/log/bladerf_install_log.txt - echo_info "\nInstalling BladeRF driver from sources. The log file for BladeRF driver installation is here: $bladerf_install_log " - ( + echo_info "\nInstalling BladeRF driver from sources." cd /tmp echo "Downloading BladeRF driver" rm -rf /tmp/bladeRF @@ -370,7 +365,6 @@ install_bladerf_driver_from_source(){ sudo mkdir -p /usr/share/Nuand/bladeRF sudo mv bladeRF_fw_latest.img /usr/share/Nuand/bladeRF/bladeRF_fw.img sudo mv hostedx40-latest.rbf /usr/share/Nuand/bladeRF/hostedx40.rbf - ) >& $bladerf_install_log } check_install_bladerf_driver(){ @@ -405,9 +399,7 @@ check_install_lmssdr_driver(){ } install_soapy_from_source(){ - soapy_install_log=$OPENAIR_DIR/cmake_targets/log/soapy_install_log.txt - echo_info "\nInstalling Soapy EcoSystem from source. The log file for Soapy installation is here: $soapy_install_log " - ( + echo_info "\nInstalling Soapy EcoSystem from source." cd /tmp echo "Downloading SoapySDR" rm -rf /tmp/SoapySDR @@ -434,13 +426,10 @@ install_soapy_from_source(){ make -j`nproc` $SUDO make install $SUDO ldconfig - ) >& $soapy_install_log } install_soapy_iris_from_source(){ - iris_install_log=$OPENAIR_DIR/cmake_targets/log/iris_install_log.txt - echo_info "\nInstalling Iris driver from source. The log file for Iris driver installation is here: $iris_install_log " - ( + echo_info "\nInstalling Iris driver from source." cd /tmp echo "Downloading SoapyIris" rm -rf /tmp/sklk-soapyiris @@ -453,7 +442,6 @@ install_soapy_iris_from_source(){ make -j`nproc` $SUDO make install $SUDO ldconfig - ) >& $iris_install_log } check_install_soapy () { @@ -585,10 +573,7 @@ check_install_oai_software() { } install_asn1c_from_source(){ - mkdir -p $OPENAIR_DIR/cmake_targets/log - asn1_install_log=$OPENAIR_DIR/cmake_targets/log/asn1c_install_log.txt - echo_info "\nInstalling ASN1. The log file for ASN1 installation is here: $asn1_install_log " - ( + echo_info "\nInstalling ASN1." $SUDO $INSTALLER -y install bison flex $SUDO rm -rf /tmp/asn1c # GIT_SSL_NO_VERIFY=true git clone https://gitlab.eurecom.fr/oai/asn1c.git /tmp/asn1c @@ -609,7 +594,6 @@ install_asn1c_from_source(){ if [[ -v CI_ENV ]]; then $SUDO rm -rf /tmp/asn1c fi - ) > $asn1_install_log 2>&1 } install_simde_from_source(){ From 334251c4ff1b1d60ae782b4e82bfb08874993864 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 7 Aug 2025 13:24:33 +0200 Subject: [PATCH 462/964] Remove unused build_helper function --- cmake_targets/tools/build_helper | 40 -------------------------------- 1 file changed, 40 deletions(-) diff --git a/cmake_targets/tools/build_helper b/cmake_targets/tools/build_helper index 7d438e6e5f..e651723e63 100755 --- a/cmake_targets/tools/build_helper +++ b/cmake_targets/tools/build_helper @@ -733,43 +733,3 @@ set_openair_env(){ export OPENAIR3_DIR=$openair_path/openair3 export OPENAIR_TARGETS=$openair_path/targets } - -################################ -# Function to killall the subprocesses when Ctrl-C Key is hit -############################### -function handle_ctrl_c(){ -CURPID=$$ -ppid=$$ -arraycounter=1 -echo_info "** Trapped CTRL-C. Killing all subprocesses now..." -echo_info "** Calling sync now..." -sync -while true -do - FORLOOP=FALSE - # Get all the child process id - for i in `ps -ef| awk '$3 == '$ppid' { print $2 }'` - do - if [ $i -ne $CURPID ] ; then - procid[$arraycounter]=$i - arraycounter=`expr $arraycounter + 1` - ppid=$i - FORLOOP=TRUE - fi - done - if [ "$FORLOOP" = "FALSE" ] ; then - arraycounter=`expr $arraycounter - 1` - ## We want to kill child process id first and then parent id's - while [ $arraycounter -ne 0 ] - do - echo "first we send ctrl-c to program" - $SUDO kill -INT "${procid[$arraycounter]}" - sleep 5 - echo "Now we force kill if that didn't work" - $SUDO kill -9 "${procid[$arraycounter]}" >/dev/null - arraycounter=`expr $arraycounter - 1` - done - exit - fi -done -} From 2086de2a98454f0a1a29ce2ebf15bd09d3dcb26e Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 7 Aug 2025 13:26:41 +0200 Subject: [PATCH 463/964] Do not collect log files that don't exist Since one of the parent commits, build_oai does not redirect files to a log folder. Hence, there is no need to collect those. --- ci-scripts/cls_cluster.py | 32 -------------------------------- ci-scripts/cls_containerize.py | 13 ------------- 2 files changed, 45 deletions(-) diff --git a/ci-scripts/cls_cluster.py b/ci-scripts/cls_cluster.py index 185e90a13e..5cbae237c3 100644 --- a/ci-scripts/cls_cluster.py +++ b/ci-scripts/cls_cluster.py @@ -165,24 +165,6 @@ class Cluster: return -1 return int(result.group("size")) - def _deploy_pod(self, filename, timeout = 120): - ret = self.cmd.run(f'oc create -f {filename}') - result = re.search(r'pod/(?P[a-zA-Z0-9_\-]+) created', ret.stdout) - if result is None: - logging.error(f'could not deploy pod: {ret.stdout}') - return None - pod = result.group("pod") - logging.debug(f'checking if pod {pod} is in Running state') - ret = self.cmd.run(f'oc wait --for=condition=ready pod {pod} --timeout={timeout}s', silent=True) - if ret.returncode == 0: - return pod - logging.error(f'pod {pod} did not reach Running state') - self._undeploy_pod(filename) - return None - - def _undeploy_pod(self, filename): - self.cmd.run(f'oc delete -f {filename}') - def PullClusterImage(self, HTML, node, images, tag_prefix): logging.debug(f'Pull OC image {images} to server {node}') self.testCase_id = HTML.testCase_id @@ -296,20 +278,6 @@ class Cluster: if not status: logging.error('failure during build of ran-base') log_files.append(self._retrieveOCLog(ctx, ranbase_job, lSourcePath, 'ran-base')) - # recover logs by mounting image - self._retag_image_statement('ran-base', 'ran-base', baseTag, 'openshift/ran-base-log-retrieval.yaml') - pod = self._deploy_pod('openshift/ran-base-log-retrieval.yaml') - if pod is not None: - logdir = f'{lSourcePath}/cmake_targets/log/ran-base' - self.cmd.run(f'mkdir -p {logdir}') - self.cmd.run(f'oc rsync {pod}:/oai-ran/cmake_targets/log/ {logdir}') - self._undeploy_pod('openshift/ran-base-log-retrieval.yaml') - ret = self.cmd.run(f'ls {logdir}') - for f in ret.stdout.splitlines(): - archiveArtifact(self.cmd, ctx, f"{logdir}/{f}") - else: - status = False - if status: self._recreate_is_tag('oai-physim', imageTag, 'openshift/oai-physim-is.yaml') self._recreate_bc('oai-physim', imageTag, 'openshift/oai-physim-bc.yaml') diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index 34522d9eef..adc270cabb 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -386,13 +386,6 @@ class Containerize(): t = ("ran-base", archiveArtifact(cmd, ctx, logfile)) log_files.append(t) - # Recover build logs, for the moment only possible when build is successful - cmd.run(f"{self.cli} create --name test {baseImage}:{baseTag}") - cmd.run("mkdir -p cmake_targets/log/ran-base") - logfile = f'{lSourcePath}/cmake_targets/log/ran-base.log' - cmd.run(f"{self.cli} cp test:/oai-ran/cmake_targets/log/all.txt {logfile}") - cmd.run(f"{self.cli} rm -f test") - archiveArtifact(cmd, ctx, logfile) # First verify if the base image was properly created. ret = cmd.run(f"{self.cli} image inspect --format=\'Size = {{{{.Size}}}} bytes\' {baseImage}:{baseTag}") allImagesSize = {} @@ -438,12 +431,6 @@ class Containerize(): log_files.append(t) if image == 'oai-gnb-aerial': cmd.run('rm -f nvipc.src.2025.05.20.tar.gz') - if image == 'ran-build' or image == 'ran-build-asan' or image == 'ran-build-fhi72': - cmd.run(f"docker run --name test-log -d {name}:{imageTag} /bin/true") - logfile = f'{lSourcePath}/{image}.ninja.log' - cmd.run(f"docker cp test-log:/oai-ran/cmake_targets/log/all.txt {logfile}") - cmd.run(f"docker rm -f test-log") - archiveArtifact(cmd, ctx, logfile) # check the status of the build ret = cmd.run(f"{self.cli} image inspect --format=\'Size = {{{{.Size}}}} bytes\' {name}:{imageTag}") if ret.returncode != 0: From 599a1a8c74414f48829d92061553317a346d280f Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 7 Aug 2025 14:28:27 +0200 Subject: [PATCH 464/964] UHD installation: remove multiple packages at once Removing packages individually is slow, because apt starts to (re-)read it's database over and over again. Do it at once to speed up. --- cmake_targets/tools/build_helper | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/cmake_targets/tools/build_helper b/cmake_targets/tools/build_helper index e651723e63..3379048171 100755 --- a/cmake_targets/tools/build_helper +++ b/cmake_targets/tools/build_helper @@ -252,18 +252,7 @@ check_install_usrp_uhd_driver(){ if [[ "$OS_BASEDISTRO" == "debian" ]]; then boost_libs_ubuntu="libboost-chrono-dev libboost-date-time-dev libboost-filesystem-dev libboost-program-options-dev libboost-thread-dev libboost-test-dev libboost-regex-dev" #first we remove old installation - $SUDO apt-get remove uhd -y || true - $SUDO apt-get remove uhd-host -y || true - $SUDO apt-get remove libuhd-dev -y || true - $SUDO apt-get remove libuhd003 -y || true - $SUDO apt-get remove libuhd3.13.1 -y || true - $SUDO apt-get remove libuhd3.14.0 -y || true - $SUDO apt-get remove libuhd3.14.1 -y || true - $SUDO apt-get remove libuhd3.15.0 -y || true - local distribution=$(get_distribution_release) - if [[ "$distribution" == "ubuntu20.04" || "$distribution" == "ubuntu22.04" ]]; then - $SUDO apt-get remove libuhd4.?.? -y || true - fi + $SUDO apt-get remove uhd* libuhd* -y || true v=$(lsb_release -cs) $SUDO apt-add-repository --remove "deb http://files.ettus.com/binaries/uhd/repo/uhd/ubuntu/$v $v main" if [[ -v BUILD_UHD_FROM_SOURCE ]] || [[ "$OS_DISTRO" == "debian" ]]; then From 47b658baf5822b39682bd936d6be5b9f2425bac1 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 7 Aug 2025 14:32:38 +0200 Subject: [PATCH 465/964] Disable various UHD features build_oai primarily builds UHD for OAI. Thus, a number of targets (B100, USRP1/2, ...) can be omitted, as OAI does not run on them. Further, disable documentation and man pages, which is typically not necessary for the averages user, and does not need to be installed for containers. --- cmake_targets/tools/build_helper | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake_targets/tools/build_helper b/cmake_targets/tools/build_helper index 3379048171..2b11412e94 100755 --- a/cmake_targets/tools/build_helper +++ b/cmake_targets/tools/build_helper @@ -231,7 +231,7 @@ install_usrp_uhd_driver_from_source(){ git diff mkdir -p host/build cd host/build || true - $CMAKE ../ -GNinja -DENABLE_TESTS=OFF -DENABLE_EXAMPLES=OFF + $CMAKE ../ -GNinja -DENABLE_TESTS=OFF -DENABLE_EXAMPLES=OFF -DENABLE_B100=OFF -DENABLE_DOXYGEN=OFF -DENABLE_MANUAL=OFF -DENABLE_MAN_PAGES=OFF -DENABLE_MAN_PAGE_COMPRESSION=OFF -DENABLE_OCTOCLOCK=ON -DENABLE_USRP1=OFF -DENABLE_USRP2=OFF echo "Compiling UHD" ninja $SUDO ninja install From e7ea9ba747770ee40ef5b0310c784f385ff464f1 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 7 Aug 2025 15:11:27 +0200 Subject: [PATCH 466/964] CI: Clarify HTML message if a (ctest-executed) test fails --- ci-scripts/cls_cluster.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci-scripts/cls_cluster.py b/ci-scripts/cls_cluster.py index 5cbae237c3..6634a3e8e7 100644 --- a/ci-scripts/cls_cluster.py +++ b/ci-scripts/cls_cluster.py @@ -460,7 +460,7 @@ class Cluster: HTML.CreateHtmlTestRowPhySimTestResult(test_summary, test_result) logging.info('\u001B[1m Physical Simulator Pass\u001B[0m') else: - HTML.CreateHtmlTestRow('Some test(s) failed!', 'KO', CONST.OC_PHYSIM_DEPLOY_FAIL) + HTML.CreateHtmlTestRowQueue('At least one physical simulator test failed!', 'KO', ["See below for details"]) HTML.CreateHtmlTestRowPhySimTestResult(test_summary, test_result) logging.error('\u001B[1m Physical Simulator Fail\u001B[0m') else: From cf967d33143529f6c7fab1fae489fd62246d5ab2 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 7 Aug 2025 18:14:35 +0200 Subject: [PATCH 467/964] Complete run_locally.sh to produce valid HTML --- ci-scripts/run_locally.sh | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/ci-scripts/run_locally.sh b/ci-scripts/run_locally.sh index 60010ea30a..facc7c8752 100755 --- a/ci-scripts/run_locally.sh +++ b/ci-scripts/run_locally.sh @@ -26,8 +26,20 @@ fi docker tag oai-nr-ue oai-ci/oai-nr-ue:develop-${SHORT_COMMIT_SHA} docker tag oai-gnb oai-ci/oai-gnb:develop-${SHORT_COMMIT_SHA} +python3 main.py --mode=InitiateHtml --ranRepository=NONE --ranBranch=${CURRENT_BRANCH} \ + --ranCommitID=${COMMIT_SHA} --ranAllowMerge=false \ + --ranTargetBranch=NONE \ + --XMLTestFile=xml_files/${TESTCASE} --local + python3 main.py --mode=TesteNB --ranRepository=NONE --ranBranch=${CURRENT_BRANCH} \ --ranCommitID=${COMMIT_SHA} --ranAllowMerge=false \ --ranTargetBranch=NONE --eNBIPAddress=NONE --eNBUserName=NONE --eNBPassword=NONE \ --eNBSourceCodePath=${REPO_PATH} \ --XMLTestFile=xml_files/${TESTCASE} --local +RET=$? + +python3 main.py --mode=FinalizeHtml \ + --local \ + --eNBIPAddress=NONE --eNBUserName=NONE --eNBPassword=NONE + +exit ${RET} From 3febc50f476cbe391618bd94d6f2f2b423e528ab Mon Sep 17 00:00:00 2001 From: Bartosz Podrygajlo Date: Sun, 27 Jul 2025 11:34:23 +0200 Subject: [PATCH 468/964] Make run_locally.sh script take the full path to the xml file Use full path to xml file in run_locally.sh to allow usage of system command line completion feature. --- ci-scripts/run_locally.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci-scripts/run_locally.sh b/ci-scripts/run_locally.sh index facc7c8752..84fd6a6f17 100755 --- a/ci-scripts/run_locally.sh +++ b/ci-scripts/run_locally.sh @@ -35,7 +35,7 @@ python3 main.py --mode=TesteNB --ranRepository=NONE --ranBranch=${CURRENT_BRANCH --ranCommitID=${COMMIT_SHA} --ranAllowMerge=false \ --ranTargetBranch=NONE --eNBIPAddress=NONE --eNBUserName=NONE --eNBPassword=NONE \ --eNBSourceCodePath=${REPO_PATH} \ - --XMLTestFile=xml_files/${TESTCASE} --local + --XMLTestFile=${TESTCASE} --local RET=$? python3 main.py --mode=FinalizeHtml \ From 089059e10a08e46bb0c844d2492c73d437847fb3 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 8 Aug 2025 09:50:36 +0200 Subject: [PATCH 469/964] Remove unused variables --- ci-scripts/cls_oai_html.py | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/ci-scripts/cls_oai_html.py b/ci-scripts/cls_oai_html.py index c90b01a338..07226bcff3 100644 --- a/ci-scripts/cls_oai_html.py +++ b/ci-scripts/cls_oai_html.py @@ -70,16 +70,6 @@ class HTMLManagement(): self.testCase_id = '' self.desc = '' - self.OsVersion = ['', ''] - self.KernelVersion = ['', ''] - self.UhdVersion = ['', ''] - self.UsrpBoard = ['', ''] - self.CpuNb = ['', ''] - self.CpuModel = ['', ''] - self.CpuMHz = ['', ''] - - - #----------------------------------------------------------- # HTML structure creation functions #----------------------------------------------------------- From 81a79980dd7729de4d502d9c9e62289df20bd330 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 8 Aug 2025 09:47:05 +0200 Subject: [PATCH 470/964] AnalyzeBuildLogs(): only analyze one file at a time Will be used in a follow-up commit to simplify analysis of log files and HTML file printing. --- ci-scripts/cls_cluster.py | 13 +++++----- ci-scripts/cls_containerize.py | 47 +++++++++++++++++----------------- 2 files changed, 31 insertions(+), 29 deletions(-) diff --git a/ci-scripts/cls_cluster.py b/ci-scripts/cls_cluster.py index 6634a3e8e7..ace1545fbc 100644 --- a/ci-scripts/cls_cluster.py +++ b/ci-scripts/cls_cluster.py @@ -412,12 +412,13 @@ class Cluster: self.cmd.close() # Analyze the logs - collectInfo = cls_containerize.AnalyzeBuildLogs(log_files, status) - for img in collectInfo: - for f in collectInfo[img]: - status = status and collectInfo[img][f]['status'] - if not status: - logging.debug(collectInfo) + collectInfo = {} + for image, lf in log_files: + files = {} + idx = 'Target Image Creation' + files[idx] = cls_containerize.AnalyzeBuildLogs(image, lf) + status = status and files[idx]['status'] + collectInfo[image] = files if status: logging.info('\u001B[1m Building OAI Image(s) Pass\u001B[0m') diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index adc270cabb..9af086308a 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -82,28 +82,23 @@ def CreateTag(ranCommitID, ranBranch, ranAllowMerge): tagToUse = f'develop-{shortCommit}' return tagToUse -def AnalyzeBuildLogs(logfiles, globalStatus): - collectInfo = {} - for image, lf in logfiles: - files = {} - errorandwarnings = {} - committed = False - tagged = False - with open(lf, mode='r') as inputfile: - for line in inputfile: - lineHasTag = re.search(f'Successfully tagged {image}:', str(line)) is not None - lineHasTag2 = re.search(f'naming to docker.io/library/{image}:', str(line)) is not None - tagged = tagged or lineHasTag or lineHasTag2 - # the OpenShift Cluster builder prepends image registry URL - lineHasCommit = re.search(r'COMMIT [a-zA-Z0-9\.:/\-]*' + image, str(line)) is not None - committed = committed or lineHasCommit - errorandwarnings['errors'] = 0 if committed or tagged else 1 - errorandwarnings['warnings'] = 0 - errorandwarnings['status'] = committed or tagged - logging.info(f"Analyzing {image}, file {lf}: {errorandwarnings}") - files['Target Image Creation'] = errorandwarnings - collectInfo[image] = files - return collectInfo +def AnalyzeBuildLogs(image, lf): + errorandwarnings = {} + committed = False + tagged = False + with open(lf, mode='r') as inputfile: + for line in inputfile: + lineHasTag = re.search(f'Successfully tagged {image}:', str(line)) is not None + lineHasTag2 = re.search(f'naming to docker.io/library/{image}:', str(line)) is not None + tagged = tagged or lineHasTag or lineHasTag2 + # the OpenShift Cluster builder prepends image registry URL + lineHasCommit = re.search(r'COMMIT [a-zA-Z0-9\.:/\-]*' + image, str(line)) is not None + committed = committed or lineHasCommit + errorandwarnings['errors'] = 0 if committed or tagged else 1 + errorandwarnings['warnings'] = 0 + errorandwarnings['status'] = committed or tagged + logging.info(f"Analyzing {image}, file {lf}: {errorandwarnings}") + return errorandwarnings def GetImageName(ssh, svcName, file): ret = ssh.run(f"docker compose -f {file} config --format json {svcName} | jq -r '.services.\"{svcName}\".image'", silent=True) @@ -467,7 +462,13 @@ class Containerize(): cmd.close() # Analyze the logs - collectInfo = AnalyzeBuildLogs(log_files, status) + collectInfo = {} + for name, lf in log_files: + files = {} + idx = 'Target Image Creation' + files[idx] = AnalyzeBuildLogs(name, lf) + status = status and files[idx]['status'] + collectInfo[name] = files if status: logging.info('\u001B[1m Building OAI Image(s) Pass\u001B[0m') From 2f43b09651bbdfe399b1bd150451836fe298d492 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 8 Aug 2025 11:58:47 +0200 Subject: [PATCH 471/964] Remove unnecessary HTML printing, simplify code --- ci-scripts/cls_cluster.py | 14 ++++----- ci-scripts/cls_containerize.py | 31 ++++---------------- ci-scripts/cls_oai_html.py | 52 ---------------------------------- 3 files changed, 11 insertions(+), 86 deletions(-) diff --git a/ci-scripts/cls_cluster.py b/ci-scripts/cls_cluster.py index ace1545fbc..53164a2d55 100644 --- a/ci-scripts/cls_cluster.py +++ b/ci-scripts/cls_cluster.py @@ -414,20 +414,16 @@ class Cluster: # Analyze the logs collectInfo = {} for image, lf in log_files: - files = {} - idx = 'Target Image Creation' - files[idx] = cls_containerize.AnalyzeBuildLogs(image, lf) - status = status and files[idx]['status'] - collectInfo[image] = files + ret = cls_containerize.AnalyzeBuildLogs(image, lf) + imgStatus = ret['status'] + msg = f"size {imageSize[image]}, analysis of {os.path.basename(lf)}: {ret['errors']} errors, {ret['warnings']} warnings" + HTML.CreateHtmlTestRowQueue(image, 'OK' if imgStatus else 'KO', [msg]) + status = status and imgStatus if status: logging.info('\u001B[1m Building OAI Image(s) Pass\u001B[0m') - HTML.CreateHtmlTestRow('all', 'OK', CONST.ALL_PROCESSES_OK) else: logging.error('\u001B[1m Building OAI Images Failed\u001B[0m') - HTML.CreateHtmlTestRow('all', 'KO', CONST.ALL_PROCESSES_OK) - - HTML.CreateHtmlNextTabHeaderTestRow(collectInfo, imageSize) # TODO fix groovy script, remove the following. # the groovy scripts expects all logs in diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index 9af086308a..c006951908 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -462,25 +462,18 @@ class Containerize(): cmd.close() # Analyze the logs - collectInfo = {} for name, lf in log_files: - files = {} - idx = 'Target Image Creation' - files[idx] = AnalyzeBuildLogs(name, lf) - status = status and files[idx]['status'] - collectInfo[name] = files + ret = AnalyzeBuildLogs(name, lf) + imgStatus = ret['status'] + msg = f"size {allImagesSize[name]}, analysis of {os.path.basename(lf)}: {ret['errors']} errors, {ret['warnings']} warnings" + HTML.CreateHtmlTestRowQueue(name, 'OK' if imgStatus else 'KO', [msg]) + status = status and imgStatus if status: logging.info('\u001B[1m Building OAI Image(s) Pass\u001B[0m') - HTML.CreateHtmlTestRow(self.imageKind, 'OK', CONST.ALL_PROCESSES_OK) - HTML.CreateHtmlNextTabHeaderTestRow(collectInfo, allImagesSize) - return True else: logging.error('\u001B[1m Building OAI Images Failed\u001B[0m') - HTML.CreateHtmlTestRow(self.imageKind, 'KO', CONST.ALL_PROCESSES_OK) - HTML.CreateHtmlNextTabHeaderTestRow(collectInfo, allImagesSize) - HTML.CreateHtmlTabFooter(False) - return False + return status def BuildProxy(self, ctx, HTML): svr = self.eNB_serverId[self.eNB_instance] @@ -545,16 +538,6 @@ class Containerize(): self.ranAllowMerge = oldRanAllowMerge self.ranTargetBranch = oldRanTargetBranch - # we do not analyze the logs (we assume the proxy builds fine at this stage), - # but need to have the following information to correctly display the HTML - files = {} - errorandwarnings = {} - errorandwarnings['errors'] = 0 - errorandwarnings['warnings'] = 0 - errorandwarnings['status'] = True - files['Target Image Creation'] = errorandwarnings - collectInfo = {} - collectInfo['proxy'] = files ret = ssh.run(f'docker image inspect --format=\'Size = {{{{.Size}}}} bytes\' proxy:{tag}') result = re.search(r'Size *= *(?P[0-9\-]+) *bytes', ret.stdout) # Cleaning any created tmp volume @@ -568,14 +551,12 @@ class Containerize(): allImagesSize['proxy'] = str(round(imageSize,1)) + ' Mbytes' logging.info('\u001B[1m Building L2sim Proxy Image Pass\u001B[0m') HTML.CreateHtmlTestRow('commit ' + tag, 'OK', CONST.ALL_PROCESSES_OK) - HTML.CreateHtmlNextTabHeaderTestRow(collectInfo, allImagesSize) return True else: logging.error('proxy size is unknown') allImagesSize['proxy'] = 'unknown' logging.error('\u001B[1m Build of L2sim proxy failed\u001B[0m') HTML.CreateHtmlTestRow('commit ' + tag, 'KO', CONST.ALL_PROCESSES_OK) - HTML.CreateHtmlTabFooter(False) return False def BuildRunTests(self, ctx, HTML): diff --git a/ci-scripts/cls_oai_html.py b/ci-scripts/cls_oai_html.py index 07226bcff3..c4e13b2e62 100644 --- a/ci-scripts/cls_oai_html.py +++ b/ci-scripts/cls_oai_html.py @@ -332,58 +332,6 @@ class HTMLManagement(): self.htmlFile.write(' \n') self.htmlFile.close() - - def CreateHtmlNextTabHeaderTestRow(self, collectInfo, allImagesSize, machine='eNB'): - if (self.htmlFooterCreated or (not self.htmlHeaderCreated)): - return - self.htmlFile = open('test_results.html', 'a') - if bool(collectInfo) == False: - self.htmlFile.write(' \n') - self.htmlFile.write(' ----IMAGES BUILDING FAILED - Unable to recover the image logs ---- \n') - self.htmlFile.write(' \n') - else: - for image in collectInfo: - files = collectInfo[image] - # TabHeader for image logs on built shared and target images - if allImagesSize[image].count('unknown') > 0: - self.htmlFile.write(' \n') - elif allImagesSize[image].count('Build Failed') > 0: - self.htmlFile.write(' \n') - else: - self.htmlFile.write(' \n') - self.htmlFile.write(' ---- ' + image + ' IMAGE STATUS ----> Size ' + allImagesSize[image] + ' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' Element\n') - self.htmlFile.write(' Nb Errors\n') - self.htmlFile.write(' Nb Warnings\n') - self.htmlFile.write(' Status\n') - self.htmlFile.write(' \n') - - for fil in files: - parameters = files[fil] - # TestRow for image logs on built shared and target images - self.htmlFile.write(' \n') - self.htmlFile.write(' ' + fil + ' \n') - if (parameters['errors'] == 0): - self.htmlFile.write(' ' + str(parameters['errors']) + '\n') - else: - self.htmlFile.write(' ' + str(parameters['errors']) + '\n') - if (parameters['errors'] > 0): - self.htmlFile.write(' ' + str(parameters['warnings']) + '\n') - elif (parameters['warnings'] == 0): - self.htmlFile.write(' ' + str(parameters['warnings']) + '\n') - else: - self.htmlFile.write(' ' + str(parameters['warnings']) + '\n') - if (parameters['errors'] == 0) and (parameters['warnings'] == 0): - self.htmlFile.write(' OK \n') - elif (parameters['errors'] == 0): - self.htmlFile.write(' OK \n') - else: - self.htmlFile.write(' NOT OK \n') - self.htmlFile.write(' \n') - self.htmlFile.close() - #for the moment it is limited to 4 columns, to be made generic later def CreateHtmlDataLogTable(self, DataLog): if (self.htmlFooterCreated or (not self.htmlHeaderCreated)): From c8c6aa50f37cb127bc45f62ce469967c60bba54a Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 8 Aug 2025 12:19:06 +0200 Subject: [PATCH 472/964] Cluster: build FHI7.2 in parallel --- ci-scripts/cls_cluster.py | 45 ++++++++++++++------------------------- 1 file changed, 16 insertions(+), 29 deletions(-) diff --git a/ci-scripts/cls_cluster.py b/ci-scripts/cls_cluster.py index 53164a2d55..ba8c208508 100644 --- a/ci-scripts/cls_cluster.py +++ b/ci-scripts/cls_cluster.py @@ -279,6 +279,11 @@ class Cluster: log_files.append(self._retrieveOCLog(ctx, ranbase_job, lSourcePath, 'ran-base')) if status: + self._recreate_is_tag('ran-build-fhi72', imageTag, 'openshift/ran-build-fhi72-is.yaml') + self._recreate_bc('ran-build-fhi72', imageTag, 'openshift/ran-build-fhi72-bc.yaml') + self._retag_image_statement('ran-base', 'image-registry.openshift-image-registry.svc:5000/oaicicd-ran/ran-base', baseTag, 'docker/Dockerfile.build.fhi72.rhel9') + ranbuildfhi72_job = self._start_build('ran-build-fhi72') + self._recreate_is_tag('oai-physim', imageTag, 'openshift/oai-physim-is.yaml') self._recreate_bc('oai-physim', imageTag, 'openshift/oai-physim-bc.yaml') self._retag_image_statement('ran-base', 'image-registry.openshift-image-registry.svc:5000/oaicicd-ran/ran-base', baseTag, 'docker/Dockerfile.phySim.rhel9') @@ -294,15 +299,22 @@ class Cluster: self._retag_image_statement('ran-base', 'image-registry.openshift-image-registry.svc:5000/oaicicd-ran/ran-base', baseTag, 'docker/Dockerfile.clang.rhel9') clang_job = self._start_build('oai-clang') - wait = ranbuild_job is not None and physim_job is not None and clang_job is not None and self._wait_build_end([ranbuild_job, physim_job, clang_job], 1200) - if not wait: logging.error('error during build of ranbuild_job or physim_job or clang_job') + wait = ranbuildfhi72_job is not None and ranbuild_job is not None and physim_job is not None and clang_job is not None and self._wait_build_end([ranbuildfhi72_job, ranbuild_job, physim_job, clang_job], 1200) + if not wait: logging.error('error during build of ranbuildfhi72_job or ranbuild_job or physim_job or clang_job') status = status and wait + log_files.append(self._retrieveOCLog(ctx, ranbuildfhi72_job, lSourcePath, 'ran-build-fhi72')) log_files.append(self._retrieveOCLog(ctx, ranbuild_job, lSourcePath, 'ran-build')) log_files.append(self._retrieveOCLog(ctx, physim_job, lSourcePath, 'oai-physim')) log_files.append(self._retrieveOCLog(ctx, clang_job, lSourcePath, 'oai-clang')) self.cmd.run(f'oc get pods.metrics.k8s.io &>> {build_metrics}') if status: + self._recreate_is_tag('oai-gnb-fhi72', imageTag, 'openshift/oai-gnb-fhi72-is.yaml') + self._recreate_bc('oai-gnb-fhi72', imageTag, 'openshift/oai-gnb-fhi72-bc.yaml') + self._retag_image_statement('ran-base', 'image-registry.openshift-image-registry.svc:5000/oaicicd-ran/ran-base', baseTag, 'docker/Dockerfile.gNB.fhi72.rhel9') + self._retag_image_statement('ran-build-fhi72', 'image-registry.openshift-image-registry.svc:5000/oaicicd-ran/ran-build-fhi72', imageTag, 'docker/Dockerfile.gNB.fhi72.rhel9') + gnb_fhi72_job = self._start_build('oai-gnb-fhi72') + self._recreate_is_tag('oai-enb', imageTag, 'openshift/oai-enb-is.yaml') self._recreate_bc('oai-enb', imageTag, 'openshift/oai-enb-bc.yaml') self._retag_image_statement('ran-base', 'image-registry.openshift-image-registry.svc:5000/oaicicd-ran/ran-base', baseTag, 'docker/Dockerfile.eNB.rhel9') @@ -321,10 +333,11 @@ class Cluster: self._retag_image_statement('ran-build', 'image-registry.openshift-image-registry.svc:5000/oaicicd-ran/ran-build', imageTag, 'docker/Dockerfile.gNB.aw2s.rhel9') gnb_aw2s_job = self._start_build('oai-gnb-aw2s') - wait = enb_job is not None and gnb_job is not None and gnb_aw2s_job is not None and self._wait_build_end([enb_job, gnb_job, gnb_aw2s_job], 800) + wait = gnb_fhi72_job is not None and enb_job is not None and gnb_job is not None and gnb_aw2s_job is not None and self._wait_build_end([gnb_fhi72_job, enb_job, gnb_job, gnb_aw2s_job], 800) if not wait: logging.error('error during build of eNB/gNB') status = status and wait # recover logs + log_files.append(self._retrieveOCLog(ctx, gnb_fhi72_job, lSourcePath, 'oai-gnb-fhi72')) log_files.append(self._retrieveOCLog(ctx, enb_job, lSourcePath, 'oai-enb')) log_files.append(self._retrieveOCLog(ctx, gnb_job, lSourcePath, 'oai-gnb')) log_files.append(self._retrieveOCLog(ctx, gnb_aw2s_job, lSourcePath, 'oai-gnb-aw2s')) @@ -357,32 +370,6 @@ class Cluster: log_files.append(self._retrieveOCLog(ctx, nrue_job, lSourcePath, 'oai-nr-ue')) self.cmd.run(f'oc get pods.metrics.k8s.io &>> {build_metrics}') - if status: - self._recreate_is_tag('ran-build-fhi72', imageTag, 'openshift/ran-build-fhi72-is.yaml') - self._recreate_bc('ran-build-fhi72', imageTag, 'openshift/ran-build-fhi72-bc.yaml') - self._retag_image_statement('ran-base', 'image-registry.openshift-image-registry.svc:5000/oaicicd-ran/ran-base', baseTag, 'docker/Dockerfile.build.fhi72.rhel9') - ranbuildfhi72_job = self._start_build('ran-build-fhi72') - - wait = ranbuildfhi72_job is not None and self._wait_build_end([ranbuildfhi72_job], 1200) - if not wait: logging.error('error during build of ranbuildfhi72_job') - status = status and wait - log_files.append(self._retrieveOCLog(ctx, ranbuildfhi72_job, lSourcePath, 'ran-build-fhi72')) - self.cmd.run(f'oc get pods.metrics.k8s.io &>> {build_metrics}') - - if status: - self._recreate_is_tag('oai-gnb-fhi72', imageTag, 'openshift/oai-gnb-fhi72-is.yaml') - self._recreate_bc('oai-gnb-fhi72', imageTag, 'openshift/oai-gnb-fhi72-bc.yaml') - self._retag_image_statement('ran-base', 'image-registry.openshift-image-registry.svc:5000/oaicicd-ran/ran-base', baseTag, 'docker/Dockerfile.gNB.fhi72.rhel9') - self._retag_image_statement('ran-build-fhi72', 'image-registry.openshift-image-registry.svc:5000/oaicicd-ran/ran-build-fhi72', imageTag, 'docker/Dockerfile.gNB.fhi72.rhel9') - gnb_fhi72_job = self._start_build('oai-gnb-fhi72') - - wait = gnb_fhi72_job is not None and self._wait_build_end([gnb_fhi72_job], 600) - if not wait: logging.error('error during build of gNB-fhi72') - status = status and wait - # recover logs - log_files.append(self._retrieveOCLog(ctx, gnb_fhi72_job, lSourcePath, 'oai-gnb-fhi72')) - self.cmd.run(f'oc get pods.metrics.k8s.io &>> {build_metrics}') - # split and analyze logs imageSize = {} for image, _ in log_files: From ae3799d4ed4b497aa9d4fa04e2438363c9c7ad2d Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 8 Aug 2025 14:42:35 +0200 Subject: [PATCH 473/964] Remove unused parameters --- ci-scripts/args_parse.py | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/ci-scripts/args_parse.py b/ci-scripts/args_parse.py index 92cb0d163f..02d31340cc 100644 --- a/ci-scripts/args_parse.py +++ b/ci-scripts/args_parse.py @@ -59,17 +59,6 @@ def ArgsParse(argvs,CiTestObj,RAN,HTML,CONTAINERS,HELP,SCA,CLUSTER): force_local = True - #--apply= as parameters file, to replace inline parameters - elif re.match(r'^\-\-Apply=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match(r'^\-\-Apply=(.+)$', myArgv, re.IGNORECASE) - py_params_file = matchReg.group(1) - with open(py_params_file,'r') as file: - # The FullLoader parameter handles the conversion from YAML - # scalar values to Python dictionary format - py_params = yaml.load(file,Loader=yaml.FullLoader) - py_param_file_present = True #to be removed once validated - #AssignParams(py_params) #to be uncommented once validated - #consider inline parameters elif re.match(r'^\-\-mode=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match(r'^\-\-mode=(.+)$', myArgv, re.IGNORECASE) @@ -196,14 +185,6 @@ def ArgsParse(argvs,CiTestObj,RAN,HTML,CONTAINERS,HELP,SCA,CLUSTER): CiTestObj.testXMLfiles.append(matchReg.group(1)) HTML.testXMLfiles.append(matchReg.group(1)) HTML.nbTestXMLfiles=HTML.nbTestXMLfiles+1 - elif re.match(r'^\-\-UEIPAddress=(.+)$', myArgv, re.IGNORECASE): # cleanup - print("parameter --UEIPAddress ignored") - elif re.match(r'^\-\-UEUserName=(.+)$', myArgv, re.IGNORECASE): - print("parameter --UEUserName ignored") - elif re.match(r'^\-\-UEPassword=(.+)$', myArgv, re.IGNORECASE): - print("parameter --UEPassword ignored") - elif re.match(r'^\-\-UESourceCodePath=(.+)$', myArgv, re.IGNORECASE): - print("parameter --UESourceCodePath ignored") elif re.match(r'^\-\-finalStatus=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match(r'^\-\-finalStatus=(.+)$', myArgv, re.IGNORECASE) finalStatus = matchReg.group(1) From 7defffe97a0c2534ce25a686b3e9d838e7af38a2 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 11 Aug 2025 12:36:10 +0200 Subject: [PATCH 474/964] Remove unused file --- .../xml_files/test_case_list_template.xml | 105 ------------------ 1 file changed, 105 deletions(-) delete mode 100644 ci-scripts/xml_files/test_case_list_template.xml diff --git a/ci-scripts/xml_files/test_case_list_template.xml b/ci-scripts/xml_files/test_case_list_template.xml deleted file mode 100644 index bcc8f94c09..0000000000 --- a/ci-scripts/xml_files/test_case_list_template.xml +++ /dev/null @@ -1,105 +0,0 @@ - - - - 010101 050101 060101 070101 030101 030201 050201 070201 060201 - 010102 030102 030103 030104 030105 030106 - - - - - Build_eNB - Build eNB (USRP) - -w USRP -c --eNB - - - - Build_eNB - Build eNB (USRP) - -w BLADERF -c --eNB - - - - Initialize_eNB - Initialize eNB (FDD/Band1/5MHz/info) - -O enb.band7.tm1.50prb.usrpb210.conf --log_config.global_log_options level,nocolor,time - - - - Initialize_eNB - Initialize eNB (FDD/Band1/10MHz/info) - -O 10M.band1.FDD.info.conf --log_config.global_log_options level,nocolor,time - - - - Initialize_eNB - Initialize eNB (FDD/Band1/20MHz/info) - -O 20M.band1.FDD.info.conf --log_config.global_log_options level,nocolor,time - - - - Initialize_eNB - Initialize eNB (TDD/Band38/5MHz/info) - -O 5M.band38.TDD.info.conf --log_config.global_log_options level,nocolor,time - - - - Initialize_eNB - Initialize eNB (TDD/Band38/10MHz/info) - -O 10M.band38.TDD.info.conf --log_config.global_log_options level,nocolor,time - - - - Initialize_eNB - Initialize eNB (TDD/Band38/20MHz/info) - -O 20M.band38.TDD.info.conf --log_config.global_log_options level,nocolor,time - - - - Terminate_eNB - Terminate eNB - - - - - - Initialize_UE - Initialize UE - - - - Terminate_UE - Terminate UE - - - - Attach_UE - Attach UE - - - - Detach_UE - Detach UE - - - From 881f753f3feac19524b22fda1a83a4598e5335aa Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 8 Aug 2025 18:42:49 +0200 Subject: [PATCH 475/964] Integrate all NSA-related XML files into one Is simpler to test manually and view the results. --- .../xml_files/container_nsa_b200_quectel.xml | 14 +++++++ ci-scripts/xml_files/nsa_epc_closure.xml | 38 ------------------ ci-scripts/xml_files/nsa_epc_start.xml | 39 ------------------- 3 files changed, 14 insertions(+), 77 deletions(-) delete mode 100644 ci-scripts/xml_files/nsa_epc_closure.xml delete mode 100644 ci-scripts/xml_files/nsa_epc_start.xml diff --git a/ci-scripts/xml_files/container_nsa_b200_quectel.xml b/ci-scripts/xml_files/container_nsa_b200_quectel.xml index 17c8a9b14f..f72d64a9d4 100644 --- a/ci-scripts/xml_files/container_nsa_b200_quectel.xml +++ b/ci-scripts/xml_files/container_nsa_b200_quectel.xml @@ -30,6 +30,7 @@ 500000 111110 111111 + 000100 010000 800833 030101 @@ -47,6 +48,7 @@ 010002 030202 030201 + 060000 300000 600000 222220 @@ -102,6 +104,12 @@ sudo cpupower idle-set -E + + DeployCoreNetwork + Start EPC + ltebox-nepes + + Initialize_UE Initialize Quectel @@ -241,6 +249,12 @@ 0 + + UndeployCoreNetwork + Terminate EPC + ltebox-nepes + + Undeploy_Object true diff --git a/ci-scripts/xml_files/nsa_epc_closure.xml b/ci-scripts/xml_files/nsa_epc_closure.xml deleted file mode 100644 index 23181ec674..0000000000 --- a/ci-scripts/xml_files/nsa_epc_closure.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - epc-closure - EPC-Closure - log-out - -060000 - - - - - UndeployCoreNetwork - Terminate EPC - ltebox-nepes - - - diff --git a/ci-scripts/xml_files/nsa_epc_start.xml b/ci-scripts/xml_files/nsa_epc_start.xml deleted file mode 100644 index 89761ddb74..0000000000 --- a/ci-scripts/xml_files/nsa_epc_start.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - epc-start-tab - EPC-Start - log-in - - 000100 - - - - - - DeployCoreNetwork - Start EPC - ltebox-nepes - - - From e25075134c1f7742f7f7d24375f3654d21013232 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 11 Aug 2025 15:19:59 +0200 Subject: [PATCH 476/964] Integrate all SA-OAIUE pipeline related files into one --- .../xml_files/container_sa_n310_nrue.xml | 15 ++++++++ ci-scripts/xml_files/sa_oaiue_cn5g_deploy.xml | 38 ------------------- .../xml_files/sa_oaiue_cn5g_undeploy.xml | 38 ------------------- 3 files changed, 15 insertions(+), 76 deletions(-) delete mode 100644 ci-scripts/xml_files/sa_oaiue_cn5g_deploy.xml delete mode 100644 ci-scripts/xml_files/sa_oaiue_cn5g_undeploy.xml diff --git a/ci-scripts/xml_files/container_sa_n310_nrue.xml b/ci-scripts/xml_files/container_sa_n310_nrue.xml index 16a23dc57a..da61c8e83f 100644 --- a/ci-scripts/xml_files/container_sa_n310_nrue.xml +++ b/ci-scripts/xml_files/container_sa_n310_nrue.xml @@ -25,6 +25,7 @@ 40 MHz TDD SA tasks + 060000 010000 010001 800813 020000 @@ -38,9 +39,16 @@ 040001 040000 333333 444444 + 060001 + + DeployCoreNetwork + Initialize 5G Core + oc-cn5g + + Pull_Cluster_Image Pull Images from Cluster @@ -179,4 +187,11 @@ oai-nr-ue + + UndeployCoreNetwork + Terminate 5G Core + true + oc-cn5g + + diff --git a/ci-scripts/xml_files/sa_oaiue_cn5g_deploy.xml b/ci-scripts/xml_files/sa_oaiue_cn5g_deploy.xml deleted file mode 100644 index a49a2cda18..0000000000 --- a/ci-scripts/xml_files/sa_oaiue_cn5g_deploy.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - cn5g-start-tab - CN5G-Start - log-in - -000100 - - - - - - DeployCoreNetwork - Initialize 5G Core - oc-cn5g - - diff --git a/ci-scripts/xml_files/sa_oaiue_cn5g_undeploy.xml b/ci-scripts/xml_files/sa_oaiue_cn5g_undeploy.xml deleted file mode 100644 index beb490dbed..0000000000 --- a/ci-scripts/xml_files/sa_oaiue_cn5g_undeploy.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - cn5g-closure - CN5G-Closure - log-out - -060000 - - - - - UndeployCoreNetwork - Terminate 5G Core - oc-cn5g - - - From d95e6bca6bfd60e9e2f38fe55eba47cab5d48d91 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 11 Aug 2025 09:30:04 +0200 Subject: [PATCH 477/964] Pull_Image_from_Registry()/Clean_Test_Server_Images(): pass node Pass the node name for a host onto/from which to pull/clean the images. For doing this, I used: - rfsim 4G eNB_IPAddress none => localhost - rfsim 5g eNB_IPAddress none => localhost - flexric eNB_IPAddress none => localhost - l2sim 4g eNB_IPAddress none => localhost - l2sim 4G eNB1_IPAddress 172.21.16.128 => obelix => localhost --- ci-scripts/cls_containerize.py | 18 ++++++++---------- ci-scripts/main.py | 6 +++--- ci-scripts/tests/pull-clean-int-registry.py | 13 ++++++------- .../xml_files/container_4g_l2sim_tdd.xml | 4 ++-- .../xml_files/container_4g_rfsim_fdd_05MHz.xml | 4 ++-- .../container_4g_rfsim_fdd_05MHz_noS1.xml | 4 ++-- .../xml_files/container_4g_rfsim_fdd_10MHz.xml | 4 ++-- .../xml_files/container_4g_rfsim_fdd_20MHz.xml | 4 ++-- .../xml_files/container_4g_rfsim_fembms.xml | 4 ++-- .../xml_files/container_4g_rfsim_mbms.xml | 4 ++-- .../xml_files/container_4g_rfsim_tdd_05MHz.xml | 4 ++-- ci-scripts/xml_files/container_5g_e1_rfsim.xml | 4 ++-- ci-scripts/xml_files/container_5g_f1_rfsim.xml | 4 ++-- .../xml_files/container_5g_fdd_rfsim.xml | 4 ++-- .../xml_files/container_5g_flexric_rfsim.xml | 8 ++++---- ci-scripts/xml_files/container_5g_rfsim.xml | 4 ++-- .../xml_files/container_5g_rfsim_24prb.xml | 4 ++-- .../xml_files/container_5g_rfsim_2x2.xml | 4 ++-- .../container_5g_rfsim_fdd_phytest.xml | 4 ++-- .../xml_files/container_5g_rfsim_fr2_32prb.xml | 4 ++-- .../xml_files/container_5g_rfsim_ntn_geo.xml | 4 ++-- .../xml_files/container_5g_rfsim_ntn_leo.xml | 4 ++-- .../xml_files/container_5g_rfsim_sidelink.xml | 4 ++-- .../xml_files/container_5g_rfsim_tdd_dora.xml | 4 ++-- .../xml_files/container_5g_rfsim_u0_25prb.xml | 4 ++-- .../container_lte_b200_fdd_05Mhz_tm1.xml | 4 ++-- .../container_lte_b200_fdd_05Mhz_tm1_if4_5.xml | 4 ++-- ..._lte_b200_fdd_05Mhz_tm1_no_rrc_activity.xml | 4 ++-- .../container_lte_b200_fdd_10Mhz_tm1.xml | 4 ++-- .../container_lte_b200_fdd_10Mhz_tm1_cdrx.xml | 4 ++-- .../container_lte_b200_fdd_10Mhz_tm1_oaiue.xml | 8 ++++---- .../container_lte_b200_fdd_20Mhz_tm1.xml | 4 ++-- .../container_lte_b200_tdd_05Mhz_tm1.xml | 4 ++-- .../container_lte_b200_tdd_05Mhz_tm1_if4_5.xml | 4 ++-- .../container_lte_b200_tdd_10Mhz_tm1.xml | 4 ++-- .../container_lte_b200_tdd_20Mhz_tm1.xml | 4 ++-- ...te_b200_tdd_20Mhz_tm1_default_scheduler.xml | 4 ++-- .../container_lte_n3xx_tdd_2x2_tm1.xml | 4 ++-- .../container_lte_n3xx_tdd_2x2_tm2.xml | 4 ++-- .../xml_files/container_nsa_b200_quectel.xml | 8 ++++---- .../xml_files/container_sa_aerial_quectel.xml | 4 ++-- .../xml_files/container_sa_aw2s_asue.xml | 2 +- .../xml_files/container_sa_aw2s_asue_2x2.xml | 2 +- .../xml_files/container_sa_b200_quectel.xml | 4 ++-- .../xml_files/container_sa_e1_b200_quectel.xml | 4 ++-- .../xml_files/container_sa_f1_b200_quectel.xml | 4 ++-- .../container_sa_fhi72_metanoia_up2_2x2.xml | 4 ++-- .../xml_files/container_sa_fhi72_vvdn_up2.xml | 4 ++-- .../container_sa_n310_2X2_100MHz_quectel.xml | 2 +- .../container_sa_n310_2X2_60MHz_quectel.xml | 2 +- .../container_sa_n310_4X4_60MHz_quectel.xml | 2 +- .../xml_files/container_sa_n310_nrue.xml | 4 ++-- .../xml_files/container_sa_sc_b200_quectel.xml | 4 ++-- 53 files changed, 118 insertions(+), 121 deletions(-) diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index c006951908..3af3291c35 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -702,28 +702,26 @@ class Containerize(): msg = "Pulled Images:\n" + '\n'.join(pulled_images) return True, msg - def Pull_Image_from_Registry(self, HTML, svr_id, images, tag=None, tag_prefix="", registry="porcepix.sboai.cs.eurecom.fr", username="oaicicd", password="oaicicd"): - lIpAddr, lSourcePath = self.GetCredentials(svr_id) - logging.debug('\u001B[1m Pulling image(s) on server: ' + lIpAddr + '\u001B[0m') + def Pull_Image_from_Registry(self, HTML, node, images, tag=None, tag_prefix="", registry="porcepix.sboai.cs.eurecom.fr", username="oaicicd", password="oaicicd"): + logging.debug(f'\u001B[1m Pulling image(s) on server: {node}\u001B[0m') if not tag: tag = CreateTag(self.ranCommitID, self.ranBranch, self.ranAllowMerge) - with cls_cmd.getConnection(lIpAddr) as cmd: + with cls_cmd.getConnection(node) as cmd: success, msg = Containerize.Pull_Image(cmd, images, tag, tag_prefix, registry, username, password) - param = f"on node {lIpAddr}" + param = f"on node {node}" if success: HTML.CreateHtmlTestRowQueue(param, 'OK', [msg]) else: HTML.CreateHtmlTestRowQueue(param, 'KO', [msg]) return success - def Clean_Test_Server_Images(self, HTML, svr_id, images, tag=None): - lIpAddr, lSourcePath = self.GetCredentials(svr_id) - logging.debug(f'\u001B[1m Cleaning image(s) from server: {lIpAddr}\u001B[0m') + def Clean_Test_Server_Images(self, HTML, node, images, tag=None): + logging.debug(f'\u001B[1m Cleaning image(s) from server: {node}\u001B[0m') if not tag: tag = CreateTag(self.ranCommitID, self.ranBranch, self.ranAllowMerge) status = True - with cls_cmd.getConnection(lIpAddr) as myCmd: + with cls_cmd.getConnection(node) as myCmd: removed_images = [] for image in images: fullImage = f"oai-ci/{image}:{tag}" @@ -734,7 +732,7 @@ class Containerize(): msg = "Removed Images:\n" + '\n'.join(removed_images) s = 'OK' if status else 'KO' - param = f"on node {lIpAddr}" + param = f"on node {node}" HTML.CreateHtmlTestRowQueue(param, s, [msg]) return status diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 0fdf538052..54f4073eb9 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -360,7 +360,7 @@ def ExecuteActionWithParam(action, ctx): if force_local: # Do not pull or remove images when running locally. User is supposed to handle image creation & cleanup return True - svr_id = test.findtext('svr_id') + node = test.findtext('node') or 'localhost' tag_prefix = test.findtext('tag_prefix') or "" images = test.findtext('images').split() # hack: for FlexRIC, we need to overwrite the tag to use @@ -368,9 +368,9 @@ def ExecuteActionWithParam(action, ctx): if len(images) == 1 and images[0] == "oai-flexric": tag = CONTAINERS.flexricTag if action == "Pull_Local_Registry": - success = CONTAINERS.Pull_Image_from_Registry(HTML, svr_id, images, tag=tag, tag_prefix=tag_prefix) + success = CONTAINERS.Pull_Image_from_Registry(HTML, node, images, tag=tag, tag_prefix=tag_prefix) if action == "Clean_Test_Server_Images": - success = CONTAINERS.Clean_Test_Server_Images(HTML, svr_id, images, tag=tag) + success = CONTAINERS.Clean_Test_Server_Images(HTML, node, images, tag=tag) elif action == 'Custom_Command': node = test.findtext('node') diff --git a/ci-scripts/tests/pull-clean-int-registry.py b/ci-scripts/tests/pull-clean-int-registry.py index d4d5b4fc0a..f17c1c7a1d 100644 --- a/ci-scripts/tests/pull-clean-int-registry.py +++ b/ci-scripts/tests/pull-clean-int-registry.py @@ -20,7 +20,6 @@ class TestDeploymentMethods(unittest.TestCase): self.html = cls_oai_html.HTMLManagement() self.html.testCaseId = "000000" self.cont = cls_containerize.Containerize() - self.cont.eNBIPAddress = 'localhost' self.cont.eNBSourceCodePath = os.getcwd() def test_pull_clean_local_reg(self): @@ -32,21 +31,21 @@ class TestDeploymentMethods(unittest.TestCase): ret = cmd.run(f"ping -c1 -w1 {registry}") if ret.returncode != 0: # could not ping once -> skip test self.skipTest(f"test_pull_clean_local_reg: could not reach {registry} (run inside sboai)") - svr_id = '0' + node = 'localhost' images = ["oai-gnb"] tag = "develop" - pull = self.cont.Pull_Image_from_Registry(self.html, svr_id, images, tag=tag) - clean = self.cont.Clean_Test_Server_Images(self.html, svr_id, images, tag=tag) + pull = self.cont.Pull_Image_from_Registry(self.html, node, images, tag=tag) + clean = self.cont.Clean_Test_Server_Images(self.html, node, images, tag=tag) self.assertTrue(pull) self.assertTrue(clean) def test_pull_clean_docker_hub(self): - svr_id = '0' + node = 'localhost' r = "docker.io" images = ["hello-world"] tag = "latest" - pull = self.cont.Pull_Image_from_Registry(self.html, svr_id, images, tag=tag, registry=r, username=None, password=None) - clean = self.cont.Clean_Test_Server_Images(self.html, svr_id, images, tag=tag) + pull = self.cont.Pull_Image_from_Registry(self.html, node, images, tag=tag, registry=r, username=None, password=None) + clean = self.cont.Clean_Test_Server_Images(self.html, node, images, tag=tag) self.assertTrue(pull) self.assertTrue(clean) diff --git a/ci-scripts/xml_files/container_4g_l2sim_tdd.xml b/ci-scripts/xml_files/container_4g_l2sim_tdd.xml index 98e0ec7d08..43334c0f91 100644 --- a/ci-scripts/xml_files/container_4g_l2sim_tdd.xml +++ b/ci-scripts/xml_files/container_4g_l2sim_tdd.xml @@ -44,7 +44,7 @@ Pull_Local_Registry Pull Images from Local Registry - 0 + obelix oai-enb oai-lte-ue @@ -153,7 +153,7 @@ Clean_Test_Server_Images true Clean Test Images on Test Server - 0 + obelix oai-enb oai-lte-ue diff --git a/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz.xml b/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz.xml index 235546928a..2f59fe3d7b 100644 --- a/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz.xml +++ b/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz.xml @@ -52,7 +52,7 @@ Pull_Local_Registry Pull Images from Local Registry - 0 + localhost oai-enb-asan oai-lte-ue-asan @@ -170,7 +170,7 @@ Clean_Test_Server_Images true Clean Test Images on Test Server - 0 + localhost oai-enb-asan oai-lte-ue-asan diff --git a/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz_noS1.xml b/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz_noS1.xml index 9b27ba1f8c..d78b926a00 100644 --- a/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz_noS1.xml +++ b/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz_noS1.xml @@ -43,7 +43,7 @@ Pull_Local_Registry Pull Images from Local Registry - 0 + localhost oai-enb-asan oai-lte-ue-asan @@ -141,7 +141,7 @@ Clean_Test_Server_Images true Clean Test Images on Test Server - 0 + localhost oai-enb-asan oai-lte-ue-asan diff --git a/ci-scripts/xml_files/container_4g_rfsim_fdd_10MHz.xml b/ci-scripts/xml_files/container_4g_rfsim_fdd_10MHz.xml index 2b8141a71d..c1a3b5ff6e 100644 --- a/ci-scripts/xml_files/container_4g_rfsim_fdd_10MHz.xml +++ b/ci-scripts/xml_files/container_4g_rfsim_fdd_10MHz.xml @@ -47,7 +47,7 @@ Pull_Local_Registry Pull Images from Local Registry - 0 + localhost oai-enb-asan oai-lte-ue-asan @@ -170,7 +170,7 @@ Clean_Test_Server_Images true Clean Test Images on Test Server - 0 + localhost oai-enb-asan oai-lte-ue-asan diff --git a/ci-scripts/xml_files/container_4g_rfsim_fdd_20MHz.xml b/ci-scripts/xml_files/container_4g_rfsim_fdd_20MHz.xml index 7afcc2f7c1..7c2622fed5 100644 --- a/ci-scripts/xml_files/container_4g_rfsim_fdd_20MHz.xml +++ b/ci-scripts/xml_files/container_4g_rfsim_fdd_20MHz.xml @@ -47,7 +47,7 @@ Pull_Local_Registry Pull Images from Local Registry - 0 + localhost oai-enb-asan oai-lte-ue-asan @@ -170,7 +170,7 @@ Clean_Test_Server_Images true Clean Test Images on Test Server - 0 + localhost oai-enb-asan oai-lte-ue-asan diff --git a/ci-scripts/xml_files/container_4g_rfsim_fembms.xml b/ci-scripts/xml_files/container_4g_rfsim_fembms.xml index 1f869ecdde..51cef07627 100644 --- a/ci-scripts/xml_files/container_4g_rfsim_fembms.xml +++ b/ci-scripts/xml_files/container_4g_rfsim_fembms.xml @@ -40,7 +40,7 @@ Pull_Local_Registry Pull Images from Local Registry - 0 + localhost oai-enb-asan oai-lte-ue-asan @@ -104,7 +104,7 @@ Clean_Test_Server_Images true Clean Test Images on Test Server - 0 + localhost oai-enb-asan oai-lte-ue-asan diff --git a/ci-scripts/xml_files/container_4g_rfsim_mbms.xml b/ci-scripts/xml_files/container_4g_rfsim_mbms.xml index 4c3691e466..621d3e121e 100644 --- a/ci-scripts/xml_files/container_4g_rfsim_mbms.xml +++ b/ci-scripts/xml_files/container_4g_rfsim_mbms.xml @@ -40,7 +40,7 @@ Pull_Local_Registry Pull Images from Local Registry - 0 + localhost oai-enb-asan oai-lte-ue-asan @@ -104,7 +104,7 @@ Clean_Test_Server_Images true Clean Test Images on Test Server - 0 + localhost oai-enb-asan oai-lte-ue-asan diff --git a/ci-scripts/xml_files/container_4g_rfsim_tdd_05MHz.xml b/ci-scripts/xml_files/container_4g_rfsim_tdd_05MHz.xml index f84269b16e..bc0e4f23d6 100644 --- a/ci-scripts/xml_files/container_4g_rfsim_tdd_05MHz.xml +++ b/ci-scripts/xml_files/container_4g_rfsim_tdd_05MHz.xml @@ -47,7 +47,7 @@ Pull_Local_Registry Pull Images from Local Registry - 0 + localhost oai-enb oai-lte-ue @@ -163,7 +163,7 @@ Clean_Test_Server_Images true Clean Test Images on Test Server - 0 + localhost oai-enb oai-lte-ue diff --git a/ci-scripts/xml_files/container_5g_e1_rfsim.xml b/ci-scripts/xml_files/container_5g_e1_rfsim.xml index 51f0270b19..50de456cdb 100644 --- a/ci-scripts/xml_files/container_5g_e1_rfsim.xml +++ b/ci-scripts/xml_files/container_5g_e1_rfsim.xml @@ -40,7 +40,7 @@ Pull_Local_Registry Pull Images from Local Registry - 0 + localhost oai-gnb oai-nr-cuup oai-nr-ue @@ -109,7 +109,7 @@ Clean_Test_Server_Images true Clean Test Images on Test Server - 0 + localhost oai-gnb oai-nr-cuup oai-nr-ue diff --git a/ci-scripts/xml_files/container_5g_f1_rfsim.xml b/ci-scripts/xml_files/container_5g_f1_rfsim.xml index 17f52daeb7..af0a9164db 100644 --- a/ci-scripts/xml_files/container_5g_f1_rfsim.xml +++ b/ci-scripts/xml_files/container_5g_f1_rfsim.xml @@ -63,7 +63,7 @@ Pull_Local_Registry Pull Images from Local Registry - 0 + localhost oai-gnb-asan oai-nr-cuup-asan oai-nr-ue-asan @@ -249,7 +249,7 @@ Clean_Test_Server_Images true Clean Test Images on Test Server - 0 + localhost oai-gnb-asan oai-nr-cuup-asan oai-nr-ue-asan diff --git a/ci-scripts/xml_files/container_5g_fdd_rfsim.xml b/ci-scripts/xml_files/container_5g_fdd_rfsim.xml index 1fd3de1ad5..99814fbc09 100644 --- a/ci-scripts/xml_files/container_5g_fdd_rfsim.xml +++ b/ci-scripts/xml_files/container_5g_fdd_rfsim.xml @@ -42,7 +42,7 @@ Pull_Local_Registry Pull Images from Local Registry - 0 + localhost oai-gnb oai-nr-ue @@ -137,7 +137,7 @@ Clean_Test_Server_Images true Clean Test Images on Test Server - 0 + localhost oai-gnb oai-nr-ue diff --git a/ci-scripts/xml_files/container_5g_flexric_rfsim.xml b/ci-scripts/xml_files/container_5g_flexric_rfsim.xml index a56248fe0e..d360645cbb 100644 --- a/ci-scripts/xml_files/container_5g_flexric_rfsim.xml +++ b/ci-scripts/xml_files/container_5g_flexric_rfsim.xml @@ -51,21 +51,21 @@ Pull_Local_Registry Pull Images from Local Registry - 0 + localhost oai-gnb oai-nr-ue Pull_Local_Registry Pull Images from Local Registry - 0 + localhost oai-flexric Clean_Test_Server_Images Clean Test Images on Test Server - 0 + localhost oai-gnb oai-nr-ue true @@ -73,7 +73,7 @@ Clean_Test_Server_Images Clean Test Images on Test Server - 0 + localhost oai-flexric true diff --git a/ci-scripts/xml_files/container_5g_rfsim.xml b/ci-scripts/xml_files/container_5g_rfsim.xml index 910a2dcbb5..8265e712c0 100644 --- a/ci-scripts/xml_files/container_5g_rfsim.xml +++ b/ci-scripts/xml_files/container_5g_rfsim.xml @@ -57,7 +57,7 @@ Pull_Local_Registry Pull Images from Local Registry - 0 + localhost oai-gnb-asan oai-nr-ue @@ -262,7 +262,7 @@ Clean_Test_Server_Images true Clean Test Images on Test Server - 0 + localhost oai-gnb-asan oai-nr-ue diff --git a/ci-scripts/xml_files/container_5g_rfsim_24prb.xml b/ci-scripts/xml_files/container_5g_rfsim_24prb.xml index 60bb0011fc..c74579d87b 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_24prb.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_24prb.xml @@ -60,7 +60,7 @@ Pull_Local_Registry Pull Images from Local Registry - 0 + localhost oai-gnb-asan oai-nr-ue-asan @@ -173,7 +173,7 @@ Clean_Test_Server_Images true Clean Test Images on Test Server - 0 + localhost oai-gnb-asan oai-nr-ue-asan diff --git a/ci-scripts/xml_files/container_5g_rfsim_2x2.xml b/ci-scripts/xml_files/container_5g_rfsim_2x2.xml index 5efb2e708b..9b5316aea6 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_2x2.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_2x2.xml @@ -42,7 +42,7 @@ Pull_Local_Registry Pull Images from Local Registry - 0 + localhost oai-gnb-asan oai-nr-ue-asan @@ -137,7 +137,7 @@ Clean_Test_Server_Images true Clean Test Images on Test Server - 0 + localhost oai-gnb-asan oai-nr-ue-asan diff --git a/ci-scripts/xml_files/container_5g_rfsim_fdd_phytest.xml b/ci-scripts/xml_files/container_5g_rfsim_fdd_phytest.xml index 58ff14102b..03afaff6d1 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_fdd_phytest.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_fdd_phytest.xml @@ -42,7 +42,7 @@ Pull_Local_Registry Pull Images from Local Registry - 0 + localhost oai-gnb-asan oai-nr-ue-asan @@ -137,7 +137,7 @@ Clean_Test_Server_Images true Clean Test Images on Test Server - 0 + acamas oai-gnb-asan oai-nr-ue-asan diff --git a/ci-scripts/xml_files/container_5g_rfsim_fr2_32prb.xml b/ci-scripts/xml_files/container_5g_rfsim_fr2_32prb.xml index 3aa9a395b3..6261fed596 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_fr2_32prb.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_fr2_32prb.xml @@ -40,7 +40,7 @@ Pull_Local_Registry Pull Images from Local Registry - 0 + acamas oai-gnb-asan oai-nr-ue-asan @@ -113,7 +113,7 @@ Clean_Test_Server_Images true Clean Test Images on Test Server - 0 + localhost oai-gnb-asan oai-nr-ue-asan diff --git a/ci-scripts/xml_files/container_5g_rfsim_ntn_geo.xml b/ci-scripts/xml_files/container_5g_rfsim_ntn_geo.xml index 88173b3659..4da64a8788 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_ntn_geo.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_ntn_geo.xml @@ -45,7 +45,7 @@ Pull_Local_Registry Pull Images from Local Registry - 0 + localhost oai-gnb-asan oai-nr-ue-asan @@ -142,7 +142,7 @@ Clean_Test_Server_Images true Clean Test Images on Test Server - 0 + localhost oai-gnb-asan oai-nr-ue-asan diff --git a/ci-scripts/xml_files/container_5g_rfsim_ntn_leo.xml b/ci-scripts/xml_files/container_5g_rfsim_ntn_leo.xml index 0d2634192d..89ff56d9fb 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_ntn_leo.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_ntn_leo.xml @@ -40,7 +40,7 @@ Pull_Local_Registry Pull Images from Local Registry - 0 + localhost oai-gnb-asan oai-nr-ue-asan @@ -110,7 +110,7 @@ Clean_Test_Server_Images true Clean Test Images on Test Server - 0 + localhost oai-gnb-asan oai-nr-ue-asan diff --git a/ci-scripts/xml_files/container_5g_rfsim_sidelink.xml b/ci-scripts/xml_files/container_5g_rfsim_sidelink.xml index 1e11870b88..9a57d49870 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_sidelink.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_sidelink.xml @@ -39,7 +39,7 @@ Pull_Local_Registry Pull Images from Local Registry - 0 + localhost oai-nr-ue-asan @@ -96,7 +96,7 @@ Clean_Test_Server_Images true Clean Test Images on Test Server - 0 + localhost oai-nr-ue-asan 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 5efa8d3401..4d36ccec80 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_tdd_dora.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_tdd_dora.xml @@ -42,7 +42,7 @@ Pull_Local_Registry Pull Images from Local Registry - 0 + localhost oai-gnb-asan oai-nr-ue-asan @@ -119,7 +119,7 @@ Clean_Test_Server_Images true Clean Test Images on Test Server - 0 + localhost oai-gnb-asan oai-nr-ue-asan diff --git a/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml b/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml index 40f3ad4607..a7a7df3a35 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml @@ -44,7 +44,7 @@ Pull_Local_Registry Pull Images from Local Registry - 0 + localhost oai-gnb-asan oai-nr-ue-asan @@ -158,7 +158,7 @@ Clean_Test_Server_Images true Clean Test Images on Test Server - 0 + localhost oai-gnb-asan oai-nr-ue-asan diff --git a/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1.xml b/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1.xml index a6d39d3f98..376c26400a 100644 --- a/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1.xml +++ b/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1.xml @@ -43,7 +43,7 @@ Replaces xml_files/enb_usrp210_band7_test_05mhz_tm1.xml Pull_Local_Registry Pull Images from Local Registry - 0 + hutch oai-enb @@ -212,7 +212,7 @@ Replaces xml_files/enb_usrp210_band7_test_05mhz_tm1.xml Clean_Test_Server_Images true Clean Test Images on Test Server - 0 + hutch oai-enb diff --git a/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1_if4_5.xml b/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1_if4_5.xml index 3e306844de..e37e1ca812 100644 --- a/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1_if4_5.xml +++ b/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1_if4_5.xml @@ -42,7 +42,7 @@ Pull_Local_Registry Pull Images from Local Registry - 0 + hutch oai-enb @@ -195,7 +195,7 @@ Clean_Test_Server_Images true Clean Test Images on Test Server - 0 + hutch oai-enb diff --git a/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1_no_rrc_activity.xml b/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1_no_rrc_activity.xml index 9d54eceaeb..04e459c4a3 100644 --- a/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1_no_rrc_activity.xml +++ b/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1_no_rrc_activity.xml @@ -42,7 +42,7 @@ Replaces xml_files/enb_usrp210_band7_test_05mhz_tm1_rrc_inactivity_no_flexran.xm Pull_Local_Registry Pull Images from Local Registry - 0 + hutch oai-enb @@ -178,7 +178,7 @@ Replaces xml_files/enb_usrp210_band7_test_05mhz_tm1_rrc_inactivity_no_flexran.xm Clean_Test_Server_Images true Clean Test Images on Test Server - 0 + hutch oai-enb diff --git a/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1.xml b/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1.xml index 2889101ee8..fc2b933805 100644 --- a/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1.xml +++ b/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1.xml @@ -44,7 +44,7 @@ Replaces xml_files/enb_usrp210_band7_test_10mhz_tm1.xml Pull_Local_Registry Pull Images from Local Registry - 0 + hutch oai-enb @@ -207,7 +207,7 @@ Replaces xml_files/enb_usrp210_band7_test_10mhz_tm1.xml Clean_Test_Server_Images true Clean Test Images on Test Server - 0 + hutch oai-enb diff --git a/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1_cdrx.xml b/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1_cdrx.xml index fb18ce090f..00a3a59d21 100644 --- a/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1_cdrx.xml +++ b/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1_cdrx.xml @@ -43,7 +43,7 @@ Replaces xml_files/enb_usrp210_band7_test_10mhz_tm1.xml Pull_Local_Registry Pull Images from Local Registry - 0 + hutch oai-enb @@ -139,7 +139,7 @@ Replaces xml_files/enb_usrp210_band7_test_10mhz_tm1.xml Clean_Test_Server_Images true Clean Test Images on Test Server - 0 + hutch oai-enb diff --git a/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1_oaiue.xml b/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1_oaiue.xml index 5501ad86fb..9f2f546bcf 100644 --- a/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1_oaiue.xml +++ b/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1_oaiue.xml @@ -49,13 +49,13 @@ Pull_Local_Registry Pull Images from Local Registry - 0 + hutch oai-enb Pull_Local_Registry Pull Images from Local Registry - 1 + carabe oai-lte-ue @@ -191,7 +191,7 @@ Clean_Test_Server_Images true Clean Test Images on eNB Test Server - 0 + hutch oai-enb @@ -199,7 +199,7 @@ Clean_Test_Server_Images true Clean Test Images on LTE-UE Test Server - 1 + carabe oai-lte-ue diff --git a/ci-scripts/xml_files/container_lte_b200_fdd_20Mhz_tm1.xml b/ci-scripts/xml_files/container_lte_b200_fdd_20Mhz_tm1.xml index 3a64107484..cda6ff236d 100644 --- a/ci-scripts/xml_files/container_lte_b200_fdd_20Mhz_tm1.xml +++ b/ci-scripts/xml_files/container_lte_b200_fdd_20Mhz_tm1.xml @@ -43,7 +43,7 @@ Replaces xml_files/enb_usrp210_band7_test_10mhz_tm1.xml Pull_Local_Registry Pull Images from Local Registry - 0 + hutch oai-enb @@ -207,7 +207,7 @@ Replaces xml_files/enb_usrp210_band7_test_10mhz_tm1.xml Clean_Test_Server_Images true Clean Test Images on Test Server - 0 + hutch oai-enb diff --git a/ci-scripts/xml_files/container_lte_b200_tdd_05Mhz_tm1.xml b/ci-scripts/xml_files/container_lte_b200_tdd_05Mhz_tm1.xml index bb6359d636..ae3275f5a6 100644 --- a/ci-scripts/xml_files/container_lte_b200_tdd_05Mhz_tm1.xml +++ b/ci-scripts/xml_files/container_lte_b200_tdd_05Mhz_tm1.xml @@ -43,7 +43,7 @@ Replaces xml_files/enb_usrp210_band40_test_05mhz_tm1.xml Pull_Local_Registry Pull Images from Local Registry - 0 + starsky oai-enb @@ -224,7 +224,7 @@ Replaces xml_files/enb_usrp210_band40_test_05mhz_tm1.xml Clean_Test_Server_Images true Clean Test Images on Test Server - 0 + starsky oai-enb diff --git a/ci-scripts/xml_files/container_lte_b200_tdd_05Mhz_tm1_if4_5.xml b/ci-scripts/xml_files/container_lte_b200_tdd_05Mhz_tm1_if4_5.xml index 0d4d1cae81..4b60443d33 100644 --- a/ci-scripts/xml_files/container_lte_b200_tdd_05Mhz_tm1_if4_5.xml +++ b/ci-scripts/xml_files/container_lte_b200_tdd_05Mhz_tm1_if4_5.xml @@ -41,7 +41,7 @@ Pull_Local_Registry Pull Images from Local Registry - 0 + starsky oai-enb @@ -210,7 +210,7 @@ Clean_Test_Server_Images true Clean Test Images on Test Server - 0 + starsky oai-enb diff --git a/ci-scripts/xml_files/container_lte_b200_tdd_10Mhz_tm1.xml b/ci-scripts/xml_files/container_lte_b200_tdd_10Mhz_tm1.xml index e261a3a057..c89cf5aeb7 100644 --- a/ci-scripts/xml_files/container_lte_b200_tdd_10Mhz_tm1.xml +++ b/ci-scripts/xml_files/container_lte_b200_tdd_10Mhz_tm1.xml @@ -42,7 +42,7 @@ Replaces xml_files/enb_usrp210_band40_test_10mhz_tm1.xml Pull_Local_Registry Pull Images from Local Registry - 0 + starsky oai-enb @@ -215,7 +215,7 @@ Replaces xml_files/enb_usrp210_band40_test_10mhz_tm1.xml Clean_Test_Server_Images true Clean Test Images on Test Server - 0 + starsky oai-enb diff --git a/ci-scripts/xml_files/container_lte_b200_tdd_20Mhz_tm1.xml b/ci-scripts/xml_files/container_lte_b200_tdd_20Mhz_tm1.xml index dd8ef337b8..455a0b3e3a 100644 --- a/ci-scripts/xml_files/container_lte_b200_tdd_20Mhz_tm1.xml +++ b/ci-scripts/xml_files/container_lte_b200_tdd_20Mhz_tm1.xml @@ -42,7 +42,7 @@ Replaces xml_files/enb_usrp210_band40_test_20mhz_tm1.xml Pull_Local_Registry Pull Images from Local Registry - 0 + starsky oai-enb @@ -213,7 +213,7 @@ Replaces xml_files/enb_usrp210_band40_test_20mhz_tm1.xml Clean_Test_Server_Images true Clean Test Images on Test Server - 0 + starsky oai-enb diff --git a/ci-scripts/xml_files/container_lte_b200_tdd_20Mhz_tm1_default_scheduler.xml b/ci-scripts/xml_files/container_lte_b200_tdd_20Mhz_tm1_default_scheduler.xml index 1719ad2691..76a9d3c020 100644 --- a/ci-scripts/xml_files/container_lte_b200_tdd_20Mhz_tm1_default_scheduler.xml +++ b/ci-scripts/xml_files/container_lte_b200_tdd_20Mhz_tm1_default_scheduler.xml @@ -42,7 +42,7 @@ Replaces xml_files/enb_usrp210_band40_test_20mhz_tm1_default_scheduler.xml Pull_Local_Registry Pull Images from Local Registry - 0 + starsky oai-enb @@ -218,7 +218,7 @@ Replaces xml_files/enb_usrp210_band40_test_20mhz_tm1_default_scheduler.xml Clean_Test_Server_Images true Clean Test Images on Test Server - 0 + starsky oai-enb diff --git a/ci-scripts/xml_files/container_lte_n3xx_tdd_2x2_tm1.xml b/ci-scripts/xml_files/container_lte_n3xx_tdd_2x2_tm1.xml index f127601e39..e8d380ffc6 100644 --- a/ci-scripts/xml_files/container_lte_n3xx_tdd_2x2_tm1.xml +++ b/ci-scripts/xml_files/container_lte_n3xx_tdd_2x2_tm1.xml @@ -48,7 +48,7 @@ Pull_Local_Registry Pull Images from Local Registry - 0 + obelix oai-enb @@ -155,7 +155,7 @@ Clean_Test_Server_Images true Clean Test Images - 0 + obelix oai-enb diff --git a/ci-scripts/xml_files/container_lte_n3xx_tdd_2x2_tm2.xml b/ci-scripts/xml_files/container_lte_n3xx_tdd_2x2_tm2.xml index af3299061a..850f9aa954 100644 --- a/ci-scripts/xml_files/container_lte_n3xx_tdd_2x2_tm2.xml +++ b/ci-scripts/xml_files/container_lte_n3xx_tdd_2x2_tm2.xml @@ -48,7 +48,7 @@ Pull_Local_Registry Pull Images from Local Registry - 0 + obelix oai-enb @@ -155,7 +155,7 @@ Clean_Test_Server_Images true Clean Test Images - 0 + obelix oai-enb diff --git a/ci-scripts/xml_files/container_nsa_b200_quectel.xml b/ci-scripts/xml_files/container_nsa_b200_quectel.xml index f72d64a9d4..03d784f8bc 100644 --- a/ci-scripts/xml_files/container_nsa_b200_quectel.xml +++ b/ci-scripts/xml_files/container_nsa_b200_quectel.xml @@ -59,14 +59,14 @@ Pull_Local_Registry Pull Images from Local Registry - 0 + nepes oai-enb Pull_Local_Registry Pull Images from Local Registry - 1 + ofqot oai-gnb @@ -270,7 +270,7 @@ Clean_Test_Server_Images true Clean Test Images on Test Server - 0 + nepes oai-enb @@ -278,7 +278,7 @@ Clean_Test_Server_Images true Clean Test Images on Test Server - 1 + ofqot oai-gnb diff --git a/ci-scripts/xml_files/container_sa_aerial_quectel.xml b/ci-scripts/xml_files/container_sa_aerial_quectel.xml index 89db1ac2bb..ac66f89f59 100644 --- a/ci-scripts/xml_files/container_sa_aerial_quectel.xml +++ b/ci-scripts/xml_files/container_sa_aerial_quectel.xml @@ -52,7 +52,7 @@ Pull_Local_Registry Pull Images from Local Registry - 0 + gracehopper1-oai oai-gnb-aerial arm_ @@ -161,7 +161,7 @@ Clean_Test_Server_Images true Clean Test Images on Test Server - 0 + gracehopper1-oai oai-gnb-aerial diff --git a/ci-scripts/xml_files/container_sa_aw2s_asue.xml b/ci-scripts/xml_files/container_sa_aw2s_asue.xml index 88ab941e31..fa277d710c 100644 --- a/ci-scripts/xml_files/container_sa_aw2s_asue.xml +++ b/ci-scripts/xml_files/container_sa_aw2s_asue.xml @@ -280,7 +280,7 @@ Clean_Test_Server_Images true Clean Test Images on Test Server - 0 + avra oai-gnb-aw2s 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 ed4a219f55..1b435276c1 100644 --- a/ci-scripts/xml_files/container_sa_aw2s_asue_2x2.xml +++ b/ci-scripts/xml_files/container_sa_aw2s_asue_2x2.xml @@ -277,7 +277,7 @@ Clean_Test_Server_Images true Clean Test Images on Test Server - 0 + avra oai-gnb-aw2s diff --git a/ci-scripts/xml_files/container_sa_b200_quectel.xml b/ci-scripts/xml_files/container_sa_b200_quectel.xml index dacee9692f..598ee98b6c 100644 --- a/ci-scripts/xml_files/container_sa_b200_quectel.xml +++ b/ci-scripts/xml_files/container_sa_b200_quectel.xml @@ -59,7 +59,7 @@ Pull_Local_Registry Pull Images from Local Registry - 0 + ofqot oai-gnb @@ -223,7 +223,7 @@ Clean_Test_Server_Images true Clean Test Images on Test Server - 0 + ofqot oai-gnb 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 4fbffbd9e8..8d9b4b996c 100644 --- a/ci-scripts/xml_files/container_sa_e1_b200_quectel.xml +++ b/ci-scripts/xml_files/container_sa_e1_b200_quectel.xml @@ -55,7 +55,7 @@ Pull_Local_Registry Pull Images from Local Registry - 0 + ofqot oai-gnb oai-nr-cuup @@ -226,7 +226,7 @@ Clean_Test_Server_Images true Clean Test Images on Test Server - 0 + ofqot oai-gnb oai-nr-cuup 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 fd935be551..13daf5b90c 100644 --- a/ci-scripts/xml_files/container_sa_f1_b200_quectel.xml +++ b/ci-scripts/xml_files/container_sa_f1_b200_quectel.xml @@ -64,7 +64,7 @@ Pull_Local_Registry Pull Images from Local Registry - 0 + ofqot oai-gnb @@ -256,7 +256,7 @@ Clean_Test_Server_Images true Clean Test Images on Test Server - 0 + ofqot oai-gnb 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 742b09e3d8..280c3ece38 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 @@ -54,7 +54,7 @@ Pull_Local_Registry Pull Images from Local Registry - 0 + cacofonix oai-gnb-fhi72 @@ -155,7 +155,7 @@ Clean_Test_Server_Images true Clean Test Images on Test Server - 0 + cacofonix oai-gnb-fhi72 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 1d7cd323e4..59744e30a8 100644 --- a/ci-scripts/xml_files/container_sa_fhi72_vvdn_up2.xml +++ b/ci-scripts/xml_files/container_sa_fhi72_vvdn_up2.xml @@ -55,7 +55,7 @@ Pull_Local_Registry Pull Images from Local Registry - 0 + cacofonix oai-gnb-fhi72 @@ -165,7 +165,7 @@ Clean_Test_Server_Images true Clean Test Images on Test Server - 0 + cacofonix oai-gnb-fhi72 diff --git a/ci-scripts/xml_files/container_sa_n310_2X2_100MHz_quectel.xml b/ci-scripts/xml_files/container_sa_n310_2X2_100MHz_quectel.xml index 94e97176ff..faf15ce772 100644 --- a/ci-scripts/xml_files/container_sa_n310_2X2_100MHz_quectel.xml +++ b/ci-scripts/xml_files/container_sa_n310_2X2_100MHz_quectel.xml @@ -158,7 +158,7 @@ Clean_Test_Server_Images true Clean Test Images on Test Server - 0 + matix oai-gnb diff --git a/ci-scripts/xml_files/container_sa_n310_2X2_60MHz_quectel.xml b/ci-scripts/xml_files/container_sa_n310_2X2_60MHz_quectel.xml index a701fc5ab9..77f8c3592a 100644 --- a/ci-scripts/xml_files/container_sa_n310_2X2_60MHz_quectel.xml +++ b/ci-scripts/xml_files/container_sa_n310_2X2_60MHz_quectel.xml @@ -158,7 +158,7 @@ Clean_Test_Server_Images true Clean Test Images on Test Server - 0 + matix oai-gnb diff --git a/ci-scripts/xml_files/container_sa_n310_4X4_60MHz_quectel.xml b/ci-scripts/xml_files/container_sa_n310_4X4_60MHz_quectel.xml index 75087fb4a0..ae7202991b 100644 --- a/ci-scripts/xml_files/container_sa_n310_4X4_60MHz_quectel.xml +++ b/ci-scripts/xml_files/container_sa_n310_4X4_60MHz_quectel.xml @@ -158,7 +158,7 @@ Clean_Test_Server_Images true Clean Test Images on Test Server - 0 + matix oai-gnb diff --git a/ci-scripts/xml_files/container_sa_n310_nrue.xml b/ci-scripts/xml_files/container_sa_n310_nrue.xml index da61c8e83f..4a69eebab7 100644 --- a/ci-scripts/xml_files/container_sa_n310_nrue.xml +++ b/ci-scripts/xml_files/container_sa_n310_nrue.xml @@ -175,7 +175,7 @@ Clean_Test_Server_Images true Clean Test Images on Test Server - 0 + avra oai-gnb @@ -183,7 +183,7 @@ Clean_Test_Server_Images true Clean Test Images on Test Server - 1 + caracal oai-nr-ue 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 f116e97e24..92c537bfd2 100644 --- a/ci-scripts/xml_files/container_sa_sc_b200_quectel.xml +++ b/ci-scripts/xml_files/container_sa_sc_b200_quectel.xml @@ -53,7 +53,7 @@ Pull_Local_Registry Pull Images from Local Registry - 0 + ofqot oai-gnb @@ -217,7 +217,7 @@ Clean_Test_Server_Images true Clean Test Images on Test Server - 0 + ofqot oai-gnb From 7839d0660157d9b7382fe9f1f0e1c52134f7a483 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 11 Aug 2025 11:10:17 +0200 Subject: [PATCH 478/964] Create/Deploy/Undeploy(): use node Pass the node name for a host on which to create a workspace or deploy/undeploy. Add a new test for the creation of workspaces. To help myself and the reviewer, here is a list of "eNB_IPAddress"/"eNB1_IPAddress" parameters I copied from the various pipelines: - rfsim 4G eNB_IPAddress none => localhost - rfsim 5g eNB_IPAddress none => localhost - flexric eNB_IPAddress none => localhost - l2sim 4g eNB_IPAddress none => localhost - l2sim 4G eNB1_IPAddress 172.21.16.128 => obelix => localhost - cluster image eNB_IPAddress poseidon - ubuntu18 eNB_IPAddress obelix => obelix - ubuntu-arm eNB_IPAddress gracehopper3-oai => gracehopper3-oai - arm-cross eNB_IPAddress alambix => alambix - lte-tdd eNB_IPAddress 172.21.18.45 => starsky - lte-fdd eNB_IPAddress 172.21.18.46 => hutch - lte-oaiue eNB_IPAddress 172.21.18.46 => hutch - lte-oaiue eNB1_IPAddress 172.21.18.47 => carabe - lte-tdd-2x2 eNB_IPAddress 172.21.16.128 => obelix - nsa eNB_IPAddress 172.21.16.137 => nepes - nsa eNB1_IPAddress 172.21.16.109 => ofqot - sa-aerial eNB_IPAddress gracehopper1-oai => gracehopper1-oai - aw2s eNB_IPAddress 172.21.16.124 => avra - sabox eNB_IPAddress 172.21.16.109 => ofqot - sa-oaiue eNB_IPAddress avra => avra - sa-oaiue eNB1_IPAddress caracal => caracal - cppcheck eNB_IPAddress 172.21.18.47 => carabe - timing-phytest eNB_IPAddress caracal => caracal - physim 4g eNB_IPAddress avra => avra - physim 5g eNB_IPAddress avra => avra --- ci-scripts/cls_containerize.py | 25 +++++------ ci-scripts/main.py | 19 +++------ ci-scripts/tests/deployment.py | 41 +++++++++++-------- ci-scripts/xml_files/cluster_image_build.xml | 1 + .../xml_files/container_4g_l2sim_proxy.xml | 3 +- .../xml_files/container_4g_l2sim_tdd.xml | 16 +++----- .../container_4g_rfsim_fdd_05MHz.xml | 18 +++----- .../container_4g_rfsim_fdd_05MHz_noS1.xml | 12 ++---- .../container_4g_rfsim_fdd_10MHz.xml | 18 +++----- .../container_4g_rfsim_fdd_20MHz.xml | 18 +++----- .../xml_files/container_4g_rfsim_fembms.xml | 12 ++---- .../xml_files/container_4g_rfsim_mbms.xml | 12 ++---- .../container_4g_rfsim_tdd_05MHz.xml | 18 +++----- .../xml_files/container_5g_e1_rfsim.xml | 15 +++---- .../xml_files/container_5g_f1_rfsim.xml | 15 +++---- .../xml_files/container_5g_fdd_rfsim.xml | 12 ++---- .../xml_files/container_5g_flexric_rfsim.xml | 30 +++++--------- ci-scripts/xml_files/container_5g_rfsim.xml | 27 ++++-------- .../xml_files/container_5g_rfsim_24prb.xml | 12 ++---- .../xml_files/container_5g_rfsim_2x2.xml | 12 ++---- .../container_5g_rfsim_fdd_phytest.xml | 14 +++---- .../container_5g_rfsim_fr2_32prb.xml | 14 +++---- .../xml_files/container_5g_rfsim_ntn_geo.xml | 12 ++---- .../xml_files/container_5g_rfsim_ntn_leo.xml | 12 ++---- .../xml_files/container_5g_rfsim_sidelink.xml | 12 ++---- .../xml_files/container_5g_rfsim_tdd_dora.xml | 12 ++---- .../xml_files/container_5g_rfsim_u0_25prb.xml | 12 ++---- .../xml_files/container_image_build.xml | 3 +- .../xml_files/container_image_build_arm.xml | 3 +- .../xml_files/container_image_build_cross.xml | 3 +- .../container_lte_b200_fdd_05Mhz_tm1.xml | 9 ++-- ...container_lte_b200_fdd_05Mhz_tm1_if4_5.xml | 12 ++---- ...lte_b200_fdd_05Mhz_tm1_no_rrc_activity.xml | 9 ++-- .../container_lte_b200_fdd_10Mhz_tm1.xml | 9 ++-- .../container_lte_b200_fdd_10Mhz_tm1_cdrx.xml | 9 ++-- ...container_lte_b200_fdd_10Mhz_tm1_oaiue.xml | 18 +++----- .../container_lte_b200_fdd_20Mhz_tm1.xml | 9 ++-- .../container_lte_b200_tdd_05Mhz_tm1.xml | 9 ++-- ...container_lte_b200_tdd_05Mhz_tm1_if4_5.xml | 12 ++---- .../container_lte_b200_tdd_10Mhz_tm1.xml | 9 ++-- .../container_lte_b200_tdd_20Mhz_tm1.xml | 9 ++-- ...e_b200_tdd_20Mhz_tm1_default_scheduler.xml | 9 ++-- .../container_lte_n3xx_tdd_2x2_tm1.xml | 9 ++-- .../container_lte_n3xx_tdd_2x2_tm2.xml | 9 ++-- .../xml_files/container_nsa_b200_quectel.xml | 18 +++----- .../xml_files/container_sa_aerial_quectel.xml | 12 ++---- .../xml_files/container_sa_aw2s_asue.xml | 9 ++-- .../xml_files/container_sa_aw2s_asue_2x2.xml | 9 ++-- .../xml_files/container_sa_b200_quectel.xml | 9 ++-- .../container_sa_e1_b200_quectel.xml | 15 +++---- .../container_sa_f1_b200_quectel.xml | 12 ++---- .../container_sa_fhi72_metanoia_up2_2x2.xml | 9 ++-- .../xml_files/container_sa_fhi72_vvdn_up2.xml | 9 ++-- .../container_sa_n310_2X2_100MHz_quectel.xml | 9 ++-- .../container_sa_n310_2X2_60MHz_quectel.xml | 9 ++-- .../container_sa_n310_4X4_60MHz_quectel.xml | 9 ++-- .../xml_files/container_sa_n310_nrue.xml | 18 +++----- .../container_sa_sc_b200_quectel.xml | 9 ++-- ci-scripts/xml_files/cppcheck.xml | 1 + ci-scripts/xml_files/gnb_usrp_build.xml | 1 + ci-scripts/xml_files/physim_4g_deploy_run.xml | 3 +- ci-scripts/xml_files/physim_5g_deploy_run.xml | 3 +- 62 files changed, 261 insertions(+), 477 deletions(-) diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index 3af3291c35..8b6b12a4e0 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -736,25 +736,23 @@ class Containerize(): HTML.CreateHtmlTestRowQueue(param, s, [msg]) return status - def Create_Workspace(self,HTML): - svr = self.eNB_serverId[self.eNB_instance] - lIpAddr, lSourcePath = self.GetCredentials(svr) - success = CreateWorkspace(lIpAddr, lSourcePath, self.ranRepository, self.ranCommitID, self.ranTargetBranch, self.ranAllowMerge) + def Create_Workspace(self, node, HTML): + lSourcePath = self.eNBSourceCodePath + success = CreateWorkspace(node, lSourcePath, self.ranRepository, self.ranCommitID, self.ranTargetBranch, self.ranAllowMerge) if success: HTML.CreateHtmlTestRowQueue('N/A', 'OK', [f"created workspace {lSourcePath}"]) else: HTML.CreateHtmlTestRowQueue('N/A', 'KO', ["cannot create workspace"]) return success - def DeployObject(self, ctx, HTML): - svr = self.eNB_serverId[self.eNB_instance] + def DeployObject(self, ctx, node, HTML): num_attempts = self.num_attempts - lIpAddr, lSourcePath = self.GetCredentials(svr) - logging.debug(f'Deploying OAI Object on server: {lIpAddr}') + lSourcePath = self.eNBSourceCodePath + logging.debug(f'Deploying OAI Object on server: {node}') yaml = self.yamlPath[self.eNB_instance].strip('/') wd = f'{lSourcePath}/{yaml}' wd_yaml = f'{wd}/docker-compose.y*ml' - with cls_cmd.getConnection(lIpAddr) as ssh: + with cls_cmd.getConnection(node) as ssh: services = GetServices(ssh, self.services[self.eNB_instance], wd_yaml) if services == [] or services == ' ' or services == None: msg = 'Cannot determine services to start' @@ -790,13 +788,12 @@ class Containerize(): HTML.CreateHtmlTestRowQueue('N/A', 'KO', ['\n'.join(imagesInfo)]) return deployed - def UndeployObject(self, ctx, HTML, RAN): - svr = self.eNB_serverId[self.eNB_instance] - lIpAddr, lSourcePath = self.GetCredentials(svr) - logging.debug(f'\u001B[1m Undeploying OAI Object from server: {lIpAddr}\u001B[0m') + def UndeployObject(self, ctx, node, HTML, RAN): + lSourcePath = self.eNBSourceCodePath + logging.debug(f'\u001B[1m Undeploying OAI Object from server: {node}\u001B[0m') yaml = self.yamlPath[self.eNB_instance].strip('/') wd = f'{lSourcePath}/{yaml}' - with cls_cmd.getConnection(lIpAddr) as ssh: + with cls_cmd.getConnection(node) as ssh: ExistEnvFilePrint(ssh, wd) services = GetRunningServices(ssh, f"{wd}/docker-compose.y*ml") copyin_res = None diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 54f4073eb9..85765de30c 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -305,16 +305,7 @@ def ExecuteActionWithParam(action, ctx): success = core_op(cn_id, ctx, HTML) elif action == 'Deploy_Object' or action == 'Undeploy_Object' or action == "Create_Workspace": - eNB_instance=test.findtext('eNB_instance') - if (eNB_instance is None): - CONTAINERS.eNB_instance=0 - else: - CONTAINERS.eNB_instance=int(eNB_instance) - eNB_serverId=test.findtext('eNB_serverId') - if (eNB_serverId is None): - CONTAINERS.eNB_serverId[CONTAINERS.eNB_instance]='0' - else: - CONTAINERS.eNB_serverId[CONTAINERS.eNB_instance]=eNB_serverId + node = test.findtext('node') string_field = test.findtext('yaml_path') if (string_field is not None): CONTAINERS.yamlPath[CONTAINERS.eNB_instance] = string_field @@ -330,14 +321,14 @@ def ExecuteActionWithParam(action, ctx): CONTAINERS.num_attempts = int(test.findtext('num_attempts') or 1) CONTAINERS.deploymentTag = cls_containerize.CreateTag(CONTAINERS.ranCommitID, CONTAINERS.ranBranch, CONTAINERS.ranAllowMerge) if action == 'Deploy_Object': - success = CONTAINERS.DeployObject(ctx, HTML) + success = CONTAINERS.DeployObject(ctx, node, HTML) elif action == 'Undeploy_Object': - success = CONTAINERS.UndeployObject(ctx, HTML, RAN) + success = CONTAINERS.UndeployObject(ctx, node, HTML, RAN) elif action == 'Create_Workspace': if force_local: # Do not create a working directory when running locally. Current repo directory will be used return True - success = CONTAINERS.Create_Workspace(HTML) + success = CONTAINERS.Create_Workspace(node, HTML) elif action == 'Run_Physim': physim_options = test.findtext('physim_run_args') @@ -360,7 +351,7 @@ def ExecuteActionWithParam(action, ctx): if force_local: # Do not pull or remove images when running locally. User is supposed to handle image creation & cleanup return True - node = test.findtext('node') or 'localhost' + node = test.findtext('node') tag_prefix = test.findtext('tag_prefix') or "" images = test.findtext('images').split() # hack: for FlexRIC, we need to overwrite the tag to use diff --git a/ci-scripts/tests/deployment.py b/ci-scripts/tests/deployment.py index d2fb0cda57..60c88f39a1 100644 --- a/ci-scripts/tests/deployment.py +++ b/ci-scripts/tests/deployment.py @@ -44,12 +44,9 @@ class TestDeploymentMethods(unittest.TestCase): self.cont.ranAllowMerge = True self.cont.ranBranch = '' self.cont.ranCommitID = '' - self.cont.eNB_serverId[0] = '0' - self.cont.eNBIPAddress = 'localhost' - self.cont.eNBUserName = None - self.cont.eNBPassword = None self.cont.eNBSourceCodePath = os.getcwd() self.cont.num_attempts = 3 + self.node = 'localhost' self.ctx = TestCaseCtx.Default(tempfile.mkdtemp()) def tearDown(self): with cls_cmd.LocalCmd() as c: @@ -58,8 +55,8 @@ class TestDeploymentMethods(unittest.TestCase): def test_deploy(self): self.cont.yamlPath[0] = 'tests/simple-dep/' self.cont.deploymentTag = "noble" - deploy = self.cont.DeployObject(self.ctx, self.html) - undeploy = self.cont.UndeployObject(self.ctx, self.html, self.ran) + deploy = self.cont.DeployObject(self.ctx, self.node, self.html) + undeploy = self.cont.UndeployObject(self.ctx, self.node, self.html, self.ran) self.assertTrue(deploy) self.assertTrue(undeploy) @@ -67,8 +64,8 @@ class TestDeploymentMethods(unittest.TestCase): # fails reliably old = self.cont.yamlPath self.cont.yamlPath[0] = 'tests/simple-fail/' - deploy = self.cont.DeployObject(self.ctx, self.html) - self.cont.UndeployObject(self.ctx, self.html, self.ran) + deploy = self.cont.DeployObject(self.ctx, self.node, self.html) + self.cont.UndeployObject(self.ctx, self.node, self.html, self.ran) self.assertFalse(deploy) self.cont.yamlPath = old @@ -76,8 +73,8 @@ class TestDeploymentMethods(unittest.TestCase): # fails reliably old = self.cont.yamlPath self.cont.yamlPath[0] = 'tests/simple-fail-2svc/' - deploy = self.cont.DeployObject(self.ctx, self.html) - self.cont.UndeployObject(self.ctx, self.html, self.ran) + deploy = self.cont.DeployObject(self.ctx, self.node, self.html) + self.cont.UndeployObject(self.ctx, self.node, self.html, self.ran) self.assertFalse(deploy) self.cont.yamlPath = old @@ -85,8 +82,8 @@ class TestDeploymentMethods(unittest.TestCase): self.cont.yamlPath[0] = 'yaml_files/5g_rfsimulator_tdd_dora' self.cont.services[0] = "oai-gnb" self.cont.deploymentTag = 'develop-12345678' - deploy = self.cont.DeployObject(self.ctx, self.html) - undeploy = self.cont.UndeployObject(self.ctx, self.html, self.ran) + deploy = self.cont.DeployObject(self.ctx, self.node, self.html) + undeploy = self.cont.UndeployObject(self.ctx, self.node, self.html, self.ran) self.assertTrue(deploy) self.assertTrue(undeploy) @@ -94,8 +91,8 @@ class TestDeploymentMethods(unittest.TestCase): self.cont.yamlPath[0] = 'yaml_files/5g_rfsimulator_tdd_dora' self.cont.services[0] = "oai-gnb oai-nr-ue" self.cont.deploymentTag = 'develop-12345678' - deploy = self.cont.DeployObject(self.ctx, self.html) - undeploy = self.cont.UndeployObject(self.ctx, self.html, self.ran) + deploy = self.cont.DeployObject(self.ctx, self.node, self.html) + undeploy = self.cont.UndeployObject(self.ctx, self.node, self.html, self.ran) self.assertTrue(deploy) self.assertTrue(undeploy) @@ -103,13 +100,23 @@ class TestDeploymentMethods(unittest.TestCase): self.cont.yamlPath[0] = 'yaml_files/5g_rfsimulator_tdd_dora' self.cont.services[0] = "oai-gnb" self.cont.deploymentTag = 'develop-12345678' - deploy1 = self.cont.DeployObject(self.ctx, self.html) + deploy1 = self.cont.DeployObject(self.ctx, self.node, self.html) self.cont.services[0] = "oai-nr-ue" - deploy2 = self.cont.DeployObject(self.ctx, self.html) - undeploy = self.cont.UndeployObject(self.ctx, self.html, self.ran) + deploy2 = self.cont.DeployObject(self.ctx, self.node, self.html) + undeploy = self.cont.UndeployObject(self.ctx, self.node, self.html, self.ran) self.assertTrue(deploy1) self.assertTrue(deploy2) self.assertTrue(undeploy) + def test_create_workspace(self): + self.cont.eNBSourceCodePath = tempfile.mkdtemp() + self.cont.ranRepository = "https://gitlab.eurecom.fr/oai/openairinterface5g.git" + self.cont.ranCommitID = "05f9c975eeecbca1bdff5940affad44465f1301f" + self.cont.ranBranch = "develop" + ws = self.cont.Create_Workspace(self.node, self.html) + with cls_cmd.LocalCmd() as cmd: + cmd.run(f"rm -rf {self.cont.eNBSourceCodePath}") + self.assertTrue(ws) + if __name__ == '__main__': unittest.main() diff --git a/ci-scripts/xml_files/cluster_image_build.xml b/ci-scripts/xml_files/cluster_image_build.xml index 6810873b1c..b8462a4ebd 100644 --- a/ci-scripts/xml_files/cluster_image_build.xml +++ b/ci-scripts/xml_files/cluster_image_build.xml @@ -32,6 +32,7 @@ Create_Workspace Create new Workspace + poseidon Build_Cluster_Image diff --git a/ci-scripts/xml_files/container_4g_l2sim_proxy.xml b/ci-scripts/xml_files/container_4g_l2sim_proxy.xml index cd57a24b6a..4e65928147 100644 --- a/ci-scripts/xml_files/container_4g_l2sim_proxy.xml +++ b/ci-scripts/xml_files/container_4g_l2sim_proxy.xml @@ -32,8 +32,7 @@ Create_Workspace Create new Workspace - 1 - 1 + localhost Build_Proxy diff --git a/ci-scripts/xml_files/container_4g_l2sim_tdd.xml b/ci-scripts/xml_files/container_4g_l2sim_tdd.xml index 43334c0f91..eabece50cd 100644 --- a/ci-scripts/xml_files/container_4g_l2sim_tdd.xml +++ b/ci-scripts/xml_files/container_4g_l2sim_tdd.xml @@ -50,43 +50,38 @@ Create_Workspace Create new Workspace - 0 - 0 + localhost Deploy_Object Deploy Cassandra Database + localhost ci-scripts/yaml_files/4g_l2sim_fdd cassandra db_init - 0 - 0 Deploy_Object Deploy OAI 4G CoreNetwork + localhost ci-scripts/yaml_files/4g_l2sim_fdd oai_hss redis magma_mme oai_spgwc oai_spgwu trf_gen - 0 - 0 Deploy_Object Deploy OAI 4G eNB L2 sim + localhost ci-scripts/yaml_files/4g_l2sim_fdd oai_enb - 0 - 0 Deploy_Object Deploy OAI L2 sim 4G LTE-UE 1 and Proxy + localhost ci-scripts/yaml_files/4g_l2sim_fdd proxy oai_ue1 - 0 - 0 @@ -145,6 +140,7 @@ Undeploy_Object true + localhost Undeploy all OAI 4G stack ci-scripts/yaml_files/4g_l2sim_fdd diff --git a/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz.xml b/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz.xml index 2f59fe3d7b..4b93c10fcd 100644 --- a/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz.xml +++ b/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz.xml @@ -46,8 +46,7 @@ Create_Workspace Create new Workspace - 0 - 0 + localhost Pull_Local_Registry @@ -59,10 +58,9 @@ Deploy_Object Deploy Cassandra Database + localhost ci-scripts/yaml_files/4g_rfsimulator_fdd_05MHz cassandra db_init - 0 - 0 @@ -80,28 +78,25 @@ Deploy_Object Deploy OAI 4G CoreNetwork + localhost ci-scripts/yaml_files/4g_rfsimulator_fdd_05MHz oai_hss redis magma_mme oai_spgwc oai_spgwu trf_gen - 0 - 0 Deploy_Object Deploy OAI 4G eNB RF sim (FDD 05MHz) + localhost ci-scripts/yaml_files/4g_rfsimulator_fdd_05MHz oai_enb0 - 0 - 0 Deploy_Object Deploy OAI 4G LTE-UE RF sim (FDD 05MHz) + localhost ci-scripts/yaml_files/4g_rfsimulator_fdd_05MHz oai_ue0 - 0 - 0 @@ -161,9 +156,8 @@ Undeploy_Object true Undeploy all OAI 4G stack + localhost ci-scripts/yaml_files/4g_rfsimulator_fdd_05MHz - 0 - 0 diff --git a/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz_noS1.xml b/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz_noS1.xml index d78b926a00..968e30071a 100644 --- a/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz_noS1.xml +++ b/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz_noS1.xml @@ -49,8 +49,7 @@ Create_Workspace Create new Workspace - 0 - 0 + localhost IdleSleep @@ -67,19 +66,17 @@ Deploy_Object Deploy OAI 4G eNB RF sim (FDD 05MHz) + localhost ci-scripts/yaml_files/4g_rfsimulator_fdd_05MHz_noS1 oai_enb0 - 0 - 0 Deploy_Object Deploy OAI 4G LTE-UE RF sim (FDD 05MHz) + localhost ci-scripts/yaml_files/4g_rfsimulator_fdd_05MHz_noS1 oai_ue0 - 0 - 0 @@ -132,9 +129,8 @@ Undeploy_Object true Undeploy all OAI 4G stack + localhost ci-scripts/yaml_files/4g_rfsimulator_fdd_05MHz_noS1 - 0 - 0 diff --git a/ci-scripts/xml_files/container_4g_rfsim_fdd_10MHz.xml b/ci-scripts/xml_files/container_4g_rfsim_fdd_10MHz.xml index c1a3b5ff6e..076ee6995b 100644 --- a/ci-scripts/xml_files/container_4g_rfsim_fdd_10MHz.xml +++ b/ci-scripts/xml_files/container_4g_rfsim_fdd_10MHz.xml @@ -53,16 +53,14 @@ Create_Workspace Create new Workspace - 0 - 0 + localhost Deploy_Object Deploy Cassandra Database + localhost ci-scripts/yaml_files/4g_rfsimulator_fdd_10MHz cassandra db_init - 0 - 0 @@ -80,28 +78,25 @@ Deploy_Object Deploy OAI 4G CoreNetwork + localhost ci-scripts/yaml_files/4g_rfsimulator_fdd_10MHz oai_hss redis magma_mme oai_spgwc oai_spgwu trf_gen - 0 - 0 Deploy_Object Deploy OAI 4G eNB RF sim (FDD 10MHz) + localhost ci-scripts/yaml_files/4g_rfsimulator_fdd_10MHz oai_enb0 - 0 - 0 Deploy_Object Deploy OAI 4G LTE-UE RF sim (FDD 10MHz) + localhost ci-scripts/yaml_files/4g_rfsimulator_fdd_10MHz oai_ue0 - 0 - 0 @@ -161,9 +156,8 @@ Undeploy_Object true Undeploy all OAI 4G stack + localhost ci-scripts/yaml_files/4g_rfsimulator_fdd_10MHz - 0 - 0 diff --git a/ci-scripts/xml_files/container_4g_rfsim_fdd_20MHz.xml b/ci-scripts/xml_files/container_4g_rfsim_fdd_20MHz.xml index 7c2622fed5..2e049e4efe 100644 --- a/ci-scripts/xml_files/container_4g_rfsim_fdd_20MHz.xml +++ b/ci-scripts/xml_files/container_4g_rfsim_fdd_20MHz.xml @@ -53,16 +53,14 @@ Create_Workspace Create new Workspace - 0 - 0 + localhost Deploy_Object Deploy Cassandra Database + localhost ci-scripts/yaml_files/4g_rfsimulator_fdd_20MHz cassandra db_init - 0 - 0 @@ -80,28 +78,25 @@ Deploy_Object Deploy OAI 4G CoreNetwork + localhost ci-scripts/yaml_files/4g_rfsimulator_fdd_20MHz oai_hss redis magma_mme oai_spgwc oai_spgwu trf_gen - 0 - 0 Deploy_Object Deploy OAI 4G eNB RF sim (FDD 20MHz) + localhost ci-scripts/yaml_files/4g_rfsimulator_fdd_20MHz oai_enb0 - 0 - 0 Deploy_Object Deploy OAI 4G LTE-UE RF sim (FDD 20MHz) + localhost ci-scripts/yaml_files/4g_rfsimulator_fdd_20MHz oai_ue0 - 0 - 0 @@ -161,9 +156,8 @@ Undeploy_Object true Undeploy all OAI 4G stack + localhost ci-scripts/yaml_files/4g_rfsimulator_fdd_20MHz - 0 - 0 diff --git a/ci-scripts/xml_files/container_4g_rfsim_fembms.xml b/ci-scripts/xml_files/container_4g_rfsim_fembms.xml index 51cef07627..7ab434c804 100644 --- a/ci-scripts/xml_files/container_4g_rfsim_fembms.xml +++ b/ci-scripts/xml_files/container_4g_rfsim_fembms.xml @@ -46,8 +46,7 @@ Create_Workspace Create new Workspace - 0 - 0 + localhost IdleSleep @@ -64,19 +63,17 @@ Deploy_Object Deploy OAI 4G eNB RF sim (FeMBMS) + localhost ci-scripts/yaml_files/4g_rfsimulator_fembms oai_enb0 - 0 - 0 Deploy_Object Deploy OAI 4G LTE-UE RF sim (FeMBMS) + localhost ci-scripts/yaml_files/4g_rfsimulator_fembms oai_ue0 - 0 - 0 @@ -95,9 +92,8 @@ Undeploy_Object true Undeploy all OAI 4G stack + localhost ci-scripts/yaml_files/4g_rfsimulator_fembms - 0 - 0 diff --git a/ci-scripts/xml_files/container_4g_rfsim_mbms.xml b/ci-scripts/xml_files/container_4g_rfsim_mbms.xml index 621d3e121e..e6a4cde19a 100644 --- a/ci-scripts/xml_files/container_4g_rfsim_mbms.xml +++ b/ci-scripts/xml_files/container_4g_rfsim_mbms.xml @@ -46,8 +46,7 @@ Create_Workspace Create new Workspace - 0 - 0 + localhost IdleSleep @@ -64,19 +63,17 @@ Deploy_Object Deploy OAI 4G eNB RF sim (MBMS) + localhost ci-scripts/yaml_files/4g_rfsimulator_mbms oai_enb0 - 0 - 0 Deploy_Object Deploy OAI 4G LTE-UE RF sim (MBMS) + localhost ci-scripts/yaml_files/4g_rfsimulator_mbms oai_ue0 - 0 - 0 @@ -95,9 +92,8 @@ Undeploy_Object true Undeploy all OAI 4G stack + localhost ci-scripts/yaml_files/4g_rfsimulator_mbms - 0 - 0 diff --git a/ci-scripts/xml_files/container_4g_rfsim_tdd_05MHz.xml b/ci-scripts/xml_files/container_4g_rfsim_tdd_05MHz.xml index bc0e4f23d6..2e22577879 100644 --- a/ci-scripts/xml_files/container_4g_rfsim_tdd_05MHz.xml +++ b/ci-scripts/xml_files/container_4g_rfsim_tdd_05MHz.xml @@ -53,16 +53,14 @@ Create_Workspace Create new Workspace - 0 - 0 + localhost Deploy_Object Deploy Cassandra Database + localhost ci-scripts/yaml_files/4g_rfsimulator_tdd_05MHz cassandra db_init - 0 - 0 @@ -80,28 +78,25 @@ Deploy_Object Deploy OAI 4G CoreNetwork + localhost ci-scripts/yaml_files/4g_rfsimulator_tdd_05MHz oai_hss oai_mme oai_spgwc oai_spgwu trf_gen - 0 - 0 Deploy_Object Deploy OAI 4G eNB RF sim (TDD 05MHz) + localhost ci-scripts/yaml_files/4g_rfsimulator_tdd_05MHz oai_enb0 - 0 - 0 Deploy_Object Deploy OAI 4G LTE-UE RF sim (TDD 05MHz) + localhost ci-scripts/yaml_files/4g_rfsimulator_tdd_05MHz oai_ue0 - 0 - 0 @@ -154,9 +149,8 @@ Undeploy_Object true Undeploy all OAI 4G stack + localhost ci-scripts/yaml_files/4g_rfsimulator_tdd_05MHz - 0 - 0 diff --git a/ci-scripts/xml_files/container_5g_e1_rfsim.xml b/ci-scripts/xml_files/container_5g_e1_rfsim.xml index 50de456cdb..d27091ac63 100644 --- a/ci-scripts/xml_files/container_5g_e1_rfsim.xml +++ b/ci-scripts/xml_files/container_5g_e1_rfsim.xml @@ -46,34 +46,30 @@ Create_Workspace Create new Workspace - 0 - 0 + localhost Deploy_Object Deploy OAI 5G CoreNetwork + localhost ci-scripts/yaml_files/5g_rfsimulator_e1 mysql oai-amf oai-smf oai-upf - 0 - 0 Deploy_Object Deploy OAI 5G RAN RF sim SA (1 CU-CP, 3 CU-UPs, 3 DUs) + localhost ci-scripts/yaml_files/5g_rfsimulator_e1 oai-cucp oai-cuup oai-cuup2 oai-cuup3 oai-du oai-du2 oai-du3 - 0 - 0 Deploy_Object Deploy OAI 5G NR-UE RF sim SA + localhost ci-scripts/yaml_files/5g_rfsimulator_e1 oai-nr-ue oai-nr-ue2 oai-nr-ue3 - 0 - 0 @@ -97,12 +93,11 @@ Undeploy_Object true + localhost Undeploy all OAI 5G stack ci-scripts/yaml_files/5g_rfsimulator_e1 1,0,0,0 1,0,0,0 - 0 - 0 diff --git a/ci-scripts/xml_files/container_5g_f1_rfsim.xml b/ci-scripts/xml_files/container_5g_f1_rfsim.xml index af0a9164db..efe8fce8e2 100644 --- a/ci-scripts/xml_files/container_5g_f1_rfsim.xml +++ b/ci-scripts/xml_files/container_5g_f1_rfsim.xml @@ -69,25 +69,22 @@ Create_Workspace Create new Workspace - 0 - 0 + localhost Deploy_Object Deploy OAI 5G CoreNetwork + localhost ci-scripts/yaml_files/5g_f1_rfsimulator mysql oai-amf oai-smf oai-upf oai-ext-dn - 0 - 0 Deploy_Object Deploy OAI 5G CU + DU-PCI0 + UE RF sim SA + localhost ci-scripts/yaml_files/5g_f1_rfsimulator oai-cu oai-du-pci0 oai-nr-ue - 0 - 0 @@ -112,10 +109,9 @@ Deploy_Object Deploy OAI 5G (target) DU-PCI1 RF sim SA + localhost ci-scripts/yaml_files/5g_f1_rfsimulator oai-du-pci1 - 0 - 0 @@ -238,11 +234,10 @@ Undeploy_Object true Undeploy all OAI 5G stack + localhost ci-scripts/yaml_files/5g_f1_rfsimulator 30,100,100,100 30,100,100,100 - 0 - 0 diff --git a/ci-scripts/xml_files/container_5g_fdd_rfsim.xml b/ci-scripts/xml_files/container_5g_fdd_rfsim.xml index 99814fbc09..6ce1e37b90 100644 --- a/ci-scripts/xml_files/container_5g_fdd_rfsim.xml +++ b/ci-scripts/xml_files/container_5g_fdd_rfsim.xml @@ -48,25 +48,22 @@ Create_Workspace Create new Workspace - 0 - 0 + localhost Deploy_Object Deploy OAI 5G CoreNetwork + localhost ci-scripts/yaml_files/5g_fdd_rfsimulator mysql oai-amf oai-smf oai-upf oai-ext-dn - 0 - 0 Deploy_Object Deploy OAI 5G gNB+UE RF sim SA + localhost ci-scripts/yaml_files/5g_fdd_rfsimulator oai-gnb oai-nr-ue - 0 - 0 @@ -126,11 +123,10 @@ Undeploy_Object true Undeploy all OAI 5G stack + localhost ci-scripts/yaml_files/5g_fdd_rfsimulator 1,0,0,0 1,0,0,0 - 0 - 0 diff --git a/ci-scripts/xml_files/container_5g_flexric_rfsim.xml b/ci-scripts/xml_files/container_5g_flexric_rfsim.xml index d360645cbb..8ee9326b5e 100644 --- a/ci-scripts/xml_files/container_5g_flexric_rfsim.xml +++ b/ci-scripts/xml_files/container_5g_flexric_rfsim.xml @@ -88,37 +88,33 @@ Deploy_Object Deploy OAI 5G CoreNetwork + localhost doc/tutorial_resources/oai-cn5g mysql oai-nrf oai-udr oai-udm oai-ausf oai-amf oai-smf oai-upf oai-ext-dn - 0 - 0 Deploy_Object Deploy OAI FlexRIC + localhost ci-scripts/yaml_files/5g_rfsimulator_flexric oai-flexric - 0 - 0 Deploy_Object Deploy OAI 5G gNB in RF sim SA + localhost ci-scripts/yaml_files/5g_rfsimulator_flexric oai-gnb - 0 - 0 Deploy_Object Deploy 2 OAI 5G NR-UEs in RF sim SA + localhost ci-scripts/yaml_files/5g_rfsimulator_flexric oai-nr-ue oai-nr-ue2 - 0 - 0 @@ -149,55 +145,49 @@ Undeploy_Object Undeploy Core Network + localhost doc/tutorial_resources/oai-cn5g - 0 - 0 true Undeploy_Object Undeploy RAN and Flexric + localhost ci-scripts/yaml_files/5g_rfsimulator_flexric - 0 - 0 true Deploy_Object RC monitoring + localhost ci-scripts/yaml_files/5g_rfsimulator_flexric xapp-rc-moni - 0 - 0 Deploy_Object KPM monitoring + localhost ci-scripts/yaml_files/5g_rfsimulator_flexric xapp-kpm-moni - 0 - 0 Deploy_Object KPM monitoring and RC control + localhost ci-scripts/yaml_files/5g_rfsimulator_flexric xapp-kpm-rc - 0 - 0 Deploy_Object Custom SMs monitoring + localhost ci-scripts/yaml_files/5g_rfsimulator_flexric xapp-gtp-mac-rlc-pdcp-moni - 0 - 0 diff --git a/ci-scripts/xml_files/container_5g_rfsim.xml b/ci-scripts/xml_files/container_5g_rfsim.xml index 8265e712c0..d7fb38ef8f 100644 --- a/ci-scripts/xml_files/container_5g_rfsim.xml +++ b/ci-scripts/xml_files/container_5g_rfsim.xml @@ -63,70 +63,62 @@ Create_Workspace Create new Workspace - 0 - 0 + localhost Deploy_Object Deploy OAI 5G CoreNetwork + localhost ci-scripts/yaml_files/5g_rfsimulator mysql oai-amf oai-smf oai-upf oai-ext-dn - 0 - 0 Deploy_Object Deploy OAI 5G gNB RF sim SA + localhost ci-scripts/yaml_files/5g_rfsimulator oai-gnb - 0 - 0 Deploy_Object Deploy OAI 5G NR-UE RF sim SA + localhost ci-scripts/yaml_files/5g_rfsimulator oai-nr-ue - 0 - 0 Deploy_Object Deploy Second OAI 5G NR-UE RF sim SA + localhost ci-scripts/yaml_files/5g_rfsimulator oai-nr-ue2 - 0 - 0 Deploy_Object Deploy OAI 5G NR-UEs (#3, #4, #5) RF sim SA + localhost ci-scripts/yaml_files/5g_rfsimulator oai-nr-ue3 oai-nr-ue4 oai-nr-ue5 - 0 - 0 Deploy_Object Deploy OAI 5G NR-UEs (#6, #7, #8) RF sim SA + localhost ci-scripts/yaml_files/5g_rfsimulator oai-nr-ue6 oai-nr-ue7 oai-nr-ue8 - 0 - 0 Deploy_Object Deploy OAI 5G NR-UEs (#9, #10) RF sim SA + localhost ci-scripts/yaml_files/5g_rfsimulator oai-nr-ue9 oai-nr-ue10 - 0 - 0 @@ -251,11 +243,10 @@ Undeploy_Object true Undeploy all OAI 5G stack + localhost ci-scripts/yaml_files/5g_rfsimulator 1,0,0,0 1,0,0,0 - 0 - 0 diff --git a/ci-scripts/xml_files/container_5g_rfsim_24prb.xml b/ci-scripts/xml_files/container_5g_rfsim_24prb.xml index c74579d87b..7db37d8e63 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_24prb.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_24prb.xml @@ -66,25 +66,22 @@ Create_Workspace Create new Workspace - 0 - 0 + localhost Deploy_Object Deploy OAI 5G CoreNetwork + localhost ci-scripts/yaml_files/5g_rfsimulator_24prb mysql oai-amf oai-smf oai-upf oai-ext-dn - 0 - 0 Deploy_Object Deploy OAI 5G gNB+UE RFsim SA + localhost ci-scripts/yaml_files/5g_rfsimulator_24prb oai-gnb oai-nr-ue - 0 - 0 @@ -164,9 +161,8 @@ Undeploy_Object true Undeploy all OAI 5G stack + localhost ci-scripts/yaml_files/5g_rfsimulator_24prb - 0 - 0 diff --git a/ci-scripts/xml_files/container_5g_rfsim_2x2.xml b/ci-scripts/xml_files/container_5g_rfsim_2x2.xml index 9b5316aea6..75924e1ca2 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_2x2.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_2x2.xml @@ -48,25 +48,22 @@ Create_Workspace Create new Workspace - 0 - 0 + localhost Deploy_Object Deploy OAI 5G CoreNetwork + localhost ci-scripts/yaml_files/5g_rfsimulator_2x2 mysql oai-amf oai-smf oai-upf oai-ext-dn - 0 - 0 Deploy_Object Deploy OAI 5G gNB+UE RF sim SA + localhost ci-scripts/yaml_files/5g_rfsimulator_2x2 oai-gnb oai-nr-ue - 0 - 0 @@ -126,9 +123,8 @@ Undeploy_Object true Undeploy all OAI 5G stack + localhost ci-scripts/yaml_files/5g_rfsimulator_2x2 - 0 - 0 1,0,0,0 1,0,0,0 diff --git a/ci-scripts/xml_files/container_5g_rfsim_fdd_phytest.xml b/ci-scripts/xml_files/container_5g_rfsim_fdd_phytest.xml index 03afaff6d1..b376df99f4 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_fdd_phytest.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_fdd_phytest.xml @@ -55,25 +55,22 @@ Create_Workspace Create new Workspace - 0 - 0 + localhost Deploy_Object Deploy OAI 5G gNB RF sim SA + localhost ci-scripts/yaml_files/5g_rfsimulator_fdd_phytest oai-gnb - 0 - 0 Deploy_Object Deploy OAI 5G NR-UE RF sim SA + localhost ci-scripts/yaml_files/5g_rfsimulator_fdd_phytest oai-nr-ue - 0 - 0 @@ -126,18 +123,17 @@ Undeploy_Object true Undeploy all OAI 5G stack + localhost ci-scripts/yaml_files/5g_rfsimulator_fdd_phytest 10,100,100,100 10,100,100,100 - 0 - 0 Clean_Test_Server_Images true Clean Test Images on Test Server - acamas + localhost oai-gnb-asan oai-nr-ue-asan diff --git a/ci-scripts/xml_files/container_5g_rfsim_fr2_32prb.xml b/ci-scripts/xml_files/container_5g_rfsim_fr2_32prb.xml index 6261fed596..6a47da0ff9 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_fr2_32prb.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_fr2_32prb.xml @@ -40,33 +40,30 @@ Pull_Local_Registry Pull Images from Local Registry - acamas + localhost oai-gnb-asan oai-nr-ue-asan Create_Workspace Create new Workspace - 0 - 0 + localhost Deploy_Object Deploy OAI gNB + localhost ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb mysql oai-amf oai-smf oai-upf oai-ext-dn - 0 - 0 Deploy_Object Deploy OAI NR-UE + localhost ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb oai-gnb oai-nr-ue - 0 - 0 @@ -102,11 +99,10 @@ Undeploy_Object true Undeploy all OAI 5G stack + localhost ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb 10,0,0,0 10,0,0,0 - 0 - 0 diff --git a/ci-scripts/xml_files/container_5g_rfsim_ntn_geo.xml b/ci-scripts/xml_files/container_5g_rfsim_ntn_geo.xml index 4da64a8788..7107b7971b 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_ntn_geo.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_ntn_geo.xml @@ -52,25 +52,22 @@ Create_Workspace Create new Workspace - 0 - 0 + localhost Deploy_Object Deploy OAI 5G CoreNetwork + localhost ci-scripts/yaml_files/5g_rfsimulator_ntn_geo mysql oai-amf oai-smf oai-upf oai-ext-dn - 0 - 0 Deploy_Object Deploy OAI 5G gNB+nrUE RF sim SA + localhost ci-scripts/yaml_files/5g_rfsimulator_ntn_geo oai-gnb oai-nr-ue - 0 - 0 @@ -133,9 +130,8 @@ Undeploy_Object true Undeploy all OAI 5G stack + localhost ci-scripts/yaml_files/5g_rfsimulator_ntn_geo - 0 - 0 diff --git a/ci-scripts/xml_files/container_5g_rfsim_ntn_leo.xml b/ci-scripts/xml_files/container_5g_rfsim_ntn_leo.xml index 89ff56d9fb..63897cfb8b 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_ntn_leo.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_ntn_leo.xml @@ -47,25 +47,22 @@ Create_Workspace Create new Workspace - 0 - 0 + localhost Deploy_Object Deploy OAI 5G CoreNetwork + localhost ci-scripts/yaml_files/5g_rfsimulator_ntn_leo mysql oai-amf oai-smf oai-upf oai-ext-dn - 0 - 0 Deploy_Object Deploy OAI 5G gNB+nrUE RF sim SA + localhost ci-scripts/yaml_files/5g_rfsimulator_ntn_leo oai-gnb oai-nr-ue - 0 - 0 @@ -101,9 +98,8 @@ Undeploy_Object true Undeploy all OAI 5G stack + localhost ci-scripts/yaml_files/5g_rfsimulator_ntn_leo - 0 - 0 diff --git a/ci-scripts/xml_files/container_5g_rfsim_sidelink.xml b/ci-scripts/xml_files/container_5g_rfsim_sidelink.xml index 9a57d49870..58bff964d4 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_sidelink.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_sidelink.xml @@ -46,26 +46,23 @@ Create_Workspace Create new Workspace - 0 - 0 + localhost Deploy_Object Deploy OAI 5G UE 1 + localhost ci-scripts/yaml_files/5g_rfsimulator_sidelink oai-nr-ue-1 - 0 - 0 Deploy_Object Deploy OAI 5G UE 2 + localhost ci-scripts/yaml_files/5g_rfsimulator_sidelink oai-nr-ue-2 - 0 - 0 @@ -85,11 +82,10 @@ Undeploy_Object true Undeploy all OAI 5G stack + localhost ci-scripts/yaml_files/5g_rfsimulator_sidelink 1,0,0,0 1,0,0,0 - 0 - 0 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 4d36ccec80..97730bd233 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_tdd_dora.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_tdd_dora.xml @@ -55,25 +55,22 @@ Create_Workspace Create new Workspace - 0 - 0 + localhost Deploy_Object Deploy OAI gNB + localhost ci-scripts/yaml_files/5g_rfsimulator_tdd_dora oai-gnb - 0 - 0 Deploy_Object Deploy OAI NR-UE + localhost ci-scripts/yaml_files/5g_rfsimulator_tdd_dora oai-nr-ue - 0 - 0 @@ -108,11 +105,10 @@ Undeploy_Object true Undeploy all OAI 5G stack + localhost ci-scripts/yaml_files/5g_rfsimulator_tdd_dora 0,0,0,0 0,0,0,0 - 0 - 0 diff --git a/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml b/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml index a7a7df3a35..c5c76124d3 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml @@ -50,25 +50,22 @@ Create_Workspace Create new Workspace - 0 - 0 + localhost Deploy_Object Deploy OAI 5G CoreNetwork + localhost ci-scripts/yaml_files/5g_rfsimulator_u0_25prb mysql oai-amf oai-smf oai-upf oai-ext-dn - 0 - 0 Deploy_Object Deploy OAI 5G VNF+PNF+nrUE RF sim SA + localhost ci-scripts/yaml_files/5g_rfsimulator_u0_25prb oai-vnf oai-pnf oai-nr-ue - 0 - 0 @@ -146,12 +143,11 @@ Undeploy_Object true Undeploy all OAI 5G stack + localhost oai-vnf oai-pnf ci-scripts/yaml_files/5g_rfsimulator_u0_25prb 1,0,0,0 1,0,0,0 - 0 - 0 diff --git a/ci-scripts/xml_files/container_image_build.xml b/ci-scripts/xml_files/container_image_build.xml index 7db63e4281..215ae2a2cb 100644 --- a/ci-scripts/xml_files/container_image_build.xml +++ b/ci-scripts/xml_files/container_image_build.xml @@ -34,8 +34,7 @@ Create_Workspace Create new Workspace for server 0 - 0 - 0 + obelix Build_Image diff --git a/ci-scripts/xml_files/container_image_build_arm.xml b/ci-scripts/xml_files/container_image_build_arm.xml index 722d23ddcf..2287c51b86 100644 --- a/ci-scripts/xml_files/container_image_build_arm.xml +++ b/ci-scripts/xml_files/container_image_build_arm.xml @@ -34,8 +34,7 @@ Create_Workspace Create new Workspace for server 0 - 0 - 0 + gracehopper3-oai Build_Image diff --git a/ci-scripts/xml_files/container_image_build_cross.xml b/ci-scripts/xml_files/container_image_build_cross.xml index 046ceb5413..c47253662b 100644 --- a/ci-scripts/xml_files/container_image_build_cross.xml +++ b/ci-scripts/xml_files/container_image_build_cross.xml @@ -32,8 +32,7 @@ Create_Workspace Create new Workspace - 0 - 0 + alambix Build_Image diff --git a/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1.xml b/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1.xml index 376c26400a..10ab1fd3b0 100644 --- a/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1.xml +++ b/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1.xml @@ -69,15 +69,13 @@ Replaces xml_files/enb_usrp210_band7_test_05mhz_tm1.xml Create_Workspace Create new Workspace for server 0 - 0 - 0 + hutch Deploy_Object Deploy eNB (FDD/Band7/5MHz/B200) in a container + hutch ci-scripts/yaml_files/lte_b200_fdd_05Mhz_tm1 - 0 - 0 @@ -90,9 +88,8 @@ Replaces xml_files/enb_usrp210_band7_test_05mhz_tm1.xml Undeploy_Object true Undeploy eNB + hutch ci-scripts/yaml_files/lte_b200_fdd_05Mhz_tm1 - 0 - 0 diff --git a/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1_if4_5.xml b/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1_if4_5.xml index e37e1ca812..ebc59e746d 100644 --- a/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1_if4_5.xml +++ b/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1_if4_5.xml @@ -68,24 +68,21 @@ Create_Workspace Create new Workspace for server 0 - 0 - 0 + hutch Deploy_Object Deploy RRU (FDD/Band7/5MHz/B200) in a container + hutch ci-scripts/yaml_files/lte_b200_fdd_05Mhz_if4.5 rru_fdd - 0 - 0 Deploy_Object Deploy RCC (FDD/Band7/5MHz) in a container + hutch ci-scripts/yaml_files/lte_b200_fdd_05Mhz_if4.5 rcc_fdd - 0 - 0 @@ -98,9 +95,8 @@ Undeploy_Object true Undeploy RCC/RRU + hutch ci-scripts/yaml_files/lte_b200_fdd_05Mhz_if4.5 - 0 - 0 diff --git a/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1_no_rrc_activity.xml b/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1_no_rrc_activity.xml index 04e459c4a3..8936a3928e 100644 --- a/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1_no_rrc_activity.xml +++ b/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1_no_rrc_activity.xml @@ -61,24 +61,21 @@ Replaces xml_files/enb_usrp210_band7_test_05mhz_tm1_rrc_inactivity_no_flexran.xm Create_Workspace Create new Workspace for server 0 - 0 - 0 + hutch Deploy_Object Deploy eNB (FDD/Band7/5MHz/B200) in a container + hutch ci-scripts/yaml_files/lte_b200_fdd_05Mhz_tm1_no_rrc_activity - 0 - 0 Undeploy_Object true Undeploy eNB + hutch ci-scripts/yaml_files/lte_b200_fdd_05Mhz_tm1_no_rrc_activity - 0 - 0 diff --git a/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1.xml b/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1.xml index fc2b933805..1456418475 100644 --- a/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1.xml +++ b/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1.xml @@ -63,15 +63,13 @@ Replaces xml_files/enb_usrp210_band7_test_10mhz_tm1.xml Create_Workspace Create new Workspace for server 0 - 0 - 0 + hutch Deploy_Object Deploy eNB (FDD/Band7/10MHz/B200) in a container + hutch ci-scripts/yaml_files/lte_b200_fdd_10Mhz_tm1 - 0 - 0 @@ -84,9 +82,8 @@ Replaces xml_files/enb_usrp210_band7_test_10mhz_tm1.xml Undeploy_Object true Undeploy eNB + hutch ci-scripts/yaml_files/lte_b200_fdd_10Mhz_tm1 - 0 - 0 diff --git a/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1_cdrx.xml b/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1_cdrx.xml index 00a3a59d21..aafcdff6ea 100644 --- a/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1_cdrx.xml +++ b/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1_cdrx.xml @@ -62,24 +62,21 @@ Replaces xml_files/enb_usrp210_band7_test_10mhz_tm1.xml Create_Workspace Create new Workspace for server 0 - 0 - 0 + hutch Deploy_Object Deploy eNB (FDD/Band7/10MHz/B200) in a container + hutch ci-scripts/yaml_files/lte_b200_fdd_10Mhz_tm1_cdrx - 0 - 0 Undeploy_Object true Undeploy eNB + hutch ci-scripts/yaml_files/lte_b200_fdd_10Mhz_tm1_cdrx - 0 - 0 diff --git a/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1_oaiue.xml b/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1_oaiue.xml index 9f2f546bcf..f50330ab89 100644 --- a/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1_oaiue.xml +++ b/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1_oaiue.xml @@ -87,28 +87,24 @@ Create_Workspace Create new Workspace for server 0 - 0 - 0 + hutch Deploy_Object Deploy eNB (FDD/Band7/10MHz/B200) in a container ci-scripts/yaml_files/lte_b200_fdd_10Mhz_tm1_magma - 0 - 0 + hutch Create_Workspace Create new Workspace for server 1 - 1 - 1 + carabe Deploy_Object Deploy LTE-UE (FDD/Band7/10MHz/B200) in a container + carabe ci-scripts/yaml_files/lte_b200_fdd_10Mhz_oai_ue_magma - 1 - 1 @@ -127,18 +123,16 @@ Undeploy_Object true Undeploy eNB + hutch ci-scripts/yaml_files/lte_b200_fdd_10Mhz_tm1_magma - 0 - 0 Undeploy_Object true Undeploy LTE-UE + carabe ci-scripts/yaml_files/lte_b200_fdd_10Mhz_oai_ue_magma - 1 - 1 diff --git a/ci-scripts/xml_files/container_lte_b200_fdd_20Mhz_tm1.xml b/ci-scripts/xml_files/container_lte_b200_fdd_20Mhz_tm1.xml index cda6ff236d..52dbcb8972 100644 --- a/ci-scripts/xml_files/container_lte_b200_fdd_20Mhz_tm1.xml +++ b/ci-scripts/xml_files/container_lte_b200_fdd_20Mhz_tm1.xml @@ -62,15 +62,13 @@ Replaces xml_files/enb_usrp210_band7_test_10mhz_tm1.xml Create_Workspace Create new Workspace for server 0 - 0 - 0 + hutch Deploy_Object Deploy eNB (FDD/Band7/20MHz/B200) in a container + hutch ci-scripts/yaml_files/lte_b200_fdd_20Mhz_tm1 - 0 - 0 @@ -83,9 +81,8 @@ Replaces xml_files/enb_usrp210_band7_test_10mhz_tm1.xml Undeploy_Object true Undeploy eNB + hutch ci-scripts/yaml_files/lte_b200_fdd_20Mhz_tm1 - 0 - 0 diff --git a/ci-scripts/xml_files/container_lte_b200_tdd_05Mhz_tm1.xml b/ci-scripts/xml_files/container_lte_b200_tdd_05Mhz_tm1.xml index ae3275f5a6..f46697a106 100644 --- a/ci-scripts/xml_files/container_lte_b200_tdd_05Mhz_tm1.xml +++ b/ci-scripts/xml_files/container_lte_b200_tdd_05Mhz_tm1.xml @@ -70,15 +70,13 @@ Replaces xml_files/enb_usrp210_band40_test_05mhz_tm1.xml Create_Workspace Create new Workspace for server 0 - 0 - 0 + starsky Deploy_Object Deploy eNB (TDD/Band40/5MHz/B200) in a container + starsky ci-scripts/yaml_files/lte_b200_tdd_05Mhz_tm1 - 0 - 0 @@ -91,9 +89,8 @@ Replaces xml_files/enb_usrp210_band40_test_05mhz_tm1.xml Undeploy_Object true Undeploy eNB + starsky ci-scripts/yaml_files/lte_b200_tdd_05Mhz_tm1 - 0 - 0 diff --git a/ci-scripts/xml_files/container_lte_b200_tdd_05Mhz_tm1_if4_5.xml b/ci-scripts/xml_files/container_lte_b200_tdd_05Mhz_tm1_if4_5.xml index 4b60443d33..da187e2120 100644 --- a/ci-scripts/xml_files/container_lte_b200_tdd_05Mhz_tm1_if4_5.xml +++ b/ci-scripts/xml_files/container_lte_b200_tdd_05Mhz_tm1_if4_5.xml @@ -68,24 +68,21 @@ Create_Workspace Create new Workspace for server 0 - 0 - 0 + starsky Deploy_Object Deploy RRU (TDD/Band40/5MHz/B200) in a container + starsky ci-scripts/yaml_files/lte_b200_tdd_05Mhz_if4.5 rru_tdd - 0 - 0 Deploy_Object Deploy RCC (TDD/Band40/5MHz) in a container + starsky ci-scripts/yaml_files/lte_b200_tdd_05Mhz_if4.5 rcc_tdd - 0 - 0 @@ -98,9 +95,8 @@ Undeploy_Object true Undeploy RRU/RCC + starsky ci-scripts/yaml_files/lte_b200_tdd_05Mhz_if4.5 - 0 - 0 diff --git a/ci-scripts/xml_files/container_lte_b200_tdd_10Mhz_tm1.xml b/ci-scripts/xml_files/container_lte_b200_tdd_10Mhz_tm1.xml index c89cf5aeb7..88b3330508 100644 --- a/ci-scripts/xml_files/container_lte_b200_tdd_10Mhz_tm1.xml +++ b/ci-scripts/xml_files/container_lte_b200_tdd_10Mhz_tm1.xml @@ -61,15 +61,13 @@ Replaces xml_files/enb_usrp210_band40_test_10mhz_tm1.xml Create_Workspace Create new Workspace for server 0 - 0 - 0 + starsky Deploy_Object Deploy eNB (TDD/Band40/10MHz/B200) in a container + starsky ci-scripts/yaml_files/lte_b200_tdd_10Mhz_tm1 - 0 - 0 @@ -82,9 +80,8 @@ Replaces xml_files/enb_usrp210_band40_test_10mhz_tm1.xml Undeploy_Object true Undeploy eNB + starsky ci-scripts/yaml_files/lte_b200_tdd_10Mhz_tm1 - 0 - 0 diff --git a/ci-scripts/xml_files/container_lte_b200_tdd_20Mhz_tm1.xml b/ci-scripts/xml_files/container_lte_b200_tdd_20Mhz_tm1.xml index 455a0b3e3a..65f4dfc6b4 100644 --- a/ci-scripts/xml_files/container_lte_b200_tdd_20Mhz_tm1.xml +++ b/ci-scripts/xml_files/container_lte_b200_tdd_20Mhz_tm1.xml @@ -61,15 +61,13 @@ Replaces xml_files/enb_usrp210_band40_test_20mhz_tm1.xml Create_Workspace Create new Workspace for server 0 - 0 - 0 + starsky Deploy_Object Deploy eNB (TDD/Band40/20MHz/B200) in a container + starsky ci-scripts/yaml_files/lte_b200_tdd_20Mhz_tm1 - 0 - 0 @@ -82,9 +80,8 @@ Replaces xml_files/enb_usrp210_band40_test_20mhz_tm1.xml Undeploy_Object true Undeploy eNB + starsky ci-scripts/yaml_files/lte_b200_tdd_20Mhz_tm1 - 0 - 0 diff --git a/ci-scripts/xml_files/container_lte_b200_tdd_20Mhz_tm1_default_scheduler.xml b/ci-scripts/xml_files/container_lte_b200_tdd_20Mhz_tm1_default_scheduler.xml index 76a9d3c020..6a0cb0f892 100644 --- a/ci-scripts/xml_files/container_lte_b200_tdd_20Mhz_tm1_default_scheduler.xml +++ b/ci-scripts/xml_files/container_lte_b200_tdd_20Mhz_tm1_default_scheduler.xml @@ -62,15 +62,13 @@ Replaces xml_files/enb_usrp210_band40_test_20mhz_tm1_default_scheduler.xml Create_Workspace Create new Workspace for server 0 - 0 - 0 + starsky Deploy_Object Deploy eNB (TDD/Band40/20MHz/B200) in a container + starsky ci-scripts/yaml_files/lte_b200_tdd_20Mhz_tm1_default_scheduler - 0 - 0 @@ -83,9 +81,8 @@ Replaces xml_files/enb_usrp210_band40_test_20mhz_tm1_default_scheduler.xml Undeploy_Object true Undeploy eNB + starsky ci-scripts/yaml_files/lte_b200_tdd_20Mhz_tm1_default_scheduler - 0 - 0 diff --git a/ci-scripts/xml_files/container_lte_n3xx_tdd_2x2_tm1.xml b/ci-scripts/xml_files/container_lte_n3xx_tdd_2x2_tm1.xml index e8d380ffc6..3337bba999 100644 --- a/ci-scripts/xml_files/container_lte_n3xx_tdd_2x2_tm1.xml +++ b/ci-scripts/xml_files/container_lte_n3xx_tdd_2x2_tm1.xml @@ -68,15 +68,13 @@ Create_Workspace Create new Workspace - 0 - 0 + obelix Deploy_Object Deploy eNB (TDD/Band38/2.6Ghz/N3XX) in a container + obelix ci-scripts/yaml_files/lte_n3xx_tdd_2x2_tm1 - 0 - 0 @@ -142,9 +140,8 @@ Undeploy_Object true Undeploy gNB + obelix ci-scripts/yaml_files/lte_n3xx_tdd_2x2_tm1 - 0 - 0 - - l2sim-4glte-proxy-build - Build L2sim proxy image - wrench - - 100001 - 000001 - - - - Create_Workspace - Create new Workspace - localhost - - - Build_Proxy - Build L2sim Proxy Image - 1 - 1 - True - b64d9bce986b38ca59e8582864ade3fcdd05c0dc - - - From 190dc55d9fff3abc2dbe2c5ee48d89451425a2d1 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 11 Aug 2025 12:35:56 +0200 Subject: [PATCH 484/964] Pass node to various Build*() functions Pass node directly from XML to these functions - BuildClusterImage() - BuildImage() - BuildProxy() - BuildRunTests() instead of reading the "server ID" and looking up from eNB_IPAddress/eNB1_IPAddress/eNB2_IPAddress. Improve the proxy build unit test by properly passing ctx information. --- ci-scripts/args_parse.py | 3 -- ci-scripts/cls_cluster.py | 10 +++---- ci-scripts/cls_containerize.py | 29 +++++++++---------- ci-scripts/cls_native.py | 6 ++-- ci-scripts/main.py | 25 ++++------------ ci-scripts/tests/build.py | 10 +++---- ci-scripts/xml_files/cluster_image_build.xml | 1 + .../xml_files/container_build_run_tests.xml | 3 +- .../xml_files/container_image_build.xml | 3 +- .../xml_files/container_image_build_arm.xml | 3 +- .../xml_files/container_image_build_cross.xml | 3 +- .../xml_files/container_l2sim_proxy.xml | 3 +- ci-scripts/xml_files/gnb_usrp_build.xml | 1 + 13 files changed, 38 insertions(+), 62 deletions(-) diff --git a/ci-scripts/args_parse.py b/ci-scripts/args_parse.py index 7b57409fb0..11b27135a2 100644 --- a/ci-scripts/args_parse.py +++ b/ci-scripts/args_parse.py @@ -125,7 +125,6 @@ def ArgsParse(argvs,CiTestObj,RAN,HTML,CONTAINERS,HELP,SCA,CLUSTER): matchReg = re.match(r'^\-\-eNBIPAddress=(.+)$', myArgv, re.IGNORECASE) RAN.eNBIPAddress=matchReg.group(1) CONTAINERS.eNBIPAddress=matchReg.group(1) - CLUSTER.eNBIPAddress=matchReg.group(1) elif re.match(r'^\-\-eNB1IPAddress=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match(r'^\-\-eNB1IPAddress=(.+)$', myArgv, re.IGNORECASE) RAN.eNB1IPAddress=matchReg.group(1) @@ -139,7 +138,6 @@ def ArgsParse(argvs,CiTestObj,RAN,HTML,CONTAINERS,HELP,SCA,CLUSTER): matchReg = re.match(r'^\-\-eNBUserName=(.+)$', myArgv, re.IGNORECASE) RAN.eNBUserName=matchReg.group(1) CONTAINERS.eNBUserName=matchReg.group(1) - CLUSTER.eNBUserName=matchReg.group(1) elif re.match(r'^\-\-eNB1UserName=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match(r'^\-\-eNB1UserName=(.+)$', myArgv, re.IGNORECASE) RAN.eNB1UserName=matchReg.group(1) @@ -153,7 +151,6 @@ def ArgsParse(argvs,CiTestObj,RAN,HTML,CONTAINERS,HELP,SCA,CLUSTER): matchReg = re.match(r'^\-\-eNBPassword=(.+)$', myArgv, re.IGNORECASE) RAN.eNBPassword=matchReg.group(1) CONTAINERS.eNBPassword=matchReg.group(1) - CLUSTER.eNBPassword=matchReg.group(1) elif re.match(r'^\-\-eNB1Password=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match(r'^\-\-eNB1Password=(.+)$', myArgv, re.IGNORECASE) RAN.eNB1Password=matchReg.group(1) diff --git a/ci-scripts/cls_cluster.py b/ci-scripts/cls_cluster.py index dd3c66d989..929dd29021 100644 --- a/ci-scripts/cls_cluster.py +++ b/ci-scripts/cls_cluster.py @@ -69,7 +69,6 @@ def OC_logout(cmd): class Cluster: def __init__(self): - self.eNBIPAddress = "" self.eNBSourceCodePath = "" self.forcedWorkspaceCleanup = False self.OCUserName = "" @@ -195,13 +194,12 @@ class Cluster: self.cmd.run(f'oc logs {job} &> {fn}') return (image, archiveArtifact(self.cmd, ctx, fn)) - def BuildClusterImage(self, ctx, HTML): + def BuildClusterImage(self, ctx, node, HTML): if self.ranRepository == '' or self.ranBranch == '' or self.ranCommitID == '': HELP.GenericHelp(CONST.Version) raise ValueError(f'Insufficient Parameter: ranRepository {self.ranRepository} ranBranch {ranBranch} ranCommitID {self.ranCommitID}') - lIpAddr = self.eNBIPAddress lSourcePath = self.eNBSourceCodePath - if lIpAddr == '' or lSourcePath == '': + if node == '' or lSourcePath == '': raise ValueError('Insufficient Parameter: eNBSourceCodePath missing') ocUserName = self.OCUserName ocPassword = self.OCPassword @@ -212,8 +210,8 @@ class Cluster: if self.OCRegistry.startswith("http") or self.OCRegistry.endswith("/"): raise ValueError(f'ocRegistry {self.OCRegistry} should not start with http:// or https:// and not end on a slash /') - logging.debug(f'Building on cluster triggered from server: {lIpAddr}') - self.cmd = cls_cmd.RemoteCmd(lIpAddr) + logging.debug(f'Building on cluster triggered from server: {node}') + self.cmd = cls_cmd.RemoteCmd(node) self.testCase_id = HTML.testCase_id diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index 7629a2ee17..282fe0f4a0 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -280,11 +280,10 @@ class Containerize(): raise ValueError(f'Insufficient Parameter: IP/node {ip}, path {path}') return (ip, path) - def BuildImage(self, ctx, HTML): - svr = self.eNB_serverId[self.eNB_instance] - lIpAddr, lSourcePath = self.GetCredentials(svr) - logging.debug('Building on server: ' + lIpAddr) - cmd = cls_cmd.getConnection(lIpAddr) + def BuildImage(self, ctx, node, HTML): + lSourcePath = self.eNBSourceCodePath + logging.debug('Building on server: ' + node) + cmd = cls_cmd.getConnection(node) log_files = [] # Checking the hostname to get adapted on cli and dockerfileprefixes @@ -475,11 +474,10 @@ class Containerize(): logging.error('\u001B[1m Building OAI Images Failed\u001B[0m') return status - def BuildProxy(self, ctx, HTML): - svr = self.eNB_serverId[self.eNB_instance] - lIpAddr, lSourcePath = self.GetCredentials(svr) - logging.debug('Building on server: ' + lIpAddr) - ssh = cls_cmd.getConnection(lIpAddr) + def BuildProxy(self, ctx, node, HTML): + lSourcePath = self.eNBSourceCodePath + logging.debug('Building on server: ' + node) + ssh = cls_cmd.getConnection(node) oldRanCommidID = self.ranCommitID oldRanRepository = self.ranRepository @@ -502,7 +500,7 @@ class Containerize(): buildProxy = ret.returncode != 0 # if no image, build new proxy if buildProxy: ssh.run(f'rm -Rf {lSourcePath}') - success = CreateWorkspace(lIpAddr, lSourcePath, self.ranRepository, self.ranCommitID, self.ranTargetBranch, self.ranAllowMerge) + success = CreateWorkspace(node, lSourcePath, self.ranRepository, self.ranCommitID, self.ranTargetBranch, self.ranAllowMerge) if not success: raise Exception("could not clone proxy repository") @@ -559,11 +557,10 @@ class Containerize(): HTML.CreateHtmlTestRow('commit ' + tag, 'KO', CONST.ALL_PROCESSES_OK) return False - def BuildRunTests(self, ctx, HTML): - svr = self.eNB_serverId[self.eNB_instance] - lIpAddr, lSourcePath = self.GetCredentials(svr) - logging.debug('Building on server: ' + lIpAddr) - cmd = cls_cmd.RemoteCmd(lIpAddr) + def BuildRunTests(self, ctx, node, HTML): + lSourcePath = self.eNBSourceCodePath + logging.debug('Building on server: ' + node) + cmd = cls_cmd.RemoteCmd(node) cmd.cd(lSourcePath) ret = cmd.run('hostnamectl') diff --git a/ci-scripts/cls_native.py b/ci-scripts/cls_native.py index 83c1b14b37..9546f93d28 100644 --- a/ci-scripts/cls_native.py +++ b/ci-scripts/cls_native.py @@ -34,11 +34,11 @@ DPDK_PATH = '/opt/dpdk-t2-22.11.0' class Native(): - def Build(ctx, test_case, HTML, host, directory, options): - logging.debug(f'Building on server: {host}') + def Build(ctx, node, test_case, HTML, directory, options): + logging.debug(f'Building on server: {node}') HTML.testCase_id = test_case - with cls_cmd.getConnection(host) as ssh: + with cls_cmd.getConnection(node) as ssh: base = f"{directory}/cmake_targets" ret = ssh.run(f"C_INCLUDE_PATH={DPDK_PATH}/include/ PKG_CONFIG_PATH={DPDK_PATH}/lib64/pkgconfig/ {base}/build_oai {options} > {base}/build_oai.log", timeout=900) success = ret.returncode == 0 diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 03e8e126a0..d30b209be7 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -110,33 +110,20 @@ def ExecuteActionWithParam(action, ctx): RAN.Build_eNB_forced_workspace_cleanup = True CONTAINERS.forcedWorkspaceCleanup = True CLUSTER.forcedWorkspaceCleanup = True - eNB_instance=test.findtext('eNB_instance') - if (eNB_instance is None): - RAN.eNB_instance=0 - CONTAINERS.eNB_instance=0 - else: - RAN.eNB_instance=int(eNB_instance) - CONTAINERS.eNB_instance=int(eNB_instance) - eNB_serverId=test.findtext('eNB_serverId') - if (eNB_serverId is None): - RAN.eNB_serverId[RAN.eNB_instance]='0' - CONTAINERS.eNB_serverId[RAN.eNB_instance]='0' - else: - RAN.eNB_serverId[RAN.eNB_instance]=eNB_serverId - CONTAINERS.eNB_serverId[CONTAINERS.eNB_instance]=eNB_serverId + node = test.findtext('node') proxy_commit = test.findtext('proxy_commit') if proxy_commit is not None: CONTAINERS.proxyCommit = proxy_commit if action == 'Build_eNB': - success = cls_native.Native.Build(ctx, HTML.testCase_id, HTML, RAN.eNBIPAddress, RAN.eNBSourceCodePath, RAN.Build_eNB_args) + success = cls_native.Native.Build(ctx, node, HTML.testCase_id, HTML, RAN.eNBSourceCodePath, RAN.Build_eNB_args) elif action == 'Build_Image': - success = CONTAINERS.BuildImage(ctx, HTML) + success = CONTAINERS.BuildImage(ctx, node, HTML) elif action == 'Build_Proxy': - success = CONTAINERS.BuildProxy(ctx, HTML) + success = CONTAINERS.BuildProxy(ctx, node, HTML) elif action == 'Build_Cluster_Image': - success = CLUSTER.BuildClusterImage(ctx, HTML) + success = CLUSTER.BuildClusterImage(ctx, node, HTML) elif action == 'Build_Run_Tests': - success = CONTAINERS.BuildRunTests(ctx, HTML) + success = CONTAINERS.BuildRunTests(ctx, node, HTML) elif action == 'Initialize_eNB': datalog_rt_stats_file=test.findtext('rt_stats_cfg') diff --git a/ci-scripts/tests/build.py b/ci-scripts/tests/build.py index 669e6711b4..013486a560 100644 --- a/ci-scripts/tests/build.py +++ b/ci-scripts/tests/build.py @@ -11,6 +11,7 @@ import tempfile sys.path.append('./') # to find OAI imports below import cls_oai_html import cls_containerize +from cls_ci_helper import TestCaseCtx import cls_cmd class TestBuild(unittest.TestCase): @@ -18,22 +19,21 @@ class TestBuild(unittest.TestCase): self.html = cls_oai_html.HTMLManagement() self.html.testCase_id = "000000" self.cont = cls_containerize.Containerize() - self.cont.eNB_serverId[0] = '0' - self.cont.eNBIPAddress = 'localhost' - self.cont.eNBUserName = None - self.cont.eNBPassword = None self._d = tempfile.mkdtemp() logging.warning(f"temporary directory: {self._d}") + self.node = 'localhost' self.cont.eNBSourceCodePath = self._d + self.ctx = TestCaseCtx.Default(tempfile.mkdtemp()) def tearDown(self): logging.warning(f"removing directory contents") with cls_cmd.getConnection(None) as cmd: cmd.run(f"rm -rf {self._d}") + cmd.run(f'rm -rf {self.ctx.logPath}') def test_build_proxy(self): self.cont.proxyCommit = "b64d9bce986b38ca59e8582864ade3fcdd05c0dc" - success = self.cont.BuildProxy(self.html) + success = self.cont.BuildProxy(self.ctx, self.node, self.html) self.assertTrue(success) if __name__ == '__main__': diff --git a/ci-scripts/xml_files/cluster_image_build.xml b/ci-scripts/xml_files/cluster_image_build.xml index b8462a4ebd..a80d1cd7d4 100644 --- a/ci-scripts/xml_files/cluster_image_build.xml +++ b/ci-scripts/xml_files/cluster_image_build.xml @@ -37,6 +37,7 @@ Build_Cluster_Image Build Images on OpenShift Cluster + poseidon diff --git a/ci-scripts/xml_files/container_build_run_tests.xml b/ci-scripts/xml_files/container_build_run_tests.xml index 479bb20a5d..087c5af598 100644 --- a/ci-scripts/xml_files/container_build_run_tests.xml +++ b/ci-scripts/xml_files/container_build_run_tests.xml @@ -32,9 +32,8 @@ Build_Run_Tests Build and Run UnitTests + obelix all - 0 - 0 diff --git a/ci-scripts/xml_files/container_image_build.xml b/ci-scripts/xml_files/container_image_build.xml index b2c0705d8a..33f29cf087 100644 --- a/ci-scripts/xml_files/container_image_build.xml +++ b/ci-scripts/xml_files/container_image_build.xml @@ -39,9 +39,8 @@ Build_Image Build all Images + obelix all - 0 - 0 True diff --git a/ci-scripts/xml_files/container_image_build_arm.xml b/ci-scripts/xml_files/container_image_build_arm.xml index e82e357d26..7c731fd3a1 100644 --- a/ci-scripts/xml_files/container_image_build_arm.xml +++ b/ci-scripts/xml_files/container_image_build_arm.xml @@ -39,9 +39,8 @@ Build_Image Build all Images + gracehopper3-oai native_arm - 0 - 0 diff --git a/ci-scripts/xml_files/container_image_build_cross.xml b/ci-scripts/xml_files/container_image_build_cross.xml index c47253662b..ddaeac3602 100644 --- a/ci-scripts/xml_files/container_image_build_cross.xml +++ b/ci-scripts/xml_files/container_image_build_cross.xml @@ -38,8 +38,7 @@ Build_Image Cross-Compile for ARM64 build_cross_arm64 - 0 - 0 + alambix True diff --git a/ci-scripts/xml_files/container_l2sim_proxy.xml b/ci-scripts/xml_files/container_l2sim_proxy.xml index 197baf429b..88026f077d 100644 --- a/ci-scripts/xml_files/container_l2sim_proxy.xml +++ b/ci-scripts/xml_files/container_l2sim_proxy.xml @@ -32,8 +32,7 @@ Build_Proxy Build L2sim Proxy Image - 1 - 1 + localhost True b64d9bce986b38ca59e8582864ade3fcdd05c0dc diff --git a/ci-scripts/xml_files/gnb_usrp_build.xml b/ci-scripts/xml_files/gnb_usrp_build.xml index 8ee89ee108..4e763678a7 100644 --- a/ci-scripts/xml_files/gnb_usrp_build.xml +++ b/ci-scripts/xml_files/gnb_usrp_build.xml @@ -41,6 +41,7 @@ TesteNB Build_eNB Build gNB (USRP) + caracal --gNB -w USRP --ninja -c -P --build-lib ldpc_cuda --build-lib ldpc_aal --cmake-opt -DASN1C_EXEC=/opt/asn1c/bin/asn1c True From 3f4df04875a27a4670f2f0fe82fa7fc69a496c70 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 11 Aug 2025 12:57:58 +0200 Subject: [PATCH 485/964] Run_Physim(): pass node --- ci-scripts/main.py | 3 +- ci-scripts/xml_files/ldpc_gpu_test.xml | 40 +++++++++++++++++++ .../xml_files/t2_offload_dec_nr_ulsim.xml | 18 +++++++++ .../xml_files/t2_offload_enc_nr_dlsim.xml | 24 +++++++++++ 4 files changed, 84 insertions(+), 1 deletion(-) diff --git a/ci-scripts/main.py b/ci-scripts/main.py index d30b209be7..90b5b7de90 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -313,7 +313,8 @@ def ExecuteActionWithParam(action, ctx): physim_options = test.findtext('physim_run_args') physim_test = test.findtext('physim_test') physim_threshold = test.findtext('physim_time_threshold') or 'inf' - success = cls_native.Native.Run_Physim(ctx, HTML, RAN.eNBIPAddress, RAN.eNBSourceCodePath, physim_options, physim_test, physim_threshold) + node = test.findtext('node') + success = cls_native.Native.Run_Physim(ctx, HTML, node, RAN.eNBSourceCodePath, physim_options, physim_test, physim_threshold) elif action == 'LicenceAndFormattingCheck': node = test.findtext('node') diff --git a/ci-scripts/xml_files/ldpc_gpu_test.xml b/ci-scripts/xml_files/ldpc_gpu_test.xml index bee9035c8b..00ccbe3da1 100644 --- a/ci-scripts/xml_files/ldpc_gpu_test.xml +++ b/ci-scripts/xml_files/ldpc_gpu_test.xml @@ -35,6 +35,7 @@ Run_Physim Run LDPC Test with CPU true + caracal ldpctest -l 3872 -s10 -n100 @@ -43,6 +44,7 @@ Run_Physim Run LDPC Test with GPU true + caracal ldpctest -l 3872 -s10 -n100 -G 1 @@ -51,6 +53,7 @@ Run_Physim Run LDPC Test with CPU true + caracal ldpctest -l 4224 -s10 -n100 @@ -59,6 +62,7 @@ Run_Physim Run LDPC Test with GPU true + caracal ldpctest -l 4224 -s10 -n100 -G 1 @@ -67,6 +71,7 @@ Run_Physim Run LDPC Test with CPU true + caracal ldpctest -l 4576 -s10 -n100 @@ -75,6 +80,7 @@ Run_Physim Run LDPC Test with GPU true + caracal ldpctest -l 4576 -s10 -n100 -G 1 @@ -83,6 +89,7 @@ Run_Physim Run LDPC Test with CPU true + caracal ldpctest -l 4928 -s10 -n100 @@ -91,6 +98,7 @@ Run_Physim Run LDPC Test with GPU true + caracal ldpctest -l 4928 -s10 -n100 -G 1 @@ -99,6 +107,7 @@ Run_Physim Run LDPC Test with CPU true + caracal ldpctest -l 5280 -s10 -n100 @@ -107,6 +116,7 @@ Run_Physim Run LDPC Test with GPU true + caracal ldpctest -l 5280 -s10 -n100 -G 1 @@ -115,6 +125,7 @@ Run_Physim Run LDPC Test with CPU true + caracal ldpctest -l 5632 -s10 -n100 @@ -123,6 +134,7 @@ Run_Physim Run LDPC Test with GPU true + caracal ldpctest -l 5632 -s10 -n100 -G 1 @@ -131,6 +143,7 @@ Run_Physim Run LDPC Test with CPU true + caracal ldpctest -l 6336 -s10 -n100 @@ -139,6 +152,7 @@ Run_Physim Run LDPC Test with GPU true + caracal ldpctest -l 6336 -s10 -n100 -G 1 @@ -147,6 +161,7 @@ Run_Physim Run LDPC Test with CPU true + caracal ldpctest -l 7040 -s10 -n100 @@ -155,6 +170,7 @@ Run_Physim Run LDPC Test with GPU true + caracal ldpctest -l 7040 -s10 -n100 -G 1 @@ -163,6 +179,7 @@ Run_Physim Run LDPC Test with CPU true + caracal ldpctest -l 7744 -s10 -n100 @@ -171,6 +188,7 @@ Run_Physim Run LDPC Test with GPU true + caracal ldpctest -l 7744 -s10 -n100 -G 1 @@ -179,6 +197,7 @@ Run_Physim Run LDPC Test with CPU true + caracal ldpctest -l 8448 -s10 -n100 @@ -187,6 +206,7 @@ Run_Physim Run LDPC Test with GPU true + caracal ldpctest -l 8448 -s10 -n100 -G 1 @@ -195,6 +215,7 @@ Run_Physim Run LDPC Test with CPU true + caracal ldpctest -l 1 -s10 -n100 @@ -203,6 +224,7 @@ Run_Physim Run LDPC Test with GPU true + caracal ldpctest -l 1 -s10 -n100 -G 1 @@ -211,6 +233,7 @@ Run_Physim Run LDPC Test with CPU true + caracal ldpctest -l 100 -s10 -n100 @@ -219,6 +242,7 @@ Run_Physim Run LDPC Test with GPU true + caracal ldpctest -l 100 -s10 -n100 -G 1 @@ -227,6 +251,7 @@ Run_Physim Run LDPC Test with CPU true + caracal ldpctest -l 193 -s10 -n100 @@ -235,6 +260,7 @@ Run_Physim Run LDPC Test with GPU true + caracal ldpctest -l 193 -s10 -n100 -G 1 @@ -243,6 +269,7 @@ Run_Physim Run LDPC Test with CPU true + caracal ldpctest -l 500 -s10 -n100 @@ -251,6 +278,7 @@ Run_Physim Run LDPC Test with GPU true + caracal ldpctest -l 500 -s10 -n100 -G 1 @@ -259,6 +287,7 @@ Run_Physim Run LDPC Test with CPU true + caracal ldpctest -l 561 -s10 -n100 @@ -267,6 +296,7 @@ Run_Physim Run LDPC Test with GPU true + caracal ldpctest -l 561 -s10 -n100 -G 1 @@ -275,6 +305,7 @@ Run_Physim Run LDPC Test with CPU true + caracal ldpctest -l 600 -s10 -n100 @@ -283,6 +314,7 @@ Run_Physim Run LDPC Test with GPU true + caracal ldpctest -l 600 -s10 -n100 -G 1 @@ -291,6 +323,7 @@ Run_Physim Run LDPC Test with CPU true + caracal ldpctest -l 641 -s10 -n100 @@ -299,6 +332,7 @@ Run_Physim Run LDPC Test with GPU true + caracal ldpctest -l 641 -s10 -n100 -G 1 @@ -307,6 +341,7 @@ Run_Physim Run LDPC Test with CPU true + caracal ldpctest -l 2000 -s10 -n100 @@ -315,6 +350,7 @@ Run_Physim Run LDPC Test with GPU true + caracal ldpctest -l 2000 -s10 -n100 -G 1 @@ -323,6 +359,7 @@ Run_Physim Run LDPC Test with CPU true + caracal ldpctest -l 3000 -s10 -n100 @@ -331,6 +368,7 @@ Run_Physim Run LDPC Test with GPU true + caracal ldpctest -l 3000 -s10 -n100 -G 1 @@ -339,6 +377,7 @@ Run_Physim Run LDPC Test with CPU true + caracal ldpctest -l 3840 -s10 -n100 @@ -347,6 +386,7 @@ Run_Physim Run LDPC Test with GPU true + caracal ldpctest -l 3840 -s10 -n100 -G 1 diff --git a/ci-scripts/xml_files/t2_offload_dec_nr_ulsim.xml b/ci-scripts/xml_files/t2_offload_dec_nr_ulsim.xml index f82c54e8de..4a2daf0b97 100644 --- a/ci-scripts/xml_files/t2_offload_dec_nr_ulsim.xml +++ b/ci-scripts/xml_files/t2_offload_dec_nr_ulsim.xml @@ -51,6 +51,7 @@ Run_Physim Run nr_ulsim with CPU: SNR = 30, MCS = 5, 106 PRBs, 1 layer true + caracal nr_ulsim 300 -n1000 -s30 -S30.2 -m5 -r106 -R106 -C10 -P @@ -60,6 +61,7 @@ Run_Physim Run nr_ulsim with T2 LDPC offload: SNR = 30, MCS = 5, 106 PRBs, 1 layer true + caracal nr_ulsim 100 -n1000 -s30 -S30.2 -m5 -r106 -R106 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 @@ -69,6 +71,7 @@ Run_Physim Run nr_ulsim with CPU: SNR = 30, MCS = 15, 106 PRBs, 1 layer true + caracal nr_ulsim 300 -n1000 -s30 -S30.2 -m15 -r106 -R106 -C10 -P @@ -78,6 +81,7 @@ Run_Physim Run nr_ulsim with T2 LDPC offload: SNR = 30, MCS = 15, 106 PRBs, 1 layer true + caracal nr_ulsim 150 -n1000 -s30 -S30.2 -m15 -r106 -R106 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 @@ -87,6 +91,7 @@ Run_Physim Run nr_ulsim with CPU: SNR = 30, MCS = 25, 106 PRBs, 1 layer true + caracal nr_ulsim 250 -n1000 -s30 -S30.2 -m25 -r106 -R106 -C10 -P @@ -96,6 +101,7 @@ Run_Physim Run nr_ulsim with T2 LDPC offload: SNR = 30, MCS = 25, 106 PRBs, 1 layer true + caracal nr_ulsim 250 -n1000 -s30 -S30.2 -m25 -r106 -R106 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 @@ -105,6 +111,7 @@ Run_Physim Run nr_ulsim with CPU: SNR = 30, MCS = 5, 273 PRBs, 1 layer true + caracal nr_ulsim 300 -n1000 -s30 -S30.2 -m5 -r273 -R273 -C10 -P @@ -114,6 +121,7 @@ Run_Physim Run nr_ulsim with T2 LDPC offload: SNR = 30, MCS = 5, 273 PRBs, 1 layer true + caracal nr_ulsim 150 -n1000 -s30 -S30.2 -m5 -r273 -R273 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 @@ -123,6 +131,7 @@ Run_Physim Run nr_ulsim with CPU: SNR = 30, MCS = 15, 273 PRBs, 1 layer true + caracal nr_ulsim 400 -n1000 -s30 -S30.2 -m15 -r273 -R273 -C10 -P @@ -132,6 +141,7 @@ Run_Physim Run nr_ulsim with T2 LDPC offload: SNR = 30, MCS = 15, 273 PRBs, 1 layer true + caracal nr_ulsim 350 -n1000 -s30 -S30.2 -m15 -r273 -R273 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 @@ -141,6 +151,7 @@ Run_Physim Run nr_ulsim with CPU: SNR = 30, MCS = 25, 273 PRBs, 1 layer true + caracal nr_ulsim 400 -n1000 -s30 -S30.2 -m25 -r273 -R273 -C10 -P @@ -150,6 +161,7 @@ Run_Physim Run nr_ulsim with T2 LDPC offload: SNR = 30, MCS = 25, 273 PRBs, 1 layer true + caracal nr_ulsim 550 -n1000 -s30 -S30.2 -m25 -r273 -R273 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 @@ -159,6 +171,7 @@ Run_Physim Run nr_ulsim with CPU: SNR = 30, MCS = 5, 273 PRBs, 2 layers true + caracal nr_ulsim 300 -n1000 -s30 -S30.2 -m5 -r273 -R273 -C10 -W2 -z2 -y2 -P @@ -168,6 +181,7 @@ Run_Physim Run nr_ulsim with T2 LDPC offload: SNR = 30, MCS = 5, 273 PRBs, 2 layers true + caracal nr_ulsim 250 -n1000 -s30 -S30.2 -m5 -r273 -R273 -C10 -W2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 @@ -177,6 +191,7 @@ Run_Physim Run nr_ulsim with CPU: SNR = 30, MCS = 15, 273 PRBs, 2 layers true + caracal nr_ulsim 600 -n1000 -s30 -S30.2 -m15 -r273 -R273 -C10 -W2 -z2 -y2 -P @@ -186,6 +201,7 @@ Run_Physim Run nr_ulsim with T2 LDPC offload: SNR = 30, MCS = 15, 273 PRBs, 2 layers true + caracal nr_ulsim 650 -n1000 -s30 -S30.2 -m15 -r273 -R273 -C10 -W2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 @@ -195,6 +211,7 @@ Run_Physim Run nr_ulsim with CPU: SNR = 30, MCS = 25, 273 PRBs, 2 layers true + caracal nr_ulsim 650 -n1000 -s30 -S30.2 -m25 -r273 -R273 -C10 -W2 -z2 -y2 -P @@ -204,6 +221,7 @@ Run_Physim Run nr_ulsim with T2 LDPC offload: SNR = 30, MCS = 25, 273 PRBs, 2 layers true + caracal nr_ulsim 1100 -n1000 -s30 -S30.2 -m25 -r273 -R273 -C10 -W2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 diff --git a/ci-scripts/xml_files/t2_offload_enc_nr_dlsim.xml b/ci-scripts/xml_files/t2_offload_enc_nr_dlsim.xml index 9b7a84c51f..69dc27943c 100644 --- a/ci-scripts/xml_files/t2_offload_enc_nr_dlsim.xml +++ b/ci-scripts/xml_files/t2_offload_enc_nr_dlsim.xml @@ -52,6 +52,7 @@ Run_Physim Run nr_dlsim with CPU: SNR = 30, MCS = 5, 106 PRBs, 1 layer true + caracal nr_dlsim 230 -n1000 -s30 -S30.2 -e5 -b106 -R106 -X 8,9,10,11,12 -P @@ -61,6 +62,7 @@ Run_Physim Run nr_dlsim with T2 LDPC offload: SNR = 30, MCS = 5, 106 PRBs, 1 layer true + caracal nr_dlsim 100 -n1000 -s30 -S30.2 -e5 -b106 -R106 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 @@ -70,6 +72,7 @@ Run_Physim Run nr_dlsim with CPU: SNR = 30, MCS = 15, 106 PRBs, 1 layer true + caracal nr_dlsim 300 -n1000 -s30 -S30.2 -e15 -b106 -R106 -X 8,9,10,11,12 -P @@ -79,6 +82,7 @@ Run_Physim Run nr_dlsim with T2 LDPC offload: SNR = 30, MCS = 15, 106 PRBs, 1 layer true + caracal nr_dlsim 100 -n1000 -s30 -S30.2 -e15 -b106 -R106 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 @@ -88,6 +92,7 @@ Run_Physim Run nr_dlsim with CPU: SNR = 30, MCS = 25, 106 PRBs, 1 layer true + caracal nr_dlsim 350 -n1000 -s30 -S30.2 -e25 -b106 -R106 -X 8,9,10,11,12 -P @@ -97,6 +102,7 @@ Run_Physim Run nr_dlsim with T2 LDPC offload: SNR = 30, MCS = 25, 106 PRBs, 1 layer true + caracal nr_dlsim 200 -n1000 -s30 -S30.2 -e25 -b106 -R106 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 @@ -106,6 +112,7 @@ Run_Physim Run nr_dlsim with CPU: SNR = 30, MCS = 5, 273 PRBs, 1 layer true + caracal nr_dlsim 300 -n1000 -s30 -S30.2 -e5 -b273 -R273 -X 8,9,10,11,12 -P @@ -115,6 +122,7 @@ Run_Physim Run nr_dlsim with T2 LDPC offload: SNR = 30, MCS = 5, 273 PRBs, 1 layer true + caracal nr_dlsim 150 -n1000 -s30 -S30.2 -e5 -b273 -R273 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 @@ -124,6 +132,7 @@ Run_Physim Run nr_dlsim with CPU: SNR = 30, MCS = 15, 273 PRBs, 1 layer true + caracal nr_dlsim 350 -n1000 -s30 -S30.2 -e15 -b273 -R273 -X 8,9,10,11,12 -P @@ -133,6 +142,7 @@ Run_Physim Run nr_dlsim with T2 LDPC offload: SNR = 30, MCS = 15, 273 PRBs, 1 layer true + caracal nr_dlsim 250 -n1000 -s30 -S30.2 -e15 -b273 -R273 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 @@ -142,6 +152,7 @@ Run_Physim Run nr_dlsim with CPU: SNR = 30, MCS = 25, 273 PRBs, 1 layer true + caracal nr_dlsim 400 -n1000 -s30 -S30.2 -e25 -b273 -R273 -X 8,9,10,11,12 -P @@ -151,6 +162,7 @@ Run_Physim Run nr_dlsim with T2 LDPC offload: SNR = 30, MCS = 25, 273 PRBs, 1 layer true + caracal nr_dlsim 400 -n1000 -s30 -S30.2 -e25 -b273 -R273 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 @@ -160,6 +172,7 @@ Run_Physim Run nr_dlsim with CPU: SNR = 30, MCS = 5, 273 PRBs, 2 layers true + caracal nr_dlsim 400 -n1000 -s30 -S30.2 -e5 -b273 -R273 -X 8,9,10,11,12 -x2 -z2 -y2 -P @@ -169,6 +182,7 @@ Run_Physim Run nr_dlsim with T2 LDPC offload: SNR = 30, MCS = 5, 273 PRBs, 2 layers true + caracal nr_dlsim 200 -n1000 -s30 -S30.2 -e5 -b273 -R273 -X4,5,6,7,8,9 -x2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 @@ -178,6 +192,7 @@ Run_Physim Run nr_dlsim with CPU: SNR = 30, MCS = 15, 273 PRBs, 2 layers true + caracal nr_dlsim 450 -n1000 -s30 -S30.2 -e15 -b273 -R273 -X 8,9,10,11,12 -x2 -z2 -y2 -P @@ -187,6 +202,7 @@ Run_Physim Run nr_dlsim with T2 LDPC offload: SNR = 30, MCS = 15, 273 PRBs, 2 layers true + caracal nr_dlsim 500 -n1000 -s30 -S30.2 -e15 -b273 -R273 -X4,5,6,7,8,9 -x2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 @@ -196,6 +212,7 @@ Run_Physim Run nr_dlsim with CPU: SNR = 30, MCS = 25, 273 PRBs, 2 layers true + caracal nr_dlsim 500 -n1000 -s30 -S30.2 -e25 -b273 -R273 -X 8,9,10,11,12 -x2 -z2 -y2 -P @@ -205,6 +222,7 @@ Run_Physim Run nr_dlsim with T2 LDPC offload: SNR = 30, MCS = 25, 273 PRBs, 2 layers true + caracal nr_dlsim 500 -n1000 -s30 -S30.2 -e25 -b273 -R273 -X4,5,6,7,8,9 -x2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 @@ -214,6 +232,7 @@ Run_Physim Run nr_dlsim with CPU: SNR = 30, MCS = 5, 273 PRBs, 2 layers, 4 antennas true + caracal nr_dlsim 400 -n1000 -s30 -S30.2 -e5 -b273 -R273 -X8,9,10,11,12 -x2 -z4 -y4 -P @@ -223,6 +242,7 @@ Run_Physim Run nr_dlsim with T2 LDPC offload: SNR = 30, MCS = 5, 273 PRBs, 2 layers, 4 antennas true + caracal nr_dlsim 200 -n1000 -s30 -S30.2 -e5 -b273 -R273 -X4,5,6,7,8,9 -x2 -z4 -y4 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 @@ -232,6 +252,7 @@ Run_Physim Run nr_dlsim with CPU: SNR = 30, MCS = 20, 273 PRBs, 2 layers, 4 antennas true + caracal nr_dlsim 400 -n1000 -s30 -S30.2 -e15 -b273 -R273 -X8,9,10,11,12 -x2 -z4 -y4 -P @@ -241,6 +262,7 @@ Run_Physim Run nr_dlsim with T2 LDPC offload: SNR = 30, MCS = 20, 273 PRBs, 2 layers, 4 antennas true + caracal nr_dlsim 300 -n1000 -s30 -S30.2 -e15 -b273 -R273 -X4,5,6,7,8,9 -x2 -z4 -y4 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 @@ -250,6 +272,7 @@ Run_Physim Run nr_dlsim with CPU: SNR = 30, MCS = 27, 273 PRBs, 2 layers, 4 antennas true + caracal nr_dlsim 450 -n1000 -s30 -S30.2 -e25 -b273 -R273 -X8,9,10,11,12 -x2 -z4 -y4 -P @@ -259,6 +282,7 @@ Run_Physim Run nr_dlsim with T2 LDPC offload: SNR = 30, MCS = 27, 273 PRBs, 2 layers, 4 antennas true + caracal nr_dlsim 450 -n1000 -s30 -S30.2 -e25 -b273 -R273 -X4,5,6,7,8,9 -x2 -z4 -y4 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 From c4efe9feed59fe8299477902332c4d5e21ad24b5 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 11 Aug 2025 13:11:00 +0200 Subject: [PATCH 486/964] cls_containerize: yamlPath/services as normal string These variables were set as lists, to be indexed by the "server ID". Since this has been removed from all XMLs, it is not necessary anymore. --- ci-scripts/cls_containerize.py | 10 +++++----- ci-scripts/main.py | 8 ++------ ci-scripts/tests/deployment.py | 22 +++++++++++----------- 3 files changed, 18 insertions(+), 22 deletions(-) diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index 282fe0f4a0..b45aed5d8d 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -247,8 +247,8 @@ class Containerize(): self.proxyCommit = None self.eNB_instance = 0 self.eNB_serverId = ['', '', ''] - self.yamlPath = ['', '', ''] - self.services = ['', '', ''] + self.yamlPath = '' + self.services = '' self.deploymentTag = '' self.cli = '' @@ -746,11 +746,11 @@ class Containerize(): num_attempts = self.num_attempts lSourcePath = self.eNBSourceCodePath logging.debug(f'Deploying OAI Object on server: {node}') - yaml = self.yamlPath[self.eNB_instance].strip('/') + yaml = self.yamlPath.strip('/') wd = f'{lSourcePath}/{yaml}' wd_yaml = f'{wd}/docker-compose.y*ml' with cls_cmd.getConnection(node) as ssh: - services = GetServices(ssh, self.services[self.eNB_instance], wd_yaml) + services = GetServices(ssh, self.services, wd_yaml) if services == [] or services == ' ' or services == None: msg = 'Cannot determine services to start' logging.error(msg) @@ -788,7 +788,7 @@ class Containerize(): def UndeployObject(self, ctx, node, HTML, RAN): lSourcePath = self.eNBSourceCodePath logging.debug(f'\u001B[1m Undeploying OAI Object from server: {node}\u001B[0m') - yaml = self.yamlPath[self.eNB_instance].strip('/') + yaml = self.yamlPath.strip('/') wd = f'{lSourcePath}/{yaml}' with cls_cmd.getConnection(node) as ssh: ExistEnvFilePrint(ssh, wd) diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 90b5b7de90..76c3962437 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -285,18 +285,14 @@ def ExecuteActionWithParam(action, ctx): elif action == 'Deploy_Object' or action == 'Undeploy_Object' or action == "Create_Workspace": node = test.findtext('node') - string_field = test.findtext('yaml_path') - if (string_field is not None): - CONTAINERS.yamlPath[CONTAINERS.eNB_instance] = string_field + CONTAINERS.yamlPath = test.findtext('yaml_path') string_field=test.findtext('d_retx_th') if (string_field is not None): CONTAINERS.ran_checkers['d_retx_th'] = [float(x) for x in string_field.split(',')] string_field=test.findtext('u_retx_th') if (string_field is not None): CONTAINERS.ran_checkers['u_retx_th'] = [float(x) for x in string_field.split(',')] - string_field = test.findtext('services') - if string_field is not None: - CONTAINERS.services[CONTAINERS.eNB_instance] = string_field + CONTAINERS.services = test.findtext('services') CONTAINERS.num_attempts = int(test.findtext('num_attempts') or 1) CONTAINERS.deploymentTag = cls_containerize.CreateTag(CONTAINERS.ranCommitID, CONTAINERS.ranBranch, CONTAINERS.ranAllowMerge) if action == 'Deploy_Object': diff --git a/ci-scripts/tests/deployment.py b/ci-scripts/tests/deployment.py index 60c88f39a1..e7efc707bf 100644 --- a/ci-scripts/tests/deployment.py +++ b/ci-scripts/tests/deployment.py @@ -40,7 +40,7 @@ class TestDeploymentMethods(unittest.TestCase): self.ci = cls_oaicitest.OaiCiTest() self.cont = cls_containerize.Containerize() self.ran = ran.RANManagement() - self.cont.yamlPath[0] = '' + self.cont.yamlPath = '' self.cont.ranAllowMerge = True self.cont.ranBranch = '' self.cont.ranCommitID = '' @@ -53,7 +53,7 @@ class TestDeploymentMethods(unittest.TestCase): c.run(f'rm -rf {self.ctx.logPath}') def test_deploy(self): - self.cont.yamlPath[0] = 'tests/simple-dep/' + self.cont.yamlPath = 'tests/simple-dep/' self.cont.deploymentTag = "noble" deploy = self.cont.DeployObject(self.ctx, self.node, self.html) undeploy = self.cont.UndeployObject(self.ctx, self.node, self.html, self.ran) @@ -63,7 +63,7 @@ class TestDeploymentMethods(unittest.TestCase): def test_deployfails(self): # fails reliably old = self.cont.yamlPath - self.cont.yamlPath[0] = 'tests/simple-fail/' + self.cont.yamlPath = 'tests/simple-fail/' deploy = self.cont.DeployObject(self.ctx, self.node, self.html) self.cont.UndeployObject(self.ctx, self.node, self.html, self.ran) self.assertFalse(deploy) @@ -72,15 +72,15 @@ class TestDeploymentMethods(unittest.TestCase): def test_deployfails_2svc(self): # fails reliably old = self.cont.yamlPath - self.cont.yamlPath[0] = 'tests/simple-fail-2svc/' + self.cont.yamlPath = 'tests/simple-fail-2svc/' deploy = self.cont.DeployObject(self.ctx, self.node, self.html) self.cont.UndeployObject(self.ctx, self.node, self.html, self.ran) self.assertFalse(deploy) self.cont.yamlPath = old def test_deploy_ran(self): - self.cont.yamlPath[0] = 'yaml_files/5g_rfsimulator_tdd_dora' - self.cont.services[0] = "oai-gnb" + self.cont.yamlPath = 'yaml_files/5g_rfsimulator_tdd_dora' + self.cont.services = "oai-gnb" self.cont.deploymentTag = 'develop-12345678' deploy = self.cont.DeployObject(self.ctx, self.node, self.html) undeploy = self.cont.UndeployObject(self.ctx, self.node, self.html, self.ran) @@ -88,8 +88,8 @@ class TestDeploymentMethods(unittest.TestCase): self.assertTrue(undeploy) def test_deploy_multiran(self): - self.cont.yamlPath[0] = 'yaml_files/5g_rfsimulator_tdd_dora' - self.cont.services[0] = "oai-gnb oai-nr-ue" + self.cont.yamlPath = 'yaml_files/5g_rfsimulator_tdd_dora' + self.cont.services = "oai-gnb oai-nr-ue" self.cont.deploymentTag = 'develop-12345678' deploy = self.cont.DeployObject(self.ctx, self.node, self.html) undeploy = self.cont.UndeployObject(self.ctx, self.node, self.html, self.ran) @@ -97,11 +97,11 @@ class TestDeploymentMethods(unittest.TestCase): self.assertTrue(undeploy) def test_deploy_staged(self): - self.cont.yamlPath[0] = 'yaml_files/5g_rfsimulator_tdd_dora' - self.cont.services[0] = "oai-gnb" + self.cont.yamlPath = 'yaml_files/5g_rfsimulator_tdd_dora' + self.cont.services = "oai-gnb" self.cont.deploymentTag = 'develop-12345678' deploy1 = self.cont.DeployObject(self.ctx, self.node, self.html) - self.cont.services[0] = "oai-nr-ue" + self.cont.services = "oai-nr-ue" deploy2 = self.cont.DeployObject(self.ctx, self.node, self.html) undeploy = self.cont.UndeployObject(self.ctx, self.node, self.html, self.ran) self.assertTrue(deploy1) From 45da9face4e2830ae13a022bfe464f27aa0beb59 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 11 Aug 2025 14:35:42 +0200 Subject: [PATCH 487/964] Reimplement Initialize_eNB()/Terminate_eNB() Reimplement these functions by - using cls_cmd - retain only the necessary steps from the timing-phytest function - pass in ctx and node information, instead of server ID - remove all superfluous variables that don't seem to be used - make some lists (corresponding indices are "server ID") into normal variables. --- ci-scripts/main.py | 45 +-- ci-scripts/ran.py | 333 +++++------------- ci-scripts/xml_files/gnb_phytest_usrp_run.xml | 2 + .../gnb_phytest_usrp_run_100_2x2.xml | 2 + .../xml_files/gnb_phytest_usrp_run_60.xml | 2 + .../xml_files/gnb_phytest_usrp_run_60_2x2.xml | 2 + 6 files changed, 101 insertions(+), 285 deletions(-) diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 76c3962437..6847e10950 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -126,53 +126,30 @@ def ExecuteActionWithParam(action, ctx): success = CONTAINERS.BuildRunTests(ctx, node, HTML) elif action == 'Initialize_eNB': + node = test.findtext('node') datalog_rt_stats_file=test.findtext('rt_stats_cfg') if datalog_rt_stats_file is None: RAN.datalog_rt_stats_file='datalog_rt_stats.default.yaml' else: RAN.datalog_rt_stats_file=datalog_rt_stats_file RAN.Initialize_eNB_args=test.findtext('Initialize_eNB_args') - eNB_instance=test.findtext('eNB_instance') - USRPIPAddress=test.findtext('USRP_IPAddress') - if USRPIPAddress is None: - RAN.USRPIPAddress='' - else: - RAN.USRPIPAddress=USRPIPAddress - if (eNB_instance is None): - RAN.eNB_instance=0 - else: - RAN.eNB_instance=int(eNB_instance) - eNB_serverId=test.findtext('eNB_serverId') - if (eNB_serverId is None): - RAN.eNB_serverId[RAN.eNB_instance]='0' - else: - RAN.eNB_serverId[RAN.eNB_instance]=eNB_serverId - + USRPIPAddress = test.findtext('USRP_IPAddress') or '' + #local variable air_interface air_interface = test.findtext('air_interface') if (air_interface is None) or (air_interface.lower() not in ['nr','lte']): - RAN.air_interface[RAN.eNB_instance] = 'lte-softmodem' + RAN.air_interface = 'lte-softmodem' else: - RAN.air_interface[RAN.eNB_instance] = air_interface.lower() +'-softmodem' + RAN.air_interface = air_interface.lower() +'-softmodem' cmd_prefix = test.findtext('cmd_prefix') if cmd_prefix is not None: RAN.cmd_prefix = cmd_prefix - success = RAN.InitializeeNB(HTML) + success = RAN.InitializeeNB(ctx, node, HTML) elif action == 'Terminate_eNB': - eNB_instance=test.findtext('eNB_instance') - if (eNB_instance is None): - RAN.eNB_instance=0 - else: - RAN.eNB_instance=int(eNB_instance) - eNB_serverId=test.findtext('eNB_serverId') - if (eNB_serverId is None): - RAN.eNB_serverId[RAN.eNB_instance]='0' - else: - RAN.eNB_serverId[RAN.eNB_instance]=eNB_serverId - + node = test.findtext('node') #retx checkers - string_field=test.findtext('d_retx_th') + string_field = test.findtext('d_retx_th') if (string_field is not None): RAN.ran_checkers['d_retx_th'] = [float(x) for x in string_field.split(',')] string_field=test.findtext('u_retx_th') @@ -182,10 +159,10 @@ def ExecuteActionWithParam(action, ctx): #local variable air_interface air_interface = test.findtext('air_interface') if (air_interface is None) or (air_interface.lower() not in ['nr','lte']): - RAN.air_interface[RAN.eNB_instance] = 'lte-softmodem' + RAN.air_interface = 'lte-softmodem' else: - RAN.air_interface[RAN.eNB_instance] = air_interface.lower() +'-softmodem' - success = RAN.TerminateeNB(ctx, HTML) + RAN.air_interface = air_interface.lower() +'-softmodem' + success = RAN.TerminateeNB(ctx, node, HTML) elif action == 'Initialize_UE' or action == 'Attach_UE' or action == 'Detach_UE' or action == 'Terminate_UE' or action == 'CheckStatusUE' or action == 'DataEnable_UE' or action == 'DataDisable_UE': CiTestObj.ue_ids = test.findtext('id').split(' ') diff --git a/ci-scripts/ran.py b/ci-scripts/ran.py index c41fec09c6..1d96308c1d 100644 --- a/ci-scripts/ran.py +++ b/ci-scripts/ran.py @@ -43,7 +43,7 @@ import cls_cmd #----------------------------------------------------------- # OAI Testing modules #----------------------------------------------------------- -import sshconnection as SSH +import cls_cmd import helpreadme as HELP import constants as CONST from cls_ci_helper import archiveArtifact @@ -72,19 +72,13 @@ class RANManagement(): self.eNB2UserName = '' self.eNB2Password = '' self.eNB2SourceCodePath = '' - self.Build_eNB_args = '' - self.Build_eNB_forced_workspace_cleanup = False self.Initialize_eNB_args = '' self.imageKind = '' - self.air_interface = ['', '', ''] #changed from 'lte' to '' may lead to side effects in main - self.eNB_instance = 0 - self.eNB_serverId = ['', '', ''] - self.eNBLogFiles = ['', '', ''] + self.air_interface = '' self.eNBOptions = ['', '', ''] self.eNBmbmsEnables = [False, False, False] self.eNBstatuses = [-1, -1, -1] self.testCase_id = '' - self.epcPcapFile = '' self.runtime_stats= '' self.datalog_rt_stats={} self.datalog_rt_stats_file='datalog_rt_stats.default.yaml' @@ -100,261 +94,98 @@ class RANManagement(): # RAN management functions #----------------------------------------------------------- - def InitializeeNB(self, HTML): - if self.eNB_serverId[self.eNB_instance] == '0': - lIpAddr = self.eNBIPAddress - lUserName = self.eNBUserName - lPassWord = self.eNBPassword - lSourcePath = self.eNBSourceCodePath - elif self.eNB_serverId[self.eNB_instance] == '1': - lIpAddr = self.eNB1IPAddress - lUserName = self.eNB1UserName - lPassWord = self.eNB1Password - lSourcePath = self.eNB1SourceCodePath - elif self.eNB_serverId[self.eNB_instance] == '2': - lIpAddr = self.eNB2IPAddress - lUserName = self.eNB2UserName - lPassWord = self.eNB2Password - lSourcePath = self.eNB2SourceCodePath - if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': - HELP.GenericHelp(CONST.Version) - sys.exit('Insufficient Parameter') - logging.debug('Starting eNB/gNB on server: ' + lIpAddr) + def InitializeeNB(self, ctx, node, HTML): + if not node: + raise ValueError(f"{node=}") + logging.debug('Starting eNB/gNB on server: ' + node) self.testCase_id = HTML.testCase_id - mySSH = SSH.SSHConnection() + lSourcePath = self.eNBSourceCodePath + cmd = cls_cmd.getConnection(node) - mySSH.open(lIpAddr, lUserName, lPassWord) - mySSH.command('cd ' + lSourcePath, '\$', 5) # Initialize_eNB_args usually start with -O and followed by the location in repository full_config_file = self.Initialize_eNB_args.replace('-O ','') extra_options = '' extIdx = full_config_file.find('.conf') - if (extIdx > 0): - extra_options = full_config_file[extIdx + 5:] - # if tracer options is on, compiling and running T Tracer - result = re.search('T_stdout', str(extra_options)) - if result is not None: - logging.debug('\u001B[1m Compiling and launching T Tracer\u001B[0m') - mySSH.command('cd common/utils/T/tracer', '\$', 5) - mySSH.command('make', '\$', 10) - mySSH.command('echo $USER; nohup ./record -d ../T_messages.txt -o ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '_record.raw -ON -off VCD -off HEAVY -off LEGACY_GROUP_TRACE -off LEGACY_GROUP_DEBUG > ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '_record.log 2>&1 &', lUserName, 5) - mySSH.command('cd ' + lSourcePath, '\$', 5) - full_config_file = full_config_file[:extIdx + 5] - config_path, config_file = os.path.split(full_config_file) - else: - sys.exit('Insufficient Parameter') - ci_full_config_file = config_path + '/ci-' + config_file - rruCheck = False - result = re.search('^rru|^rcc|^du.band', str(config_file)) - if result is not None: - rruCheck = True - mySSH.command('cp ' + full_config_file + ' ' + ci_full_config_file, '\$', 5) - mySSH.command('sed -i -e \'s/CI_ENB_IP_ADDR/' + lIpAddr + '/\' ' + ci_full_config_file, '\$', 2); - mySSH.command('sed -i -e \'s/CI_GNB_IP_ADDR/' + lIpAddr + '/\' ' + ci_full_config_file, '\$', 2); - mySSH.command('sed -i -e \'s/CI_RCC_IP_ADDR/' + self.eNBIPAddress + '/\' ' + ci_full_config_file, '\$', 2); - mySSH.command('sed -i -e \'s/CI_RRU1_IP_ADDR/' + self.eNB1IPAddress + '/\' ' + ci_full_config_file, '\$', 2); - mySSH.command('sed -i -e \'s/CI_RRU2_IP_ADDR/' + self.eNB2IPAddress + '/\' ' + ci_full_config_file, '\$', 2); - mySSH.command('sed -i -e \'s/CI_FR1_CTL_ENB_IP_ADDR/' + self.eNBIPAddress + '/\' ' + ci_full_config_file, '\$', 2); - self.eNBmbmsEnables[int(self.eNB_instance)] = False - mySSH.command('grep --colour=never enable_enb_m2 ' + ci_full_config_file, '\$', 2); - result = re.search('yes', mySSH.getBefore()) - if result is not None: - self.eNBmbmsEnables[int(self.eNB_instance)] = True - logging.debug('\u001B[1m MBMS is enabled on this eNB\u001B[0m') - result = re.search('noS1', str(self.Initialize_eNB_args)) - eNBinNoS1 = False - if result is not None: - eNBinNoS1 = True - logging.debug('\u001B[1m eNB is in noS1 configuration \u001B[0m') - # Launch eNB with the modified config file - mySSH.command('source oaienv', '\$', 5) - mySSH.command('cd cmake_targets', '\$', 5) - if self.air_interface[self.eNB_instance] == 'nr-softmodem': - mySSH.command('if [ -e rbconfig.raw ]; then echo ' + lPassWord + ' | sudo -S rm rbconfig.raw; fi', '\$', 5) - mySSH.command('if [ -e reconfig.raw ]; then echo ' + lPassWord + ' | sudo -S rm reconfig.raw; fi', '\$', 5) - # NOTE: WE SHALL do a check if the executable is present (in case build went wrong) + if (extIdx <= 0): + raise ValueError(f"no config file in {self.Initialize_eNB_args}") + extra_options = full_config_file[extIdx + 5:] + full_config_file = full_config_file[:extIdx + 5] + config_path, config_file = os.path.split(full_config_file) - #hack UHD_RFNOC_DIR variable for gNB / N310 on RHEL8 server: - #if the USRP address is in the xml then we are using an eth USRP (N3xx) - if self.air_interface[self.eNB_instance] == 'lte-softmodem': - gNB = False - else: - gNB = True - mySSH.command(f'echo "ulimit -c unlimited && {self.cmd_prefix} ./ran_build/build/{self.air_interface[self.eNB_instance]} -O {lSourcePath}/{ci_full_config_file} {extra_options}" > ./my-lte-softmodem-run{self.eNB_instance}.sh', '\$', 5) + logfile = f'{lSourcePath}/cmake_targets/enb.log' + cmd.cd(f"{lSourcePath}/cmake_targets/") # important: set wd so nrL1_stats.log etc are logged here + cmd.run(f'sudo -E stdbuf -o0 {self.cmd_prefix} {lSourcePath}/cmake_targets/ran_build/build/{self.air_interface} -O {lSourcePath}/{full_config_file} {extra_options} > {logfile} 2>&1 &') - mySSH.command('chmod 775 ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) - mySSH.command('echo ' + lPassWord + ' | sudo -S rm -Rf enb_' + self.testCase_id + '.log', '\$', 5) - mySSH.command('echo $USER; nohup sudo -E stdbuf -o0 ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh > ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '.log 2>&1 &', lUserName, 10) - - self.eNBLogFiles[int(self.eNB_instance)] = 'enb_' + self.testCase_id + '.log' if extra_options != '': - self.eNBOptions[int(self.eNB_instance)] = extra_options - time.sleep(6) - doLoop = True - loopCounter = 20 + self.eNBOptions = extra_options + enbDidSync = False - while (doLoop): - loopCounter = loopCounter - 1 - if (loopCounter == 0): - # In case of T tracer recording, we may need to kill it - result = re.search('T_stdout', str(self.Initialize_eNB_args)) - if result is not None: - mySSH.command('killall --signal SIGKILL record', '\$', 5) - mySSH.close() - doLoop = False - logging.error('\u001B[1;37;41m eNB/gNB logging system did not show got sync! \u001B[0m') - HTML.CreateHtmlTestRow(self.air_interface[self.eNB_instance] + ' -O ' + config_file + extra_options, 'KO', CONST.ALL_PROCESSES_OK) - return False - else: - mySSH.command('stdbuf -o0 cat enb_' + self.testCase_id + '.log | grep -E --text --color=never -i "wait|sync|Starting|Started"', '\$', 4) - if rruCheck: - result = re.search('wait RUs', mySSH.getBefore()) - else: - result = re.search('got sync|Starting F1AP at CU', mySSH.getBefore()) - if result is None: - time.sleep(6) - else: - doLoop = False - enbDidSync = True - time.sleep(10) - - rruCheck = False - result = re.search('^rru|^du.band', str(config_file)) - if result is not None: - rruCheck = True - if enbDidSync and eNBinNoS1 and not rruCheck: - mySSH.command('ifconfig oaitun_enb1', '\$', 4) - mySSH.command('ifconfig oaitun_enb1', '\$', 4) - result = re.search('inet addr:1|inet 1', mySSH.getBefore()) + for _ in range(10): + time.sleep(5) + ret = cmd.run(f'grep --text -E --color=never -i "wait|sync|Starting|Started" {logfile}', reportNonZero=False) + result = re.search('got sync|Starting F1AP at CU', ret.stdout) if result is not None: - logging.debug('\u001B[1m oaitun_enb1 interface is mounted and configured\u001B[0m') - else: - logging.error('\u001B[1m oaitun_enb1 interface is either NOT mounted or NOT configured\u001B[0m') - if self.eNBmbmsEnables[int(self.eNB_instance)]: - mySSH.command('ifconfig oaitun_enm1', '\$', 4) - result = re.search('inet addr', mySSH.getBefore()) - if result is not None: - logging.debug('\u001B[1m oaitun_enm1 interface is mounted and configured\u001B[0m') - else: - logging.error('\u001B[1m oaitun_enm1 interface is either NOT mounted or NOT configured\u001B[0m') + enbDidSync = True + break + if not enbDidSync: + cmd.run(f'sudo killall -9 {self.air_interface}') # in case it did not stop automatically + archiveArtifact(cmd, ctx, logfile) + + cmd.close() + + msg = f'{self.cmd_prefix} {self.air_interface} -O {config_file} {extra_options}' if enbDidSync: - self.eNBstatuses[int(self.eNB_instance)] = int(self.eNB_serverId[self.eNB_instance]) + logging.debug('\u001B[1m Initialize eNB/gNB Completed\u001B[0m') + HTML.CreateHtmlTestRowQueue(msg, 'OK', []) + else: + logging.error('\u001B[1;37;41m eNB/gNB logging system did not show got sync! \u001B[0m') + HTML.CreateHtmlTestRowQueue(msg, 'KO', []) - mySSH.close() - - HTML.CreateHtmlTestRow(f'{self.cmd_prefix} {self.air_interface[self.eNB_instance]} -O {config_file} {extra_options}', 'OK', CONST.ALL_PROCESSES_OK) - logging.debug('\u001B[1m Initialize eNB/gNB Completed\u001B[0m') return enbDidSync - def TerminateeNB(self, ctx, HTML): - if self.eNB_serverId[self.eNB_instance] == '0': - lIpAddr = self.eNBIPAddress - lUserName = self.eNBUserName - lPassWord = self.eNBPassword - lSourcePath = self.eNBSourceCodePath - elif self.eNB_serverId[self.eNB_instance] == '1': - lIpAddr = self.eNB1IPAddress - lUserName = self.eNB1UserName - lPassWord = self.eNB1Password - lSourcePath = self.eNB1SourceCodePath - elif self.eNB_serverId[self.eNB_instance] == '2': - lIpAddr = self.eNB2IPAddress - lUserName = self.eNB2UserName - lPassWord = self.eNB2Password - lSourcePath = self.eNB2SourceCodePath - if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': - HELP.GenericHelp(CONST.Version) - sys.exit('Insufficient Parameter') - logging.debug('Stopping eNB/gNB on server: ' + lIpAddr) - mySSH = SSH.SSHConnection() - mySSH.open(lIpAddr, lUserName, lPassWord) - mySSH.command('cd ' + lSourcePath + '/cmake_targets', '\$', 5) - if self.air_interface[self.eNB_instance] == 'lte-softmodem': - nodeB_prefix = 'e' - else: - nodeB_prefix = 'g' - mySSH.command('stdbuf -o0 ps -aux | grep --color=never -e softmodem | grep -v grep', '\$', 5) - result = re.search('-softmodem', mySSH.getBefore()) + def TerminateeNB(self, ctx, node, HTML): + logging.debug('Stopping eNB/gNB on server: ' + node) + lSourcePath = self.eNBSourceCodePath + cmd = cls_cmd.getConnection(node) + ret = cmd.run('ps -aux | grep --color=never -e softmodem | grep -v grep') + result = re.search('-softmodem', ret.stdout) if result is not None: - mySSH.command('echo ' + lPassWord + ' | sudo -S killall --signal SIGINT -r .*-softmodem || true', '\$', 5) - time.sleep(10) - mySSH.command('stdbuf -o0 ps -aux | grep --color=never -e softmodem | grep -v grep', '\$', 5) - result = re.search('-softmodem', mySSH.getBefore()) - if result is not None: - mySSH.command('echo ' + lPassWord + ' | sudo -S killall --signal SIGKILL -r .*-softmodem || true', '\$', 5) - time.sleep(5) - mySSH.command('rm -f my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) - #stopping tshark (valid if eNB and enabled in xml, will not harm otherwise) - logging.debug('\u001B[1m Stopping tshark on xNB \u001B[0m') - mySSH.command('echo ' + lPassWord + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5) - time.sleep(1) - mySSH.close() - # if T tracer was run with option 0 (no logs), analyze logs - # from textlog, otherwise do normal analysis (e.g., option 2) - result = re.search('T_stdout 0', str(self.Initialize_eNB_args)) - if (result is not None): - logging.debug('\u001B[1m Replaying RAW record file\u001B[0m') - mySSH.open(lIpAddr, lUserName, lPassWord) - mySSH.command('cd ' + lSourcePath + '/common/utils/T/tracer/', '\$', 5) - enbLogFile = self.eNBLogFiles[int(self.eNB_instance)] - raw_record_file = enbLogFile.replace('.log', '_record.raw') - replay_log_file = enbLogFile.replace('.log', '_replay.log') - extracted_txt_file = enbLogFile.replace('.log', '_extracted_messages.txt') - extracted_log_file = enbLogFile.replace('.log', '_extracted_messages.log') - mySSH.command('./extract_config -i ' + lSourcePath + '/cmake_targets/' + raw_record_file + ' > ' + lSourcePath + '/cmake_targets/' + extracted_txt_file, '\$', 5) - mySSH.command('echo $USER; nohup ./replay -i ' + lSourcePath + '/cmake_targets/' + raw_record_file + ' > ' + lSourcePath + '/cmake_targets/' + replay_log_file + ' 2>&1 &', lUserName, 5) - mySSH.command('./textlog -d ' + lSourcePath + '/cmake_targets/' + extracted_txt_file + ' -no-gui -ON -full > ' + lSourcePath + '/cmake_targets/' + extracted_log_file, '\$', 5) - mySSH.close() - mySSH.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/' + extracted_log_file, '.') - logging.debug('\u001B[1m Analyzing eNB replay logfile \u001B[0m') - logStatus = self.AnalyzeLogFile_eNB(extracted_log_file, HTML, self.ran_checkers) + cmd.run('sudo -S killall --signal SIGINT -r .*-softmodem') + time.sleep(6) + + ret = cmd.run('ps -aux | grep --color=never -e softmodem | grep -v grep') + result = re.search('-softmodem', ret.stdout) + if result is not None: + cmd.run('sudo -S killall --signal SIGKILL -r .*-softmodem') + time.sleep(5) + + # see InitializeeNB() + logfile = f'{lSourcePath}/cmake_targets/enb.log' + logdir = os.path.dirname(logfile) + + file = archiveArtifact(cmd, ctx, logfile) + archiveArtifact(cmd, ctx, f"{logdir}/nrL1_stats.log") + archiveArtifact(cmd, ctx, f"{logdir}/nrMAC_stats.log") + cmd.close() + if file is None: + logging.debug('\u001B[1;37;41m Could not copy xNB logfile to analyze it! \u001B[0m') + msg = 'Could not copy xNB logfile to analyze it!' + HTML.CreateHtmlTestRowQueue('N/A', 'KO', [msg]) + return False + + logging.debug('\u001B[1m Analyzing xNB logfile \u001B[0m ' + file) + logStatus = self.AnalyzeLogFile_eNB(file, HTML, self.ran_checkers) + if logStatus < 0: + HTML.CreateHtmlTestRow('N/A', 'KO', logStatus) + else: HTML.CreateHtmlTestRow(self.runtime_stats, 'OK', CONST.ALL_PROCESSES_OK) - self.eNBLogFiles[int(self.eNB_instance)] = '' - return True - else: - analyzeFile = False - if self.eNBLogFiles[int(self.eNB_instance)] != '': - analyzeFile = True - fileToAnalyze = self.eNBLogFiles[int(self.eNB_instance)] - self.eNBLogFiles[int(self.eNB_instance)] = '' - if analyzeFile: - with cls_cmd.getConnection(lIpAddr) as cmd: - file = archiveArtifact(cmd, ctx, lSourcePath + '/cmake_targets/' + fileToAnalyze) - archiveArtifact(cmd, ctx, lSourcePath + '/cmake_targets/nrL1_stats.log') - archiveArtifact(cmd, ctx, lSourcePath + '/cmake_targets/nrMAC_stats.log') - if file is None: - logging.debug('\u001B[1;37;41m Could not copy ' + nodeB_prefix + 'NB logfile to analyze it! \u001B[0m') - HTML.htmleNBFailureMsg='Could not copy ' + nodeB_prefix + 'NB logfile to analyze it!' - HTML.CreateHtmlTestRow('N/A', 'KO', CONST.ENB_PROCESS_NOLOGFILE_TO_ANALYZE) - self.eNBmbmsEnables[int(self.eNB_instance)] = False - return False - if self.eNB_serverId[self.eNB_instance] != '0': - #*stats.log files + pickle + png - #debug / tentative - mySSH.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, './nrL1_stats.log', self.eNBSourceCodePath + '/cmake_targets/') - mySSH.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, './nrMAC_stats.log', self.eNBSourceCodePath + '/cmake_targets/') - mySSH.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, './' + fileToAnalyze, self.eNBSourceCodePath + '/cmake_targets/') - logging.debug('\u001B[1m Analyzing ' + nodeB_prefix + 'NB logfile \u001B[0m ' + file) - logStatus = self.AnalyzeLogFile_eNB(file, HTML, self.ran_checkers) - if (logStatus < 0): - HTML.CreateHtmlTestRow('N/A', 'KO', logStatus) - #display rt stats for gNB only - if len(self.datalog_rt_stats)!=0 and nodeB_prefix == 'g': - HTML.CreateHtmlDataLogTable(self.datalog_rt_stats) - self.eNBmbmsEnables[int(self.eNB_instance)] = False - return False - else: - HTML.CreateHtmlTestRow(self.runtime_stats, 'OK', CONST.ALL_PROCESSES_OK) - else: - HTML.CreateHtmlTestRow(self.runtime_stats, 'OK', CONST.ALL_PROCESSES_OK) #display rt stats for gNB only - if len(self.datalog_rt_stats)!=0 and nodeB_prefix == 'g': + if len(self.datalog_rt_stats) != 0: HTML.CreateHtmlDataLogTable(self.datalog_rt_stats) - self.eNBmbmsEnables[int(self.eNB_instance)] = False - self.eNBstatuses[int(self.eNB_instance)] = -1 - return True + + return logStatus >= 0 def LogCollecteNB(self): mySSH = SSH.SSHConnection() @@ -526,16 +357,16 @@ class RANManagement(): X2HO_state = CONST.X2_HO_REQ_STATE__IDLE X2HO_outNbProcedures += 1 - if self.eNBOptions[int(self.eNB_instance)] != '': - res1 = re.search('max_rxgain (?P[0-9]+)', self.eNBOptions[int(self.eNB_instance)]) + if self.eNBOptions[0] != '': + res1 = re.search('max_rxgain (?P[0-9]+)', self.eNBOptions[0]) res2 = re.search('max_rxgain (?P[0-9]+)', str(line)) if res1 is not None and res2 is not None: requested_option = int(res1.group('requested_option')) applied_option = int(res2.group('applied_option')) if requested_option == applied_option: - htmleNBFailureMsg += ' Command line option(s) correctly applied ' + self.eNBOptions[int(self.eNB_instance)] + '\n\n' + htmleNBFailureMsg += ' Command line option(s) correctly applied ' + self.eNBOptions[0] + '\n\n' else: - htmleNBFailureMsg += ' Command line option(s) NOT applied ' + self.eNBOptions[int(self.eNB_instance)] + '\n\n' + htmleNBFailureMsg += ' Command line option(s) NOT applied ' + self.eNBOptions[0] + '\n\n' result = re.search('Exiting OAI softmodem|Caught SIGTERM, shutting down', str(line)) if result is not None: exitSignalReceived = True @@ -622,7 +453,7 @@ class RANManagement(): result = re.search('dropping, not enough RBs', str(line)) if result is not None: dropNotEnoughRBs += 1 - if self.eNBmbmsEnables[int(self.eNB_instance)]: + if self.eNBmbmsEnables[0]: result = re.search('MBMS USER-PLANE.*Requesting.*bytes from RLC', str(line)) if result is not None: mbmsRequestMsg += 1 @@ -731,7 +562,7 @@ class RANManagement(): #post processing depending on the node type if not nodeB_prefix_found: - if self.air_interface[self.eNB_instance] == 'lte-softmodem': + if self.air_interface == 'lte-softmodem': nodeB_prefix = 'e' else: nodeB_prefix = 'g' @@ -935,7 +766,7 @@ class RANManagement(): rrcMsg = ' -- ' + str(rrcReestablishReject) + ' were rejected' logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') htmleNBFailureMsg += rrcMsg + '\n' - if self.eNBmbmsEnables[int(self.eNB_instance)]: + if self.eNBmbmsEnables[0]: if mbmsRequestMsg > 0: rrcMsg = 'eNB requested ' + str(mbmsRequestMsg) + ' times the RLC for MBMS USER-PLANE' logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') @@ -948,8 +779,8 @@ class RANManagement(): rrcMsg = 'eNB completed ' + str(X2HO_outNbProcedures) + ' X2 Handover Release procedure(s)' logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') htmleNBFailureMsg += rrcMsg + '\n' - if self.eNBOptions[int(self.eNB_instance)] != '': - res1 = re.search('drx_Config_present prSetup', self.eNBOptions[int(self.eNB_instance)]) + if self.eNBOptions[0] != '': + res1 = re.search('drx_Config_present prSetup', self.eNBOptions[0]) if res1 is not None: if cdrxActivationMessageCount > 0: rrcMsg = 'eNB activated the CDRX Configuration for ' + str(cdrxActivationMessageCount) + ' time(s)' diff --git a/ci-scripts/xml_files/gnb_phytest_usrp_run.xml b/ci-scripts/xml_files/gnb_phytest_usrp_run.xml index 658d0b8c70..5adeb17966 100644 --- a/ci-scripts/xml_files/gnb_phytest_usrp_run.xml +++ b/ci-scripts/xml_files/gnb_phytest_usrp_run.xml @@ -45,6 +45,7 @@ Initialize_eNB Initialize gNB USRP + caracal -O ci-scripts/conf_files/gnb.band79.106prb.usrpn300.phytest-dora.conf --phy-test -q -U 768 -T 106 -t 23 -D 127 -m 28 -M 106 --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time datalog_rt_stats.default.yaml NR @@ -63,6 +64,7 @@ Terminate_eNB true Terminate gNB + caracal NR diff --git a/ci-scripts/xml_files/gnb_phytest_usrp_run_100_2x2.xml b/ci-scripts/xml_files/gnb_phytest_usrp_run_100_2x2.xml index 3a24805449..7821be863c 100644 --- a/ci-scripts/xml_files/gnb_phytest_usrp_run_100_2x2.xml +++ b/ci-scripts/xml_files/gnb_phytest_usrp_run_100_2x2.xml @@ -45,6 +45,7 @@ Initialize_eNB Initialize gNB USRP + caracal -O ci-scripts/conf_files/gnb.band79.273prb.usrpn300.phytest-dora.conf --phy-test -q -U 768 -T 273 -t 23 -D 127 -m 23 -M 273 -l 2 --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time datalog_rt_stats.100.2x2.yaml NR @@ -63,6 +64,7 @@ Terminate_eNB true Terminate gNB + caracal NR diff --git a/ci-scripts/xml_files/gnb_phytest_usrp_run_60.xml b/ci-scripts/xml_files/gnb_phytest_usrp_run_60.xml index bececb210f..72e4b5244e 100644 --- a/ci-scripts/xml_files/gnb_phytest_usrp_run_60.xml +++ b/ci-scripts/xml_files/gnb_phytest_usrp_run_60.xml @@ -45,6 +45,7 @@ Initialize_eNB Initialize gNB USRP + caracal -O ci-scripts/conf_files/gnb.band79.162prb.usrpn300.phytest-dora.conf --phy-test -q -U 768 -T 162 -t 23 -D 127 -m 23 -M 162 --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time datalog_rt_stats.1x1.60.yaml NR @@ -63,6 +64,7 @@ Terminate_eNB true Terminate gNB + caracal NR diff --git a/ci-scripts/xml_files/gnb_phytest_usrp_run_60_2x2.xml b/ci-scripts/xml_files/gnb_phytest_usrp_run_60_2x2.xml index 503f0880a5..1be4a24477 100644 --- a/ci-scripts/xml_files/gnb_phytest_usrp_run_60_2x2.xml +++ b/ci-scripts/xml_files/gnb_phytest_usrp_run_60_2x2.xml @@ -45,6 +45,7 @@ Initialize_eNB Initialize gNB USRP + caracal -O ci-scripts/conf_files/gnb.band79.162prb.usrpn300.phytest-dora.conf --phy-test --gNBs.[0].pdsch_AntennaPorts_XP 2 --RUs.[0].nb_tx 2 --RUs.[0].nb_rx 2 -q -U 768 -T 162 -t 23 -D 127 -m 23 -M 162 -l 2 --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time datalog_rt_stats.60.2x2.yaml NR @@ -63,6 +64,7 @@ Terminate_eNB true Terminate gNB + caracal NR From dc27690c86f02d88db6b39f16b08e2b1a2679c4c Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 11 Aug 2025 15:03:50 +0200 Subject: [PATCH 488/964] LogCollecteNB() not used anymore Since 28ce0dc444fa2 ("Main: pass in ctx"), the CI always collects logs into cmake_targets/log/. Hence, LogCollecteNB() is never called. We can remove it. Further, change the cmake_targets/log/ to ci-log/, which is shorter, and append a / on the zip path to make sure that only contents is zipped. --- ci-scripts/main.py | 1 - ci-scripts/ran.py | 25 ------------------------- 2 files changed, 26 deletions(-) diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 6847e10950..6426b358ea 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -437,7 +437,6 @@ elif re.match('^LogCollecteNB$', mode, re.IGNORECASE): logging.error("Command '{}' returned non-zero exit status {}.".format(e.cmd, e.returncode)) logging.error("Error output:\n{}".format(e.output)) sys.exit(0) - RAN.LogCollecteNB() elif re.match('^LogCollectHSS$', mode, re.IGNORECASE): logging.warning("Option LogCollectHSS ignored") elif re.match('^LogCollectMME$', mode, re.IGNORECASE): diff --git a/ci-scripts/ran.py b/ci-scripts/ran.py index 1d96308c1d..f56bbec42a 100644 --- a/ci-scripts/ran.py +++ b/ci-scripts/ran.py @@ -187,31 +187,6 @@ class RANManagement(): return logStatus >= 0 - def LogCollecteNB(self): - mySSH = SSH.SSHConnection() - # Copying back to xNB server any log from all the runs. - # Should also contains ping and iperf logs - absPath = os.path.abspath('.') - if absPath.count('ci-scripts') == 0: - os.chdir('./ci-scripts') - - for x in os.listdir(): - if x.endswith('.log') or x.endswith('.log.png'): - mySSH.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, x, self.eNBSourceCodePath + '/cmake_targets/', silent=True, ignorePermDenied=True) - # Back to normal - mySSH.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword) - mySSH.command('cd ' + self.eNBSourceCodePath, '\$', 5) - mySSH.command('cd cmake_targets', '\$', 5) - mySSH.command('echo ' + self.eNBPassword + ' | sudo -S mv /tmp/enb_*.pcap .','\$',20) - mySSH.command('echo ' + self.eNBPassword + ' | sudo -S mv /tmp/gnb_*.pcap .','\$',20) - mySSH.command('echo ' + self.eNBPassword + ' | sudo -S rm -f enb.log.zip', '\$', 5) - mySSH.command('echo ' + self.eNBPassword + ' | sudo -S zip enb.log.zip *.log enb_*record.raw enb_*.pcap gnb_*.pcap enb_*txt physim_*.log *stats.log *monitor.pickle *monitor*.png ping*.log* iperf*.log log/*/*.log log/*/*.pcap', '\$', 60) - result = re.search('core.\d+', mySSH.getBefore()) - if result is not None: - mySSH.command('echo ' + self.eNBPassword + ' | sudo -S zip enb.log.zip core* ran_build/build/{lte,nr}-softmodem', '\$', 60) # add core and executable to zip - mySSH.command('echo ' + self.eNBPassword + ' | sudo -S rm enb*.log core* enb_*record.raw enb_*.pcap gnb_*.pcap enb_*txt physim_*.log *stats.log *monitor.pickle *monitor*.png ping*.log* iperf*.log log/*/*.log log/*/*.pcap', '\$', 15) - mySSH.close() - def _analyzeUeRetx(self, rounds, checkers, regex): if len(rounds) == 0 or len(checkers) == 0: logging.warning(f'warning: rounds={rounds} checkers={checkers}') From 0e60be785ca07d4dc42f962ac14aba21d0609ebc Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 11 Aug 2025 14:38:18 +0200 Subject: [PATCH 489/964] Remove SSH connection Remove this class. It is not safe to use (no return codes, can get out of sync), hardcodes the use of passwords, and it's API is cumbersone. More explanations can also be found in !1867. It is superseded by cls_cmd.py --- ci-scripts/sshconnection.py | 281 ------------------------------------ 1 file changed, 281 deletions(-) delete mode 100644 ci-scripts/sshconnection.py diff --git a/ci-scripts/sshconnection.py b/ci-scripts/sshconnection.py deleted file mode 100644 index a41b8bf7f1..0000000000 --- a/ci-scripts/sshconnection.py +++ /dev/null @@ -1,281 +0,0 @@ -#/* -# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more -# * contributor license agreements. See the NOTICE file distributed with -# * this work for additional information regarding copyright ownership. -# * The OpenAirInterface Software Alliance licenses this file to You under -# * the OAI Public License, Version 1.1 (the "License"); you may not use this file -# * except in compliance with the License. -# * You may obtain a copy of the License at -# * -# * http://www.openairinterface.org/?page_id=698 -# * -# * Unless required by applicable law or agreed to in writing, software -# * distributed under the License is distributed on an "AS IS" BASIS, -# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# * See the License for the specific language governing permissions and -# * limitations under the License. -# *------------------------------------------------------------------------------- -# * For more information about the OpenAirInterface (OAI) Software Alliance: -# * contact@openairinterface.org -# */ -#--------------------------------------------------------------------- -# Python for CI of OAI-eNB + COTS-UE -# -# Required Python Version -# Python 3.x -# -# Required Python Package -# pexpect -#--------------------------------------------------------------------- - -#----------------------------------------------------------- -# Import -#----------------------------------------------------------- -import pexpect # pexpect -import logging -import time # sleep -import re -import subprocess -import sys - -#----------------------------------------------------------- -# Class Declaration -#----------------------------------------------------------- -class SSHConnection(): - def __init__(self): - self.ssh = '' - self.picocom_closure = False - self.ipaddress = '' - self.username = '' - self.cmd2Results = '' - - def disablePicocomClosure(self): - self.picocom_closure = False - - def enablePicocomClosure(self): - self.picocom_closure = True - - def open(self, ipaddress, username, password): - prompt = "\$" - count = 0 - connect_status = False - while count < 4: - self.ssh = pexpect.spawn('ssh -o PubkeyAuthentication=yes {}@{}'.format(username,ipaddress)) - # Longer timeout at connection due to asterix slowness - self.ssh.timeout = 25 - self.sshresponse = self.ssh.expect(['Are you sure you want to continue connecting (yes/no)?', 'password:', 'Last login', pexpect.EOF, pexpect.TIMEOUT]) - if self.sshresponse == 0: - self.ssh.sendline('yes') - self.sshresponse = self.ssh.expect(['password:', username + '@']) - if self.sshresponse == 0: - self.ssh.sendline(password) - self.sshresponse = self.ssh.expect([prompt, 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) - if self.sshresponse == 0: - count = 10 - connect_status = True - else: - logging.warning('self.sshresponse = ' + str(self.sshresponse)) - elif self.sshresponse == 1: - self.ssh.sendline(password) - self.sshresponse = self.ssh.expect([prompt, 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) - if self.sshresponse == 0: - count = 10 - connect_status = True - else: - logging.warning('self.sshresponse = ' + str(self.sshresponse)) - elif self.sshresponse == 2: - # We directly ended up on the remote server because of pubkey auth - count = 10 - connect_status = True - # this expect() seems to be necessary to advance the read buffer until the prompt, or getBefore() will not return the last command - self.sshresponse = self.ssh.expect([prompt]) - else: - # debug output - logging.warning(str(self.ssh.before)) - logging.warning('self.sshresponse = ' + str(self.sshresponse)) - # adding a tempo when failure - if not connect_status: - time.sleep(1) - count += 1 - if connect_status: - self.command('unset HISTFILE', prompt, 5, silent=True) - else: - raise ConnectionError('SSH Connection Failed') - self.ipaddress = ipaddress - self.username = username - - - - - def cde_check_value(self, commandline, expected, timeout): - logging.info(commandline) - self.ssh.timeout = timeout - self.ssh.sendline(commandline) - expected.append(pexpect.EOF) - expected.append(pexpect.TIMEOUT) - self.sshresponse = self.ssh.expect(expected) - return self.sshresponse - - def command(self, commandline, expectedline, timeout, silent=False, resync=False): - if not silent: - logging.info(commandline) - self.ssh.timeout = timeout - # Nasty patch when pexpect output is out of sync. - # Much pronounced when running back-to-back-back oc commands - if resync: - self.ssh.send(commandline) - self.ssh.expect([commandline, pexpect.TIMEOUT]) - self.ssh.send('\r\n') - self.sshresponse = self.ssh.expect([expectedline, pexpect.EOF, pexpect.TIMEOUT]) - else: - self.ssh.sendline(commandline) - self.sshresponse = self.ssh.expect([expectedline, pexpect.EOF, pexpect.TIMEOUT]) - if self.sshresponse == 0: - return 0 - elif self.sshresponse == 1: - logging.error('\u001B[1;37;41m Unexpected EOF \u001B[0m') - logging.error('Expected Line : ' + expectedline) - logging.error(str(self.ssh.before)) - raise ConnectionError(self.sshresponse) - elif self.sshresponse == 2: - logging.error('\u001B[1;37;41m Unexpected TIMEOUT \u001B[0m') - logging.error('Expected Line : ' + expectedline) - result = re.search('ping |iperf |picocom', str(commandline)) - if result is None: - logging.warning(str(self.ssh.before)) - raise ConnectionError(self.sshresponse) - else: - return -1 - else: - logging.error('\u001B[1;37;41m Unexpected Others \u001B[0m') - logging.error('Expected Line : ' + expectedline) - raise ConnectionError(self.sshresponse) - - def command2(self, commandline, timeout, silent=False): - if not silent: - logging.info(commandline) - self.cmd2Results = '' - noHistoryCmd = 'unset HISTFILE; ' + commandline - myHost = self.username + '@' + self.ipaddress - # CAUTION: THIS METHOD IMPLIES THAT THERE ARE VALID SSH KEYS - # BETWEEN THE PYTHON EXECUTOR NODE AND THE REMOTE HOST - # OTHERWISE IT WON'T WORK - lSsh = subprocess.Popen(["ssh", "%s" % myHost, noHistoryCmd],shell=False,stdout=subprocess.PIPE,stderr=subprocess.PIPE) - self.cmd2Results = str(lSsh.stdout.readlines()) - - def command3(self, commandline, timeout, silent=False): - if not silent: - logging.info(commandline) - self.cmd2Results = '' - noHistoryCmd = 'unset HISTFILE; ' + commandline - myHost = self.username + '@' + self.ipaddress - # CAUTION: THIS METHOD IMPLIES THAT THERE ARE VALID SSH KEYS - # BETWEEN THE PYTHON EXECUTOR NODE AND THE REMOTE HOST - # OTHERWISE IT WON'T WORK - lSsh = subprocess.Popen(["ssh", "%s" % myHost, noHistoryCmd],shell=False,stdout=subprocess.PIPE,stderr=subprocess.PIPE) - return lSsh.stdout.readlines() - - - def close(self): - self.ssh.timeout = 5 - self.ssh.sendline('exit') - self.sshresponse = self.ssh.expect([pexpect.EOF, pexpect.TIMEOUT]) - self.ipaddress = '' - self.username = '' - if self.sshresponse == 0: - pass - elif self.sshresponse == 1: - if not self.picocom_closure: - logging.warning('\u001B[1;37;41m Unexpected TIMEOUT during closing\u001B[0m') - else: - logging.warning('\u001B[1;37;41m Unexpected Others during closing\u001B[0m') - - def copyin(self, ipaddress, username, password, source, destination): - count = 0 - copy_status = False - logging.info('scp -r '+ username + '@' + ipaddress + ':' + source + ' ' + destination) - while count < 10: - scp_spawn = pexpect.spawn('scp -r '+ username + '@' + ipaddress + ':' + source + ' ' + destination, timeout = 100) - scp_response = scp_spawn.expect(['Are you sure you want to continue connecting (yes/no)?', 'password:', pexpect.EOF, pexpect.TIMEOUT]) - if scp_response == 0: - scp_spawn.sendline('yes') - scp_spawn.expect('password:') - scp_spawn.sendline(password) - scp_response = scp_spawn.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) - if scp_response == 0: - count = 10 - copy_status = True - else: - logging.warning('1 - scp_response = ' + str(scp_response)) - elif scp_response == 1: - scp_spawn.sendline(password) - scp_response = scp_spawn.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) - if scp_response == 0 or scp_response == 3: - count = 10 - copy_status = True - else: - logging.warning('2 - scp_response = ' + str(scp_response)) - elif scp_response == 2: - count = 10 - copy_status = True - else: - logging.warning('3 - scp_response = ' + str(scp_response)) - # adding a tempo when failure - if not copy_status: - time.sleep(1) - count += 1 - if copy_status: - return 0 - else: - return -1 - - def copyout(self, ipaddress, username, password, source, destination, silent=False, ignorePermDenied=False): - count = 0 - copy_status = False - if not silent: - logging.info('scp -r ' + source + ' ' + username + '@' + ipaddress + ':' + destination) - while count < 4: - scp_spawn = pexpect.spawn('scp -r ' + source + ' ' + username + '@' + ipaddress + ':' + destination, timeout = 100) - scp_response = scp_spawn.expect(['Are you sure you want to continue connecting (yes/no)?', 'password:', pexpect.EOF, pexpect.TIMEOUT]) - if scp_response == 0: - scp_spawn.sendline('yes') - scp_spawn.expect('password:') - scp_spawn.sendline(password) - scp_response = scp_spawn.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) - if scp_response == 0: - count = 10 - copy_status = True - elif scp_response == 1 and ignorePermDenied: - logging.warning(f'copyout(): permission denied, not copying file ({source})') - count = 10 - copy_status = True - else: - logging.warning('1 - scp_response = ' + str(scp_response)) - elif scp_response == 1: - scp_spawn.sendline(password) - scp_response = scp_spawn.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) - if scp_response == 0 or scp_response == 3: - count = 10 - copy_status = True - elif scp_response == 1 and ignorePermDenied: - logging.warning(f'copyout(): permission denied, not copying file ({source})') - count = 10 - copy_status = True - else: - logging.warning('2 - scp_response = ' + str(scp_response)) - elif scp_response == 2: - count = 10 - copy_status = True - else: - logging.warning('3 - scp_response = ' + str(scp_response)) - # adding a tempo when failure - if not copy_status: - time.sleep(1) - count += 1 - if copy_status: - pass - else: - raise ConnectionError('SCP failed') - - def getBefore(self): - return self.ssh.before.decode('utf-8') From 9e1cbb103507c5f3c570560fc88e9eaf581d2df2 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 11 Aug 2025 14:06:25 +0200 Subject: [PATCH 490/964] Ignore eNB{,1,2}{UserName,IPAddress,Password} parameters After having transitioned to direct node names in the XML, these parameters are not relevant anymore. The best way to view this patch is with git show --ignore-all-space --- ci-scripts/Jenkinsfile-cluster | 13 +---- ci-scripts/Jenkinsfile-nrue | 21 +------ ci-scripts/Jenkinsfile-physim-deploy | 11 +--- ci-scripts/Jenkinsfile-tmp-full-ran | 42 +++----------- ci-scripts/Jenkinsfile-tmp-multi-enb | 73 +++++------------------- ci-scripts/Jenkinsfile-tmp-multi-enb-nsa | 68 +++++----------------- ci-scripts/Jenkinsfile-tmp-ran | 43 +++----------- ci-scripts/args_parse.py | 47 ++------------- ci-scripts/cls_containerize.py | 27 --------- ci-scripts/helpreadme.py | 5 +- ci-scripts/main.py | 8 +-- ci-scripts/ran.py | 11 ---- ci-scripts/run_locally.sh | 6 +- ci-scripts/tests/test-runner/run.sh | 3 - 14 files changed, 65 insertions(+), 313 deletions(-) diff --git a/ci-scripts/Jenkinsfile-cluster b/ci-scripts/Jenkinsfile-cluster index e91b27426e..174ccab62f 100644 --- a/ci-scripts/Jenkinsfile-cluster +++ b/ci-scripts/Jenkinsfile-cluster @@ -98,18 +98,10 @@ pipeline { echo "no LockResources given" allParametersPresent = false } - if (params.eNB_IPAddress == null) { - echo "no eNB_IPAddress given" - allParametersPresent = false - } if (params.eNB_SourceCodePath == null) { echo "no eNB_SourceCodePath given" allParametersPresent = false } - if (params.eNB_Credentials == null) { - echo "no eNB_Credentials given" - allParametersPresent = false - } // the following 4 parameters should be pushed by the master trigger // if not present, take the job GIT variables (used for developing) if (params.eNB_Repository == null) { @@ -188,7 +180,6 @@ pipeline { } } withCredentials([ - [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password'], [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.OC_Credentials}", usernameVariable: 'OC_Username', passwordVariable: 'OC_Password'] ]) { sh "python3 main.py --mode=InitiateHtml --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} ${mainPythonAllXmlFiles}" @@ -196,7 +187,7 @@ pipeline { if (fileExists(xmlFile)) { try { timeout (time: 60, unit: 'MINUTES') { - sh "python3 main.py --mode=TesteNB --eNBIPAddress=${params.eNB_IPAddress} --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password} --eNBSourceCodePath=${params.eNB_SourceCodePath} --XMLTestFile=${xmlFile} --OCUserName=${OC_Username} --OCPassword=${OC_Password} --OCProjectName=${OC_ProjectName}" + sh "python3 main.py --mode=TesteNB --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} --eNBSourceCodePath=${params.eNB_SourceCodePath} --XMLTestFile=${xmlFile} --OCUserName=${OC_Username} --OCPassword=${OC_Password} --OCProjectName=${OC_ProjectName}" } } catch (Exception e) { currentBuild.result = 'FAILURE' @@ -204,7 +195,7 @@ pipeline { } } } - sh "python3 main.py --mode=FinalizeHtml --finalStatus=${buildStageStatus} --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password}" + sh "python3 main.py --mode=FinalizeHtml --finalStatus=${buildStageStatus}" } } } diff --git a/ci-scripts/Jenkinsfile-nrue b/ci-scripts/Jenkinsfile-nrue index aed99b3568..3f7ef9b9ed 100644 --- a/ci-scripts/Jenkinsfile-nrue +++ b/ci-scripts/Jenkinsfile-nrue @@ -91,24 +91,9 @@ pipeline { echo "no LockResources given" allParametersPresent = false } - if (params.eNB_IPAddress == null) { - allParametersPresent = false - } if (params.eNB_SourceCodePath == null) { allParametersPresent = false } - if (params.eNB_Credentials == null) { - allParametersPresent = false - } - if (params.eNB1_IPAddress == null) { - allParametersPresent = false - } - if (params.eNB1_SourceCodePath == null) { - allParametersPresent = false - } - if (params.eNB1_Credentials == null) { - allParametersPresent = false - } // the following 4 parameters should be pushed by the master trigger // if not present, take the job GIT variables (used for developing) if (params.eNB_Repository == null) { @@ -187,8 +172,6 @@ pipeline { } } withCredentials([ - [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password'], - [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB1_Credentials}", usernameVariable: 'eNB1_Username', passwordVariable: 'eNB1_Password'], [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.OC_Credentials}", usernameVariable: 'OC_Username', passwordVariable: 'OC_Password'] ]) { sh "python3 main.py --mode=InitiateHtml --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} ${mainPythonAllXmlFiles}" @@ -197,7 +180,7 @@ pipeline { if (fileExists(xmlFile)) { try { timeout (time: 60, unit: 'MINUTES') { - sh "python3 main.py --mode=TesteNB --eNBIPAddress=${params.eNB_IPAddress} --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password} --eNBSourceCodePath=${params.eNB_SourceCodePath} --XMLTestFile=${xmlFile} --OCUserName=${OC_Username} --OCPassword=${OC_Password} --OCProjectName=${OC_ProjectName} --eNB1IPAddress=${params.eNB1_IPAddress} --eNB1UserName=${eNB1_Username} --eNB1Password=${eNB1_Password} --eNB1SourceCodePath=${params.eNB1_SourceCodePath}" + sh "python3 main.py --mode=TesteNB --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} --eNBSourceCodePath=${params.eNB_SourceCodePath} --XMLTestFile=${xmlFile} --OCUserName=${OC_Username} --OCPassword=${OC_Password} --OCProjectName=${OC_ProjectName}" } } catch (Exception e) { currentBuild.result = 'FAILURE' @@ -205,7 +188,7 @@ pipeline { } } } - sh "python3 main.py --mode=FinalizeHtml --finalStatus=${buildStageStatus} --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password}" + sh "python3 main.py --mode=FinalizeHtml --finalStatus=${buildStageStatus}" } } } diff --git a/ci-scripts/Jenkinsfile-physim-deploy b/ci-scripts/Jenkinsfile-physim-deploy index ffeff8685b..e3d243d07b 100644 --- a/ci-scripts/Jenkinsfile-physim-deploy +++ b/ci-scripts/Jenkinsfile-physim-deploy @@ -92,15 +92,9 @@ pipeline { echo "no LockResources given" allParametersPresent = false } - if (params.eNB_IPAddress == null) { - allParametersPresent = false - } if (params.eNB_SourceCodePath == null) { allParametersPresent = false } - if (params.eNB_Credentials == null) { - allParametersPresent = false - } // the following 4 parameters should be pushed by the master trigger // if not present, take the job GIT variables (used for developing) if (params.eNB_Repository == null) { @@ -179,7 +173,6 @@ pipeline { } } withCredentials([ - [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password'], [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.OC_Credentials}", usernameVariable: 'OC_Username', passwordVariable: 'OC_Password'] ]) { sh "python3 main.py --mode=InitiateHtml --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} ${mainPythonAllXmlFiles}" @@ -188,7 +181,7 @@ pipeline { if (fileExists(xmlFile)) { try { timeout (time: 60, unit: 'MINUTES') { - sh "python3 main.py --mode=TesteNB --eNBIPAddress=${params.eNB_IPAddress} --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password} --eNBSourceCodePath=${params.eNB_SourceCodePath} --XMLTestFile=${xmlFile} --OCUserName=${OC_Username} --OCPassword=${OC_Password} --OCProjectName=${OC_ProjectName}" + sh "python3 main.py --mode=TesteNB --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} --eNBSourceCodePath=${params.eNB_SourceCodePath} --XMLTestFile=${xmlFile} --OCUserName=${OC_Username} --OCPassword=${OC_Password} --OCProjectName=${OC_ProjectName}" } } catch (Exception e) { currentBuild.result = 'FAILURE' @@ -196,7 +189,7 @@ pipeline { } } } - sh "python3 main.py --mode=FinalizeHtml --finalStatus=${buildStageStatus} --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password}" + sh "python3 main.py --mode=FinalizeHtml --finalStatus=${buildStageStatus}" } } } diff --git a/ci-scripts/Jenkinsfile-tmp-full-ran b/ci-scripts/Jenkinsfile-tmp-full-ran index 3bc1d6ad8e..07b10ab980 100644 --- a/ci-scripts/Jenkinsfile-tmp-full-ran +++ b/ci-scripts/Jenkinsfile-tmp-full-ran @@ -91,15 +91,9 @@ pipeline { echo "no LockResources given" allParametersPresent = false } - if (params.eNB_IPAddress == null) { - allParametersPresent = false - } if (params.eNB_SourceCodePath == null) { allParametersPresent = false } - if (params.eNB_Credentials == null) { - allParametersPresent = false - } // the following 4 parameters should be pushed by the master trigger // if not present, take the job GIT variables (used for developing) if (params.eNB_Repository == null) { @@ -170,25 +164,21 @@ pipeline { } } } - withCredentials([ - [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password'], - ]) { - sh "python3 main.py --mode=InitiateHtml --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} ${mainPythonAllXmlFiles}" - String[] myXmlTestSuite = testXMLFile.split("\\r?\\n") - for (xmlFile in myXmlTestSuite) { + sh "python3 main.py --mode=InitiateHtml --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} ${mainPythonAllXmlFiles}" + String[] myXmlTestSuite = testXMLFile.split("\\r?\\n") + for (xmlFile in myXmlTestSuite) { if (fileExists(xmlFile)) { try { timeout (time: 60, unit: 'MINUTES') { - sh "python3 main.py --mode=TesteNB --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password} --eNBSourceCodePath=${params.eNB_SourceCodePath} --XMLTestFile=${xmlFile}" + sh "python3 main.py --mode=TesteNB --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} --eNBSourceCodePath=${params.eNB_SourceCodePath} --XMLTestFile=${xmlFile}" } } catch (Exception e) { currentBuild.result = 'FAILURE' buildStageStatus = false } } - } - sh "python3 main.py --mode=FinalizeHtml --finalStatus=${buildStageStatus} --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password}" } + sh "python3 main.py --mode=FinalizeHtml --finalStatus=${buildStageStatus}" } } } @@ -198,11 +188,7 @@ pipeline { stage('Terminate eNB') { steps { echo '\u2705 \u001B[32mTerminate eNB\u001B[0m' - withCredentials([ - [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password'] - ]) { - sh "python3 ci-scripts/main.py --mode=TerminateeNB --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password}" - } + sh "python3 ci-scripts/main.py --mode=TerminateeNB" } post { success { @@ -218,15 +204,9 @@ pipeline { parallel { stage('Log Collection (eNB - Run)') { steps { - withCredentials([ - [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password'] - ]) { - echo '\u2705 \u001B[32mLog Collection (eNB - Run)\u001B[0m' - sh "python3 ci-scripts/main.py --mode=LogCollecteNB --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password} --eNBSourceCodePath=${params.eNB_SourceCodePath} --BuildId=${env.BUILD_ID}" + echo '\u2705 \u001B[32mLog Collection (eNB - Run)\u001B[0m' + sh "python3 ci-scripts/main.py --mode=LogCollecteNB --eNBSourceCodePath=${params.eNB_SourceCodePath} --BuildId=${env.BUILD_ID}" - echo '\u2705 \u001B[32mLog Transfer (eNB - Run)\u001B[0m' - sh "sshpass -p \'${eNB_Password}\' scp -o 'StrictHostKeyChecking no' -o 'ConnectTimeout 10' ${eNB_Username}@${params.eNB_IPAddress}:${eNB_SourceCodePath}/cmake_targets/enb.log.zip ./enb.log.${env.BUILD_ID}.zip || true" - } script { if(fileExists("enb.log.${env.BUILD_ID}.zip")) { archiveArtifacts "enb.log.${env.BUILD_ID}.zip" @@ -262,11 +242,7 @@ pipeline { failure { script { if (!termStatusArray[termENB]) { - withCredentials([ - [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password'] - ]) { - sh "python3 ci-scripts/main.py --mode=TerminateeNB --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password}" - } + sh "python3 ci-scripts/main.py --mode=TerminateeNB" } } } diff --git a/ci-scripts/Jenkinsfile-tmp-multi-enb b/ci-scripts/Jenkinsfile-tmp-multi-enb index 7c7397f30b..c01c8daf7e 100644 --- a/ci-scripts/Jenkinsfile-tmp-multi-enb +++ b/ci-scripts/Jenkinsfile-tmp-multi-enb @@ -81,36 +81,9 @@ pipeline { echo "no LockResources given" allParametersPresent = false } - // 1st eNB parameters - if (params.eNB_IPAddress == null) { - allParametersPresent = false - } if (params.eNB_SourceCodePath == null) { allParametersPresent = false } - if (params.eNB_Credentials == null) { - allParametersPresent = false - } - // 2nd eNB parameters - if (params.eNB1_IPAddress == null) { - allParametersPresent = false - } - if (params.eNB1_SourceCodePath == null) { - allParametersPresent = false - } - if (params.eNB1_Credentials == null) { - allParametersPresent = false - } - // 3rd eNB parameters - if (params.eNB2_IPAddress == null) { - allParametersPresent = false - } - if (params.eNB2_SourceCodePath == null) { - allParametersPresent = false - } - if (params.eNB2_Credentials == null) { - allParametersPresent = false - } // the following 4 parameters should be pushed by the master trigger // if not present, take the job GIT variables (used for developing) if (params.eNB_Repository == null) { @@ -181,27 +154,21 @@ pipeline { } } } - withCredentials([ - [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password'], - [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB1_Credentials}", usernameVariable: 'eNB1_Username', passwordVariable: 'eNB1_Password'], - [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB2_Credentials}", usernameVariable: 'eNB2_Username', passwordVariable: 'eNB2_Password'], - ]) { - sh "python3 main.py --mode=InitiateHtml --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} ${mainPythonAllXmlFiles}" - String[] myXmlTestSuite = testXMLFile.split("\\r?\\n") - for (xmlFile in myXmlTestSuite) { - if (fileExists(xmlFile)) { - try { - timeout (time: 60, unit: 'MINUTES') { - sh "python3 main.py --mode=TesteNB --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password} --eNBSourceCodePath=${params.eNB_SourceCodePath} --eNB1IPAddress=${params.eNB1_IPAddress} --eNB1UserName=${eNB1_Username} --eNB1Password=${eNB1_Password} --eNB1SourceCodePath=${params.eNB1_SourceCodePath} --eNB2IPAddress=${params.eNB2_IPAddress} --eNB2UserName=${eNB2_Username} --eNB2Password=${eNB2_Password} --eNB2SourceCodePath=${params.eNB2_SourceCodePath} --XMLTestFile=${xmlFile}" - } - } catch (Exception e) { - currentBuild.result = 'FAILURE' - buildStageStatus = false - } + sh "python3 main.py --mode=InitiateHtml --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} ${mainPythonAllXmlFiles}" + String[] myXmlTestSuite = testXMLFile.split("\\r?\\n") + for (xmlFile in myXmlTestSuite) { + if (fileExists(xmlFile)) { + try { + timeout (time: 60, unit: 'MINUTES') { + sh "python3 main.py --mode=TesteNB --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} --eNBSourceCodePath=${params.eNB_SourceCodePath} --XMLTestFile=${xmlFile}" + } + } catch (Exception e) { + currentBuild.result = 'FAILURE' + buildStageStatus = false } } - sh "python3 main.py --mode=FinalizeHtml --finalStatus=${buildStageStatus} --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password}" } + sh "python3 main.py --mode=FinalizeHtml --finalStatus=${buildStageStatus}" } } } @@ -211,11 +178,7 @@ pipeline { stage('Terminate eNB') { steps { echo '\u2705 \u001B[32mTerminate eNB\u001B[0m' - withCredentials([ - [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password'] - ]) { - sh "python3 ci-scripts/main.py --mode=TerminateeNB --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password}" - } + sh "python3 ci-scripts/main.py --mode=TerminateeNB" } } } @@ -224,15 +187,9 @@ pipeline { parallel { stage('Log Collection (eNB - Run)') { steps { - withCredentials([ - [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password'] - ]) { - echo '\u2705 \u001B[32mLog Collection (eNB - Run)\u001B[0m' - sh "python3 ci-scripts/main.py --mode=LogCollecteNB --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password} --eNBSourceCodePath=${params.eNB_SourceCodePath} --BuildId=${env.BUILD_ID}" + echo '\u2705 \u001B[32mLog Collection (eNB - Run)\u001B[0m' + sh "python3 ci-scripts/main.py --mode=LogCollecteNB --eNBSourceCodePath=${params.eNB_SourceCodePath} --BuildId=${env.BUILD_ID}" - echo '\u2705 \u001B[32mLog Transfer (eNB - Run)\u001B[0m' - sh "sshpass -p \'${eNB_Password}\' scp -o 'StrictHostKeyChecking no' -o 'ConnectTimeout 10' ${eNB_Username}@${params.eNB_IPAddress}:${eNB_SourceCodePath}/cmake_targets/enb.log.zip ./enb.log.${env.BUILD_ID}.zip || true" - } script { if(fileExists("enb.log.${env.BUILD_ID}.zip")) { archiveArtifacts "enb.log.${env.BUILD_ID}.zip" diff --git a/ci-scripts/Jenkinsfile-tmp-multi-enb-nsa b/ci-scripts/Jenkinsfile-tmp-multi-enb-nsa index 89daaec8c1..67aa6b4511 100644 --- a/ci-scripts/Jenkinsfile-tmp-multi-enb-nsa +++ b/ci-scripts/Jenkinsfile-tmp-multi-enb-nsa @@ -83,36 +83,9 @@ pipeline { echo "no LockResources given" allParametersPresent = false } - // 1st eNB parameters - if (params.eNB_IPAddress == null) { - allParametersPresent = false - } if (params.eNB_SourceCodePath == null) { allParametersPresent = false } - if (params.eNB_Credentials == null) { - allParametersPresent = false - } - // 2nd eNB parameters - if (params.eNB1_IPAddress == null) { - allParametersPresent = false - } - if (params.eNB1_SourceCodePath == null) { - allParametersPresent = false - } - if (params.eNB1_Credentials == null) { - allParametersPresent = false - } - // 3rd eNB parameters - if (params.eNB2_IPAddress == null) { - allParametersPresent = false - } - if (params.eNB2_SourceCodePath == null) { - allParametersPresent = false - } - if (params.eNB2_Credentials == null) { - allParametersPresent = false - } // the following 4 parameters should be pushed by the master trigger // if not present, take the job GIT variables (used for developing) if (params.eNB_Repository == null) { @@ -183,27 +156,21 @@ pipeline { } } } - withCredentials([ - [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password'], - [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB1_Credentials}", usernameVariable: 'eNB1_Username', passwordVariable: 'eNB1_Password'], - [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB2_Credentials}", usernameVariable: 'eNB2_Username', passwordVariable: 'eNB2_Password'], - ]) { - sh "python3 main.py --mode=InitiateHtml --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} ${mainPythonAllXmlFiles}" - String[] myXmlTestSuite = testXMLFile.split("\\r?\\n") - for (xmlFile in myXmlTestSuite) { - if (fileExists(xmlFile)) { - try { - timeout (time: 60, unit: 'MINUTES') { - sh "python3 main.py --mode=TesteNB --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password} --eNBSourceCodePath=${params.eNB_SourceCodePath} --eNB1IPAddress=${params.eNB1_IPAddress} --eNB1UserName=${eNB1_Username} --eNB1Password=${eNB1_Password} --eNB1SourceCodePath=${params.eNB1_SourceCodePath} --eNB2IPAddress=${params.eNB2_IPAddress} --eNB2UserName=${eNB2_Username} --eNB2Password=${eNB2_Password} --eNB2SourceCodePath=${params.eNB2_SourceCodePath} --XMLTestFile=${xmlFile}" - } - } catch (Exception e) { - currentBuild.result = 'FAILURE' - buildStageStatus = false - } + sh "python3 main.py --mode=InitiateHtml --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} ${mainPythonAllXmlFiles}" + String[] myXmlTestSuite = testXMLFile.split("\\r?\\n") + for (xmlFile in myXmlTestSuite) { + if (fileExists(xmlFile)) { + try { + timeout (time: 60, unit: 'MINUTES') { + sh "python3 main.py --mode=TesteNB --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} --eNBSourceCodePath=${params.eNB_SourceCodePath} --XMLTestFile=${xmlFile}" + } + } catch (Exception e) { + currentBuild.result = 'FAILURE' + buildStageStatus = false } } - sh "python3 main.py --mode=FinalizeHtml --finalStatus=${buildStageStatus} --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password}" } + sh "python3 main.py --mode=FinalizeHtml --finalStatus=${buildStageStatus}" } } } @@ -212,15 +179,8 @@ pipeline { parallel { stage('Log Collection (eNB - Run)') { steps { - withCredentials([ - [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password'] - ]) { - echo '\u2705 \u001B[32mLog Collection (eNB - Run)\u001B[0m' - sh "python3 ci-scripts/main.py --mode=LogCollecteNB --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password} --eNBSourceCodePath=${params.eNB_SourceCodePath} --BuildId=${env.BUILD_ID}" - - echo '\u2705 \u001B[32mLog Transfer (eNB - Run)\u001B[0m' - sh "sshpass -p \'${eNB_Password}\' scp -o 'StrictHostKeyChecking no' -o 'ConnectTimeout 10' ${eNB_Username}@${params.eNB_IPAddress}:${eNB_SourceCodePath}/cmake_targets/enb.log.zip ./enb.log.${env.BUILD_ID}.zip || true" - } + echo '\u2705 \u001B[32mLog Collection (eNB - Run)\u001B[0m' + sh "python3 ci-scripts/main.py --mode=LogCollecteNB --eNBSourceCodePath=${params.eNB_SourceCodePath} --BuildId=${env.BUILD_ID}" script { if(fileExists("enb.log.${env.BUILD_ID}.zip")) { archiveArtifacts "enb.log.${env.BUILD_ID}.zip" diff --git a/ci-scripts/Jenkinsfile-tmp-ran b/ci-scripts/Jenkinsfile-tmp-ran index 82db6641e3..526899a5a2 100644 --- a/ci-scripts/Jenkinsfile-tmp-ran +++ b/ci-scripts/Jenkinsfile-tmp-ran @@ -96,15 +96,9 @@ pipeline { echo "no LockResources given" allParametersPresent = false } - if (params.eNB_IPAddress == null) { - allParametersPresent = false - } if (params.eNB_SourceCodePath == null) { allParametersPresent = false } - if (params.eNB_Credentials == null) { - allParametersPresent = false - } // the following 4 parameters should be pushed by the master trigger // if not present, take the job GIT variables (used for developing) if (params.eNB_Repository == null) { @@ -181,25 +175,21 @@ pipeline { } } } - withCredentials([ - [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password'], - ]) { - sh "python3 main.py --mode=InitiateHtml --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} ${flexricOption} ${mainPythonAllXmlFiles}" - String[] myXmlTestSuite = testXMLFile.split("\\r?\\n") - for (xmlFile in myXmlTestSuite) { + sh "python3 main.py --mode=InitiateHtml --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} ${flexricOption} ${mainPythonAllXmlFiles}" + String[] myXmlTestSuite = testXMLFile.split("\\r?\\n") + for (xmlFile in myXmlTestSuite) { if (fileExists(xmlFile)) { try { timeout (time: 60, unit: 'MINUTES') { - sh "python3 main.py --mode=TesteNB --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} ${flexricOption} --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password} --eNBSourceCodePath=${params.eNB_SourceCodePath} --XMLTestFile=${xmlFile}" + sh "python3 main.py --mode=TesteNB --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} ${flexricOption} --eNBSourceCodePath=${params.eNB_SourceCodePath} --XMLTestFile=${xmlFile}" } } catch (Exception e) { currentBuild.result = 'FAILURE' buildStageStatus = false } } - } - sh "python3 main.py --mode=FinalizeHtml --finalStatus=${buildStageStatus} --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password}" } + sh "python3 main.py --mode=FinalizeHtml --finalStatus=${buildStageStatus}" } } } @@ -209,11 +199,7 @@ pipeline { stage('Terminate eNB') { steps { echo '\u2705 \u001B[32mTerminate eNB\u001B[0m' - withCredentials([ - [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password'] - ]) { - sh "python3 ci-scripts/main.py --mode=TerminateeNB --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password}" - } + sh "python3 ci-scripts/main.py --mode=TerminateeNB" } post { success { @@ -229,15 +215,8 @@ pipeline { parallel { stage('Log Collection (eNB - Run)') { steps { - withCredentials([ - [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password'] - ]) { - echo '\u2705 \u001B[32mLog Collection (eNB - Run)\u001B[0m' - sh "python3 ci-scripts/main.py --mode=LogCollecteNB --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password} --eNBSourceCodePath=${params.eNB_SourceCodePath} --BuildId=${env.BUILD_ID}" - - echo '\u2705 \u001B[32mLog Transfer (eNB - Run)\u001B[0m' - sh "sshpass -p \'${eNB_Password}\' scp -o 'StrictHostKeyChecking no' -o 'ConnectTimeout 10' ${eNB_Username}@${params.eNB_IPAddress}:${eNB_SourceCodePath}/cmake_targets/enb.log.zip ./enb.log.${env.BUILD_ID}.zip || true" - } + echo '\u2705 \u001B[32mLog Collection (eNB - Run)\u001B[0m' + sh "python3 ci-scripts/main.py --mode=LogCollecteNB --eNBSourceCodePath=${params.eNB_SourceCodePath} --BuildId=${env.BUILD_ID}" script { if(fileExists("enb.log.${env.BUILD_ID}.zip")) { archiveArtifacts "enb.log.${env.BUILD_ID}.zip" @@ -273,11 +252,7 @@ pipeline { failure { script { if (!termStatusArray[termENB]) { - withCredentials([ - [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password'] - ]) { - sh "python3 ci-scripts/main.py --mode=TerminateeNB --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password}" - } + sh "python3 ci-scripts/main.py --mode=TerminateeNB" } } } diff --git a/ci-scripts/args_parse.py b/ci-scripts/args_parse.py index 11b27135a2..4953f049fb 100644 --- a/ci-scripts/args_parse.py +++ b/ci-scripts/args_parse.py @@ -121,44 +121,11 @@ def ArgsParse(argvs,CiTestObj,RAN,HTML,CONTAINERS,HELP,SCA,CLUSTER): SCA.ranTargetBranch=matchReg.group(1) CLUSTER.ranTargetBranch=matchReg.group(1) elif re.match(r'^\-\-eNBIPAddress=(.+)$|^\-\-eNB[1-2]IPAddress=(.+)$', myArgv, re.IGNORECASE): - if re.match(r'^\-\-eNBIPAddress=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match(r'^\-\-eNBIPAddress=(.+)$', myArgv, re.IGNORECASE) - RAN.eNBIPAddress=matchReg.group(1) - CONTAINERS.eNBIPAddress=matchReg.group(1) - elif re.match(r'^\-\-eNB1IPAddress=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match(r'^\-\-eNB1IPAddress=(.+)$', myArgv, re.IGNORECASE) - RAN.eNB1IPAddress=matchReg.group(1) - CONTAINERS.eNB1IPAddress=matchReg.group(1) - elif re.match(r'^\-\-eNB2IPAddress=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match(r'^\-\-eNB2IPAddress=(.+)$', myArgv, re.IGNORECASE) - RAN.eNB2IPAddress=matchReg.group(1) - CONTAINERS.eNB2IPAddress=matchReg.group(1) + print("parameters --eNB*IPAddress ignored") elif re.match(r'^\-\-eNBUserName=(.+)$|^\-\-eNB[1-2]UserName=(.+)$', myArgv, re.IGNORECASE): - if re.match(r'^\-\-eNBUserName=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match(r'^\-\-eNBUserName=(.+)$', myArgv, re.IGNORECASE) - RAN.eNBUserName=matchReg.group(1) - CONTAINERS.eNBUserName=matchReg.group(1) - elif re.match(r'^\-\-eNB1UserName=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match(r'^\-\-eNB1UserName=(.+)$', myArgv, re.IGNORECASE) - RAN.eNB1UserName=matchReg.group(1) - CONTAINERS.eNB1UserName=matchReg.group(1) - elif re.match(r'^\-\-eNB2UserName=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match(r'^\-\-eNB2UserName=(.+)$', myArgv, re.IGNORECASE) - RAN.eNB2UserName=matchReg.group(1) - CONTAINERS.eNB2UserName=matchReg.group(1) + print("parameters --eNB*UserName ignored") elif re.match(r'^\-\-eNBPassword=(.+)$|^\-\-eNB[1-2]Password=(.+)$', myArgv, re.IGNORECASE): - if re.match(r'^\-\-eNBPassword=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match(r'^\-\-eNBPassword=(.+)$', myArgv, re.IGNORECASE) - RAN.eNBPassword=matchReg.group(1) - CONTAINERS.eNBPassword=matchReg.group(1) - elif re.match(r'^\-\-eNB1Password=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match(r'^\-\-eNB1Password=(.+)$', myArgv, re.IGNORECASE) - RAN.eNB1Password=matchReg.group(1) - CONTAINERS.eNB1Password=matchReg.group(1) - elif re.match(r'^\-\-eNB2Password=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match(r'^\-\-eNB2Password=(.+)$', myArgv, re.IGNORECASE) - RAN.eNB2Password=matchReg.group(1) - CONTAINERS.eNB2Password=matchReg.group(1) + print("parameter --eNB*Password ignored") elif re.match(r'^\-\-eNBSourceCodePath=(.+)$|^\-\-eNB[1-2]SourceCodePath=(.+)$', myArgv, re.IGNORECASE): if re.match(r'^\-\-eNBSourceCodePath=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match(r'^\-\-eNBSourceCodePath=(.+)$', myArgv, re.IGNORECASE) @@ -167,13 +134,9 @@ def ArgsParse(argvs,CiTestObj,RAN,HTML,CONTAINERS,HELP,SCA,CLUSTER): SCA.eNBSourceCodePath=matchReg.group(1) CLUSTER.eNBSourceCodePath=matchReg.group(1) elif re.match(r'^\-\-eNB1SourceCodePath=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match(r'^\-\-eNB1SourceCodePath=(.+)$', myArgv, re.IGNORECASE) - RAN.eNB1SourceCodePath=matchReg.group(1) - CONTAINERS.eNB1SourceCodePath=matchReg.group(1) + print("parameter --eNB1SourceCodePath ignored") elif re.match(r'^\-\-eNB2SourceCodePath=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match(r'^\-\-eNB2SourceCodePath=(.+)$', myArgv, re.IGNORECASE) - RAN.eNB2SourceCodePath=matchReg.group(1) - CONTAINERS.eNB2SourceCodePath=matchReg.group(1) + print("parameter --eNB2SourceCodePath ignored") elif re.match(r'^\-\-XMLTestFile=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match(r'^\-\-XMLTestFile=(.+)$', myArgv, re.IGNORECASE) CiTestObj.testXMLfiles.append(matchReg.group(1)) diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index b45aed5d8d..920f08f75c 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -230,23 +230,10 @@ class Containerize(): self.ranAllowMerge = False self.ranCommitID = '' self.ranTargetBranch = '' - self.eNBIPAddress = '' - self.eNBUserName = '' - self.eNBPassword = '' self.eNBSourceCodePath = '' - self.eNB1IPAddress = '' - self.eNB1UserName = '' - self.eNB1Password = '' - self.eNB1SourceCodePath = '' - self.eNB2IPAddress = '' - self.eNB2UserName = '' - self.eNB2Password = '' - self.eNB2SourceCodePath = '' self.forcedWorkspaceCleanup = False self.imageKind = '' self.proxyCommit = None - self.eNB_instance = 0 - self.eNB_serverId = ['', '', ''] self.yamlPath = '' self.services = '' self.deploymentTag = '' @@ -266,20 +253,6 @@ class Containerize(): # Container management functions #----------------------------------------------------------- - def GetCredentials(self, server_id): - if server_id == '0': - ip, path = self.eNBIPAddress, self.eNBSourceCodePath - elif server_id == '1': - ip, path = self.eNB1IPAddress, self.eNB1SourceCodePath - elif server_id == '2': - ip, path = self.eNB2IPAddress, self.eNB2SourceCodePath - else: - raise ValueError(f"unknown server ID '{server_id}'") - if ip == '' or path == '': - HELP.GenericHelp(CONST.Version) - raise ValueError(f'Insufficient Parameter: IP/node {ip}, path {path}') - return (ip, path) - def BuildImage(self, ctx, node, HTML): lSourcePath = self.eNBSourceCodePath logging.debug('Building on server: ' + node) diff --git a/ci-scripts/helpreadme.py b/ci-scripts/helpreadme.py index ce4c594f58..a9783bd1f0 100644 --- a/ci-scripts/helpreadme.py +++ b/ci-scripts/helpreadme.py @@ -52,10 +52,7 @@ def GitSrvHelp(repository,branch,commit,mergeallow,targetbranch): print(' --ranAllowMerge=[Allow Merge Request (with target branch) (true or false)] -- ' + mergeallow) print(' --ranTargetBranch=[Target Branch in case of a Merge Request] -- ' + targetbranch) -def eNBSrvHelp(ipaddr, username, password, sourcepath): - print(' --eNBIPAddress=[eNB\'s IP Address] -- ' + ipaddr) - print(' --eNBUserName=[eNB\'s Login User Name] -- ' + username) - print(' --eNBPassword=[eNB\'s Login Password] -- ' + password) +def eNBSrvHelp(sourcepath): print(' --eNBSourceCodePath=[eNB\'s Source Code Path] -- ' + sourcepath) def XmlHelp(filename): diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 6426b358ea..76fe64c2f6 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -425,7 +425,7 @@ elif re.match('^TerminateSPGW$', mode, re.IGNORECASE): elif re.match('^LogCollectBuild$', mode, re.IGNORECASE): logging.warning("Option LogCollectBuild ignored") elif re.match('^LogCollecteNB$', mode, re.IGNORECASE): - if RAN.eNBIPAddress == '' or RAN.eNBUserName == '' or RAN.eNBPassword == '' or RAN.eNBSourceCodePath == '': + if RAN.eNBSourceCodePath == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') if os.path.isdir('cmake_targets/log'): @@ -481,12 +481,12 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re logging.info('\u001B[1m Starting Scenario: ' + CiTestObj.testXMLfiles[0] + '\u001B[0m') logging.info('\u001B[1m----------------------------------------\u001B[0m') if re.match('^TesteNB$', mode, re.IGNORECASE): - if RAN.eNBIPAddress == '' or RAN.ranRepository == '' or RAN.ranBranch == '' or RAN.eNBUserName == '' or RAN.eNBPassword == '' or RAN.eNBSourceCodePath == '': + if RAN.ranRepository == '' or RAN.ranBranch == '' or RAN.eNBSourceCodePath == '': HELP.GenericHelp(CONST.Version) if RAN.ranRepository == '': HELP.GitSrvHelp(RAN.ranRepository, RAN.ranBranch, RAN.ranCommitID, RAN.ranAllowMerge, RAN.ranTargetBranch) - if RAN.eNBIPAddress == '' or RAN.eNBUserName == '' or RAN.eNBPassword == '' or RAN.eNBSourceCodePath == '': - HELP.eNBSrvHelp(RAN.eNBIPAddress, RAN.eNBUserName, RAN.eNBPassword, RAN.eNBSourceCodePath) + if RAN.eNBSourceCodePath == '': + HELP.eNBSrvHelp(RAN.eNBSourceCodePath) sys.exit('Insufficient Parameter') else: if CiTestObj.ranRepository == '' or CiTestObj.ranBranch == '': diff --git a/ci-scripts/ran.py b/ci-scripts/ran.py index f56bbec42a..49032f01e2 100644 --- a/ci-scripts/ran.py +++ b/ci-scripts/ran.py @@ -60,18 +60,7 @@ class RANManagement(): self.ranAllowMerge = False self.ranCommitID = '' self.ranTargetBranch = '' - self.eNBIPAddress = '' - self.eNBUserName = '' - self.eNBPassword = '' self.eNBSourceCodePath = '' - self.eNB1IPAddress = '' - self.eNB1UserName = '' - self.eNB1Password = '' - self.eNB1SourceCodePath = '' - self.eNB2IPAddress = '' - self.eNB2UserName = '' - self.eNB2Password = '' - self.eNB2SourceCodePath = '' self.Initialize_eNB_args = '' self.imageKind = '' self.air_interface = '' diff --git a/ci-scripts/run_locally.sh b/ci-scripts/run_locally.sh index 84fd6a6f17..1d4a73e919 100755 --- a/ci-scripts/run_locally.sh +++ b/ci-scripts/run_locally.sh @@ -33,13 +33,11 @@ python3 main.py --mode=InitiateHtml --ranRepository=NONE --ranBranch=${CURRENT_B python3 main.py --mode=TesteNB --ranRepository=NONE --ranBranch=${CURRENT_BRANCH} \ --ranCommitID=${COMMIT_SHA} --ranAllowMerge=false \ - --ranTargetBranch=NONE --eNBIPAddress=NONE --eNBUserName=NONE --eNBPassword=NONE \ + --ranTargetBranch=NONE \ --eNBSourceCodePath=${REPO_PATH} \ --XMLTestFile=${TESTCASE} --local RET=$? -python3 main.py --mode=FinalizeHtml \ - --local \ - --eNBIPAddress=NONE --eNBUserName=NONE --eNBPassword=NONE +python3 main.py --mode=FinalizeHtml --local exit ${RET} diff --git a/ci-scripts/tests/test-runner/run.sh b/ci-scripts/tests/test-runner/run.sh index 9c02186a5f..55d421cdb0 100755 --- a/ci-scripts/tests/test-runner/run.sh +++ b/ci-scripts/tests/test-runner/run.sh @@ -22,9 +22,6 @@ python3 main.py \ --ranCommitID=${commit} \ --ranAllowMerge=true \ --ranTargetBranch=develop \ - --eNBIPAddress=localhost \ - --eNBUserName=NONE \ - --eNBPassword=NONE \ --eNBSourceCodePath=NONE \ --XMLTestFile=tests/test-runner/test.xml From 35f080e426c2df485d3ba4825426cf3b5ef4b815 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 11 Aug 2025 17:39:07 +0200 Subject: [PATCH 491/964] Fix: new Iperf test need to get ctx --- ci-scripts/tests/ping-iperf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci-scripts/tests/ping-iperf.py b/ci-scripts/tests/ping-iperf.py index f63ce323d6..bd30768a9f 100644 --- a/ci-scripts/tests/ping-iperf.py +++ b/ci-scripts/tests/ping-iperf.py @@ -77,7 +77,7 @@ class TestPingIperf(unittest.TestCase): self.ci.iperf_profile = "balanced" infra_file = "tests/config/infra_ping_iperf.yaml" # TODO Should need nothing but options and UE(s) to use - success = self.ci.Iperf(self.html, self.cont, infra_file=infra_file) + success = self.ci.Iperf(self.ctx, self.html, infra_file=infra_file) self.assertTrue(success) if __name__ == '__main__': From 3c54daf4e29070cd2ddb72541b8e3eaf9a9564d1 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 11 Aug 2025 19:02:19 +0200 Subject: [PATCH 492/964] Remove "forcedWorkspaceCleanup" option It is superseded by the CreateWorkspace() function and task step (which removes and recreates a workspace), and this option was not actually used in any function except for the build of unit tests, but no XML step actually specified this option. --- ci-scripts/cls_cluster.py | 1 - ci-scripts/cls_containerize.py | 4 ---- ci-scripts/main.py | 8 -------- ci-scripts/xml_files/container_image_build.xml | 1 - ci-scripts/xml_files/container_image_build_cross.xml | 1 - ci-scripts/xml_files/container_l2sim_proxy.xml | 1 - ci-scripts/xml_files/gnb_usrp_build.xml | 1 - 7 files changed, 17 deletions(-) diff --git a/ci-scripts/cls_cluster.py b/ci-scripts/cls_cluster.py index 929dd29021..ae4e718ecf 100644 --- a/ci-scripts/cls_cluster.py +++ b/ci-scripts/cls_cluster.py @@ -70,7 +70,6 @@ def OC_logout(cmd): class Cluster: def __init__(self): self.eNBSourceCodePath = "" - self.forcedWorkspaceCleanup = False self.OCUserName = "" self.OCPassword = "" self.OCProjectName = "" diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index 920f08f75c..b91b857521 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -231,7 +231,6 @@ class Containerize(): self.ranCommitID = '' self.ranTargetBranch = '' self.eNBSourceCodePath = '' - self.forcedWorkspaceCleanup = False self.imageKind = '' self.proxyCommit = None self.yamlPath = '' @@ -544,9 +543,6 @@ class Containerize(): raise Exception("Can build unit tests only on Ubuntu server") logging.debug('running on Ubuntu as expected') - if self.forcedWorkspaceCleanup: - cmd.run(f'sudo -S rm -Rf {lSourcePath}') - # check that ran-base image exists as we expect it baseImage = 'ran-base' baseTag = 'develop' diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 76fe64c2f6..cbc03a47d5 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -102,14 +102,6 @@ def ExecuteActionWithParam(action, ctx): if action == 'Build_eNB' or action == 'Build_Image' or action == 'Build_Proxy' or action == "Build_Cluster_Image" or action == "Build_Run_Tests": RAN.Build_eNB_args=test.findtext('Build_eNB_args') CONTAINERS.imageKind=test.findtext('kind') - forced_workspace_cleanup = test.findtext('forced_workspace_cleanup') - RAN.Build_eNB_forced_workspace_cleanup=False - CONTAINERS.forcedWorkspaceCleanup=False - CLUSTER.forcedWorkspaceCleanup = False - if forced_workspace_cleanup is not None and re.match('true', forced_workspace_cleanup, re.IGNORECASE): - RAN.Build_eNB_forced_workspace_cleanup = True - CONTAINERS.forcedWorkspaceCleanup = True - CLUSTER.forcedWorkspaceCleanup = True node = test.findtext('node') proxy_commit = test.findtext('proxy_commit') if proxy_commit is not None: diff --git a/ci-scripts/xml_files/container_image_build.xml b/ci-scripts/xml_files/container_image_build.xml index 33f29cf087..afd58d4d6d 100644 --- a/ci-scripts/xml_files/container_image_build.xml +++ b/ci-scripts/xml_files/container_image_build.xml @@ -41,7 +41,6 @@ Build all Images obelix all - True diff --git a/ci-scripts/xml_files/container_image_build_cross.xml b/ci-scripts/xml_files/container_image_build_cross.xml index ddaeac3602..ab94d847c8 100644 --- a/ci-scripts/xml_files/container_image_build_cross.xml +++ b/ci-scripts/xml_files/container_image_build_cross.xml @@ -39,7 +39,6 @@ Cross-Compile for ARM64 build_cross_arm64 alambix - True diff --git a/ci-scripts/xml_files/container_l2sim_proxy.xml b/ci-scripts/xml_files/container_l2sim_proxy.xml index 88026f077d..c2f19f9471 100644 --- a/ci-scripts/xml_files/container_l2sim_proxy.xml +++ b/ci-scripts/xml_files/container_l2sim_proxy.xml @@ -33,7 +33,6 @@ Build_Proxy Build L2sim Proxy Image localhost - True b64d9bce986b38ca59e8582864ade3fcdd05c0dc diff --git a/ci-scripts/xml_files/gnb_usrp_build.xml b/ci-scripts/xml_files/gnb_usrp_build.xml index 4e763678a7..42d567cd15 100644 --- a/ci-scripts/xml_files/gnb_usrp_build.xml +++ b/ci-scripts/xml_files/gnb_usrp_build.xml @@ -43,7 +43,6 @@ Build gNB (USRP) caracal --gNB -w USRP --ninja -c -P --build-lib ldpc_cuda --build-lib ldpc_aal --cmake-opt -DASN1C_EXEC=/opt/asn1c/bin/asn1c - True From 852e98d3852bd0b3303f753407402e1db82a013e Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 12 Aug 2025 10:13:22 +0200 Subject: [PATCH 493/964] Run_Physim(): avoid large console logs, rewrite file Many of these tests exit with an exit code != 0. Thus, the CI automatically logs the result. Rather, write everything including stderr to the file for analysis. Also, rewrite the file with ">" instead of appending through ">>". While appending works because the CI removes files after archiving, it seems "cleaner" to remove files. --- ci-scripts/cls_native.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci-scripts/cls_native.py b/ci-scripts/cls_native.py index 9546f93d28..1736cc144d 100644 --- a/ci-scripts/cls_native.py +++ b/ci-scripts/cls_native.py @@ -70,7 +70,7 @@ class Native(): workSpacePath = f'{directory}/cmake_targets' runLogFile=f'{workSpacePath}/physim.log' with cls_cmd.getConnection(host) as cmd: - cmd.run(f'sudo LD_LIBRARY_PATH=.:{DPDK_PATH}/lib64/ {workSpacePath}/ran_build/build/{physim_test} {options} >> {runLogFile}') + cmd.run(f'sudo LD_LIBRARY_PATH=.:{DPDK_PATH}/lib64/ {workSpacePath}/ran_build/build/{physim_test} {options} > {runLogFile} 2>&1') physim_file = archiveArtifact(cmd, ctx, runLogFile) success, msg = cls_analysis.Analysis.analyze_physim(physim_file, physim_test, options, threshold) if success: From c5624661eb3e8204ebad3d47dd48f0d51d6cc231 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 12 Aug 2025 10:20:33 +0200 Subject: [PATCH 494/964] Remove HTML 'no analysis function' For some network functions, we don't match an analysis function. In the console logs we print an info message. In the HTML, it's just noise. --- ci-scripts/cls_containerize.py | 1 - 1 file changed, 1 deletion(-) diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index b91b857521..bfb27e4548 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -214,7 +214,6 @@ def CheckLogs(self, filename, HTML, RAN): HTML.htmleNBFailureMsg = "" else: logging.info(f"Skipping analysis of log '{filename}': no submatch for xNB/UE") - HTML.CreateHtmlTestRowQueue(f"file {name}", 'OK', ["no analysis function"]) logging.debug(f"log check: file {filename} passed analysis {success}") return success From f82063c25231f0b507835d6ff6cbb0eb2a14f0f5 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 12 Aug 2025 10:37:49 +0200 Subject: [PATCH 495/964] CI: Sleep: print time to wait --- ci-scripts/cls_oaicitest.py | 1 + 1 file changed, 1 insertion(+) diff --git a/ci-scripts/cls_oaicitest.py b/ci-scripts/cls_oaicitest.py index 37b0ca76a9..18631134c0 100644 --- a/ci-scripts/cls_oaicitest.py +++ b/ci-scripts/cls_oaicitest.py @@ -244,6 +244,7 @@ def Custom_Script(HTML, node, script): return status == 'OK' or status == 'Warning' def IdleSleep(HTML, idle_sleep_time): + logging.debug(f"sleep for {idle_sleep_time} seconds") time.sleep(idle_sleep_time) HTML.CreateHtmlTestRow(f"{idle_sleep_time} sec", 'OK', CONST.ALL_PROCESSES_OK) return True From b075c733f31dbe8c695fbbe1b2d8251206e0d8fd Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 12 Aug 2025 10:43:28 +0200 Subject: [PATCH 496/964] CI: correct log analysis filename interpolation A previous commit changed to use archiveArtifact() to recover CI logs, and then attempted to "guess" the L1/MAC stats file name through a regex. However, the format "enb-[0-9]+" is not correct, as archiveArtifact() puts the task ID ("[0-9]+") BEFORE the file name (here, "enb"). So, make it more generic and match the final "-enb.log" ("$" means "end of string"). Fixes: 244ea8fc220 ("Use archiveArtifact() for TerminateeNB()") --- ci-scripts/ran.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ci-scripts/ran.py b/ci-scripts/ran.py index 49032f01e2..e440fc3a62 100644 --- a/ci-scripts/ran.py +++ b/ci-scripts/ran.py @@ -493,8 +493,8 @@ class RANManagement(): # nrL1_stats.log/nrMAC_stats.log should be in the same directory as main log file # currently the link is only implicit as below based on pattern matching # I will rework this to give the file explicitly - l1_stats_fn = re.sub(r'enb_[0-9]+', 'nrL1_stats', eNBlogFile) - mac_stats_fn = re.sub(r'enb_[0-9]+', 'nrMAC_stats', eNBlogFile) + l1_stats_fn = re.sub(r'-enb.log$', '-nrL1_stats.log', eNBlogFile) + mac_stats_fn = re.sub(r'-enb.log$', '-nrMAC_stats.log', eNBlogFile) if os.path.isfile(l1_stats_fn) and os.path.isfile(mac_stats_fn): # don't use CI-nrL1_stats.log, as this will increase the processing time for # no reason, we just need the last occurence From 5b8d66bbacadf4feac2b2bdf23f28f7a41898679 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 7 Aug 2025 18:15:26 +0200 Subject: [PATCH 497/964] Write simple CI documentation and add sample script --- ci-scripts/README.md | 60 ++++++++++++ .../xml_files/container_5g_rfsim_simple.xml | 97 +++++++++++++++++++ doc/README.md | 2 + 3 files changed, 159 insertions(+) create mode 100644 ci-scripts/README.md create mode 100644 ci-scripts/xml_files/container_5g_rfsim_simple.xml diff --git a/ci-scripts/README.md b/ci-scripts/README.md new file mode 100644 index 0000000000..becd518e4c --- /dev/null +++ b/ci-scripts/README.md @@ -0,0 +1,60 @@ +This document outlines how to use the OAI CI framework and gives a quickstart. + +[[_TOC_]] + +# Quickstart + +There is a script `main.py` that + +- reads scenario files from XML +- executes the steps (e.g., deployment of CN/gNB/UE, attach, ping, ...) + +To simplify, a script `run_locally.sh` can be used to run a single scenario +locally. First, download images for gNB&UE (we assume you already downloaded +the CN) and tag them "latest", which is expected by `run_locally.sh`: + + docker pull oaisoftwarealliance/oai-gnb:develop + docker tag oaisoftwarealliance/oai-gnb:develop oai-gnb + docker pull oaisoftwarealliance/oai-nr-ue:develop + docker tag oaisoftwarealliance/oai-nr-ue:develop oai-nr-ue + +Now, run the scenario: + + cd ~/openairinterface5g/ci-scripts/ + ./run_locally.sh xml_files/container_5g_rfsim_simple.xml + +Output should look like + +``` +[2025-08-07 18:07:49,631] INFO: ---------------------------------------- +[2025-08-07 18:07:49,631] INFO: Creating HTML header +[2025-08-07 18:07:49,631] INFO: ---------------------------------------- +[2025-08-07 18:07:49,766] INFO: ---------------------------------------- +[2025-08-07 18:07:49,767] INFO: Starting Scenario: xml_files/container_5g_rfsim_simple.xml +[2025-08-07 18:07:49,767] INFO: ---------------------------------------- +[2025-08-07 18:07:49,767] INFO: placing all artifacts for this run in /home/richie/oai/cmake_targets/log/container_5g_rfsim_simple.xml.d/ + +[...] + +[2025-08-07 18:07:49,771] INFO: ---------------------------------------- +[2025-08-07 18:07:49,771] INFO: Test ID: 1 (#1) +[2025-08-07 18:07:49,771] INFO: Deploy OAI 5G CoreNetwork +[2025-08-07 18:07:49,771] INFO: ---------------------------------------- +``` + +it will run an end-to-end test, connecting one UE to the gNB, and ping, before +undeploying. As shown, logs will be under +`/home/richie/oai/cmake_targets/log/container_5g_rfsim_simple.xml.d/`. The +python code also produces an HTML report in `ci-scripts/test_results.html`. + +# Running with local changes + +In order to run the tests as above, with local changes, please [build images +locally](../docker/README.md). + +It is not yet possible to override an existing image with changes made locally +to a source file and run it directly through the CI framework. However, it is +possible to override an existing image with local changes, and run the scenario +manually following the console logs steps provided above. This is described in +the [5G RFsimulator +README](yaml_files/5g_rfsimulator/README.md#6-running-with-local-changes). diff --git a/ci-scripts/xml_files/container_5g_rfsim_simple.xml b/ci-scripts/xml_files/container_5g_rfsim_simple.xml new file mode 100644 index 0000000000..738ce1a077 --- /dev/null +++ b/ci-scripts/xml_files/container_5g_rfsim_simple.xml @@ -0,0 +1,97 @@ + + + rfsim-5gnr-tdd + Monolithic SA TDD gNB + wrench + + 000001 + 000002 + 000003 + 000008 + 020001 + 444444 + 100001 + + + + + Deploy_Object + Deploy OAI 5G CoreNetwork + localhost + ci-scripts/yaml_files/5g_rfsimulator + mysql oai-amf oai-smf oai-upf oai-ext-dn + + + + Deploy_Object + Deploy OAI 5G gNB RF sim SA + localhost + ci-scripts/yaml_files/5g_rfsimulator + oai-gnb + + + + Deploy_Object + Deploy OAI 5G NR-UE RF sim SA + localhost + ci-scripts/yaml_files/5g_rfsimulator + oai-nr-ue + + + + Attach_UE + Attach OAI UE (Wait for IP) + rfsim5g_ue + localhost + + + + Ping + Ping ext-dn from NR-UE + rfsim5g_ue + localhost + rfsim5g_ext_dn + localhost + -c 20 -i 0.25 + 5 + + + + Detach_UE + Detach OAI UE 1 + rfsim5g_ue + localhost + + + + Undeploy_Object + true + Undeploy all OAI 5G stack + localhost + ci-scripts/yaml_files/5g_rfsimulator + 1,0,0,0 + 1,0,0,0 + + + diff --git a/doc/README.md b/doc/README.md index 40f838750a..226592ac60 100644 --- a/doc/README.md +++ b/doc/README.md @@ -133,6 +133,8 @@ The other SDRs (AW2S, LimeSDR, ...) have no READMEs. - Component tests are under `tests/`. Currently, there is a simple CU-UP tester, see the corresponding [README.md](../tests/nr-cuup/README.md). - [TESTBenches.md](./TESTBenches.md) lists the CI setup and links to pipelines +- The CI setup uses a [custom framework](../ci-scripts/README.md) to run + end-to-end tests. # Developer tools From 5212bd7a851e4a211a161b43a93cf6467701f71d Mon Sep 17 00:00:00 2001 From: Romain Beurdouche Date: Wed, 30 Jul 2025 09:59:55 +0000 Subject: [PATCH 498/964] feat(rf_emulator): Add a dummy RF library Add a simple RF emulator library with no real RF. It only synchronizes the gNB with the real time clock. It is to be used for stress test or benchmarking in phy-test mode. --- cmake_targets/build_oai | 2 +- radio/CMakeLists.txt | 5 + radio/emulator/CMakeLists.txt | 3 + radio/emulator/rf_emulator.c | 267 ++++++++++++++++++++++++++++++++++ 4 files changed, 276 insertions(+), 1 deletion(-) create mode 100644 radio/emulator/CMakeLists.txt create mode 100644 radio/emulator/rf_emulator.c diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index 292e8d0575..c2268a64b5 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -487,7 +487,7 @@ function main() { # add some default libraries that should always be built # for eNB, gNB, UEs, simulators if [[ $gNB == 1 || $eNB == 1 || $UE == 1 || $nrUE == 1 || $SIMUS_PHY == 1 || $RU == 1 ]]; then - TARGET_LIST="$TARGET_LIST params_libconfig coding rfsimulator dfts params_yaml vrtsim" + TARGET_LIST="$TARGET_LIST params_libconfig coding rfsimulator dfts params_yaml vrtsim rf_emulator" fi mkdir -p $DIR/$BUILD_DIR/build diff --git a/radio/CMakeLists.txt b/radio/CMakeLists.txt index 654fb037f0..a47a358903 100644 --- a/radio/CMakeLists.txt +++ b/radio/CMakeLists.txt @@ -42,3 +42,8 @@ add_boolean_option(VRTSIM_RADIO ON "Activate OAI's shared memory radio driver" O if(VRTSIM_RADIO) add_subdirectory(vrtsim) endif() + +add_boolean_option(OAI_RF_EMULATOR ON "Activate OAI's RF emulator" OFF) +if(OAI_RF_EMULATOR) + add_subdirectory(emulator) +endif() diff --git a/radio/emulator/CMakeLists.txt b/radio/emulator/CMakeLists.txt new file mode 100644 index 0000000000..af25cf7019 --- /dev/null +++ b/radio/emulator/CMakeLists.txt @@ -0,0 +1,3 @@ +add_library(rf_emulator MODULE rf_emulator.c) +set_target_properties(rf_emulator PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) +add_dependencies(rf_emulator generate_T) diff --git a/radio/emulator/rf_emulator.c b/radio/emulator/rf_emulator.c new file mode 100644 index 0000000000..307d9ea80d --- /dev/null +++ b/radio/emulator/rf_emulator.c @@ -0,0 +1,267 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file radio/emulator/rf_emulator.c + * \brief RF library that does nothing to be used in benchmarks with phy-test without RF + */ + +#include +#include + +#include +#include +#include "common/utils/threadPool/pthread_utils.h" +#include "common_lib.h" + +// structures and timing thread job for timing +typedef struct { + uint64_t timestamp; + pthread_mutex_t mutex; + pthread_cond_t cond; +} emulator_timestamp_t; + +typedef struct { + uint64_t last_received_sample; + double timescale; + double sample_rate; + emulator_timestamp_t emulator_timestamp; + pthread_t timing_thread; + bool run_timing_thread; +} emulator_state_t; + +static void *emulator_timing_job(void *arg) +{ + emulator_state_t *emulator_state = (emulator_state_t *)arg; + struct timespec timestamp; + if (clock_gettime(CLOCK_REALTIME, ×tamp)) { + LOG_E(UTIL, "clock_gettime failed\n"); + exit(1); + } + double leftover_samples = 0; + while (emulator_state->run_timing_thread) { + struct timespec current_time; + if (clock_gettime(CLOCK_REALTIME, ¤t_time)) { + LOG_E(UTIL, "clock_gettime failed\n"); + exit(1); + } + uint64_t diff = (current_time.tv_sec - timestamp.tv_sec) * 1000000000 + (current_time.tv_nsec - timestamp.tv_nsec); + timestamp = current_time; + double samples_to_produce = emulator_state->sample_rate * emulator_state->timescale * diff / 1e9; + + // Attempt to correct compounding rounding error + leftover_samples += samples_to_produce - (uint64_t)samples_to_produce; + if (leftover_samples > 1.0f) { + samples_to_produce += 1; + leftover_samples -= 1; + } + + emulator_timestamp_t *emulator_timestamp = &emulator_state->emulator_timestamp; + mutexlock(emulator_timestamp->mutex); + emulator_timestamp->timestamp += samples_to_produce; + condbroadcast(emulator_timestamp->cond); + mutexunlock(emulator_timestamp->mutex); + + usleep(1); + } + return 0; +} + +/*! \brief Called to start the RF transceiver. Return 0 if OK, < 0 if error + * \param device pointer to the device structure specific to the RF hardware target + */ +static int emulator_start(openair0_device *device) +{ + // Start the timing thread + emulator_state_t *emulator_state = (emulator_state_t *)device->priv; + if (!emulator_state->run_timing_thread) { + emulator_timestamp_t *emulator_timestamp = &emulator_state->emulator_timestamp; + memset(emulator_timestamp, 0, sizeof(emulator_timestamp_t)); + + pthread_mutexattr_t mutex_attr; + pthread_condattr_t cond_attr; + int ret = pthread_mutexattr_init(&mutex_attr); + AssertFatal(ret == 0, "pthread_mutexattr_init() failed: errno %d, %s\n", errno, strerror(errno)); + + ret = pthread_condattr_init(&cond_attr); + AssertFatal(ret == 0, "pthread_condattr_init() failed: errno %d, %s\n", errno, strerror(errno)); + + ret = pthread_mutexattr_setpshared(&mutex_attr, PTHREAD_PROCESS_SHARED); + AssertFatal(ret == 0, "pthread_mutexattr_setpshared() failed: errno %d, %s\n", errno, strerror(errno)); + + ret = pthread_condattr_setpshared(&cond_attr, PTHREAD_PROCESS_SHARED); + AssertFatal(ret == 0, "pthread_condattr_setpshared() failed: errno %d, %s\n", errno, strerror(errno)); + + ret = pthread_mutex_init(&emulator_timestamp->mutex, &mutex_attr); + AssertFatal(ret == 0, "pthread_mutex_init() failed: errno %d, %s\n", errno, strerror(errno)); + + ret = pthread_cond_init(&emulator_timestamp->cond, &cond_attr); + AssertFatal(ret == 0, "pthread_cond_init() failed: errno %d, %s\n", errno, strerror(errno)); + + emulator_state->run_timing_thread = true; + ret = pthread_create(&emulator_state->timing_thread, NULL, emulator_timing_job, emulator_state); + AssertFatal(ret == 0, "pthread_create() failed: errno: %d, %s\n", errno, strerror(errno)); + } + + return 0; +} + +/*! \brief print the RF statistics + * \param device pointer to the device structure specific to the RF hardware target + * \returns 0 on success + */ +int emulator_get_stats(openair0_device *device) +{ + return (0); +} + +/*! \brief Reset the RF statistics + * \param device pointer to the device structure specific to the RF hardware target + * \returns 0 on success + */ +int emulator_reset_stats(openair0_device *device) +{ + return (0); +} + +/*! \brief Terminate operation of the RF transceiver -- free all associated resources (if any) + * \param pointer to the device structure specific to the RF hardware target + */ +static void emulator_end(openair0_device *device) +{ + // Stop the timing thread + emulator_state_t *emulator_state = (emulator_state_t *)device->priv; + if (emulator_state->run_timing_thread) { + emulator_state->run_timing_thread = false; + int ret = pthread_join(emulator_state->timing_thread, NULL); + AssertFatal(ret == 0, "pthread_join() failed: errno: %d, %s\n", errno, strerror(errno)); + } +} + +/*! \brief Stop RF + * \param device pointer to the device structure specific to the RF hardware target + */ +int emulator_stop(openair0_device *device) +{ + return (0); +} + +/*! \brief Set Gains (TX/RX) + * \param device pointer to the device structure specific to the RF hardware target + * \param openair0_cfg RF frontend parameters set by application + * \returns 0 in success + */ +int emulator_set_gains(openair0_device *device, openair0_config_t *openair0_cfg) +{ + return (0); +} + +/*! \brief Set frequencies (TX/RX). + * \param device pointer to the device structure specific to the RF hardware target + * \param openair0_cfg RF frontend parameters set by application + * \returns 0 in success + */ +int emulator_set_freq(openair0_device *device, openair0_config_t *openair0_cfg) +{ + return (0); +} + +int emulator_write_init(openair0_device *device) +{ + return (0); +} + +/*! \brief Called to send samples to the RF target + * \param device pointer to the device structure specific to the RF hardware target + * \param timestamp The timestamp at which the first sample MUST be sent + * \param buff Buffer which holds the samples + * \param nsamps number of samples to be sent + * \param nbAnt number of antennas + * \param flags flags must be set to true if timestamp parameter needs to be applied + */ +static int emulator_write(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps, int nbAnt, int flags) +{ + return 0; +} + +/*! \brief Receive samples from hardware. + * Read \ref nsamps samples from each channel to buffers. buff[0] is the array for + * the first channel. + * \param[out] ptimestamp time at which the first sample was received. + * \param device pointer to the device structure specific to the RF hardware target + * \param[out] ptimestamp the time at which the first sample was received. + * \param[out] buff An array of pointers to buffers for received samples. The buffers must be large enough to hold the number of + * samples \ref nsamps. \param nsamps Number of samples. One sample is 2 byte I + 2 byte Q => 4 byte. + * \param nbAnt number of antennas + * \returns the number of samples read + */ +static int emulator_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int nbAnt) +{ + emulator_state_t *emulator_state = (emulator_state_t *)device->priv; + + emulator_timestamp_t *emulator_timestamp = &emulator_state->emulator_timestamp; + uint64_t timestamp = emulator_state->last_received_sample + nsamps; + uint64_t current_timestamp = emulator_timestamp->timestamp; + if (current_timestamp < timestamp) { + mutexlock(emulator_timestamp->mutex); + while (current_timestamp < timestamp) { + condwait(emulator_timestamp->cond, emulator_timestamp->mutex); + current_timestamp = emulator_timestamp->timestamp; + } + mutexunlock(emulator_timestamp->mutex); + } else { + LOG_W(HW, "RF read is late!\n"); + } + *ptimestamp = emulator_state->last_received_sample; + emulator_state->last_received_sample += nsamps; + + for (int i = 0; i < nbAnt; i++) { + memset(buff[i], 0, nsamps * sizeof(uint32_t)); // TODO Play random data + } + + return nsamps; +} + +int device_init(openair0_device *device, openair0_config_t *openair0_cfg) +{ + LOG_I(HW, "This is emulator RF that does nothing\n"); + + emulator_state_t *emulator_state = calloc_or_fail(1, sizeof(emulator_state_t)); + emulator_state->last_received_sample = 0; + emulator_state->timescale = 1.0; + emulator_state->sample_rate = openair0_cfg->sample_rate; + emulator_state->run_timing_thread = false; + + device->priv = emulator_state; + device->openair0_cfg = openair0_cfg; + device->trx_start_func = emulator_start; + device->trx_get_stats_func = emulator_get_stats; + device->trx_reset_stats_func = emulator_reset_stats; + device->trx_end_func = emulator_end; + device->trx_stop_func = emulator_stop; + device->trx_set_freq_func = emulator_set_freq; + device->trx_set_gains_func = emulator_set_gains; + device->trx_write_init = emulator_write_init; + device->type = RFSIMULATOR; + device->trx_write_func = emulator_write; + device->trx_read_func = emulator_read; + + return 0; +} From bf83b787586445652c83de907a09dde694a36758 Mon Sep 17 00:00:00 2001 From: Romain Beurdouche Date: Thu, 31 Jul 2025 13:46:48 +0000 Subject: [PATCH 499/964] feat(rf_emulator): Count late reads Count late reads and print every second instead of printing each. --- radio/emulator/rf_emulator.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/radio/emulator/rf_emulator.c b/radio/emulator/rf_emulator.c index 307d9ea80d..0ba9ea0636 100644 --- a/radio/emulator/rf_emulator.c +++ b/radio/emulator/rf_emulator.c @@ -36,6 +36,7 @@ typedef struct { uint64_t timestamp; pthread_mutex_t mutex; pthread_cond_t cond; + uint64_t late_reads; } emulator_timestamp_t; typedef struct { @@ -62,6 +63,15 @@ static void *emulator_timing_job(void *arg) LOG_E(UTIL, "clock_gettime failed\n"); exit(1); } + + emulator_timestamp_t *emulator_timestamp = &emulator_state->emulator_timestamp; + if (current_time.tv_sec != timestamp.tv_sec) { + if (emulator_timestamp->late_reads != 0) { + LOG_W(HW, "%ld RF reads were late\n", emulator_timestamp->late_reads); + } + emulator_timestamp->late_reads = 0; + } + uint64_t diff = (current_time.tv_sec - timestamp.tv_sec) * 1000000000 + (current_time.tv_nsec - timestamp.tv_nsec); timestamp = current_time; double samples_to_produce = emulator_state->sample_rate * emulator_state->timescale * diff / 1e9; @@ -73,7 +83,6 @@ static void *emulator_timing_job(void *arg) leftover_samples -= 1; } - emulator_timestamp_t *emulator_timestamp = &emulator_state->emulator_timestamp; mutexlock(emulator_timestamp->mutex); emulator_timestamp->timestamp += samples_to_produce; condbroadcast(emulator_timestamp->cond); @@ -227,7 +236,9 @@ static int emulator_read(openair0_device *device, openair0_timestamp *ptimestamp } mutexunlock(emulator_timestamp->mutex); } else { - LOG_W(HW, "RF read is late!\n"); + mutexlock(emulator_timestamp->mutex); + emulator_timestamp->late_reads++; + mutexunlock(emulator_timestamp->mutex); } *ptimestamp = emulator_state->last_received_sample; emulator_state->last_received_sample += nsamps; From 33cbbafddb1ba8334075d97ae08e198cabcac47d Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Thu, 24 Jul 2025 16:59:12 +0200 Subject: [PATCH 500/964] ds: add a new type "byte array producer" Introduced to write bytes to a byte array with size checking. --- common/utils/ds/CMakeLists.txt | 1 + common/utils/ds/byte_array_producer.c | 64 +++++++++++++++++++++++++++ common/utils/ds/byte_array_producer.h | 40 +++++++++++++++++ 3 files changed, 105 insertions(+) create mode 100644 common/utils/ds/byte_array_producer.c create mode 100644 common/utils/ds/byte_array_producer.h diff --git a/common/utils/ds/CMakeLists.txt b/common/utils/ds/CMakeLists.txt index a5ae86c52f..b5f5efb47a 100644 --- a/common/utils/ds/CMakeLists.txt +++ b/common/utils/ds/CMakeLists.txt @@ -1,5 +1,6 @@ add_library(ds OBJECT byte_array.c + byte_array_producer.c seq_arr.c ) diff --git a/common/utils/ds/byte_array_producer.c b/common/utils/ds/byte_array_producer.c new file mode 100644 index 0000000000..07f46c363c --- /dev/null +++ b/common/utils/ds/byte_array_producer.c @@ -0,0 +1,64 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include "byte_array_producer.h" + +/* create a byte array producer from an existing buffer */ +byte_array_producer_t byte_array_producer_from_buffer(uint8_t *buffer, int len) +{ + byte_array_producer_t result = { .b.len = len, .b.buf = buffer, .pos = 0 }; + return result; +} + +/* put a byte in a byte array if there is space + * returns 1 on success, 0 on error + */ +int byte_array_producer_put_byte(byte_array_producer_t *b, uint8_t byte) +{ + if (b->pos == b->b.len) + return 0; + + b->b.buf[b->pos] = byte; + b->pos++; + + return 1; +} + +/* put an u32 number as big endian in a byte array if there is space + * returns 1 on success, 0 on error + */ +int byte_array_producer_put_u32_be(byte_array_producer_t *b, uint32_t v) +{ + return byte_array_producer_put_byte(b, (v >> 24) & 0xff) + && byte_array_producer_put_byte(b, (v >> 16) & 0xff) + && byte_array_producer_put_byte(b, (v >> 8) & 0xff) + && byte_array_producer_put_byte(b, v & 0xff); +} + +/* put an u24 number as big endian in a byte array if there is space + * returns 1 on success, 0 on error + */ +int byte_array_producer_put_u24_be(byte_array_producer_t *b, uint32_t v) +{ + return byte_array_producer_put_byte(b, (v >> 16) & 0xff) + && byte_array_producer_put_byte(b, (v >> 8) & 0xff) + && byte_array_producer_put_byte(b, v & 0xff); +} diff --git a/common/utils/ds/byte_array_producer.h b/common/utils/ds/byte_array_producer.h new file mode 100644 index 0000000000..2087c77af1 --- /dev/null +++ b/common/utils/ds/byte_array_producer.h @@ -0,0 +1,40 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef BYTE_ARRAY_PRODUCER_H +#define BYTE_ARRAY_PRODUCER_H + +#include + +#include "byte_array.h" + +typedef struct { + byte_array_t b; + size_t pos; +} byte_array_producer_t; + +byte_array_producer_t byte_array_producer_from_buffer(uint8_t *buffer, int len); + +int byte_array_producer_put_byte(byte_array_producer_t *b, uint8_t v); +int byte_array_producer_put_u32_be(byte_array_producer_t *b, uint32_t v); +int byte_array_producer_put_u24_be(byte_array_producer_t *b, uint32_t v); + +#endif From 5e0374883572a65e23ddc15ee1310e1b5f140459 Mon Sep 17 00:00:00 2001 From: Romain Beurdouche Date: Fri, 1 Aug 2025 16:15:03 +0000 Subject: [PATCH 501/964] feat(rf_emulator): Add noise generation --- radio/emulator/CMakeLists.txt | 1 + radio/emulator/rf_emulator.c | 46 ++++++++++++++++++++++++++++++++--- radio/vrtsim/CMakeLists.txt | 6 +++-- 3 files changed, 48 insertions(+), 5 deletions(-) diff --git a/radio/emulator/CMakeLists.txt b/radio/emulator/CMakeLists.txt index af25cf7019..42b196ee95 100644 --- a/radio/emulator/CMakeLists.txt +++ b/radio/emulator/CMakeLists.txt @@ -1,3 +1,4 @@ add_library(rf_emulator MODULE rf_emulator.c) set_target_properties(rf_emulator PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) +target_link_libraries(rf_emulator PRIVATE noise_device) add_dependencies(rf_emulator generate_T) diff --git a/radio/emulator/rf_emulator.c b/radio/emulator/rf_emulator.c index 0ba9ea0636..c53ac7adf3 100644 --- a/radio/emulator/rf_emulator.c +++ b/radio/emulator/rf_emulator.c @@ -30,6 +30,8 @@ #include #include "common/utils/threadPool/pthread_utils.h" #include "common_lib.h" +#include "radio/vrtsim/noise_device.h" +#include "simde/x86/avx512.h" // structures and timing thread job for timing typedef struct { @@ -98,9 +100,11 @@ static void *emulator_timing_job(void *arg) */ static int emulator_start(openair0_device *device) { - // Start the timing thread + // Start the timing thread and the noise device emulator_state_t *emulator_state = (emulator_state_t *)device->priv; if (!emulator_state->run_timing_thread) { + init_noise_device(0); // TODO configure noise level + emulator_timestamp_t *emulator_timestamp = &emulator_state->emulator_timestamp; memset(emulator_timestamp, 0, sizeof(emulator_timestamp_t)); @@ -155,12 +159,13 @@ int emulator_reset_stats(openair0_device *device) */ static void emulator_end(openair0_device *device) { - // Stop the timing thread + // Stop the timing thread and the noise device emulator_state_t *emulator_state = (emulator_state_t *)device->priv; if (emulator_state->run_timing_thread) { emulator_state->run_timing_thread = false; int ret = pthread_join(emulator_state->timing_thread, NULL); AssertFatal(ret == 0, "pthread_join() failed: errno: %d, %s\n", errno, strerror(errno)); + free_noise_device(); } } @@ -210,6 +215,41 @@ static int emulator_write(openair0_device *device, openair0_timestamp timestamp, return 0; } +/*! \brief Store noise in the buffer buff + * \param[out] buff A buffer for received samples. + * The buffers must be large enough to hold the number of samples \ref nsamps. + * \param nsamps Number of samples. One sample is 2 byte I + 2 byte Q => 4 byte. + */ +static void read_noise(void *buff, int nsamps) +{ + int aligned_nsamps = ceil_mod(nsamps, (512 / 8) / sizeof(cf_t)); + cf_t samples[aligned_nsamps] __attribute__((aligned(64))); + // Apply noise from global settings + get_noise_vector((float *)samples, nsamps * 2); + + // Convert to c16_t + c16_t samples_out[aligned_nsamps] __attribute__((aligned(64))); +#if defined(__AVX512F__) + for (int i = 0; i < aligned_nsamps / 8; i++) { + simde__m512 *in = (simde__m512 *)&samples[i * 8]; + simde__m256i *out = (simde__m256i *)&samples_out[i * 8]; + *out = simde_mm512_cvtsepi32_epi16(simde_mm512_cvtps_epi32(*in)); + } +#elif defined(__AVX2__) + for (int i = 0; i < aligned_nsamps / 4; i++) { + simde__m256 *in = (simde__m256 *)&samples[i * 4]; + simde__m128i *out = (simde__m128i *)&samples_out[i * 4]; + *out = simde_mm256_cvtsepi32_epi16(simde_mm256_cvtps_epi32(*in)); + } +#else + for (int i = 0; i < nsamps; i++) { + samples_out[i].r = lroundf(samples[i].r); + samples_out[i].i = lroundf(samples[i].i); + } +#endif + memcpy(buff, samples_out, nsamps * sizeof(c16_t)); +} + /*! \brief Receive samples from hardware. * Read \ref nsamps samples from each channel to buffers. buff[0] is the array for * the first channel. @@ -244,7 +284,7 @@ static int emulator_read(openair0_device *device, openair0_timestamp *ptimestamp emulator_state->last_received_sample += nsamps; for (int i = 0; i < nbAnt; i++) { - memset(buff[i], 0, nsamps * sizeof(uint32_t)); // TODO Play random data + read_noise(buff[i], nsamps); } return nsamps; diff --git a/radio/vrtsim/CMakeLists.txt b/radio/vrtsim/CMakeLists.txt index 79eb4d88da..8586183099 100644 --- a/radio/vrtsim/CMakeLists.txt +++ b/radio/vrtsim/CMakeLists.txt @@ -1,4 +1,6 @@ -add_library(vrtsim MODULE vrtsim.c noise_device.c) +add_library(noise_device STATIC noise_device.c) + +add_library(vrtsim MODULE vrtsim.c) set_target_properties(vrtsim PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) -target_link_libraries(vrtsim PRIVATE SIMU shm_td_iq_channel actor) +target_link_libraries(vrtsim PRIVATE SIMU shm_td_iq_channel actor noise_device) add_dependencies(vrtsim generate_T) From dfa77647b1f9a1f877b5c8e3fa6832259a296a59 Mon Sep 17 00:00:00 2001 From: Romain Beurdouche Date: Mon, 4 Aug 2025 15:29:25 +0000 Subject: [PATCH 502/964] feat(rf_emulator): Add late writes counter --- radio/emulator/rf_emulator.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/radio/emulator/rf_emulator.c b/radio/emulator/rf_emulator.c index c53ac7adf3..a747afc053 100644 --- a/radio/emulator/rf_emulator.c +++ b/radio/emulator/rf_emulator.c @@ -39,6 +39,7 @@ typedef struct { pthread_mutex_t mutex; pthread_cond_t cond; uint64_t late_reads; + uint64_t late_writes; } emulator_timestamp_t; typedef struct { @@ -72,6 +73,10 @@ static void *emulator_timing_job(void *arg) LOG_W(HW, "%ld RF reads were late\n", emulator_timestamp->late_reads); } emulator_timestamp->late_reads = 0; + if (emulator_timestamp->late_writes != 0) { + LOG_W(HW, "%ld RF writes were late\n", emulator_timestamp->late_writes); + } + emulator_timestamp->late_writes = 0; } uint64_t diff = (current_time.tv_sec - timestamp.tv_sec) * 1000000000 + (current_time.tv_nsec - timestamp.tv_nsec); @@ -212,6 +217,17 @@ int emulator_write_init(openair0_device *device) */ static int emulator_write(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps, int nbAnt, int flags) { + emulator_state_t *emulator_state = (emulator_state_t *)device->priv; + + // timestamp in the past + emulator_timestamp_t *emulator_timestamp = &emulator_state->emulator_timestamp; + uint64_t current_timestamp = emulator_timestamp->timestamp; + if (timestamp < current_timestamp) { + mutexlock(emulator_timestamp->mutex); + emulator_timestamp->late_writes++; + mutexunlock(emulator_timestamp->mutex); + } + return 0; } From 29108a0974d458ba423837bcfe1afd7f442c6350 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Fri, 1 Aug 2025 15:22:50 +0200 Subject: [PATCH 503/964] cleaning syntax of nr-ru.c --- executables/nr-ru.c | 979 +++++++++++++++++++++----------------------- 1 file changed, 459 insertions(+), 520 deletions(-) diff --git a/executables/nr-ru.c b/executables/nr-ru.c index c0da88e634..72bc44bffb 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -63,7 +63,6 @@ static int DEFRUTPCORES[] = {-1,-1,-1,-1}; #include - #include "T.h" #include "nfapi_interface.h" #include @@ -74,63 +73,69 @@ static void NRRCconfig_RU(configmodule_interface_t *cfg); /*************************************************************/ /* Functions to attach and configure RRU */ -int attach_rru(RU_t *ru) { - ssize_t msg_len,len; +int attach_rru(RU_t *ru) +{ RRU_CONFIG_msg_t rru_config_msg; int received_capabilities=0; wait_gNBs(); // Wait for capabilities while (received_capabilities==0) { - memset((void *)&rru_config_msg,0,sizeof(rru_config_msg)); - rru_config_msg.type = RAU_tick; - rru_config_msg.len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE; + rru_config_msg = (RRU_CONFIG_msg_t){.type = RAU_tick, .len = sizeof(rru_config_msg.msg)}; LOG_D(PHY, "Sending RAU tick to RRU %d\n", ru->idx); AssertFatal((ru->ifdevice.trx_ctlsend_func(&ru->ifdevice,&rru_config_msg,rru_config_msg.len)!=-1), "RU %d cannot access remote radio\n",ru->idx); - msg_len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE+sizeof(RRU_capabilities_t); - + ssize_t msg_len = rru_config_msg.len + sizeof(RRU_capabilities_t); // wait for answer with timeout - if ((len = ru->ifdevice.trx_ctlrecv_func(&ru->ifdevice, - &rru_config_msg, - msg_len))<0) { + ssize_t len = ru->ifdevice.trx_ctlrecv_func(&ru->ifdevice, &rru_config_msg, msg_len); + if (len < 0) { LOG_D(PHY, "Waiting for RRU %d\n", ru->idx); } else if (rru_config_msg.type == RRU_capabilities) { - AssertFatal(rru_config_msg.len==msg_len,"Received capabilities with incorrect length (%d!=%d)\n",(int)rru_config_msg.len,(int)msg_len); - LOG_I(PHY,"Received capabilities from RRU %d (len %d/%d, num_bands %d,max_pdschReferenceSignalPower %d, max_rxgain %d, nb_tx %d, nb_rx %d)\n",ru->idx, - (int)rru_config_msg.len,(int)msg_len, - ((RRU_capabilities_t *)&rru_config_msg.msg[0])->num_bands, - ((RRU_capabilities_t *)&rru_config_msg.msg[0])->max_pdschReferenceSignalPower[0], - ((RRU_capabilities_t *)&rru_config_msg.msg[0])->max_rxgain[0], - ((RRU_capabilities_t *)&rru_config_msg.msg[0])->nb_tx[0], - ((RRU_capabilities_t *)&rru_config_msg.msg[0])->nb_rx[0]); + AssertFatal(rru_config_msg.len == msg_len, + "Received capabilities with incorrect length (%ld!=%ld)\n", + rru_config_msg.len, + msg_len); + RRU_capabilities_t *cap = (RRU_capabilities_t *)rru_config_msg.msg; + LOG_I(PHY, + "Received capabilities from RRU %d (len %ld/%ld, num_bands %d,max_pdschReferenceSignalPower %d, max_rxgain %d, nb_tx " + "%d, nb_rx %d)\n", + ru->idx, + rru_config_msg.len, + msg_len, + cap->num_bands, + cap->max_pdschReferenceSignalPower[0], + cap->max_rxgain[0], + cap->nb_tx[0], + cap->nb_rx[0]); received_capabilities=1; } else { LOG_E(PHY,"Received incorrect message %d from RRU %d\n",rru_config_msg.type,ru->idx); } } - configure_ru(ru, (RRU_capabilities_t *)&rru_config_msg.msg[0]); + configure_ru(ru, (RRU_capabilities_t *)rru_config_msg.msg); rru_config_msg.type = RRU_config; rru_config_msg.len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE+sizeof(RRU_config_t); - LOG_I(PHY,"Sending Configuration to RRU %d (num_bands %d,band0 %d,txfreq %u,rxfreq %u,att_tx %d,att_rx %d,N_RB_DL %d,N_RB_UL %d,3/4FS %d, prach_FO %d, prach_CI %d)\n",ru->idx, - ((RRU_config_t *)&rru_config_msg.msg[0])->num_bands, - ((RRU_config_t *)&rru_config_msg.msg[0])->band_list[0], - ((RRU_config_t *)&rru_config_msg.msg[0])->tx_freq[0], - ((RRU_config_t *)&rru_config_msg.msg[0])->rx_freq[0], - ((RRU_config_t *)&rru_config_msg.msg[0])->att_tx[0], - ((RRU_config_t *)&rru_config_msg.msg[0])->att_rx[0], - ((RRU_config_t *)&rru_config_msg.msg[0])->N_RB_DL[0], - ((RRU_config_t *)&rru_config_msg.msg[0])->N_RB_UL[0], - ((RRU_config_t *)&rru_config_msg.msg[0])->threequarter_fs[0], - ((RRU_config_t *)&rru_config_msg.msg[0])->prach_FreqOffset[0], - ((RRU_config_t *)&rru_config_msg.msg[0])->prach_ConfigIndex[0]); + RRU_config_t *conf = (RRU_config_t *)rru_config_msg.msg; + LOG_I(PHY, + "Sending Configuration to RRU %d (num_bands %d,band0 %d,txfreq %u,rxfreq %u,att_tx %d,att_rx %d,N_RB_DL %d,N_RB_UL " + "%d,3/4FS %d, prach_FO %d, prach_CI %d)\n", + ru->idx, + conf->num_bands, + conf->band_list[0], + conf->tx_freq[0], + conf->rx_freq[0], + conf->att_tx[0], + conf->att_rx[0], + conf->N_RB_DL[0], + conf->N_RB_UL[0], + conf->threequarter_fs[0], + conf->prach_FreqOffset[0], + conf->prach_ConfigIndex[0]); AssertFatal((ru->ifdevice.trx_ctlsend_func(&ru->ifdevice,&rru_config_msg,rru_config_msg.len)!=-1), "RU %d failed send configuration to remote radio\n",ru->idx); - - if ((len = ru->ifdevice.trx_ctlrecv_func(&ru->ifdevice, - &rru_config_msg, - msg_len))<0) { + int len = ru->ifdevice.trx_ctlrecv_func(&ru->ifdevice, &rru_config_msg, sizeof(rru_config_msg.msg)); + if (len < 0) { LOG_I(PHY,"Waiting for RRU %d\n",ru->idx); } else if (rru_config_msg.type == RRU_config_ok) { LOG_I(PHY, "RRU_config_ok received\n"); @@ -142,58 +147,57 @@ int attach_rru(RU_t *ru) { } int connect_rau(RU_t *ru) { - RRU_CONFIG_msg_t rru_config_msg; - ssize_t msg_len; - int tick_received = 0; - int configuration_received = 0; - RRU_capabilities_t *cap; - int i; - int len; + RRU_CONFIG_msg_t rru_config_msg; // wait for RAU_tick + int tick_received = 0; while (tick_received == 0) { - msg_len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE; - - if ((len = ru->ifdevice.trx_ctlrecv_func(&ru->ifdevice, - &rru_config_msg, - msg_len))<0) { + ssize_t msg_len = sizeof(rru_config_msg.msg); + int len = ru->ifdevice.trx_ctlrecv_func(&ru->ifdevice, &rru_config_msg, msg_len); + if (len < 0) { LOG_I(PHY,"Waiting for RAU\n"); } else { if (rru_config_msg.type == RAU_tick) { LOG_I(PHY,"Tick received from RAU\n"); tick_received = 1; - } else LOG_E(PHY,"Received erroneous message (%d)from RAU, expected RAU_tick\n",rru_config_msg.type); + } else + LOG_E(PHY, "Received erroneous message (%d)from RAU, expected RAU_tick\n", rru_config_msg.type); } } // send capabilities rru_config_msg.type = RRU_capabilities; rru_config_msg.len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE+sizeof(RRU_capabilities_t); - cap = (RRU_capabilities_t *)&rru_config_msg.msg[0]; - LOG_I(PHY,"Sending Capabilities (len %d, num_bands %d,max_pdschReferenceSignalPower %d, max_rxgain %d, nb_tx %d, nb_rx %d)\n", - (int)rru_config_msg.len,ru->num_bands,ru->max_pdschReferenceSignalPower,ru->max_rxgain,ru->nb_tx,ru->nb_rx); + RRU_capabilities_t *cap = (RRU_capabilities_t *)rru_config_msg.msg; + LOG_I(PHY, + "Sending Capabilities (len %ld, num_bands %d,max_pdschReferenceSignalPower %d, max_rxgain %d, nb_tx %d, nb_rx %d)\n", + rru_config_msg.len, + ru->num_bands, + ru->max_pdschReferenceSignalPower, + ru->max_rxgain, + ru->nb_tx, + ru->nb_rx); switch (ru->function) { case NGFI_RRU_IF4p5: - cap->FH_fmt = OAI_IF4p5_only; + cap->FH_fmt = OAI_IF4p5_only; break; case NGFI_RRU_IF5: - cap->FH_fmt = OAI_IF5_only; + cap->FH_fmt = OAI_IF5_only; break; case MBP_RRU_IF5: - cap->FH_fmt = MBP_IF5; + cap->FH_fmt = MBP_IF5; break; default: - AssertFatal(1==0,"RU_function is unknown %d\n",RC.ru[0]->function); + AssertFatal(false, "RU_function is unknown %d\n", RC.ru[0]->function); break; } - cap->num_bands = ru->num_bands; - - for (i=0; inum_bands; i++) { + cap->num_bands = ru->num_bands; + for (int i = 0; i < ru->num_bands; i++) { LOG_I(PHY,"Band %d: nb_rx %d nb_tx %d pdschReferenceSignalPower %d rxgain %d\n", ru->band[i],ru->nb_rx,ru->nb_tx,ru->max_pdschReferenceSignalPower,ru->max_rxgain); cap->band_list[i] = ru->band[i]; @@ -208,25 +212,28 @@ int connect_rau(RU_t *ru) { // wait for configuration rru_config_msg.len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE+sizeof(RRU_config_t); + int configuration_received = 0; while (configuration_received == 0) { - if ((len = ru->ifdevice.trx_ctlrecv_func(&ru->ifdevice, - &rru_config_msg, - rru_config_msg.len))<0) { + int len = ru->ifdevice.trx_ctlrecv_func(&ru->ifdevice, &rru_config_msg, rru_config_msg.len); + if (len < 0) { LOG_I(PHY,"Waiting for configuration from RAU\n"); } else { - LOG_I(PHY,"Configuration received from RAU (num_bands %d,band0 %d,txfreq %u,rxfreq %u,att_tx %d,att_rx %d,N_RB_DL %d,N_RB_UL %d,3/4FS %d, prach_FO %d, prach_CI %d)\n", - ((RRU_config_t *)&rru_config_msg.msg[0])->num_bands, - ((RRU_config_t *)&rru_config_msg.msg[0])->band_list[0], - ((RRU_config_t *)&rru_config_msg.msg[0])->tx_freq[0], - ((RRU_config_t *)&rru_config_msg.msg[0])->rx_freq[0], - ((RRU_config_t *)&rru_config_msg.msg[0])->att_tx[0], - ((RRU_config_t *)&rru_config_msg.msg[0])->att_rx[0], - ((RRU_config_t *)&rru_config_msg.msg[0])->N_RB_DL[0], - ((RRU_config_t *)&rru_config_msg.msg[0])->N_RB_UL[0], - ((RRU_config_t *)&rru_config_msg.msg[0])->threequarter_fs[0], - ((RRU_config_t *)&rru_config_msg.msg[0])->prach_FreqOffset[0], - ((RRU_config_t *)&rru_config_msg.msg[0])->prach_ConfigIndex[0]); - configure_rru(ru, (void *)&rru_config_msg.msg[0]); + RRU_config_t *conf = (RRU_config_t *)rru_config_msg.msg; + LOG_I(PHY, + "Configuration received from RAU (num_bands %d,band0 %d,txfreq %u,rxfreq %u,att_tx %d,att_rx %d,N_RB_DL %d,N_RB_UL " + "%d,3/4FS %d, prach_FO %d, prach_CI %d)\n", + conf->num_bands, + conf->band_list[0], + conf->tx_freq[0], + conf->rx_freq[0], + conf->att_tx[0], + conf->att_rx[0], + conf->N_RB_DL[0], + conf->N_RB_UL[0], + conf->threequarter_fs[0], + conf->prach_FreqOffset[0], + conf->prach_ConfigIndex[0]); + configure_rru(ru, (void *)rru_config_msg.msg); configuration_received = 1; } } @@ -238,15 +245,23 @@ int connect_rau(RU_t *ru) { // southbound IF5 fronthaul for 16-bit OAI format void fh_if5_south_out(RU_t *ru, int frame, int slot, uint64_t timestamp) { - if (ru == RC.ru[0]) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, ru->proc.timestamp_tx&0xffffffff ); + if (ru == RC.ru[0]) + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, ru->proc.timestamp_tx & 0xffffffff); int offset = ru->nr_frame_parms->get_samples_slot_timestamp(slot,ru->nr_frame_parms,0); void *buffs[ru->nb_tx]; for (int aid = 0; aid < ru->nb_tx; aid++) buffs[aid] = (void*)&ru->common.txdata[aid][offset]; struct timespec txmeas; clock_gettime(CLOCK_MONOTONIC, &txmeas); - LOG_D(NR_PHY,"IF5 TX %d.%d, TS %llu, buffs[0] %p, buffs[1] %p ener0 %f dB, tx start %d\n",frame,slot,(unsigned long long)timestamp,buffs[0],buffs[1], - 10*log10((double)signal_energy(buffs[0],ru->nr_frame_parms->get_samples_per_slot(slot,ru->nr_frame_parms))),(int)txmeas.tv_nsec); + LOG_D(NR_PHY, + "IF5 TX %d.%d, TS %lu, buffs[0] %p, buffs[1] %p ener0 %f dB, tx start %d\n", + frame, + slot, + timestamp, + buffs[0], + buffs[1], + 10 * log10((double)signal_energy(buffs[0], ru->nr_frame_parms->get_samples_per_slot(slot, ru->nr_frame_parms))), + (int)txmeas.tv_nsec); ru->ifdevice.trx_write_func2(&ru->ifdevice, timestamp, buffs, @@ -258,13 +273,12 @@ void fh_if5_south_out(RU_t *ru, int frame, int slot, uint64_t timestamp) { // southbound IF4p5 fronthaul void fh_if4p5_south_out(RU_t *ru, int frame, int slot, uint64_t timestamp) { - nfapi_nr_config_request_scf_t *cfg = &ru->config; - - if (ru == RC.ru[0]) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, ru->proc.timestamp_tx&0xffffffff ); + if (ru == RC.ru[0]) + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, ru->proc.timestamp_tx & 0xffffffff); LOG_D(PHY,"Sending IF4p5 for frame %d subframe %d\n",ru->proc.frame_tx,ru->proc.tti_tx); - if ((nr_slot_select(cfg,ru->proc.frame_tx,ru->proc.tti_tx)&NR_DOWNLINK_SLOT) > 0) + if ((nr_slot_select(&ru->config, ru->proc.frame_tx, ru->proc.tti_tx) & NR_DOWNLINK_SLOT) > 0) send_IF4p5(ru,frame, slot, IF4p5_PDLFFT); } @@ -281,11 +295,11 @@ void fh_if5_south_in(RU_t *ru, VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 1 ); start_meas(&ru->rx_fhaul); - ru->ifdevice.trx_read_func2(&ru->ifdevice,&proc->timestamp_rx,NULL,fp->get_samples_per_slot(*tti,fp)); - if (proc->first_rx == 1) ru->ts_offset = proc->timestamp_rx; - proc->frame_rx = ((proc->timestamp_rx-ru->ts_offset) / (fp->samples_per_subframe*10))&1023; - proc->tti_rx = fp->get_slot_from_timestamp(proc->timestamp_rx-ru->ts_offset,fp); - + ru->ifdevice.trx_read_func2(&ru->ifdevice, &proc->timestamp_rx, NULL, fp->get_samples_per_slot(*tti, fp)); + if (proc->first_rx == 1) + ru->ts_offset = proc->timestamp_rx; + proc->frame_rx = ((proc->timestamp_rx - ru->ts_offset) / (fp->samples_per_subframe * 10)) & 1023; + proc->tti_rx = fp->get_slot_from_timestamp(proc->timestamp_rx - ru->ts_offset, fp); if (proc->first_rx == 0) { if (proc->tti_rx != *tti) { @@ -311,8 +325,26 @@ void fh_if5_south_in(RU_t *ru, struct timespec rxmeas; clock_gettime(CLOCK_MONOTONIC, &rxmeas); double fhtime = ru->rx_fhaul.p_time/(cpu_freq_GHz*1000.0); - if (fhtime > 800) LOG_W(PHY,"IF5 %d.%d => RX %d.%d first_rx %d: time %f, rxstart %d\n",*frame,*tti,proc->frame_rx,proc->tti_rx,proc->first_rx,ru->rx_fhaul.p_time/(cpu_freq_GHz*1000.0),(int)rxmeas.tv_nsec); - else LOG_D(PHY,"IF5 %d.%d => RX %d.%d first_rx %d: time %f, rxstart %d\n",*frame,*tti,proc->frame_rx,proc->tti_rx,proc->first_rx,ru->rx_fhaul.p_time/(cpu_freq_GHz*1000.0),(int)rxmeas.tv_nsec); + if (fhtime > 800) + LOG_W(PHY, + "IF5 %d.%d => RX %d.%d first_rx %d: time %f, rxstart %ld\n", + *frame, + *tti, + proc->frame_rx, + proc->tti_rx, + proc->first_rx, + ru->rx_fhaul.p_time / (cpu_freq_GHz * 1000.0), + rxmeas.tv_nsec); + else + LOG_D(PHY, + "IF5 %d.%d => RX %d.%d first_rx %d: time %f, rxstart %ld\n", + *frame, + *tti, + proc->frame_rx, + proc->tti_rx, + proc->first_rx, + ru->rx_fhaul.p_time / (cpu_freq_GHz * 1000.0), + rxmeas.tv_nsec); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff ); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 0 ); @@ -329,21 +361,16 @@ void fh_if4p5_south_in(RU_t *ru, uint32_t symbol_number=0; uint32_t symbol_mask_full=0; - /* - if ((fp->frame_type == TDD) && (subframe_select(fp,*slot)==SF_S)) - symbol_mask_full = (1<ul_symbols_in_S_subframe)-1; - else - symbol_mask_full = (1<symbols_per_slot)-1; - - AssertFatal(proc->symbol_mask[*slot]==0,"rx_fh_if4p5: proc->symbol_mask[%d] = %x\n",*slot,proc->symbol_mask[*slot]);*/ do { // Blocking, we need a timeout on this !!!!!!!!!!!!!!!!!!!!!!! recv_IF4p5(ru, &f, &sl, &packet_type, &symbol_number); if (packet_type == IF4p5_PULFFT) proc->symbol_mask[sl] = proc->symbol_mask[sl] | (1<first_rx==0) && (f!=*frame)) LOG_E(PHY,"rx_fh_if4p5: PULTICK received frame %d != expected %d\n",f,*frame); + if ((proc->first_rx == 0) && (f != *frame)) + LOG_E(PHY, "rx_fh_if4p5: PULTICK received frame %d != expected %d\n", f, *frame); - if ((proc->first_rx==0) && (sl!=*slot)) LOG_E(PHY,"rx_fh_if4p5: PULTICK received subframe %d != expected %d (first_rx %d)\n",sl,*slot,proc->first_rx); + if ((proc->first_rx == 0) && (sl != *slot)) + LOG_E(PHY, "rx_fh_if4p5: PULTICK received subframe %d != expected %d (first_rx %d)\n", sl, *slot, proc->first_rx); break; } else if (packet_type == IF4p5_PRACH) { @@ -359,7 +386,7 @@ void fh_if4p5_south_in(RU_t *ru, proc->timestamp_rx = (proc->frame_rx * fp->samples_per_subframe * 10) + fp->get_samples_slot_timestamp(proc->tti_rx, fp, 0); // proc->timestamp_tx = proc->timestamp_rx + (4*fp->samples_per_subframe); proc->tti_tx = (sl+ru->sl_ahead)%fp->slots_per_frame; - proc->frame_tx = (sl>(fp->slots_per_frame-1-(ru->sl_ahead))) ? (f+1)&1023 : f; + proc->frame_tx = (sl > (fp->slots_per_frame - 1 - (ru->sl_ahead))) ? (f + 1) & 1023 : f; if (proc->first_rx == 0) { if (proc->tti_rx != *slot) { @@ -394,20 +421,12 @@ void fh_if4p5_south_asynch_in(RU_t *ru,int *frame,int *slot) { NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; RU_proc_t *proc = &ru->proc; uint16_t packet_type; - uint32_t symbol_number,symbol_mask,prach_rx; - // uint32_t got_prach_info=0; - symbol_number = 0; - symbol_mask = (1<<(fp->symbols_per_slot))-1; - prach_rx = 0; + uint32_t symbol_number = 0; + uint32_t symbol_mask = (1 << fp->symbols_per_slot) - 1; + uint32_t prach_rx = 0; do { // Blocking, we need a timeout on this !!!!!!!!!!!!!!!!!!!!!!! recv_IF4p5(ru, &proc->frame_rx, &proc->tti_rx, &packet_type, &symbol_number); - - // grab first prach information for this new subframe - /*if (got_prach_info==0) { - prach_rx = is_prach_subframe(fp, proc->frame_rx, proc->tti_rx); - got_prach_info = 1; - }*/ if (proc->first_rx != 0) { *frame = proc->frame_rx; *slot = proc->tti_rx; @@ -417,22 +436,19 @@ void fh_if4p5_south_asynch_in(RU_t *ru,int *frame,int *slot) { LOG_E(PHY,"frame_rx %d is not what we expect %d\n",proc->frame_rx,*frame); exit_fun("Exiting"); } - if (proc->tti_rx != *slot) { LOG_E(PHY,"tti_rx %d is not what we expect %d\n",proc->tti_rx,*slot); exit_fun("Exiting"); } } - if (packet_type == IF4p5_PULFFT) symbol_mask &= (~(1< 0) || (prach_rx >0)); // haven't received all PUSCH symbols and PRACH information + if (packet_type == IF4p5_PULFFT) + symbol_mask &= ~(1 << symbol_number); + else if (packet_type == IF4p5_PRACH) + prach_rx &= ~0x1; + } while (symbol_mask > 0 || prach_rx > 0); // haven't received all PUSCH symbols and PRACH information } - - - - /*************************************************************/ /* Input Fronthaul from North RRU */ @@ -459,26 +475,9 @@ void fh_if4p5_north_in(RU_t *ru,int *frame,int *slot) { } } -void fh_if5_north_asynch_in(RU_t *ru,int *frame,int *slot) { - NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; - RU_proc_t *proc = &ru->proc; - int tti_tx,frame_tx; - openair0_timestamp timestamp_tx = 0; +void fh_if5_north_asynch_in(RU_t *ru, int *frame, int *slot) +{ AssertFatal(1 == 0, "Shouldn't get here\n"); - frame_tx = (timestamp_tx / (fp->samples_per_subframe*10))&1023; - uint32_t idx_sf = timestamp_tx / fp->samples_per_subframe; - tti_tx = (idx_sf * fp->slots_per_subframe + (int)round((float)(timestamp_tx % fp->samples_per_subframe) / fp->samples_per_slot0))%(fp->slots_per_frame); - - if (proc->first_tx != 0) { - *slot = tti_tx; - *frame = frame_tx; - proc->first_tx = 0; - } else { - AssertFatal(tti_tx == *slot, - "tti_tx %d is not what we expect %d\n",tti_tx,*slot); - AssertFatal(frame_tx == *frame, - "frame_tx %d is not what we expect %d\n",frame_tx,*frame); - } } void fh_if4p5_north_asynch_in(RU_t *ru,int *frame,int *slot) { @@ -486,17 +485,18 @@ void fh_if4p5_north_asynch_in(RU_t *ru,int *frame,int *slot) { nfapi_nr_config_request_scf_t *cfg = &ru->config; RU_proc_t *proc = &ru->proc; uint16_t packet_type; - uint32_t symbol_number,symbol_mask,symbol_mask_full=0; + uint32_t symbol_mask_full = 0; int slot_tx,frame_tx; LOG_D(PHY, "%s(ru:%p frame, subframe)\n", __FUNCTION__, ru); - symbol_number = 0; - symbol_mask = 0; + uint32_t symbol_number = 0; + uint32_t symbol_mask = 0; // symbol_mask_full = ((subframe_select(fp,*slot) == SF_S) ? (1<dl_symbols_in_S_subframe) : (1<symbols_per_slot))-1; do { recv_IF4p5(ru, &frame_tx, &slot_tx, &packet_type, &symbol_number); - if (((nr_slot_select(cfg,frame_tx,slot_tx) & NR_DOWNLINK_SLOT) > 0) && (symbol_number == 0)) start_meas(&ru->rx_fhaul); + if (((nr_slot_select(cfg, frame_tx, slot_tx) & NR_DOWNLINK_SLOT) > 0) && (symbol_number == 0)) + start_meas(&ru->rx_fhaul); LOG_D(PHY,"slot %d (%d): frame %d, slot %d, symbol %d\n", *slot,nr_slot_select(cfg,frame_tx,*slot),frame_tx,slot_tx,symbol_number); @@ -505,7 +505,6 @@ void fh_if4p5_north_asynch_in(RU_t *ru,int *frame,int *slot) { *frame = frame_tx; *slot = slot_tx; proc->first_tx = 0; - //symbol_mask_full = ((subframe_select(fp,*slot) == SF_S) ? (1<dl_symbols_in_S_subframe) : (1<symbols_per_slot))-1; } else { AssertFatal(frame_tx == *frame, "frame_tx %d is not what we expect %d\n",frame_tx,*frame); @@ -515,18 +514,22 @@ void fh_if4p5_north_asynch_in(RU_t *ru,int *frame,int *slot) { if (packet_type == IF4p5_PDLFFT) { symbol_mask = symbol_mask | (1<0) stop_meas(&ru->rx_fhaul); + if ((nr_slot_select(cfg, frame_tx, slot_tx) & NR_DOWNLINK_SLOT) > 0) + stop_meas(&ru->rx_fhaul); proc->tti_tx = slot_tx; proc->frame_tx = frame_tx; - if ((frame_tx == 0)&&(slot_tx == 0)) proc->frame_tx_unwrap += 1024; + if (frame_tx == 0 && slot_tx == 0) + proc->frame_tx_unwrap += 1024; - proc->timestamp_tx = (((uint64_t)frame_tx + (uint64_t)proc->frame_tx_unwrap) * fp->samples_per_subframe * 10) + fp->get_samples_slot_timestamp(slot_tx, fp, 0); - LOG_D(PHY,"RU %d/%d TST %llu, frame %d, subframe %d\n",ru->idx,0,(long long unsigned int)proc->timestamp_tx,frame_tx,slot_tx); + proc->timestamp_tx = + ((uint64_t)frame_tx + proc->frame_tx_unwrap) * fp->samples_per_subframe * 10 + fp->get_samples_slot_timestamp(slot_tx, fp, 0); + LOG_D(PHY, "RU %d/%d TST %lu, frame %d, subframe %d\n", ru->idx, 0, proc->timestamp_tx, frame_tx, slot_tx); // dump VCD output for first RU in list if (ru == RC.ru[0]) { @@ -544,24 +547,15 @@ void fh_if4p5_north_asynch_in(RU_t *ru,int *frame,int *slot) { void fh_if5_north_out(RU_t *ru) { /// **** send_IF5 of rxdata to BBU **** /// VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 1 ); - AssertFatal(1==0,"Shouldn't get here\n"); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 0 ); + AssertFatal(1 == 0, "Shouldn't get here\n"); } // RRU IF4p5 northbound interface (RX) void fh_if4p5_north_out(RU_t *ru) { RU_proc_t *proc=&ru->proc; + if (ru->idx == 0) + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_RX0_RU, proc->tti_rx); - //NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; - //const int subframe = proc->tti_rx; - if (ru->idx==0) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_RX0_RU, proc->tti_rx ); - - /* - if ((fp->frame_type == TDD) && (subframe_select(fp,subframe)!=SF_UL)) { - /// **** in TDD during DL send_IF4 of ULTICK to RCC **** /// - send_IF4p5(ru, proc->frame_rx, proc->tti_rx, IF4p5_PULTICK); - return; - }*/ start_meas(&ru->tx_fhaul); send_IF4p5(ru, proc->frame_rx, proc->tti_rx, IF4p5_PULFFT); stop_meas(&ru->tx_fhaul); @@ -572,7 +566,7 @@ void *emulatedRF_thread(void *param) { int microsec = 500; // length of time to sleep, in miliseconds struct timespec req = {0}; req.tv_sec = 0; - req.tv_nsec = (numerology>0)? ((microsec * 1000L)/numerology):(microsec * 1000L)*2; + req.tv_nsec = numerology > 0 ? (microsec * 1000L) / numerology : microsec * 1000L * 2; wait_sync("emulatedRF_thread"); while(!oai_exit) { @@ -618,8 +612,6 @@ static void rx_rf(RU_t *ru, int *frame, int *slot) VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 ); proc->timestamp_rx = ts-ru->ts_offset; - //AssertFatal(rxs == fp->samples_per_subframe, - //"rx_rf: Asked for %d samples, got %d from USRP\n",fp->samples_per_subframe,rxs); if (rxs != samples_per_slot) LOG_E(PHY, "rx_rf: Asked for %d samples, got %d from USRP\n", samples_per_slot, rxs); @@ -636,23 +628,26 @@ static void rx_rf(RU_t *ru, int *frame, int *slot) } } - //compute system frame number (SFN) according to O-RAN-WG4-CUS.0-v02.00 (using alpha=beta=0) - // this assumes that the USRP has been synchronized to the GPS time - // OAI uses timestamps in sample time stored in int64_t, but it will fit in double precision for many years to come. - double gps_sec = ((double) ts)/cfg->sample_rate; - //proc->frame_rx = ((int64_t) (gps_sec/0.01)) & 1023; + // compute system frame number (SFN) according to O-RAN-WG4-CUS.0-v02.00 (using alpha=beta=0) + // this assumes that the USRP has been synchronized to the GPS time + // OAI uses timestamps in sample time stored in int64_t, but it will fit in double precision for many years to come. + double gps_sec = ((double)ts) / cfg->sample_rate; // in fact the following line is the same as long as the timestamp_rx is synchronized to GPS. proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_subframe*10))&1023; proc->tti_rx = fp->get_slot_from_timestamp(proc->timestamp_rx,fp); // synchronize first reception to frame 0 subframe 0 - LOG_D(PHY,"RU %d/%d TS %ld, GPS %f, SR %f, frame %d, slot %d.%d / %d\n", + LOG_D(PHY, + "RU %d/%d TS %ld, GPS %f, SR %f, frame %d, slot %d.%d / %d\n", ru->idx, 0, - ts, //(unsigned long long int)(proc->timestamp_rx+ru->ts_offset), - gps_sec, - cfg->sample_rate, - proc->frame_rx,proc->tti_rx,proc->tti_tx,fp->slots_per_frame); + ts, + gps_sec, + cfg->sample_rate, + proc->frame_rx, + proc->tti_rx, + proc->tti_tx, + fp->slots_per_frame); // dump VCD output for first RU in list if (ru == RC.ru[0]) { @@ -662,15 +657,19 @@ static void rx_rf(RU_t *ru, int *frame, int *slot) if (proc->first_rx == 0) { if (proc->tti_rx != *slot) { - LOG_E(PHY,"Received Timestamp (%llu) doesn't correspond to the time we think it is (proc->tti_rx %d, slot %d)\n",(long long unsigned int)proc->timestamp_rx,proc->tti_rx,*slot); + LOG_E(PHY, + "Received Timestamp (%lu) doesn't correspond to the time we think it is (proc->tti_rx %d, slot %d)\n", + proc->timestamp_rx, + proc->tti_rx, + *slot); exit_fun("Exiting"); } if (proc->frame_rx != *frame) { LOG_E(PHY, - "Received Timestamp (%llu) doesn't correspond to the time we think it is (proc->frame_rx %d frame %d, proc->tti_rx %d, " + "Received Timestamp (%lu) doesn't correspond to the time we think it is (proc->frame_rx %d frame %d, proc->tti_rx %d, " "slot %d)\n", - (long long unsigned int)proc->timestamp_rx, + proc->timestamp_rx, proc->frame_rx, *frame, proc->tti_rx, @@ -720,6 +719,7 @@ static radio_tx_gpio_flag_t get_gpio_flags(RU_t *ru, int slot) } } break; + case RU_GPIO_CONTROL_INTERDIGITAL: { // the beam index is written in bits 8-10 of the flags // bit 11 enables the gpio programming @@ -805,9 +805,7 @@ void tx_rf(RU_t *ru, int frame,int slot, uint64_t timestamp) flags_gpio = get_gpio_flags(ru, slot); const int flags = flags_burst | (flags_gpio << 4); - - if (proc->first_tx == 1) - proc->first_tx = 0; + proc->first_tx = 0; VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_TRX_WRITE_FLAGS, flags); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, frame); @@ -828,10 +826,10 @@ void tx_rf(RU_t *ru, int frame,int slot, uint64_t timestamp) nt, flags); LOG_D(PHY, - "[TXPATH] RU %d tx_rf, writing to TS %llu, %d.%d, unwrapped_frame %d, slot %d, flags %d, siglen+sf_extension %d, " + "[TXPATH] RU %d tx_rf, writing to TS %lu, %d.%d, unwrapped_frame %d, slot %d, flags %d, siglen+sf_extension %d, " "returned %d, E %f\n", ru->idx, - (long long unsigned int)(timestamp + ru->ts_offset - sf_extension), + timestamp + ru->ts_offset - sf_extension, frame, slot, proc->frame_tx_unwrap, @@ -841,7 +839,6 @@ void tx_rf(RU_t *ru, int frame,int slot, uint64_t timestamp) txs, 10 * log10((double)signal_energy(txp[0], siglen + sf_extension))); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0); - // AssertFatal(txs == 0,"trx write function error %d\n", txs); } static void fill_rf_config(RU_t *ru, char *rf_config_file) @@ -880,12 +877,12 @@ static void fill_rf_config(RU_t *ru, char *rf_config_file) for (int i = 0; i < ru->nb_tx * ru->num_beams_period; i++) { if (ru->if_frequency == 0) { - cfg->tx_freq[i] = (double)fp->dl_CarrierFreq; + cfg->tx_freq[i] = fp->dl_CarrierFreq; } else if (ru->if_freq_offset) { - cfg->tx_freq[i] = (double)(ru->if_frequency); + cfg->tx_freq[i] = ru->if_frequency; LOG_I(PHY, "Setting IF TX frequency to %lu Hz with IF TX frequency offset %d Hz\n", ru->if_frequency, ru->if_freq_offset); } else { - cfg->tx_freq[i] = (double)ru->if_frequency; + cfg->tx_freq[i] = ru->if_frequency; } cfg->tx_gain[i] = ru->att_tx; @@ -895,12 +892,12 @@ static void fill_rf_config(RU_t *ru, char *rf_config_file) for (int i = 0; i < ru->nb_rx * ru->num_beams_period; i++) { if (ru->if_frequency == 0) { - cfg->rx_freq[i] = (double)fp->ul_CarrierFreq; + cfg->rx_freq[i] = fp->ul_CarrierFreq; } else if (ru->if_freq_offset) { - cfg->rx_freq[i] = (double)(ru->if_frequency + ru->if_freq_offset); + cfg->rx_freq[i] = ru->if_frequency + ru->if_freq_offset; LOG_I(PHY, "Setting IF RX frequency to %lu Hz with IF RX frequency offset %d Hz\n", ru->if_frequency, ru->if_freq_offset); } else { - cfg->rx_freq[i] = (double)(ru->if_frequency+fp->ul_CarrierFreq-fp->dl_CarrierFreq); + cfg->rx_freq[i] = ru->if_frequency + fp->ul_CarrierFreq - fp->dl_CarrierFreq; } cfg->rx_gain[i] = ru->max_rxgain-ru->att_rx; @@ -941,17 +938,11 @@ static void fill_split7_2_config(split7_config_t *split7, const nfapi_nr_config_ antennas are mapped to successive RF chains on the same card. */ int setup_RU_buffers(RU_t *ru) { - int card,ant; - //uint16_t N_TA_offset = 0; - NR_DL_FRAME_PARMS *fp; + if (!ru) + return (-1); + + NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; nfapi_nr_config_request_scf_t *config = &ru->config; - - if (ru) { - fp = ru->nr_frame_parms; - } else { - return(-1); - } - int mu = config->ssb_config.scs_common.value; int N_RB = config->carrier_config.dl_grid_size[config->ssb_config.scs_common.value].value; @@ -963,8 +954,8 @@ int setup_RU_buffers(RU_t *ru) if (ru->openair0_cfg.mmapped_dma == 1) { // replace RX signal buffers with mmaped HW versions for (int i = 0; i < ru->nb_rx * ru->num_beams_period; i++) { - card = i / 4; - ant = i % 4; + int card = i / 4; + int ant = i % 4; LOG_D(PHY, "Mapping RU id %u, rx_ant %d, on card %d, chain %d\n", ru->idx, i, ru->rf_map.card + card, ru->rf_map.chain + ant); free(ru->common.rxdata[i]); ru->common.rxdata[i] = ru->openair0_cfg.rxbase[ru->rf_map.chain + ant]; @@ -975,8 +966,8 @@ int setup_RU_buffers(RU_t *ru) } for (int i = 0; i < ru->nb_tx * ru->num_beams_period; i++) { - card = i / 4; - ant = i % 4; + int card = i / 4; + int ant = i % 4; LOG_D(PHY, "Mapping RU id %u, tx_ant %d, on card %d, chain %d\n", ru->idx, i, ru->rf_map.card + card, ru->rf_map.chain + ant); free(ru->common.txdata[i]); ru->common.txdata[i] = ru->openair0_cfg.txbase[ru->rf_map.chain + ant]; @@ -985,8 +976,9 @@ int setup_RU_buffers(RU_t *ru) ru->common.txdata[i][j] = 16 - j; } } - } else { // not memory-mapped DMA - //nothing to do, everything already allocated in lte_init + } else { + // not memory-mapped DMA + // nothing to do, everything already allocated in lte_init } return(0); @@ -1007,14 +999,13 @@ void ru_tx_func(void *param) ru->feptx_prec(ru,frame_tx,slot_tx); // do OFDM with/without TX front-end processing if needed - if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) + if (ru->fh_north_asynch_in == NULL && ru->feptx_ofdm) ru->feptx_ofdm(ru, frame_tx, slot_tx); if(!emulate_rf) { // do outgoing fronthaul (south) if needed - if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) + if (ru->fh_north_asynch_in == NULL && ru->fh_south_out) ru->fh_south_out(ru, frame_tx, slot_tx, info->timestamp_tx); - if (ru->fh_north_out) ru->fh_north_out(ru); } else { @@ -1111,7 +1102,7 @@ void *ru_thread(void *param) // set default return value sprintf(threadname,"ru_thread %u",ru->idx); LOG_I(PHY,"Starting RU %d (%s,%s) on cpu %d\n",ru->idx,NB_functions[ru->function],NB_timing[ru->if_timing],sched_getcpu()); - memcpy((void *)&ru->config,(void *)&RC.gNB[0]->gNB_config,sizeof(ru->config)); + ru->config = RC.gNB[0]->gNB_config; nr_init_frame_parms(&ru->config, fp); nr_dump_frame_parms(fp); @@ -1136,7 +1127,6 @@ void *ru_thread(void *param) if (t != NULL) ru->fh_south_out = t; } else { - malloc_IF4p5_buffer(ru); } @@ -1156,9 +1146,10 @@ void *ru_thread(void *param) AssertFatal(ru->nr_start_if(ru,NULL) == 0, "Could not start the IF device\n"); if (ru->has_ctrl_prt > 0) { - if (ru->if_south == LOCAL_RF) ret = connect_rau(ru); - else ret = attach_rru(ru); - + if (ru->if_south == LOCAL_RF) + ret = connect_rau(ru); + else + ret = attach_rru(ru); AssertFatal(ret==0,"Cannot connect to remote radio\n"); } @@ -1204,8 +1195,8 @@ void *ru_thread(void *param) // This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices struct timespec slot_start; - clock_gettime(CLOCK_MONOTONIC, &slot_start); - + clock_gettime(CLOCK_MONOTONIC, &slot_start); + while (!oai_exit) { if (slot==(fp->slots_per_frame-1)) { slot=0; @@ -1222,8 +1213,8 @@ void *ru_thread(void *param) // synchronization on input FH interface, acquire signals/data and block LOG_D(PHY,"[RU_thread] read data: frame_rx = %d, tti_rx = %d\n", frame, slot); - if (ru->fh_south_in) ru->fh_south_in(ru,&frame,&slot); - else AssertFatal(1==0, "No fronthaul interface at south port"); + AssertFatal(ru->fh_south_in, "No fronthaul interface at south port"); + ru->fh_south_in(ru, &frame, &slot); if (initial_wait == 1 && proc->frame_rx < 300) { if (proc->frame_rx > 0 && ((proc->frame_rx % 100) == 0) && proc->tti_rx == 0) { @@ -1308,14 +1299,14 @@ void *ru_thread(void *param) } // end if (slot_type == NR_UPLINK_SLOT || slot_type == NR_MIXED_SLOT) { notifiedFIFO_elt_t *resTx = newNotifiedFIFO_elt(sizeof(processingData_L1tx_t), 0, &gNB->L1_tx_out, NULL); - processingData_L1tx_t *syncMsgTx = NotifiedFifoData(resTx); - syncMsgTx->gNB = gNB; - syncMsgTx->frame = proc->frame_tx; - syncMsgTx->slot = proc->tti_tx; - syncMsgTx->frame_rx = proc->frame_rx; - syncMsgTx->slot_rx = proc->tti_rx; - syncMsgTx->timestamp_tx = proc->timestamp_tx; resTx->key = proc->tti_tx; + processingData_L1tx_t *syncMsgTx = NotifiedFifoData(resTx); + *syncMsgTx = (processingData_L1tx_t){.gNB = gNB, + .frame = proc->frame_tx, + .slot = proc->tti_tx, + .frame_rx = proc->frame_rx, + .slot_rx = proc->tti_rx, + .timestamp_tx = proc->timestamp_tx}; pushNotifiedFIFO(&gNB->L1_tx_out, resTx); } @@ -1325,15 +1316,16 @@ void *ru_thread(void *param) int start_streaming(RU_t *ru) { LOG_I(PHY,"Starting streaming on third-party RRU\n"); - return(ru->ifdevice.thirdparty_startstreaming(&ru->ifdevice)); + return ru->ifdevice.thirdparty_startstreaming(&ru->ifdevice); } int nr_start_if(struct RU_t_s *ru, struct PHY_VARS_gNB_s *gNB) { if (ru->if_south <= REMOTE_IF5) - for (int i=0;inb_rx;i++) ru->openair0_cfg.rxbase[i] = ru->common.rxdata[i]; + for (int i = 0; i < ru->nb_rx; i++) + ru->openair0_cfg.rxbase[i] = ru->common.rxdata[i]; ru->openair0_cfg.rxsize = ru->nr_frame_parms->samples_per_subframe*10; reset_meas(&ru->ifdevice.tx_fhaul); - return(ru->ifdevice.trx_start_func(&ru->ifdevice)); + return ru->ifdevice.trx_start_func(&ru->ifdevice); } int start_rf(RU_t *ru) { @@ -1349,29 +1341,16 @@ int stop_rf(RU_t *ru) { } int start_write_thread(RU_t *ru) { - return(ru->rfdevice.trx_write_init(&ru->rfdevice)); + return ru->rfdevice.trx_write_init(&ru->rfdevice); } void init_RU_proc(RU_t *ru) { - int i=0; - RU_proc_t *proc; - proc = &ru->proc; - memset((void *)proc,0,sizeof(RU_proc_t)); - proc->ru = ru; - proc->instance_cnt_emulateRF = -1; - proc->first_rx = 1; - proc->first_tx = 1; - proc->frame_offset = 0; - proc->num_slaves = 0; - proc->frame_tx_unwrap = 0; - - for (i=0; i<10; i++) proc->symbol_mask[i]=0; - - pthread_mutex_init( &proc->mutex_emulateRF,NULL); - pthread_cond_init( &proc->cond_emulateRF, NULL); + ru->proc = (RU_proc_t){.ru = ru, .instance_cnt_emulateRF = -1, .first_rx = 1, .first_tx = 1}; + pthread_mutex_init(&ru->proc.mutex_emulateRF, NULL); + pthread_cond_init(&ru->proc.cond_emulateRF, NULL); if(emulate_rf) - threadCreate( &proc->pthread_emulateRF, emulatedRF_thread, (void *)proc, "emulateRF", -1, OAI_PRIORITY_RT ); + threadCreate(&ru->proc.pthread_emulateRF, emulatedRF_thread, (void *)&ru->proc, "emulateRF", -1, OAI_PRIORITY_RT); LOG_I(PHY, "Initialized RU proc %d (%s,%s),\n", ru->idx, NB_functions[ru->function], NB_timing[ru->if_timing]); } @@ -1395,10 +1374,10 @@ void kill_NR_RU_proc(int inst) { * mutex_fep/cond_fep. Thus, we unlocked above for pthread_FH above and do * the same for FEP thread below again (using broadcast() to ensure both * threads get the signal). This one will also destroy the mutex and cond. */ - pthread_mutex_lock(&proc->mutex_fep[0]); + pthread_mutex_lock(proc->mutex_fep); proc->instance_cnt_fep[0] = 0; - pthread_cond_broadcast(&proc->cond_fep[0]); - pthread_mutex_unlock( &proc->mutex_fep[0] ); + pthread_cond_broadcast(proc->cond_fep); + pthread_mutex_unlock(proc->mutex_fep); pthread_join(proc->pthread_FH, NULL); // everything should be stopped now, we can safely stop the RF device @@ -1417,19 +1396,15 @@ void kill_NR_RU_proc(int inst) { int check_capabilities(RU_t *ru,RRU_capabilities_t *cap) { FH_fmt_options_t fmt = cap->FH_fmt; int i; - int found_band=0; LOG_I(PHY,"RRU %d, num_bands %d, looking for band %d\n",ru->idx,cap->num_bands,ru->nr_frame_parms->nr_band); for (i=0; inum_bands; i++) { LOG_I(PHY,"band %d on RRU %d\n",cap->band_list[i],ru->idx); - - if (ru->nr_frame_parms->nr_band == cap->band_list[i]) { - found_band=1; + if (ru->nr_frame_parms->nr_band == cap->band_list[i]) break; - } } - if (found_band == 0) { + if (i == cap->num_bands) { LOG_I(PHY,"Couldn't find target NR band %d on RRU %d\n",ru->nr_frame_parms->nr_band,ru->idx); return(-1); } @@ -1441,18 +1416,18 @@ int check_capabilities(RU_t *ru,RRU_capabilities_t *cap) { break; case REMOTE_IF5: - if (fmt == OAI_IF5_only || fmt == OAI_IF5_and_IF4p5) return(0); - + if (fmt == OAI_IF5_only || fmt == OAI_IF5_and_IF4p5) + return (0); break; case REMOTE_IF4p5: - if (fmt == OAI_IF4p5_only || fmt == OAI_IF5_and_IF4p5) return(0); - + if (fmt == OAI_IF4p5_only || fmt == OAI_IF5_and_IF4p5) + return (0); break; case REMOTE_MBP_IF5: - if (fmt == MBP_IF5) return(0); - + if (fmt == MBP_IF5) + return (0); break; default: @@ -1464,46 +1439,40 @@ int check_capabilities(RU_t *ru,RRU_capabilities_t *cap) { } const char rru_format_options[4][20] = {"OAI_IF5_only", "OAI_IF4p5_only", "OAI_IF5_and_IF4p5", "MBP_IF5"}; - const char rru_formats[3][20] = {"OAI_IF5", "MBP_IF5", "OAI_IF4p5"}; const char ru_if_formats[4][20] = {"LOCAL_RF", "REMOTE_OAI_IF5", "REMOTE_MBP_IF5", "REMOTE_OAI_IF4p5"}; void configure_ru(void *ruu, void *arg) { RU_t *ru = (RU_t *)ruu; - RRU_config_t *config = (RRU_config_t *)arg; - RRU_capabilities_t *capabilities = (RRU_capabilities_t *)arg; nfapi_nr_config_request_scf_t *cfg = &ru->config; int ret; LOG_I(PHY, "Received capabilities from RRU %d\n", ru->idx); - if (capabilities->FH_fmt < MAX_FH_FMTs) LOG_I(PHY, "RU FH options %s\n",rru_format_options[capabilities->FH_fmt]); + RRU_capabilities_t *capabilities = (RRU_capabilities_t *)arg; + if (capabilities->FH_fmt < MAX_FH_FMTs) + LOG_I(PHY, "RU FH options %s\n", rru_format_options[capabilities->FH_fmt]); ret = check_capabilities(ru,capabilities); AssertFatal(ret == 0, "Cannot configure RRU %d, check_capabilities returned %d\n", ru->idx, ret); // take antenna capabilities of RRU - ru->nb_tx = capabilities->nb_tx[0]; - ru->nb_rx = capabilities->nb_rx[0]; + ru->nb_tx = capabilities->nb_tx[0]; + ru->nb_rx = capabilities->nb_rx[0]; // Pass configuration to RRU LOG_I(PHY, "Using %s fronthaul (%d), band %d \n",ru_if_formats[ru->if_south],ru->if_south,ru->nr_frame_parms->nr_band); + // wait for configuration - config->FH_fmt = ru->if_south; - config->num_bands = 1; - config->band_list[0] = ru->nr_frame_parms->nr_band; - config->tx_freq[0] = ru->nr_frame_parms->dl_CarrierFreq; - config->rx_freq[0] = ru->nr_frame_parms->ul_CarrierFreq; - //config->tdd_config[0] = ru->nr_frame_parms->tdd_config; - //config->tdd_config_S[0] = ru->nr_frame_parms->tdd_config_S; - config->att_tx[0] = ru->att_tx; - config->att_rx[0] = ru->att_rx; - config->N_RB_DL[0] = cfg->carrier_config.dl_grid_size[cfg->ssb_config.scs_common.value].value; - config->N_RB_UL[0] = cfg->carrier_config.dl_grid_size[cfg->ssb_config.scs_common.value].value; - config->threequarter_fs[0] = ru->nr_frame_parms->threequarter_fs; - /* if (ru->if_south==REMOTE_IF4p5) { - config->prach_FreqOffset[0] = ru->nr_frame_parms->prach_config_common.prach_ConfigInfo.prach_FreqOffset; - config->prach_ConfigIndex[0] = ru->nr_frame_parms->prach_config_common.prach_ConfigInfo.prach_ConfigIndex; - LOG_I(PHY,"REMOTE_IF4p5: prach_FrequOffset %d, prach_ConfigIndex %d\n", - config->prach_FreqOffset[0],config->prach_ConfigIndex[0]);*/ + RRU_config_t *config = (RRU_config_t *)arg; + *config = (RRU_config_t){.FH_fmt = ru->if_south, + .num_bands = 1, + .band_list[0] = ru->nr_frame_parms->nr_band, + .tx_freq[0] = ru->nr_frame_parms->dl_CarrierFreq, + .rx_freq[0] = ru->nr_frame_parms->ul_CarrierFreq, + .att_tx[0] = ru->att_tx, + .att_rx[0] = ru->att_rx, + .N_RB_DL[0] = cfg->carrier_config.dl_grid_size[cfg->ssb_config.scs_common.value].value, + .N_RB_UL[0] = cfg->carrier_config.dl_grid_size[cfg->ssb_config.scs_common.value].value, + .threequarter_fs[0] = ru->nr_frame_parms->threequarter_fs}; nr_init_frame_parms(&ru->config, ru->nr_frame_parms); nr_phy_init_RU(ru); } @@ -1513,37 +1482,31 @@ void configure_rru(void *ruu, void *arg) RRU_config_t *config = (RRU_config_t *)arg; RU_t *ru = (RU_t *)ruu; nfapi_nr_config_request_scf_t *cfg = &ru->config; - ru->nr_frame_parms->nr_band = config->band_list[0]; - ru->nr_frame_parms->dl_CarrierFreq = config->tx_freq[0]; - ru->nr_frame_parms->ul_CarrierFreq = config->rx_freq[0]; + NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; - if (ru->nr_frame_parms->dl_CarrierFreq == ru->nr_frame_parms->ul_CarrierFreq) { - cfg->cell_config.frame_duplex_type.value = TDD; - //ru->nr_frame_parms->tdd_config = config->tdd_config[0]; - //ru->nr_frame_parms->tdd_config_S = config->tdd_config_S[0]; + fp->nr_band = config->band_list[0]; + fp->dl_CarrierFreq = config->tx_freq[0]; + fp->ul_CarrierFreq = config->rx_freq[0]; + + if (fp->dl_CarrierFreq == fp->ul_CarrierFreq) { + cfg->cell_config.frame_duplex_type.value = TDD; } else - cfg->cell_config.frame_duplex_type.value = FDD; + cfg->cell_config.frame_duplex_type.value = FDD; - ru->att_tx = config->att_tx[0]; - ru->att_rx = config->att_rx[0]; + ru->att_tx = config->att_tx[0]; + ru->att_rx = config->att_rx[0]; int mu = cfg->ssb_config.scs_common.value; - cfg->carrier_config.dl_grid_size[mu].value = config->N_RB_DL[0]; - cfg->carrier_config.dl_grid_size[mu].value = config->N_RB_UL[0]; - ru->nr_frame_parms->threequarter_fs = config->threequarter_fs[0]; + cfg->carrier_config.dl_grid_size[mu].value = config->N_RB_DL[0]; + cfg->carrier_config.dl_grid_size[mu].value = config->N_RB_UL[0]; + fp->threequarter_fs = config->threequarter_fs[0]; - //ru->nr_frame_parms->pdsch_config_common.referenceSignalPower = ru->max_pdschReferenceSignalPower-config->att_tx[0]; if (ru->function==NGFI_RRU_IF4p5) { - ru->nr_frame_parms->att_rx = ru->att_rx; - ru->nr_frame_parms->att_tx = ru->att_tx; - /* - LOG_I(PHY,"Setting ru->function to NGFI_RRU_IF4p5, prach_FrequOffset %d, prach_ConfigIndex %d, att (%d,%d)\n", - config->prach_FreqOffset[0],config->prach_ConfigIndex[0],ru->att_tx,ru->att_rx); - ru->nr_frame_parms->prach_config_common.prach_ConfigInfo.prach_FreqOffset = config->prach_FreqOffset[0]; - ru->nr_frame_parms->prach_config_common.prach_ConfigInfo.prach_ConfigIndex = config->prach_ConfigIndex[0]; */ + fp->att_rx = ru->att_rx; + fp->att_tx = ru->att_tx; } fill_rf_config(ru,ru->rf_config_file); - nr_init_frame_parms(&ru->config, ru->nr_frame_parms); + nr_init_frame_parms(&ru->config, fp); nr_phy_init_RU(ru); } @@ -1600,17 +1563,6 @@ void set_function_spec_param(RU_t *ru) ru->stop_rf = stop_rf; ru->start_write_thread = start_write_thread; // starting RF TX in different thread } - - /* - fill_rf_config(ru,rf_config_file); - init_frame_parms(&ru->frame_parms,1); - nr_phy_init_RU(ru); - - ret = openair0_device_load(&ru->rfdevice,&ru->openair0_cfg); - if (setup_RU_buffers(ru)!=0) { - exit(-1); - } - */ break; case REMOTE_IF5: // the remote unit is IF5 RRU @@ -1659,12 +1611,6 @@ void set_function_spec_param(RU_t *ru) void init_NR_RU(configmodule_interface_t *cfg, char *rf_config_file) { - int ru_id; - RU_t *ru; - PHY_VARS_gNB *gNB_RC; - PHY_VARS_gNB *gNB0= (PHY_VARS_gNB *)NULL; - NR_DL_FRAME_PARMS *fp = (NR_DL_FRAME_PARMS *)NULL; - int i; // create status mask RC.ru_mask = 0; pthread_mutex_init(&RC.ru_mutex,NULL); @@ -1674,9 +1620,9 @@ void init_NR_RU(configmodule_interface_t *cfg, char *rf_config_file) LOG_I(PHY,"number of L1 instances %d, number of RU %d, number of CPU cores %d\n",RC.nb_nr_L1_inst,RC.nb_RU,get_nprocs()); LOG_D(PHY,"Process RUs RC.nb_RU:%d\n",RC.nb_RU); - for (ru_id=0; ru_idrf_config_file = rf_config_file; ru->idx = ru_id; ru->ts_offset = 0; @@ -1693,23 +1639,18 @@ void init_NR_RU(configmodule_interface_t *cfg, char *rf_config_file) } } - gNB_RC = RC.gNB[0]; - gNB0 = ru->gNB_list[0]; - fp = ru->nr_frame_parms; + PHY_VARS_gNB *gNB_RC = RC.gNB[0]; + PHY_VARS_gNB *gNB0 = ru->gNB_list[0]; LOG_D(PHY, "RU FUnction:%d ru->if_south:%d\n", ru->function, ru->if_south); if (gNB0) { - if ((ru->function != NGFI_RRU_IF5) && (ru->function != NGFI_RRU_IF4p5)) - AssertFatal(gNB0, "gNB0 is null!\n"); - - if (gNB0 && gNB_RC) { + if (gNB_RC) { LOG_D(PHY, "Copying frame parms from gNB in RC to gNB %d in ru %d and frame_parms in ru\n", gNB0->Mod_id, ru->idx); - memcpy((void *)fp, &gNB_RC->frame_parms, sizeof(NR_DL_FRAME_PARMS)); - memcpy((void *)&gNB0->frame_parms, (void *)&gNB_RC->frame_parms, sizeof(NR_DL_FRAME_PARMS)); + *ru->nr_frame_parms = gNB_RC->frame_parms; + gNB0->frame_parms = gNB_RC->frame_parms; // attach all RU to all gNBs in its list/ LOG_D(PHY,"ru->num_gNB:%d gNB0->num_RU:%d\n", ru->num_gNB, gNB0->num_RU); - - for (i=0; inum_gNB; i++) { + for (int i = 0; i < ru->num_gNB; i++) { gNB0 = ru->gNB_list[i]; gNB0->RU_list[gNB0->num_RU++] = ru; } @@ -1723,22 +1664,21 @@ void init_NR_RU(configmodule_interface_t *cfg, char *rf_config_file) LOG_E(PHY, "Number of threads for gNB should be more than 1. Allocated only %d\n", threadCnt); char pool[80]; int s_offset = sprintf(pool,"%d",ru->tpcores[0]); - for (int icpu=1; icputpcores[icpu]); + for (int icpu = 1; icpu < threadCnt; icpu++) { + s_offset += sprintf(pool + s_offset, ",%d", ru->tpcores[icpu]); } LOG_I(PHY, "RU thread-pool core string %s (size %d)\n", pool, threadCnt); - ru->threadPool = (tpool_t*)malloc(sizeof(tpool_t)); + ru->threadPool = malloc(sizeof(tpool_t)); initTpool(pool, ru->threadPool, cpumeas(CPUMEAS_GETSTATE)); // FEP RX result FIFO - ru->respfeprx = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t)); + ru->respfeprx = malloc(sizeof(notifiedFIFO_t)); initNotifiedFIFO(ru->respfeprx); // FEP TX result FIFO - ru->respfeptx = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t)); + ru->respfeptx = malloc(sizeof(notifiedFIFO_t)); initNotifiedFIFO(ru->respfeptx); } } // for ru_id - // sleep(1); LOG_D(HW,"[nr-softmodem.c] RU threads created\n"); } @@ -1755,7 +1695,6 @@ void stop_RU(int nb_ru) { } } - /* --------------------------------------------------------*/ /* from here function to use configuration module */ static void NRRCconfig_RU(configmodule_interface_t *cfg) @@ -1764,199 +1703,199 @@ static void NRRCconfig_RU(configmodule_interface_t *cfg) paramlist_def_t RUParamList = {CONFIG_STRING_RU_LIST, NULL, 0}; config_getlist(cfg, &RUParamList, RUParams, sizeofArray(RUParams), NULL); - if (RUParamList.numelt > 0) { - RC.ru = (RU_t **)malloc(RC.nb_RU*sizeof(RU_t *)); - RC.ru_mask = (1 << RC.nb_RU) - 1; + if (RUParamList.numelt <= 0) + return; - for (int j = 0; j < RC.nb_RU; j++) { - RC.ru[j] = calloc(1, sizeof(*RC.ru[j])); - RC.ru[j]->idx = j; - RC.ru[j]->nr_frame_parms = calloc(1, sizeof(*RC.ru[j]->nr_frame_parms)); - RC.ru[j]->frame_parms = calloc(1, sizeof(*RC.ru[j]->frame_parms)); - RC.ru[j]->if_timing = synch_to_ext_device; + RC.ru = (RU_t **)malloc(RC.nb_RU * sizeof(RU_t *)); + RC.ru_mask = (1 << RC.nb_RU) - 1; - if (RC.nb_nr_L1_inst > 0) - RC.ru[j]->num_gNB = RUParamList.paramarray[j][RU_ENB_LIST_IDX].numelt; - else - RC.ru[j]->num_gNB = 0; + for (int j = 0; j < RC.nb_RU; j++) { + RU_t *ru = RC.ru[j] = calloc(1, sizeof(*RC.ru[j])); + ru->idx = j; + ru->nr_frame_parms = calloc(1, sizeof(*ru->nr_frame_parms)); + ru->frame_parms = calloc(1, sizeof(*ru->frame_parms)); + ru->if_timing = synch_to_ext_device; + paramdef_t *param = RUParamList.paramarray[j]; + if (RC.nb_nr_L1_inst > 0) + ru->num_gNB = param[RU_ENB_LIST_IDX].numelt; + else + ru->num_gNB = 0; - for (int i = 0; i < RC.ru[j]->num_gNB; i++) - RC.ru[j]->gNB_list[i] = RC.gNB[RUParamList.paramarray[j][RU_ENB_LIST_IDX].iptr[i]]; + for (int i = 0; i < ru->num_gNB; i++) + ru->gNB_list[i] = RC.gNB[param[RU_ENB_LIST_IDX].iptr[i]]; - if (config_isparamset(RUParamList.paramarray[j], RU_SDR_ADDRS)) { - RC.ru[j]->openair0_cfg.sdr_addrs = strdup(*(RUParamList.paramarray[j][RU_SDR_ADDRS].strptr)); - } + if (config_isparamset(param, RU_SDR_ADDRS)) { + ru->openair0_cfg.sdr_addrs = strdup(*param[RU_SDR_ADDRS].strptr); + } - if (config_isparamset(RUParamList.paramarray[j], RU_GPIO_CONTROL)) { - if (strcmp(*RUParamList.paramarray[j][RU_GPIO_CONTROL].strptr, "generic") == 0) { - RC.ru[j]->openair0_cfg.gpio_controller = RU_GPIO_CONTROL_GENERIC; - LOG_I(PHY, "RU GPIO control set as 'generic'\n"); - } else if (strcmp(*RUParamList.paramarray[j][RU_GPIO_CONTROL].strptr, "interdigital") == 0) { - RC.ru[j]->openair0_cfg.gpio_controller = RU_GPIO_CONTROL_INTERDIGITAL; - LOG_I(PHY, "RU GPIO control set as 'interdigital'\n"); - } else { - AssertFatal(false, - "bad GPIO controller in configuration file: '%s'\n", - *(RUParamList.paramarray[j][RU_GPIO_CONTROL].strptr)); - } - } else - RC.ru[j]->openair0_cfg.gpio_controller = RU_GPIO_CONTROL_NONE; - - if (config_isparamset(RUParamList.paramarray[j], RU_TX_SUBDEV)) { - RC.ru[j]->openair0_cfg.tx_subdev = strdup(*(RUParamList.paramarray[j][RU_TX_SUBDEV].strptr)); - LOG_I(PHY, "RU USRP tx subdev == %s\n", RC.ru[j]->openair0_cfg.tx_subdev); - } - - if (config_isparamset(RUParamList.paramarray[j], RU_RX_SUBDEV)) { - RC.ru[j]->openair0_cfg.rx_subdev = strdup(*(RUParamList.paramarray[j][RU_RX_SUBDEV].strptr)); - LOG_I(PHY, "RU USRP rx subdev == %s\n", RC.ru[j]->openair0_cfg.rx_subdev); - } - - if (config_isparamset(RUParamList.paramarray[j], RU_SDR_CLK_SRC)) { - if (strcmp(*(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr), "internal") == 0) { - RC.ru[j]->openair0_cfg.clock_source = internal; - LOG_I(PHY, "RU clock source set as internal\n"); - } else if (strcmp(*(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr), "external") == 0) { - RC.ru[j]->openair0_cfg.clock_source = external; - LOG_I(PHY, "RU clock source set as external\n"); - } else if (strcmp(*(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr), "gpsdo") == 0) { - RC.ru[j]->openair0_cfg.clock_source = gpsdo; - LOG_I(PHY, "RU clock source set as gpsdo\n"); - } else { - LOG_E(PHY, "Erroneous RU clock source in the provided configuration file: '%s'\n", *(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr)); - } + if (config_isparamset(param, RU_GPIO_CONTROL)) { + char *str = *param[RU_GPIO_CONTROL].strptr; + if (strcmp(str, "generic") == 0) { + ru->openair0_cfg.gpio_controller = RU_GPIO_CONTROL_GENERIC; + LOG_I(PHY, "RU GPIO control set as 'generic'\n"); + } else if (strcmp(str, "interdigital") == 0) { + ru->openair0_cfg.gpio_controller = RU_GPIO_CONTROL_INTERDIGITAL; + LOG_I(PHY, "RU GPIO control set as 'interdigital'\n"); } else { - LOG_D(PHY, "Setting clock source to internal\n"); - RC.ru[j]->openair0_cfg.clock_source = internal; + AssertFatal(false, "bad GPIO controller in configuration file: '%s'\n", str); } + } else + ru->openair0_cfg.gpio_controller = RU_GPIO_CONTROL_NONE; - if (config_isparamset(RUParamList.paramarray[j], RU_SDR_TME_SRC)) { - if (strcmp(*(RUParamList.paramarray[j][RU_SDR_TME_SRC].strptr), "internal") == 0) { - RC.ru[j]->openair0_cfg.time_source = internal; - LOG_I(PHY, "RU time source set as internal\n"); - } else if (strcmp(*(RUParamList.paramarray[j][RU_SDR_TME_SRC].strptr), "external") == 0) { - RC.ru[j]->openair0_cfg.time_source = external; - LOG_I(PHY, "RU time source set as external\n"); - } else if (strcmp(*(RUParamList.paramarray[j][RU_SDR_TME_SRC].strptr), "gpsdo") == 0) { - RC.ru[j]->openair0_cfg.time_source = gpsdo; - LOG_I(PHY, "RU time source set as gpsdo\n"); - } else { - LOG_E(PHY, "Erroneous RU time source in the provided configuration file: '%s'\n", *(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr)); - } + if (config_isparamset(param, RU_TX_SUBDEV)) { + ru->openair0_cfg.tx_subdev = strdup(*param[RU_TX_SUBDEV].strptr); + LOG_I(PHY, "RU USRP tx subdev == %s\n", ru->openair0_cfg.tx_subdev); + } + + if (config_isparamset(param, RU_RX_SUBDEV)) { + ru->openair0_cfg.rx_subdev = strdup(*param[RU_RX_SUBDEV].strptr); + LOG_I(PHY, "RU USRP rx subdev == %s\n", ru->openair0_cfg.rx_subdev); + } + + if (config_isparamset(param, RU_SDR_CLK_SRC)) { + char *str = *param[RU_SDR_CLK_SRC].strptr; + if (strcmp(str, "internal") == 0) { + ru->openair0_cfg.clock_source = internal; + LOG_I(PHY, "RU clock source set as internal\n"); + } else if (strcmp(str, "external") == 0) { + ru->openair0_cfg.clock_source = external; + LOG_I(PHY, "RU clock source set as external\n"); + } else if (strcmp(str, "gpsdo") == 0) { + ru->openair0_cfg.clock_source = gpsdo; + LOG_I(PHY, "RU clock source set as gpsdo\n"); } else { - LOG_D(PHY, "Setting time source to internal\n"); - RC.ru[j]->openair0_cfg.time_source = internal; + LOG_E(PHY, "Erroneous RU clock source in the provided configuration file: '%s'\n", str); + } + } else { + LOG_D(PHY, "Setting clock source to internal\n"); + ru->openair0_cfg.clock_source = internal; + } + + if (config_isparamset(param, RU_SDR_TME_SRC)) { + char *str = *param[RU_SDR_TME_SRC].strptr; + if (strcmp(str, "internal") == 0) { + ru->openair0_cfg.time_source = internal; + LOG_I(PHY, "RU time source set as internal\n"); + } else if (strcmp(str, "external") == 0) { + ru->openair0_cfg.time_source = external; + LOG_I(PHY, "RU time source set as external\n"); + } else if (strcmp(str, "gpsdo") == 0) { + ru->openair0_cfg.time_source = gpsdo; + LOG_I(PHY, "RU time source set as gpsdo\n"); + } else { + LOG_E(PHY, "Erroneous RU time source in the provided configuration file: '%s'\n", str); + } + } else { + LOG_D(PHY, "Setting time source to internal\n"); + ru->openair0_cfg.time_source = internal; + } + + ru->openair0_cfg.tune_offset = get_softmodem_params()->tune_offset; + + if (strcmp(*param[RU_LOCAL_RF_IDX].strptr, "yes") == 0) { + if (!config_isparamset(param, RU_LOCAL_IF_NAME_IDX)) { + ru->if_south = LOCAL_RF; + ru->function = gNodeB_3GPP; + LOG_D(PHY, "Setting function for RU %d to gNodeB_3GPP\n", j); + } else { + ru->eth_params.local_if_name = strdup(*param[RU_LOCAL_IF_NAME_IDX].strptr); + ru->eth_params.my_addr = strdup(*param[RU_LOCAL_ADDRESS_IDX].strptr); + ru->eth_params.remote_addr = strdup(*param[RU_REMOTE_ADDRESS_IDX].strptr); + ru->eth_params.my_portc = *param[RU_LOCAL_PORTC_IDX].uptr; + ru->eth_params.remote_portc = *param[RU_REMOTE_PORTC_IDX].uptr; + ru->eth_params.my_portd = *param[RU_LOCAL_PORTD_IDX].uptr; + ru->eth_params.remote_portd = *param[RU_REMOTE_PORTD_IDX].uptr; + char *str = *param[RU_TRANSPORT_PREFERENCE_IDX].strptr; + if (strcmp(str, "udp") == 0) { + ru->if_south = LOCAL_RF; + ru->function = NGFI_RRU_IF5; + ru->eth_params.transp_preference = ETH_UDP_MODE; + LOG_D(PHY, "Setting function for RU %d to NGFI_RRU_IF5 (udp)\n", j); + } else if (strcmp(str, "raw") == 0) { + ru->if_south = LOCAL_RF; + ru->function = NGFI_RRU_IF5; + ru->eth_params.transp_preference = ETH_RAW_MODE; + LOG_D(PHY, "Setting function for RU %d to NGFI_RRU_IF5 (raw)\n", j); + } else if (strcmp(str, "udp_if4p5") == 0) { + ru->if_south = LOCAL_RF; + ru->function = NGFI_RRU_IF4p5; + ru->eth_params.transp_preference = ETH_UDP_IF4p5_MODE; + LOG_D(PHY, "Setting function for RU %d to NGFI_RRU_IF4p5 (udp)\n", j); + } else if (strcmp(str, "raw_if4p5") == 0) { + ru->if_south = LOCAL_RF; + ru->function = NGFI_RRU_IF4p5; + ru->eth_params.transp_preference = ETH_RAW_IF4p5_MODE; + LOG_D(PHY, "Setting function for RU %d to NGFI_RRU_IF4p5 (raw)\n", j); + } } - RC.ru[j]->openair0_cfg.tune_offset = get_softmodem_params()->tune_offset; + ru->max_pdschReferenceSignalPower = *param[RU_MAX_RS_EPRE_IDX].uptr; + ru->max_rxgain = *param[RU_MAX_RXGAIN_IDX].uptr; + ru->sf_extension = *param[RU_SF_EXTENSION_IDX].uptr; + } // strcmp(local_rf, "yes") == 0 + else { + char *str = *param[RU_TRANSPORT_PREFERENCE_IDX].strptr; + LOG_D(PHY, "RU %d: Transport %s\n", j, str); + ru->eth_params.local_if_name = strdup(*param[RU_LOCAL_IF_NAME_IDX].strptr); + ru->eth_params.my_addr = strdup(*param[RU_LOCAL_ADDRESS_IDX].strptr); + ru->eth_params.remote_addr = strdup(*param[RU_REMOTE_ADDRESS_IDX].strptr); + ru->eth_params.my_portc = *param[RU_LOCAL_PORTC_IDX].uptr; + ru->eth_params.remote_portc = *param[RU_REMOTE_PORTC_IDX].uptr; + ru->eth_params.my_portd = *param[RU_LOCAL_PORTD_IDX].uptr; + ru->eth_params.remote_portd = *param[RU_REMOTE_PORTD_IDX].uptr; - if (strcmp(*(RUParamList.paramarray[j][RU_LOCAL_RF_IDX].strptr), "yes") == 0) { - if (!(config_isparamset(RUParamList.paramarray[j],RU_LOCAL_IF_NAME_IDX))) { - RC.ru[j]->if_south = LOCAL_RF; - RC.ru[j]->function = gNodeB_3GPP; - LOG_D(PHY, "Setting function for RU %d to gNodeB_3GPP\n", j); - } else { - RC.ru[j]->eth_params.local_if_name = strdup(*(RUParamList.paramarray[j][RU_LOCAL_IF_NAME_IDX].strptr)); - RC.ru[j]->eth_params.my_addr = strdup(*(RUParamList.paramarray[j][RU_LOCAL_ADDRESS_IDX].strptr)); - RC.ru[j]->eth_params.remote_addr = strdup(*(RUParamList.paramarray[j][RU_REMOTE_ADDRESS_IDX].strptr)); - RC.ru[j]->eth_params.my_portc = *(RUParamList.paramarray[j][RU_LOCAL_PORTC_IDX].uptr); - RC.ru[j]->eth_params.remote_portc = *(RUParamList.paramarray[j][RU_REMOTE_PORTC_IDX].uptr); - RC.ru[j]->eth_params.my_portd = *(RUParamList.paramarray[j][RU_LOCAL_PORTD_IDX].uptr); - RC.ru[j]->eth_params.remote_portd = *(RUParamList.paramarray[j][RU_REMOTE_PORTD_IDX].uptr); - - if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "udp") == 0) { - RC.ru[j]->if_south = LOCAL_RF; - RC.ru[j]->function = NGFI_RRU_IF5; - RC.ru[j]->eth_params.transp_preference = ETH_UDP_MODE; - LOG_D(PHY, "Setting function for RU %d to NGFI_RRU_IF5 (udp)\n", j); - } else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "raw") == 0) { - RC.ru[j]->if_south = LOCAL_RF; - RC.ru[j]->function = NGFI_RRU_IF5; - RC.ru[j]->eth_params.transp_preference = ETH_RAW_MODE; - LOG_D(PHY, "Setting function for RU %d to NGFI_RRU_IF5 (raw)\n", j); - } else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "udp_if4p5") == 0) { - RC.ru[j]->if_south = LOCAL_RF; - RC.ru[j]->function = NGFI_RRU_IF4p5; - RC.ru[j]->eth_params.transp_preference = ETH_UDP_IF4p5_MODE; - LOG_D(PHY, "Setting function for RU %d to NGFI_RRU_IF4p5 (udp)\n", j); - } else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "raw_if4p5") == 0) { - RC.ru[j]->if_south = LOCAL_RF; - RC.ru[j]->function = NGFI_RRU_IF4p5; - RC.ru[j]->eth_params.transp_preference = ETH_RAW_IF4p5_MODE; - LOG_D(PHY, "Setting function for RU %d to NGFI_RRU_IF4p5 (raw)\n", j); - } - } - - RC.ru[j]->max_pdschReferenceSignalPower = *(RUParamList.paramarray[j][RU_MAX_RS_EPRE_IDX].uptr);; - RC.ru[j]->max_rxgain = *(RUParamList.paramarray[j][RU_MAX_RXGAIN_IDX].uptr); - RC.ru[j]->sf_extension = *(RUParamList.paramarray[j][RU_SF_EXTENSION_IDX].uptr); - } //strcmp(local_rf, "yes") == 0 - else { - LOG_D(PHY, "RU %d: Transport %s\n", j, *(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr)); - RC.ru[j]->eth_params.local_if_name = strdup(*(RUParamList.paramarray[j][RU_LOCAL_IF_NAME_IDX].strptr)); - RC.ru[j]->eth_params.my_addr = strdup(*(RUParamList.paramarray[j][RU_LOCAL_ADDRESS_IDX].strptr)); - RC.ru[j]->eth_params.remote_addr = strdup(*(RUParamList.paramarray[j][RU_REMOTE_ADDRESS_IDX].strptr)); - RC.ru[j]->eth_params.my_portc = *(RUParamList.paramarray[j][RU_LOCAL_PORTC_IDX].uptr); - RC.ru[j]->eth_params.remote_portc = *(RUParamList.paramarray[j][RU_REMOTE_PORTC_IDX].uptr); - RC.ru[j]->eth_params.my_portd = *(RUParamList.paramarray[j][RU_LOCAL_PORTD_IDX].uptr); - RC.ru[j]->eth_params.remote_portd = *(RUParamList.paramarray[j][RU_REMOTE_PORTD_IDX].uptr); - - if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "udp") == 0) { - RC.ru[j]->if_south = REMOTE_IF5; - RC.ru[j]->function = NGFI_RAU_IF5; - RC.ru[j]->eth_params.transp_preference = ETH_UDP_MODE; - } else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "udp_ecpri_if5") == 0) { - RC.ru[j]->if_south = REMOTE_IF5; - RC.ru[j]->function = NGFI_RAU_IF5; - RC.ru[j]->eth_params.transp_preference = ETH_UDP_IF5_ECPRI_MODE; - } else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "raw") == 0) { - RC.ru[j]->if_south = REMOTE_IF5; - RC.ru[j]->function = NGFI_RAU_IF5; - RC.ru[j]->eth_params.transp_preference = ETH_RAW_MODE; - } else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "udp_if4p5") == 0) { - RC.ru[j]->if_south = REMOTE_IF4p5; - RC.ru[j]->function = NGFI_RAU_IF4p5; - RC.ru[j]->eth_params.transp_preference = ETH_UDP_IF4p5_MODE; - } else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "raw_if4p5") == 0) { - RC.ru[j]->if_south = REMOTE_IF4p5; - RC.ru[j]->function = NGFI_RAU_IF4p5; - RC.ru[j]->eth_params.transp_preference = ETH_RAW_IF4p5_MODE; - } - } /* strcmp(local_rf, "yes") != 0 */ - - RC.ru[j]->nb_tx = *(RUParamList.paramarray[j][RU_NB_TX_IDX].uptr); - RC.ru[j]->nb_rx = *(RUParamList.paramarray[j][RU_NB_RX_IDX].uptr); - RC.ru[j]->att_tx = *(RUParamList.paramarray[j][RU_ATT_TX_IDX].uptr); - RC.ru[j]->att_rx = *(RUParamList.paramarray[j][RU_ATT_RX_IDX].uptr); - RC.ru[j]->if_frequency = *(RUParamList.paramarray[j][RU_IF_FREQUENCY].u64ptr); - RC.ru[j]->if_freq_offset = *(RUParamList.paramarray[j][RU_IF_FREQ_OFFSET].iptr); - RC.ru[j]->sl_ahead = *(RUParamList.paramarray[j][RU_SL_AHEAD].iptr); - RC.ru[j]->num_bands = RUParamList.paramarray[j][RU_BAND_LIST_IDX].numelt; - for (int i = 0; i < RC.ru[j]->num_bands; i++) - RC.ru[j]->band[i] = RUParamList.paramarray[j][RU_BAND_LIST_IDX].iptr[i]; - RC.ru[j]->openair0_cfg.nr_flag = *(RUParamList.paramarray[j][RU_NR_FLAG].iptr); - RC.ru[j]->openair0_cfg.nr_band = RC.ru[j]->band[0]; - RC.ru[j]->openair0_cfg.nr_scs_for_raster = *(RUParamList.paramarray[j][RU_NR_SCS_FOR_RASTER].iptr); - LOG_D(PHY, - "[RU %d] Setting nr_flag %d, nr_band %d, nr_scs_for_raster %d\n", - j, - RC.ru[j]->openair0_cfg.nr_flag, - RC.ru[j]->openair0_cfg.nr_band, - RC.ru[j]->openair0_cfg.nr_scs_for_raster); - RC.ru[j]->openair0_cfg.rxfh_cores[0] = *(RUParamList.paramarray[j][RU_RXFH_CORE_ID].iptr); - RC.ru[j]->openair0_cfg.txfh_cores[0] = *(RUParamList.paramarray[j][RU_TXFH_CORE_ID].iptr); - RC.ru[j]->num_tpcores = *(RUParamList.paramarray[j][RU_NUM_TP_CORES].iptr); - RC.ru[j]->half_slot_parallelization = *(RUParamList.paramarray[j][RU_HALF_SLOT_PARALLELIZATION].iptr); - RC.ru[j]->ru_thread_core = *(RUParamList.paramarray[j][RU_RU_THREAD_CORE].iptr); - LOG_D(PHY, "[RU %d] Setting half-slot parallelization to %d\n", j, RC.ru[j]->half_slot_parallelization); - AssertFatal(RC.ru[j]->num_tpcores <= RUParamList.paramarray[j][RU_TP_CORES].numelt, "Number of TP cores should be <=16\n"); - for (int i = 0; i < RC.ru[j]->num_tpcores; i++) - RC.ru[j]->tpcores[i] = RUParamList.paramarray[j][RU_TP_CORES].iptr[i]; - }// j=0..num_rus - } else { - RC.nb_RU = 0; - } // setting != NULL + if (strcmp(str, "udp") == 0) { + ru->if_south = REMOTE_IF5; + ru->function = NGFI_RAU_IF5; + ru->eth_params.transp_preference = ETH_UDP_MODE; + } else if (strcmp(str, "udp_ecpri_if5") == 0) { + ru->if_south = REMOTE_IF5; + ru->function = NGFI_RAU_IF5; + ru->eth_params.transp_preference = ETH_UDP_IF5_ECPRI_MODE; + } else if (strcmp(str, "raw") == 0) { + ru->if_south = REMOTE_IF5; + ru->function = NGFI_RAU_IF5; + ru->eth_params.transp_preference = ETH_RAW_MODE; + } else if (strcmp(str, "udp_if4p5") == 0) { + ru->if_south = REMOTE_IF4p5; + ru->function = NGFI_RAU_IF4p5; + ru->eth_params.transp_preference = ETH_UDP_IF4p5_MODE; + } else if (strcmp(str, "raw_if4p5") == 0) { + ru->if_south = REMOTE_IF4p5; + ru->function = NGFI_RAU_IF4p5; + ru->eth_params.transp_preference = ETH_RAW_IF4p5_MODE; + } + } /* strcmp(local_rf, "yes") != 0 */ + ru->nb_tx = *param[RU_NB_TX_IDX].uptr; + ru->nb_rx = *param[RU_NB_RX_IDX].uptr; + ru->att_tx = *param[RU_ATT_TX_IDX].uptr; + ru->att_rx = *param[RU_ATT_RX_IDX].uptr; + ru->if_frequency = *param[RU_IF_FREQUENCY].u64ptr; + ru->if_freq_offset = *param[RU_IF_FREQ_OFFSET].iptr; + ru->sl_ahead = *param[RU_SL_AHEAD].iptr; + ru->num_bands = param[RU_BAND_LIST_IDX].numelt; + for (int i = 0; i < ru->num_bands; i++) + ru->band[i] = param[RU_BAND_LIST_IDX].iptr[i]; + ru->openair0_cfg.nr_flag = *param[RU_NR_FLAG].iptr; + ru->openair0_cfg.nr_band = ru->band[0]; + ru->openair0_cfg.nr_scs_for_raster = *param[RU_NR_SCS_FOR_RASTER].iptr; + LOG_D(PHY, + "[RU %d] Setting nr_flag %d, nr_band %d, nr_scs_for_raster %d\n", + j, + ru->openair0_cfg.nr_flag, + ru->openair0_cfg.nr_band, + ru->openair0_cfg.nr_scs_for_raster); + ru->openair0_cfg.rxfh_cores[0] = *param[RU_RXFH_CORE_ID].iptr; + ru->openair0_cfg.txfh_cores[0] = *param[RU_TXFH_CORE_ID].iptr; + ru->num_tpcores = *param[RU_NUM_TP_CORES].iptr; + ru->half_slot_parallelization = *param[RU_HALF_SLOT_PARALLELIZATION].iptr; + ru->ru_thread_core = *param[RU_RU_THREAD_CORE].iptr; + LOG_D(PHY, "[RU %d] Setting half-slot parallelization to %d\n", j, ru->half_slot_parallelization); + AssertFatal(ru->num_tpcores <= param[RU_TP_CORES].numelt, "Number of TP cores should be <=16\n"); + for (int i = 0; i < ru->num_tpcores; i++) + ru->tpcores[i] = param[RU_TP_CORES].iptr[i]; + } // j=0..num_rus return; } From 096ea7bd87f430b8bbe9d7a1e48e5ce076f44ac6 Mon Sep 17 00:00:00 2001 From: Bartosz Podrygajlo Date: Tue, 15 Apr 2025 09:41:53 +0200 Subject: [PATCH 504/964] Fixes for vrtsim - Allow client to exit cleanly if server is down - Ensure timing_thread is joined only once avoiding exit_function loop - Free noise_device - Save previously sent samples for channel modelling --- .../utils/shm_iq_channel/shm_td_iq_channel.c | 3 -- radio/vrtsim/noise_device.c | 4 +- radio/vrtsim/vrtsim.c | 53 +++++++++++++++---- 3 files changed, 46 insertions(+), 14 deletions(-) diff --git a/common/utils/shm_iq_channel/shm_td_iq_channel.c b/common/utils/shm_iq_channel/shm_td_iq_channel.c index 89e09ddb1f..3920fe027f 100644 --- a/common/utils/shm_iq_channel/shm_td_iq_channel.c +++ b/common/utils/shm_iq_channel/shm_td_iq_channel.c @@ -228,9 +228,6 @@ IQChannelErrorType shm_td_iq_channel_rx(ShmTDIQChannel *channel, void shm_td_iq_channel_produce_samples(ShmTDIQChannel *channel, size_t num_samples) { ShmTDIQChannelData *data = channel->data; - if (channel->type != IQ_CHANNEL_TYPE_SERVER) { - return; - } if (data->is_connected == false) { return; } diff --git a/radio/vrtsim/noise_device.c b/radio/vrtsim/noise_device.c index 2e15944d4a..acb3a2b5da 100644 --- a/radio/vrtsim/noise_device.c +++ b/radio/vrtsim/noise_device.c @@ -18,6 +18,7 @@ * For more information about the OpenAirInterface (OAI) Software Alliance: * contact@openairinterface.org */ +#include "assertions.h" #include #include #include "noise_device.h" @@ -74,7 +75,8 @@ void init_noise_device(float noise_power) void free_noise_device(void) { state.running = false; - pthread_join(state.noise_device_thread, NULL); + int ret = pthread_join(state.noise_device_thread, NULL); + AssertFatal(ret == 0, "pthread_join failed: %d, errno %d (%s)\n", ret, errno, strerror(errno)); } void get_noise_vector(float *noise_vector, int length) diff --git a/radio/vrtsim/vrtsim.c b/radio/vrtsim/vrtsim.c index f0e0151aa6..0e602b3686 100644 --- a/radio/vrtsim/vrtsim.c +++ b/radio/vrtsim/vrtsim.c @@ -19,6 +19,7 @@ * contact@openairinterface.org */ +#include "PHY/TOOLS/tools_defs.h" #include #include #include @@ -50,7 +51,8 @@ // Simulator role typedef enum { ROLE_SERVER = 1, ROLE_CLIENT } role; -#define NUM_CHANMOD_THREADS 1 +#define MAX_NUM_ANTENNAS_TX 4 +#define MAX_CHANNEL_LENGTH (1 << 20) #define ROLE_CLIENT_STRING "client" #define ROLE_SERVER_STRING "server" @@ -112,6 +114,9 @@ typedef struct { Actor_t *channel_modelling_actors; } vrtsim_state_t; +// Sample history for channel impulse response +static c16_t saved_samples[MAX_NUM_ANTENNAS_TX][MAX_CHANNEL_LENGTH] __attribute__((aligned(32))) = {0}; + static void histogram_add(histogram_t *histogram, double diff) { histogram->num_samples++; @@ -149,6 +154,16 @@ static void load_channel_model(vrtsim_state_t *vrtsim_state) vrtsim_state->tx_bw); char *model_name = vrtsim_state->role == ROLE_CLIENT ? "client_tx_channel_model" : "server_tx_channel_model"; vrtsim_state->channel_desc = find_channel_desc_fromname(model_name); + AssertFatal(vrtsim_state->channel_desc != NULL, + "Could not find model name %s. Make sure it is present in the config file", + model_name); + LOG_I(HW, + "Channel model %s parameters: path_loss_dB=%.2f, nb_tx=%d, nb_rx=%d, channel_length=%d\n", + model_name, + vrtsim_state->channel_desc->path_loss_dB, + vrtsim_state->channel_desc->nb_tx, + vrtsim_state->channel_desc->nb_rx, + vrtsim_state->channel_desc->channel_length); random_channel(vrtsim_state->channel_desc, 0); AssertFatal(vrtsim_state->channel_desc != NULL, "Could not find channel model %s\n", model_name); } @@ -376,7 +391,7 @@ static int vrtsim_write_internal(vrtsim_state_t *vrtsim_state, typedef struct { vrtsim_state_t *vrtsim_state; openair0_timestamp timestamp; - c16_t *samples[4]; + c16_t *samples[MAX_NUM_ANTENNAS_TX]; int nsamps; int nbAnt; int flags; @@ -410,17 +425,16 @@ static void perform_channel_modelling(void *arg) } for (int aatx = 0; aatx < nb_tx_ant; aatx++) { + c16_t *previous_samples = saved_samples[aatx]; for (int i = 0; i < nsamps; i++) { cf_t *impulse_response = channel_impulse_response[aatx]; for (int l = 0; l < channel_desc->channel_length; l++) { int idx = i - l; - // TODO: Use AVX512 for this - // TODO: What are the previously sent samples (for impulse response) - if (idx >= 0) { - c16_t tx_input = input_samples[aatx][idx]; - samples[i].r += tx_input.r * impulse_response[l].r - tx_input.i * impulse_response[l].i; - samples[i].i += tx_input.i * impulse_response[l].r + tx_input.r * impulse_response[l].i; - } + // TODO: Use AVX2 for this + c16_t tx_input = idx >= 0 ? input_samples[aatx][idx] + : previous_samples[(channel_modelling_args->timestamp + i + idx) % MAX_CHANNEL_LENGTH]; + samples[i].r += tx_input.r * impulse_response[l].r - tx_input.i * impulse_response[l].i; + samples[i].i += tx_input.i * impulse_response[l].r + tx_input.r * impulse_response[l].i; } } } @@ -462,6 +476,7 @@ static int vrtsim_write_with_chanmod(vrtsim_state_t *vrtsim_state, int nbAnt, int flags) { + AssertFatal(nbAnt < MAX_NUM_ANTENNAS_TX, "Number of antennas %d exceeds maximum %d\n", nbAnt, MAX_NUM_ANTENNAS_TX); for (int aarx = 0; aarx < vrtsim_state->peer_info.num_rx_antennas; aarx++) { notifiedFIFO_elt_t *task = newNotifiedFIFO_elt(sizeof(channel_modelling_args_t), 0, NULL, perform_channel_modelling); channel_modelling_args_t *args = (channel_modelling_args_t *)NotifiedFifoData(task); @@ -476,6 +491,23 @@ static int vrtsim_write_with_chanmod(vrtsim_state_t *vrtsim_state, } pushNotifiedFIFO(&vrtsim_state->channel_modelling_actors[aarx].fifo, task); } + int start_index = timestamp % MAX_CHANNEL_LENGTH; + int end_index = min(start_index + nsamps, MAX_CHANNEL_LENGTH); + int cp_nsamps = end_index - start_index; + for (int aatx = 0; aatx < nbAnt; aatx++) { + c16_t *samples = (c16_t *)samplesVoid[aatx]; + memcpy(&saved_samples[aatx][start_index], &samples[0], sizeof(c16_t) * cp_nsamps); + } + + if (end_index < start_index + nsamps) { + // wrap around condition, write at beginning of buffer + cp_nsamps = nsamps - cp_nsamps; // remaining samples + start_index = 0; + for (int aatx = 0; aatx < nbAnt; aatx++) { + c16_t *samples = (c16_t *)samplesVoid[aatx]; + memcpy(&saved_samples[aatx][start_index], &samples[0], sizeof(c16_t) * cp_nsamps); + } + } return nsamps; } @@ -506,7 +538,7 @@ static int vrtsim_read(openair0_device *device, openair0_timestamp *ptimestamp, static void vrtsim_end(openair0_device *device) { vrtsim_state_t *vrtsim_state = (vrtsim_state_t *)device->priv; - if (vrtsim_state->role == ROLE_SERVER) { + if (vrtsim_state->role == ROLE_SERVER && vrtsim_state->run_timing_thread) { vrtsim_state->run_timing_thread = false; int ret = pthread_join(vrtsim_state->timing_thread, NULL); AssertFatal(ret == 0, "pthread_join() failed: errno: %d, %s\n", errno, strerror(errno)); @@ -526,6 +558,7 @@ static void vrtsim_end(openair0_device *device) tx_timing->tx_samples_total += tx_timing[i].tx_samples_total; } tx_timing->average_tx_budget /= vrtsim_state->peer_info.num_rx_antennas; + free_noise_device(); } // produce 1 second of extra samples so threads can finish shm_td_iq_channel_produce_samples(vrtsim_state->channel, vrtsim_state->sample_rate); From c8d64f0dd187d945fd7504fd4b6559e15be066f6 Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Mon, 21 Jul 2025 15:04:07 +0200 Subject: [PATCH 505/964] nr rlc: add an API function to retrieve the occupancy of TX list --- openair2/LAYER2/nr_rlc/nr_rlc_entity.c | 3 +++ openair2/LAYER2/nr_rlc/nr_rlc_entity.h | 1 + openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c | 5 +++++ openair2/LAYER2/nr_rlc/nr_rlc_entity_am.h | 1 + openair2/LAYER2/nr_rlc/nr_rlc_entity_tm.c | 6 ++++++ openair2/LAYER2/nr_rlc/nr_rlc_entity_tm.h | 1 + openair2/LAYER2/nr_rlc/nr_rlc_entity_um.c | 6 ++++++ openair2/LAYER2/nr_rlc/nr_rlc_entity_um.h | 1 + openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c | 19 +++++++++++++++++++ openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h | 2 ++ 10 files changed, 45 insertions(+) diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_entity.c b/openair2/LAYER2/nr_rlc/nr_rlc_entity.c index 6103a7011a..e452981357 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_entity.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_entity.c @@ -125,6 +125,7 @@ nr_rlc_entity_t *new_nr_rlc_entity_am( ret->common.reestablishment = nr_rlc_entity_am_reestablishment; ret->common.delete_entity = nr_rlc_entity_am_delete; ret->common.available_tx_space = nr_rlc_entity_am_available_tx_space; + ret->common.tx_list_occupancy = nr_rlc_entity_am_tx_list_occupancy; ret->common.get_stats = nr_rlc_entity_get_stats; ret->common.deliver_sdu = deliver_sdu; @@ -186,6 +187,7 @@ nr_rlc_entity_t *new_nr_rlc_entity_um( ret->common.reestablishment = nr_rlc_entity_um_reestablishment; ret->common.delete_entity = nr_rlc_entity_um_delete; ret->common.available_tx_space = nr_rlc_entity_um_available_tx_space; + ret->common.tx_list_occupancy = nr_rlc_entity_um_tx_list_occupancy; ret->common.get_stats = nr_rlc_entity_get_stats; ret->common.deliver_sdu = deliver_sdu; @@ -226,6 +228,7 @@ nr_rlc_entity_t *new_nr_rlc_entity_tm( ret->common.reestablishment = nr_rlc_entity_tm_reestablishment; ret->common.delete_entity = nr_rlc_entity_tm_delete; ret->common.available_tx_space = nr_rlc_entity_tm_available_tx_space; + ret->common.tx_list_occupancy = nr_rlc_entity_tm_tx_list_occupancy; ret->common.get_stats = nr_rlc_entity_get_stats; ret->common.deliver_sdu = deliver_sdu; diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_entity.h b/openair2/LAYER2/nr_rlc/nr_rlc_entity.h index dc0bf4907c..459e9f59a5 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_entity.h +++ b/openair2/LAYER2/nr_rlc/nr_rlc_entity.h @@ -116,6 +116,7 @@ typedef struct nr_rlc_entity_t { void (*delete_entity)(struct nr_rlc_entity_t *entity); int (*available_tx_space)(struct nr_rlc_entity_t *entity); + int (*tx_list_occupancy)(struct nr_rlc_entity_t *entity); void (*get_stats)(struct nr_rlc_entity_t *entity, nr_rlc_statistics_t *out); diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c b/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c index a66ebe82e5..b1f87a7a05 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c @@ -2116,3 +2116,8 @@ int nr_rlc_entity_am_available_tx_space(nr_rlc_entity_t *_entity) return entity->tx_maxsize - entity->tx_size; } +int nr_rlc_entity_am_tx_list_occupancy(nr_rlc_entity_t *_entity) +{ + nr_rlc_entity_am_t *entity = (nr_rlc_entity_am_t *)_entity; + return entity->tx_size; +} diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.h b/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.h index 6b61e84a2f..3ffcab6176 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.h +++ b/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.h @@ -101,5 +101,6 @@ void nr_rlc_entity_am_discard_sdu(nr_rlc_entity_t *_entity, int sdu_id); void nr_rlc_entity_am_reestablishment(nr_rlc_entity_t *_entity); void nr_rlc_entity_am_delete(nr_rlc_entity_t *entity); int nr_rlc_entity_am_available_tx_space(nr_rlc_entity_t *entity); +int nr_rlc_entity_am_tx_list_occupancy(nr_rlc_entity_t *_entity); #endif /* _NR_RLC_ENTITY_AM_H_ */ diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_entity_tm.c b/openair2/LAYER2/nr_rlc/nr_rlc_entity_tm.c index 7b541c02ff..be20d574c1 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_entity_tm.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_entity_tm.c @@ -221,3 +221,9 @@ int nr_rlc_entity_tm_available_tx_space(nr_rlc_entity_t *_entity) nr_rlc_entity_tm_t *entity = (nr_rlc_entity_tm_t *)_entity; return entity->tx_maxsize - entity->tx_size; } + +int nr_rlc_entity_tm_tx_list_occupancy(nr_rlc_entity_t *_entity) +{ + nr_rlc_entity_tm_t *entity = (nr_rlc_entity_tm_t *)_entity; + return entity->tx_size; +} diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_entity_tm.h b/openair2/LAYER2/nr_rlc/nr_rlc_entity_tm.h index 716b35d14d..2792017c34 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_entity_tm.h +++ b/openair2/LAYER2/nr_rlc/nr_rlc_entity_tm.h @@ -56,5 +56,6 @@ void nr_rlc_entity_tm_discard_sdu(nr_rlc_entity_t *_entity, int sdu_id); void nr_rlc_entity_tm_reestablishment(nr_rlc_entity_t *_entity); void nr_rlc_entity_tm_delete(nr_rlc_entity_t *entity); int nr_rlc_entity_tm_available_tx_space(nr_rlc_entity_t *entity); +int nr_rlc_entity_tm_tx_list_occupancy(nr_rlc_entity_t *_entity); #endif /* _NR_RLC_ENTITY_TM_H_ */ diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_entity_um.c b/openair2/LAYER2/nr_rlc/nr_rlc_entity_um.c index 75e407328b..4edee0ddab 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_entity_um.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_entity_um.c @@ -765,3 +765,9 @@ int nr_rlc_entity_um_available_tx_space(nr_rlc_entity_t *_entity) nr_rlc_entity_um_t *entity = (nr_rlc_entity_um_t *)_entity; return entity->tx_maxsize - entity->tx_size; } + +int nr_rlc_entity_um_tx_list_occupancy(nr_rlc_entity_t *_entity) +{ + nr_rlc_entity_um_t *entity = (nr_rlc_entity_um_t *)_entity; + return entity->tx_size; +} diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_entity_um.h b/openair2/LAYER2/nr_rlc/nr_rlc_entity_um.h index 6395bfd47e..c32c5aaedf 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_entity_um.h +++ b/openair2/LAYER2/nr_rlc/nr_rlc_entity_um.h @@ -80,5 +80,6 @@ void nr_rlc_entity_um_discard_sdu(nr_rlc_entity_t *_entity, int sdu_id); void nr_rlc_entity_um_reestablishment(nr_rlc_entity_t *_entity); void nr_rlc_entity_um_delete(nr_rlc_entity_t *entity); int nr_rlc_entity_um_available_tx_space(nr_rlc_entity_t *entity); +int nr_rlc_entity_um_tx_list_occupancy(nr_rlc_entity_t *_entity); #endif /* _NR_RLC_ENTITY_UM_H_ */ diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c index 88c8d5d377..e187541fd5 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c @@ -320,6 +320,25 @@ int nr_rlc_get_available_tx_space(const int ue_id, const logical_chan_id_t chann return ret; } +int nr_rlc_tx_list_occupancy(int ue_id, logical_chan_id_t lcid) +{ + int ret; + + nr_rlc_manager_lock(nr_rlc_ue_manager); + nr_rlc_ue_t *ue = nr_rlc_manager_get_ue(nr_rlc_ue_manager, ue_id); + nr_rlc_entity_t *rb = get_rlc_entity_from_lcid(ue, lcid); + + if (rb != NULL) { + ret = rb->tx_list_occupancy(rb); + } else { + ret = 0; + } + + nr_rlc_manager_unlock(nr_rlc_ue_manager); + + return ret; +} + int nr_rlc_module_init(nr_rlc_op_mode_t mode) { static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h index fec65796d9..454a59b928 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h +++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h @@ -80,6 +80,8 @@ void nr_rlc_reconfigure_entity(int ue_id, int lc_id, NR_RLC_Config_t *rlc_Config int nr_rlc_get_available_tx_space(const int ue_id, const logical_chan_id_t channel_idP); +int nr_rlc_tx_list_occupancy(int ue_id, logical_chan_id_t lcid); + void nr_rlc_activate_avg_time_to_tx(const int ue_id, const logical_chan_id_t channel_id, const bool is_on); void nr_rlc_srb_recv_sdu(const int ue_id, const logical_chan_id_t channel_id, unsigned char *buf, int size); From ee2668b7c38014ee2291656254af1b79bdfd2856 Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Mon, 21 Jul 2025 15:08:55 +0200 Subject: [PATCH 506/964] T GUI: add a get_range() API function for xy_plot --- common/utils/T/tracer/gui/gui.h | 2 ++ common/utils/T/tracer/gui/xy_plot.c | 16 ++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/common/utils/T/tracer/gui/gui.h b/common/utils/T/tracer/gui/gui.h index 0fb96db325..b2fce32cff 100644 --- a/common/utils/T/tracer/gui/gui.h +++ b/common/utils/T/tracer/gui/gui.h @@ -54,6 +54,8 @@ void container_set_child_growable(gui *_gui, widget *_this, int xy_plot_new_plot(gui *gui, widget *this, int color); void xy_plot_set_range(gui *gui, widget *this, float xmin, float xmax, float ymin, float ymax); +void xy_plot_get_range(gui *gui, widget *this, + float *xmin, float *xmax, float *ymin, float *ymax); void xy_plot_set_points(gui *gui, widget *this, int plot, int npoints, float *x, float *y); void xy_plot_get_dimensions(gui *gui, widget *this, int *width, int *height); diff --git a/common/utils/T/tracer/gui/xy_plot.c b/common/utils/T/tracer/gui/xy_plot.c index c10b76c6ee..cc198475c2 100644 --- a/common/utils/T/tracer/gui/xy_plot.c +++ b/common/utils/T/tracer/gui/xy_plot.c @@ -280,6 +280,22 @@ void xy_plot_set_range(gui *_gui, widget *_this, gunlock(g); } +void xy_plot_get_range(gui *_gui, widget *_this, + float *xmin, float *xmax, float *ymin, float *ymax) +{ + struct gui *g = _gui; + struct xy_plot_widget *this = _this; + + glock(g); + + *xmin = this->xmin; + *xmax = this->xmax; + *ymin = this->ymin; + *ymax = this->ymax; + + gunlock(g); +} + void xy_plot_set_points(gui *_gui, widget *_this, int plot, int npoints, float *x, float *y) { From 645393f4647fdab12a90d4969724ae9de895c070 Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Mon, 21 Jul 2025 15:30:00 +0200 Subject: [PATCH 507/964] T: throughputlog: handle tick discontinuities Think: TDD. --- common/utils/T/tracer/logger/throughputlog.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/common/utils/T/tracer/logger/throughputlog.c b/common/utils/T/tracer/logger/throughputlog.c index 8a2d46da91..8faa942533 100644 --- a/common/utils/T/tracer/logger/throughputlog.c +++ b/common/utils/T/tracer/logger/throughputlog.c @@ -73,12 +73,18 @@ static void _tick_event(void *p, event e) for (i = 0; i < l->common.vsize; i++) l->common.v[i]->append(l->common.v[i], frame, subframe, (double)l->total); - l->insert_point = (l->insert_point + 1) % 1000; - l->total -= l->bits[l->insert_point]; - l->bits[l->insert_point] = 0; + while (l->last_tick_frame != frame || l->last_tick_subframe != subframe) { + l->insert_point = (l->insert_point + 1) % 1000; + l->total -= l->bits[l->insert_point]; + l->bits[l->insert_point] = 0; + l->last_tick_subframe++; + if (l->last_tick_subframe == 10) { + l->last_tick_subframe = 0; + l->last_tick_frame++; + l->last_tick_frame %= 1024; + } + } - l->last_tick_frame = frame; - l->last_tick_subframe = subframe; } logger *new_throughputlog(event_handler *h, void *database, From 595e650f9fff7f3cba8dcf796bfa4577c485a13e Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Mon, 21 Jul 2025 15:46:15 +0200 Subject: [PATCH 508/964] T: scrolltti: handle tick discontinuities For TDD. --- common/utils/T/tracer/view/scrolltti.c | 30 ++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/common/utils/T/tracer/view/scrolltti.c b/common/utils/T/tracer/view/scrolltti.c index ad83cbc756..3dde5daecc 100644 --- a/common/utils/T/tracer/view/scrolltti.c +++ b/common/utils/T/tracer/view/scrolltti.c @@ -20,6 +20,8 @@ struct scrolltti { float xout[1000]; float yout[1000]; int insert_point; + int next_tick_frame; + int next_tick_subframe; }; /* this array is used to get Y range 1000, 2000, 5000, 10000, ... */ @@ -65,15 +67,35 @@ static void clear(view *this) /* TODO */ } +static void insert(struct scrolltti *this, double value) +{ + this->total -= this->data[this->insert_point]; + this->data[this->insert_point] = value; + this->total += this->data[this->insert_point]; + this->insert_point = (this->insert_point + 1) % 1000; +} + +static void next_subframe(struct scrolltti *this) +{ + this->next_tick_subframe++; + if (this->next_tick_subframe == 10) { + this->next_tick_subframe = 0; + this->next_tick_frame++; + this->next_tick_frame %= 1024; + } +} + static void append(view *_this, int frame, int subframe, double value) { struct scrolltti *this = (struct scrolltti *)_this; if (pthread_mutex_lock(&this->lock)) abort(); - this->total -= this->data[this->insert_point]; - this->data[this->insert_point] = value; - this->total += this->data[this->insert_point]; - this->insert_point = (this->insert_point + 1) % 1000; + while (this->next_tick_frame != frame || this->next_tick_subframe != subframe) { + insert(this, 0); + next_subframe(this); + } + insert(this, value); + next_subframe(this); if (pthread_mutex_unlock(&this->lock)) abort(); } From 138886ad5e05baba37cec5c9dd037deeb9971822 Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Mon, 21 Jul 2025 16:05:02 +0200 Subject: [PATCH 509/964] T: tti view: add automax ability Also, update a cmake file because compilation of the tracer 'ue' fails otherwise. --- common/utils/T/tracer/CMakeLists.txt | 4 ++-- common/utils/T/tracer/view/tti.c | 25 +++++++++++++++++++++++++ common/utils/T/tracer/view/view.h | 1 + 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/common/utils/T/tracer/CMakeLists.txt b/common/utils/T/tracer/CMakeLists.txt index e1c79ffdf6..60266b5fa9 100644 --- a/common/utils/T/tracer/CMakeLists.txt +++ b/common/utils/T/tracer/CMakeLists.txt @@ -63,8 +63,8 @@ if(T_TRACER_GUI) target_link_libraries(gnb PRIVATE png) add_executable(ue ue.c) - target_link_libraries(ue PRIVATE tracer_utils tracer_filter tracer_gui - tracer_logger tracer_view tracer_events) + target_link_libraries(ue PRIVATE tracer_utils tracer_view tracer_gui + tracer_logger tracer_filter tracer_events) target_link_libraries(ue PRIVATE png) add_executable(vcd vcd.c) diff --git a/common/utils/T/tracer/view/tti.c b/common/utils/T/tracer/view/tti.c index ebf9fc657c..38a7a70777 100644 --- a/common/utils/T/tracer/view/tti.c +++ b/common/utils/T/tracer/view/tti.c @@ -5,11 +5,14 @@ #include #include #include +#include struct tti { view common; gui *g; widget *w; + int automax; + widget *w2; int plot; float refresh_rate; pthread_mutex_t lock; @@ -48,6 +51,7 @@ static void *tti_thread(void *_this) if (pthread_mutex_lock(&this->lock)) abort(); xy_plot_get_dimensions(this->g, this->w, &plot_width, &plot_height); length = 0; + double max = 0; /* TODO: optimize */ for (i = 0; i < 1024*10; i++) /* do not take points too close after last insertion point */ @@ -55,8 +59,22 @@ static void *tti_thread(void *_this) far_enough(i, this->last_insert_point, plot_width)) { this->xout[length] = i; this->yout[length] = this->data[i]; + if (this->data[i] > max) max = this->data[i]; length++; } + if (this->automax) { + char o[128]; + sprintf(o, "%d", (int)max); + textarea_set_text(this->g, this->w2, o); + /* for Y range we want 10, 20, 50, 100, 200, 500, etc. */ + if (max < 10) max = 10; + double mlog = pow(10, floor(log10(max))); + static int tolog[11] = { -1, 1, 2, 5, 5, 5, 10, 10, 10, 10, 10 }; + max = tolog[(int)ceil(max/mlog)] * mlog; + float xmin, xmax, ymin, ymax; + xy_plot_get_range(this->g, this->w, &xmin, &xmax, &ymin, &ymax); + xy_plot_set_range(this->g, this->w, xmin, xmax, 0, max); + } xy_plot_set_points(this->g, this->w, this->plot, length, this->xout, this->yout); if (pthread_mutex_unlock(&this->lock)) abort(); @@ -119,3 +137,10 @@ view *new_view_tti(float refresh_rate, gui *g, widget *w, int color) return (view *)ret; } + +void view_tti_enable_automax(view *_tti, widget *w2) +{ + struct tti *tti = (struct tti *)_tti; + tti->automax = 1; + tti->w2 = w2; +} diff --git a/common/utils/T/tracer/view/view.h b/common/utils/T/tracer/view/view.h index 8167a00ccd..3dec6d3bff 100644 --- a/common/utils/T/tracer/view/view.h +++ b/common/utils/T/tracer/view/view.h @@ -27,5 +27,6 @@ view *new_subview_time(view *time, int line, int color, int size); view *new_view_ticktime(float refresh_rate, gui *g, widget *w); view *new_subview_ticktime(view *ticktime, int line, int color, int size); void ticktime_set_tick(view *ticktime, void *logger); +void view_tti_enable_automax(view *tti, widget *w2); #endif /* _VIEW_H_ */ From c4acec706deebdca240ab3ed6e2607f5df754e3d Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Mon, 21 Jul 2025 16:13:14 +0200 Subject: [PATCH 510/964] T: make number of subframes per frame a configurable item Think: NR with different number of slots per frame depending on mu. The name 'subframes_per_frame' is a bit ambiguous. It is valid for LTE, but for NR it should be 'slots_per_frame'. For example, for sub-carrier spacing of 30KHz, we have 20 slots per frame, so in this case subframes_per_frame = 20. In reality whatever the numerology, there is always 10 subframes per frame in NR. But how to name this variable which is used both for LTE and NR cases? 'subframes_or_slots_per_frame'? It's a bit long and also ambiguous. Conclusion: no big deal I think. 'subframes_per_frame' and so be it. --- common/utils/T/tracer/enb.c | 16 ++++---- common/utils/T/tracer/logger/logger.h | 2 +- common/utils/T/tracer/logger/throughputlog.c | 13 +++++-- common/utils/T/tracer/ue.c | 34 ++++++++--------- common/utils/T/tracer/view/scrolltti.c | 33 ++++++++++------ common/utils/T/tracer/view/tti.c | 40 +++++++++++++------- common/utils/T/tracer/view/view.h | 6 +-- 7 files changed, 86 insertions(+), 58 deletions(-) diff --git a/common/utils/T/tracer/enb.c b/common/utils/T/tracer/enb.c index 5bb1cb87e2..f48f8e7dd7 100644 --- a/common/utils/T/tracer/enb.c +++ b/common/utils/T/tracer/enb.c @@ -340,12 +340,12 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database, xy_plot_set_range(g, w, 0, 1024*10, -10, 80); l = new_ttilog(h, database, "ENB_PHY_PUCCH_1_ENERGY", "frame", "subframe", "threshold", 0); - v = new_view_tti(10, g, w, new_color(g, "#ff0000")); + v = new_view_tti(10, g, w, new_color(g, "#ff0000"), 10); logger_add_view(l, v); e->pucch1_energy_ue_threshold_logger = l; l = new_ttilog(h, database, "ENB_PHY_PUCCH_1_ENERGY", "frame", "subframe", "energy", 1); - v = new_view_tti(10, g, w, new_color(g, "#0c0c72")); + v = new_view_tti(10, g, w, new_color(g, "#0c0c72"), 10); logger_add_view(l, v); e->pucch1_energy_ue_energy_logger = l; @@ -368,7 +368,7 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database, widget_add_child(g, line, w, -1); l = new_ticked_ttilog(h, database, "ENB_PHY_DL_TICK", "frame", "subframe", "ENB_PHY_DLSCH_UE_DCI", "mcs", 0, -1); - v = new_view_tti(10, g, w, new_color(g, "#0c0c72")); + v = new_view_tti(10, g, w, new_color(g, "#0c0c72"), 10); logger_add_view(l, v); e->dl_mcs_logger = l; @@ -379,7 +379,7 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database, widget_add_child(g, line, w, -1); l = new_ticked_ttilog(h, database, "ENB_PHY_DL_TICK", "frame", "subframe", "ENB_PHY_ULSCH_UE_DCI", "mcs", 0, -1); - v = new_view_tti(10, g, w, new_color(g, "#0c0c72")); + v = new_view_tti(10, g, w, new_color(g, "#0c0c72"), 10); logger_add_view(l, v); e->ul_mcs_logger = l; @@ -394,8 +394,8 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database, widget_add_child(g, col, w, -1); container_set_child_growable(g, col, w, 1); l = new_throughputlog(h, database, "ENB_PHY_DL_TICK", "frame", "subframe", - "ENB_PHY_DLSCH_UE_DCI", "TBS"); - v = new_view_scrolltti(10, g, w, new_color(g, "#0c0c72"), w2); + "ENB_PHY_DLSCH_UE_DCI", "TBS", 10); + v = new_view_scrolltti(10, g, w, new_color(g, "#0c0c72"), w2, 10); logger_add_view(l, v); /* UE x UL PHY (truly: DCI) throughput */ @@ -409,8 +409,8 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database, widget_add_child(g, col, w, -1); container_set_child_growable(g, col, w, 1); l = new_throughputlog(h, database, "ENB_PHY_DL_TICK", "frame", "subframe", - "ENB_PHY_ULSCH_UE_DCI", "TBS"); - v = new_view_scrolltti(10, g, w, new_color(g, "#0c0c72"), w2); + "ENB_PHY_ULSCH_UE_DCI", "TBS", 10); + v = new_view_scrolltti(10, g, w, new_color(g, "#0c0c72"), w2, 10); logger_add_view(l, v); /* downlink/uplink UE DCIs */ diff --git a/common/utils/T/tracer/logger/logger.h b/common/utils/T/tracer/logger/logger.h index d746161e70..8508032ec0 100644 --- a/common/utils/T/tracer/logger/logger.h +++ b/common/utils/T/tracer/logger/logger.h @@ -16,7 +16,7 @@ logger *new_ticked_ttilog(void *event_handler, void *database, int convert_to_dB, float empty_value); logger *new_throughputlog(void *event_handler, void *database, char *tick_event_name, char *frame_varname, char *subframe_varname, - char *event_name, char *data_varname); + char *event_name, char *data_varname, int subframes_per_frame); logger *new_timelog(void *event_handler, void *database, char *event_name); logger *new_ticklog(void *event_handler, void *database, char *event_name, char *frame_name, char *subframe_name); diff --git a/common/utils/T/tracer/logger/throughputlog.c b/common/utils/T/tracer/logger/throughputlog.c index 8faa942533..e7b48f6e2f 100644 --- a/common/utils/T/tracer/logger/throughputlog.c +++ b/common/utils/T/tracer/logger/throughputlog.c @@ -19,7 +19,8 @@ struct throughputlog { int data_arg; int last_tick_frame; int last_tick_subframe; - unsigned long bits[1000]; + int subframes_per_frame; + unsigned long *bits; unsigned long total; int insert_point; char *tick_event_name; @@ -74,11 +75,11 @@ static void _tick_event(void *p, event e) l->common.v[i]->append(l->common.v[i], frame, subframe, (double)l->total); while (l->last_tick_frame != frame || l->last_tick_subframe != subframe) { - l->insert_point = (l->insert_point + 1) % 1000; + l->insert_point = (l->insert_point + 1) % (100 * l->subframes_per_frame); l->total -= l->bits[l->insert_point]; l->bits[l->insert_point] = 0; l->last_tick_subframe++; - if (l->last_tick_subframe == 10) { + if (l->last_tick_subframe == l->subframes_per_frame) { l->last_tick_subframe = 0; l->last_tick_frame++; l->last_tick_frame %= 1024; @@ -89,7 +90,7 @@ static void _tick_event(void *p, event e) logger *new_throughputlog(event_handler *h, void *database, char *tick_event_name, char *frame_varname, char *subframe_varname, - char *event_name, char *data_varname) + char *event_name, char *data_varname, int subframes_per_frame) { struct throughputlog *ret; int event_id; @@ -189,6 +190,10 @@ logger *new_throughputlog(event_handler *h, void *database, abort(); } + ret->subframes_per_frame = subframes_per_frame; + ret->bits = calloc(100 * subframes_per_frame, sizeof(unsigned long)); + if (ret->bits == NULL) abort(); + return ret; } diff --git a/common/utils/T/tracer/ue.c b/common/utils/T/tracer/ue.c index b28f83b0f2..f4ea38f980 100644 --- a/common/utils/T/tracer/ue.c +++ b/common/utils/T/tracer/ue.c @@ -250,15 +250,15 @@ static void ue_main_gui(ue_gui *e, gui *g, event_handler *h, void *database, widget_add_child(g, line, w, -1); xy_plot_set_range(g, w, 0, 1024*10, -130, 35); /*l = new_ticked_ttilog(h, database,"UE_PHY_DL_TICK", "frame", "subframe","UE_PHY_MEAS", "rssi", 0, -1); - v = new_view_tti(10, g, w, new_color(g, "#720c0c")); + v = new_view_tti(10, g, w, new_color(g, "#720c0c"), 10); logger_add_view(l, v); e->phy_meas_logger = l;*/ l = new_ticked_ttilog(h, database,"UE_PHY_DL_TICK", "frame", "subframe","UE_PHY_MEAS", "rsrp", 0, -1); - v = new_view_tti(10, g, w, new_color(g, "#0c0c72")); + v = new_view_tti(10, g, w, new_color(g, "#0c0c72"), 10); logger_add_view(l, v); e->phy_meas_logger = l; l = new_ticked_ttilog(h, database,"UE_PHY_DL_TICK", "frame", "subframe","UE_PHY_MEAS", "snr", 0, -1); - v = new_view_tti(10, g, w, new_color(g, "#0c720c")); + v = new_view_tti(10, g, w, new_color(g, "#0c720c"), 10); logger_add_view(l, v); e->phy_meas_logger = l; @@ -277,7 +277,7 @@ static void ue_main_gui(ue_gui *e, gui *g, event_handler *h, void *database, widget_add_child(g, line, w, -1); l = new_ticked_ttilog(h, database, "UE_PHY_DL_TICK", "frame", "subframe", "UE_PHY_DLSCH_UE_DCI", "mcs", 0, -1); - v = new_view_tti(10, g, w, new_color(g, "#0c0c72")); + v = new_view_tti(10, g, w, new_color(g, "#0c0c72"), 10); logger_add_view(l, v); e->dl_mcs_logger = l; @@ -288,7 +288,7 @@ static void ue_main_gui(ue_gui *e, gui *g, event_handler *h, void *database, widget_add_child(g, line, w, -1); l = new_ticked_ttilog(h, database, "UE_PHY_DL_TICK", "frame", "subframe", "UE_PHY_ULSCH_UE_DCI", "mcs", 0, -1); - v = new_view_tti(10, g, w, new_color(g, "#0c0c72")); + v = new_view_tti(10, g, w, new_color(g, "#0c0c72"), 10); logger_add_view(l, v); e->ul_mcs_logger = l; @@ -301,12 +301,12 @@ static void ue_main_gui(ue_gui *e, gui *g, event_handler *h, void *database, xy_plot_set_range(g, w, 0, 1024*10, -30, 50); l = new_ttilog(h, database, "UE_PHY_PUSCH_TX_POWER", "frame", "subframe", "p0_pusch", 0); - v = new_view_tti(10, g, w, new_color(g, "#0c0c72")); + v = new_view_tti(10, g, w, new_color(g, "#0c0c72"), 10); logger_add_view(l, v); e->pusch_power_logger = l; l = new_ttilog(h, database, "UE_PHY_PUSCH_TX_POWER", "frame", "subframe", "ampl", 1); - v = new_view_tti(10, g, w, new_color(g, "#720c0c")); + v = new_view_tti(10, g, w, new_color(g, "#720c0c"), 10); logger_add_view(l, v); e->pusch_ampl_logger = l; @@ -319,12 +319,12 @@ static void ue_main_gui(ue_gui *e, gui *g, event_handler *h, void *database, xy_plot_set_range(g, w, 0, 1024*10, -30, 50); l = new_ttilog(h, database, "UE_PHY_PUCCH_TX_POWER", "frame", "subframe", "p0_pucch", 0); - v = new_view_tti(10, g, w, new_color(g, "#0c0c72")); + v = new_view_tti(10, g, w, new_color(g, "#0c0c72"), 10); logger_add_view(l, v); e->pucch_power_logger = l; l = new_ttilog(h, database, "UE_PHY_PUCCH_TX_POWER", "frame", "subframe", "ampl", 1); - v = new_view_tti(10, g, w, new_color(g, "#720c0c")); + v = new_view_tti(10, g, w, new_color(g, "#720c0c"), 10); logger_add_view(l, v); e->pucch_ampl_logger = l; @@ -335,22 +335,22 @@ static void ue_main_gui(ue_gui *e, gui *g, event_handler *h, void *database, xy_plot_set_range(g, w, 0, 1024*10, -10, 80); l = new_ttilog(h, database, "UE_PHY_PDSCH_ENERGY", "frame", "subframe", "pdsch_ch_level00", 1); - v = new_view_tti(10, g, w, new_color(g, "#ff0000")); + v = new_view_tti(10, g, w, new_color(g, "#ff0000"), 10); logger_add_view(l, v); e->pdsch_energy_logger = l; l = new_ttilog(h, database, "UE_PHY_PDSCH_ENERGY", "frame", "subframe", "pdsch_ch_level01", 1); - v = new_view_tti(10, g, w, new_color(g, "#00ff00")); + v = new_view_tti(10, g, w, new_color(g, "#00ff00"), 10); logger_add_view(l, v); e->pdsch_energy_logger = l; l = new_ttilog(h, database, "UE_PHY_PDSCH_ENERGY", "frame", "subframe", "pdsch_ch_level10", 1); - v = new_view_tti(10, g, w, new_color(g, "#0f0f0f")); + v = new_view_tti(10, g, w, new_color(g, "#0f0f0f"), 10); logger_add_view(l, v); e->pdsch_energy_logger = l; l = new_ttilog(h, database, "UE_PHY_PDSCH_ENERGY", "frame", "subframe", "pdsch_ch_level11", 1); - v = new_view_tti(10, g, w, new_color(g, "#0000ff")); + v = new_view_tti(10, g, w, new_color(g, "#0000ff"), 10); logger_add_view(l, v); e->pdsch_energy_logger = l; @@ -361,22 +361,22 @@ static void ue_main_gui(ue_gui *e, gui *g, event_handler *h, void *database, xy_plot_set_range(g, w, 0, 1024*10, -10, 80); l = new_ttilog(h, database, "UE_PHY_PDCCH_ENERGY", "frame", "subframe", "pdcch_ch_level00", 1); - v = new_view_tti(10, g, w, new_color(g, "#ff0000")); + v = new_view_tti(10, g, w, new_color(g, "#ff0000"), 10); logger_add_view(l, v); e->pdcch_energy_logger = l; l = new_ttilog(h, database, "UE_PHY_PDCCH_ENERGY", "frame", "subframe", "pdcch_ch_level01", 1); - v = new_view_tti(10, g, w, new_color(g, "#00ff00")); + v = new_view_tti(10, g, w, new_color(g, "#00ff00"), 10); logger_add_view(l, v); e->pdcch_energy_logger = l; l = new_ttilog(h, database, "UE_PHY_PDCCH_ENERGY", "frame", "subframe", "pdcch_ch_level10", 1); - v = new_view_tti(10, g, w, new_color(g, "#0f0f0f")); + v = new_view_tti(10, g, w, new_color(g, "#0f0f0f"), 10); logger_add_view(l, v); e->pdcch_energy_logger = l; l = new_ttilog(h, database, "UE_PHY_PDCCH_ENERGY", "frame", "subframe", "pdcch_ch_level11", 1); - v = new_view_tti(10, g, w, new_color(g, "#0000ff")); + v = new_view_tti(10, g, w, new_color(g, "#0000ff"), 10); logger_add_view(l, v); e->pdcch_energy_logger = l; diff --git a/common/utils/T/tracer/view/scrolltti.c b/common/utils/T/tracer/view/scrolltti.c index 3dde5daecc..66fe0b3f02 100644 --- a/common/utils/T/tracer/view/scrolltti.c +++ b/common/utils/T/tracer/view/scrolltti.c @@ -15,10 +15,11 @@ struct scrolltti { int plot; float refresh_rate; pthread_mutex_t lock; - unsigned long data[1000]; - unsigned long total; /* sum data[0..999] to have smoother value printed */ - float xout[1000]; - float yout[1000]; + int subframes_per_frame; + unsigned long *data; + unsigned long total; /* sum data[0..n] to have smoother value printed */ + float *xout; + float *yout; int insert_point; int next_tick_frame; int next_tick_subframe; @@ -40,21 +41,21 @@ static void *scrolltti_thread(void *_this) /* TODO: optimize */ p = this->insert_point; max = 0; - for (i = 0; i < 1000; i++) { + for (i = 0; i < this->subframes_per_frame * 100; i++) { this->xout[i] = i; this->yout[i] = this->data[p]; if (this->data[p] > max) max = this->data[p]; - p = (p + 1) % 1000; + p = (p + 1) % (this->subframes_per_frame * 100); } - bps(o, this->total/1000., "b/s"); + bps(o, this->total/(this->subframes_per_frame * 100.), "b/s"); textarea_set_text(this->g, this->throughput_textarea, o); /* for Y range we want 1000, 2000, 5000, 10000, 20000, 50000, etc. */ if (max < 1000) max = 1000; mlog = pow(10, floor(log10(max))); max = tolog[(int)ceil(max/mlog)] * mlog; - xy_plot_set_range(this->g, this->w, 0, 1000, 0, max); + xy_plot_set_range(this->g, this->w, 0, this->subframes_per_frame * 100, 0, max); xy_plot_set_points(this->g, this->w, this->plot, - 1000, this->xout, this->yout); + this->subframes_per_frame * 100, this->xout, this->yout); if (pthread_mutex_unlock(&this->lock)) abort(); sleepms(1000/this->refresh_rate); } @@ -72,13 +73,13 @@ static void insert(struct scrolltti *this, double value) this->total -= this->data[this->insert_point]; this->data[this->insert_point] = value; this->total += this->data[this->insert_point]; - this->insert_point = (this->insert_point + 1) % 1000; + this->insert_point = (this->insert_point + 1) % (this->subframes_per_frame * 100); } static void next_subframe(struct scrolltti *this) { this->next_tick_subframe++; - if (this->next_tick_subframe == 10) { + if (this->next_tick_subframe == this->subframes_per_frame) { this->next_tick_subframe = 0; this->next_tick_frame++; this->next_tick_frame %= 1024; @@ -100,7 +101,7 @@ static void append(view *_this, int frame, int subframe, double value) } view *new_view_scrolltti(float refresh_rate, gui *g, widget *w, int color, - widget *throughput_textarea) + widget *throughput_textarea, int subframes_per_frame) { struct scrolltti *ret = calloc(1, sizeof(struct scrolltti)); if (ret == NULL) abort(); @@ -114,6 +115,14 @@ view *new_view_scrolltti(float refresh_rate, gui *g, widget *w, int color, ret->throughput_textarea = throughput_textarea; ret->plot = xy_plot_new_plot(g, w, color); + ret->subframes_per_frame = subframes_per_frame; + ret->data = calloc(subframes_per_frame * 100, sizeof(unsigned long)); + if (ret->data == NULL) abort(); + ret->xout = calloc(subframes_per_frame * 100, sizeof(float)); + if (ret->xout == NULL) abort(); + ret->yout = calloc(subframes_per_frame * 100, sizeof(float)); + if (ret->yout == NULL) abort(); + if (pthread_mutex_init(&ret->lock, NULL)) abort(); new_thread(scrolltti_thread, ret); diff --git a/common/utils/T/tracer/view/tti.c b/common/utils/T/tracer/view/tti.c index 38a7a70777..6c352d08d5 100644 --- a/common/utils/T/tracer/view/tti.c +++ b/common/utils/T/tracer/view/tti.c @@ -16,23 +16,25 @@ struct tti { int plot; float refresh_rate; pthread_mutex_t lock; - float data[1024*10]; - int valid[1024*10]; - float xout[1024*10]; - float yout[1024*10]; + float *data; + int *valid; + float *xout; + float *yout; int last_insert_point; + int subframes_per_frame; }; -static int far_enough(int i, int last_insert, int plot_width) +static int far_enough(int i, int last_insert, int plot_width, + int subframes_per_frame) { int p1; int p2; int hole_size_px; int hole_size_tti; hole_size_px = 10; - hole_size_tti = 10240 * hole_size_px / plot_width; + hole_size_tti = 1024 * subframes_per_frame * hole_size_px / plot_width; p1 = last_insert; - p2 = (last_insert + hole_size_tti) % (1024*10); + p2 = (last_insert + hole_size_tti) % (1024 * subframes_per_frame); if (p1 < p2) { return !(i > p1 && i < p2); } @@ -53,10 +55,11 @@ static void *tti_thread(void *_this) length = 0; double max = 0; /* TODO: optimize */ - for (i = 0; i < 1024*10; i++) + for (i = 0; i < 1024 * this->subframes_per_frame; i++) /* do not take points too close after last insertion point */ if (this->valid[i] && - far_enough(i, this->last_insert_point, plot_width)) { + far_enough(i, this->last_insert_point, plot_width, + this->subframes_per_frame)) { this->xout[length] = i; this->yout[length] = this->data[i]; if (this->data[i] > max) max = this->data[i]; @@ -93,7 +96,7 @@ static void append(view *_this, int frame, int subframe, double value) { struct tti *this = (struct tti *)_this; int i; - int index = frame * 10 + subframe; + int index = frame * this->subframes_per_frame + subframe; if (pthread_mutex_lock(&this->lock)) abort(); @@ -102,10 +105,10 @@ static void append(view *_this, int frame, int subframe, double value) * this may be wrong if delay between two append is * greater than 1024 frames (something like that) */ - i = (this->last_insert_point + 1) % (1024*10); + i = (this->last_insert_point + 1) % (1024 * this->subframes_per_frame); while (i != index) { this->valid[i] = 0; - i = (i + 1) % (1024*10); + i = (i + 1) % (1024 * this->subframes_per_frame); } this->data[index] = value; @@ -116,7 +119,8 @@ static void append(view *_this, int frame, int subframe, double value) if (pthread_mutex_unlock(&this->lock)) abort(); } -view *new_view_tti(float refresh_rate, gui *g, widget *w, int color) +view *new_view_tti(float refresh_rate, gui *g, widget *w, int color, + int subframes_per_frame) { struct tti *ret = calloc(1, sizeof(struct tti)); if (ret == NULL) abort(); @@ -133,6 +137,16 @@ view *new_view_tti(float refresh_rate, gui *g, widget *w, int color) if (pthread_mutex_init(&ret->lock, NULL)) abort(); + ret->subframes_per_frame = subframes_per_frame; + ret->data = calloc(subframes_per_frame * 1024, sizeof(float)); + if (ret->data == NULL) abort(); + ret->valid = calloc(subframes_per_frame * 1024, sizeof(int)); + if (ret->valid == NULL) abort(); + ret->xout = calloc(subframes_per_frame * 1024, sizeof(float)); + if (ret->xout == NULL) abort(); + ret->yout = calloc(subframes_per_frame * 1024, sizeof(float)); + if (ret->yout == NULL) abort(); + new_thread(tti_thread, ret); return (view *)ret; diff --git a/common/utils/T/tracer/view/view.h b/common/utils/T/tracer/view/view.h index 3dec6d3bff..7f131efbb5 100644 --- a/common/utils/T/tracer/view/view.h +++ b/common/utils/T/tracer/view/view.h @@ -17,10 +17,10 @@ view *new_view_stdout(void); view *new_view_textlist(int maxsize, float refresh_rate, gui *g, widget *w); view *new_view_xy(int length, float refresh_rate, gui *g, widget *w, int color, enum xy_mode mode); -view *new_view_tti(float refresh_rate, gui *g, widget *w, - int color); +view *new_view_tti(float refresh_rate, gui *g, widget *w, int color, + int subframes_per_frame); view *new_view_scrolltti(float refresh_rate, gui *g, widget *w, - int color, widget *throughput_label); + int color, widget *throughput_label, int subframes_per_frame); view *new_view_time(int number_of_seconds, float refresh_rate, gui *g, widget *w); view *new_subview_time(view *time, int line, int color, int size); From cc87c72ac3942e01716ba94b647e883f69ec0baf Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Mon, 21 Jul 2025 16:20:52 +0200 Subject: [PATCH 511/964] T: fix a typo --- common/utils/T/T_messages.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/utils/T/T_messages.txt b/common/utils/T/T_messages.txt index 813226ec14..b45b0fc68d 100644 --- a/common/utils/T/T_messages.txt +++ b/common/utils/T/T_messages.txt @@ -92,9 +92,9 @@ ID = UE_PHY_INITIATE_RA_PROCEDURE GROUP = ALL:PHY:UE:WIRESHARK FORMAT = int,frame : int,subframe_or_slot : int,preamble : int,power ID = GNB_PHY_DL_TICK - DESC = gNodeB downlink tick - one tick per ms at start of downlink processing + DESC = gNodeB downlink tick - one tick per slot at start of downlink processing GROUP = ALL:PHY:GRAPHIC:GNB - FORMAT = int,gNB_ID : int,frame : int,subframe + FORMAT = int,gNB_ID : int,frame : int,slot ID = ENB_PHY_MIB DESC = MIB data GROUP = ALL:PHY:ENB:WIRESHARK From c4562df2e7707beeb8239359c9c56d5e1e3f0fc2 Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Mon, 21 Jul 2025 16:25:12 +0200 Subject: [PATCH 512/964] T: add some traces To be used by next commit. --- common/utils/T/T_messages.txt | 20 +++++++++++++++++++ executables/nr-gnb.c | 2 ++ .../LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 2 ++ .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 4 ++++ 4 files changed, 28 insertions(+) diff --git a/common/utils/T/T_messages.txt b/common/utils/T/T_messages.txt index b45b0fc68d..8dd5052714 100644 --- a/common/utils/T/T_messages.txt +++ b/common/utils/T/T_messages.txt @@ -95,6 +95,10 @@ ID = GNB_PHY_DL_TICK DESC = gNodeB downlink tick - one tick per slot at start of downlink processing GROUP = ALL:PHY:GRAPHIC:GNB FORMAT = int,gNB_ID : int,frame : int,slot +ID = GNB_PHY_UL_TICK + DESC = gNodeB uplink tick - one tick per slot at start of uplink processing + GROUP = ALL:PHY:GRAPHIC:GNB + FORMAT = int,gNB_ID : int,frame : int,slot ID = ENB_PHY_MIB DESC = MIB data GROUP = ALL:PHY:ENB:WIRESHARK @@ -221,6 +225,22 @@ ID = NRUE_MAC_DL_RAR_PDU_WITH_DATA DESC = NR MAC downlink PDU for RAR GROUP = ALL:MAC:UE:WIRESHARK FORMAT = int,rnti : int,frame : int,slot : buffer,data +ID = GNB_MAC_DL + DESC = NR MAC downlink scheduler decision for an UE + GROUP = ALL:MAC:GNB + FORMAT = int,rnti : int,frame : int,slot : int,mcs : int,tbs +ID = GNB_MAC_LCID_DL + DESC = NR MAC downlink scheduler decision for an UE for a specific LCID + GROUP = ALL:MAC:GNB + FORMAT = int,rnti : int,frame : int,slot : int,lcid : int,data_size : int,tx_list_occupancy +ID = GNB_MAC_UL + DESC = NR MAC uplink scheduler decision for an UE + GROUP = ALL:MAC:GNB + FORMAT = int,rnti : int,frame : int,slot : int,mcs : int,tbs +ID = GNB_MAC_LCID_UL + DESC = NR MAC uplink traffic received for an UE for a specific LCID + GROUP = ALL:MAC:GNB + FORMAT = int,rnti : int,frame : int,slot : int,lcid : int,data_size #RLC logs ID = ENB_RLC_DL diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index 345b58df7e..5ba70dc32b 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -174,6 +174,8 @@ static void rx_func(processingData_L1_t *info) int slot_rx = info->slot_rx; nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config; + T(T_GNB_PHY_UL_TICK, T_INT(gNB->Mod_id), T_INT(frame_rx), T_INT(slot_rx)); + // RX processing int rx_slot_type = nr_slot_select(cfg, frame_rx, slot_rx); if (rx_slot_type == NR_UPLINK_SLOT || rx_slot_type == NR_MIXED_SLOT) { diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index 44d4affb08..c47b8ceb33 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -1307,6 +1307,7 @@ void nr_schedule_ue_spec(module_id_t module_id, if (len == 0) break; + T(T_GNB_MAC_LCID_DL, T_INT(rnti), T_INT(frame), T_INT(slot), T_INT(lcid), T_INT(len * 8), T_INT(nr_rlc_tx_list_occupancy(rnti, lcid))); header->R = 0; header->F = 1; header->LCID = lcid; @@ -1380,6 +1381,7 @@ void nr_schedule_ue_spec(module_id_t module_id, T(T_GNB_MAC_DL_PDU_WITH_DATA, T_INT(module_id), T_INT(CC_id), T_INT(rnti), T_INT(frame), T_INT(slot), T_INT(current_harq_pid), T_BUFFER(harq->transportBlock.buf, TBS)); + T(T_GNB_MAC_DL, T_INT(rnti), T_INT(frame), T_INT(slot), T_INT(sched_pdsch->mcs), T_INT(TBS)); } const int ntx_req = TX_req->Number_of_PDUs; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 4486be536d..c177a791b9 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -485,6 +485,7 @@ static int nr_process_mac_pdu(instance_t module_idP, UE->mac_stats.ul.total_sdu_bytes += mac_len; UE->mac_stats.ul.lc_bytes[lcid] += mac_len; } + T(T_GNB_MAC_LCID_UL, T_INT(UE->rnti), T_INT(frameP), T_INT(slot), T_INT(lcid), T_INT(mac_len * 8)); break; case UL_SCH_LCID_DTCH ...(UL_SCH_LCID_DTCH + 28): @@ -512,6 +513,7 @@ static int nr_process_mac_pdu(instance_t module_idP, else sched_ctrl->estimated_ul_buffer = 0; } + T(T_GNB_MAC_LCID_UL, T_INT(UE->rnti), T_INT(frameP), T_INT(slot), T_INT(lcid), T_INT(mac_len * 8)); break; case UL_SCH_LCID_RECOMMENDED_BITRATE_QUERY: @@ -2467,6 +2469,8 @@ void post_process_ulsch(gNB_MAC_INST *nr_mac, post_process_pusch_t *pusch, NR_UE sched_ctrl->estimated_ul_buffer - sched_ctrl->sched_ul_bytes, sched_ctrl->tpc0); + T(T_GNB_MAC_UL, T_INT(UE->rnti), T_INT(frame), T_INT(slot), T_INT(sched_pusch->mcs), T_INT(sched_pusch->tb_size)); + /* PUSCH in a later slot, but corresponding DCI now! */ const int index = ul_buffer_index(sched_pusch->frame, sched_pusch->slot, From 92dc641e98bc12f6e2a2e8326c9c930d27ae4bb6 Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 19 Aug 2025 09:17:33 +0200 Subject: [PATCH 513/964] common channel level function --- .../PHY/nr_phy_common/inc/nr_phy_common.h | 7 ++++++ .../PHY/nr_phy_common/src/nr_phy_common.c | 22 +++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/openair1/PHY/nr_phy_common/inc/nr_phy_common.h b/openair1/PHY/nr_phy_common/inc/nr_phy_common.h index d52b6d9c43..febf434e5a 100644 --- a/openair1/PHY/nr_phy_common/inc/nr_phy_common.h +++ b/openair1/PHY/nr_phy_common/inc/nr_phy_common.h @@ -54,6 +54,13 @@ void freq2time(uint16_t ofdm_symbol_size, int16_t *freq_signal, int16_t *time_si void nr_est_delay(int ofdm_symbol_size, const c16_t *ls_est, c16_t *ch_estimates_time, delay_t *delay); unsigned int nr_get_tx_amp(int power_dBm, int power_max_dBm, int total_nb_rb, int nb_rb); void nr_fo_compensation(double fo_Hz, int samples_per_ms, int sample_offset, const c16_t *rxdata_in, c16_t *rxdata_out, int size); +void nr_channel_level(const int symbol, + const int size_est, + const c16_t ch_estimates_ext[][size_est], + const int nb_rx, + const int Nl, + int32_t avg[nb_rx * Nl], + const uint32_t len); void nr_generate_csi_rs(const NR_DL_FRAME_PARMS *frame_parms, const csi_mapping_parms_t *phy_csi_parms, const int16_t amp, diff --git a/openair1/PHY/nr_phy_common/src/nr_phy_common.c b/openair1/PHY/nr_phy_common/src/nr_phy_common.c index e86652bd49..4e8951d124 100644 --- a/openair1/PHY/nr_phy_common/src/nr_phy_common.c +++ b/openair1/PHY/nr_phy_common/src/nr_phy_common.c @@ -420,6 +420,28 @@ unsigned int nr_get_tx_amp(int power_dBm, int power_max_dBm, int total_nb_rb, in return (0); } +// compute average channel_level on each antenna +void nr_channel_level(const int symbol, + const int size_est, + const c16_t ch_estimates_ext[][size_est], + const int nb_rx, + const int Nl, + int32_t avg[nb_rx * Nl], + const uint32_t len) +{ + int16_t x = factor2(len); + int16_t y = len >> x; + for (int aarx = 0; aarx < nb_rx; aarx++) { + for (int l = 0; l < Nl; l++) { + simde__m128i *ch128 = (simde__m128i *)&ch_estimates_ext[l * nb_rx + aarx][symbol * len]; + //compute average level + avg[l * nb_rx + aarx] = simde_mm_average(ch128, len, x, y); + LOG_D(PHY, "Channel level: %d\n", avg[l * nb_rx + aarx]); + } + } +} + + void nr_fo_compensation(double fo_Hz, int samples_per_ms, int sample_offset, const c16_t *rxdata_in, c16_t *rxdata_out, int size) { const double phase_inc = -fo_Hz / (samples_per_ms * 1000); From a95a32c2f63ea70df75fb5212b13db409ff625e6 Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 19 Aug 2025 09:32:19 +0200 Subject: [PATCH 514/964] use common channel level for PBCH --- openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c | 38 ++++--------------- openair1/PHY/NR_UE_TRANSPORT/nr_psbch_rx.c | 8 +++- .../NR_UE_TRANSPORT/nr_transport_proto_ue.h | 3 -- 3 files changed, 14 insertions(+), 35 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c b/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c index 298de612ee..8065da24b2 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c @@ -38,6 +38,7 @@ #include #include #include "openair1/PHY/NR_REFSIG/nr_refsig_common.h" +#include "PHY/nr_phy_common/inc/nr_phy_common.h" #include "instrumentation.h" //#define DEBUG_PBCH //#define DEBUG_PBCH_ENCODING @@ -201,31 +202,6 @@ static uint16_t nr_pbch_extract(uint32_t rxdataF_sz, return(0); } -//__m128i avg128; - -//compute average channel_level on each (TX,RX) antenna pair -int nr_pbch_channel_level(struct complex16 dl_ch_estimates_ext[][PBCH_MAX_RE_PER_SYMBOL], - const NR_DL_FRAME_PARMS *frame_parms, - int nb_re) -{ - int32_t avg2 = 0; - - for (int aarx=0; aarxnb_antennas_rx; aarx++) { - - simde__m128i *dl_ch128 = (simde__m128i *)dl_ch_estimates_ext[aarx]; - - //compute average level - int32_t avg1 = simde_mm_average(dl_ch128, nb_re, 0, nb_re); - - if (avg1>avg2) - avg2 = avg1; - - //LOG_I(PHY,"Channel level : %d, %d\n",avg1, avg2); - } - - return(avg2); -} - void nr_pbch_channel_compensation(struct complex16 rxdataF_ext[][PBCH_MAX_RE_PER_SYMBOL], struct complex16 dl_ch_estimates_ext[][PBCH_MAX_RE_PER_SYMBOL], int nb_re, @@ -346,7 +322,6 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue, const struct complex16 rxdataF[][rxdataFSize]) { TracyCZone(ctx, true); - int max_h=0; int symbol; uint8_t Lmax=frame_parms->Lmax; int M = NR_POLAR_PBCH_E; @@ -390,11 +365,14 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue, LOG_I(PHY,"[PHY] PBCH starting channel_level\n"); #endif + int max_h = 0; if (symbol == 1) { - max_h = nr_pbch_channel_level(dl_ch_estimates_ext, - frame_parms, - nb_re); - log2_maxh = 3+(log2_approx(max_h)/2); + int avg[frame_parms->nb_antennas_rx]; + nr_channel_level(0, PBCH_MAX_RE_PER_SYMBOL, dl_ch_estimates_ext, frame_parms->nb_antennas_rx, 1, avg, nb_re); + max_h = avg[0]; + for (int i = 1; i < frame_parms->nb_antennas_rx; i++) + max_h = cmax(avg[i], max_h); + log2_maxh = 3 + (log2_approx(max_h) / 2); } #ifdef DEBUG_PBCH diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_psbch_rx.c b/openair1/PHY/NR_UE_TRANSPORT/nr_psbch_rx.c index 7406855cc4..1010a6e5e8 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_psbch_rx.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_psbch_rx.c @@ -25,6 +25,7 @@ #include "common/utils/LOG/log.h" #include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h" #include "PHY/TOOLS/phy_scope_interface.h" +#include "PHY/nr_phy_common/inc/nr_phy_common.h" // #define DEBUG_PSBCH @@ -158,8 +159,11 @@ int nr_rx_psbch(PHY_VARS_NR_UE *ue, int max_h = 0; if (symbol == 0) { - max_h = nr_pbch_channel_level(dl_ch_estimates_ext, frame_parms, nb_re); - // log2_maxh = 3+(log2_approx(max_h)/2); + int avg[frame_parms->nb_antennas_rx]; + nr_channel_level(0, PBCH_MAX_RE_PER_SYMBOL, dl_ch_estimates_ext, frame_parms->nb_antennas_rx, 1, avg, nb_re); + max_h = avg[0]; + for (int i = 1; i < frame_parms->nb_antennas_rx; i++) + max_h = cmax(avg[i], max_h); log2_maxh = 5 + (log2_approx(max_h) / 2); // LLR32 crc error. LLR 16 CRC works } #ifdef DEBUG_PSBCH diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h index a4098394ac..395081b4a8 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h @@ -346,9 +346,6 @@ void nr_tx_psbch(PHY_VARS_NR_UE *UE, uint32_t frame_tx, uint32_t slot_tx, sl_nr_ nr_initial_sync_t sl_nr_slss_search(PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc, int num_frames); // Reuse already existing PBCH functions -int nr_pbch_channel_level(struct complex16 dl_ch_estimates_ext[][PBCH_MAX_RE_PER_SYMBOL], - const NR_DL_FRAME_PARMS *frame_parms, - int nb_re); void nr_pbch_channel_compensation(struct complex16 rxdataF_ext[][PBCH_MAX_RE_PER_SYMBOL], struct complex16 dl_ch_estimates_ext[][PBCH_MAX_RE_PER_SYMBOL], int nb_re, From 65d0fb152e4a9b89b1101ec449bbbde1d55abad2 Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 19 Aug 2025 10:00:00 +0200 Subject: [PATCH 515/964] use common channel level for DCI reception --- openair1/PHY/NR_UE_TRANSPORT/dci_nr.c | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c index b4e2c413cf..43b27e3932 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c @@ -36,6 +36,7 @@ #include "PHY/CODING/nrPolar_tools/nr_polar_dci_defs.h" #include "PHY/phy_extern.h" #include "PHY/CODING/coding_extern.h" +#include "PHY/nr_phy_common/inc/nr_phy_common.h" #include "PHY/sse_intrin.h" #include "common/utils/nr/nr_common.h" #include @@ -197,20 +198,6 @@ static void nr_pdcch_llr(uint32_t sz, c16_t *rxF, c16_t *llr) } } -//compute average channel_level on each (TX,RX) antenna pair -static int32_t nr_pdcch_channel_level(int nb_re, int arraySz, c16_t dl_ch_estimates_ext[][arraySz], int nb_antennas_rx) -{ - int32_t avgs = 0; - for (int aarx = 0; aarx < nb_antennas_rx; aarx++) { - simde__m128i *dl_ch128 = (simde__m128i *)&dl_ch_estimates_ext[aarx]; - // compute average level - // if nb_re is not %4, some samples are missed inside simde_mm_average, so let's discard it - int32_t tmp = simde_mm_average(dl_ch128, nb_re & ~3, 0, nb_re & ~3); - avgs = cmax(avgs, tmp); - } - return avgs; -} - // This function will extract the mapped DM-RS PDCCH REs as per 38.211 Section 7.4.1.3.2 (Mapping to physical resources) static void nr_pdcch_extract_rbs_single(uint32_t rxdataF_sz, uint32_t coreset_nbr_rb, @@ -372,9 +359,13 @@ void nr_rx_pdcch(PHY_VARS_NR_UE *ue, rel15->coreset.frequency_domain_resource, rel15->BWPStart); - LOG_D(NR_PHY_DCI, "in nr_pdcch_channel_level(dl_ch_estimates_ext -> dl_ch_estimates_ext)\n"); + LOG_D(NR_PHY_DCI, "in channel level function (dl_ch_estimates_ext -> dl_ch_estimates_ext)\n"); // compute channel level based on ofdm symbol 0 - int32_t avgs = nr_pdcch_channel_level(n_rb, arraySz, pdcch_dl_ch_estimates_ext, antRx); + int avg[antRx]; + nr_channel_level(0, arraySz, pdcch_dl_ch_estimates_ext, antRx, 1, avg, n_rb); + int avgs = avg[0]; + for (int i = 1; i < antRx; i++) + avgs = cmax(avgs, avg[i]); uint8_t log2_maxh = (log2_approx(avgs) / 2) + 5; //+antRx; #ifdef UE_DEBUG_TRACE From 8d904dbf233f2ba29576a3a8c4ce2104b4dce471 Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 19 Aug 2025 10:17:51 +0200 Subject: [PATCH 516/964] use common channel level for PUSCH --- .../PHY/NR_TRANSPORT/nr_ulsch_demodulation.c | 46 +++++-------------- 1 file changed, 11 insertions(+), 35 deletions(-) diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c index e8d8efeb28..bd4ee92284 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c @@ -7,6 +7,7 @@ #include "PHY/NR_REFSIG/ptrs_nr.h" #include "PHY/NR_ESTIMATION/nr_ul_estimation.h" #include "PHY/defs_nr_common.h" +#include "PHY/nr_phy_common/inc/nr_phy_common.h" #include "common/utils/nr/nr_common.h" #include #include "PHY/sse_intrin.h" @@ -210,31 +211,6 @@ static int get_nb_re_pusch (NR_DL_FRAME_PARMS *frame_parms, nfapi_nr_pusch_pdu_t } else return(rel15_ul->rb_size * NR_NB_SC_PER_RB); } -// compute average channel_level on each (TX,RX) antenna pair -static void nr_ulsch_channel_level(int size_est, - int ul_ch_estimates_ext[][size_est], - NR_DL_FRAME_PARMS *frame_parms, - int32_t *avg, - uint8_t symbol, - uint32_t len, - uint8_t nrOfLayers) -{ - int16_t x = factor2(len); - int16_t y = (len)>>x; - - for (int aatx = 0; aatx < nrOfLayers; aatx++) { - for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { - - simde__m128i *ul_ch128 = (simde__m128i *)&ul_ch_estimates_ext[aatx * frame_parms->nb_antennas_rx + aarx][symbol * len]; - - //compute average level - avg[aatx * frame_parms->nb_antennas_rx + aarx] = simde_mm_average(ul_ch128, len, x, y); - //LOG_D(PHY, "Channel level: %d\n", avg[aatx * frame_parms->nb_antennas_rx + aarx]); - } - } - -} - static void nr_ulsch_channel_compensation(uint32_t buffer_length, int nb_rx_ant, c16_t rxFext[][buffer_length], @@ -1394,8 +1370,6 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, rel15_ul, frame_parms); - int avgs = 0; - int avg[frame_parms->nb_antennas_rx*rel15_ul->nrOfLayers]; uint8_t shift_ch_ext = rel15_ul->nrOfLayers > 1 ? log2_approx(max_ch >> 11) : 0; //---------------------------------------------------------- @@ -1410,15 +1384,17 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, rel15_ul->nrOfLayers, rel15_ul->rb_size, shift_ch_ext); - - nr_ulsch_channel_level(size_est, - ul_ch_estimates_ext, - frame_parms, - avg, - meas_symbol, // index of the start symbol - nb_re_pusch, // number of the re in pusch - rel15_ul->nrOfLayers); + int avg[frame_parms->nb_antennas_rx*rel15_ul->nrOfLayers]; + nr_channel_level(meas_symbol, + size_est, + (c16_t (*)[size_est])ul_ch_estimates_ext, + frame_parms->nb_antennas_rx, + rel15_ul->nrOfLayers, + avg, + nb_re_pusch); + + int avgs = 0; for (int nl = 0; nl < rel15_ul->nrOfLayers; nl++) for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) avgs = cmax(avgs, avg[nl * frame_parms->nb_antennas_rx + aarx]); From 6af8f5619a0513290cbab3a31263532ced0db6ca Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 19 Aug 2025 11:30:00 +0200 Subject: [PATCH 517/964] use common channel level for PDSCH --- .../NR_UE_TRANSPORT/nr_dlsch_demodulation.c | 65 +++---------------- 1 file changed, 8 insertions(+), 57 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c index d0457b3bb9..39f91d3b4e 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c @@ -193,20 +193,6 @@ static void nr_dlsch_channel_compensation(uint32_t rx_size_symbol, unsigned char output_shift, PHY_NR_MEASUREMENTS *measurements); -/** \brief This function computes the average channel level over all allocated RBs and antennas (TX/RX) in order to compute output shift for compensated signal - @param dl_ch_estimates_ext Channel estimates in allocated RBs - @param frame_parms Pointer to frame descriptor - @param avg Pointer to average signal strength - @param pilots_flag Flag to indicate pilots in symbol - @param nb_rb Number of allocated RBs -*/ -static void nr_dlsch_channel_level(uint32_t rx_size_symbol, - int32_t dl_ch_estimates_ext[][rx_size_symbol], - uint8_t n_rx, - uint8_t n_tx, - int32_t avg[MAX_ANT][MAX_ANT], - uint32_t len); - void nr_dlsch_scale_channel(uint32_t rx_size_symbol, int32_t dl_ch_estimates_ext[][rx_size_symbol], NR_DL_FRAME_PARMS *frame_parms, @@ -538,25 +524,25 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, //---------------------------------------------------------- start_meas_nr_ue_phy(ue, DLSCH_CHANNEL_LEVEL_STATS); if (first_symbol_flag) { - int32_t avg[MAX_ANT][MAX_ANT] = {}; + int32_t avg[nl * n_rx]; if (nb_re_pdsch) - nr_dlsch_channel_level(rx_size_symbol, dl_ch_estimates_ext, frame_parms->nb_antennas_rx, nl, avg, nb_re_pdsch); + nr_channel_level(0, rx_size_symbol, (c16_t (*)[rx_size_symbol])dl_ch_estimates_ext, n_rx, nl, avg, nb_re_pdsch); else LOG_E(NR_PHY, "Average channel level is 0: nb_rb_pdsch = %d, nb_re_pdsch = %d\n", nb_rb_pdsch, nb_re_pdsch); int avgs = 0; int32_t median[MAX_ANT][MAX_ANT]; - for (int aatx = 0; aatx < nl; aatx++) + for (int l = 0; l < nl; l++) for (int aarx = 0; aarx < n_rx; aarx++) { - avgs = cmax(avgs, avg[aatx][aarx]); - LOG_D(PHY, "nb_rb %d avg_%d_%d Power per SC is %d\n", nb_rb_pdsch, aarx, aatx, avg[aatx][aarx]); + avgs = cmax(avgs, avg[l * n_rx + aarx]); + LOG_D(PHY, "nb_rb %d avg_%d_%d Power per SC is %d\n", nb_rb_pdsch, aarx, l, avg[l * n_rx + aarx]); LOG_D(PHY, "avgs Power per SC is %d\n", avgs); - median[aatx][aarx] = avg[aatx][aarx]; + median[l][aarx] = avg[l * n_rx + aarx]; } if (nl > 1) { nr_dlsch_channel_level_median(rx_size_symbol, dl_ch_estimates_ext, median, nl, n_rx, nb_re_pdsch); - for (int aatx = 0; aatx < nl; aatx++) { + for (int l = 0; l < nl; l++) { for (int aarx = 0; aarx < n_rx; aarx++) { - avgs = cmax(avgs, median[aatx][aarx]); + avgs = cmax(avgs, median[l][aarx]); } } } @@ -1032,41 +1018,6 @@ void nr_dlsch_scale_channel(uint32_t rx_size_symbol, } } - -/** @brief This function computes the average channel level over all allocated RBs - * and antennas (TX/RX) in order to compute output shift for compensated signal - @param rx_size_symbol - @param dl_ch_estimates_ext Channel estimates in allocated RBs - @param n_rx number of antennas in RX - @param n_tx number of antennas in TX - @param avg Pointer to average signal strength - @param len Number of allocated PDSCH REs -*/ -void nr_dlsch_channel_level(uint32_t rx_size_symbol, - int32_t dl_ch_estimates_ext[][rx_size_symbol], - uint8_t n_rx, - uint8_t n_tx, - int32_t avg[MAX_ANT][MAX_ANT], - uint32_t len) -{ - int16_t x = factor2(len); - int16_t y = (len) >> x; - - uint32_t nb_rb_0 = len / NR_NB_SC_PER_RB + ((len % NR_NB_SC_PER_RB) ? 1 : 0); - LOG_D(NR_PHY, "nb_rb_0 %d len %d = %d * 2^(%d)\n", nb_rb_0, len, y, x); - - for (int aatx = 0; aatx < n_tx; aatx++) { - for (int aarx = 0; aarx < n_rx; aarx++) { - - simde__m128i *dl_ch128 = (simde__m128i *)dl_ch_estimates_ext[(aatx * n_rx) + aarx]; - - //compute average level - avg[aatx][aarx] = simde_mm_average(dl_ch128, nb_rb_0 * 12, x, y); - //LOG_D(PHY, "Channel level: %d\n", avg[aatx][aarx]); - } - } -} - static void nr_dlsch_channel_level_median(uint32_t rx_size_symbol, int32_t dl_ch_estimates_ext[][rx_size_symbol], int32_t median[MAX_ANT][MAX_ANT], From b4796b4ddae0137da6d6535f07b288c50b86022f Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 15 Oct 2024 08:22:35 +0200 Subject: [PATCH 518/964] remove unused deinterleaving function from dlsch ue --- .../NR_UE_TRANSPORT/nr_dlsch_demodulation.c | 47 ------------------- .../NR_UE_TRANSPORT/nr_transport_proto_ue.h | 7 --- 2 files changed, 54 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c index 39f91d3b4e..1da2ef8d45 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c @@ -781,53 +781,6 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, return (0); } -void nr_dlsch_deinterleaving(uint8_t symbol, - uint8_t start_symbol, - uint16_t L, - uint16_t *llr, - uint16_t *llr_deint, - uint16_t nb_rb_pdsch) -{ - - uint32_t bundle_idx, N_bundle, R, C, r,c; - int32_t m,k; - uint8_t nb_re; - - R=2; - N_bundle = nb_rb_pdsch/L; - C=N_bundle/R; - - uint32_t bundle_deint[N_bundle]; - memset(bundle_deint, 0 , sizeof(bundle_deint)); - - printf("N_bundle %u L %d nb_rb_pdsch %d\n",N_bundle, L,nb_rb_pdsch); - - if (symbol==start_symbol) - nb_re = 6; - else - nb_re = 12; - - - AssertFatal(llr!=NULL,"nr_dlsch_deinterleaving: FATAL llr is Null\n"); - - - for (c =0; c< C; c++){ - for (r=0; r Date: Tue, 29 Jul 2025 16:54:43 +0200 Subject: [PATCH 519/964] Change tracy version to latest release --- CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 898b387237..5d756434c4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -285,7 +285,9 @@ add_boolean_option(UE_TIMING_TRACE False "Activate UE timing trace" ON) add_boolean_option(TRACY_ENABLE OFF "Enable tracy instrumentation" ON) if (TRACY_ENABLE) - CPMAddPackage("gh:wolfpld/tracy#v0.11.1") + # the tracy version here should match the tracy server version + # below is latest release as of this commit + CPMAddPackage("gh:wolfpld/tracy#0.12.2") endif() set (OCP_ITTI ${OPENAIR_DIR}/common/utils/ocp_itti) From c4f4f8d9198630872a3da9890538d9851b70f3ee Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Tue, 29 Jul 2025 16:56:17 +0200 Subject: [PATCH 520/964] Remove threequarter_fs, log_level; make functions static 2 functions with same name as static to make it clearer they are separate. remove unused copy of log_level global var. remove threequarter sampling variable from the radio board general configuration. The decision of sampling rate is made above. A better behavior can be done later, like ask to the radio board what sampling rate it can do,then use it to decide the appropiate sampling rate from the gNB configuration. In UE case, it is another issue, as the sampling rate would change after we decode SIB1, but also it is not developped yet. --- executables/lte-uesoftmodem.c | 3 ++- executables/nr-uesoftmodem.c | 3 +-- openair1/SIMULATION/NR_PHY/ulsim.c | 6 ++++-- radio/COMMON/common_lib.h | 4 ---- radio/ETHERNET/ethernet_lib.c | 1 - radio/fhi_72/oran-config.c | 2 -- 6 files changed, 7 insertions(+), 12 deletions(-) diff --git a/executables/lte-uesoftmodem.c b/executables/lte-uesoftmodem.c index ea48edd801..7de3014ee9 100644 --- a/executables/lte-uesoftmodem.c +++ b/executables/lte-uesoftmodem.c @@ -384,7 +384,8 @@ void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]) { } } -void init_openair0(LTE_DL_FRAME_PARMS *frame_parms,int rxgain) { +static void init_openair0(LTE_DL_FRAME_PARMS *frame_parms, int rxgain) +{ int card; int i; diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index 6ed407a507..8b331e4976 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -249,7 +249,7 @@ void set_options(int CC_id, PHY_VARS_NR_UE *UE){ } -void init_openair0() +static void init_openair0() { int card; int freq_off = 0; @@ -261,7 +261,6 @@ void init_openair0() for (card=0; cardthreequarter_fs; openair0_cfg[card].sample_rate = frame_parms->samples_per_subframe * 1e3; openair0_cfg[card].samples_per_frame = frame_parms->samples_per_frame; diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index b2b2dc38bb..b5bd02aefd 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -237,6 +237,8 @@ int main(int argc, char *argv[]) int max_ldpc_iterations = 5; int num_antennas_per_thread = 1; uint32_t log_format = 0; + int threequarter_fs = 0; + if ((uniqCfg = load_configmodule(argc, argv, CONFIG_ENABLECMDLINEONLY)) == 0) { exit_fun("[NR_ULSIM] Error, configuration module init failed\n"); } @@ -351,7 +353,7 @@ int main(int argc, char *argv[]) case 'k': printf("Setting threequarter_fs_flag\n"); - openair0_cfg[0].threequarter_fs= 1; + threequarter_fs = 1; break; case 'm': @@ -584,7 +586,7 @@ int main(int argc, char *argv[]) uint32_t samples; get_samplerate_and_bw(mu, N_RB_DL, - openair0_cfg[0].threequarter_fs, + threequarter_fs, &sampling_frequency, &samples, &tx_bandwidth, diff --git a/radio/COMMON/common_lib.h b/radio/COMMON/common_lib.h index 86d09b00fb..f928d554a8 100644 --- a/radio/COMMON/common_lib.h +++ b/radio/COMMON/common_lib.h @@ -204,8 +204,6 @@ typedef struct split7_config { typedef struct openair0_config { //! Module ID for this configuration int Mod_id; - //! device log level - int log_level; //! duplexing mode duplex_mode_t duplex_mode; //! number of downlink resource blocks @@ -292,8 +290,6 @@ typedef struct openair0_config { double rx_sample_rate; //! the sample rate for transmit. double tx_sample_rate; - //! check for threequarter sampling rate - int8_t threequarter_fs; //! Flag to indicate this configuration is for NR int nr_flag; //! NR band number diff --git a/radio/ETHERNET/ethernet_lib.c b/radio/ETHERNET/ethernet_lib.c index eb23ef28cc..2a4d021afc 100644 --- a/radio/ETHERNET/ethernet_lib.c +++ b/radio/ETHERNET/ethernet_lib.c @@ -617,7 +617,6 @@ void dump_dev(openair0_device *device) eth_state_t *eth = (eth_state_t*)device->priv; printf("Ethernet device interface %i configuration:\n" ,device->openair0_cfg->Mod_id); - printf(" Log level is %i :\n" ,device->openair0_cfg->log_level); printf(" RB number: %i, sample rate: %lf \n" , device->openair0_cfg->num_rb_dl, device->openair0_cfg->sample_rate); printf(" RAU configured for %i tx/%i rx channels)\n", diff --git a/radio/fhi_72/oran-config.c b/radio/fhi_72/oran-config.c index 4eff24aacf..89c1838fa3 100644 --- a/radio/fhi_72/oran-config.c +++ b/radio/fhi_72/oran-config.c @@ -884,8 +884,6 @@ static bool set_fh_config(void *mplane_api, int ru_idx, int num_rus, enum xran_c for (int i = 1; i < oai0->rx_num_channels; ++i) DevAssert(oai0->rx_freq[0] == oai0->rx_freq[i]); DevAssert(oai0->nr_band > 0); - AssertFatal(oai0->threequarter_fs == 0, "cannot use three-quarter sampling with O-RAN 7.2 split\n"); - paramdef_t FHconfigs[] = ORAN_FH_DESC; paramlist_def_t FH_ConfigList = {CONFIG_STRING_ORAN_FH}; char aprefix[MAX_OPTNAME_SIZE] = {0}; From 7cc35cf7e07c44d79511b2239e1836d5988433ed Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Tue, 29 Jul 2025 17:22:23 +0200 Subject: [PATCH 521/964] remove dead function --- openair1/PHY/INIT/nr_init.c | 1 - openair1/PHY/nr_phy_common/inc/nr_phy_common.h | 7 ------- openair1/PHY/nr_phy_common/src/nr_phy_common.c | 16 ---------------- 3 files changed, 24 deletions(-) diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c index dcdc4ee433..60bc63dac4 100644 --- a/openair1/PHY/INIT/nr_init.c +++ b/openair1/PHY/INIT/nr_init.c @@ -131,7 +131,6 @@ void phy_init_nr_gNB(PHY_VARS_gNB *gNB) crcTableInit(); init_byte2m128i(); - init_byte2bit16(); init_pucch2_luts(); nr_init_fde(); // Init array for frequency equalization of transform precoding of PUSCH diff --git a/openair1/PHY/nr_phy_common/inc/nr_phy_common.h b/openair1/PHY/nr_phy_common/inc/nr_phy_common.h index d52b6d9c43..134222d675 100644 --- a/openair1/PHY/nr_phy_common/inc/nr_phy_common.h +++ b/openair1/PHY/nr_phy_common/inc/nr_phy_common.h @@ -26,15 +26,8 @@ #include "PHY/NR_REFSIG/nr_refsig_common.h" #include "PHY/MODULATION/nr_modulation.h" -extern simde__m128i byte2bit16_lut[256]; -void init_byte2bit16(void); void init_byte2m128i(void); -static inline simde__m128i byte2bit16(uint8_t b) -{ - return byte2bit16_lut[b]; -} - typedef struct { int size; int ports; diff --git a/openair1/PHY/nr_phy_common/src/nr_phy_common.c b/openair1/PHY/nr_phy_common/src/nr_phy_common.c index e86652bd49..233645fb2d 100644 --- a/openair1/PHY/nr_phy_common/src/nr_phy_common.c +++ b/openair1/PHY/nr_phy_common/src/nr_phy_common.c @@ -26,22 +26,6 @@ #endif #define PEAK_DETECT_THRESHOLD 15 - -simde__m128i byte2bit16_lut[256]; -void init_byte2bit16(void) -{ - for (int s = 0; s < 256; s++) { - byte2bit16_lut[s] = simde_mm_insert_epi16(byte2bit16_lut[s], s & 1, 0); - byte2bit16_lut[s] = simde_mm_insert_epi16(byte2bit16_lut[s], (s >> 1) & 1, 1); - byte2bit16_lut[s] = simde_mm_insert_epi16(byte2bit16_lut[s], (s >> 2) & 1, 2); - byte2bit16_lut[s] = simde_mm_insert_epi16(byte2bit16_lut[s], (s >> 3) & 1, 3); - byte2bit16_lut[s] = simde_mm_insert_epi16(byte2bit16_lut[s], (s >> 4) & 1, 4); - byte2bit16_lut[s] = simde_mm_insert_epi16(byte2bit16_lut[s], (s >> 5) & 1, 5); - byte2bit16_lut[s] = simde_mm_insert_epi16(byte2bit16_lut[s], (s >> 6) & 1, 6); - byte2bit16_lut[s] = simde_mm_insert_epi16(byte2bit16_lut[s], (s >> 7) & 1, 7); - } -} - simde__m128i byte2m128i[256]; void init_byte2m128i(void) { From 2dae7b0db4787b4328d62bb2c36466a2823d0e85 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Tue, 29 Jul 2025 17:36:33 +0200 Subject: [PATCH 522/964] Limit visibilty of roundKeys --- openair3/NAS/UE/API/USIM/aka_functions.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair3/NAS/UE/API/USIM/aka_functions.c b/openair3/NAS/UE/API/USIM/aka_functions.c index d2e3fc36c5..1f461c3bbf 100644 --- a/openair3/NAS/UE/API/USIM/aka_functions.c +++ b/openair3/NAS/UE/API/USIM/aka_functions.c @@ -303,7 +303,7 @@ void ComputeOPc(const u8 op[16], u8 op_c_pP[16]) return; } /* end of function ComputeOPc */ /*-------------------- Rijndael round subkeys ---------------------*/ -u8 roundKeys[11][4][4]; +static u8 roundKeys[11][4][4]; /*--------------------- Rijndael S box table ----------------------*/ const u8 S[256] = { 99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, 118, 202, 130, 201, 125, 250, 89, 71, 240, From 4a3ebb30330f549c7b18e55d98651ee4324861ce Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Tue, 29 Jul 2025 17:58:00 +0200 Subject: [PATCH 523/964] remove dead code and replace unmanaged asn1_xer_print global variable by the appropriate existing debug flag --- CMakeLists.txt | 1 - doc/Doxyfile | 1 - executables/nr-cuup.c | 1 - openair2/E1AP/e1ap_common.h | 2 -- openair2/GNB_APP/gnb_paramdef.h | 3 -- openair2/M2AP/m2ap_common.c | 4 +-- openair2/M2AP/m2ap_common.h | 2 -- openair2/M2AP/m2ap_decoder.c | 2 +- openair2/M2AP/m2ap_encoder.c | 2 +- openair2/X2AP/x2ap_common.c | 6 ++-- openair2/X2AP/x2ap_common.h | 2 -- openair2/X2AP/x2ap_eNB_decoder.c | 2 +- openair2/X2AP/x2ap_eNB_encoder.c | 2 +- openair3/M3AP/m3ap_common.c | 4 +-- openair3/M3AP/m3ap_common.h | 2 -- openair3/M3AP/m3ap_decoder.c | 2 +- openair3/M3AP/m3ap_encoder.c | 2 +- openair3/NGAP/ngap_common.c | 2 -- openair3/NGAP/ngap_common.h | 3 -- openair3/NGAP/ngap_gNB_encoder.c | 2 +- openair3/NGAP/ngap_gNB_nas_procedures.c | 4 +-- openair3/S1AP/s1ap_common.c | 41 ------------------------- openair3/S1AP/s1ap_common.h | 8 ----- openair3/S1AP/s1ap_eNB_encoder.c | 6 ++-- openair3/TEST/test_s1ap.c | 4 --- 25 files changed, 19 insertions(+), 91 deletions(-) delete mode 100644 openair3/S1AP/s1ap_common.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 5d756434c4..2544c86d7a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -339,7 +339,6 @@ target_link_libraries(nr_rrc PUBLIC asn1_nr_rrc asn1_lte_rrc) set(S1AP_DIR ${OPENAIR3_DIR}/S1AP) include_directories ("${S1AP_DIR}") add_library(s1ap - ${S1AP_DIR}/s1ap_common.c ${S1AP_DIR}/s1ap_eNB.c ${S1AP_DIR}/s1ap_eNB_context_management_procedures.c ${S1AP_DIR}/s1ap_eNB_decoder.c diff --git a/doc/Doxyfile b/doc/Doxyfile index f128e3eb88..e67078a043 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -1021,7 +1021,6 @@ INPUT = \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/S1AP/s1ap_eNB_ue_context.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/S1AP/s1ap_eNB_management_procedures.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/S1AP/s1ap_eNB_context_management_procedures.c \ -@CMAKE_CURRENT_SOURCE_DIR@/../openair3/S1AP/s1ap_common.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/S1AP/s1ap_eNB_decoder.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/S1AP/s1ap_eNB_management_procedures.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/S1AP/s1ap_eNB_handlers.h \ diff --git a/executables/nr-cuup.c b/executables/nr-cuup.c index 6467683cac..403f78ddb3 100644 --- a/executables/nr-cuup.c +++ b/executables/nr-cuup.c @@ -37,7 +37,6 @@ RAN_CONTEXT_t RC; THREAD_STRUCT thread_struct; uint64_t downlink_frequency[MAX_NUM_CCs][4]; int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; -int asn1_xer_print; int oai_exit = 0; instance_t CUuniqInstance = 0; diff --git a/openair2/E1AP/e1ap_common.h b/openair2/E1AP/e1ap_common.h index 452762965c..6c556a6cc6 100644 --- a/openair2/E1AP/e1ap_common.h +++ b/openair2/E1AP/e1ap_common.h @@ -41,8 +41,6 @@ typedef struct e1ap_upcp_inst_s { e1ap_net_config_t net_config; } e1ap_upcp_inst_t; -extern int asn1_xer_print; - // forward declaration so we don't require E1AP ASN.1 when including this // header struct E1AP_E1AP_PDU; diff --git a/openair2/GNB_APP/gnb_paramdef.h b/openair2/GNB_APP/gnb_paramdef.h index db04c5a8da..b751d78733 100644 --- a/openair2/GNB_APP/gnb_paramdef.h +++ b/openair2/GNB_APP/gnb_paramdef.h @@ -49,9 +49,6 @@ #define GNB_CONF_STRING_OTG_APP_TYPE "app_type" #define GNB_CONF_STRING_OTG_BG_TRAFFIC "bg_traffic" -extern int asn_debug; -extern int asn1_xer_print; - #ifdef LIBCONFIG_LONG #define libconfig_int long #else diff --git a/openair2/M2AP/m2ap_common.c b/openair2/M2AP/m2ap_common.c index aa090d124d..d9183df6fb 100644 --- a/openair2/M2AP/m2ap_common.c +++ b/openair2/M2AP/m2ap_common.c @@ -47,7 +47,7 @@ ssize_t m2ap_generate_initiating_message( pdu.choice.initiatingMessage.criticality = criticality; ANY_fromType_aper((ANY_t *)&pdu.choice.initiatingMessage.value, td, sptr); - if (asn1_xer_print) { + if (LOG_DEBUGFLAG(DEBUG_ASN1)) { xer_fprint(stdout, &asn_DEF_M2AP_M2AP_PDU, (void *)&pdu); } @@ -80,7 +80,7 @@ ssize_t m2ap_generate_unsuccessfull_outcome( pdu.choice.successfulOutcome.criticality = criticality; ANY_fromType_aper((ANY_t *)&pdu.choice.successfulOutcome.value, td, sptr); - if (asn1_xer_print) { + if (LOG_DEBUGFLAG(DEBUG_ASN1)) { xer_fprint(stdout, &asn_DEF_M2AP_M2AP_PDU, (void *)&pdu); } diff --git a/openair2/M2AP/m2ap_common.h b/openair2/M2AP/m2ap_common.h index 266b303518..a875d8d078 100644 --- a/openair2/M2AP/m2ap_common.h +++ b/openair2/M2AP/m2ap_common.h @@ -50,8 +50,6 @@ # define M2AP_PORT 36423 #endif -extern int asn1_xer_print; - #include "common/utils/LOG/log.h" #include "m2ap_default_values.h" #define M2AP_INFO(x, args...) LOG_I(M2AP, x, ##args) diff --git a/openair2/M2AP/m2ap_decoder.c b/openair2/M2AP/m2ap_decoder.c index 1237c4ec8e..4abd43f564 100644 --- a/openair2/M2AP/m2ap_decoder.c +++ b/openair2/M2AP/m2ap_decoder.c @@ -165,7 +165,7 @@ int m2ap_decode_pdu(M2AP_M2AP_PDU_t *pdu, const uint8_t *const buffer, uint32_t length, 0, 0); - if (asn1_xer_print) { + if (LOG_DEBUGFLAG(DEBUG_ASN1)) { xer_fprint(stdout, &asn_DEF_M2AP_M2AP_PDU, pdu); } diff --git a/openair2/M2AP/m2ap_encoder.c b/openair2/M2AP/m2ap_encoder.c index 8f798ff55c..81a3bfce92 100644 --- a/openair2/M2AP/m2ap_encoder.c +++ b/openair2/M2AP/m2ap_encoder.c @@ -44,7 +44,7 @@ int m2ap_encode_pdu(M2AP_M2AP_PDU_t *pdu, uint8_t **buffer, uint32_t *len) DevAssert(buffer != NULL); DevAssert(len != NULL); - if (asn1_xer_print) { + if (LOG_DEBUGFLAG(DEBUG_ASN1)) { xer_fprint(stdout, &asn_DEF_M2AP_M2AP_PDU, (void *)pdu); } diff --git a/openair2/X2AP/x2ap_common.c b/openair2/X2AP/x2ap_common.c index a687b90666..0fc63b7de5 100644 --- a/openair2/X2AP/x2ap_common.c +++ b/openair2/X2AP/x2ap_common.c @@ -47,7 +47,7 @@ ssize_t x2ap_generate_initiating_message( pdu.choice.initiatingMessage.criticality = criticality; ANY_fromType_aper((ANY_t *)&pdu.choice.initiatingMessage.value, td, sptr); - if (asn1_xer_print) { + if (LOG_DEBUGFLAG(DEBUG_ASN1)) { xer_fprint(stdout, &asn_DEF_X2AP_X2AP_PDU, (void *)&pdu); } @@ -79,7 +79,7 @@ ssize_t x2ap_generate_successfull_outcome( pdu.choice.successfulOutcome.criticality = criticality; ANY_fromType_aper((ANY_t *)&pdu.choice.successfulOutcome.value, td, sptr); - if (asn1_xer_print) { + if (LOG_DEBUGFLAG(DEBUG_ASN1)) { xer_fprint(stdout, &asn_DEF_X2AP_X2AP_PDU, (void *)&pdu); } @@ -111,7 +111,7 @@ ssize_t x2ap_generate_unsuccessfull_outcome( pdu.choice.successfulOutcome.criticality = criticality; ANY_fromType_aper((ANY_t *)&pdu.choice.successfulOutcome.value, td, sptr); - if (asn1_xer_print) { + if (LOG_DEBUGFLAG(DEBUG_ASN1)) { xer_fprint(stdout, &asn_DEF_X2AP_X2AP_PDU, (void *)&pdu); } diff --git a/openair2/X2AP/x2ap_common.h b/openair2/X2AP/x2ap_common.h index 81880cb71c..36dfe24287 100644 --- a/openair2/X2AP/x2ap_common.h +++ b/openair2/X2AP/x2ap_common.h @@ -49,8 +49,6 @@ # define X2AP_PORT 36422 #endif -extern int asn1_xer_print; - #include "common/utils/LOG/log.h" #define X2AP_INFO(x, args...) LOG_I(X2AP, x, ##args) #define X2AP_ERROR(x, args...) LOG_E(X2AP, x, ##args) diff --git a/openair2/X2AP/x2ap_eNB_decoder.c b/openair2/X2AP/x2ap_eNB_decoder.c index 6d7897bf14..81cb77dfef 100644 --- a/openair2/X2AP/x2ap_eNB_decoder.c +++ b/openair2/X2AP/x2ap_eNB_decoder.c @@ -156,7 +156,7 @@ int x2ap_eNB_decode_pdu(X2AP_X2AP_PDU_t *pdu, const uint8_t *const buffer, uint3 length, 0, 0); - if (asn1_xer_print) { + if (LOG_DEBUGFLAG(DEBUG_ASN1)) { xer_fprint(stdout, &asn_DEF_X2AP_X2AP_PDU, pdu); } diff --git a/openair2/X2AP/x2ap_eNB_encoder.c b/openair2/X2AP/x2ap_eNB_encoder.c index 8b1c030d35..a82eb03f9a 100644 --- a/openair2/X2AP/x2ap_eNB_encoder.c +++ b/openair2/X2AP/x2ap_eNB_encoder.c @@ -44,7 +44,7 @@ int x2ap_eNB_encode_pdu(X2AP_X2AP_PDU_t *pdu, uint8_t **buffer, uint32_t *len) DevAssert(buffer != NULL); DevAssert(len != NULL); - if (asn1_xer_print) { + if (LOG_DEBUGFLAG(DEBUG_ASN1)) { xer_fprint(stdout, &asn_DEF_X2AP_X2AP_PDU, (void *)pdu); } diff --git a/openair3/M3AP/m3ap_common.c b/openair3/M3AP/m3ap_common.c index e43275d96c..669d7eaa5e 100644 --- a/openair3/M3AP/m3ap_common.c +++ b/openair3/M3AP/m3ap_common.c @@ -47,7 +47,7 @@ ssize_t m3ap_generate_initiating_message( pdu.choice.initiatingMessage.criticality = criticality; ANY_fromType_aper((ANY_t *)&pdu.choice.initiatingMessage.value, td, sptr); - if (asn1_xer_print) { + if (LOG_DEBUGFLAG(DEBUG_ASN1)) { xer_fprint(stdout, &asn_DEF_M3AP_M3AP_PDU, (void *)&pdu); } @@ -80,7 +80,7 @@ ssize_t m3ap_generate_unsuccessfull_outcome( pdu.choice.successfulOutcome.criticality = criticality; ANY_fromType_aper((ANY_t *)&pdu.choice.successfulOutcome.value, td, sptr); - if (asn1_xer_print) { + if (LOG_DEBUGFLAG(DEBUG_ASN1)) { xer_fprint(stdout, &asn_DEF_M3AP_M3AP_PDU, (void *)&pdu); } diff --git a/openair3/M3AP/m3ap_common.h b/openair3/M3AP/m3ap_common.h index 7c8ea18a5d..f5acb6bdf5 100644 --- a/openair3/M3AP/m3ap_common.h +++ b/openair3/M3AP/m3ap_common.h @@ -48,8 +48,6 @@ # define M3AP_PORT 36444 #endif -extern int asn1_xer_print; - #include "common/utils/LOG/log.h" #include "m3ap_default_values.h" #define M3AP_INFO(x, args...) LOG_I(M3AP, x, ##args) diff --git a/openair3/M3AP/m3ap_decoder.c b/openair3/M3AP/m3ap_decoder.c index cee0a5ff41..36c8f64fae 100644 --- a/openair3/M3AP/m3ap_decoder.c +++ b/openair3/M3AP/m3ap_decoder.c @@ -188,7 +188,7 @@ int m3ap_decode_pdu(M3AP_M3AP_PDU_t *pdu, const uint8_t *const buffer, uint32_t length, 0, 0); - if (asn1_xer_print) { + if (LOG_DEBUGFLAG(DEBUG_ASN1)) { xer_fprint(stdout, &asn_DEF_M3AP_M3AP_PDU, pdu); } diff --git a/openair3/M3AP/m3ap_encoder.c b/openair3/M3AP/m3ap_encoder.c index 2e1cbf80af..86a710ca90 100644 --- a/openair3/M3AP/m3ap_encoder.c +++ b/openair3/M3AP/m3ap_encoder.c @@ -44,7 +44,7 @@ int m3ap_encode_pdu(M3AP_M3AP_PDU_t *pdu, uint8_t **buffer, uint32_t *len) DevAssert(buffer != NULL); DevAssert(len != NULL); - if (asn1_xer_print) { + if (LOG_DEBUGFLAG(DEBUG_ASN1)) { xer_fprint(stdout, &asn_DEF_M3AP_M3AP_PDU, (void *)pdu); } diff --git a/openair3/NGAP/ngap_common.c b/openair3/NGAP/ngap_common.c index 7b960fed0b..82c2ccaf2a 100644 --- a/openair3/NGAP/ngap_common.c +++ b/openair3/NGAP/ngap_common.c @@ -31,8 +31,6 @@ #include "conversions.h" #include "ngap_common.h" -int asn1_xer_print = 0; - void encode_ngap_cause(NGAP_Cause_t *out, const ngap_cause_t *in) { switch (in->type) { diff --git a/openair3/NGAP/ngap_common.h b/openair3/NGAP/ngap_common.h index 82a8fe9234..dd7fdebc54 100644 --- a/openair3/NGAP/ngap_common.h +++ b/openair3/NGAP/ngap_common.h @@ -48,9 +48,6 @@ #define NGAP_UE_ID_FMT "0x%06"PRIX32 -extern int asn_debug; -extern int asn1_xer_print; - # include "common/utils/LOG/log.h" # include "ngap_gNB_default_values.h" # define NGAP_ERROR(x, args...) LOG_E(NGAP, x, ##args) diff --git a/openair3/NGAP/ngap_gNB_encoder.c b/openair3/NGAP/ngap_gNB_encoder.c index ee3b37e07d..c3c095541d 100644 --- a/openair3/NGAP/ngap_gNB_encoder.c +++ b/openair3/NGAP/ngap_gNB_encoder.c @@ -115,7 +115,7 @@ int ngap_gNB_encode_pdu(NGAP_NGAP_PDU_t *pdu, uint8_t **buffer, uint32_t *len) DevAssert(pdu != NULL); DevAssert(buffer != NULL); DevAssert(len != NULL); - if (asn1_xer_print) { + if (LOG_DEBUGFLAG(DEBUG_ASN1)) { xer_fprint(stdout, &asn_DEF_NGAP_NGAP_PDU, (void *)pdu); } switch (pdu->present) { diff --git a/openair3/NGAP/ngap_gNB_nas_procedures.c b/openair3/NGAP/ngap_gNB_nas_procedures.c index 1aafeca8c9..b291f6b96c 100644 --- a/openair3/NGAP/ngap_gNB_nas_procedures.c +++ b/openair3/NGAP/ngap_gNB_nas_procedures.c @@ -690,7 +690,7 @@ int ngap_gNB_initial_ctxt_resp(instance_t instance, ngap_initial_context_setup_r // ie->value.choice.CriticalityDiagnostics =; } - if (asn1_xer_print) { + if (LOG_DEBUGFLAG(DEBUG_ASN1)) { xer_fprint(stdout, &asn_DEF_NGAP_NGAP_PDU, &pdu); } @@ -772,7 +772,7 @@ int ngap_gNB_initial_ctxt_fail(instance_t instance, ngap_initial_context_setup_f ie->value.present = NGAP_InitialContextSetupFailureIEs__value_PR_Cause; encode_ngap_cause(&ie->value.choice.Cause, &initial_ctxt_fail->cause); } - if (asn1_xer_print) { + if (LOG_DEBUGFLAG(DEBUG_ASN1)) { xer_fprint(stdout, &asn_DEF_NGAP_NGAP_PDU, &pdu); } if (ngap_gNB_encode_pdu(&pdu, &buffer, &length) < 0) { diff --git a/openair3/S1AP/s1ap_common.c b/openair3/S1AP/s1ap_common.c deleted file mode 100644 index d31c6e5839..0000000000 --- a/openair3/S1AP/s1ap_common.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.openairinterface.org/?page_id=698 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -/*! \file s1ap_common.c - * \brief s1ap procedures for both eNB and MME - * \author Sebastien ROUX and Navid Nikaein - * \email navid.nikaein@eurecom.fr - * \date 2012-2015 - * \version 0.1 - */ - -#include - -#include "s1ap_common.h" -#include "S1AP_S1AP-PDU.h" - - -int asn1_xer_print = 0; - - -void s1ap_handle_criticality(S1AP_Criticality_t criticality) -{ -} diff --git a/openair3/S1AP/s1ap_common.h b/openair3/S1AP/s1ap_common.h index 797bc7be8a..7ef7e589ca 100644 --- a/openair3/S1AP/s1ap_common.h +++ b/openair3/S1AP/s1ap_common.h @@ -52,8 +52,6 @@ #define S1AP_UE_ID_FMT "0x%06"PRIX32 -extern int asn1_xer_print; - #include "common/utils/LOG/log.h" #include "s1ap_eNB_default_values.h" #define S1AP_ERROR(x, args...) LOG_E(S1AP, x, ##args) @@ -89,10 +87,4 @@ extern int asn1_xer_print; **/ typedef int (*s1ap_message_decoded_callback)(sctp_assoc_t assoc_id, uint32_t stream, S1AP_S1AP_PDU_t *pdu); -/** \brief Handle criticality - \param criticality Criticality of the IE - @returns void - **/ -void s1ap_handle_criticality(S1AP_Criticality_t criticality); -/** @}*/ #endif /* S1AP_COMMON_H_ */ diff --git a/openair3/S1AP/s1ap_eNB_encoder.c b/openair3/S1AP/s1ap_eNB_encoder.c index 8317f02731..6ff837a7f1 100644 --- a/openair3/S1AP/s1ap_eNB_encoder.c +++ b/openair3/S1AP/s1ap_eNB_encoder.c @@ -129,7 +129,7 @@ int s1ap_eNB_encode_initiating(S1AP_S1AP_PDU_t *pdu, return -1; } - if (asn1_xer_print) { + if (LOG_DEBUGFLAG(DEBUG_ASN1)) { xer_fprint(stdout, &asn_DEF_S1AP_S1AP_PDU, (void *)pdu); } @@ -183,7 +183,7 @@ int s1ap_eNB_encode_successfull_outcome(S1AP_S1AP_PDU_t *pdu, return -1; } - if (asn1_xer_print) { + if (LOG_DEBUGFLAG(DEBUG_ASN1)) { xer_fprint(stdout, &asn_DEF_S1AP_S1AP_PDU, (void *)pdu); } @@ -214,7 +214,7 @@ int s1ap_eNB_encode_unsuccessfull_outcome(S1AP_S1AP_PDU_t *pdu, return -1; } - if (asn1_xer_print) { + if (LOG_DEBUGFLAG(DEBUG_ASN1)) { xer_fprint(stdout, &asn_DEF_S1AP_S1AP_PDU, (void *)pdu); } diff --git a/openair3/TEST/test_s1ap.c b/openair3/TEST/test_s1ap.c index 8e61c338ac..1ecb30d476 100644 --- a/openair3/TEST/test_s1ap.c +++ b/openair3/TEST/test_s1ap.c @@ -154,10 +154,6 @@ void doit (void) { int i; break_on_error = 1; - - // asn1_xer_print = 1; - // asn_debug = 1; - for (i = 0; i < sizeof(s1ap_test) / sizeof(s1ap_test_t); i++) { S1AP_S1AP_PDU_t pdu; uint8_t *buffer; From c2d9f17242bd845b5306d7593ff5d5724766e2e1 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Tue, 29 Jul 2025 17:59:53 +0200 Subject: [PATCH 524/964] remove a dependancy of gNB to LTE that is not used and adds global vars to gNB --- executables/nr-softmodem.c | 1 - 1 file changed, 1 deletion(-) diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c index 5cc5e3a4fc..261dc9a66b 100644 --- a/executables/nr-softmodem.c +++ b/executables/nr-softmodem.c @@ -24,7 +24,6 @@ #include "common/config/config_userapi.h" #include "common/utils/load_module_shlib.h" -#include "RRC/LTE/rrc_vars.h" #ifdef SMBV #include "PHY/TOOLS/smbv.h" unsigned short config_frames[4] = {2,9,11,13}; From 4b47d26ea291fdd71dd5d8384aa4fdab8fb89999 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Tue, 29 Jul 2025 18:07:51 +0200 Subject: [PATCH 525/964] remove dirty and unused functions with global vars (not working anyway) --- executables/lte-softmodem.c | 49 ----------------------------------- executables/lte-uesoftmodem.c | 49 ----------------------------------- executables/nr-softmodem.c | 46 -------------------------------- 3 files changed, 144 deletions(-) diff --git a/executables/lte-softmodem.c b/executables/lte-softmodem.c index 6a7e607586..3034512b2c 100644 --- a/executables/lte-softmodem.c +++ b/executables/lte-softmodem.c @@ -204,55 +204,6 @@ void nr_slot_select() {}; void NR_UL_indication(NR_UL_IND_t *UL_INFO) {}; void gNB_dlsch_ulsch_scheduler() {}; -/*---------------------BMC: timespec helpers -----------------------------*/ - -struct timespec min_diff_time = { .tv_sec = 0, .tv_nsec = 0 }; -struct timespec max_diff_time = { .tv_sec = 0, .tv_nsec = 0 }; - -struct timespec clock_difftime(struct timespec start, struct timespec end) { - struct timespec temp; - - if ((end.tv_nsec-start.tv_nsec)<0) { - temp.tv_sec = end.tv_sec-start.tv_sec-1; - temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec; - } else { - temp.tv_sec = end.tv_sec-start.tv_sec; - temp.tv_nsec = end.tv_nsec-start.tv_nsec; - } - - return temp; -} - -void print_difftimes(void) { -#ifdef DEBUG - printf("difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec); -#else - LOG_I(HW,"difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec); -#endif -} - -void update_difftimes(struct timespec start, struct timespec end) { - struct timespec diff_time = { .tv_sec = 0, .tv_nsec = 0 }; - int changed = 0; - diff_time = clock_difftime(start, end); - - if ((min_diff_time.tv_nsec == 0) || (diff_time.tv_nsec < min_diff_time.tv_nsec)) { - min_diff_time.tv_nsec = diff_time.tv_nsec; - changed = 1; - } - - if ((max_diff_time.tv_nsec == 0) || (diff_time.tv_nsec > max_diff_time.tv_nsec)) { - max_diff_time.tv_nsec = diff_time.tv_nsec; - changed = 1; - } - -#if 1 - - if (changed) print_difftimes(); - -#endif -} - /*------------------------------------------------------------------------*/ unsigned int build_rflocal(int txi, int txq, int rxi, int rxq) { diff --git a/executables/lte-uesoftmodem.c b/executables/lte-uesoftmodem.c index 7de3014ee9..b212ceb3f1 100644 --- a/executables/lte-uesoftmodem.c +++ b/executables/lte-uesoftmodem.c @@ -174,55 +174,6 @@ instance_t CUuniqInstance=0; /* forward declarations */ void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]); -/*---------------------BMC: timespec helpers -----------------------------*/ - -struct timespec min_diff_time = { .tv_sec = 0, .tv_nsec = 0 }; -struct timespec max_diff_time = { .tv_sec = 0, .tv_nsec = 0 }; - -struct timespec clock_difftime(struct timespec start, struct timespec end) { - struct timespec temp; - - if ((end.tv_nsec-start.tv_nsec)<0) { - temp.tv_sec = end.tv_sec-start.tv_sec-1; - temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec; - } else { - temp.tv_sec = end.tv_sec-start.tv_sec; - temp.tv_nsec = end.tv_nsec-start.tv_nsec; - } - - return temp; -} - -void print_difftimes(void) { -#ifdef DEBUG - printf("difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec); -#else - LOG_I(HW,"difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec); -#endif -} - -void update_difftimes(struct timespec start, struct timespec end) { - struct timespec diff_time = { .tv_sec = 0, .tv_nsec = 0 }; - int changed = 0; - diff_time = clock_difftime(start, end); - - if ((min_diff_time.tv_nsec == 0) || (diff_time.tv_nsec < min_diff_time.tv_nsec)) { - min_diff_time.tv_nsec = diff_time.tv_nsec; - changed = 1; - } - - if ((max_diff_time.tv_nsec == 0) || (diff_time.tv_nsec > max_diff_time.tv_nsec)) { - max_diff_time.tv_nsec = diff_time.tv_nsec; - changed = 1; - } - -#if 1 - - if (changed) print_difftimes(); - -#endif -} - /*------------------------------------------------------------------------*/ unsigned int build_rflocal(int txi, int txq, int rxi, int rxq) { diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c index 261dc9a66b..c3875bf267 100644 --- a/executables/nr-softmodem.c +++ b/executables/nr-softmodem.c @@ -129,52 +129,6 @@ void pdcp_run(const protocol_ctxt_t *const ctxt_pP) abort(); } -/*---------------------BMC: timespec helpers -----------------------------*/ - -struct timespec min_diff_time = { .tv_sec = 0, .tv_nsec = 0 }; -struct timespec max_diff_time = { .tv_sec = 0, .tv_nsec = 0 }; - -struct timespec clock_difftime(struct timespec start, struct timespec end) { - struct timespec temp; - - if ((end.tv_nsec-start.tv_nsec)<0) { - temp.tv_sec = end.tv_sec-start.tv_sec-1; - temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec; - } else { - temp.tv_sec = end.tv_sec-start.tv_sec; - temp.tv_nsec = end.tv_nsec-start.tv_nsec; - } - - return temp; -} - -void print_difftimes(void) -{ - LOG_I(HW, "difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec); -} - -void update_difftimes(struct timespec start, struct timespec end) { - struct timespec diff_time = { .tv_sec = 0, .tv_nsec = 0 }; - int changed = 0; - diff_time = clock_difftime(start, end); - - if ((min_diff_time.tv_nsec == 0) || (diff_time.tv_nsec < min_diff_time.tv_nsec)) { - min_diff_time.tv_nsec = diff_time.tv_nsec; - changed = 1; - } - - if ((max_diff_time.tv_nsec == 0) || (diff_time.tv_nsec > max_diff_time.tv_nsec)) { - max_diff_time.tv_nsec = diff_time.tv_nsec; - changed = 1; - } - -#if 1 - - if (changed) print_difftimes(); - -#endif -} - /*------------------------------------------------------------------------*/ unsigned int build_rflocal(int txi, int txq, int rxi, int rxq) { From 2bda52b054faf2f0e99148d5d0d2416d25267fb3 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Tue, 29 Jul 2025 19:11:04 +0200 Subject: [PATCH 526/964] rename a global "ru" in root_unit and include correctly the .h file, that leads to mistakes fixes --- openair1/PHY/LTE_TRANSPORT/prach.c | 7 ++- openair1/PHY/LTE_TRANSPORT/prach_common.c | 13 ++--- openair1/PHY/LTE_TRANSPORT/prach_extern.h | 14 ++---- openair1/PHY/LTE_UE_TRANSPORT/prach_ue.c | 47 +++++++------------ .../PHY/LTE_UE_TRANSPORT/transport_proto_ue.h | 3 +- openair1/PHY/defs_UE.h | 2 +- openair1/PHY/defs_eNB.h | 4 +- 7 files changed, 34 insertions(+), 56 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/prach.c b/openair1/PHY/LTE_TRANSPORT/prach.c index e220549045..90c9d63925 100644 --- a/openair1/PHY/LTE_TRANSPORT/prach.c +++ b/openair1/PHY/LTE_TRANSPORT/prach.c @@ -69,8 +69,7 @@ void rx_prach0(PHY_VARS_eNB *eNB, uint32_t preamble_shift2; uint16_t preamble_index0=0,n_shift_ra=0,n_shift_ra_bar; uint16_t d_start=0; - uint16_t numshift=0; - uint16_t *prach_root_sequence_map; + uint16_t numshift = 0; uint8_t not_found; int k=0; uint16_t u; @@ -221,7 +220,7 @@ void rx_prach0(PHY_VARS_eNB *eNB, if (eNB) start_meas(&eNB->rx_prach); - prach_root_sequence_map = (prach_fmt < 4) ? prach_root_sequence_map0_3 : prach_root_sequence_map4; + const uint16_t *prach_root_sequence_map = (prach_fmt < 4) ? prach_root_sequence_map0_3 : prach_root_sequence_map4; // PDP is oversampled, e.g. 1024 sample instead of 839 // Adapt the NCS (zero-correlation zones) with oversampling factor e.g. 1024/839 NCS2 = (N_ZC==839) ? ((NCS<<10)/839) : ((NCS<<8)/139); @@ -495,7 +494,7 @@ void rx_prach0(PHY_VARS_eNB *eNB, new_dft = 0; if (br_flag == 1) { - Xu=(c16_t *)eNB->X_u_br[ce_level][preamble_offset-first_nonzero_root_idx]; + Xu = eNB->X_u_br[ce_level][preamble_offset - first_nonzero_root_idx]; prach_ifft = prach_ifftp[prach_ifft_cnt++]; if (eNB->prach_vars_br.repetition_number[ce_level]==1) memset(prach_ifft,0,((N_ZC==839)?2048:256)*sizeof(int32_t)); diff --git a/openair1/PHY/LTE_TRANSPORT/prach_common.c b/openair1/PHY/LTE_TRANSPORT/prach_common.c index 2d9ef9d712..0939398c60 100644 --- a/openair1/PHY/LTE_TRANSPORT/prach_common.c +++ b/openair1/PHY/LTE_TRANSPORT/prach_common.c @@ -35,12 +35,13 @@ #include "PHY/phy_extern_ue.h" #include "common/utils/LOG/vcd_signal_dumper.h" #include "common/utils/lte/prach_utils.h" +#include "openair1/PHY/LTE_TRANSPORT/prach_extern.h" const uint16_t NCS_unrestricted[16] = {0, 13, 15, 18, 22, 26, 32, 38, 46, 59, 76, 93, 119, 167, 279, 419}; const uint16_t NCS_restricted[15] = {15, 18, 22, 26, 32, 38, 46, 55, 68, 82, 100, 128, 158, 202, 237}; // high-speed case const uint16_t NCS_4[7] = {2, 4, 6, 8, 10, 12, 15}; -int16_t ru[2*839]; // quantized roots of unity +c16_t root_unit[839]; // quantized roots of unity static uint32_t ZC_inv[839]; // multiplicative inverse for roots u uint16_t du[838]; @@ -367,13 +368,13 @@ int is_prach_subframe(LTE_DL_FRAME_PARMS *frame_parms, uint32_t frame, uint8_t s return(prach_mask); } - void compute_prach_seq(uint16_t rootSequenceIndex, uint8_t prach_ConfigIndex, uint8_t zeroCorrelationZoneConfig, uint8_t highSpeedFlag, frame_type_t frame_type, - uint32_t X_u[64][839]) { + c16_t X_u[64][839]) +{ // Compute DFT of x_u => X_u[k] = x_u(inv(u)*k)^* X_u[k] = exp(j\pi u*inv(u)*k*(inv(u)*k+1)/N_ZC) unsigned int k,inv_u,i,NCS=0,num_preambles; int N_ZC; @@ -495,7 +496,7 @@ void compute_prach_seq(uint16_t rootSequenceIndex, for (k=0; kframe_parms.prach_config_common.prach_ConfigInfo.prach_ConfigIndex, ue->frame_parms.prach_config_common.prach_ConfigInfo.prach_FreqOffset, tdd_mapindex, Nf); - prach_root_sequence_map = (prach_fmt<4) ? prach_root_sequence_map0_3 : prach_root_sequence_map4; + const uint16_t *prach_root_sequence_map = (prach_fmt < 4) ? prach_root_sequence_map0_3 : prach_root_sequence_map4; /* // this code is not part of get_prach_prb_offset if (frame_type == TDD) { // TDD @@ -215,20 +210,6 @@ int32_t generate_prach( PHY_VARS_UE *ue, uint8_t eNB_id, uint8_t subframe, uint1 #endif // nsymb = (frame_parms->Ncp==0) ? 14:12; // subframe_offset = (unsigned int)frame_parms->ofdm_symbol_size*subframe*nsymb; - k = (12*n_ra_prb) - 6*ue->frame_parms.N_RB_UL; - - if (k<0) - k+=ue->frame_parms.ofdm_symbol_size; - - k*=12; - k+=13; - Xu = (int16_t *)ue->X_u[preamble_offset-first_nonzero_root_idx]; - /* - k+=(12*ue->frame_parms.first_carrier_offset); - if (k>(12*ue->frame_parms.ofdm_symbol_size)) - k-=(12*ue->frame_parms.ofdm_symbol_size); - */ - k*=2; switch (ue->frame_parms.N_RB_UL) { case 6: @@ -259,20 +240,26 @@ int32_t generate_prach( PHY_VARS_UE *ue, uint8_t eNB_id, uint8_t subframe, uint1 break; } + { + int k = (12 * n_ra_prb) - 6 * ue->frame_parms.N_RB_UL; - for (offset=0,offset2=0; offset= N_ZC) - offset2 -= N_ZC; + if (k < 0) + k += ue->frame_parms.ofdm_symbol_size; - Xu_re = (((int32_t)Xu[offset<<1]*amp)>>15); - Xu_im = (((int32_t)Xu[1+(offset<<1)]*amp)>>15); - prachF[k++]= ((Xu_re*ru[offset2<<1]) - (Xu_im*ru[1+(offset2<<1)]))>>15; - prachF[k++]= ((Xu_im*ru[offset2<<1]) + (Xu_re*ru[1+(offset2<<1)]))>>15; + k *= 12; + k += 13; + c16_t *Xu_ue = ue->X_u[preamble_offset - first_nonzero_root_idx]; + c16_t *complex_prachF = (c16_t *)prachF; + for (int offset = 0, offset2 = 0; offset < N_ZC; offset++, offset2 += preamble_shift) { + if (offset2 >= N_ZC) + offset2 -= N_ZC; + c16_t Xu = c16mulRealShift(*Xu_ue++, amp, 15); + complex_prachF[k++] = c16mulShift(Xu, root_unit[offset2], 15); - if (k==(12*2*ue->frame_parms.ofdm_symbol_size)) - k=0; + if (k == 12 * ue->frame_parms.ofdm_symbol_size) + k = 0; + } } - switch (prach_fmt) { case 0: Ncp = 3168; diff --git a/openair1/PHY/LTE_UE_TRANSPORT/transport_proto_ue.h b/openair1/PHY/LTE_UE_TRANSPORT/transport_proto_ue.h index 9aab56e52a..06bf87fc74 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/transport_proto_ue.h +++ b/openair1/PHY/LTE_UE_TRANSPORT/transport_proto_ue.h @@ -1649,8 +1649,7 @@ void compute_prach_seq(uint16_t rootSequenceIndex, uint8_t zeroCorrelationZoneConfig, uint8_t highSpeedFlag, frame_type_t frame_type, - uint32_t X_u[64][839]); - + c16_t X_u[64][839]); void init_prach_tables(int N_ZC); diff --git a/openair1/PHY/defs_UE.h b/openair1/PHY/defs_UE.h index 17ae02610e..20d5a9ab8d 100644 --- a/openair1/PHY/defs_UE.h +++ b/openair1/PHY/defs_UE.h @@ -640,7 +640,7 @@ typedef struct { /// mbsfn reference symbols uint32_t lte_gold_mbsfn_khz_1dot25_table[10][150]; - uint32_t X_u[64][839]; + c16_t X_u[64][839]; uint32_t high_speed_flag; uint32_t perfect_ce; diff --git a/openair1/PHY/defs_eNB.h b/openair1/PHY/defs_eNB.h index 68ebf65462..98d1080ee3 100644 --- a/openair1/PHY/defs_eNB.h +++ b/openair1/PHY/defs_eNB.h @@ -600,8 +600,8 @@ typedef struct PHY_VARS_eNB_s { // PUCCH1a/b energy detection parameters for eMTC per CE-level int pucch1ab_DTX_threshold_emtc[4]; - uint32_t X_u[64][839]; - uint32_t X_u_br[4][64][839]; + c16_t X_u[64][839]; + c16_t X_u_br[4][64][839]; uint8_t pbch_configured; uint8_t pbch_pdu[4]; //PBCH_PDU_SIZE char eNB_generate_rar; From 13f5c258ca5b188dcd1b3df7e1f3745143b310d6 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Tue, 29 Jul 2025 19:24:24 +0200 Subject: [PATCH 527/964] remove unused global --- nfapi/oai_integration/nfapi_pnf.c | 1 - 1 file changed, 1 deletion(-) diff --git a/nfapi/oai_integration/nfapi_pnf.c b/nfapi/oai_integration/nfapi_pnf.c index 48e31b7264..3de11d8003 100644 --- a/nfapi/oai_integration/nfapi_pnf.c +++ b/nfapi/oai_integration/nfapi_pnf.c @@ -88,7 +88,6 @@ extern int nfapi_sync_var; extern int sync_var; nfapi_tx_request_pdu_t *tx_request_pdu[1023][10][10]; // [frame][subframe][max_num_pdus] -nfapi_nr_pdu_t *tx_data_request[1023][20][10]; //[frame][slot][max_num_pdus] uint8_t tx_pdus[32][8][4096]; nfapi_ue_release_request_body_t release_rntis; From fc1c8a9be066eeee0f90a9d9ce67ad24ff478be0 Mon Sep 17 00:00:00 2001 From: Sagar Arora Date: Wed, 20 Aug 2025 13:17:45 +0200 Subject: [PATCH 528/964] Align add_boolean_option as per cmake documentation use only ON/OFF for uniformity Signed-off-by: Sagar Arora --- CMakeLists.txt | 42 +++++++++++++++++++++--------------------- doc/CMakeLists.txt | 2 +- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 898b387237..cba949fbad 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -194,26 +194,26 @@ set(CMAKE_CXX_FLAGS "${C_FLAGS_PROCESSOR} ${commonOpts} -std=c++11 ${CMAKE_CXX_FLAGS}") -add_boolean_option(SANITIZE_ADDRESS False "enable the address sanitizer (ASan)" ON) +add_boolean_option(SANITIZE_ADDRESS OFF "enable the address sanitizer (ASan)" ON) if (SANITIZE_ADDRESS) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fno-omit-frame-pointer -fno-common") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer -fno-common") endif () -add_boolean_option(SANITIZE_THREAD False "enable the address sanitizer (TSan)" ON) +add_boolean_option(SANITIZE_THREAD OFF "enable the address sanitizer (TSan)" ON) if (SANITIZE_THREAD) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=thread -fno-omit-frame-pointer -fno-common") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=thread -fno-omit-frame-pointer -fno-common") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=thread") endif() -add_boolean_option(SANITIZE_UNDEFINED False "enable the undefined behavior sanitizer (UBSan)" ON) +add_boolean_option(SANITIZE_UNDEFINED OFF "enable the undefined behavior sanitizer (UBSan)" ON) if (SANITIZE_UNDEFINED) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=undefined -fno-sanitize-recover=all") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined -fno-sanitize-recover=all") endif () -add_boolean_option(SANITIZE_MEMORY False "enable the memory sanitizer (MSan, requires clang, incompatible with ASan/UBSan)" ON) +add_boolean_option(SANITIZE_MEMORY OFF "enable the memory sanitizer (MSan, requires clang, incompatible with ASan/UBSan)" ON) if(SANITIZE_MEMORY) if (SANITIZE_UNDEFINED OR SANITIZE_ADDRESS) message(FATAL_ERROR "memory sanitizer cannot coexist with address sanitizer or undefined behavior sanitizer, please disable either MSan or ASan and UBSan") @@ -278,10 +278,10 @@ endif() # OAI uses this feature to re-use OAI LOG_I(ASN1, ...) # see common/utils/config.h add_boolean_option(TRACE_ASN1C_ENC_DEC OFF "Enable ASN1 encoder/decoder debug traces via OAI logging system" ON) -add_boolean_option(T_TRACER True "Activate the T tracer, a debugging/monitoring framework" ON) -add_boolean_option(ENABLE_LTTNG False "Activate the LTTNG tracer, a debugging/monitoring framework" ON) -add_boolean_option(UE_DEBUG_TRACE False "Activate UE debug trace" ON) -add_boolean_option(UE_TIMING_TRACE False "Activate UE timing trace" ON) +add_boolean_option(T_TRACER ON "Activate the T tracer, a debugging/monitoring framework" ON) +add_boolean_option(ENABLE_LTTNG OFF "Activate the LTTNG tracer, a debugging/monitoring framework" ON) +add_boolean_option(UE_DEBUG_TRACE OFF "Activate UE debug trace" ON) +add_boolean_option(UE_TIMING_TRACE OFF "Activate UE timing trace" ON) add_boolean_option(TRACY_ENABLE OFF "Enable tracy instrumentation" ON) if (TRACY_ENABLE) @@ -509,34 +509,34 @@ include_directories ("${OPENAIR_DIR}/radio/COMMON") # ???!!! TO BE DOCUMENTED OPTIONS !!!??? ############################################################## -add_boolean_option(UE_EXPANSION False "enable UE_EXPANSION with max 256 UE" ON) -add_boolean_option(PHY_TX_THREAD False "enable UE_EXPANSION with max 256 UE" ON) -add_boolean_option(PRE_SCD_THREAD False "enable UE_EXPANSION with max 256 UE" ON) +add_boolean_option(UE_EXPANSION OFF "enable UE_EXPANSION with max 256 UE" ON) +add_boolean_option(PHY_TX_THREAD OFF "enable UE_EXPANSION with max 256 UE" ON) +add_boolean_option(PRE_SCD_THREAD OFF "enable UE_EXPANSION with max 256 UE" ON) ########################## # SCHEDULING/REAL-TIME/PERF options ########################## -add_boolean_option(ENABLE_USE_CPU_EXECUTION_TIME False "Add data in vcd traces: disable it if perf issues" ON) -add_boolean_option(ENABLE_VCD False "always true now, time measurements of proc calls and var displays" ON) -add_boolean_option(ENABLE_VCD_FIFO False "time measurements of proc calls and var displays sent to FIFO (one more thread)" ON) +add_boolean_option(ENABLE_USE_CPU_EXECUTION_TIME OFF "Add data in vcd traces: disable it if perf issues" ON) +add_boolean_option(ENABLE_VCD OFF "always true now, time measurements of proc calls and var displays" ON) +add_boolean_option(ENABLE_VCD_FIFO OFF "time measurements of proc calls and var displays sent to FIFO (one more thread)" ON) ########################## # PHY options ########################## -add_integer_option(MAX_NUM_CCs 1 "Carrier component data arrays size (oai doesn't support carrier aggreagtion for now)" ON) -add_boolean_option(SMBV False "Rohde&Schwarz SMBV100A vector signal generator" ON) -add_boolean_option(DEBUG_PHY False "Enable PHY layer debugging options" ON) -add_boolean_option(DEBUG_PHY_PROC False "Enable debugging of PHY layer procedures" ON) +add_integer_option(MAX_NUM_CCs 1 "Carrier component data arrays size (oai doesn't support carrier aggregation for now)" ON) +add_boolean_option(SMBV OFF "Rohde&Schwarz SMBV100A vector signal generator" ON) +add_boolean_option(DEBUG_PHY OFF "Enable PHY layer debugging options" ON) +add_boolean_option(DEBUG_PHY_PROC OFF "Enable debugging of PHY layer procedures" ON) ########################## # NAS LAYER OPTIONS ########################## -add_boolean_option(NAS_BUILT_IN_UE True "UE NAS layer present in this executable" ON) +add_boolean_option(NAS_BUILT_IN_UE ON "UE NAS layer present in this executable" ON) ########################## # RRC LAYER OPTIONS ########################## -add_boolean_option(RRC_DEFAULT_RAB_IS_AM True "set the LTE RLC mode to AM for the default bearer, otherwise it is UM." ON) +add_boolean_option(RRC_DEFAULT_RAB_IS_AM ON "set the LTE RLC mode to AM for the default bearer, otherwise it is UM." ON) # add the binary tree to the search path for include files # We will find common/oai_version.h after generation in target directory @@ -603,7 +603,7 @@ include_directories("${OPENAIR_DIR}") ############### # include T directory even if the T is off because T macros are in the code -# no matter what. Note: sone files are generated, so we have both source and +# no matter what. Note: some files are generated, so we have both source and # binary directories include_directories(${CMAKE_CURRENT_SOURCE_DIR}/common/utils/T ${CMAKE_CURRENT_BINARY_DIR}/common/utils/T) diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index 2b6c1dd0bb..7f46dc1517 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -1,4 +1,4 @@ -add_boolean_option(GENERATE_DOXYGEN False "Generate source code doc using doxygen" OFF) +add_boolean_option(GENERATE_DOXYGEN OFF "Generate source code doc using doxygen" OFF) if(GENERATE_DOXYGEN) find_package(Doxygen REQUIRED) From 16f529920382a8e43b3fd4d82ddfe075289246aa Mon Sep 17 00:00:00 2001 From: Bartosz Podrygajlo Date: Tue, 15 Apr 2025 16:12:13 +0200 Subject: [PATCH 529/964] Taps client client for vrtsim Added a libary that can connect to a channel emulator and provide taps as they are generated. - Enable connection from vrtsim to channel emulation server - Depends on flatbuffers definition file from raytracing-channel-emulator - Depends on libanomsg-dev and flatbuffers-compiler (Ubuntu) or equivalent - Added a compile time option ENABLE_TAPS_CLIENT to prevent other users from being affected by additional dependencies --- openair1/SIMULATION/TOOLS/sim.h | 2 + radio/vrtsim/CMakeLists.txt | 25 ++++ radio/vrtsim/taps_client.cpp | 198 ++++++++++++++++++++++++++++++++ radio/vrtsim/taps_client.h | 38 ++++++ radio/vrtsim/vrtsim.c | 70 ++++++++--- 5 files changed, 318 insertions(+), 15 deletions(-) create mode 100644 radio/vrtsim/taps_client.cpp create mode 100644 radio/vrtsim/taps_client.h diff --git a/openair1/SIMULATION/TOOLS/sim.h b/openair1/SIMULATION/TOOLS/sim.h index 98b4fb26c6..359df00b55 100644 --- a/openair1/SIMULATION/TOOLS/sim.h +++ b/openair1/SIMULATION/TOOLS/sim.h @@ -77,6 +77,8 @@ typedef struct { struct complexd **a; ///interpolated (sample-spaced) channel impulse response. size(ch) = (n_tx * n_rx) * channel_length. ATTENTION: the dimensions of ch are the transposed ones of a. This is to allow the use of BLAS when applying the correlation matrices to the state. struct complexd **ch; + ///Same as above but single precision + struct complexf **ch_ps; ///Sampled frequency response (90 kHz resolution) struct complexd **chF; ///Maximum path delay in mus. diff --git a/radio/vrtsim/CMakeLists.txt b/radio/vrtsim/CMakeLists.txt index 79eb4d88da..9ac1555099 100644 --- a/radio/vrtsim/CMakeLists.txt +++ b/radio/vrtsim/CMakeLists.txt @@ -2,3 +2,28 @@ add_library(vrtsim MODULE vrtsim.c noise_device.c) set_target_properties(vrtsim PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) target_link_libraries(vrtsim PRIVATE SIMU shm_td_iq_channel actor) add_dependencies(vrtsim generate_T) + +add_boolean_option(OAI_VRTSIM_TAPS_CLIENT OFF "Enable taps client" ON) +if (OAI_VRTSIM_TAPS_CLIENT) + target_link_libraries(vrtsim PRIVATE taps_client) + file(DOWNLOAD + "https://gitlab.eurecom.fr/oai/raytracing-channel-emulator/-/raw/59589ad2a534881810b2aa7dd81e63066245bb8d/server/api/taps.fbs?inline=false" + ${CMAKE_SOURCE_DIR}/taps.fbs + ) + + set(TAPS_IF_PATH ${CMAKE_SOURCE_DIR}/taps.fbs) + set(TAPS_API_HEADER taps_generated.h) + + add_custom_command(OUTPUT ${TAPS_API_HEADER} + COMMAND flatc -c ${TAPS_IF_PATH} + DEPENDS ${TAPS_IF_PATH} + COMMENT "Generating flatbuffers API from ${TAPS_IF_PATH}" + ) + add_library(taps_api INTERFACE) + target_include_directories(taps_api INTERFACE ${CMAKE_CURRENT_BINARY_DIR}) + + add_library(taps_client taps_client.cpp ${TAPS_API_HEADER}) + target_include_directories(taps_client PUBLIC .) + find_package(Flatbuffers REQUIRED) + target_link_libraries(taps_client PUBLIC flatbuffers taps_api SIMU nanomsg) +endif() diff --git a/radio/vrtsim/taps_client.cpp b/radio/vrtsim/taps_client.cpp new file mode 100644 index 0000000000..6ebfc450fd --- /dev/null +++ b/radio/vrtsim/taps_client.cpp @@ -0,0 +1,198 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ +#include +#include +#include +#include +#include +#include "pthread.h" +#include "taps_generated.h" +#include "SIMULATION/TOOLS/sim.h" +extern "C" { +#include "assertions.h" +#include "common/utils/LOG/log.h" +#include "sim.h" +#include "utils.h" +} +#include + +#define NUM_TAPS_BUFFERS 4 +#define MAX_TAPS_LEN 100 +#define MAX_TAPS_MSG_SIZE (sizeof(struct complexf) * MAX_TAPS_LEN * 4 * 4 + 20) + +static pthread_t client_thread; +static bool should_run = true; +typedef struct { + int id; + int sock; + uint32_t num_tx_antennas; + uint32_t num_rx_antennas; + channel_desc_t **channel_desc; +} client_thread_args_t; + +typedef struct { + void *taps_msg; + channel_desc_t *channel_desc; +} taps_buffer_t; + +typedef struct { + taps_buffer_t taps_buffers[NUM_TAPS_BUFFERS]; + int current_buffer; +} taps_storage_t; + +void ascii_line_plot(const float *data, size_t size, char *buffer) +{ + const char levels[] = "_.-=#"; // ASCII characters for different levels + size_t num_levels = sizeof(levels) - 1; // Number of levels (excluding the null terminator) + + // Calculate min and max values from the data + float min_val = FLT_MAX; + float max_val = FLT_MIN; + for (size_t i = 0; i < size; i++) { + if (data[i] < min_val) + min_val = data[i]; + if (data[i] > max_val) + max_val = data[i]; + } + + // Handle edge case where all values are the same + if (min_val == max_val) { + min_val -= 1.0f; + max_val += 1.0f; + } + + // Normalize and map data to levels + for (size_t i = 0; i < size; i++) { + float normalized = (data[i] - min_val) / (max_val - min_val); // Normalize to [0, 1] + size_t level_index = (size_t)(normalized * num_levels); // Map to level index + if (level_index > num_levels) + level_index = num_levels; // Clamp to valid range + snprintf(buffer + i, 2, "%c", levels[level_index]); + } +} + +static void init_taps_storage(taps_storage_t *storage, int num_tx_antennas, int num_rx_antennas) +{ + for (int i = 0; i < NUM_TAPS_BUFFERS; i++) { + storage->taps_buffers[i].taps_msg = calloc_or_fail(1, MAX_TAPS_MSG_SIZE); + storage->taps_buffers[i].channel_desc = (channel_desc_t *)calloc_or_fail(1, sizeof(channel_desc_t)); + storage->taps_buffers[i].channel_desc->ch_ps = + (struct complexf **)calloc_or_fail(num_rx_antennas * num_tx_antennas, sizeof(struct complexf *)); + } + storage->current_buffer = 0; +} + +static taps_storage_t taps_storage; + +void *client_thread_func(void *args) +{ + client_thread_args_t *client_thread_args = (client_thread_args_t *)args; + while (should_run) { + int next_buffer = (taps_storage.current_buffer + 1) % NUM_TAPS_BUFFERS; + taps_buffer_t *taps_buffer = &taps_storage.taps_buffers[next_buffer]; + int ret = nn_recv(client_thread_args->sock, taps_buffer->taps_msg, MAX_TAPS_MSG_SIZE, 0); + if (ret < 0) { + LOG_E(HW, "nn_recv() failed: errno: %d, %s\n", errno, strerror(errno)); + continue; + } + auto taps_message = Phy::GetTaps(taps_buffer->taps_msg); + if (taps_message->num_rx_antennas() != client_thread_args->num_rx_antennas + || taps_message->num_tx_antennas() != client_thread_args->num_tx_antennas) { + LOG_E(HW, + "Number of antennas mismatch: expected %d x %d, got %d x %d\n", + client_thread_args->num_rx_antennas, + client_thread_args->num_tx_antennas, + taps_message->num_rx_antennas(), + taps_message->num_tx_antennas()); + continue; + } + channel_desc_t *channel_desc = taps_buffer->channel_desc; + const flatbuffers::Vector *taps = taps_message->taps(); + struct complexf *base_pointer = (struct complexf *)taps->data(); + int taps_len = taps_message->taps_len(); + AssertFatal(taps_len < MAX_TAPS_LEN, "Too many samples in the taps array, taps_len = %d\n", taps_len); + for (unsigned int aarx = 0U; aarx < client_thread_args->num_rx_antennas; aarx++) { + for (unsigned int aatx = 0U; aatx < client_thread_args->num_tx_antennas; aatx++) { + channel_desc->ch_ps[aarx + (client_thread_args->num_rx_antennas * aatx)] = + &base_pointer[(aarx + (client_thread_args->num_rx_antennas * aatx)) * taps_len]; + } + } + channel_desc->path_loss_dB = 0; + channel_desc->channel_length = taps_len; + *client_thread_args->channel_desc = channel_desc; + taps_storage.current_buffer = next_buffer; + LOG_A(HW, "Receved new taps message, channel_length %d, buffer %d\n", channel_desc->channel_length, next_buffer); + for (unsigned int aarx = 0; aarx < client_thread_args->num_rx_antennas; aarx++) { + for (unsigned int aatx = 0; aatx < client_thread_args->num_tx_antennas; aatx++) { + char buffer[MAX_TAPS_LEN + 1]; + memset(buffer, 0, sizeof(buffer)); + float magnitudes[MAX_TAPS_LEN]; + cf_t *channel = channel_desc->ch_ps[aarx + (client_thread_args->num_rx_antennas * aatx)]; + for (int i = 0; i < channel_desc->channel_length; i++) { + magnitudes[i] = sqrtf(powf(channel[i].r, 2) + powf(channel[i].i, 2)); + } + ascii_line_plot(magnitudes, channel_desc->channel_length, buffer); + LOG_A(HW, "Taps message %d, channel %d x %d: %s\n", client_thread_args->id, aarx, aatx, buffer); + } + } + } + return NULL; +} + +extern "C" void taps_client_connect(int id, + const char *socket_path, + int num_tx_antennas, + int num_rx_antennas, + channel_desc_t **channel_desc) +{ + // Create a socket + int sock = nn_socket(AF_SP, NN_SUB); + AssertFatal(sock >= 0, "nn_socket() failed: errno: %d, %s\n", errno, strerror(errno)); + + int ret = nn_connect(sock, socket_path); + AssertFatal(ret >= 0, "nn_connect() failed: errno: %d, %s\n", errno, strerror(errno)); + + // Subscribe to all messages + ret = nn_setsockopt(sock, NN_SUB, NN_SUB_SUBSCRIBE, "", 0); + AssertFatal(ret == 0, "nn_setsockopt() failed, errno %d, %s\n", errno, strerror(errno)); + + init_taps_storage(&taps_storage, num_tx_antennas, num_rx_antennas); + + client_thread_args_t *client_thread_args = static_cast(malloc(sizeof(client_thread_args_t))); + client_thread_args->id = id; + client_thread_args->sock = sock; + client_thread_args->num_rx_antennas = num_rx_antennas; + client_thread_args->num_tx_antennas = num_tx_antennas; + client_thread_args->channel_desc = channel_desc; + ret = pthread_create(&client_thread, NULL, client_thread_func, client_thread_args); + AssertFatal(ret == 0, "pthread_create() failed: errno: %d, %s\n", errno, strerror(errno)); +} + +extern "C" void taps_client_stop() +{ + should_run = false; + pthread_join(client_thread, NULL); + for (int i = 0; i < NUM_TAPS_BUFFERS; i++) { + free(taps_storage.taps_buffers[i].taps_msg); + free(taps_storage.taps_buffers[i].channel_desc->ch_ps); + free(taps_storage.taps_buffers[i].channel_desc); + } +} diff --git a/radio/vrtsim/taps_client.h b/radio/vrtsim/taps_client.h new file mode 100644 index 0000000000..c0a577c787 --- /dev/null +++ b/radio/vrtsim/taps_client.h @@ -0,0 +1,38 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef TAPS_CLIENT_H +#define TAPS_CLIENT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "sim.h" + +void taps_client_connect(int id, const char *socket_path, int num_tx_antennas, int num_rx_antennas, channel_desc_t **channel_desc); +void taps_client_stop(); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/radio/vrtsim/vrtsim.c b/radio/vrtsim/vrtsim.c index 0e602b3686..9d498d450b 100644 --- a/radio/vrtsim/vrtsim.c +++ b/radio/vrtsim/vrtsim.c @@ -47,6 +47,7 @@ #include "actor.h" #include "noise_device.h" #include "simde/x86/avx512.h" +#include "taps_client.h" // Simulator role typedef enum { ROLE_SERVER = 1, ROLE_CLIENT } role; @@ -60,6 +61,7 @@ typedef enum { ROLE_SERVER = 1, ROLE_CLIENT } role; #define VRTSIM_SECTION "vrtsim" #define TIME_SCALE_HLP \ "sample time scale. 1.0 means realtime. Values > 1 mean faster than realtime. Values < 1 mean slower than realtime\n" +#define TAPS_SOCKET_HLP "Socket to connect to the channel emulation server\n" // clang-format off #define VRTSIM_PARAMS_DESC \ @@ -68,6 +70,7 @@ typedef enum { ROLE_SERVER = 1, ROLE_CLIENT } role; {"role", "either client or server\n", 0, .strptr = &role, .defstrval = ROLE_CLIENT_STRING, TYPE_STRING, 0}, \ {"timescale", TIME_SCALE_HLP, 0, .dblptr = &vrtsim_state->timescale, .defdblval = 1.0, TYPE_DOUBLE, 0}, \ {"chanmod", "Enable channel modelling", 0, .iptr = &vrtsim_state->chanmod, .defintval = 0, TYPE_INT, 0}, \ + {"taps-socket", TAPS_SOCKET_HLP, 0, .strptr = &vrtsim_state->taps_socket, .defstrval = NULL, TYPE_STRING, 0}, \ }; // clang-format on @@ -112,6 +115,7 @@ typedef struct { int rx_num_channels; channel_desc_t *channel_desc; Actor_t *channel_modelling_actors; + char *taps_socket; } vrtsim_state_t; // Sample history for channel impulse response @@ -183,6 +187,15 @@ static void vrtsim_readconfig(vrtsim_state_t *vrtsim_state) } else { AssertFatal(false, "Invalid role configuration\n"); } +#ifdef ENABLE_TAPS_CLIENT + if (vrtsim_state->taps_socket) { + LOG_A(HW, "VRTSIM: will use taps socket %s\n", vrtsim_state->taps_socket); + } +#else + if (vrtsim_state->taps_socket) { + AssertFatal(false, "Invalid configuration: Build with ENABLE_TAPS_CLIENT to use taps socket\n"); + } +#endif } static void *vrtsim_timing_job(void *arg) @@ -326,12 +339,20 @@ static int vrtsim_connect(openair0_device *device) // Handle channel modelling after number of RX antennas are known int num_tx_stats = 1; - if (vrtsim_state->chanmod) { + if (vrtsim_state->chanmod || vrtsim_state->taps_socket) { vrtsim_state->channel_modelling_actors = calloc_or_fail(vrtsim_state->peer_info.num_rx_antennas, sizeof(Actor_t)); for (int i = 0; i < vrtsim_state->peer_info.num_rx_antennas; i++) { init_actor(&vrtsim_state->channel_modelling_actors[i], "chanmod", -1); } - load_channel_model(vrtsim_state); + if (vrtsim_state->taps_socket) { + taps_client_connect(0, + vrtsim_state->taps_socket, + device->openair0_cfg[0].tx_num_channels, + vrtsim_state->peer_info.num_rx_antennas, + &vrtsim_state->channel_desc); + } else { + load_channel_model(vrtsim_state); + } num_tx_stats = vrtsim_state->peer_info.num_rx_antennas; } vrtsim_state->tx_timing = calloc_or_fail(num_tx_stats, sizeof(tx_timing_t)); @@ -401,6 +422,7 @@ typedef struct { static void perform_channel_modelling(void *arg) { channel_modelling_args_t *channel_modelling_args = arg; + vrtsim_state_t *vrtsim_state = channel_modelling_args->vrtsim_state; int nsamps = channel_modelling_args->nsamps; int aarx = channel_modelling_args->aarx; int nb_tx_ant = channel_modelling_args->nbAnt; @@ -411,23 +433,36 @@ static void perform_channel_modelling(void *arg) // Apply noise from global settings get_noise_vector((float *)samples, nsamps * 2); - channel_desc_t *channel_desc = channel_modelling_args->vrtsim_state->channel_desc; - const float pathloss_linear = powf(10, channel_desc->path_loss_dB / 20.0); + channel_desc_t *channel_desc = vrtsim_state->channel_desc; + + if (channel_desc == NULL) { + return; + } - // Convert channel impulse response to float + apply pathloss cf_t channel_impulse_response[nb_tx_ant][channel_desc->channel_length]; - for (int aatx = 0; aatx < nb_tx_ant; aatx++) { - const struct complexd *channelModel = channel_desc->ch[aarx + (aatx * channel_desc->nb_rx)]; - for (int i = 0; i < channel_desc->channel_length; i++) { - channel_impulse_response[aatx][i].r = channelModel[i].r * pathloss_linear; - channel_impulse_response[aatx][i].i = channelModel[i].i * pathloss_linear; + cf_t *channel_impulse_response_p[nb_tx_ant]; + if (!vrtsim_state->taps_socket) { + const float pathloss_linear = powf(10, channel_desc->path_loss_dB / 20.0); + // Convert channel impulse response to float + apply pathloss + for (int aatx = 0; aatx < nb_tx_ant; aatx++) { + const struct complexd *channelModel = channel_desc->ch[aarx + (aatx * channel_desc->nb_rx)]; + for (int i = 0; i < channel_desc->channel_length; i++) { + channel_impulse_response[aatx][i].r = channelModel[i].r * pathloss_linear; + channel_impulse_response[aatx][i].i = channelModel[i].i * pathloss_linear; + } + channel_impulse_response_p[aatx] = channel_impulse_response[aatx]; + } + } else { + for (int aatx = 0; aatx < nb_tx_ant; aatx++) { + struct complexf *channelModel = channel_desc->ch_ps[aarx + (aatx * channel_desc->nb_rx)]; + channel_impulse_response_p[aatx] = channelModel; } } for (int aatx = 0; aatx < nb_tx_ant; aatx++) { c16_t *previous_samples = saved_samples[aatx]; for (int i = 0; i < nsamps; i++) { - cf_t *impulse_response = channel_impulse_response[aatx]; + cf_t *impulse_response = channel_impulse_response_p[aatx]; for (int l = 0; l < channel_desc->channel_length; l++) { int idx = i - l; // TODO: Use AVX2 for this @@ -515,8 +550,9 @@ static int vrtsim_write(openair0_device *device, openair0_timestamp timestamp, v { timestamp -= device->openair0_cfg->command_line_sample_advance; vrtsim_state_t *vrtsim_state = (vrtsim_state_t *)device->priv; - return vrtsim_state->chanmod ? vrtsim_write_with_chanmod(vrtsim_state, timestamp, samplesVoid, nsamps, nbAnt, flags) - : vrtsim_write_internal(vrtsim_state, timestamp, (c16_t *)samplesVoid[0], nsamps, 0, flags, 0); + bool channel_modelling = vrtsim_state->chanmod || vrtsim_state->taps_socket; + return channel_modelling ? vrtsim_write_with_chanmod(vrtsim_state, timestamp, samplesVoid, nsamps, nbAnt, flags) + : vrtsim_write_internal(vrtsim_state, timestamp, (c16_t *)samplesVoid[0], nsamps, 0, flags, 0); } static int vrtsim_read(openair0_device *device, openair0_timestamp *ptimestamp, void **samplesVoid, int nsamps, int nbAnt) @@ -545,7 +581,7 @@ static void vrtsim_end(openair0_device *device) } tx_timing_t *tx_timing = vrtsim_state->tx_timing; - if (vrtsim_state->chanmod) { + if (vrtsim_state->chanmod || vrtsim_state->taps_socket) { for (int i = 0; i < vrtsim_state->peer_info.num_rx_antennas; i++) { shutdown_actor(&vrtsim_state->channel_modelling_actors[i]); } @@ -559,6 +595,9 @@ static void vrtsim_end(openair0_device *device) } tx_timing->average_tx_budget /= vrtsim_state->peer_info.num_rx_antennas; free_noise_device(); + if (vrtsim_state->taps_socket) { + taps_client_stop(); + } } // produce 1 second of extra samples so threads can finish shm_td_iq_channel_produce_samples(vrtsim_state->channel, vrtsim_state->sample_rate); @@ -621,10 +660,11 @@ __attribute__((__visibility__("default"))) int device_init(openair0_device *devi vrtsim_state->tx_num_channels = openair0_cfg->tx_num_channels; vrtsim_state->rx_num_channels = openair0_cfg->rx_num_channels; - if (vrtsim_state->chanmod) { + if (vrtsim_state->chanmod || vrtsim_state->taps_socket) { init_channelmod(); int noise_power_dBFS = get_noise_power_dBFS(); int16_t noise_power = noise_power_dBFS == INVALID_DBFS_VALUE ? 0 : (int16_t)(32767.0 / powf(10.0, .05 * -noise_power_dBFS)); + LOG_A(HW, "VRTSIM: Noise power %d sample value\n", noise_power); init_noise_device(noise_power); } return 0; From fcea07ca715aae57efb7b600c44eeeeb1bad0b47 Mon Sep 17 00:00:00 2001 From: Bartosz Podrygajlo Date: Fri, 27 Jun 2025 10:46:53 +0200 Subject: [PATCH 530/964] Detect disconnecton & handle error states in vrtsim Add handling for error states in vrtsim which allows to close the softmodems with CTRL+C without hanging, improving user experience - Client detection of stale timer. - Abort state for client and server --- .../utils/shm_iq_channel/shm_td_iq_channel.c | 63 ++++++++++++++++--- .../utils/shm_iq_channel/shm_td_iq_channel.h | 19 +++++- .../tests/test_shm_td_iq_channel.c | 4 +- radio/vrtsim/vrtsim.c | 13 +++- 4 files changed, 85 insertions(+), 14 deletions(-) diff --git a/common/utils/shm_iq_channel/shm_td_iq_channel.c b/common/utils/shm_iq_channel/shm_td_iq_channel.c index 3920fe027f..1086979a75 100644 --- a/common/utils/shm_iq_channel/shm_td_iq_channel.c +++ b/common/utils/shm_iq_channel/shm_td_iq_channel.c @@ -52,6 +52,7 @@ typedef struct ShmTDIQChannel_s { char name[256]; sample_t *tx_iq_data; sample_t *rx_iq_data; + bool abort; } ShmTDIQChannel; ShmTDIQChannel *shm_td_iq_channel_create(const char *name, int num_tx_ant, int num_rx_ant) @@ -237,10 +238,11 @@ void shm_td_iq_channel_produce_samples(ShmTDIQChannel *channel, size_t num_sampl mutexunlock(data->mutex); } -void shm_td_iq_channel_wait(ShmTDIQChannel *channel, uint64_t timestamp) +void shm_td_iq_channel_wait(ShmTDIQChannel *channel, uint64_t timestamp, uint64_t timeout_uS) { ShmTDIQChannelData *data = channel->data; if (data->is_connected == false) { + fprintf(stderr, "Error: Channel is not connected.\n"); abort(); return; } @@ -249,13 +251,41 @@ void shm_td_iq_channel_wait(ShmTDIQChannel *channel, uint64_t timestamp) if (current_timestamp >= timestamp) { return; } - mutexlock(data->mutex); - while (current_timestamp < timestamp) { - condwait(data->cond, data->mutex); - current_timestamp = data->timestamp; + if (timeout_uS == 0) { + mutexlock(data->mutex); + while (current_timestamp < timestamp && !channel->abort) { + condwait(data->cond, data->mutex); + current_timestamp = data->timestamp; + } + mutexunlock(data->mutex); + } else { + struct timespec ts = {.tv_sec = 0, .tv_nsec = 0}; + if (clock_gettime(CLOCK_REALTIME, &ts) != 0) { + fprintf(stderr, "Error: clock_gettime failed: %s\n", strerror(errno)); + channel->abort = true; + return; + } + + ts.tv_sec += timeout_uS / 1000000; // Convert microseconds to seconds + ts.tv_nsec += (timeout_uS % 1000000) * 1000; // Convert remaining microseconds to nanoseconds + + mutexlock(data->mutex); + while (current_timestamp < timestamp && !channel->abort) { + int ret = pthread_cond_timedwait(&data->cond, &data->mutex, &ts); + if (ret == ETIMEDOUT) { + channel->abort = true; + fprintf(stderr, "Error: Timed out waiting for samples. Aborting vrtsim\n");\ + break; + } else if (ret != 0) { + channel->abort = true; + fprintf(stderr, "Error: pthread_cond_timedwait failed: %s\n", strerror(ret)); + break; + } else { + current_timestamp = data->timestamp; + } + } + mutexunlock(data->mutex); } - mutexunlock(data->mutex); - return; } uint64_t shm_td_iq_channel_get_current_sample(const ShmTDIQChannel *channel) @@ -269,15 +299,32 @@ bool shm_td_iq_channel_is_connected(const ShmTDIQChannel *channel) return channel->data->is_connected; } +void shm_td_iq_channel_abort(ShmTDIQChannel *channel) +{ + ShmTDIQChannelData *data = channel->data; + mutexlock(data->mutex); + channel->abort = true; + condbroadcast(data->cond); + mutexunlock(data->mutex); +} + +bool shm_td_iq_channel_is_aborted(const ShmTDIQChannel *channel) +{ + return channel->abort; +} + void shm_td_iq_channel_destroy(ShmTDIQChannel *channel) { ShmTDIQChannelData *data = channel->data; size_t tx_buffer_size = CIRCULAR_BUFFER_SIZE * sizeof(sample_t) * data->num_antennas_tx; size_t rx_buffer_size = CIRCULAR_BUFFER_SIZE * sizeof(sample_t) * data->num_antennas_rx; size_t total_size = sizeof(ShmTDIQChannelData) + tx_buffer_size + rx_buffer_size; - munmap(data, total_size); if (channel->type == IQ_CHANNEL_TYPE_SERVER) { + data->is_connected = false; + munmap(data, total_size); shm_unlink(channel->name); + } else { + munmap(data, total_size); } free(channel); } diff --git a/common/utils/shm_iq_channel/shm_td_iq_channel.h b/common/utils/shm_iq_channel/shm_td_iq_channel.h index 7c5a730914..30c7cd73f1 100644 --- a/common/utils/shm_iq_channel/shm_td_iq_channel.h +++ b/common/utils/shm_iq_channel/shm_td_iq_channel.h @@ -118,8 +118,10 @@ void shm_td_iq_channel_produce_samples(ShmTDIQChannel *channel, uint64_t num_sam * @brief Wait until sample at the specified timestamp is available * * @param channel The ShmTDIQChannel structure. + * @param timestamp The timestamp for which to wait. + * @param timeout_uS The timeout in microseconds to wait for the sample. 0 means wait indefinitely. */ -void shm_td_iq_channel_wait(ShmTDIQChannel *channel, uint64_t timestamp); +void shm_td_iq_channel_wait(ShmTDIQChannel *channel, uint64_t timestamp, uint64_t timeout_uS); /** * @brief Checks if the IQ channel is connected. @@ -129,6 +131,21 @@ void shm_td_iq_channel_wait(ShmTDIQChannel *channel, uint64_t timestamp); */ bool shm_td_iq_channel_is_connected(const ShmTDIQChannel *channel); +/** + * @brief Aborts the IQ channel causing the wait to return immediately + * + * @param channel The ShmTDIQChannel structure. + */ +void shm_td_iq_channel_abort(ShmTDIQChannel *channel); + +/** + * @brief Checks if the IQ channel is aborted. + * + * @param channel The ShmTDIQChannel structure. + * @return True if the channel is aborted, false otherwise. + */ +bool shm_td_iq_channel_is_aborted(const ShmTDIQChannel *channel); + /** * @brief Destroys the shared memory IQ channel. * diff --git a/common/utils/shm_iq_channel/tests/test_shm_td_iq_channel.c b/common/utils/shm_iq_channel/tests/test_shm_td_iq_channel.c index f5170b8144..351bdd678d 100644 --- a/common/utils/shm_iq_channel/tests/test_shm_td_iq_channel.c +++ b/common/utils/shm_iq_channel/tests/test_shm_td_iq_channel.c @@ -104,7 +104,7 @@ void server(void) uint64_t timestamp = 0; int iq_contents = 0; while (timestamp < num_samples_per_update * num_updates) { - shm_td_iq_channel_wait(channel, timestamp + num_samples_per_update); + shm_td_iq_channel_wait(channel, timestamp + num_samples_per_update, 0); uint64_t target_timestamp = timestamp + num_samples_per_update; timestamp += num_samples_per_update; uint32_t iq_data[num_samples_per_update]; @@ -141,7 +141,7 @@ int client(void) int iq_contents = 0; while (timestamp < num_samples_per_update * num_updates) { - shm_td_iq_channel_wait(channel, timestamp + num_samples_per_update); + shm_td_iq_channel_wait(channel, timestamp + num_samples_per_update, 0); // Server starts producing from second slot if (timestamp > num_samples_per_update) { uint64_t target_timestamp = timestamp - num_samples_per_update; diff --git a/radio/vrtsim/vrtsim.c b/radio/vrtsim/vrtsim.c index 9d498d450b..7fb85589ea 100644 --- a/radio/vrtsim/vrtsim.c +++ b/radio/vrtsim/vrtsim.c @@ -558,7 +558,15 @@ static int vrtsim_write(openair0_device *device, openair0_timestamp timestamp, v static int vrtsim_read(openair0_device *device, openair0_timestamp *ptimestamp, void **samplesVoid, int nsamps, int nbAnt) { vrtsim_state_t *vrtsim_state = (vrtsim_state_t *)device->priv; - shm_td_iq_channel_wait(vrtsim_state->channel, vrtsim_state->last_received_sample + nsamps); + if (shm_td_iq_channel_is_aborted(vrtsim_state->channel)) { + LOG_E(HW, "Channel is aborted, returning void samples\n"); + for (int i = 0; i < nbAnt; i++) { + memset(samplesVoid[i], 0, sizeof(c16_t) * nsamps); + } + return nsamps; + } + uint64_t timeout_uS = 2 * 1000 * 1000 / vrtsim_state->timescale; // 2 seconds in uS + shm_td_iq_channel_wait(vrtsim_state->channel, vrtsim_state->last_received_sample + nsamps, timeout_uS); int ret = shm_td_iq_channel_rx(vrtsim_state->channel, vrtsim_state->last_received_sample, nsamps, 0, samplesVoid[0]); if (ret == CHANNEL_ERROR_TOO_LATE) { vrtsim_state->rx_samples_late += nsamps; @@ -599,8 +607,7 @@ static void vrtsim_end(openair0_device *device) taps_client_stop(); } } - // produce 1 second of extra samples so threads can finish - shm_td_iq_channel_produce_samples(vrtsim_state->channel, vrtsim_state->sample_rate); + shm_td_iq_channel_abort(vrtsim_state->channel); sleep(1); shm_td_iq_channel_destroy(vrtsim_state->channel); From acba82b874930b00a623f14b3f34c3a528f10592 Mon Sep 17 00:00:00 2001 From: Bartosz Podrygajlo Date: Thu, 7 Aug 2025 14:03:05 +0200 Subject: [PATCH 531/964] Simplify shm td iq channel implementation Move the channel state management outside the channel implementation. This simplifies the channel implementation but forces users of the channel to manage it's state manually. --- .../utils/shm_iq_channel/shm_td_iq_channel.c | 27 ------------------- .../utils/shm_iq_channel/shm_td_iq_channel.h | 8 ------ .../tests/test_shm_td_iq_channel.c | 18 ------------- radio/vrtsim/vrtsim.c | 4 --- 4 files changed, 57 deletions(-) diff --git a/common/utils/shm_iq_channel/shm_td_iq_channel.c b/common/utils/shm_iq_channel/shm_td_iq_channel.c index 1086979a75..126c386be9 100644 --- a/common/utils/shm_iq_channel/shm_td_iq_channel.c +++ b/common/utils/shm_iq_channel/shm_td_iq_channel.c @@ -40,7 +40,6 @@ typedef struct { int num_antennas_tx; int num_antennas_rx; uint64_t timestamp; - bool is_connected; pthread_mutex_t mutex; pthread_cond_t cond; } ShmTDIQChannelData; @@ -48,7 +47,6 @@ typedef struct { typedef struct ShmTDIQChannel_s { IQChannelType type; ShmTDIQChannelData *data; - uint64_t last_timestamp; char name[256]; sample_t *tx_iq_data; sample_t *rx_iq_data; @@ -76,14 +74,12 @@ ShmTDIQChannel *shm_td_iq_channel_create(const char *name, int num_tx_ant, int n memset(shm_ptr, 0, total_size); shm_ptr->num_antennas_tx = num_tx_ant; shm_ptr->num_antennas_rx = num_rx_ant; - shm_ptr->is_connected = false; ShmTDIQChannel *channel = calloc_or_fail(1, sizeof(ShmTDIQChannel)); strncpy(channel->name, name, sizeof(channel->name) - 1); channel->tx_iq_data = (sample_t *)(shm_ptr + 1); channel->rx_iq_data = channel->tx_iq_data + tx_buffer_size / sizeof(sample_t); channel->data = shm_ptr; channel->type = IQ_CHANNEL_TYPE_SERVER; - channel->last_timestamp = 0; pthread_mutexattr_t mutex_attr; pthread_condattr_t cond_attr; int ret = pthread_mutexattr_init(&mutex_attr); @@ -138,12 +134,10 @@ ShmTDIQChannel *shm_td_iq_channel_connect(const char *name, int timeout_in_secon size_t tx_buffer_size = CIRCULAR_BUFFER_SIZE * sizeof(sample_t) * channel->data->num_antennas_tx; channel->rx_iq_data = channel->tx_iq_data + tx_buffer_size / sizeof(sample_t); channel->type = IQ_CHANNEL_TYPE_CLIENT; - channel->last_timestamp = 0; while (shm_ptr->magic != SHM_MAGIC_NUMBER) { printf("Waiting for server to initialize shared memory\n"); sleep(1); } - shm_ptr->is_connected = true; close(fd); return channel; } @@ -155,9 +149,6 @@ IQChannelErrorType shm_td_iq_channel_tx(ShmTDIQChannel *channel, const sample_t *tx_iq_data) { ShmTDIQChannelData *data = channel->data; - if (data->is_connected == false) { - return CHANNEL_ERROR_NOT_CONNECTED; - } // timestamp in the past uint64_t current_time = data->timestamp; if (timestamp < current_time) { @@ -194,9 +185,6 @@ IQChannelErrorType shm_td_iq_channel_rx(ShmTDIQChannel *channel, sample_t *tx_iq_data) { ShmTDIQChannelData *data = channel->data; - if (data->is_connected == false) { - return CHANNEL_ERROR_NOT_CONNECTED; - } // timestamp in the future uint64_t current_time = data->timestamp; if (timestamp > current_time) { @@ -229,9 +217,6 @@ IQChannelErrorType shm_td_iq_channel_rx(ShmTDIQChannel *channel, void shm_td_iq_channel_produce_samples(ShmTDIQChannel *channel, size_t num_samples) { ShmTDIQChannelData *data = channel->data; - if (data->is_connected == false) { - return; - } mutexlock(data->mutex); data->timestamp += num_samples; condbroadcast(data->cond); @@ -241,12 +226,6 @@ void shm_td_iq_channel_produce_samples(ShmTDIQChannel *channel, size_t num_sampl void shm_td_iq_channel_wait(ShmTDIQChannel *channel, uint64_t timestamp, uint64_t timeout_uS) { ShmTDIQChannelData *data = channel->data; - if (data->is_connected == false) { - fprintf(stderr, "Error: Channel is not connected.\n"); - abort(); - return; - } - size_t current_timestamp = data->timestamp; if (current_timestamp >= timestamp) { return; @@ -294,11 +273,6 @@ uint64_t shm_td_iq_channel_get_current_sample(const ShmTDIQChannel *channel) return data->timestamp; } -bool shm_td_iq_channel_is_connected(const ShmTDIQChannel *channel) -{ - return channel->data->is_connected; -} - void shm_td_iq_channel_abort(ShmTDIQChannel *channel) { ShmTDIQChannelData *data = channel->data; @@ -320,7 +294,6 @@ void shm_td_iq_channel_destroy(ShmTDIQChannel *channel) size_t rx_buffer_size = CIRCULAR_BUFFER_SIZE * sizeof(sample_t) * data->num_antennas_rx; size_t total_size = sizeof(ShmTDIQChannelData) + tx_buffer_size + rx_buffer_size; if (channel->type == IQ_CHANNEL_TYPE_SERVER) { - data->is_connected = false; munmap(data, total_size); shm_unlink(channel->name); } else { diff --git a/common/utils/shm_iq_channel/shm_td_iq_channel.h b/common/utils/shm_iq_channel/shm_td_iq_channel.h index 30c7cd73f1..8c7bfad318 100644 --- a/common/utils/shm_iq_channel/shm_td_iq_channel.h +++ b/common/utils/shm_iq_channel/shm_td_iq_channel.h @@ -123,14 +123,6 @@ void shm_td_iq_channel_produce_samples(ShmTDIQChannel *channel, uint64_t num_sam */ void shm_td_iq_channel_wait(ShmTDIQChannel *channel, uint64_t timestamp, uint64_t timeout_uS); -/** - * @brief Checks if the IQ channel is connected. - * - * @param channel The ShmTDIQChannel structure. - * @return True if the channel is connected, false otherwise. - */ -bool shm_td_iq_channel_is_connected(const ShmTDIQChannel *channel); - /** * @brief Aborts the IQ channel causing the wait to return immediately * diff --git a/common/utils/shm_iq_channel/tests/test_shm_td_iq_channel.c b/common/utils/shm_iq_channel/tests/test_shm_td_iq_channel.c index 351bdd678d..05140a0f63 100644 --- a/common/utils/shm_iq_channel/tests/test_shm_td_iq_channel.c +++ b/common/utils/shm_iq_channel/tests/test_shm_td_iq_channel.c @@ -87,15 +87,6 @@ void server(void) int num_ant_tx = 1; int num_ant_rx = 1; ShmTDIQChannel *channel = shm_td_iq_channel_create(SHM_CHANNEL_NAME, num_ant_tx, num_ant_rx); - for (int i = 0; i < 10; i++) { - if (shm_td_iq_channel_is_connected(channel)) { - printf("Server connected\n"); - break; - } - printf("Waiting for client\n"); - sleep(1); - } - AssertFatal(shm_td_iq_channel_is_connected(channel), "Server failed to connect\n"); pthread_t producer_thread; int ret = pthread_create(&producer_thread, NULL, produce_symbols, channel); @@ -127,15 +118,6 @@ int client(void) { int total_errors = 0; ShmTDIQChannel *channel = shm_td_iq_channel_connect(SHM_CHANNEL_NAME, 10); - for (int i = 0; i < 10; i++) { - if (shm_td_iq_channel_is_connected(channel)) { - printf("Client connected\n"); - break; - } - printf("Waiting for server\n"); - sleep(1); - } - AssertFatal(shm_td_iq_channel_is_connected(channel), "Client failed to connect\n"); uint64_t timestamp = 0; int iq_contents = 0; diff --git a/radio/vrtsim/vrtsim.c b/radio/vrtsim/vrtsim.c index 7fb85589ea..c668bac64c 100644 --- a/radio/vrtsim/vrtsim.c +++ b/radio/vrtsim/vrtsim.c @@ -368,10 +368,6 @@ static int vrtsim_connect(openair0_device *device) vrtsim_state->peer_info.num_rx_antennas, device->openair0_cfg[0].rx_num_channels); vrtsim_state->run_timing_thread = true; - while (!shm_td_iq_channel_is_connected(vrtsim_state->channel)) { - LOG_I(HW, "Waiting for client\n"); - sleep(1); - } int ret = pthread_create(&vrtsim_state->timing_thread, NULL, vrtsim_timing_job, vrtsim_state); AssertFatal(ret == 0, "pthread_create() failed: errno: %d, %s\n", errno, strerror(errno)); } else { From fc28e2d3fc6220325e35a1b9d4c4cae8892c7ec3 Mon Sep 17 00:00:00 2001 From: Bartosz Podrygajlo Date: Thu, 7 Aug 2025 14:05:06 +0200 Subject: [PATCH 532/964] Make vrtsim output to stdout more readable. --- radio/vrtsim/vrtsim.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/radio/vrtsim/vrtsim.c b/radio/vrtsim/vrtsim.c index c668bac64c..f5d2410bf1 100644 --- a/radio/vrtsim/vrtsim.c +++ b/radio/vrtsim/vrtsim.c @@ -555,7 +555,6 @@ static int vrtsim_read(openair0_device *device, openair0_timestamp *ptimestamp, { vrtsim_state_t *vrtsim_state = (vrtsim_state_t *)device->priv; if (shm_td_iq_channel_is_aborted(vrtsim_state->channel)) { - LOG_E(HW, "Channel is aborted, returning void samples\n"); for (int i = 0; i < nbAnt; i++) { memset(samplesVoid[i], 0, sizeof(c16_t) * nsamps); } @@ -615,7 +614,7 @@ static void vrtsim_end(openair0_device *device) "VRTSIM: Read/write too early (suspected radio implementaton error) TX: %lu, RX: %lu\n", tx_timing->tx_early, vrtsim_state->rx_early); - LOG_I(HW, "VRTSIM: Average TX budget %.3lf uS\n", tx_timing->average_tx_budget); + LOG_I(HW, "VRTSIM: Average TX budget %.3lf uS (more is better)\n", tx_timing->average_tx_budget); histogram_print(&tx_timing->tx_histogram); free(vrtsim_state->tx_timing); } From 54fdd3547bc8125721b3b0520a7b433f614d7625 Mon Sep 17 00:00:00 2001 From: Bartosz Podrygajlo Date: Fri, 8 Aug 2025 16:51:22 +0200 Subject: [PATCH 533/964] Clean exit of vrtsim client if server is stopped first Force exit in case current sample is not modified by the server with 2s. --- .../utils/shm_iq_channel/shm_td_iq_channel.c | 18 +++++----- .../utils/shm_iq_channel/shm_td_iq_channel.h | 4 ++- radio/vrtsim/vrtsim.c | 35 +++++++++++++++---- 3 files changed, 41 insertions(+), 16 deletions(-) diff --git a/common/utils/shm_iq_channel/shm_td_iq_channel.c b/common/utils/shm_iq_channel/shm_td_iq_channel.c index 126c386be9..ecebbaf494 100644 --- a/common/utils/shm_iq_channel/shm_td_iq_channel.c +++ b/common/utils/shm_iq_channel/shm_td_iq_channel.c @@ -223,12 +223,12 @@ void shm_td_iq_channel_produce_samples(ShmTDIQChannel *channel, size_t num_sampl mutexunlock(data->mutex); } -void shm_td_iq_channel_wait(ShmTDIQChannel *channel, uint64_t timestamp, uint64_t timeout_uS) +int shm_td_iq_channel_wait(ShmTDIQChannel *channel, uint64_t timestamp, uint64_t timeout_uS) { ShmTDIQChannelData *data = channel->data; size_t current_timestamp = data->timestamp; if (current_timestamp >= timestamp) { - return; + return 0; } if (timeout_uS == 0) { mutexlock(data->mutex); @@ -241,8 +241,7 @@ void shm_td_iq_channel_wait(ShmTDIQChannel *channel, uint64_t timestamp, uint64_ struct timespec ts = {.tv_sec = 0, .tv_nsec = 0}; if (clock_gettime(CLOCK_REALTIME, &ts) != 0) { fprintf(stderr, "Error: clock_gettime failed: %s\n", strerror(errno)); - channel->abort = true; - return; + return 1; } ts.tv_sec += timeout_uS / 1000000; // Convert microseconds to seconds @@ -252,19 +251,20 @@ void shm_td_iq_channel_wait(ShmTDIQChannel *channel, uint64_t timestamp, uint64_ while (current_timestamp < timestamp && !channel->abort) { int ret = pthread_cond_timedwait(&data->cond, &data->mutex, &ts); if (ret == ETIMEDOUT) { - channel->abort = true; - fprintf(stderr, "Error: Timed out waiting for samples. Aborting vrtsim\n");\ - break; + fprintf(stderr, "Error: Timed out waiting for samples.\n"); + mutexunlock(data->mutex); + return 1; } else if (ret != 0) { - channel->abort = true; fprintf(stderr, "Error: pthread_cond_timedwait failed: %s\n", strerror(ret)); - break; + mutexunlock(data->mutex); + return 1; } else { current_timestamp = data->timestamp; } } mutexunlock(data->mutex); } + return 0; } uint64_t shm_td_iq_channel_get_current_sample(const ShmTDIQChannel *channel) diff --git a/common/utils/shm_iq_channel/shm_td_iq_channel.h b/common/utils/shm_iq_channel/shm_td_iq_channel.h index 8c7bfad318..b71720c1f9 100644 --- a/common/utils/shm_iq_channel/shm_td_iq_channel.h +++ b/common/utils/shm_iq_channel/shm_td_iq_channel.h @@ -120,8 +120,10 @@ void shm_td_iq_channel_produce_samples(ShmTDIQChannel *channel, uint64_t num_sam * @param channel The ShmTDIQChannel structure. * @param timestamp The timestamp for which to wait. * @param timeout_uS The timeout in microseconds to wait for the sample. 0 means wait indefinitely. + * + * @return 0 if the sample is available, 1 if timed out */ -void shm_td_iq_channel_wait(ShmTDIQChannel *channel, uint64_t timestamp, uint64_t timeout_uS); +int shm_td_iq_channel_wait(ShmTDIQChannel *channel, uint64_t timestamp, uint64_t timeout_uS); /** * @brief Aborts the IQ channel causing the wait to return immediately diff --git a/radio/vrtsim/vrtsim.c b/radio/vrtsim/vrtsim.c index f5d2410bf1..97c820a859 100644 --- a/radio/vrtsim/vrtsim.c +++ b/radio/vrtsim/vrtsim.c @@ -223,6 +223,7 @@ static void *vrtsim_timing_job(void *arg) samples_to_produce += 1; leftover_samples -= 1; } + AssertFatal(samples_to_produce >= 0, "Negative samples to produce: %f\n", samples_to_produce); shm_td_iq_channel_produce_samples(vrtsim_state->channel, samples_to_produce); usleep(1); } @@ -544,6 +545,12 @@ static int vrtsim_write_with_chanmod(vrtsim_state_t *vrtsim_state, static int vrtsim_write(openair0_device *device, openair0_timestamp timestamp, void **samplesVoid, int nsamps, int nbAnt, int flags) { + AssertFatal(nsamps > 0, "Number of samples must be greater than 0\n"); + AssertFatal(nbAnt > 0 && nbAnt <= MAX_NUM_ANTENNAS_TX, + "Number of antennas %d must be between 1 and %d\n", + nbAnt, + MAX_NUM_ANTENNAS_TX); + AssertFatal(timestamp >= 0, "Timestamp must be non-negative, got %ld\n", timestamp); timestamp -= device->openair0_cfg->command_line_sample_advance; vrtsim_state_t *vrtsim_state = (vrtsim_state_t *)device->priv; bool channel_modelling = vrtsim_state->chanmod || vrtsim_state->taps_socket; @@ -555,13 +562,29 @@ static int vrtsim_read(openair0_device *device, openair0_timestamp *ptimestamp, { vrtsim_state_t *vrtsim_state = (vrtsim_state_t *)device->priv; if (shm_td_iq_channel_is_aborted(vrtsim_state->channel)) { - for (int i = 0; i < nbAnt; i++) { - memset(samplesVoid[i], 0, sizeof(c16_t) * nsamps); - } - return nsamps; + return 0; } - uint64_t timeout_uS = 2 * 1000 * 1000 / vrtsim_state->timescale; // 2 seconds in uS - shm_td_iq_channel_wait(vrtsim_state->channel, vrtsim_state->last_received_sample + nsamps, timeout_uS); + if (vrtsim_state->role == ROLE_SERVER) { + uint64_t timeout_uS = 0; // 0 means no timeout + shm_td_iq_channel_wait(vrtsim_state->channel, vrtsim_state->last_received_sample + nsamps, timeout_uS); + } else { + uint64_t start_sample = shm_td_iq_channel_get_current_sample(vrtsim_state->channel); + uint64_t timeout_uS = 2 * 1000 * 1000; // 2 seconds timeout waiting for sample number to change + // + while (shm_td_iq_channel_wait(vrtsim_state->channel, vrtsim_state->last_received_sample + nsamps, timeout_uS) == 1) { + uint64_t sample = shm_td_iq_channel_get_current_sample(vrtsim_state->channel); + if (sample == start_sample) { + LOG_E(HW, + "VRTSIM: Read timeout waiting for sample %lu to change, aborting channel\n", + vrtsim_state->last_received_sample + nsamps); + shm_td_iq_channel_abort(vrtsim_state->channel); + break; + } else { + start_sample = sample; + } + } + } + int ret = shm_td_iq_channel_rx(vrtsim_state->channel, vrtsim_state->last_received_sample, nsamps, 0, samplesVoid[0]); if (ret == CHANNEL_ERROR_TOO_LATE) { vrtsim_state->rx_samples_late += nsamps; From ea3a4b991c33be95c19b8e3e0b978650d8e677a0 Mon Sep 17 00:00:00 2001 From: Bartosz Podrygajlo Date: Fri, 8 Aug 2025 17:24:40 +0200 Subject: [PATCH 534/964] VRTSIM: allow client reconnection via a connection descriptor file Replace the unwieldy unix socket implementation of peer information exchange with an authorative connection descriptor file that informs the client of the connection method an number of antennas on the server. This allows the server to run without the client and allows the client to reconnect as long as the server is running, as many times as needed. --- radio/vrtsim/vrtsim.c | 186 ++++++++++++++++++------------------------ 1 file changed, 78 insertions(+), 108 deletions(-) diff --git a/radio/vrtsim/vrtsim.c b/radio/vrtsim/vrtsim.c index 97c820a859..9e678a5305 100644 --- a/radio/vrtsim/vrtsim.c +++ b/radio/vrtsim/vrtsim.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -62,15 +63,20 @@ typedef enum { ROLE_SERVER = 1, ROLE_CLIENT } role; #define TIME_SCALE_HLP \ "sample time scale. 1.0 means realtime. Values > 1 mean faster than realtime. Values < 1 mean slower than realtime\n" #define TAPS_SOCKET_HLP "Socket to connect to the channel emulation server\n" +#define CLIENT_NUM_RX_HLP "Number of RX antennas of the client, specified on the server\n" +#define CONNECTION_DESCRIPTOR_HLP "Path to the file written by the server that the client can use to connect." +#define DEFAULT_CHANNEL_NAME "vrtsim_channel" +#define DEFAULT_DESCRIPTOR "/tmp/vrtsim_connection" // clang-format off #define VRTSIM_PARAMS_DESC \ { \ - {"channel_name", "shared memory channel name\n", 0, .strptr = &channel_name, .defstrval = "vrtsim_channel", TYPE_STRING, 0}, \ - {"role", "either client or server\n", 0, .strptr = &role, .defstrval = ROLE_CLIENT_STRING, TYPE_STRING, 0}, \ - {"timescale", TIME_SCALE_HLP, 0, .dblptr = &vrtsim_state->timescale, .defdblval = 1.0, TYPE_DOUBLE, 0}, \ - {"chanmod", "Enable channel modelling", 0, .iptr = &vrtsim_state->chanmod, .defintval = 0, TYPE_INT, 0}, \ - {"taps-socket", TAPS_SOCKET_HLP, 0, .strptr = &vrtsim_state->taps_socket, .defstrval = NULL, TYPE_STRING, 0}, \ + {"connection_descriptor", CONNECTION_DESCRIPTOR_HLP, 0, .strptr = &vrtsim_state->connection_descriptor, .defstrval = DEFAULT_DESCRIPTOR, TYPE_STRING, 0}, \ + {"role", "either client or server\n", 0, .strptr = &role, .defstrval = ROLE_CLIENT_STRING, TYPE_STRING, 0}, \ + {"timescale", TIME_SCALE_HLP, 0, .dblptr = &vrtsim_state->timescale, .defdblval = 1.0, TYPE_DOUBLE, 0}, \ + {"chanmod", "Enable channel modelling", 0, .iptr = &vrtsim_state->chanmod, .defintval = 0, TYPE_INT, 0}, \ + {"taps-socket", TAPS_SOCKET_HLP, 0, .strptr = &vrtsim_state->taps_socket, .defstrval = NULL, TYPE_STRING, 0}, \ + {"client-num-rx-antennas", CLIENT_NUM_RX_HLP, 0, .iptr = &vrtsim_state->client_num_rx_antennas, .defintval = 1, TYPE_INT, 0}, \ }; // clang-format on @@ -96,7 +102,7 @@ typedef struct tx_timing_s { typedef struct { int role; - char channel_name[40]; + char *connection_descriptor; ShmTDIQChannel *channel; uint64_t last_received_sample; pthread_t timing_thread; @@ -116,6 +122,7 @@ typedef struct { channel_desc_t *channel_desc; Actor_t *channel_modelling_actors; char *taps_socket; + int client_num_rx_antennas; } vrtsim_state_t; // Sample history for channel impulse response @@ -174,12 +181,10 @@ static void load_channel_model(vrtsim_state_t *vrtsim_state) static void vrtsim_readconfig(vrtsim_state_t *vrtsim_state) { - char *channel_name = NULL; char *role = NULL; paramdef_t vrtsim_params[] = VRTSIM_PARAMS_DESC; int ret = config_get(config_get_if(), vrtsim_params, sizeofArray(vrtsim_params), VRTSIM_SECTION); AssertFatal(ret >= 0, "configuration couldn't be performed\n"); - strncpy(vrtsim_state->channel_name, channel_name, sizeof(vrtsim_state->channel_name) - 1); if (strncmp(role, ROLE_CLIENT_STRING, strlen(ROLE_CLIENT_STRING)) == 0) { vrtsim_state->role = ROLE_CLIENT; } else if (strncmp(role, ROLE_SERVER_STRING, strlen(ROLE_SERVER_STRING)) == 0) { @@ -230,112 +235,80 @@ static void *vrtsim_timing_job(void *arg) return 0; } +typedef struct client_info_s { + int server_num_rx_antennas; + int client_num_rx_antennas; +} client_info_t; + /** - * @brief Exchanges peer information between the server and the client. + * @brief Publishes the client information information to a file for the client to read. * - * This function sets up a Unix domain socket server, waits for a client to connect, - * and exchanges peer information (number of RX antennas) with the client. + * The server writes its client_info (number of RX antennas) to a file, which the client reads. + * The server does not wait for the client to write back; the client can connect at any point. * - * @param peer_info The peer information to send to the client. - * @return The peer information received from the client. - * - * @note This function will block until a client connects and the information is exchanged. + * @param client_info The client information to publish. + * @return The peer information (same as input, server is authoritative). */ -static peer_info_t server_exchange_peer_info(peer_info_t peer_info) +static void server_publish_client_info(client_info_t client_info, char *descriptor_file) { - int server_fd, client_fd; - - // Create a Unix domain socket - server_fd = socket(AF_UNIX, SOCK_STREAM, 0); - AssertFatal(server_fd >= 0, "socket() failed: errno: %d, %s\n", errno, strerror(errno)); - - // Bind the socket to a file path - struct sockaddr_un addr = {.sun_family = AF_UNIX}; - strncpy(addr.sun_path, "/tmp/vrtsim_socket", sizeof(addr.sun_path) - 1); - unlink(addr.sun_path); // Ensure the path does not already exist - int ret = bind(server_fd, (struct sockaddr *)&addr, sizeof(addr)); - AssertFatal(ret == 0, "bind() failed: errno: %d, %s\n", errno, strerror(errno)); - - // Listen for incoming connections - ret = listen(server_fd, 1); - AssertFatal(ret == 0, "listen() failed: errno: %d, %s\n", errno, strerror(errno)); - - // Accept a connection from a client - socklen_t addr_len = sizeof(addr); - client_fd = accept(server_fd, (struct sockaddr *)&addr, &addr_len); - AssertFatal(client_fd >= 0, "accept() failed: errno: %d, %s\n", errno, strerror(errno)); - - // Send the antenna info to the server - ssize_t bytes_sent = send(client_fd, &peer_info, sizeof(peer_info), 0); - AssertFatal(bytes_sent == sizeof(peer_info), "send() failed: errno: %d, %s\n", errno, strerror(errno)); - - ssize_t bytes_received = recv(client_fd, &peer_info, sizeof(peer_info), 0); - AssertFatal(bytes_received == sizeof(peer_info), "recv() failed: errno: %d, %s\n", errno, strerror(errno)); - - LOG_I(HW, "Received client info: RX %d\n", peer_info.num_rx_antennas); - - // Close the client and server sockets - close(client_fd); - close(server_fd); - return peer_info; + FILE *fp = fopen(descriptor_file, "wb"); + AssertFatal(fp != NULL, "Failed to open client info file for writing: %s\n", strerror(errno)); + size_t written = fwrite(&client_info, sizeof(client_info), 1, fp); + AssertFatal(written == 1, "Failed to write client info to file\n"); + fclose(fp); } -/** - * @brief Exchanges peer information between the client and the server. - * - * This function connects to a Unix domain socket server, exchanges peer information - * (number of RX antennas) with the server, and returns the peer information received - * from the server. - * - * @param peer_info The peer information to send to the server. - * @return The peer information received from the server. - * - * @note This function will block until the information is exchanged. - */ -static peer_info_t client_exchange_peer_info(peer_info_t peer_info) +static client_info_t client_read_info(char *descriptor_file) { - int client_fd; - - // Create a Unix domain socket - client_fd = socket(AF_UNIX, SOCK_STREAM, 0); - AssertFatal(client_fd >= 0, "socket() failed: errno: %d, %s\n", errno, strerror(errno)); - - // Connect to the server - struct sockaddr_un addr = {.sun_family = AF_UNIX}; - strncpy(addr.sun_path, "/tmp/vrtsim_socket", sizeof(addr.sun_path) - 1); - int ret = -1; + client_info_t client_info; int tries = 0; - while (ret != 0 && tries < 10) { - ret = connect(client_fd, (struct sockaddr *)&addr, sizeof(addr)); - tries++; + while (tries < 10) { + FILE *fp = fopen(descriptor_file, "rb"); + if (fp) { + size_t read = fread(&client_info, sizeof(client_info), 1, fp); + fclose(fp); + if (read == 1) { + return client_info; + } + } sleep(1); + tries++; } - AssertFatal(ret == 0, "connect() failed: errno: %d, %s\n", errno, strerror(errno)); - - peer_info_t peer_info_received; - ssize_t bytes_received = recv(client_fd, &peer_info_received, sizeof(peer_info_received), 0); - AssertFatal(bytes_received == sizeof(peer_info_received), "recv() failed: errno: %d, %s\n", errno, strerror(errno)); - - // Send the antenna info to the server - ssize_t bytes_sent = send(client_fd, &peer_info, sizeof(peer_info), 0); - AssertFatal(bytes_sent == sizeof(peer_info), "send() failed: errno: %d, %s\n", errno, strerror(errno)); - - LOG_I(HW, "Received peer info: RX %d\n", peer_info_received.num_rx_antennas); - - // Close the client socket - close(client_fd); - return peer_info_received; + AssertFatal(0, "Timeout waiting for client info\n"); + return client_info; } static int vrtsim_connect(openair0_device *device) { vrtsim_state_t *vrtsim_state = (vrtsim_state_t *)device->priv; - // Exchange peer info - peer_info_t peer_info = {.num_rx_antennas = device->openair0_cfg[0].rx_num_channels}; + + // Setup a shared memory channel if (vrtsim_state->role == ROLE_SERVER) { - vrtsim_state->peer_info = server_exchange_peer_info(peer_info); + vrtsim_state->peer_info.num_rx_antennas = vrtsim_state->client_num_rx_antennas; + vrtsim_state->channel = shm_td_iq_channel_create(DEFAULT_CHANNEL_NAME, + vrtsim_state->peer_info.num_rx_antennas, + device->openair0_cfg[0].rx_num_channels); + // Exchange peer info + client_info_t client_info = { + .server_num_rx_antennas = device->openair0_cfg[0].rx_num_channels, + .client_num_rx_antennas = vrtsim_state->client_num_rx_antennas, + }; + server_publish_client_info(client_info, vrtsim_state->connection_descriptor); + + vrtsim_state->run_timing_thread = true; + int ret = pthread_create(&vrtsim_state->timing_thread, NULL, vrtsim_timing_job, vrtsim_state); + AssertFatal(ret == 0, "pthread_create() failed: errno: %d, %s\n", errno, strerror(errno)); } else { - vrtsim_state->peer_info = client_exchange_peer_info(peer_info); + client_info_t client_info = client_read_info(vrtsim_state->connection_descriptor); + AssertFatal(client_info.server_num_rx_antennas > 0, "Server did not publish valid client info, aborting client connection\n"); + AssertFatal( + client_info.client_num_rx_antennas == device->openair0_cfg[0].rx_num_channels, + "Server expects different number of RX antennas. %d != %d. Use server command line option --client-num-rx-antennas\n", + client_info.client_num_rx_antennas, + device->openair0_cfg[0].rx_num_channels); + vrtsim_state->channel = shm_td_iq_channel_connect(DEFAULT_CHANNEL_NAME, 10); + vrtsim_state->peer_info.num_rx_antennas = client_info.server_num_rx_antennas; + vrtsim_state->last_received_sample = shm_td_iq_channel_get_current_sample(vrtsim_state->channel); } // Handle channel modelling after number of RX antennas are known @@ -363,18 +336,6 @@ static int vrtsim_connect(openair0_device *device) vrtsim_state->tx_timing[i].tx_histogram.range = 3000.0; } - // Setup a shared memory channel - if (vrtsim_state->role == ROLE_SERVER) { - vrtsim_state->channel = shm_td_iq_channel_create(vrtsim_state->channel_name, - vrtsim_state->peer_info.num_rx_antennas, - device->openair0_cfg[0].rx_num_channels); - vrtsim_state->run_timing_thread = true; - int ret = pthread_create(&vrtsim_state->timing_thread, NULL, vrtsim_timing_job, vrtsim_state); - AssertFatal(ret == 0, "pthread_create() failed: errno: %d, %s\n", errno, strerror(errno)); - } else { - vrtsim_state->channel = shm_td_iq_channel_connect(vrtsim_state->channel_name, 10); - } - return 0; } @@ -640,6 +601,15 @@ static void vrtsim_end(openair0_device *device) LOG_I(HW, "VRTSIM: Average TX budget %.3lf uS (more is better)\n", tx_timing->average_tx_budget); histogram_print(&tx_timing->tx_histogram); free(vrtsim_state->tx_timing); + + if (vrtsim_state->role == ROLE_SERVER) { + int ret = remove(vrtsim_state->connection_descriptor); + if (ret != 0) { + LOG_E(HW, "Failed to remove connection descriptor file %s: %s\n", vrtsim_state->connection_descriptor, strerror(errno)); + } else { + LOG_A(HW, "Removed connection descriptor file %s\n", vrtsim_state->connection_descriptor); + } + } } static int vrtsim_stub(openair0_device *device) From 74fc56813f8157ca7051768f1121004d1db90fcf Mon Sep 17 00:00:00 2001 From: Bartosz Podrygajlo Date: Fri, 8 Aug 2025 17:55:12 +0200 Subject: [PATCH 535/964] Update vrtsim documentation --- radio/vrtsim/README.md | 80 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 75 insertions(+), 5 deletions(-) diff --git a/radio/vrtsim/README.md b/radio/vrtsim/README.md index 71455175c3..2cd90e7886 100644 --- a/radio/vrtsim/README.md +++ b/radio/vrtsim/README.md @@ -4,12 +4,24 @@ This implements a shared memory realtime and near-realtime radio interface. This is performed using `shm_td_iq_channel` which handles the shared memory interface. +# Architecture + +The `vrtsim` architecture follows a server-client model: + +- **Server (gNB)**: On startup, the server writes a file, default location is + `/tmp/vrtsim_connection`. This file contains information required by the client + to establish communication. +- **Client (UE)**: The client reads this file from, verifies its contents, and uses + the provided information to open and connect to the shared memory channel. +- **Shared Memory Channel**: Both server and client use the `shm_td_iq_channel` to + exchange IQ samples and control data in real time or near-real time. + +## Channel modelling: + + # Limitations - Only 1gNB to 1nrUE: gNB as a server, UE as a client. - - Server only accepts connections during device bringup. This means that - restarting the client will not make it reconnect, the server has to be - restarted as well. # Usage @@ -21,5 +33,63 @@ is the default and means realtime. Channel modelling can be enabled by adding `vrtsim.chanmod 1` to the command line and should work the same as channel modelling in rfsimulator, -see rfsimulator [documentation](../rfsimulator/README.md), provided that your -CPU is fast enough. +see rfsimulator [documentation](../rfsimulator/README.md) with a slight difference: +channel modelling is done on transmission instead of reception. To refect this, +the model names are slightly different: the server expects a model named +`server_tx_channel_model` while the client expects a model named `client_tx_channel_model` + +Additionally, `taps_client` is available in vrtsim. This allows to connect to +channel emulation server and receive external taps (or channel impulse responses). +To use external taps, use `--taps-socket` and provide a nanomsg PUB socket address +that will publish the taps. + +# Debugging + +## Realtime issues + +Realtime issues can prevent the UE from connecting to the gNB, especially with +channel modelling enabled. Consider adjusting `timescale` parameter until +the UE can connect reliably. + +On exit, vrtsim will output a histogram of the measured transmission budget, which +is defined as the number of microseconds before the transmitted samples could be +read by peer. + +Example: + +``` +[HW] VRTSIM: Average TX budget 939.210 uS (more is better) +[HW] VRTSIM: TX budget histogram: 216 samples +[HW] Bin 0 [0.0 - 100.0uS]: 0 +[HW] Bin 1 [100.0 - 200.0uS]: 0 +[HW] Bin 2 [200.0 - 300.0uS]: 0 +[HW] Bin 3 [300.0 - 400.0uS]: 0 +[HW] Bin 4 [400.0 - 500.0uS]: 0 +[HW] Bin 5 [500.0 - 600.0uS]: 0 +[HW] Bin 6 [600.0 - 700.0uS]: 0 +[HW] Bin 7 [700.0 - 800.0uS]: 0 +[HW] Bin 8 [800.0 - 900.0uS]: 0 +[HW] Bin 9 [900.0 - 1000.0uS]: 117 +[HW] Bin 10 [1000.0 - 1100.0uS]: 0 +[HW] Bin 11 [1100.0 - 1200.0uS]: 0 +[HW] Bin 12 [1200.0 - 1300.0uS]: 0 +[HW] Bin 13 [1300.0 - 1400.0uS]: 0 +[HW] Bin 14 [1400.0 - 1500.0uS]: 0 +[HW] Bin 15 [1500.0 - 1600.0uS]: 0 +[HW] Bin 16 [1600.0 - 1700.0uS]: 0 +[HW] Bin 17 [1700.0 - 1800.0uS]: 0 +[HW] Bin 18 [1800.0 - 1900.0uS]: 0 +[HW] Bin 19 [1900.0 - 2000.0uS]: 0 +[HW] Bin 20 [2000.0 - 2100.0uS]: 0 +[HW] Bin 21 [2100.0 - 2200.0uS]: 0 +[HW] Bin 22 [2200.0 - 2300.0uS]: 0 +[HW] Bin 23 [2300.0 - 2400.0uS]: 0 +[HW] Bin 24 [2400.0 - 2500.0uS]: 0 +[HW] Bin 25 [2500.0 - 2600.0uS]: 0 +[HW] Bin 26 [2600.0 - 2700.0uS]: 0 +[HW] Bin 27 [2700.0 - 2800.0uS]: 0 +[HW] Bin 28 [2800.0 - 2900.0uS]: 0 +[HW] Bin 29 [2900.0 - 3000.0uS]: 0 +``` + +Samples in bin 0 indicate realtime issues. From 171b3f206f415f28fda86d6fa2934d384b77de0b Mon Sep 17 00:00:00 2001 From: Bartosz Podrygajlo Date: Mon, 18 Aug 2025 09:43:34 +0200 Subject: [PATCH 536/964] VRTsim: Add a timeout in taps client Add a timeout in nanomsg receive code to allow the client thread to exit cleanly. --- radio/vrtsim/taps_client.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/radio/vrtsim/taps_client.cpp b/radio/vrtsim/taps_client.cpp index 6ebfc450fd..c314c3981c 100644 --- a/radio/vrtsim/taps_client.cpp +++ b/radio/vrtsim/taps_client.cpp @@ -108,8 +108,13 @@ void *client_thread_func(void *args) while (should_run) { int next_buffer = (taps_storage.current_buffer + 1) % NUM_TAPS_BUFFERS; taps_buffer_t *taps_buffer = &taps_storage.taps_buffers[next_buffer]; - int ret = nn_recv(client_thread_args->sock, taps_buffer->taps_msg, MAX_TAPS_MSG_SIZE, 0); + int ret = nn_recv(client_thread_args->sock, taps_buffer->taps_msg, MAX_TAPS_MSG_SIZE, NN_DONTWAIT); if (ret < 0) { + if (errno == EAGAIN) { + // Timeout: no message available, sleep briefly and continue + usleep(100); + continue; + } LOG_E(HW, "nn_recv() failed: errno: %d, %s\n", errno, strerror(errno)); continue; } From 513173ae0d1bc6a1304c663ecd0407042a786919 Mon Sep 17 00:00:00 2001 From: Bartosz Podrygajlo Date: Mon, 18 Aug 2025 09:51:27 +0200 Subject: [PATCH 537/964] Rename VRTSIM cmake option to OAI_VRTSIM --- radio/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/radio/CMakeLists.txt b/radio/CMakeLists.txt index 654fb037f0..e68c84ec90 100644 --- a/radio/CMakeLists.txt +++ b/radio/CMakeLists.txt @@ -38,7 +38,7 @@ if(OAI_USRP) add_subdirectory(USRP) endif() -add_boolean_option(VRTSIM_RADIO ON "Activate OAI's shared memory radio driver" OFF) -if(VRTSIM_RADIO) +add_boolean_option(OAI_VRTSIM ON "Activate OAI's shared memory radio driver" OFF) +if(OAI_VRTSIM) add_subdirectory(vrtsim) endif() From c35f07b0b91e39d1fda9688232af45fb6dfa00b3 Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Thu, 24 Jul 2025 17:05:43 +0200 Subject: [PATCH 538/964] GTPU: add an API to better deal with extension headers And adapt existing code to use it. Only for transmission for the moment. --- CMakeLists.txt | 3 +- openair3/ocp-gtpu/gtp_itf.cpp | 131 +++++++++++++------------- openair3/ocp-gtpu/gtpu_extensions.c | 137 ++++++++++++++++++++++++++++ openair3/ocp-gtpu/gtpu_extensions.h | 75 +++++++++++++++ 4 files changed, 276 insertions(+), 70 deletions(-) create mode 100644 openair3/ocp-gtpu/gtpu_extensions.c create mode 100644 openair3/ocp-gtpu/gtpu_extensions.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 898b387237..bfd4b3f7c1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1395,9 +1395,10 @@ include_directories("${OPENAIR1_DIR}/SCHED_NR_UE") add_library (GTPV1U ${RRC_DIR}/rrc_eNB_GTPV1U.c ${OPENAIR3_DIR}/ocp-gtpu/gtp_itf.cpp + ${OPENAIR3_DIR}/ocp-gtpu/gtpu_extensions.c ) target_link_libraries(GTPV1U PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) -target_link_libraries(GTPV1U PRIVATE SIMU) +target_link_libraries(GTPV1U PRIVATE SIMU ds) include_directories(${OPENAIR3_DIR}/ocp-gtp) set (MME_APP_SRC diff --git a/openair3/ocp-gtpu/gtp_itf.cpp b/openair3/ocp-gtpu/gtp_itf.cpp index 9e07a44747..5d910e8027 100644 --- a/openair3/ocp-gtpu/gtp_itf.cpp +++ b/openair3/ocp-gtpu/gtp_itf.cpp @@ -21,6 +21,7 @@ extern "C" { #include #include #include "openair2/SDAP/nr_sdap/nr_sdap.h" +#include "openair3/ocp-gtpu/gtpu_extensions.h" #include "sim.h" #pragma pack(1) @@ -230,11 +231,9 @@ static int gtpv1uCreateAndSendMsg(gtpv1u_bearer_t *bearer, int msgLen, bool seqNumFlag, bool npduNumFlag, - int extHdrType, - uint8_t *extensionHeader_buffer, - uint8_t extensionHeader_length) + gtpu_extension_header_t *extensions, + int extensions_count) { - DevAssert(msgLen + HDR_MAX < 65536); // maximum size of UDP packet uint8_t buffer[msgLen + HDR_MAX]; uint8_t *curPtr = buffer; @@ -242,7 +241,7 @@ static int gtpv1uCreateAndSendMsg(gtpv1u_bearer_t *bearer, // N should be 0 for us (it was used only in 2G and 3G) msgHdr->PN = npduNumFlag; msgHdr->S = seqNumFlag; - msgHdr->E = extHdrType != NO_MORE_EXT_HDRS; + msgHdr->E = extensions_count != 0; msgHdr->spare = 0; // PT=0 is for GTP' TS 32.295 (charging) msgHdr->PT = 1; @@ -252,32 +251,32 @@ static int gtpv1uCreateAndSendMsg(gtpv1u_bearer_t *bearer, curPtr += sizeof(Gtpv1uMsgHeaderT); - if (seqNumFlag || (extHdrType != NO_MORE_EXT_HDRS) || npduNumFlag) { + if (msgHdr->PN || msgHdr->S || msgHdr->E) { *(uint16_t *)curPtr = seqNumFlag ? bearer->seqNum : 0x0000; curPtr += sizeof(uint16_t); *(uint8_t *)curPtr = npduNumFlag ? bearer->npduNum : 0x00; curPtr++; - *(uint8_t *)curPtr = extHdrType; + *curPtr = extensions_count ? serialize_gtpu_extension_type(extensions[0].type) : 0; curPtr++; } - // Bug: if there is more than one extension, infinite loop on extensionHeader_buffer - while (extHdrType != NO_MORE_EXT_HDRS) { - if (extensionHeader_length > 0) { - memcpy(curPtr, extensionHeader_buffer, extensionHeader_length); - curPtr += extensionHeader_length; - LOG_D(GTPU, - "Extension Header for DDD added. The length is: %d, extension header type is: %x \n", - extensionHeader_length, - *((uint8_t *)(buffer + 11))); - extHdrType = extensionHeader_buffer[extensionHeader_length - 1]; - LOG_D(GTPU, "Next extension header type is: %x \n", *((uint8_t *)(buffer + 11))); - } else { - LOG_W(GTPU, "Extension header type not supported, returning... \n"); + for (int i = 0; i < extensions_count; i++) { + int available_size = sizeof(buffer) - (curPtr - buffer); + gtpu_extension_header_type_t next = i == extensions_count - 1 ? GTPU_EXT_NONE : extensions[i + 1].type; + int len = serialize_extension(&extensions[i], next, curPtr, available_size); + if (len == -1) { + LOG_E(GTPU, "GTP extension serialization: buffer too small\n"); + return GTPNOK; } + curPtr += len; } if (Msg != NULL) { + int available_size = sizeof(buffer) - (curPtr - buffer); + if (msgLen > available_size) { + LOG_E(GTPU, "GTP message creation: buffer too small\n"); + return GTPNOK; + } memcpy(curPtr, Msg, msgLen); curPtr += msgLen; } @@ -347,18 +346,22 @@ void gtpv1uSendDirect(instance_t instance, gtpv1u_bearer_t bearer = ptr2->second; pthread_mutex_unlock(&globGtp.gtp_lock); - Gtpv1uExtHeaderT *opt_ext = NULL; - Gtpv1uExtHeaderT ext = {0}; + int extension_count = 0; + gtpu_extension_header_t ext = {}; if (bearer.outgoing_qfi != -1) { - opt_ext = &ext; - ext.ExtHeaderLen = 1; // in quad bytes EXT_HDR_LNTH_OCTET_UNITS - ext.pdusession_cntr.spare = 0; - ext.pdusession_cntr.PDU_type = UL_PDU_SESSION_INFORMATION; - ext.pdusession_cntr.QFI = bearer.outgoing_qfi; - ext.pdusession_cntr.Reflective_QoS_activation = false; - ext.pdusession_cntr.Paging_Policy_Indicator = false; - ext.NextExtHeaderType = NO_MORE_EXT_HDRS; - + ext = { + .type = GTPU_EXT_UL_PDU_SESSION_INFORMATION, + .ul_pdu_session_information = { + .qmp = false, + .dl_delay_ind = false, + .ul_delay_ind = false, + .snp = false, + .n3n9_delay_ind = false, + .new_ie_flag = false, + .qfi = bearer.outgoing_qfi + } + }; + extension_count++; } DevAssert(compatInst(instance) == bearer.sock_fd); @@ -368,9 +371,30 @@ void gtpv1uSendDirect(instance_t instance, len, seqNumFlag, npduNumFlag, - opt_ext ? PDU_SESSION_CONTAINER : NO_MORE_EXT_HDRS, - (uint8_t *)opt_ext, - sizeof(*opt_ext)); + &ext, + extension_count); +} + +static void fillDlDeliveryStatusReport(gtpu_extension_header_t *ext, uint32_t RLC_buffer_availability, uint32_t NR_PDCP_PDU_SN) +{ + *ext = { + .type = GTPU_EXT_DL_DATA_DELIVERY_STATUS, + .dl_data_delivery_status = { + /* previous version of the code was sending highest_transmitted_nr_pdcp_sn if + * it is != 0, let's do the same for the moment */ + .highest_transmitted_nr_pdcp_sn_ind = NR_PDCP_PDU_SN != 0, + .highest_delivered_nr_pdcp_sn_ind = false, + .final_frame_ind = false, + .lost_packet_report = false, + .delivered_nr_pdcp_sn_range_ind = false, + .data_rate_ind = false, + .retransmitted_nr_pdcp_sn_ind = false, + .delivered_retransmitted_nr_pdcp_ind = false, + .cause_report = false, + .desired_buffer_size = RLC_buffer_availability, + .highest_transmitted_nr_pdcp_sn = NR_PDCP_PDU_SN + } + }; } static void gtpv1uEndTunnel(instance_t instance, gtpv1u_enb_end_marker_req_t *req) @@ -950,7 +974,6 @@ static int Gtpv1uHandleEchoReq(int h, uint8_t *msgBuf, uint32_t msgBufLen, const sizeof recovery, true, false, - NO_MORE_EXT_HDRS, NULL, 0); } @@ -1168,37 +1191,8 @@ static int Gtpv1uHandleGpdu(int h, uint8_t *msgBuf, uint32_t msgBufLen, const st LOG_D(GTPU, "Create and send DL DATA Delivery status for the previously received PDU, NR_PDCP_PDU_SN: %u \n", NR_PDCP_PDU_SN); int rlc_tx_buffer_space = nr_rlc_get_available_tx_space(ctxt.rntiMaybeUEid, rb_id + 3); LOG_D(GTPU, "Available buffer size in RLC for Tx: %d \n", rlc_tx_buffer_space); - /*Total size of DDD_status PDU = 1 octet to report extension header length - * size of mandatory part + 3 octets for highest transmitted/delivered PDCP SN - * 1 octet for padding + 1 octet for next extension header type, - * according to TS 38.425: Fig. 5.5.2.2-1 and section 5.5.3.24*/ - extensionHeader_t *extensionHeader; - extensionHeader = (extensionHeader_t *)calloc(1, sizeof(extensionHeader_t)); - extensionHeader->buffer[0] = (1 + sizeof(DlDataDeliveryStatus_flagsT) + 3 + 1 + 1) / 4; - DlDataDeliveryStatus_flagsT DlDataDeliveryStatus; - DlDataDeliveryStatus.deliveredPdcpSn = 0; - DlDataDeliveryStatus.transmittedPdcpSn = 1; - DlDataDeliveryStatus.pduType = 1; - DlDataDeliveryStatus.drbBufferSize = - htonl(rlc_tx_buffer_space); // htonl(10000000); //hardcoded for now but normally we should extract it from RLC - memcpy(extensionHeader->buffer + 1, &DlDataDeliveryStatus, sizeof(DlDataDeliveryStatus_flagsT)); - uint8_t offset = sizeof(DlDataDeliveryStatus_flagsT) + 1; - - extensionHeader->buffer[offset] = (NR_PDCP_PDU_SN >> 16) & 0xff; - extensionHeader->buffer[offset + 1] = (NR_PDCP_PDU_SN >> 8) & 0xff; - extensionHeader->buffer[offset + 2] = NR_PDCP_PDU_SN & 0xff; - LOG_D(GTPU, - "Octets reporting NR_PDCP_PDU_SN, extensionHeader-> %u:%u:%u \n", - extensionHeader->buffer[offset], - extensionHeader->buffer[offset + 1], - extensionHeader->buffer[offset + 2]); - extensionHeader->buffer[offset + 3] = 0x00; // Padding octet - extensionHeader->buffer[offset + 4] = 0x00; // No more extension headers - /*Total size of DDD_status PDU = size of mandatory part + - * 3 octets for highest transmitted/delivered PDCP SN + - * 1 octet for padding + 1 octet for next extension header type, - * according to TS 38.425: Fig. 5.5.2.2-1 and section 5.5.3.24*/ - extensionHeader->length = 1 + sizeof(DlDataDeliveryStatus_flagsT) + 3 + 1 + 1; + gtpu_extension_header_t ext; + fillDlDeliveryStatusReport(&ext, rlc_tx_buffer_space, NR_PDCP_PDU_SN); uint32_t teid = globGtp.te2ue_mapping[ntohl(msgHdr->teid)].outgoing_teid; gtpv1u_bearer_t bearer = create_bearer(h, addr, teid, 0); gtpv1uCreateAndSendMsg(&bearer, @@ -1207,9 +1201,8 @@ static int Gtpv1uHandleGpdu(int h, uint8_t *msgBuf, uint32_t msgBufLen, const st 0, false, false, - NR_RAN_CONTAINER, - extensionHeader->buffer, - extensionHeader->length); + &ext, + 1); } LOG_D(GTPU, "[%d] Received a %d bytes packet for: teid:%x\n", h, msgBufLen - offset, ntohl(msgHdr->teid)); diff --git a/openair3/ocp-gtpu/gtpu_extensions.c b/openair3/ocp-gtpu/gtpu_extensions.c new file mode 100644 index 0000000000..b06e20e23e --- /dev/null +++ b/openair3/ocp-gtpu/gtpu_extensions.c @@ -0,0 +1,137 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include "gtpu_extensions.h" +#include "common/utils/assertions.h" +#include "common/utils/ds/byte_array_producer.h" +#include "LOG/log.h" + +/* 29.281 Figure 5.2.1-3 */ +#define NR_RAN_CONTAINER 0x84 +#define PDU_SESSION_CONTAINER 0x85 + +/* from an extension type, returns its "extension header type" + * as defined in 29.281 Figure 5.2.1-3 + */ +int serialize_gtpu_extension_type(gtpu_extension_header_type_t type) +{ + switch (type) { + case GTPU_EXT_NONE: + /* 0, no more extension */ + return 0; + case GTPU_EXT_UL_PDU_SESSION_INFORMATION: + return PDU_SESSION_CONTAINER; + case GTPU_EXT_DL_DATA_DELIVERY_STATUS: + return NR_RAN_CONTAINER; + default: + AssertFatal(0, "unknown GTPU extension type %d\n", type); + } +} + +/* returns 0 on error, 1 on success */ +static int serialize_ul_pdu_session_information(byte_array_producer_t *b, ul_pdu_session_information_t *ext) +{ + /* see 38.415 5.5.2.2 */ + AssertFatal(!ext->qmp && !ext->dl_delay_ind && !ext->ul_delay_ind + && !ext->snp && !ext->n3n9_delay_ind && !ext->new_ie_flag, + "todo\n"); + + uint8_t b1 = (1 << 4) | (ext->qmp << 3) | (ext->dl_delay_ind << 2) | (ext->ul_delay_ind << 1) | ext->snp; + uint8_t b2 = (ext->n3n9_delay_ind << 7) | (ext->new_ie_flag << 6) | ext->qfi; + return byte_array_producer_put_byte(b, b1) && byte_array_producer_put_byte(b, b2); +} + +/* returns 0 on error, 1 on success */ +static int serialize_dl_data_delivery_status(byte_array_producer_t *b, dl_data_delivery_status_t *ext) +{ + /* see 38.425 5.5.2.2 */ + AssertFatal(!ext->highest_delivered_nr_pdcp_sn_ind && !ext->final_frame_ind + && !ext->lost_packet_report && !ext->delivered_nr_pdcp_sn_range_ind + && !ext->data_rate_ind && !ext->retransmitted_nr_pdcp_sn_ind + && !ext->delivered_retransmitted_nr_pdcp_ind && !ext->cause_report, + "todo\n"); + + uint8_t b1 = (1 << 4) + | (ext->highest_transmitted_nr_pdcp_sn_ind << 3) + | (ext->highest_delivered_nr_pdcp_sn_ind << 2) + | (ext->final_frame_ind << 1) + | ext->lost_packet_report; + uint8_t b2 = (ext->delivered_nr_pdcp_sn_range_ind << 4) + | (ext->data_rate_ind << 3) + | (ext->retransmitted_nr_pdcp_sn_ind << 2) + | (ext->delivered_retransmitted_nr_pdcp_ind << 1) + | ext->cause_report; + if (!byte_array_producer_put_byte(b, b1) || !byte_array_producer_put_byte(b, b2)) + return 0; + + if (!byte_array_producer_put_u32_be(b, ext->desired_buffer_size)) + return 0; + + if (ext->highest_transmitted_nr_pdcp_sn_ind) + if (!byte_array_producer_put_u24_be(b, ext->highest_transmitted_nr_pdcp_sn)) + return 0; + + return 1; +} + +/* returns -1 on error, number of serialized bytes on success */ +int serialize_extension(gtpu_extension_header_t *ext, gtpu_extension_header_type_t next, uint8_t *out_buf, int out_len) +{ + byte_array_producer_t b; + + b = byte_array_producer_from_buffer(out_buf, out_len); + /* length - will be set later */ + if (!byte_array_producer_put_byte(&b, 0)) + goto error; + + switch (ext->type) { + case GTPU_EXT_UL_PDU_SESSION_INFORMATION: + if (!serialize_ul_pdu_session_information(&b, &ext->ul_pdu_session_information)) + goto error; + break; + case GTPU_EXT_DL_DATA_DELIVERY_STATUS: + if (!serialize_dl_data_delivery_status(&b, &ext->dl_data_delivery_status)) + goto error; + break; + default: + LOG_E(GTPU, "unknown extension type %d\n", ext->type); + return -1; + } + + /* padding */ + while ((b.pos & 3) != 3) + if (!byte_array_producer_put_byte(&b, 0)) + goto error; + + /* next */ + if (!byte_array_producer_put_byte(&b, serialize_gtpu_extension_type(next))) + goto error; + + /* length is now know */ + DevAssert(b.pos / 4 <= 255); + out_buf[0] = b.pos / 4; + + return b.pos; + +error: + LOG_E(GTPU, "error serializing extension\n"); + return -1; +} diff --git a/openair3/ocp-gtpu/gtpu_extensions.h b/openair3/ocp-gtpu/gtpu_extensions.h new file mode 100644 index 0000000000..750277eb32 --- /dev/null +++ b/openair3/ocp-gtpu/gtpu_extensions.h @@ -0,0 +1,75 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef GTPU_EXTENSIONS_H +#define GTPU_EXTENSIONS_H + +#include +#include + +typedef enum { + GTPU_EXT_NONE, + /* 38.415 */ + GTPU_EXT_UL_PDU_SESSION_INFORMATION, + /* 38.425 */ + GTPU_EXT_DL_DATA_DELIVERY_STATUS, +} gtpu_extension_header_type_t; + +/* 38.415 */ +typedef struct { + /* not all fields are present, to be refined if needed */ + bool qmp; + bool dl_delay_ind; + bool ul_delay_ind; + bool snp; + bool n3n9_delay_ind; + bool new_ie_flag; + int qfi; +} ul_pdu_session_information_t; + +/* 38.425 */ +typedef struct { + /* not all fields are present, to be refined if needed */ + bool highest_transmitted_nr_pdcp_sn_ind; + bool highest_delivered_nr_pdcp_sn_ind; + bool final_frame_ind; + bool lost_packet_report; + bool delivered_nr_pdcp_sn_range_ind; + bool data_rate_ind; + bool retransmitted_nr_pdcp_sn_ind; + bool delivered_retransmitted_nr_pdcp_ind; + bool cause_report; + uint32_t desired_buffer_size; + uint32_t highest_transmitted_nr_pdcp_sn; +} dl_data_delivery_status_t; + +typedef struct { + gtpu_extension_header_type_t type; + union { + ul_pdu_session_information_t ul_pdu_session_information; + dl_data_delivery_status_t dl_data_delivery_status; + }; +} gtpu_extension_header_t; + +int serialize_gtpu_extension_type(gtpu_extension_header_type_t type); +int serialize_extension(gtpu_extension_header_t *ext, gtpu_extension_header_type_t next, uint8_t *out_buf, int out_len); + +#endif /* GTPU_EXTENSIONS_H */ From 84ce708f96fcc4531c1643b3793160f6c7d4a036 Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Fri, 25 Jul 2025 16:32:50 +0200 Subject: [PATCH 539/964] GTPU: basic support of DL USER DATA See 3GPP TS 38.425 5.5.2.1. Only sending part, only dealing with NR-U Sequence Number. --- openair3/ocp-gtpu/gtpu_extensions.c | 30 +++++++++++++++++++++++++++++ openair3/ocp-gtpu/gtpu_extensions.h | 16 +++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/openair3/ocp-gtpu/gtpu_extensions.c b/openair3/ocp-gtpu/gtpu_extensions.c index b06e20e23e..13f0cee053 100644 --- a/openair3/ocp-gtpu/gtpu_extensions.c +++ b/openair3/ocp-gtpu/gtpu_extensions.c @@ -40,6 +40,7 @@ int serialize_gtpu_extension_type(gtpu_extension_header_type_t type) case GTPU_EXT_UL_PDU_SESSION_INFORMATION: return PDU_SESSION_CONTAINER; case GTPU_EXT_DL_DATA_DELIVERY_STATUS: + case GTPU_EXT_DL_USER_DATA: return NR_RAN_CONTAINER; default: AssertFatal(0, "unknown GTPU extension type %d\n", type); @@ -92,6 +93,31 @@ static int serialize_dl_data_delivery_status(byte_array_producer_t *b, dl_data_d return 1; } +/* returns 0 on error, 1 on success */ +static int serialize_dl_user_data(byte_array_producer_t *b, dl_user_data_t *ext) +{ + /* see 38.425 5.5.2.1 */ + AssertFatal(!ext->dl_discard_blocks && !ext->dl_flush && !ext->report_polling + && !ext->request_out_of_seq_report && !ext->report_delivered + && !ext->user_data_existence_flag && !ext->assistance_info_report_polling_flag + && !ext->retransmission_flag, + "todo\n"); + + uint8_t b1 = (0 << 4) | (ext->dl_discard_blocks << 2) | (ext->dl_flush << 1) | ext->report_polling; + uint8_t b2 = (ext->request_out_of_seq_report << 4) + | (ext->report_delivered << 3) + | (ext->user_data_existence_flag << 2) + | (ext->assistance_info_report_polling_flag << 1) + | ext->retransmission_flag; + if (!byte_array_producer_put_byte(b, b1) || !byte_array_producer_put_byte(b, b2)) + return 0; + + if (!byte_array_producer_put_u24_be(b, ext->nru_sequence_number)) + return 0; + + return 1; +} + /* returns -1 on error, number of serialized bytes on success */ int serialize_extension(gtpu_extension_header_t *ext, gtpu_extension_header_type_t next, uint8_t *out_buf, int out_len) { @@ -111,6 +137,10 @@ int serialize_extension(gtpu_extension_header_t *ext, gtpu_extension_header_type if (!serialize_dl_data_delivery_status(&b, &ext->dl_data_delivery_status)) goto error; break; + case GTPU_EXT_DL_USER_DATA: + if (!serialize_dl_user_data(&b, &ext->dl_user_data)) + goto error; + break; default: LOG_E(GTPU, "unknown extension type %d\n", ext->type); return -1; diff --git a/openair3/ocp-gtpu/gtpu_extensions.h b/openair3/ocp-gtpu/gtpu_extensions.h index 750277eb32..b621d27e14 100644 --- a/openair3/ocp-gtpu/gtpu_extensions.h +++ b/openair3/ocp-gtpu/gtpu_extensions.h @@ -31,6 +31,7 @@ typedef enum { GTPU_EXT_UL_PDU_SESSION_INFORMATION, /* 38.425 */ GTPU_EXT_DL_DATA_DELIVERY_STATUS, + GTPU_EXT_DL_USER_DATA, } gtpu_extension_header_type_t; /* 38.415 */ @@ -61,11 +62,26 @@ typedef struct { uint32_t highest_transmitted_nr_pdcp_sn; } dl_data_delivery_status_t; +/* 38.425 */ +typedef struct { + /* not all fields are present, to be refined if needed */ + bool dl_discard_blocks; + bool dl_flush; + bool report_polling; + bool request_out_of_seq_report; + bool report_delivered; + bool user_data_existence_flag; + bool assistance_info_report_polling_flag; + bool retransmission_flag; + uint32_t nru_sequence_number; +} dl_user_data_t; + typedef struct { gtpu_extension_header_type_t type; union { ul_pdu_session_information_t ul_pdu_session_information; dl_data_delivery_status_t dl_data_delivery_status; + dl_user_data_t dl_user_data; }; } gtpu_extension_header_t; From 807b38ddaeb0e517c2ff3ddf58ab4fa9aec7c8f0 Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Fri, 25 Jul 2025 16:56:51 +0200 Subject: [PATCH 540/964] GTPU: CU has to send NR-U Sequence Number This is in 3GPP TS 38.425. Because it was not done, there was a problem of interoperability between openair CU and srsran DU. No DL traffic was reaching the UE. A new GTPU API function is introduced: gtpv1uSendDirectWithNRUSeqNum(). It is only used in the gNB CU, in PDCP. So it was decided to not add a new parameter to gtpv1uSendDirect() but instead add a new API function. --- openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c | 2 +- openair3/ocp-gtpu/gtp_itf.cpp | 95 ++++++++++++++++++++--- openair3/ocp-gtpu/gtp_itf.h | 5 ++ 3 files changed, 91 insertions(+), 11 deletions(-) diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c index e170e90823..4d1c0b5ba0 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c @@ -469,7 +469,7 @@ static void deliver_pdu_drb_gnb(void *deliver_pdu_data, ue_id_t ue_id, int rb_id if (NODE_IS_CU(node_type)) { LOG_D(PDCP, "%s() (drb %d) sending message to gtp size %d\n", __func__, rb_id, size); extern instance_t CUuniqInstance; - gtpv1uSendDirect(CUuniqInstance, ue_id, rb_id, (uint8_t *)buf, size, false, false); + gtpv1uSendDirectWithNRUSeqNum(CUuniqInstance, ue_id, rb_id, (uint8_t *)buf, size); } else { uint8_t *memblock = malloc16(size); memcpy(memblock, buf, size); diff --git a/openair3/ocp-gtpu/gtp_itf.cpp b/openair3/ocp-gtpu/gtp_itf.cpp index 5d910e8027..9be1873612 100644 --- a/openair3/ocp-gtpu/gtp_itf.cpp +++ b/openair3/ocp-gtpu/gtp_itf.cpp @@ -113,6 +113,7 @@ typedef struct gtpv1u_bearer_s { teid_t teid_outgoing; uint16_t seqNum; uint8_t npduNum; + int32_t nru_sequence_number; int outgoing_qfi; } gtpv1u_bearer_t; @@ -306,13 +307,14 @@ static int gtpv1uCreateAndSendMsg(gtpv1u_bearer_t *bearer, return !GTPNOK; } -void gtpv1uSendDirect(instance_t instance, - ue_id_t ue_id, - int bearer_id, - uint8_t *buf, - size_t len, - bool seqNumFlag, - bool npduNumFlag) +static void _gtpv1uSendDirect(instance_t instance, + ue_id_t ue_id, + int bearer_id, + uint8_t *buf, + size_t len, + bool seqNumFlag, + bool npduNumFlag, + int32_t nru_seqnum) { pthread_mutex_lock(&globGtp.gtp_lock); getInstRetVoid(compatInst(instance)); @@ -347,9 +349,13 @@ void gtpv1uSendDirect(instance_t instance, pthread_mutex_unlock(&globGtp.gtp_lock); int extension_count = 0; - gtpu_extension_header_t ext = {}; + gtpu_extension_header_t ext[2]; if (bearer.outgoing_qfi != -1) { - ext = { + /* 29.281 Figure 5.2.1-3 note 4 says PDU Session Container must come first. + * GTPU_EXT_UL_PDU_SESSION_INFORMATION is within a PDU Session Container + * so it must be put before any other extension. + */ + ext[extension_count] = { .type = GTPU_EXT_UL_PDU_SESSION_INFORMATION, .ul_pdu_session_information = { .qmp = false, @@ -364,6 +370,24 @@ void gtpv1uSendDirect(instance_t instance, extension_count++; } + if (nru_seqnum != -1) { + ext[extension_count] = { + .type = GTPU_EXT_DL_USER_DATA, + .dl_user_data = { + .dl_discard_blocks = false, + .dl_flush = false, + .report_polling = false, + .request_out_of_seq_report = false, + .report_delivered = false, + .user_data_existence_flag = false, + .assistance_info_report_polling_flag = false, + .retransmission_flag = false, + .nru_sequence_number = (uint32_t)nru_seqnum + } + }; + extension_count++; + } + DevAssert(compatInst(instance) == bearer.sock_fd); gtpv1uCreateAndSendMsg(&bearer, GTP_GPDU, @@ -371,10 +395,61 @@ void gtpv1uSendDirect(instance_t instance, len, seqNumFlag, npduNumFlag, - &ext, + ext, extension_count); } +void gtpv1uSendDirect(instance_t instance, + ue_id_t ue_id, + int bearer_id, + uint8_t *buf, + size_t len, + bool seqNumFlag, + bool npduNumFlag) +{ + _gtpv1uSendDirect(instance, + ue_id, + bearer_id, + buf, + len, + seqNumFlag, + npduNumFlag, + -1); +} + +void gtpv1uSendDirectWithNRUSeqNum(instance_t instance, + ue_id_t ue_id, + int bearer_id, + uint8_t *buf, + size_t len) +{ + pthread_mutex_lock(&globGtp.gtp_lock); + getInstRetVoid(compatInst(instance)); + getUeRetVoid(inst, ue_id); + auto ptr2 = ptrUe->second.bearers.find(bearer_id); + + if (ptr2 == ptrUe->second.bearers.end()) { + LOG_E(GTPU, "[%ld] GTP-U instance: sending a packet to a non existant UE:RAB: %lx/%x\n", instance, ue_id, bearer_id); + pthread_mutex_unlock(&globGtp.gtp_lock); + return; + } + + int32_t nru_seqnum = ptr2->second.nru_sequence_number; + ptr2->second.nru_sequence_number++; + ptr2->second.nru_sequence_number &= (1 << 24) - 1; + + pthread_mutex_unlock(&globGtp.gtp_lock); + + _gtpv1uSendDirect(instance, + ue_id, + bearer_id, + buf, + len, + false, + false, + nru_seqnum); +} + static void fillDlDeliveryStatusReport(gtpu_extension_header_t *ext, uint32_t RLC_buffer_availability, uint32_t NR_PDCP_PDU_SN) { *ext = { diff --git a/openair3/ocp-gtpu/gtp_itf.h b/openair3/ocp-gtpu/gtp_itf.h index d341acb311..4fcb8190e4 100644 --- a/openair3/ocp-gtpu/gtp_itf.h +++ b/openair3/ocp-gtpu/gtp_itf.h @@ -128,6 +128,11 @@ typedef struct gtpv1u_gnb_delete_tunnel_req_s gtpv1u_gnb_delete_tunnel_req_t; int newGtpuDeleteTunnels(instance_t instance, ue_id_t ue_id, int nbTunnels, int *pdusession_id); void gtpv1uSendDirect(instance_t instance, ue_id_t ue_id, int bearer_id, uint8_t *buf, size_t len, bool seqNumFlag, bool npduNumFlag); + void gtpv1uSendDirectWithNRUSeqNum(instance_t instance, + ue_id_t ue_id, + int bearer_id, + uint8_t *buf, + size_t len); instance_t gtpv1Init(openAddr_t context); void *gtpv1uTask(void *args); From 653ad775eae479ba51b5548fe360d06ef7c64e3d Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Fri, 25 Jul 2025 17:03:22 +0200 Subject: [PATCH 541/964] hack: ignore empty Cell Group Config returned by DU Interoperability testing with srsRAN DU shows than when receiving RRCReconfigurationCompleteIndicator in a UEContextModificationRequest the DU replies in the UEContextModificationResponse with an empty CellGroupConfig. This CellGroupConfig is encoded as 2 zero bytes. Let's ignore this message when we receive it, don't forward it to the UE in a RRC Reconfiguration, as it should per standard (38.473 8.3.4.2): If the CellGroupConfig IE is included in the DU to CU RRC Information IE contained in the UE CONTEXT MODIFICATION RESPONSE message, the gNB-CU shall perform RRC Reconfiguration as described in TS 38.331 [8]. The CellGroupConfig IE shall transparently be signaled to the UE as specified in TS 38.331 [8]. To be removed/reworked in the future if the interoperability situation improves. --- openair2/RRC/NR/rrc_gNB.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 75f6838a78..000c4f46cb 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -2305,13 +2305,19 @@ static void rrc_CU_process_ue_context_modification_response(MessageDef *msg_p, i uper_decode_complete(NULL, &asn_DEF_NR_CellGroupConfig, (void **)&cellGroupConfig, (uint8_t *)cgc->buf, cgc->len); AssertFatal(dec_rval.code == RC_OK && dec_rval.consumed > 0, "Cell group config decode error\n"); - if (UE->masterCellGroup) { - ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->masterCellGroup); - LOG_I(RRC, "UE %04x replacing existing CellGroupConfig with new one received from DU\n", UE->rnti); + /* hack for interoperability with srsRAN: ignore cell group config if empty */ + /* cell group config is empty if buffer length is 2 and content is all 0 */ + bool cgc_is_empty = cgc->len == 2 && cgc->buf[0] == 0 && cgc->buf[1] == 0; + if (!cgc_is_empty) { + if (UE->masterCellGroup) { + ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->masterCellGroup); + LOG_I(RRC, "UE %04x replacing existing CellGroupConfig with new one received from DU\n", UE->rnti); + } + UE->masterCellGroup = cellGroupConfig; + rrc_gNB_generate_dedicatedRRCReconfiguration(rrc, UE); + } else { + LOG_W(NR_RRC, "hack: UE %d: ignore empty CellGroupConfig in UEContextModificationResponse\n", UE->rrc_ue_id); } - UE->masterCellGroup = cellGroupConfig; - - rrc_gNB_generate_dedicatedRRCReconfiguration(rrc, UE); } // Reconfiguration should have been sent to the UE, so it will attempt the From dd0188dfdce725ee6eabd2ff2152d927106f1e12 Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 21 Aug 2025 09:41:14 +0200 Subject: [PATCH 542/964] fix for config UE TCI state ID --- openair2/LAYER2/NR_MAC_UE/config_ue.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index 73bb02a575..d764f7cb86 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -700,8 +700,11 @@ static void modlist_coreset(NR_ControlResourceSet_t *source, NR_ControlResourceS if (id == *target->tci_StatesPDCCH_ToAddList->list.array[j]) break; } - if (j == target->tci_StatesPDCCH_ToAddList->list.count) - ASN_SEQUENCE_ADD(&target->tci_StatesPDCCH_ToAddList->list, source->tci_StatesPDCCH_ToAddList->list.array[i]); + if (j == target->tci_StatesPDCCH_ToAddList->list.count) { + long *tci_id = calloc(1, sizeof(*tci_id)); + *tci_id = id; + ASN_SEQUENCE_ADD(&target->tci_StatesPDCCH_ToAddList->list, tci_id); + } } } else UPDATE_IE(target->tci_StatesPDCCH_ToAddList, From 8a091a0b844ca6a6f5638b865bb7eadf5c26fa97 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 21 Aug 2025 10:31:20 +0200 Subject: [PATCH 543/964] DLSCH sched: only sort relevant part of list This reduces the amount of elements to compare. See also: 7ee8e8eaba7f ("Fix bug: only sort relevant part of list") --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index 44d4affb08..f831e8af2e 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -613,7 +613,7 @@ static void pf_dl(module_id_t module_id, int remainUEs[num_beams]; for (int i = 0; i < num_beams; i++) remainUEs[i] = max_num_ue; - int curUE = 0; + int numUE = 0; int CC_id = 0; int slots_per_frame = mac->frame_structure.numb_slots_frame; @@ -704,13 +704,13 @@ static void pf_dl(module_id_t module_id, tbs, coeff_ue); /* Create UE_sched list for UEs eligible for new transmission*/ - UE_sched[curUE].coef=coeff_ue; - UE_sched[curUE].UE=UE; - curUE++; + UE_sched[numUE].coef = coeff_ue; + UE_sched[numUE].UE = UE; + numUE++; } } - qsort(UE_sched, sizeofArray(UE_sched), sizeof(UEsched_t), comparator); + qsort(UE_sched, numUE, sizeof(UEsched_t), comparator); UEsched_t *iterator = UE_sched; const int min_rbSize = 5; From a30bee2fab87f02656882fd01af38fbf4858f88f Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 13 Aug 2025 13:51:35 +0200 Subject: [PATCH 544/964] DLSCH sched: Fix coefficients for UE list ordering Update the comparator() to properly sort UEs based on their coefficient by appliey a consistent logic of -1/0/1 (see man qsort) for smaller/equal/larger. The previous logic was only sorting based on 0/1 (equal/larger), which would result in some UEs with a high coefficient not necessarily advancing to the start of the list, which could reduce the likelihood of them being scheduled when they actually should (in other words, this should improve fairness). See also: 62e4025bc846 ("Integrate inactivity scheduling into main allocation loop") --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index f831e8af2e..c88ad3bd96 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -594,8 +594,15 @@ typedef struct UEsched_s { NR_UE_info_t * UE; } UEsched_t; -static int comparator(const void *p, const void *q) { - return ((UEsched_t*)p)->coef < ((UEsched_t*)q)->coef; +static int comparator(const void *p, const void *q) +{ + const UEsched_t *pp = p; + const UEsched_t *qq = q; + if (pp->coef < qq->coef) + return 1; + else if (pp->coef > qq->coef) + return -1; + return 0; } static void pf_dl(module_id_t module_id, From 1cebf02b1eb4842e12728545466376ac1308c303 Mon Sep 17 00:00:00 2001 From: Romain Beurdouche Date: Tue, 5 Aug 2025 11:25:22 +0000 Subject: [PATCH 545/964] feat(rf_emulator): Add parameters Add two parameters: * `enable_noise` to enable noise injection at TX * `noise_level_dBFS` to set noise level --- radio/emulator/rf_emulator.c | 43 ++++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/radio/emulator/rf_emulator.c b/radio/emulator/rf_emulator.c index a747afc053..861daab2ba 100644 --- a/radio/emulator/rf_emulator.c +++ b/radio/emulator/rf_emulator.c @@ -32,6 +32,16 @@ #include "common_lib.h" #include "radio/vrtsim/noise_device.h" #include "simde/x86/avx512.h" +#include "SIMULATION/TOOLS/sim.h" + +#define RF_EMULATOR_SECTION "rf_emulator" +// clang-format off +#define RF_EMULATOR_PARAMS_DESC \ + { \ + {"enable_noise", "Enable noise injection", 0, .iptr = &emulator_state->enable_noise, .defintval = 1, TYPE_INT, 0},\ + {"noise_level_dBFS", "Noise level", 0, .iptr = &emulator_state->noise_level_dBFS, .defintval = INVALID_DBFS_VALUE, TYPE_INT, 0},\ + }; +// clang-format on // structures and timing thread job for timing typedef struct { @@ -49,6 +59,8 @@ typedef struct { emulator_timestamp_t emulator_timestamp; pthread_t timing_thread; bool run_timing_thread; + int enable_noise; + int noise_level_dBFS; } emulator_state_t; static void *emulator_timing_job(void *arg) @@ -108,7 +120,13 @@ static int emulator_start(openair0_device *device) // Start the timing thread and the noise device emulator_state_t *emulator_state = (emulator_state_t *)device->priv; if (!emulator_state->run_timing_thread) { - init_noise_device(0); // TODO configure noise level + if (emulator_state->enable_noise > 0) { + float noise_level = emulator_state->noise_level_dBFS == INVALID_DBFS_VALUE + ? 0.0f + : (32767.0 / powf(10.0, .05 * -(emulator_state->noise_level_dBFS))); + init_noise_device(noise_level); + LOG_I(HW, "Using noise level with %d dBFS/%f\n", emulator_state->noise_level_dBFS, noise_level); + } emulator_timestamp_t *emulator_timestamp = &emulator_state->emulator_timestamp; memset(emulator_timestamp, 0, sizeof(emulator_timestamp_t)); @@ -170,7 +188,9 @@ static void emulator_end(openair0_device *device) emulator_state->run_timing_thread = false; int ret = pthread_join(emulator_state->timing_thread, NULL); AssertFatal(ret == 0, "pthread_join() failed: errno: %d, %s\n", errno, strerror(errno)); - free_noise_device(); + if (emulator_state->enable_noise > 0) { + free_noise_device(); + } } } @@ -299,13 +319,26 @@ static int emulator_read(openair0_device *device, openair0_timestamp *ptimestamp *ptimestamp = emulator_state->last_received_sample; emulator_state->last_received_sample += nsamps; - for (int i = 0; i < nbAnt; i++) { - read_noise(buff[i], nsamps); + if (emulator_state->enable_noise > 0) { + for (int i = 0; i < nbAnt; i++) { + read_noise(buff[i], nsamps); + } + } else { + for (int i = 0; i < nbAnt; i++) { + memset(buff[i], 0, nsamps * sizeof(c16_t)); + } } return nsamps; } +static void emulator_readconfig(emulator_state_t *emulator_state) +{ + paramdef_t emulator_params[] = RF_EMULATOR_PARAMS_DESC; + int ret = config_get(config_get_if(), emulator_params, sizeofArray(emulator_params), RF_EMULATOR_SECTION); + AssertFatal(ret >= 0, "configuration couldn't be performed\n"); +} + int device_init(openair0_device *device, openair0_config_t *openair0_cfg) { LOG_I(HW, "This is emulator RF that does nothing\n"); @@ -330,5 +363,7 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) device->trx_write_func = emulator_write; device->trx_read_func = emulator_read; + emulator_readconfig(emulator_state); + return 0; } From 89e6e53f8c8991719379afdfb02282392e6718db Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 6 Aug 2025 18:50:33 +0200 Subject: [PATCH 546/964] Remove --emulate-rf option and corresponding code With the RFemulator, there is no need for a dedicated --emulate-rf option anymore. For all uses of --emulate-rf, RFemulator should be used instead. --- common/config/DOC/config/rtusage.md | 1 - executables/lte-ru.c | 176 +++++----------------- executables/lte-softmodem.c | 1 - executables/lte-softmodem.h | 1 - executables/nr-ru.c | 203 +++++++++----------------- executables/nr-softmodem-common.h | 1 - executables/nr-softmodem.c | 1 - executables/softmodem-common.h | 5 - openair1/PHY/defs_RU.h | 13 -- openair1/PHY/defs_eNB.h | 5 - openair1/SIMULATION/LTE_PHY/dlsim.c | 1 - openair1/SIMULATION/LTE_PHY/mbmssim.c | 2 - 12 files changed, 104 insertions(+), 306 deletions(-) diff --git a/common/config/DOC/config/rtusage.md b/common/config/DOC/config/rtusage.md index 3b51e1afd2..7c42a6edcc 100644 --- a/common/config/DOC/config/rtusage.md +++ b/common/config/DOC/config/rtusage.md @@ -55,7 +55,6 @@ To get help on supported parameters you can use specific options: --ulsch-max-errors: set the eNodeB max ULSCH erros --phy-test: test UE phy layer, mac disabled --usim-test: use XOR autentication algo in case of test usim mode - --emulate-rf: Emulated RF enabled(disable by defult) --clock: tells hardware to use a clock reference (0:internal, 1:external, 2:gpsdo) --wait-for-sync: Help string not specified -C: Set the downlink frequency for all component carriers diff --git a/executables/lte-ru.c b/executables/lte-ru.c index 326e55b288..eed5a90eb9 100644 --- a/executables/lte-ru.c +++ b/executables/lte-ru.c @@ -531,44 +531,6 @@ volatile late_control_e late_control=STATE_BURST_NORMAL; /* add fail safe for late command end */ -static void *emulatedRF_thread(void *param) { - RU_proc_t *proc = (RU_proc_t *) param; - int microsec = 500; // length of time to sleep, in miliseconds - int numerology = 0 ; - struct timespec req = {0}; - req.tv_sec = 0; - req.tv_nsec = (numerology>0)? ((microsec * 1000L)/numerology):(microsec * 1000L)*2; - cpu_set_t cpuset; - CPU_ZERO(&cpuset); - CPU_SET(1,&cpuset); - pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); - int policy; - int ret; - struct sched_param sparam; - memset(&sparam, 0, sizeof(sparam)); - sparam.sched_priority = sched_get_priority_max(SCHED_FIFO); - policy = SCHED_FIFO ; - pthread_setschedparam(pthread_self(), policy, &sparam); - wait_sync("emulatedRF_thread"); - - while(!oai_exit) { - nanosleep(&req, (struct timespec *)NULL); - - if(proc->emulate_rf_busy ) { - LOG_E(PHY,"rf being delayed in emulated RF\n"); - } - - proc->emulate_rf_busy = 1; - AssertFatal((ret=pthread_mutex_lock(&proc->mutex_emulateRF))==0,"mutex_lock returns %d\n",ret); - ++proc->instance_cnt_emulateRF; - pthread_cond_signal(&proc->cond_emulateRF); - AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_emulateRF))==0,"mutex_unlock returns %d\n",ret); - } - - return 0; -} - - void rx_rf(RU_t *ru, int *frame, int *subframe) { @@ -586,17 +548,7 @@ void rx_rf(RU_t *ru, VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 ); old_ts = proc->timestamp_rx; - if(ru->emulate_rf) { - wait_on_condition(&proc->mutex_emulateRF,&proc->cond_emulateRF,&proc->instance_cnt_emulateRF,"emulatedRF_thread"); - release_thread(&proc->mutex_emulateRF,&proc->instance_cnt_emulateRF,"emulatedRF_thread"); - rxs = fp->samples_per_tti; - } else { - rxs = ru->rfdevice.trx_read_func(&ru->rfdevice, - &ts, - rxp, - fp->samples_per_tti, - ru->nb_rx); - } + rxs = ru->rfdevice.trx_read_func(&ru->rfdevice, &ts, rxp, fp->samples_per_tti, ru->nb_rx); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 ); ru->south_in_cnt++; @@ -613,11 +565,7 @@ void rx_rf(RU_t *ru, resynch=1; } - if(get_softmodem_params()->emulate_rf) { - proc->timestamp_rx = old_ts + fp->samples_per_tti; - } else { - proc->timestamp_rx = ts-ru->ts_offset; - } + proc->timestamp_rx = ts-ru->ts_offset; // AssertFatal(rxs == fp->samples_per_tti, // "rx_rf: Asked for %d samples, got %d from SDR\n",fp->samples_per_tti,rxs); @@ -1229,7 +1177,6 @@ void wakeup_L1s(RU_t *ru) { // pthread_mutex_unlock(&proc->mutex_RU); // LOG_D(PHY,"wakeup eNB top for for subframe %d\n", ru->proc.tti_rx); // ru->eNB_top(eNB_list[0],ru->proc.frame_rx,ru->proc.tti_rx,string); - ru->proc.emulate_rf_busy = 0; } @@ -1497,7 +1444,6 @@ static void *ru_thread_tx( void *param ) { L1_rxtx_proc_t *L1_proc; cpu_set_t cpuset; CPU_ZERO(&cpuset); - char filename[256]; thread_top_init("ru_thread_tx",1,400000,500000,500000); //CPU_SET(5, &cpuset); //pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); @@ -1530,24 +1476,12 @@ static void *ru_thread_tx( void *param ) { // do OFDM if needed if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru,frame_tx,tti_tx); - if(!(ru->emulate_rf)) { //if(!emulate_rf){ - // do outgoing fronthaul (south) if needed - if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) ru->fh_south_out(ru,frame_tx,tti_tx,timestamp_tx); + // do outgoing fronthaul (south) if needed + if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) + ru->fh_south_out(ru, frame_tx, tti_tx, timestamp_tx); - if (ru->fh_north_out) ru->fh_north_out(ru); - } else { - for (int i=0; inb_tx; i++) { - if(frame_tx == 2) { - sprintf(filename,"txdataF%d_frame%d_sf%d.m",i,frame_tx,tti_tx); - LOG_M(filename,"txdataF_frame",ru->common.txdataF_BF[i],fp->symbols_per_tti*fp->ofdm_symbol_size, 1, 1); - } - - if(frame_tx == 2 && tti_tx==0) { - sprintf(filename,"txdata%d_frame%d.m",i,frame_tx); - LOG_M(filename,"txdata_frame",ru->common.txdata[i],fp->samples_per_tti*10, 1, 1); - } - } - } + if (ru->fh_north_out) + ru->fh_north_out(ru); LOG_D(PHY,"ru_thread_tx: releasing RU TX in %d.%d\n", frame_tx, tti_tx); release_thread(&proc->mutex_eNBs,&proc->instance_cnt_eNBs,"ru_thread_tx"); @@ -1612,7 +1546,6 @@ static void *ru_thread( void *param ) { int ret; cpu_set_t cpuset; CPU_ZERO(&cpuset); - char filename[256]; // set default return value #if defined(PRE_SCD_THREAD) dlsch_ue_select_tbl_in_use = 1; @@ -1625,21 +1558,7 @@ static void *ru_thread( void *param ) { LOG_I(PHY,"thread ru created id=%ld\n", syscall(__NR_gettid)); LOG_I(PHY,"Starting RU %d (%s,%s),\n", ru->idx, NB_functions[ru->function], NB_timing[ru->if_timing]); - if(get_softmodem_params()->emulate_rf) { - phy_init_RU(ru); - - if (setup_RU_buffers(ru)!=0) { - LOG_I(PHY,"Exiting, cannot initialize RU Buffers\n"); - exit(-1); - } - - LOG_I(PHY, "Signaling main thread that RU %d is ready\n",ru->idx); - AssertFatal((ret=pthread_mutex_lock(ru->ru_mutex))==0,"mutex_lock returns %d\n",ret); - *ru->ru_mask &= ~(1<idx); - pthread_cond_signal(ru->ru_cond); - AssertFatal((ret=pthread_mutex_unlock(ru->ru_mutex))==0,"mutex_unlock returns %d\n",ret); - ru->state = RU_RUN; - } else if (ru->has_ctrl_prt == 0) { + if (ru->has_ctrl_prt == 0) { // There is no control port: start everything here LOG_I(PHY, "RU %d has no OAI ctrl port\n",ru->idx); @@ -1695,18 +1614,22 @@ static void *ru_thread( void *param ) { } else wait_sync("ru_thread"); LOG_D(PHY,"RU %d: Got start from control thread\n",ru->idx); - if(!(ru->emulate_rf)) { - if (ru->is_slave == 0) AssertFatal(ru->state == RU_RUN,"ru-%d state = %s != RU_RUN\n",ru->idx,ru_states[ru->state]); - else if (ru->is_slave == 1) AssertFatal(ru->state == RU_SYNC || ru->state == RU_RUN || - ru->state == RU_CHECK_SYNC,"ru %d state = %s != RU_SYNC or RU_RUN or RU_CHECK_SYNC\n",ru->idx,ru_states[ru->state]); + if (ru->is_slave == 0) + AssertFatal(ru->state == RU_RUN, "ru-%d state = %s != RU_RUN\n", ru->idx, ru_states[ru->state]); + else if (ru->is_slave == 1) + AssertFatal(ru->state == RU_SYNC || ru->state == RU_RUN || ru->state == RU_CHECK_SYNC, + "ru %d state = %s != RU_SYNC or RU_RUN or RU_CHECK_SYNC\n", + ru->idx, + ru_states[ru->state]); - // Start RF device if any - if (ru->start_rf) { - if (ru->start_rf(ru) != 0) - AssertFatal(1==0,"Could not start the RF device\n"); - else LOG_I(PHY,"RU %d rf device ready\n",ru->idx); - } else LOG_D(PHY,"RU %d no rf device\n",ru->idx); - } + // Start RF device if any + if (ru->start_rf) { + if (ru->start_rf(ru) != 0) + AssertFatal(1 == 0, "Could not start the RF device\n"); + else + LOG_I(PHY, "RU %d rf device ready\n", ru->idx); + } else + LOG_D(PHY, "RU %d no rf device\n", ru->idx); // if an asnych_rxtx thread exists // wakeup the thread because the devices are ready at this point @@ -1864,26 +1787,13 @@ static void *ru_thread( void *param ) { // do OFDM if needed if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru, proc->frame_tx, proc->tti_tx); - if(!(ru->emulate_rf)) { //if(!emulate_rf){ - // do outgoing fronthaul (south) if needed - if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) ru->fh_south_out(ru, proc->frame_tx, proc->tti_tx, proc->timestamp_tx); + // do outgoing fronthaul (south) if needed + if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) + ru->fh_south_out(ru, proc->frame_tx, proc->tti_tx, proc->timestamp_tx); - if ((ru->fh_north_out) && (ru->state!=RU_CHECK_SYNC)) ru->fh_north_out(ru); - } else { - for (int i=0; inb_tx; i++) { - if(proc->frame_tx == 2) { - sprintf(filename,"txdataF%d_frame%d_sf%d.m",i,proc->frame_tx,proc->tti_tx); - LOG_M(filename,"txdataF_frame",ru->common.txdataF_BF[i],ru->frame_parms->symbols_per_tti*ru->frame_parms->ofdm_symbol_size, 1, 1); - } + if ((ru->fh_north_out) && (ru->state != RU_CHECK_SYNC)) + ru->fh_north_out(ru); - if(proc->frame_tx == 2 && proc->tti_tx==0) { - sprintf(filename,"txdata%d_frame%d.m",i,proc->frame_tx); - LOG_M(filename,"txdata_frame",ru->common.txdata[i],ru->frame_parms->samples_per_tti*10, 1, 1); - } - } - } - - proc->emulate_rf_busy = 0; } #else @@ -1903,12 +1813,11 @@ static void *ru_thread( void *param ) { LOG_I(PHY, "Exiting ru_thread \n"); - if (!(ru->emulate_rf)) { - if (ru->stop_rf != NULL) { - if (ru->stop_rf(ru) != 0) - LOG_E(HW,"Could not stop the RF device\n"); - else LOG_I(PHY,"RU %d rf device stopped\n",ru->idx); - } + if (ru->stop_rf != NULL) { + if (ru->stop_rf(ru) != 0) + LOG_E(HW, "Could not stop the RF device\n"); + else + LOG_I(PHY, "RU %d rf device stopped\n", ru->idx); } return NULL; @@ -2128,12 +2037,12 @@ static void *rf_tx( void *param ) { // do OFDM if needed if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru,proc->frame_tx,proc->tti_tx); - if(!ru->emulate_rf) { - // do outgoing fronthaul (south) if needed - if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) ru->fh_south_out(ru,proc->frame_tx,proc->tti_tx,proc->timestamp_tx); + // do outgoing fronthaul (south) if needed + if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) + ru->fh_south_out(ru, proc->frame_tx, proc->tti_tx, proc->timestamp_tx); - if (ru->fh_north_out) ru->fh_north_out(ru); - } + if (ru->fh_north_out) + ru->fh_north_out(ru); } if (release_thread(&proc->mutex_rf_tx,&proc->instance_cnt_rf_tx,"rf_tx") < 0) break; @@ -2205,7 +2114,7 @@ int start_write_thread(RU_t *ru) { void init_RU_proc(RU_t *ru) { int i=0; RU_proc_t *proc; - pthread_attr_t *attr_FH=NULL, *attr_FH1=NULL, *attr_prach=NULL, *attr_asynch=NULL, *attr_synch=NULL, *attr_emulateRF=NULL, *attr_ctrl=NULL, *attr_prach_br=NULL; + pthread_attr_t *attr_FH=NULL, *attr_FH1=NULL, *attr_prach=NULL, *attr_asynch=NULL, *attr_synch=NULL, *attr_ctrl=NULL, *attr_prach_br=NULL; //pthread_attr_t *attr_fep=NULL; LOG_I(PHY,"Initializing RU proc %d (%s,%s),\n",ru->idx,NB_functions[ru->function],NB_timing[ru->if_timing]); proc = &ru->proc; @@ -2215,7 +2124,6 @@ void init_RU_proc(RU_t *ru) { proc->instance_cnt_synch = -1; proc->instance_cnt_FH = -1; proc->instance_cnt_FH1 = -1; - proc->instance_cnt_emulateRF = -1; proc->instance_cnt_asynch_rxtx = -1; proc->instance_cnt_ru = -1; proc->instance_cnt_eNBs = -1; @@ -2232,20 +2140,17 @@ void init_RU_proc(RU_t *ru) { pthread_mutex_init( &proc->mutex_synch,NULL); pthread_mutex_init( &proc->mutex_FH,NULL); pthread_mutex_init( &proc->mutex_FH1,NULL); - pthread_mutex_init( &proc->mutex_emulateRF,NULL); pthread_mutex_init( &proc->mutex_eNBs, NULL); pthread_mutex_init( &proc->mutex_ru,NULL); pthread_cond_init( &proc->cond_prach, NULL); pthread_cond_init( &proc->cond_FH, NULL); pthread_cond_init( &proc->cond_FH1, NULL); - pthread_cond_init( &proc->cond_emulateRF, NULL); pthread_cond_init( &proc->cond_asynch_rxtx, NULL); pthread_cond_init( &proc->cond_synch,NULL); pthread_cond_init( &proc->cond_eNBs, NULL); pthread_cond_init( &proc->cond_ru_thread,NULL); pthread_attr_init( &proc->attr_FH); pthread_attr_init( &proc->attr_FH1); - pthread_attr_init( &proc->attr_emulateRF); pthread_attr_init( &proc->attr_prach); pthread_attr_init( &proc->attr_synch); pthread_attr_init( &proc->attr_asynch_rxtx); @@ -2289,9 +2194,6 @@ void init_RU_proc(RU_t *ru) { pthread_create( &proc->pthread_rf_tx, NULL, rf_tx, (void *)ru ); #endif - if (ru->emulate_rf) - pthread_create( &proc->pthread_emulateRF, attr_emulateRF, emulatedRF_thread, (void *)proc ); - if (get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT || get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) pthread_create( &proc->pthread_FH1, attr_FH1, ru_thread_tx, (void *)ru ); diff --git a/executables/lte-softmodem.c b/executables/lte-softmodem.c index 6a7e607586..6dbfbbc7d6 100644 --- a/executables/lte-softmodem.c +++ b/executables/lte-softmodem.c @@ -138,7 +138,6 @@ RU_t **RCconfig_RU(int nb_RU,int nb_L1_inst,PHY_VARS_eNB ***eNB,uint64_t *ru_mas RU_t **RCconfig_RU(int nb_RU,int nb_L1_inst,PHY_VARS_eNB ***eNB,uint64_t *ru_mask,pthread_mutex_t *ru_mutex,pthread_cond_t *ru_cond); int transmission_mode=1; -int emulate_rf = 0; int numerology = 0; THREAD_STRUCT thread_struct; diff --git a/executables/lte-softmodem.h b/executables/lte-softmodem.h index 8c55f0dc65..db6136c351 100644 --- a/executables/lte-softmodem.h +++ b/executables/lte-softmodem.h @@ -127,7 +127,6 @@ extern int sync_var; extern int transmission_mode; extern double cpuf; -extern int emulate_rf; extern int numerology; extern int usrp_tx_thread; diff --git a/executables/nr-ru.c b/executables/nr-ru.c index c0da88e634..39499227a8 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -567,25 +567,6 @@ void fh_if4p5_north_out(RU_t *ru) { stop_meas(&ru->tx_fhaul); } -void *emulatedRF_thread(void *param) { - RU_proc_t *proc = (RU_proc_t *) param; - int microsec = 500; // length of time to sleep, in miliseconds - struct timespec req = {0}; - req.tv_sec = 0; - req.tv_nsec = (numerology>0)? ((microsec * 1000L)/numerology):(microsec * 1000L)*2; - wait_sync("emulatedRF_thread"); - - while(!oai_exit) { - nanosleep(&req, (struct timespec *)NULL); - pthread_mutex_lock(&proc->mutex_emulateRF); - ++proc->instance_cnt_emulateRF; - pthread_mutex_unlock(&proc->mutex_emulateRF); - pthread_cond_signal(&proc->cond_emulateRF); - } - - return 0; -} - static void rx_rf(RU_t *ru, int *frame, int *slot) { RU_proc_t *proc = &ru->proc; @@ -606,14 +587,7 @@ static void rx_rf(RU_t *ru, int *frame, int *slot) openair0_timestamp ts; unsigned int rxs; - if(emulate_rf) { - wait_on_condition(&proc->mutex_emulateRF,&proc->cond_emulateRF,&proc->instance_cnt_emulateRF,"emulatedRF_thread"); - release_thread(&proc->mutex_emulateRF,&proc->instance_cnt_emulateRF,"emulatedRF_thread"); - rxs = samples_per_slot; - ts = old_ts + rxs; - } else { - rxs = ru->rfdevice.trx_read_func(&ru->rfdevice, &ts, rxp, samples_per_slot, nb); - } + rxs = ru->rfdevice.trx_read_func(&ru->rfdevice, &ts, rxp, samples_per_slot, nb); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 ); proc->timestamp_rx = ts-ru->ts_offset; @@ -683,10 +657,8 @@ static void rx_rf(RU_t *ru, int *frame, int *slot) *slot = proc->tti_rx; } - if (!emulate_rf) { - metadata mt = {.slot = *slot, .frame = *frame}; - gNBscopeCopyWithMetadata(ru, gNbTimeDomainSamples, rxp[0], sizeof(c16_t), 1, samples_per_slot, 0, &mt); - } + metadata mt = {.slot = *slot, .frame = *frame}; + gNBscopeCopyWithMetadata(ru, gNbTimeDomainSamples, rxp[0], sizeof(c16_t), 1, samples_per_slot, 0, &mt); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, (proc->timestamp_rx+ru->ts_offset)&0xffffffff ); @@ -996,11 +968,8 @@ void ru_tx_func(void *param) { processingData_RU_t *info = (processingData_RU_t *) param; RU_t *ru = info->ru; - NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; int frame_tx = info->frame_tx; int slot_tx = info->slot_tx; - int print_frame = 8; - char filename[40]; // do TX front-end processing if needed (precoding and/or IDFTs) if (ru->feptx_prec) @@ -1010,44 +979,12 @@ void ru_tx_func(void *param) if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru, frame_tx, slot_tx); - if(!emulate_rf) { - // do outgoing fronthaul (south) if needed - if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) - ru->fh_south_out(ru, frame_tx, slot_tx, info->timestamp_tx); + // do outgoing fronthaul (south) if needed + if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) + ru->fh_south_out(ru, frame_tx, slot_tx, info->timestamp_tx); - if (ru->fh_north_out) - ru->fh_north_out(ru); - } else { - if(frame_tx == print_frame) { - for (int i = 0; i < ru->nb_tx * ru->num_beams_period; i++) { - if(slot_tx == 0) { - sprintf(filename,"gNBdataF_frame%d_sl%d.m", print_frame, slot_tx); - LOG_M(filename,"txdataF_frame",&ru->gNB_list[0]->common_vars.txdataF[i][0],fp->samples_per_frame_wCP, 1, 1); - sprintf(filename,"tx%ddataF_frame%d_sl%d.m", i, print_frame, slot_tx); - LOG_M(filename,"txdataF_frame",&ru->common.txdataF[i][0],fp->samples_per_frame_wCP, 1, 1); - sprintf(filename,"tx%ddataF_BF_frame%d_sl%d.m", i, print_frame, slot_tx); - LOG_M(filename,"txdataF_BF_frame",&ru->common.txdataF_BF[i][0],fp->samples_per_subframe_wCP, 1, 1); - } - - if(slot_tx == 9) { - sprintf(filename,"tx%ddata_frame%d.m", i, print_frame); - LOG_M(filename,"txdata_frame",&ru->common.txdata[i][0],fp->samples_per_frame, 1, 1); - sprintf(filename,"tx%ddata_frame%d.dat", i, print_frame); - FILE *output_fd = fopen(filename,"w"); - - if (output_fd) { - fwrite(&ru->common.txdata[i][0], - sizeof(int32_t), - fp->samples_per_frame, - output_fd); - fclose(output_fd); - } else { - LOG_E(PHY,"Cannot write to file %s\n",filename); - } - }//if(slot_tx == 9) - }//for (i=0; inb_tx; i++) - }//if(frame_tx == print_frame) - }//else emulate_rf + if (ru->fh_north_out) + ru->fh_north_out(ru); } /* @brief wait for the next RX TTI to be free @@ -1119,54 +1056,50 @@ void *ru_thread(void *param) fill_rf_config(ru, ru->rf_config_file); fill_split7_2_config(&ru->openair0_cfg.split7, &ru->config, fp->slots_per_frame, fp->ofdm_symbol_size); - if(!emulate_rf) { - // Start IF device if any - if (ru->nr_start_if) { - LOG_I(PHY, "starting transport\n"); - ret = openair0_transport_load(&ru->ifdevice, &ru->openair0_cfg, &ru->eth_params); - AssertFatal(ret == 0, "RU %u: openair0_transport_init() ret %d: cannot initialize transport protocol\n", ru->idx, ret); - - if (ru->ifdevice.get_internal_parameter != NULL) { - /* it seems the device can "overwrite" (request?) to set the callbacks - * for fh_south_in()/fh_south_out() differently */ - void *t = ru->ifdevice.get_internal_parameter("fh_if4p5_south_in"); - if (t != NULL) - ru->fh_south_in = t; - t = ru->ifdevice.get_internal_parameter("fh_if4p5_south_out"); - if (t != NULL) - ru->fh_south_out = t; - } else { - - malloc_IF4p5_buffer(ru); - } - - int cpu = sched_getcpu(); - if (ru->ru_thread_core > -1 && cpu != ru->ru_thread_core) { - /* we start the ru_thread using threadCreate(), which already sets CPU - * affinity; let's force it here again as per feature request #732 */ - cpu_set_t cpuset; - CPU_ZERO(&cpuset); - CPU_SET(ru->ru_thread_core, &cpuset); - int ret = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); - AssertFatal(ret == 0, "Error in pthread_getaffinity_np(): ret: %d, errno: %d", ret, errno); - LOG_I(PHY, "RU %d: manually set CPU affinity to CPU %d\n", ru->idx, ru->ru_thread_core); - } - - LOG_I(PHY,"Starting IF interface for RU %d, nb_rx %d\n",ru->idx,ru->nb_rx); - AssertFatal(ru->nr_start_if(ru,NULL) == 0, "Could not start the IF device\n"); - - if (ru->has_ctrl_prt > 0) { - if (ru->if_south == LOCAL_RF) ret = connect_rau(ru); - else ret = attach_rru(ru); - - AssertFatal(ret==0,"Cannot connect to remote radio\n"); - } + // Start IF device if any + if (ru->nr_start_if) { + LOG_I(PHY, "starting transport\n"); + ret = openair0_transport_load(&ru->ifdevice, &ru->openair0_cfg, &ru->eth_params); + AssertFatal(ret == 0, "RU %u: openair0_transport_init() ret %d: cannot initialize transport protocol\n", ru->idx, ret); + if (ru->ifdevice.get_internal_parameter != NULL) { + /* it seems the device can "overwrite" (request?) to set the callbacks + * for fh_south_in()/fh_south_out() differently */ + void *t = ru->ifdevice.get_internal_parameter("fh_if4p5_south_in"); + if (t != NULL) + ru->fh_south_in = t; + t = ru->ifdevice.get_internal_parameter("fh_if4p5_south_out"); + if (t != NULL) + ru->fh_south_out = t; + } else { + malloc_IF4p5_buffer(ru); } - else if (ru->if_south == LOCAL_RF) { // configure RF parameters only - ret = openair0_device_load(&ru->rfdevice,&ru->openair0_cfg); - AssertFatal(ret==0,"Cannot connect to local radio\n"); + + int cpu = sched_getcpu(); + if (ru->ru_thread_core > -1 && cpu != ru->ru_thread_core) { + /* we start the ru_thread using threadCreate(), which already sets CPU + * affinity; let's force it here again as per feature request #732 */ + cpu_set_t cpuset; + CPU_ZERO(&cpuset); + CPU_SET(ru->ru_thread_core, &cpuset); + int ret = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); + AssertFatal(ret == 0, "Error in pthread_getaffinity_np(): ret: %d, errno: %d", ret, errno); + LOG_I(PHY, "RU %d: manually set CPU affinity to CPU %d\n", ru->idx, ru->ru_thread_core); } + + LOG_I(PHY,"Starting IF interface for RU %d, nb_rx %d\n",ru->idx,ru->nb_rx); + AssertFatal(ru->nr_start_if(ru,NULL) == 0, "Could not start the IF device\n"); + + if (ru->has_ctrl_prt > 0) { + if (ru->if_south == LOCAL_RF) ret = connect_rau(ru); + else ret = attach_rru(ru); + + AssertFatal(ret==0,"Cannot connect to remote radio\n"); + } + + } else if (ru->if_south == LOCAL_RF) { // configure RF parameters only + ret = openair0_device_load(&ru->rfdevice,&ru->openair0_cfg); + AssertFatal(ret==0,"Cannot connect to local radio\n"); } if (setup_RU_buffers(ru)!=0) { @@ -1181,23 +1114,23 @@ void *ru_thread(void *param) pthread_mutex_unlock(&RC.ru_mutex); wait_sync("ru_thread"); - if(!emulate_rf) { - // Start RF device if any - if (ru->start_rf) { - if (ru->start_rf(ru) != 0) - LOG_E(HW,"Could not start the RF device\n"); - else LOG_I(PHY,"RU %d rf device ready\n",ru->idx); - } else LOG_I(PHY,"RU %d no rf device\n",ru->idx); + // Start RF device if any + if (ru->start_rf) { + if (ru->start_rf(ru) != 0) + LOG_E(HW, "Could not start the RF device\n"); + else + LOG_I(PHY, "RU %d rf device ready\n", ru->idx); + } else + LOG_I(PHY, "RU %d no rf device\n", ru->idx); - LOG_I(PHY, "RU %d RF started cpu_meas_enabled %d\n", ru->idx, cpu_meas_enabled); - // start trx write thread - if(usrp_tx_thread == 1) { - if (ru->start_write_thread) { - if(ru->start_write_thread(ru) != 0) { - LOG_E(HW,"Could not start tx write thread\n"); - } else { - LOG_I(PHY,"tx write thread ready\n"); - } + LOG_I(PHY, "RU %d RF started cpu_meas_enabled %d\n", ru->idx, cpu_meas_enabled); + // start trx write thread + if (usrp_tx_thread == 1) { + if (ru->start_write_thread) { + if (ru->start_write_thread(ru) != 0) { + LOG_E(HW, "Could not start tx write thread\n"); + } else { + LOG_I(PHY, "tx write thread ready\n"); } } } @@ -1358,7 +1291,6 @@ void init_RU_proc(RU_t *ru) { proc = &ru->proc; memset((void *)proc,0,sizeof(RU_proc_t)); proc->ru = ru; - proc->instance_cnt_emulateRF = -1; proc->first_rx = 1; proc->first_tx = 1; proc->frame_offset = 0; @@ -1367,11 +1299,6 @@ void init_RU_proc(RU_t *ru) { for (i=0; i<10; i++) proc->symbol_mask[i]=0; - pthread_mutex_init( &proc->mutex_emulateRF,NULL); - pthread_cond_init( &proc->cond_emulateRF, NULL); - - if(emulate_rf) - threadCreate( &proc->pthread_emulateRF, emulatedRF_thread, (void *)proc, "emulateRF", -1, OAI_PRIORITY_RT ); LOG_I(PHY, "Initialized RU proc %d (%s,%s),\n", ru->idx, NB_functions[ru->function], NB_timing[ru->if_timing]); } diff --git a/executables/nr-softmodem-common.h b/executables/nr-softmodem-common.h index 3ab6d1e73d..61823d43cd 100644 --- a/executables/nr-softmodem-common.h +++ b/executables/nr-softmodem-common.h @@ -133,7 +133,6 @@ extern int sync_var; extern int transmission_mode; extern double cpuf; -extern int emulate_rf; extern int numerology; extern int usrp_tx_thread; void wait_gNBs(void); diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c index 5cc5e3a4fc..9a0ee6ec9e 100644 --- a/executables/nr-softmodem.c +++ b/executables/nr-softmodem.c @@ -119,7 +119,6 @@ double rx_gain_off = 0.0; static int tx_max_power[MAX_NUM_CCs]; /* = {0,0}*/; int chain_offset = 0; -int emulate_rf = 0; int numerology = 0; double cpuf; diff --git a/executables/softmodem-common.h b/executables/softmodem-common.h index 33d4f4cf04..d122b1a1d5 100644 --- a/executables/softmodem-common.h +++ b/executables/softmodem-common.h @@ -96,7 +96,6 @@ extern "C" #define CONFIG_HLP_NUMEROLOGY "adding numerology for 5G\n" #define CONFIG_HLP_BAND "band index\n" -#define CONFIG_HLP_EMULATE_RF "Emulated RF enabled(disable by defult)\n" #define CONFIG_HLP_PARALLEL_CMD "three config for level of parallelism 'PARALLEL_SINGLE_THREAD', 'PARALLEL_RU_L1_SPLIT', or 'PARALLEL_RU_L1_TRX_SPLIT'\n" #define CONFIG_HLP_WORKER_CMD "two option for worker 'WORKER_DISABLE' or 'WORKER_ENABLE'\n" #define CONFIG_HLP_USRP_THREAD "having extra thead for usrp tx\n" @@ -128,7 +127,6 @@ extern "C" #define CHAIN_OFFSET softmodem_params.chain_offset #define NUMEROLOGY softmodem_params.numerology #define BAND softmodem_params.band -#define EMULATE_RF softmodem_params.emulate_rf #define CLOCK_SOURCE softmodem_params.clock_source #define TIMING_SOURCE softmodem_params.timing_source #define TUNE_OFFSET softmodem_params.tune_offset @@ -164,7 +162,6 @@ extern int usrp_tx_thread; {"q" , CONFIG_HLP_STMON, PARAMFLAG_BOOL, .iptr=&cpu_meas_enabled, .defintval=0, TYPE_INT, 0}, \ {"numerology" , CONFIG_HLP_NUMEROLOGY, 0, .iptr=&NUMEROLOGY, .defintval=1, TYPE_INT, 0}, \ {"band" , CONFIG_HLP_BAND, 0, .iptr=&BAND, .defintval=78, TYPE_INT, 0}, \ - {"emulate-rf" , CONFIG_HLP_EMULATE_RF, PARAMFLAG_BOOL, .iptr=&EMULATE_RF, .defintval=0, TYPE_INT, 0}, \ {"parallel-config", CONFIG_HLP_PARALLEL_CMD, 0, .strptr=¶llel_config, .defstrval=NULL, TYPE_STRING, 0}, \ {"worker-config", CONFIG_HLP_WORKER_CMD, 0, .strptr=&worker_config, .defstrval=NULL, TYPE_STRING, 0}, \ {"noS1", CONFIG_HLP_NOS1, PARAMFLAG_BOOL, .uptr=&noS1, .defintval=0, TYPE_UINT, 0}, \ @@ -217,7 +214,6 @@ extern int usrp_tx_thread; { .s5 = { NULL } }, \ { .s5 = { NULL } }, \ { .s5 = { NULL } }, \ - { .s5 = { NULL } }, \ { .s3a = { config_checkstr_assign_integer, \ {"MONOLITHIC", "PNF", "VNF", "AERIAL","UE_STUB_PNF","UE_STUB_OFFNET","STANDALONE_PNF"}, \ {NFAPI_MONOLITHIC, NFAPI_MODE_PNF, NFAPI_MODE_VNF, NFAPI_MODE_AERIAL,NFAPI_UE_STUB_PNF,NFAPI_UE_STUB_OFFNET,NFAPI_MODE_STANDALONE_PNF}, \ @@ -320,7 +316,6 @@ typedef struct { int phy_test; int do_ra; uint8_t sl_mode; - int emulate_rf; int chain_offset; int numerology; int band; diff --git a/openair1/PHY/defs_RU.h b/openair1/PHY/defs_RU.h index a2c39852f5..e72465c4a9 100644 --- a/openair1/PHY/defs_RU.h +++ b/openair1/PHY/defs_RU.h @@ -255,7 +255,6 @@ typedef struct RU_proc_t_s { int instance_cnt_feptx; /// \internal This variable is protected by \ref mutex_ru_thread int instance_cnt_ru; - int instance_cnt_emulateRF; /// pthread structure for RU FH processing thread pthread_t pthread_FH; pthread_t pthread_FH1; @@ -271,8 +270,6 @@ typedef struct RU_proc_t_s { pthread_t pthread_fep[8]; /// pthread struct for RU TX FEP worker thread pthread_t pthread_feptx; - /// pthread struct for emulated RF - pthread_t pthread_emulateRF; /// pthread structure for asychronous RX/TX processing thread pthread_t pthread_asynch_rxtx; /// flag to indicate first RX acquisition @@ -296,8 +293,6 @@ typedef struct RU_proc_t_s { pthread_attr_t attr_fep; /// pthread attributes for worker feptx thread pthread_attr_t attr_feptx; - /// pthread attributes for emulated RF - pthread_attr_t attr_emulateRF; /// scheduling parameters for RU FH thread struct sched_param sched_param_FH; struct sched_param sched_param_FH1; @@ -324,8 +319,6 @@ typedef struct RU_proc_t_s { pthread_cond_t cond_fep[8]; /// condition varible for RU TX FEP thread pthread_cond_t cond_feptx; - /// condition varible for emulated RF - pthread_cond_t cond_emulateRF; /// condition variable for eNB signal pthread_cond_t cond_eNBs; /// condition variable for gNB signal @@ -353,8 +346,6 @@ typedef struct RU_proc_t_s { pthread_mutex_t mutex_feptx; /// mutex for ru_thread pthread_mutex_t mutex_ru; - /// mutex for emulated RF thread - pthread_mutex_t mutex_emulateRF; /// symbol mask for IF4p5 reception per subframe uint32_t symbol_mask[10]; /// time measurements for each subframe @@ -394,7 +385,6 @@ typedef struct RU_proc_t_s { /// pipeline ready state int ru_rx_ready; int ru_tx_ready; - int emulate_rf_busy; /// structure for precoding thread RU_prec_t prec[16]; @@ -407,7 +397,6 @@ typedef enum { REMOTE_IF4p5 =3, REMOTE_IF1pp =4, MAX_RU_IF_TYPES =5 - //EMULATE_RF =6 } RU_if_south_t; @@ -453,8 +442,6 @@ typedef struct RU_t_s { node_function_t function; /// Ethernet parameters for fronthaul interface eth_params_t eth_params; - /// flag to indicate RF emulation mode - int emulate_rf; /// numerology index int numerology; /// flag to indicate the RU is in sync with a master reference diff --git a/openair1/PHY/defs_eNB.h b/openair1/PHY/defs_eNB.h index 68ebf65462..2a889c4570 100644 --- a/openair1/PHY/defs_eNB.h +++ b/openair1/PHY/defs_eNB.h @@ -255,11 +255,6 @@ typedef struct { tpool_t *threadPool; int nbDecode; notifiedFIFO_t *respDecode; - pthread_mutex_t mutex_emulateRF; - int instance_cnt_emulateRF; - pthread_t pthread_emulateRF; - pthread_attr_t attr_emulateRF; - pthread_cond_t cond_emulateRF; int first_rx; } L1_rxtx_proc_t; diff --git a/openair1/SIMULATION/LTE_PHY/dlsim.c b/openair1/SIMULATION/LTE_PHY/dlsim.c index 5e6140db9d..a593a0dfb4 100644 --- a/openair1/SIMULATION/LTE_PHY/dlsim.c +++ b/openair1/SIMULATION/LTE_PHY/dlsim.c @@ -90,7 +90,6 @@ static int cmpdouble(const void *p1, const void *p2) { } RAN_CONTEXT_t RC; -int emulate_rf = 0; void handler(int sig) { void *array[10]; size_t size; diff --git a/openair1/SIMULATION/LTE_PHY/mbmssim.c b/openair1/SIMULATION/LTE_PHY/mbmssim.c index ac50bf62bd..dac151e4fe 100644 --- a/openair1/SIMULATION/LTE_PHY/mbmssim.c +++ b/openair1/SIMULATION/LTE_PHY/mbmssim.c @@ -89,8 +89,6 @@ int n_rx_dropped = 0; /*!< \brief initial max process time for rx */ THREAD_STRUCT thread_struct; -int emulate_rf = 0; - void handler(int sig) { void *array[10]; size_t size; From 946939e8ccca9ea864d662e2ab4d10f542c62fcf Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 14 Aug 2025 16:35:49 +0200 Subject: [PATCH 547/964] CI: integrate RFemulator phytest in timing-phytest pipeline --- .../gnb_phytest_rfemulator_run_100_2x2.xml | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 ci-scripts/xml_files/gnb_phytest_rfemulator_run_100_2x2.xml diff --git a/ci-scripts/xml_files/gnb_phytest_rfemulator_run_100_2x2.xml b/ci-scripts/xml_files/gnb_phytest_rfemulator_run_100_2x2.xml new file mode 100644 index 0000000000..3d2efb5084 --- /dev/null +++ b/ci-scripts/xml_files/gnb_phytest_rfemulator_run_100_2x2.xml @@ -0,0 +1,70 @@ + + + gNB-PHY-Test-100-2x2-RFemu + Timing phytest 100 MHz 2x2 RFemulator + tasks + +100000 390101 000001 390109 200000 + + + + Custom_Command + Disable Sleep States + caracal + sudo cpupower idle-set -D 0 + + + Custom_Command + true + Enable Sleep States + caracal + sudo cpupower idle-set -E + + + + Initialize_eNB + Initialize gNB USRP + caracal + -O ci-scripts/conf_files/gnb.band79.273prb.usrpn300.phytest-dora.conf --phy-test -q -U 768 -T 273 -t 23 -D 127 -m 23 -M 273 -l 2 --device.name rf_emulator --rf_emulator.noise_level_dBFS -36 --log_config.global_log_options level,nocolor,time + datalog_rt_stats.100.2x2.yaml + NR + numactl --cpunodebind=netdev:enp94s0f0np0 --membind=netdev:enp94s0f0np0 + + + + IdleSleep + Sleep + 60 + + + + + Terminate_eNB + caracal + true + Terminate gNB + NR + + + From 42ad189bf3904e5bffe88543d0edfc57d2db2fc8 Mon Sep 17 00:00:00 2001 From: Romain Beurdouche Date: Thu, 14 Aug 2025 16:30:09 +0000 Subject: [PATCH 548/964] feat(rf_emulator): documentation --- doc/README.md | 1 + radio/emulator/README.md | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 radio/emulator/README.md diff --git a/doc/README.md b/doc/README.md index 40f838750a..8ed2d8896b 100644 --- a/doc/README.md +++ b/doc/README.md @@ -118,6 +118,7 @@ Some directories under `radio` contain READMEs: - [IQPlayer](../radio/iqplayer/DOC/iqrecordplayer_usage.md), and [general documentation](./iqrecordplayer_usage.md) - [fhi_72](../radio/fhi_72/README.md) - [vrtsim](../radio/vrtsim/README.md) +- [rf_emulator](../radio/emulator/README.md) The other SDRs (AW2S, LimeSDR, ...) have no READMEs. diff --git a/radio/emulator/README.md b/radio/emulator/README.md new file mode 100644 index 0000000000..b3b58ba6a7 --- /dev/null +++ b/radio/emulator/README.md @@ -0,0 +1,25 @@ +# RF emulator library + +The RF emulator is a simple network stack terminator on the RF side. +It is meant to run the network stack without real radio and without RF simulation. +It simply drops TX signal and generate noise as an RX signal. +It can be used in `phy-test` mode to simply benchmark the network stack in a determined scenario. +It synchronizes the network stack on the real time clock of the host to guarantee a realistic behavior of the network stack. +It detects and report late samples reads and writes to assess the real time behavior of the network stack. + +## Building + +`librf_emulator.so` is built by default by the `build_oai.sh` script. +It is then located in the root build directory (usually `cmake_targets/ran_build/build`). + +## Usage + +### Enabling `rf_emulator` + +Use the option `--device.name rf_emulator` of the softmodem to use the RF emulator. + +### Options + +Two options are available to configure the RF emulator: +* `--rf_emulator.enable_noise ` Enables (enable = 1) or disables (enable = 0) noise generation on RX. By default noise generation is enabled. +* `--rf_emulator.noise_level_dBFS ` Sets the level of noise generated in dB. If omitted no noise is generated. From 2de3d1f525df1fb45dc1e3f061ed34af5057ef76 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 21 Aug 2025 18:18:13 +0200 Subject: [PATCH 549/964] CI: Upgrade RFsim CNs to v2.1.10 --- .../yaml_files/5g_f1_rfsimulator/docker-compose.yaml | 6 +++--- .../yaml_files/5g_fdd_rfsimulator/docker-compose.yaml | 6 +++--- ci-scripts/yaml_files/5g_rfsimulator/README.md | 8 ++++---- ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml | 6 +++--- .../yaml_files/5g_rfsimulator_24prb/docker-compose.yaml | 6 +++--- .../yaml_files/5g_rfsimulator_2x2/docker-compose.yaml | 6 +++--- .../yaml_files/5g_rfsimulator_e1/docker-compose.yaml | 6 +++--- .../5g_rfsimulator_fr2_32prb/docker-compose.yaml | 6 +++--- .../yaml_files/5g_rfsimulator_ntn_geo/docker-compose.yaml | 6 +++--- .../yaml_files/5g_rfsimulator_ntn_leo/docker-compose.yaml | 6 +++--- .../5g_rfsimulator_u0_25prb/docker-compose.yaml | 6 +++--- 11 files changed, 34 insertions(+), 34 deletions(-) diff --git a/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml b/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml index 541bde6372..18313d0559 100644 --- a/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml @@ -24,7 +24,7 @@ services: ipv4_address: 192.168.71.131 oai-amf: container_name: "rfsim5g-oai-amf" - image: oaisoftwarealliance/oai-amf:v2.1.9 + image: oaisoftwarealliance/oai-amf:v2.1.10 environment: - TZ=Europe/paris volumes: @@ -36,7 +36,7 @@ services: ipv4_address: 192.168.71.132 oai-smf: container_name: "rfsim5g-oai-smf" - image: oaisoftwarealliance/oai-smf:v2.1.9 + image: oaisoftwarealliance/oai-smf:v2.1.10 environment: - TZ=Europe/Paris volumes: @@ -48,7 +48,7 @@ services: ipv4_address: 192.168.71.133 oai-upf: container_name: "rfsim5g-oai-upf" - image: oaisoftwarealliance/oai-upf:v2.1.9 + image: oaisoftwarealliance/oai-upf:v2.1.10 init: true environment: - TZ=Europe/Paris diff --git a/ci-scripts/yaml_files/5g_fdd_rfsimulator/docker-compose.yaml b/ci-scripts/yaml_files/5g_fdd_rfsimulator/docker-compose.yaml index 164a9bc0d4..9eec82a98b 100644 --- a/ci-scripts/yaml_files/5g_fdd_rfsimulator/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_fdd_rfsimulator/docker-compose.yaml @@ -24,7 +24,7 @@ services: ipv4_address: 192.168.71.131 oai-amf: container_name: "rfsim5g-oai-amf" - image: oaisoftwarealliance/oai-amf:v2.1.9 + image: oaisoftwarealliance/oai-amf:v2.1.10 environment: - TZ=Europe/paris volumes: @@ -36,7 +36,7 @@ services: ipv4_address: 192.168.71.132 oai-smf: container_name: "rfsim5g-oai-smf" - image: oaisoftwarealliance/oai-smf:v2.1.9 + image: oaisoftwarealliance/oai-smf:v2.1.10 environment: - TZ=Europe/Paris volumes: @@ -48,7 +48,7 @@ services: ipv4_address: 192.168.71.133 oai-upf: container_name: "rfsim5g-oai-upf" - image: oaisoftwarealliance/oai-upf:v2.1.9 + image: oaisoftwarealliance/oai-upf:v2.1.10 init: true environment: - TZ=Europe/Paris diff --git a/ci-scripts/yaml_files/5g_rfsimulator/README.md b/ci-scripts/yaml_files/5g_rfsimulator/README.md index 7e0858457c..629d0860fd 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator/README.md +++ b/ci-scripts/yaml_files/5g_rfsimulator/README.md @@ -37,9 +37,9 @@ Now pull images. ```bash $ docker pull mysql:8.0 -$ docker pull oaisoftwarealliance/oai-amf:v2.1.9 -$ docker pull oaisoftwarealliance/oai-smf:v2.1.9 -$ docker pull oaisoftwarealliance/oai-upf:v2.1.9 +$ docker pull oaisoftwarealliance/oai-amf:v2.1.10 +$ docker pull oaisoftwarealliance/oai-smf:v2.1.10 +$ docker pull oaisoftwarealliance/oai-upf:v2.1.10 $ docker pull oaisoftwarealliance/trf-gen-cn5g:focal $ docker pull oaisoftwarealliance/oai-gnb:develop @@ -52,7 +52,7 @@ $ docker logout **CAUTION: 2023/01/27 with the release `v1.5.0` of the `CN5G`, the previous version was not compatible any-more.** -**This new version is working only with the `v2.1.9` of the `CN5G`.** +**This new version is working only with `v2.1.9` or later of the `CN5G`.** # 2. Deploy containers # diff --git a/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml index d531b15270..ecdf79872b 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml @@ -24,7 +24,7 @@ services: ipv4_address: 192.168.71.131 oai-amf: container_name: "rfsim5g-oai-amf" - image: oaisoftwarealliance/oai-amf:v2.1.9 + image: oaisoftwarealliance/oai-amf:v2.1.10 environment: - TZ=Europe/paris volumes: @@ -36,7 +36,7 @@ services: ipv4_address: 192.168.71.132 oai-smf: container_name: "rfsim5g-oai-smf" - image: oaisoftwarealliance/oai-smf:v2.1.9 + image: oaisoftwarealliance/oai-smf:v2.1.10 environment: - TZ=Europe/Paris volumes: @@ -48,7 +48,7 @@ services: ipv4_address: 192.168.71.133 oai-upf: container_name: "rfsim5g-oai-upf" - image: oaisoftwarealliance/oai-upf:v2.1.9 + image: oaisoftwarealliance/oai-upf:v2.1.10 init: true environment: - TZ=Europe/Paris diff --git a/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml index 7b09c4a955..9cab11ea9e 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml @@ -24,7 +24,7 @@ services: ipv4_address: 192.168.71.131 oai-amf: container_name: "rfsim5g-oai-amf" - image: oaisoftwarealliance/oai-amf:v2.1.9 + image: oaisoftwarealliance/oai-amf:v2.1.10 environment: - TZ=Europe/paris volumes: @@ -36,7 +36,7 @@ services: ipv4_address: 192.168.71.132 oai-smf: container_name: "rfsim5g-oai-smf" - image: oaisoftwarealliance/oai-smf:v2.1.9 + image: oaisoftwarealliance/oai-smf:v2.1.10 environment: - TZ=Europe/Paris volumes: @@ -48,7 +48,7 @@ services: ipv4_address: 192.168.71.133 oai-upf: container_name: "rfsim5g-oai-upf" - image: oaisoftwarealliance/oai-upf:v2.1.9 + image: oaisoftwarealliance/oai-upf:v2.1.10 init: true environment: - TZ=Europe/Paris diff --git a/ci-scripts/yaml_files/5g_rfsimulator_2x2/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_2x2/docker-compose.yaml index ba7b9a86f4..778754fd58 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_2x2/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_2x2/docker-compose.yaml @@ -24,7 +24,7 @@ services: ipv4_address: 192.168.71.131 oai-amf: container_name: "rfsim5g-oai-amf" - image: oaisoftwarealliance/oai-amf:v2.1.9 + image: oaisoftwarealliance/oai-amf:v2.1.10 environment: - TZ=Europe/paris volumes: @@ -36,7 +36,7 @@ services: ipv4_address: 192.168.71.132 oai-smf: container_name: "rfsim5g-oai-smf" - image: oaisoftwarealliance/oai-smf:v2.1.9 + image: oaisoftwarealliance/oai-smf:v2.1.10 environment: - TZ=Europe/Paris volumes: @@ -48,7 +48,7 @@ services: ipv4_address: 192.168.71.133 oai-upf: container_name: "rfsim5g-oai-upf" - image: oaisoftwarealliance/oai-upf:v2.1.9 + image: oaisoftwarealliance/oai-upf:v2.1.10 init: true environment: - TZ=Europe/Paris diff --git a/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml index 53fa6a8181..9ccce2a8e1 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml @@ -24,7 +24,7 @@ services: ipv4_address: 192.168.71.131 oai-amf: container_name: "rfsim5g-oai-amf" - image: oaisoftwarealliance/oai-amf:v2.1.9 + image: oaisoftwarealliance/oai-amf:v2.1.10 environment: - TZ=Europe/paris volumes: @@ -36,7 +36,7 @@ services: ipv4_address: 192.168.71.132 oai-smf: container_name: "rfsim5g-oai-smf" - image: oaisoftwarealliance/oai-smf:v2.1.9 + image: oaisoftwarealliance/oai-smf:v2.1.10 environment: - TZ=Europe/Paris volumes: @@ -48,7 +48,7 @@ services: ipv4_address: 192.168.71.133 oai-upf: container_name: "rfsim5g-oai-upf" - image: oaisoftwarealliance/oai-upf:v2.1.9 + image: oaisoftwarealliance/oai-upf:v2.1.10 init: true environment: - TZ=Europe/Paris diff --git a/ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb/docker-compose.yaml index aa0b9a6ca3..13d91d9090 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb/docker-compose.yaml @@ -24,7 +24,7 @@ services: ipv4_address: 192.168.71.131 oai-amf: container_name: "rfsim5g-oai-amf" - image: oaisoftwarealliance/oai-amf:v2.1.9 + image: oaisoftwarealliance/oai-amf:v2.1.10 environment: - TZ=Europe/paris volumes: @@ -36,7 +36,7 @@ services: ipv4_address: 192.168.71.132 oai-smf: container_name: "rfsim5g-oai-smf" - image: oaisoftwarealliance/oai-smf:v2.1.9 + image: oaisoftwarealliance/oai-smf:v2.1.10 environment: - TZ=Europe/Paris volumes: @@ -48,7 +48,7 @@ services: ipv4_address: 192.168.71.133 oai-upf: container_name: "rfsim5g-oai-upf" - image: oaisoftwarealliance/oai-upf:v2.1.9 + image: oaisoftwarealliance/oai-upf:v2.1.10 init: true environment: - TZ=Europe/Paris diff --git a/ci-scripts/yaml_files/5g_rfsimulator_ntn_geo/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_ntn_geo/docker-compose.yaml index f127fdc3b0..c83060b713 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_ntn_geo/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_ntn_geo/docker-compose.yaml @@ -24,7 +24,7 @@ services: ipv4_address: 192.168.71.131 oai-amf: container_name: "rfsim5g-oai-amf" - image: oaisoftwarealliance/oai-amf:v2.1.9 + image: oaisoftwarealliance/oai-amf:v2.1.10 environment: - TZ=Europe/paris volumes: @@ -36,7 +36,7 @@ services: ipv4_address: 192.168.71.132 oai-smf: container_name: "rfsim5g-oai-smf" - image: oaisoftwarealliance/oai-smf:v2.1.9 + image: oaisoftwarealliance/oai-smf:v2.1.10 environment: - TZ=Europe/Paris volumes: @@ -48,7 +48,7 @@ services: ipv4_address: 192.168.71.133 oai-upf: container_name: "rfsim5g-oai-upf" - image: oaisoftwarealliance/oai-upf:v2.1.9 + image: oaisoftwarealliance/oai-upf:v2.1.10 init: true environment: - TZ=Europe/Paris diff --git a/ci-scripts/yaml_files/5g_rfsimulator_ntn_leo/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_ntn_leo/docker-compose.yaml index a0c44153cd..5469b0b247 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_ntn_leo/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_ntn_leo/docker-compose.yaml @@ -23,7 +23,7 @@ services: ipv4_address: 192.168.71.131 oai-amf: container_name: "rfsim5g-oai-amf" - image: oaisoftwarealliance/oai-amf:v2.1.9 + image: oaisoftwarealliance/oai-amf:v2.1.10 environment: - TZ=Europe/paris volumes: @@ -35,7 +35,7 @@ services: ipv4_address: 192.168.71.132 oai-smf: container_name: "rfsim5g-oai-smf" - image: oaisoftwarealliance/oai-smf:v2.1.9 + image: oaisoftwarealliance/oai-smf:v2.1.10 environment: - TZ=Europe/Paris volumes: @@ -47,7 +47,7 @@ services: ipv4_address: 192.168.71.133 oai-upf: container_name: "rfsim5g-oai-upf" - image: oaisoftwarealliance/oai-upf:v2.1.9 + image: oaisoftwarealliance/oai-upf:v2.1.10 environment: - TZ=Europe/Paris volumes: diff --git a/ci-scripts/yaml_files/5g_rfsimulator_u0_25prb/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_u0_25prb/docker-compose.yaml index a1b873eb96..ed1701ef86 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_u0_25prb/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_u0_25prb/docker-compose.yaml @@ -24,7 +24,7 @@ services: ipv4_address: 192.168.71.131 oai-amf: container_name: "rfsim5g-oai-amf" - image: oaisoftwarealliance/oai-amf:v2.1.9 + image: oaisoftwarealliance/oai-amf:v2.1.10 environment: - TZ=Europe/paris volumes: @@ -36,7 +36,7 @@ services: ipv4_address: 192.168.71.132 oai-smf: container_name: "rfsim5g-oai-smf" - image: oaisoftwarealliance/oai-smf:v2.1.9 + image: oaisoftwarealliance/oai-smf:v2.1.10 environment: - TZ=Europe/Paris volumes: @@ -48,7 +48,7 @@ services: ipv4_address: 192.168.71.133 oai-upf: container_name: "rfsim5g-oai-upf" - image: oaisoftwarealliance/oai-upf:v2.1.9 + image: oaisoftwarealliance/oai-upf:v2.1.10 init: true environment: - TZ=Europe/Paris From 792a7faf09bd8dad11eea6fe6c8a31c9df22e477 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 21 Aug 2025 18:19:04 +0200 Subject: [PATCH 550/964] MBIM stop script: remove IP address The CI detects whether a UE connected (and has a PDU session) by trying to read the IP address. It therefore assumes that as long as the UE is not connected, no IP would be present. With the existing stop_quectel_mbim.sh script, this was not the case; it would simply leave the IP address. Modify this script to flush all IP addresses on disconnect to remedy this. --- ci-scripts/mbim_scripts/stop_quectel_mbim.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ci-scripts/mbim_scripts/stop_quectel_mbim.sh b/ci-scripts/mbim_scripts/stop_quectel_mbim.sh index e7dbbaa43d..5115646b0d 100644 --- a/ci-scripts/mbim_scripts/stop_quectel_mbim.sh +++ b/ci-scripts/mbim_scripts/stop_quectel_mbim.sh @@ -1,3 +1,7 @@ set -x sudo mbimcli -p -d /dev/cdc-wdm0 --set-radio-state=off + +IF=wwan0 +sudo ip link set ${IF} down +sudo ip addr flush dev ${IF} From 598fbb5a241eeda6b94b24e11e46023486c52af8 Mon Sep 17 00:00:00 2001 From: Bartosz Podrygajlo Date: Fri, 18 Apr 2025 11:08:54 +0200 Subject: [PATCH 551/964] Consider PDSCH EPRE to DMRS EPRE in NR UE --- common/utils/nr/nr_common.c | 4 ++-- common/utils/nr/nr_common.h | 10 +++++----- openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c | 3 +-- openair1/PHY/NR_REFSIG/nr_dmrs_rx.c | 4 +++- openair1/PHY/NR_REFSIG/refsig_defs_ue.h | 3 ++- .../PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c | 6 +++++- openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h | 1 + openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c | 2 +- openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 1 + 9 files changed, 21 insertions(+), 13 deletions(-) diff --git a/common/utils/nr/nr_common.c b/common/utils/nr/nr_common.c index 7954db7d54..265b680500 100644 --- a/common/utils/nr/nr_common.c +++ b/common/utils/nr/nr_common.c @@ -1465,13 +1465,13 @@ frequency_range_t get_freq_range_from_band(uint16_t band) return band <= 256 ? FR1 : FR2; } -float get_beta_dmrs_pusch(int num_cdm_groups_no_data, pusch_dmrs_type_t dmrs_type) +float get_beta_dmrs(int num_cdm_groups_no_data, bool is_type2) { float beta_dmrs_pusch = 1.0; if (num_cdm_groups_no_data == 2) { beta_dmrs_pusch = powf(10.0, 3.0 / 20.0); } else if (num_cdm_groups_no_data == 3) { - if (dmrs_type == pusch_dmrs_type2) + if (is_type2) beta_dmrs_pusch = powf(10.0, 4.77 / 20.0); } return beta_dmrs_pusch; diff --git a/common/utils/nr/nr_common.h b/common/utils/nr/nr_common.h index 752d500c1b..6ab3f58dab 100644 --- a/common/utils/nr/nr_common.h +++ b/common/utils/nr/nr_common.h @@ -320,15 +320,15 @@ frequency_range_t get_freq_range_from_arfcn(uint32_t arfcn); frequency_range_t get_freq_range_from_band(uint16_t band); /** - * @brief Calculates the scaling factor for the ratio of PUSCH EPRE to DMRS EPRE. + * @brief Calculates the scaling factor for the ratio of PUSCH/PDSCH EPRE to DMRS EPRE. * * @param num_cdm_groups_no_data The number of CDM groups without data. - * @param dmrs_type The DMRS type. - * @return The calculated beta scaling factor for the ratio of PUSCH EPRE to DMRS EPRE. + * @param is_type2 true if calculating for DMRS configuration type 2 + * @return The calculated beta scaling factor for the ratio of PUSCH/PDSCH EPRE to DMRS EPRE. * - * @note The values are derived from TS 38.214 Table 6.2.2-1. + * @note The values are the same for PUSCH and PDSCH and are derived from TS 38.214 Table 6.2.2-1./4.1-1 */ -float get_beta_dmrs_pusch(int num_cdm_groups_no_data, pusch_dmrs_type_t dmrs_type); +float get_beta_dmrs(int num_cdm_groups_no_data, bool is_type2); #define CEILIDIV(a,b) ((a+b-1)/b) #define ROUNDIDIV(a,b) (((a<<1)+b)/(b<<1)) diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c index 383140ba88..3b644ba4d3 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c @@ -499,8 +499,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, pusch_pdu->scid, Ns, symbol); - pusch_dmrs_type_t dmrs_type = pusch_pdu->dmrs_config_type == NFAPI_NR_DMRS_TYPE1 ? pusch_dmrs_type1 : pusch_dmrs_type2; - float beta_dmrs_pusch = get_beta_dmrs_pusch(pusch_pdu->num_dmrs_cdm_grps_no_data, dmrs_type); + float beta_dmrs_pusch = get_beta_dmrs(pusch_pdu->num_dmrs_cdm_grps_no_data, pusch_pdu->dmrs_config_type == pusch_dmrs_type2); int16_t dmrs_scaling = (1 / beta_dmrs_pusch) * (1 << 14); nr_pusch_dmrs_rx(gNB, Ns, diff --git a/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c b/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c index e929fc5f3e..7fd703ea30 100644 --- a/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c +++ b/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c @@ -117,7 +117,8 @@ int nr_pdsch_dmrs_rx(const PHY_VARS_NR_UE *ue, unsigned short p, unsigned char lp, unsigned short nb_pdsch_rb, - uint8_t config_type) + uint8_t config_type, + int16_t dmrs_scaling) { typedef int array_of_w[2]; const array_of_w *wf = (config_type == NFAPI_NR_DMRS_TYPE1) ? wf1 : wf2; @@ -131,6 +132,7 @@ int nr_pdsch_dmrs_rx(const PHY_VARS_NR_UE *ue, for (int i = 0; i < nb_pdsch_rb * ((config_type == NFAPI_NR_DMRS_TYPE1) ? 6 : 4); i++) { int w = (wf[p - 1000][i & 1]) * (wt[p - 1000][lp]); output[i] = get_modulated(nr_gold_pdsch, i, w == 1); + output[i] = c16mulRealShift(output[i], dmrs_scaling, 14); #ifdef DEBUG_PDSCH printf("nr_pdsch_dmrs_rx dmrs config type %d port %d nb_pdsch_rb %d\n", config_type, p, nb_pdsch_rb); diff --git a/openair1/PHY/NR_REFSIG/refsig_defs_ue.h b/openair1/PHY/NR_REFSIG/refsig_defs_ue.h index 7df105d05c..1d2d4b87ae 100644 --- a/openair1/PHY/NR_REFSIG/refsig_defs_ue.h +++ b/openair1/PHY/NR_REFSIG/refsig_defs_ue.h @@ -49,7 +49,8 @@ int nr_pdsch_dmrs_rx(const PHY_VARS_NR_UE *ue, unsigned short p, unsigned char lp, unsigned short nb_pdsch_rb, - uint8_t config_type); + uint8_t config_type, + int16_t dmrs_scaling); void sl_generate_pss(SL_NR_UE_INIT_PARAMS_t *sl_init_params, uint8_t n_sl_id2, uint16_t scaling); void sl_generate_pss_ifft_samples(sl_nr_ue_phy_params_t *sl_ue_params, SL_NR_UE_INIT_PARAMS_t *sl_init_params); diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c index 0e186a3bc3..a291eb9bd1 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c @@ -19,6 +19,7 @@ * contact@openairinterface.org */ +#include "nr_common.h" #include #include "SCHED_NR_UE/defs.h" #include "nr_estimation.h" @@ -1258,6 +1259,7 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, unsigned short scrambling_id, unsigned short BWPStart, uint8_t config_type, + int n_dmrs_cdm_groups, uint16_t rb_offset, unsigned short bwp_start_subcarrier, unsigned short nb_rb_pdsch, @@ -1291,8 +1293,10 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, c16_t pilot[3280] __attribute__((aligned(16))); // Note: pilot returned by the following function is already the complex conjugate of the transmitted DMRS + float beta_dmrs_pdsch = get_beta_dmrs(n_dmrs_cdm_groups, config_type == NFAPI_NR_DMRS_TYPE2); + int16_t dmrs_scaling = (int16_t)((1 / beta_dmrs_pdsch) * (1 << 14)); const uint32_t *gold = nr_gold_pdsch(fp->N_RB_DL, fp->symbols_per_slot, scrambling_id, nscid, slot, symbol); - nr_pdsch_dmrs_rx(ue, slot, gold, pilot, 1000 + p, 0, nb_rb_pdsch + rb_offset, config_type); + nr_pdsch_dmrs_rx(ue, slot, gold, pilot, 1000 + p, 0, nb_rb_pdsch + rb_offset, config_type, dmrs_scaling); delay_t delay = {0}; diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h index da6fd31eb5..0d35fe6ada 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h @@ -87,6 +87,7 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, unsigned short scrambling_id, unsigned short BWPStart, uint8_t config_type, + int n_dmrs_cdm_groups, uint16_t rb_offset, unsigned short bwp_start_subcarrier, unsigned short nb_rb_pdsch, diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c index ebfd6f6352..0eabc873e4 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c @@ -396,7 +396,7 @@ static void dmrs_amp_mult(const uint32_t dmrs_port, const pusch_dmrs_type_t dmrs_type, const unsigned int num_cdm_groups_no_data) { - float beta_dmrs_pusch = get_beta_dmrs_pusch(num_cdm_groups_no_data, dmrs_type); + float beta_dmrs_pusch = get_beta_dmrs(num_cdm_groups_no_data, dmrs_type == pusch_dmrs_type2); /* short array that hold amplitude for k_prime = 0 and k_prime = 1 */ int32_t alpha_dmrs[2] __attribute((aligned(16))); for (int_fast8_t i = 0; i < sizeofArray(alpha_dmrs); i++) { diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index b95c7b8f79..bd0e110565 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -553,6 +553,7 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, dlschCfg->dlDmrsScramblingId, dlschCfg->BWPStart, dlschCfg->dmrsConfigType, + dlschCfg->n_dmrs_cdm_groups, dlschCfg->rb_offset, ue->frame_parms.first_carrier_offset + (dlschCfg->BWPStart + dlschCfg->start_rb) * 12, dlschCfg->number_rbs, From ba585cd96da44c4e2b9b3fed8b4588a678405685 Mon Sep 17 00:00:00 2001 From: Bartosz Podrygajlo Date: Wed, 7 May 2025 15:40:05 +0200 Subject: [PATCH 552/964] Add deregistration for all UE instances. --- executables/nr-uesoftmodem.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index 8b331e4976..6a5fcf2394 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -326,9 +326,11 @@ static void trigger_stop(int sig) static void trigger_deregistration(int sig) { if (!stop_immediately && IS_SA_MODE(get_softmodem_params())) { - MessageDef *msg = itti_alloc_new_message(TASK_NAS_NRUE, 0, NAS_DEREGISTRATION_REQ); - NAS_DEREGISTRATION_REQ(msg).cause = AS_DETACH; - itti_send_msg_to_task(TASK_NAS_NRUE, 0, msg); + for (int ue_inst = 0; ue_inst < NB_UE_INST; ue_inst++) { + MessageDef *msg = itti_alloc_new_message(TASK_NAS_NRUE, ue_inst, NAS_DEREGISTRATION_REQ); + NAS_DEREGISTRATION_REQ(msg).cause = AS_DETACH; + itti_send_msg_to_task(TASK_NAS_NRUE, ue_inst, msg); + } stop_immediately = true; static const char m[] = "Press ^C again to trigger immediate shutdown\n"; __attribute__((unused)) int unused = write(STDOUT_FILENO, m, sizeof(m) - 1); From e58c52829d0bc8fcdaac0bf3f6c8fa1bd0bc7bd2 Mon Sep 17 00:00:00 2001 From: Bartosz Podrygajlo Date: Tue, 22 Jul 2025 22:42:20 +0200 Subject: [PATCH 553/964] Introduce MAX_NUM_NR_UE_INST Add a new define for maximum number of NR UE per process --- executables/nr-uesoftmodem.h | 1 + 1 file changed, 1 insertion(+) diff --git a/executables/nr-uesoftmodem.h b/executables/nr-uesoftmodem.h index e5f2eb6571..3ceb3e479e 100644 --- a/executables/nr-uesoftmodem.h +++ b/executables/nr-uesoftmodem.h @@ -5,6 +5,7 @@ #include "common/utils/threadPool/thread-pool.h" #include "PHY/defs_nr_UE.h" +#define MAX_NUM_NR_UE_INST 32 extern int NB_UE_INST; extern uint16_t ue_id_g; From 32f8f258faf1af33948c680b5ec044e1c1f334b8 Mon Sep 17 00:00:00 2001 From: Bartosz Podrygajlo Date: Tue, 22 Jul 2025 22:43:20 +0200 Subject: [PATCH 554/964] NR UE NAS: Use global define MAX_NUM_NR_UE_INST Use NR UE global MAX_NUM_NR_UE_INST define instead of local define MAX_NAS_UE --- openair3/NAS/NR_UE/nr_nas_msg.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/openair3/NAS/NR_UE/nr_nas_msg.c b/openair3/NAS/NR_UE/nr_nas_msg.c index 615cc5a4f1..cf8b5dd0d6 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg.c +++ b/openair3/NAS/NR_UE/nr_nas_msg.c @@ -76,9 +76,7 @@ #include "key_nas_deriver.h" #include "nr-uesoftmodem.h" -#define MAX_NAS_UE 4 - -static nr_ue_nas_t nr_ue_nas[MAX_NAS_UE] = {0}; +static nr_ue_nas_t nr_ue_nas[MAX_NUM_NR_UE_INST] = {0}; #define FOREACH_STATE(TYPE_DEF) \ TYPE_DEF(NAS_SECURITY_NO_SECURITY_CONTEXT, 0) \ @@ -676,7 +674,7 @@ static void derive_ue_keys(uint8_t *buf, nr_ue_nas_t *nas) nr_ue_nas_t *get_ue_nas_info(module_id_t module_id) { - DevAssert(module_id < MAX_NAS_UE); + AssertFatal(module_id < MAX_NUM_NR_UE_INST, "Invalid module_id %d\n", module_id); if (!nr_ue_nas[module_id].uicc) { nr_ue_nas[module_id].uicc = checkUicc(module_id); nr_ue_nas[module_id].UE_id = module_id; From c957e116820723532473002657271b9f4f720a0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Soares=20Silva?= Date: Fri, 22 Aug 2025 15:17:47 +0100 Subject: [PATCH 555/964] Change last_idx type to int16 to properly avoid unpacking if the tlv length is 0 --- nfapi/open-nFAPI/fapi/src/nr_fapi_p7.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nfapi/open-nFAPI/fapi/src/nr_fapi_p7.c b/nfapi/open-nFAPI/fapi/src/nr_fapi_p7.c index fa0ed1bd8f..befd2c9dd3 100644 --- a/nfapi/open-nFAPI/fapi/src/nr_fapi_p7.c +++ b/nfapi/open-nFAPI/fapi/src/nr_fapi_p7.c @@ -2308,7 +2308,7 @@ uint8_t unpack_nr_srs_report_tlv_value(nfapi_srs_report_tlv_t *report_tlv, uint8 } } #else - const uint16_t last_idx = ((report_tlv->length + 3) / 4) - 1; + const int16_t last_idx = ((report_tlv->length + 3) / 4) - 1; for (int i = 0; i < last_idx; i++) { if (!pull32(ppReadPackedMsg, &report_tlv->value[i], end)) { return 0; From 014be5326e80a36b0fb17e70735aa0c2cc639cce Mon Sep 17 00:00:00 2001 From: Bartosz Podrygajlo Date: Tue, 22 Jul 2025 22:48:53 +0200 Subject: [PATCH 556/964] Use MAX_NUM_NR_UE_INST in RRC Use MAX_NUM_NR_UE_INST for number of NR UE RRC instances. Change the RRC interface slightly so nr_rrc_init_ue initializes only one RRC instance pointed to by the id given to the function --- executables/nr-ue.c | 14 ++-- openair2/RRC/NR_UE/rrc_UE.c | 129 ++++++++++++++++++------------------ 2 files changed, 72 insertions(+), 71 deletions(-) diff --git a/executables/nr-ue.c b/executables/nr-ue.c index 0e5a308259..ed95caec5d 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -1284,20 +1284,20 @@ void *UE_thread(void *arg) void init_NR_UE(int nb_inst, char *uecap_file, char *reconfig_file, char *rbconfig_file) { - NR_UE_RRC_INST_t *rrc_inst = nr_rrc_init_ue(uecap_file, nb_inst, get_nrUE_params()->nb_antennas_tx); NR_UE_MAC_INST_t *mac_inst = nr_l2_init_ue(nb_inst); AssertFatal(mac_inst, "Couldn't allocate MAC module\n"); - for (int i = 0; i < nb_inst; i++) { - NR_UE_MAC_INST_t *mac = get_mac_inst(i); - mac->if_module = nr_ue_if_module_init(i); + for (int instance_id = 0; instance_id < nb_inst; instance_id++) { + NR_UE_MAC_INST_t *mac = get_mac_inst(instance_id); + NR_UE_RRC_INST_t *rrc = nr_rrc_init_ue(uecap_file, instance_id, get_nrUE_params()->nb_antennas_tx); + mac->if_module = nr_ue_if_module_init(instance_id); AssertFatal(mac->if_module, "can not initialize IF module\n"); if (!IS_SA_MODE(get_softmodem_params()) && !get_softmodem_params()->sl_mode) { - init_nsa_message(&rrc_inst[i], reconfig_file, rbconfig_file); - nr_rlc_activate_srb0(mac_inst[i].crnti, NULL, send_srb0_rrc); + init_nsa_message(rrc, reconfig_file, rbconfig_file); + nr_rlc_activate_srb0(mac_inst[instance_id].crnti, NULL, send_srb0_rrc); } //TODO: Move this call to RRC - start_sidelink((&rrc_inst[i])->ue_id); + start_sidelink(instance_id); } } diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 87cb68303a..df95a177d6 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -72,7 +72,7 @@ #include "nr_nas_msg.h" #include "openair2/SDAP/nr_sdap/nr_sdap_entity.h" -static NR_UE_RRC_INST_t *NR_UE_rrc_inst; +static NR_UE_RRC_INST_t *NR_UE_rrc_inst[MAX_NUM_NR_UE_INST] = {0}; /* NAS Attach request with IMSI */ static const char nr_nas_attach_req_imsi_dummy_NSA_case[] = { 0x07, @@ -149,9 +149,14 @@ static void nr_rrc_ue_process_masterCellGroup(NR_UE_RRC_INST_t *rrc, static void nr_rrc_ue_process_measConfig(rrcPerNB_t *rrc, NR_MeasConfig_t *const measConfig, NR_UE_Timers_Constants_t *timers); -NR_UE_RRC_INST_t* get_NR_UE_rrc_inst(int instance) +NR_UE_RRC_INST_t *get_NR_UE_rrc_inst(int instance) { - return &NR_UE_rrc_inst[instance]; + AssertFatal(instance >= 0 && instance < MAX_NUM_NR_UE_INST, "RRC instance %d out of bounds\n", instance); + NR_UE_RRC_INST_t *rrc = NR_UE_rrc_inst[instance]; + if (rrc == NULL) + return NULL; + AssertFatal(rrc->ue_id == instance, "RRC ID %d doesn't match with input %d\n", (int)rrc->ue_id, instance); + return rrc; } static NR_RB_status_t get_DRB_status(const NR_UE_RRC_INST_t *rrc, NR_DRB_Identity_t drb_id) @@ -731,67 +736,63 @@ static bool verify_ue_cap(NR_UE_NR_Capability_t *UE_NR_Capability, int nb_antenn return true; } -NR_UE_RRC_INST_t* nr_rrc_init_ue(char* uecap_file, int nb_inst, int num_ant_tx) +NR_UE_RRC_INST_t* nr_rrc_init_ue(char* uecap_file, int instance_id, int num_ant_tx) { - NR_UE_rrc_inst = (NR_UE_RRC_INST_t *)calloc(nb_inst, sizeof(NR_UE_RRC_INST_t)); - AssertFatal(NR_UE_rrc_inst, "Couldn't allocate %d instances of RRC module\n", nb_inst); + AssertFatal(instance_id < MAX_NUM_NR_UE_INST, "RRC instance %d out of bounds\n", instance_id); + AssertFatal(NR_UE_rrc_inst[instance_id] == NULL, "RRC instance %d already initialized\n", instance_id); + NR_UE_rrc_inst[instance_id] = calloc_or_fail(1, sizeof(NR_UE_RRC_INST_t)); + NR_UE_RRC_INST_t *rrc = NR_UE_rrc_inst[instance_id]; + rrc->ue_id = instance_id; + // fill UE-NR-Capability @ UE-CapabilityRAT-Container here. + rrc->selected_plmn_identity = 1; + rrc->ra_trigger = RA_NOT_RUNNING; + rrc->dl_bwp_id = 0; + rrc->ul_bwp_id = 0; + rrc->as_security_activated = false; + rrc->detach_after_release = false; + rrc->reconfig_after_reestab = false; + /* 5G-S-TMSI */ + rrc->fiveG_S_TMSI = UINT64_MAX; + rrc->access_barred = false; - for(int nr_ue = 0; nr_ue < nb_inst; nr_ue++) { - NR_UE_RRC_INST_t *rrc = &NR_UE_rrc_inst[nr_ue]; - rrc->ue_id = nr_ue; - // fill UE-NR-Capability @ UE-CapabilityRAT-Container here. - rrc->selected_plmn_identity = 1; - rrc->ra_trigger = RA_NOT_RUNNING; - rrc->dl_bwp_id = 0; - rrc->ul_bwp_id = 0; - rrc->as_security_activated = false; - rrc->detach_after_release = false; - rrc->reconfig_after_reestab = false; - /* 5G-S-TMSI */ - rrc->fiveG_S_TMSI = UINT64_MAX; - rrc->access_barred = false; - - FILE *f = NULL; - if (uecap_file) - f = fopen(uecap_file, "r"); - if (f) { - char UE_NR_Capability_xer[65536]; - size_t size = fread(UE_NR_Capability_xer, 1, sizeof UE_NR_Capability_xer, f); - if (size == 0 || size == sizeof UE_NR_Capability_xer) { - LOG_E(NR_RRC, "UE Capabilities XER file %s is too large (%ld)\n", uecap_file, size); - } - else { - asn_dec_rval_t dec_rval = - xer_decode(0, &asn_DEF_NR_UE_NR_Capability, (void *)&rrc->UECap.UE_NR_Capability, UE_NR_Capability_xer, size); - assert(dec_rval.code == RC_OK); - } - fclose(f); - /* Verify consistency of num PHY antennas vs UE Capabilities */ - verify_ue_cap(rrc->UECap.UE_NR_Capability, num_ant_tx); + FILE *f = NULL; + if (uecap_file) + f = fopen(uecap_file, "r"); + if (f) { + char UE_NR_Capability_xer[65536]; + size_t size = fread(UE_NR_Capability_xer, 1, sizeof UE_NR_Capability_xer, f); + if (size == 0 || size == sizeof UE_NR_Capability_xer) { + LOG_E(NR_RRC, "UE Capabilities XER file %s is too large (%ld)\n", uecap_file, size); + } else { + asn_dec_rval_t dec_rval = + xer_decode(0, &asn_DEF_NR_UE_NR_Capability, (void *)&rrc->UECap.UE_NR_Capability, UE_NR_Capability_xer, size); + assert(dec_rval.code == RC_OK); } - - memset(&rrc->timers_and_constants, 0, sizeof(rrc->timers_and_constants)); - set_default_timers_and_constants(&rrc->timers_and_constants); - - for (int j = 0; j < NR_NUM_SRB; j++) - rrc->Srb[j] = RB_NOT_PRESENT; - for (int j = 1; j <= MAX_DRBS_PER_UE; j++) - set_DRB_status(rrc, j, RB_NOT_PRESENT); - // SRB0 activated by default - rrc->Srb[0] = RB_ESTABLISHED; - for (int j = 0; j < NR_MAX_NUM_LCID; j++) - rrc->active_RLC_entity[j] = false; - - for (int i = 0; i < NB_CNX_UE; i++) { - rrcPerNB_t *ptr = &rrc->perNB[i]; - ptr->SInfo = (NR_UE_RRC_SI_INFO){0}; - init_SI_timers(&ptr->SInfo); - } - - init_sidelink(rrc); + fclose(f); + /* Verify consistency of num PHY antennas vs UE Capabilities */ + verify_ue_cap(rrc->UECap.UE_NR_Capability, num_ant_tx); } - return NR_UE_rrc_inst; + memset(&rrc->timers_and_constants, 0, sizeof(rrc->timers_and_constants)); + set_default_timers_and_constants(&rrc->timers_and_constants); + + for (int j = 0; j < NR_NUM_SRB; j++) + rrc->Srb[j] = RB_NOT_PRESENT; + for (int j = 1; j <= MAX_DRBS_PER_UE; j++) + set_DRB_status(rrc, j, RB_NOT_PRESENT); + // SRB0 activated by default + rrc->Srb[0] = RB_ESTABLISHED; + for (int j = 0; j < NR_MAX_NUM_LCID; j++) + rrc->active_RLC_entity[j] = false; + + for (int i = 0; i < NB_CNX_UE; i++) { + rrcPerNB_t *ptr = &rrc->perNB[i]; + ptr->SInfo = (NR_UE_RRC_SI_INFO){0}; + init_SI_timers(&ptr->SInfo); + } + + init_sidelink(rrc); + return rrc; } bool check_si_validity(NR_UE_RRC_SI_INFO *SI_info, int si_type) @@ -2246,7 +2247,7 @@ void *rrc_nrue(void *notUsed) instance_t instance = ITTI_MSG_DESTINATION_INSTANCE(msg_p); LOG_D(NR_RRC, "[UE %ld] Received %s\n", instance, ITTI_MSG_NAME(msg_p)); - NR_UE_RRC_INST_t *rrc = &NR_UE_rrc_inst[instance]; + NR_UE_RRC_INST_t *rrc = get_NR_UE_rrc_inst(instance); AssertFatal(instance == rrc->ue_id, "Instance %ld received from ITTI doesn't matach with UE-ID %ld\n", instance, rrc->ue_id); switch (ITTI_MSG_ID(msg_p)) { @@ -2541,7 +2542,7 @@ void *recv_msgs_from_lte_ue(void *args_p) LOG_E(NR_RRC, "%s: Received truncated message %d\n", __func__, recvLen); continue; } - process_lte_nsa_msg(NR_UE_rrc_inst, &msg, recvLen); + process_lte_nsa_msg(get_NR_UE_rrc_inst(0), &msg, recvLen); } return NULL; } @@ -2679,8 +2680,8 @@ static void process_lte_nsa_msg(NR_UE_RRC_INST_t *rrc, nsa_msg_t *msg, int msg_l uint8_t *nr_RadioBearer_buffer = msg_buffer + offsetof(struct msg, buffer); uint8_t *nr_SecondaryCellGroup_buffer = nr_RadioBearer_buffer + nr_RadioBearer_size; - process_nsa_message(NR_UE_rrc_inst, nr_SecondaryCellGroupConfig_r15, nr_SecondaryCellGroup_buffer, nr_SecondaryCellGroup_size); - process_nsa_message(NR_UE_rrc_inst, nr_RadioBearerConfigX_r15, nr_RadioBearer_buffer, nr_RadioBearer_size); + process_nsa_message(get_NR_UE_rrc_inst(0), nr_SecondaryCellGroupConfig_r15, nr_SecondaryCellGroup_buffer, nr_SecondaryCellGroup_size); + process_nsa_message(get_NR_UE_rrc_inst(0), nr_RadioBearerConfigX_r15, nr_RadioBearer_buffer, nr_RadioBearer_size); LOG_I(NR_RRC, "Calling do_NR_RRCReconfigurationComplete. t_id %ld \n", t_id); uint8_t buffer[NR_RRC_BUF_SIZE]; size_t size = do_NR_RRCReconfigurationComplete_for_nsa(buffer, sizeof(buffer), t_id); @@ -2944,7 +2945,7 @@ void handle_t430_expiry(NR_UE_RRC_INST_t *rrc) void start_sidelink(int instance) { - NR_UE_RRC_INST_t *rrc = &NR_UE_rrc_inst[instance]; + NR_UE_RRC_INST_t *rrc = get_NR_UE_rrc_inst(instance); if (get_softmodem_params()->sl_mode == 2) { From 0d651bf3a9dc881b4a597b579379028858f7c368 Mon Sep 17 00:00:00 2001 From: Bartosz Podrygajlo Date: Tue, 22 Jul 2025 22:56:59 +0200 Subject: [PATCH 557/964] Add MAX_NUM_NR_UE_INST to NR UE MAC - Use MAX_NUM_NR_UE_INST in NR UE MAC to control number of MAC instances. - Modify the MAC interface slightly so that nr_l2_init_ue only initializes one instance --- common/utils/telnetsrv/CMakeLists.txt | 2 +- executables/nr-ue.c | 9 ++--- openair1/SIMULATION/NR_PHY/dlsim.c | 3 +- openair1/SIMULATION/NR_PHY/ulsim.c | 3 +- openair2/LAYER2/NR_MAC_UE/main_ue_nr.c | 47 +++++++++++++------------- 5 files changed, 30 insertions(+), 34 deletions(-) diff --git a/common/utils/telnetsrv/CMakeLists.txt b/common/utils/telnetsrv/CMakeLists.txt index 5f190edc02..1a740adbe2 100644 --- a/common/utils/telnetsrv/CMakeLists.txt +++ b/common/utils/telnetsrv/CMakeLists.txt @@ -62,7 +62,7 @@ add_dependencies(telnetsrv telnetsrv_ci) message(STATUS "Add CI specific telnet functions for nrUE in telnetsrv_ciUE.so") add_library(telnetsrv_ciUE MODULE telnetsrv_ciUE.c) -target_link_libraries(telnetsrv_ciUE PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) +target_link_libraries(telnetsrv_ciUE PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs UTIL) add_dependencies(telnetsrv telnetsrv_ciUE) message(STATUS "Add bearer specific telnet functions in libtelnetsrv_bearer.so") diff --git a/executables/nr-ue.c b/executables/nr-ue.c index ed95caec5d..4a534df3b6 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -1284,17 +1284,14 @@ void *UE_thread(void *arg) void init_NR_UE(int nb_inst, char *uecap_file, char *reconfig_file, char *rbconfig_file) { - NR_UE_MAC_INST_t *mac_inst = nr_l2_init_ue(nb_inst); - AssertFatal(mac_inst, "Couldn't allocate MAC module\n"); - for (int instance_id = 0; instance_id < nb_inst; instance_id++) { - NR_UE_MAC_INST_t *mac = get_mac_inst(instance_id); - NR_UE_RRC_INST_t *rrc = nr_rrc_init_ue(uecap_file, instance_id, get_nrUE_params()->nb_antennas_tx); + NR_UE_RRC_INST_t* rrc = nr_rrc_init_ue(uecap_file, instance_id, get_nrUE_params()->nb_antennas_tx); + NR_UE_MAC_INST_t *mac = nr_l2_init_ue(instance_id); mac->if_module = nr_ue_if_module_init(instance_id); AssertFatal(mac->if_module, "can not initialize IF module\n"); if (!IS_SA_MODE(get_softmodem_params()) && !get_softmodem_params()->sl_mode) { init_nsa_message(rrc, reconfig_file, rbconfig_file); - nr_rlc_activate_srb0(mac_inst[instance_id].crnti, NULL, send_srb0_rrc); + nr_rlc_activate_srb0(mac->crnti, NULL, send_srb0_rrc); } //TODO: Move this call to RRC start_sidelink(instance_id); diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index 0f21fdb145..fdca90b094 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -924,8 +924,7 @@ printf("%d\n", slot); init_nr_ue_transport(UE); - nr_l2_init_ue(1); - UE_mac = get_mac_inst(0); + UE_mac = nr_l2_init_ue(0); ue_init_config_request(UE_mac, get_slots_per_frame_from_scs(mu)); UE->if_inst = nr_ue_if_module_init(0); diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index e5361a3e2d..466ffc6822 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -780,8 +780,7 @@ int main(int argc, char *argv[]) init_nr_ue_transport(UE); //Configure UE - nr_l2_init_ue(1); - NR_UE_MAC_INST_t* UE_mac = get_mac_inst(0); + NR_UE_MAC_INST_t* UE_mac = nr_l2_init_ue(0); ue_init_config_request(UE_mac, get_slots_per_frame_from_scs(mu)); diff --git a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c index e189d7dcf9..78328461b4 100644 --- a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c +++ b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c @@ -38,7 +38,7 @@ #include "nr_rlc/nr_rlc_oai_api.h" #include "RRC/NR_UE/rrc_proto.h" #include -static NR_UE_MAC_INST_t *nr_ue_mac_inst; +static NR_UE_MAC_INST_t *nr_ue_mac_inst[MAX_NUM_NR_UE_INST] = {0}; void send_srb0_rrc(int ue_id, const uint8_t *sdu, sdu_size_t sdu_len, void *data) { @@ -124,37 +124,38 @@ NR_UE_L2_STATE_t nr_ue_get_sync_state(module_id_t mod_id) return mac->state; } -NR_UE_MAC_INST_t *nr_l2_init_ue(int nb_inst) +NR_UE_MAC_INST_t *nr_l2_init_ue(int instance_id) { - //init mac here - nr_ue_mac_inst = (NR_UE_MAC_INST_t *)calloc(nb_inst, sizeof(NR_UE_MAC_INST_t)); - AssertFatal(nr_ue_mac_inst, "Couldn't allocate %d instances of MAC module\n", nb_inst); + AssertFatal(instance_id < MAX_NUM_NR_UE_INST, "instance_id %d is out of range\n", instance_id); + AssertFatal(nr_ue_mac_inst[instance_id] == NULL, "MAC instance %d already initialized\n", instance_id); + nr_ue_mac_inst[instance_id] = calloc_or_fail(1, sizeof(NR_UE_MAC_INST_t)); - for (int j = 0; j < nb_inst; j++) { - NR_UE_MAC_INST_t *mac = &nr_ue_mac_inst[j]; - mac->ue_id = j; - nr_ue_init_mac(mac); - int ret = pthread_mutex_init(&mac->if_mutex, NULL); - AssertFatal(ret == 0, "Mutex init failed\n"); - nr_ue_mac_default_configs(mac); - if (IS_SA_MODE(get_softmodem_params())) - ue_init_config_request(mac, get_slots_per_frame_from_scs(get_softmodem_params()->numerology)); + NR_UE_MAC_INST_t *mac = nr_ue_mac_inst[instance_id]; + mac->ue_id = instance_id; + nr_ue_init_mac(mac); + int ret = pthread_mutex_init(&mac->if_mutex, NULL); + AssertFatal(ret == 0, "Mutex init failed\n"); + nr_ue_mac_default_configs(mac); + if (IS_SA_MODE(get_softmodem_params())) + ue_init_config_request(mac, get_slots_per_frame_from_scs(get_softmodem_params()->numerology)); + + static bool initialized = false; + if (!initialized) { + int rc = nr_rlc_module_init(NR_RLC_OP_MODE_UE); + AssertFatal(rc == 0, "Could not initialize RLC layer\n"); + initialized = true; } - int rc = nr_rlc_module_init(NR_RLC_OP_MODE_UE); - AssertFatal(rc == 0, "Could not initialize RLC layer\n"); + nr_rlc_activate_srb0(instance_id, NULL, send_srb0_rrc); - for (int j = 0; j < nb_inst; j++) { - nr_rlc_activate_srb0(j, NULL, send_srb0_rrc); - } - - return (nr_ue_mac_inst); + return nr_ue_mac_inst[instance_id]; } NR_UE_MAC_INST_t *get_mac_inst(module_id_t module_id) { - NR_UE_MAC_INST_t *mac = &nr_ue_mac_inst[(int)module_id]; - AssertFatal(mac, "Couldn't get MAC inst %d\n", module_id); + AssertFatal(module_id < MAX_NUM_NR_UE_INST, "module_id %d is out of range\n", module_id); + NR_UE_MAC_INST_t *mac = nr_ue_mac_inst[module_id]; + if (mac == NULL) return NULL; AssertFatal(mac->ue_id == module_id, "MAC ID %d doesn't match with input %d\n", mac->ue_id, module_id); return mac; } From f1fbf4aa29d78ecd2902f22ea302ea80ace0ae73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Soares=20Silva?= Date: Fri, 22 Aug 2025 15:22:05 +0100 Subject: [PATCH 558/964] Skip unpacking SRS.indication TLV when report type is 0 Move the check for timing advance offset being 0xffff to before locking the scheduler --- .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 4486be536d..b4ab184deb 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -1498,8 +1498,17 @@ void handle_nr_srs_measurements(const module_id_t module_id, nfapi_nr_srs_indication_pdu_t *srs_ind) { gNB_MAC_INST *nrmac = RC.nrmac[module_id]; - NR_SCHED_LOCK(&nrmac->sched_lock); LOG_D(NR_MAC, "(%d.%d) Received SRS indication for UE %04x\n", frame, slot, srs_ind->rnti); + if (srs_ind->report_type == 0) { + //SCF 222.10.04 Table 3-129 Report type = 0 means a null report, we can skip unpacking it + return; + } + + if (srs_ind->timing_advance_offset == 0xFFFF) { + LOG_W(NR_MAC, "Invalid timing advance offset for RNTI %04x\n", srs_ind->rnti); + return; + } + NR_SCHED_LOCK(&nrmac->sched_lock); #ifdef SRS_IND_DEBUG LOG_I(NR_MAC, "frame = %i\n", frame); @@ -1518,12 +1527,6 @@ void handle_nr_srs_measurements(const module_id_t module_id, return; } - if (srs_ind->timing_advance_offset == 0xFFFF) { - LOG_W(NR_MAC, "Invalid timing advance offset for RNTI %04x\n", srs_ind->rnti); - NR_SCHED_UNLOCK(&nrmac->sched_lock); - return; - } - gNB_MAC_INST *nr_mac = RC.nrmac[module_id]; NR_mac_stats_t *stats = &UE->mac_stats; nfapi_srs_report_tlv_t *report_tlv = &srs_ind->report_tlv; From e5b68fb6ee3ac188b4adc982f13f2e53f66fe555 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Mon, 25 Aug 2025 09:27:31 +0200 Subject: [PATCH 559/964] NR UE: modify shift value in nr_dlsch_mmse() for improved performance --- .../NR_UE_TRANSPORT/nr_dlsch_demodulation.c | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c index 1da2ef8d45..e281e1851d 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c @@ -80,7 +80,7 @@ unsigned char offset_mumimo_llr_drange[29][3]={{8,8,8},{7,7,7},{7,7,7},{7,7,7},{ /* compute the MMSE up to 4x4 matrices */ static void nr_dlsch_mmse(uint32_t rx_size_symbol, unsigned char n_rx, - unsigned char n_tx, // number of layer + unsigned char nl, // number of layer int32_t rxdataF_comp[][n_rx][rx_size_symbol * NR_SYMBOLS_PER_SLOT], c16_t dl_ch_mag[][n_rx][rx_size_symbol], c16_t dl_ch_magb[][n_rx][rx_size_symbol], @@ -203,7 +203,7 @@ void nr_dlsch_scale_channel(uint32_t rx_size_symbol, uint32_t len, unsigned short nb_rb); static void nr_dlsch_detection_mrc(uint32_t rx_size_symbol, - short n_tx, + short nl, short n_rx, int32_t rxdataF_comp[][n_rx][rx_size_symbol * NR_SYMBOLS_PER_SLOT], int ***rho, @@ -1456,7 +1456,7 @@ static void nr_dlsch_mmse(uint32_t rx_size_symbol, int length, uint32_t noise_var) { - uint32_t nb_rb_0 = length / 12 + ((length % 12) ? 1 : 0); + uint32_t nb_rb_0 = (length + 11) / 12; c16_t determ_fin[12 * nb_rb_0] __attribute__((aligned(32))); ///Allocate H^*H matrix elements and sub elements @@ -1513,7 +1513,7 @@ static void nr_dlsch_mmse(uint32_t rx_size_symbol, determ_fin, // determin nb_rb_0, fp_flag, // fixed point flag - shift - (fp_flag == 1 ? 2 : 0)); // the out put is Q15 + shift - (fp_flag == 1 ? 1 : 0)); // the out put is Q15 // multiply Matrix inversion pf H_h_H by the rx signal vector c16_t outtemp[12 * nb_rb_0] __attribute__((aligned(32))); @@ -1531,7 +1531,7 @@ static void nr_dlsch_mmse(uint32_t rx_size_symbol, (c16_t *)(rxdataF_comp[ctx][0] + symbol * rx_size_symbol), outtemp, sizeofArray(outtemp), - shift - (fp_flag == 1 ? 2 : 0)); + shift - (fp_flag == 1 ? 1 : 0)); nr_a_sum_b(rxdataF_zforcing[rtx], outtemp, nb_rb_0); // a = a + b } #ifdef DEBUG_DLSCH_DEMOD @@ -1582,13 +1582,9 @@ static void nr_dlsch_mmse(uint32_t rx_size_symbol, dl_ch_mag128b_0[0] = mmtmpD2; dl_ch_mag128r_0[0] = mmtmpD2; - dl_ch_mag128_0[0] = simde_mm_mulhi_epi16(dl_ch_mag128_0[0],QAM_amp128); - dl_ch_mag128_0[0] = simde_mm_slli_epi16(dl_ch_mag128_0[0],1); - - dl_ch_mag128b_0[0] = simde_mm_mulhi_epi16(dl_ch_mag128b_0[0],QAM_amp128b); - dl_ch_mag128b_0[0] = simde_mm_slli_epi16(dl_ch_mag128b_0[0],1); - dl_ch_mag128r_0[0] = simde_mm_mulhi_epi16(dl_ch_mag128r_0[0],QAM_amp128r); - dl_ch_mag128r_0[0] = simde_mm_slli_epi16(dl_ch_mag128r_0[0],1); + dl_ch_mag128_0[0] = simde_mm_mulhrs_epi16(dl_ch_mag128_0[0], QAM_amp128); + dl_ch_mag128b_0[0] = simde_mm_mulhrs_epi16(dl_ch_mag128b_0[0],QAM_amp128b); + dl_ch_mag128r_0[0] = simde_mm_mulhrs_epi16(dl_ch_mag128r_0[0],QAM_amp128r); determ_fin_128 += 1; dl_ch_mag128_0 += 1; From 0ebb97c4aed63fe9acf74811faf86ae60af0a7a0 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 26 Aug 2025 08:45:57 +0200 Subject: [PATCH 560/964] nfapi.md: fix link to current document --- doc/nfapi.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/nfapi.md b/doc/nfapi.md index 73aaf2e770..214aa2799f 100644 --- a/doc/nfapi.md +++ b/doc/nfapi.md @@ -171,7 +171,7 @@ After installing WLS, you can run the build command as shown below: #### How to run OAI PNF with OAI VNF -Refer to the above steps in [Quickstart](.#quickstart), but run the PNF first as it is the WLS "master". +Refer to the above steps in [Quickstart](#quickstart), but run the PNF first as it is the WLS "master". #### How to run OAI PNF with OSC/Radisys O-DU From 4e9e2b39e9171e6c0de806ea38bcc8337107772a Mon Sep 17 00:00:00 2001 From: Teodora Date: Thu, 26 Jun 2025 15:02:28 +0200 Subject: [PATCH 561/964] Set the correct yang node name for MTU retrieval --- radio/fhi_72/mplane/ru-mplane-api.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radio/fhi_72/mplane/ru-mplane-api.c b/radio/fhi_72/mplane/ru-mplane-api.c index d387a40864..f70514e66f 100644 --- a/radio/fhi_72/mplane/ru-mplane-api.c +++ b/radio/fhi_72/mplane/ru-mplane-api.c @@ -61,7 +61,7 @@ bool get_config_for_xran(const char *buffer, const int max_num_ant, xran_mplane_ xran_mplane->ru_mac_addr = get_ru_xml_node(buffer, "mac-address"); // TODO: support for VVDN, as it defines multiple MAC addresses // MTU - const uint32_t interface_mtu = (uint32_t)atoi(get_ru_xml_node(buffer, "interface-mtu")); + const uint32_t interface_mtu = (uint32_t)atoi(get_ru_xml_node(buffer, "l2-mtu")); // IQ bitwidth char **match_list = NULL; From 10d60f71ce014f371f9a3c938159148212fac297 Mon Sep 17 00:00:00 2001 From: Teodora Date: Tue, 19 Aug 2025 17:09:26 +0200 Subject: [PATCH 562/964] Separate Tx/Rx endpoint creation As per o-ran-uplane-conf model, some nodes exist in Rx but not in Tx (e.g. "ul-fft-sampling-offsets"), and vice versa. --- radio/fhi_72/mplane/yang/create-yang-config.c | 44 ++++++++++++++----- 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/radio/fhi_72/mplane/yang/create-yang-config.c b/radio/fhi_72/mplane/yang/create-yang-config.c index 7276b9fae0..a4e315c3a5 100644 --- a/radio/fhi_72/mplane/yang/create-yang-config.c +++ b/radio/fhi_72/mplane/yang/create-yang-config.c @@ -104,20 +104,20 @@ static bool create_proc_elem_v2(struct ly_ctx **ctx, const ru_session_t *ru_sess return true; } -static bool fill_uplane_ch_v2(const xran_mplane_t *xran_mplane, const size_t idx, struct lyd_node **root) +static LY_ERR fill_uplane_ch_common_v2(const xran_mplane_t *xran_mplane, const size_t idx, struct lyd_node **root) { LY_ERR ret = LY_SUCCESS; ret = lyd_new_term(*root, NULL, "cp-length", "0", 0, NULL); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"cp-length\" node.\n"); - + ret = lyd_new_term(*root, NULL, "cp-length-other", "0", 0, NULL); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"cp-length-other\" node.\n"); - + // to we actually store this from DU config file? ret = lyd_new_term(*root, NULL, "offset-to-absolute-frequency-center", "0", 0, NULL); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"offset-to-absolute-frequency-center\" node.\n"); - + struct lyd_node *compression_node = NULL; ret = lyd_new_inner(*root, NULL, "compression", 0, &compression_node); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"compression\" node.\n"); @@ -126,15 +126,15 @@ static bool fill_uplane_ch_v2(const xran_mplane_t *xran_mplane, const size_t idx snprintf(iq_width_str, sizeof(iq_width_str), "%d", xran_mplane->iq_width); ret = lyd_new_term(compression_node, NULL, "iq-bitwidth", iq_width_str, 0, NULL); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"iq-bitwidth\" node.\n"); - + if (xran_mplane->iq_width < 16) { ret = lyd_new_term(compression_node, NULL, "compression-type", "STATIC", 0, NULL); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"compression-type\" node.\n"); - + // ret = lyd_new_term(compression_node, NULL, "compression-method", "BLOCK_FLOATING_POINT", 0, NULL); // VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"compression-method\" node.\n"); } - + struct lyd_node *eaxc_conf = NULL; ret = lyd_new_inner(*root, NULL, "e-axcid", 0, &eaxc_conf); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"e-axcid\" node.\n"); @@ -143,12 +143,12 @@ static bool fill_uplane_ch_v2(const xran_mplane_t *xran_mplane, const size_t idx snprintf(eaxc_id, sizeof(eaxc_id), "%ld", idx); ret = lyd_new_term(eaxc_conf, NULL, "eaxc-id", eaxc_id, 0, NULL); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"eaxc-id\" node.\n"); - + char du_port_bitmask[16]; snprintf(du_port_bitmask, sizeof(du_port_bitmask), "%d", xran_mplane->du_port_bitmask); ret = lyd_new_term(eaxc_conf, NULL, "o-du-port-bitmask", du_port_bitmask, 0, NULL); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"o-du-port-bitmask\" node.\n"); - + char band_sector_bitmask[8]; snprintf(band_sector_bitmask, sizeof(band_sector_bitmask), "%d", xran_mplane->band_sector_bitmask); ret = lyd_new_term(eaxc_conf, NULL, "band-sector-bitmask", band_sector_bitmask, 0, NULL); @@ -164,6 +164,26 @@ static bool fill_uplane_ch_v2(const xran_mplane_t *xran_mplane, const size_t idx ret = lyd_new_term(eaxc_conf, NULL, "ru-port-bitmask", ru_port_bitmask, 0, NULL); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"ru-port-bitmask\" node.\n"); + return LY_SUCCESS; +} + +static bool fill_uplane_ch_rx_v2(const xran_mplane_t *xran_mplane, const openair0_config_t *oai, const size_t idx, struct lyd_node **root) +{ + LY_ERR ret = LY_SUCCESS; + + ret = fill_uplane_ch_common_v2(xran_mplane, idx, root); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create common nodes.\n"); + + return true; +} + +static bool fill_uplane_ch_tx_v2(const xran_mplane_t *xran_mplane, const openair0_config_t *oai, const size_t idx, struct lyd_node **root) +{ + LY_ERR ret = LY_SUCCESS; + + ret = fill_uplane_ch_common_v2(xran_mplane, idx, root); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create common nodes.\n"); + return true; } @@ -254,7 +274,7 @@ static bool create_uplane_conf_v2(struct ly_ctx **ctx, const ru_session_t *ru_se ret = lyd_new_list(*root, NULL, "low-level-rx-endpoints", 0, &pusch_node, ru_session->ru_mplane_config.rx_endpoints.name[i]); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"low-level-rx-endpoints\" node.\n"); - success = fill_uplane_ch_v2(&ru_session->xran_mplane, i, &pusch_node); + success = fill_uplane_ch_rx_v2(&ru_session->xran_mplane, i, &pusch_node); VERIFY_SUCCESS(success, "[MPLANE] Failed to fill \"low-level-rx-endpoints\" node for %s.\n", ru_session->ru_mplane_config.rx_endpoints.name[i]); const size_t prach_endpoint_name_offset = i + (ru_session->ru_mplane_config.rx_endpoints.num / 2); @@ -262,7 +282,7 @@ static bool create_uplane_conf_v2(struct ly_ctx **ctx, const ru_session_t *ru_se ret = lyd_new_list(*root, NULL, "low-level-rx-endpoints", 0, &prach_node, ru_session->ru_mplane_config.rx_endpoints.name[prach_endpoint_name_offset]); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"low-level-rx-endpoints\" node.\n"); - success = fill_uplane_ch_v2(&ru_session->xran_mplane, i + ru_session->xran_mplane.prach_offset, &prach_node); + success = fill_uplane_ch_rx_v2(&ru_session->xran_mplane, i + ru_session->xran_mplane.prach_offset, &prach_node); VERIFY_SUCCESS(success, "[MPLANE] Failed to fill \"low-level-rx-endpoints\" node for %s.\n", ru_session->ru_mplane_config.rx_endpoints.name[prach_endpoint_name_offset]); } @@ -273,7 +293,7 @@ static bool create_uplane_conf_v2(struct ly_ctx **ctx, const ru_session_t *ru_se ret = lyd_new_list(*root, NULL, "low-level-tx-endpoints", 0, &pdsch_node, ru_session->ru_mplane_config.tx_endpoints.name[i]); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"low-level-tx-endpoints\" node.\n"); - success = fill_uplane_ch_v2(&ru_session->xran_mplane, i, &pdsch_node); + success = fill_uplane_ch_tx_v2(&ru_session->xran_mplane, i, &pdsch_node); VERIFY_SUCCESS(success, "[MPLANE] Failed to fill \"low-level-tx-endpoints\" node for %s.\n", ru_session->ru_mplane_config.tx_endpoints.name[i]); } From 0b0e804f73fdf20922cc4825e405320de4461a3c Mon Sep 17 00:00:00 2001 From: Teodora Date: Fri, 27 Jun 2025 10:36:21 +0200 Subject: [PATCH 563/964] Properly pass the frequency offset to Tx/Rx endpoints --- executables/nr-ru.c | 7 ++++++ radio/COMMON/common_lib.h | 4 ++++ radio/fhi_72/mplane/yang/create-yang-config.c | 23 ++++++++++++------- 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/executables/nr-ru.c b/executables/nr-ru.c index de3a4b7875..f11366f0ba 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -883,6 +883,7 @@ static void fill_split7_2_config(split7_config_t *split7, const nfapi_nr_config_ const nfapi_nr_prach_config_t *prach_config = &config->prach_config; const nfapi_nr_tdd_table_t *tdd_table = &config->tdd_table; const nfapi_nr_cell_config_t *cell_config = &config->cell_config; + const nfapi_nr_carrier_config_t *carrier_config = &config->carrier_config; DevAssert(prach_config->prach_ConfigurationIndex.tl.tag == NFAPI_NR_CONFIG_PRACH_CONFIG_INDEX_TAG); split7->prach_index = prach_config->prach_ConfigurationIndex.value; @@ -902,6 +903,12 @@ static void fill_split7_2_config(split7_config_t *split7, const nfapi_nr_config_ } split7->fftSize = log2(ofdm_symbol_size); + + // M-plane related parameters + for (size_t i = 0; i < 5 ; i++) { + split7->dl_k0[i] = carrier_config->dl_k0[i].value; + split7->ul_k0[i] = carrier_config->ul_k0[i].value; + } } /* this function maps the RU tx and rx buffers to the available rf chains. diff --git a/radio/COMMON/common_lib.h b/radio/COMMON/common_lib.h index f928d554a8..d8465e3758 100644 --- a/radio/COMMON/common_lib.h +++ b/radio/COMMON/common_lib.h @@ -198,6 +198,10 @@ typedef struct split7_config { } slot_dirs[160]; /*! this is the exponent in 2^X for the FFT size */ uint16_t fftSize; + + // M-plane related parameters + uint16_t dl_k0[5]; + uint16_t ul_k0[5]; } split7_config_t; /*! \brief RF frontend parameters set by application */ diff --git a/radio/fhi_72/mplane/yang/create-yang-config.c b/radio/fhi_72/mplane/yang/create-yang-config.c index a4e315c3a5..0ab680ee19 100644 --- a/radio/fhi_72/mplane/yang/create-yang-config.c +++ b/radio/fhi_72/mplane/yang/create-yang-config.c @@ -104,7 +104,9 @@ static bool create_proc_elem_v2(struct ly_ctx **ctx, const ru_session_t *ru_sess return true; } -static LY_ERR fill_uplane_ch_common_v2(const xran_mplane_t *xran_mplane, const size_t idx, struct lyd_node **root) +typedef enum { UP_CH_RX, UP_CH_TX } uplane_dir_t; + +static LY_ERR fill_uplane_ch_common_v2(const uplane_dir_t dir, const xran_mplane_t *xran_mplane, const openair0_config_t *oai, const size_t idx, struct lyd_node **root) { LY_ERR ret = LY_SUCCESS; @@ -114,8 +116,13 @@ static LY_ERR fill_uplane_ch_common_v2(const xran_mplane_t *xran_mplane, const s ret = lyd_new_term(*root, NULL, "cp-length-other", "0", 0, NULL); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"cp-length-other\" node.\n"); - // to we actually store this from DU config file? - ret = lyd_new_term(*root, NULL, "offset-to-absolute-frequency-center", "0", 0, NULL); + char freq_offset[8]; + if (dir == UP_CH_RX) { + snprintf(freq_offset, sizeof(freq_offset), "%d", oai->split7.ul_k0[oai->nr_scs_for_raster]); + } else { + snprintf(freq_offset, sizeof(freq_offset), "%d", oai->split7.dl_k0[oai->nr_scs_for_raster]); + } + ret = lyd_new_term(*root, NULL, "offset-to-absolute-frequency-center", freq_offset, 0, NULL); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"offset-to-absolute-frequency-center\" node.\n"); struct lyd_node *compression_node = NULL; @@ -171,7 +178,7 @@ static bool fill_uplane_ch_rx_v2(const xran_mplane_t *xran_mplane, const openair { LY_ERR ret = LY_SUCCESS; - ret = fill_uplane_ch_common_v2(xran_mplane, idx, root); + ret = fill_uplane_ch_common_v2(UP_CH_RX, xran_mplane, oai, idx, root); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create common nodes.\n"); return true; @@ -181,7 +188,7 @@ static bool fill_uplane_ch_tx_v2(const xran_mplane_t *xran_mplane, const openair { LY_ERR ret = LY_SUCCESS; - ret = fill_uplane_ch_common_v2(xran_mplane, idx, root); + ret = fill_uplane_ch_common_v2(UP_CH_TX, xran_mplane, oai, idx, root); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create common nodes.\n"); return true; @@ -274,7 +281,7 @@ static bool create_uplane_conf_v2(struct ly_ctx **ctx, const ru_session_t *ru_se ret = lyd_new_list(*root, NULL, "low-level-rx-endpoints", 0, &pusch_node, ru_session->ru_mplane_config.rx_endpoints.name[i]); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"low-level-rx-endpoints\" node.\n"); - success = fill_uplane_ch_rx_v2(&ru_session->xran_mplane, i, &pusch_node); + success = fill_uplane_ch_rx_v2(&ru_session->xran_mplane, oai, i, &pusch_node); VERIFY_SUCCESS(success, "[MPLANE] Failed to fill \"low-level-rx-endpoints\" node for %s.\n", ru_session->ru_mplane_config.rx_endpoints.name[i]); const size_t prach_endpoint_name_offset = i + (ru_session->ru_mplane_config.rx_endpoints.num / 2); @@ -282,7 +289,7 @@ static bool create_uplane_conf_v2(struct ly_ctx **ctx, const ru_session_t *ru_se ret = lyd_new_list(*root, NULL, "low-level-rx-endpoints", 0, &prach_node, ru_session->ru_mplane_config.rx_endpoints.name[prach_endpoint_name_offset]); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"low-level-rx-endpoints\" node.\n"); - success = fill_uplane_ch_rx_v2(&ru_session->xran_mplane, i + ru_session->xran_mplane.prach_offset, &prach_node); + success = fill_uplane_ch_rx_v2(&ru_session->xran_mplane, oai, i + ru_session->xran_mplane.prach_offset, &prach_node); VERIFY_SUCCESS(success, "[MPLANE] Failed to fill \"low-level-rx-endpoints\" node for %s.\n", ru_session->ru_mplane_config.rx_endpoints.name[prach_endpoint_name_offset]); } @@ -293,7 +300,7 @@ static bool create_uplane_conf_v2(struct ly_ctx **ctx, const ru_session_t *ru_se ret = lyd_new_list(*root, NULL, "low-level-tx-endpoints", 0, &pdsch_node, ru_session->ru_mplane_config.tx_endpoints.name[i]); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"low-level-tx-endpoints\" node.\n"); - success = fill_uplane_ch_tx_v2(&ru_session->xran_mplane, i, &pdsch_node); + success = fill_uplane_ch_tx_v2(&ru_session->xran_mplane, oai, i, &pdsch_node); VERIFY_SUCCESS(success, "[MPLANE] Failed to fill \"low-level-tx-endpoints\" node for %s.\n", ru_session->ru_mplane_config.tx_endpoints.name[i]); } From 8bd6e16ad108379e73bfb9b3e8c64be721e94b9c Mon Sep 17 00:00:00 2001 From: Teodora Date: Fri, 27 Jun 2025 12:41:00 +0200 Subject: [PATCH 564/964] Correctly fill the frame structure for Tx/Rx endpoints and fft size for Rx endpoints --- radio/fhi_72/mplane/ru-mplane-api.c | 7 +++++++ radio/fhi_72/mplane/ru-mplane-api.h | 1 + radio/fhi_72/mplane/yang/create-yang-config.c | 17 +++++++++++++++++ 3 files changed, 25 insertions(+) diff --git a/radio/fhi_72/mplane/ru-mplane-api.c b/radio/fhi_72/mplane/ru-mplane-api.c index f70514e66f..508ed2a393 100644 --- a/radio/fhi_72/mplane/ru-mplane-api.c +++ b/radio/fhi_72/mplane/ru-mplane-api.c @@ -91,6 +91,13 @@ bool get_config_for_xran(const char *buffer, const int max_num_ant, xran_mplane_ // RU port ID xran_mplane->ru_port = 0; + // Frame structure + match_list = NULL; + count = 0; + get_ru_xml_list(buffer, "supported-frame-structures", &match_list, &count); + xran_mplane->frame_str = (int16_t)atoi((char *)match_list[0]); + free_match_list(match_list, count); + if (strcasecmp(ru_vendor, "BENETEL") == 0 /* || strcmp(ru_vendor, "VVDN-LPRU") == 0 || strcmp(ru_vendor, "Metanoia") == 0 */) { fix_benetel_setting(xran_mplane, interface_mtu, first_iq_width, max_num_ant); } else { diff --git a/radio/fhi_72/mplane/ru-mplane-api.h b/radio/fhi_72/mplane/ru-mplane-api.h index 70857adea6..a51e500c96 100644 --- a/radio/fhi_72/mplane/ru-mplane-api.h +++ b/radio/fhi_72/mplane/ru-mplane-api.h @@ -57,6 +57,7 @@ typedef struct { uint8_t band_sector; uint8_t ccid; uint8_t ru_port; + int16_t frame_str; // might be needed in the future xran releases } xran_mplane_t; diff --git a/radio/fhi_72/mplane/yang/create-yang-config.c b/radio/fhi_72/mplane/yang/create-yang-config.c index 0ab680ee19..e6cf25c626 100644 --- a/radio/fhi_72/mplane/yang/create-yang-config.c +++ b/radio/fhi_72/mplane/yang/create-yang-config.c @@ -23,6 +23,7 @@ #include "common/utils/nr/nr_common.h" #define VERIFY_SUCCESS(var, message, args...) AssertError(var, return false, message, ##args) +const char *scs_name[] = {"KHZ_15", "KHZ_30", "KHZ_60", "KHZ_120", "KHZ_240", NULL}; #ifdef MPLANE_V2 static bool create_cu_interface_v2(struct ly_ctx **ctx, const ru_session_t *ru_session, const size_t idx, const char *int_name, struct lyd_node **root) @@ -110,6 +111,11 @@ static LY_ERR fill_uplane_ch_common_v2(const uplane_dir_t dir, const xran_mplane { LY_ERR ret = LY_SUCCESS; + char frame_str[8]; + snprintf(frame_str, sizeof(frame_str), "%d", (oai->split7.fftSize << 4) + oai->nr_scs_for_raster); // 3GPP TS 38.211 + ret = lyd_new_term(*root, NULL, "frame-structure", frame_str, 0, NULL); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"frame-structure\" node.\n"); + ret = lyd_new_term(*root, NULL, "cp-length", "0", 0, NULL); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"cp-length\" node.\n"); @@ -181,6 +187,17 @@ static bool fill_uplane_ch_rx_v2(const xran_mplane_t *xran_mplane, const openair ret = fill_uplane_ch_common_v2(UP_CH_RX, xran_mplane, oai, idx, root); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create common nodes.\n"); + struct lyd_node *fft_offset = NULL; + ret = lyd_new_list(*root, NULL, "ul-fft-sampling-offsets", 0, &fft_offset, scs_name[oai->nr_scs_for_raster]); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"ul-fft-sampling-offsets\" node.\n"); + + // Note: set of allowed values is restricted by SCS derived from values in supported-frame-structures. + char ul_fft_offset[8]; + const int frame = (oai->split7.fftSize << 4) + oai->nr_scs_for_raster; + snprintf(ul_fft_offset, sizeof(ul_fft_offset), "%d", frame - xran_mplane->frame_str); + ret = lyd_new_term(fft_offset, NULL, "ul-fft-sampling-offset", ul_fft_offset, 0, NULL); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"ul-fft-sampling-offset\" node.\n"); + return true; } From 9bb15f15b8aaa16f6b57b375e4a576fe771a549e Mon Sep 17 00:00:00 2001 From: Teodora Date: Fri, 27 Jun 2025 14:19:45 +0200 Subject: [PATCH 565/964] Correctly fill the cyclic prefix for Tx/Rx endpoints --- executables/nr-ru.c | 10 ++++++---- radio/COMMON/common_lib.h | 3 +++ radio/fhi_72/mplane/yang/create-yang-config.c | 14 ++++++++++++-- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/executables/nr-ru.c b/executables/nr-ru.c index f11366f0ba..20deff5725 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -878,7 +878,7 @@ static void fill_rf_config(RU_t *ru, char *rf_config_file) } } -static void fill_split7_2_config(split7_config_t *split7, const nfapi_nr_config_request_scf_t *config, int slots_per_frame, uint16_t ofdm_symbol_size) +static void fill_split7_2_config(split7_config_t *split7, const nfapi_nr_config_request_scf_t *config, const NR_DL_FRAME_PARMS *fp) { const nfapi_nr_prach_config_t *prach_config = &config->prach_config; const nfapi_nr_tdd_table_t *tdd_table = &config->tdd_table; @@ -894,7 +894,7 @@ static void fill_split7_2_config(split7_config_t *split7, const nfapi_nr_config_ if (cell_config->frame_duplex_type.value == 1 /* TDD */) { DevAssert(tdd_table->tdd_period.tl.tag == NFAPI_NR_CONFIG_TDD_PERIOD_TAG); int nb_periods_per_frame = get_nb_periods_per_frame(tdd_table->tdd_period.value); - split7->n_tdd_period = slots_per_frame / nb_periods_per_frame; + split7->n_tdd_period = fp->slots_per_frame / nb_periods_per_frame; for (int slot = 0; slot < split7->n_tdd_period; ++slot) { for (int sym = 0; sym < 14; ++sym) { split7->slot_dirs[slot].sym_dir[sym] = tdd_table->max_tdd_periodicity_list[slot].max_num_of_symbol_per_slot_list[sym].slot_config.value; @@ -902,13 +902,15 @@ static void fill_split7_2_config(split7_config_t *split7, const nfapi_nr_config_ } } - split7->fftSize = log2(ofdm_symbol_size); + split7->fftSize = log2(fp->ofdm_symbol_size); // M-plane related parameters for (size_t i = 0; i < 5 ; i++) { split7->dl_k0[i] = carrier_config->dl_k0[i].value; split7->ul_k0[i] = carrier_config->ul_k0[i].value; } + split7->cp_prefix0 = fp->nb_prefix_samples0; + split7->cp_prefix_other = fp->nb_prefix_samples; } /* this function maps the RU tx and rx buffers to the available rf chains. @@ -1051,7 +1053,7 @@ void *ru_thread(void *param) nr_dump_frame_parms(fp); nr_phy_init_RU(ru); fill_rf_config(ru, ru->rf_config_file); - fill_split7_2_config(&ru->openair0_cfg.split7, &ru->config, fp->slots_per_frame, fp->ofdm_symbol_size); + fill_split7_2_config(&ru->openair0_cfg.split7, &ru->config, fp); // Start IF device if any if (ru->nr_start_if) { diff --git a/radio/COMMON/common_lib.h b/radio/COMMON/common_lib.h index d8465e3758..b87a6a8abf 100644 --- a/radio/COMMON/common_lib.h +++ b/radio/COMMON/common_lib.h @@ -202,6 +202,9 @@ typedef struct split7_config { // M-plane related parameters uint16_t dl_k0[5]; uint16_t ul_k0[5]; + uint16_t cp_prefix0; + uint16_t cp_prefix_other; + } split7_config_t; /*! \brief RF frontend parameters set by application */ diff --git a/radio/fhi_72/mplane/yang/create-yang-config.c b/radio/fhi_72/mplane/yang/create-yang-config.c index e6cf25c626..58be178801 100644 --- a/radio/fhi_72/mplane/yang/create-yang-config.c +++ b/radio/fhi_72/mplane/yang/create-yang-config.c @@ -116,10 +116,20 @@ static LY_ERR fill_uplane_ch_common_v2(const uplane_dir_t dir, const xran_mplane ret = lyd_new_term(*root, NULL, "frame-structure", frame_str, 0, NULL); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"frame-structure\" node.\n"); - ret = lyd_new_term(*root, NULL, "cp-length", "0", 0, NULL); + // EXTENDED not supported + // 3GPP TS 38.211 + const char cp_type[] = "NORMAL"; + ret = lyd_new_term(*root, NULL, "cp-type", cp_type, 0, NULL); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"cp-type\" node.\n"); + + char cp_len[8]; + snprintf(cp_len, sizeof(cp_len), "%d", oai->split7.cp_prefix0); + ret = lyd_new_term(*root, NULL, "cp-length", cp_len, 0, NULL); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"cp-length\" node.\n"); - ret = lyd_new_term(*root, NULL, "cp-length-other", "0", 0, NULL); + char cp_len_other[8]; + snprintf(cp_len_other, sizeof(cp_len_other), "%d", oai->split7.cp_prefix_other); + ret = lyd_new_term(*root, NULL, "cp-length-other", cp_len_other, 0, NULL); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"cp-length-other\" node.\n"); char freq_offset[8]; From 2e9101f8339233e1b0575fbec03f950d028d6d29 Mon Sep 17 00:00:00 2001 From: Teodora Date: Fri, 27 Jun 2025 14:45:28 +0200 Subject: [PATCH 566/964] Add managed delay node in Rx endpoint creation --- radio/fhi_72/mplane/ru-mplane-api.c | 4 ++++ radio/fhi_72/mplane/ru-mplane-api.h | 1 + radio/fhi_72/mplane/yang/create-yang-config.c | 4 ++++ 3 files changed, 9 insertions(+) diff --git a/radio/fhi_72/mplane/ru-mplane-api.c b/radio/fhi_72/mplane/ru-mplane-api.c index 508ed2a393..972a286d9b 100644 --- a/radio/fhi_72/mplane/ru-mplane-api.c +++ b/radio/fhi_72/mplane/ru-mplane-api.c @@ -98,6 +98,10 @@ bool get_config_for_xran(const char *buffer, const int max_num_ant, xran_mplane_ xran_mplane->frame_str = (int16_t)atoi((char *)match_list[0]); free_match_list(match_list, count); + // Managed delay support + const char *managed_delay = get_ru_xml_node(buffer, "managed-delay-support"); + xran_mplane->managed_delay = (strcasecmp(managed_delay, "NON_MANAGED") == 0) ? false : true; + if (strcasecmp(ru_vendor, "BENETEL") == 0 /* || strcmp(ru_vendor, "VVDN-LPRU") == 0 || strcmp(ru_vendor, "Metanoia") == 0 */) { fix_benetel_setting(xran_mplane, interface_mtu, first_iq_width, max_num_ant); } else { diff --git a/radio/fhi_72/mplane/ru-mplane-api.h b/radio/fhi_72/mplane/ru-mplane-api.h index a51e500c96..4888c51608 100644 --- a/radio/fhi_72/mplane/ru-mplane-api.h +++ b/radio/fhi_72/mplane/ru-mplane-api.h @@ -58,6 +58,7 @@ typedef struct { uint8_t ccid; uint8_t ru_port; int16_t frame_str; // might be needed in the future xran releases + bool managed_delay; } xran_mplane_t; diff --git a/radio/fhi_72/mplane/yang/create-yang-config.c b/radio/fhi_72/mplane/yang/create-yang-config.c index 58be178801..6742dc452d 100644 --- a/radio/fhi_72/mplane/yang/create-yang-config.c +++ b/radio/fhi_72/mplane/yang/create-yang-config.c @@ -197,6 +197,10 @@ static bool fill_uplane_ch_rx_v2(const xran_mplane_t *xran_mplane, const openair ret = fill_uplane_ch_common_v2(UP_CH_RX, xran_mplane, oai, idx, root); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create common nodes.\n"); + const char *managed_delay = xran_mplane->managed_delay ? "true" : "false"; + ret = lyd_new_term(*root, NULL, "non-time-managed-delay-enabled", managed_delay, 0, NULL); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"non-time-managed-delay-enabled\" node.\n"); + struct lyd_node *fft_offset = NULL; ret = lyd_new_list(*root, NULL, "ul-fft-sampling-offsets", 0, &fft_offset, scs_name[oai->nr_scs_for_raster]); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"ul-fft-sampling-offsets\" node.\n"); From eee7d976ecb44be1f5bacffda454e2448e530d5a Mon Sep 17 00:00:00 2001 From: Teodora Date: Fri, 27 Jun 2025 16:43:54 +0200 Subject: [PATCH 567/964] Correct the Tx gain --- doc/ORAN_FHI7.2_Tutorial.md | 2 +- radio/fhi_72/mplane/ru-mplane-api.c | 24 +++++++++++++++---- radio/fhi_72/mplane/ru-mplane-api.h | 2 ++ radio/fhi_72/mplane/yang/create-yang-config.c | 8 +++++-- ...73prb.fhi72.8x8-benetel650_650-mplane.conf | 2 +- ...78.273prb.fhi72.4x4-benetel550-mplane.conf | 2 +- 6 files changed, 31 insertions(+), 9 deletions(-) diff --git a/doc/ORAN_FHI7.2_Tutorial.md b/doc/ORAN_FHI7.2_Tutorial.md index 7aff02f9df..ed340cc5c1 100644 --- a/doc/ORAN_FHI7.2_Tutorial.md +++ b/doc/ORAN_FHI7.2_Tutorial.md @@ -1393,7 +1393,7 @@ The reference gNB configuration file for one Benetel RAN550: The reference DU configuration file for two Benetel RAN650: [gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650-mplane.conf](../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650-mplane.conf) -In order to run gNB/DU with M-plane, we need to modify the `fhi_72` section in the configuration file. +In order to run gNB/DU with M-plane, we need to modify Tx gain `att_tx` in RU section, as well as the `fhi_72` section in the configuration file. Example for one RU: ```bash fhi_72 = { diff --git a/radio/fhi_72/mplane/ru-mplane-api.c b/radio/fhi_72/mplane/ru-mplane-api.c index 972a286d9b..e6be2e11b5 100644 --- a/radio/fhi_72/mplane/ru-mplane-api.c +++ b/radio/fhi_72/mplane/ru-mplane-api.c @@ -33,7 +33,7 @@ static void free_match_list(char **match_list, size_t count) free(match_list); } -static void fix_benetel_setting(xran_mplane_t *xran_mplane, const uint32_t interface_mtu, const int16_t first_iq_width, const int max_num_ant) +static void fix_benetel_setting(xran_mplane_t *xran_mplane, const uint32_t interface_mtu, const int16_t first_iq_width, const int max_num_ant, const char *model_name) { if (interface_mtu == 1500) { MP_LOG_I("Interface MTU %d unreliable/not correctly reported by Benetel O-RU, hardcoding to 9600.\n", interface_mtu); @@ -50,6 +50,14 @@ static void fix_benetel_setting(xran_mplane_t *xran_mplane, const uint32_t inter } xran_mplane->prach_offset = max_num_ant; + + if (strcasecmp(model_name, "RAN550") == 0) { + xran_mplane->max_tx_gain = 24.0; + } else if (strcasecmp(model_name, "RAN650") == 0) { + xran_mplane->max_tx_gain = 35.0; + } else { + assert(false && "[MPLANE] Unknown Benetel model name.\n"); + } } bool get_config_for_xran(const char *buffer, const int max_num_ant, xran_mplane_t *xran_mplane) @@ -102,8 +110,14 @@ bool get_config_for_xran(const char *buffer, const int max_num_ant, xran_mplane_ const char *managed_delay = get_ru_xml_node(buffer, "managed-delay-support"); xran_mplane->managed_delay = (strcasecmp(managed_delay, "NON_MANAGED") == 0) ? false : true; + // Store the max gain + xran_mplane->max_tx_gain = (double)atof(get_ru_xml_node(buffer, "max-gain")); + + // Model name + const char *model_name = get_ru_xml_node(buffer, "model-name"); + if (strcasecmp(ru_vendor, "BENETEL") == 0 /* || strcmp(ru_vendor, "VVDN-LPRU") == 0 || strcmp(ru_vendor, "Metanoia") == 0 */) { - fix_benetel_setting(xran_mplane, interface_mtu, first_iq_width, max_num_ant); + fix_benetel_setting(xran_mplane, interface_mtu, first_iq_width, max_num_ant, model_name); } else { AssertError(false, return false, "[MPLANE] %s RU currently not supported.\n", ru_vendor); } @@ -120,7 +134,8 @@ bool get_config_for_xran(const char *buffer, const int max_num_ant, xran_mplane_ DU port ID %d\n\ Band sector ID %d\n\ CC ID %d\n\ - RU port ID %d\n", + RU port ID %d\n\ + max Tx gain %.1f\n", xran_mplane->ru_mac_addr, xran_mplane->mtu, xran_mplane->iq_width, @@ -132,7 +147,8 @@ bool get_config_for_xran(const char *buffer, const int max_num_ant, xran_mplane_ xran_mplane->du_port, xran_mplane->band_sector, xran_mplane->ccid, - xran_mplane->ru_port); + xran_mplane->ru_port, + xran_mplane->max_tx_gain); return true; } diff --git a/radio/fhi_72/mplane/ru-mplane-api.h b/radio/fhi_72/mplane/ru-mplane-api.h index 4888c51608..df6a89042f 100644 --- a/radio/fhi_72/mplane/ru-mplane-api.h +++ b/radio/fhi_72/mplane/ru-mplane-api.h @@ -60,6 +60,8 @@ typedef struct { int16_t frame_str; // might be needed in the future xran releases bool managed_delay; + double max_tx_gain; + } xran_mplane_t; typedef struct { diff --git a/radio/fhi_72/mplane/yang/create-yang-config.c b/radio/fhi_72/mplane/yang/create-yang-config.c index 6742dc452d..2092ed19fa 100644 --- a/radio/fhi_72/mplane/yang/create-yang-config.c +++ b/radio/fhi_72/mplane/yang/create-yang-config.c @@ -292,8 +292,12 @@ static bool create_uplane_conf_v2(struct ly_ctx **ctx, const ru_session_t *ru_se ret = lyd_new_term(tx_carrier_node, NULL, "channel-bandwidth", tx_bw, 0, NULL); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"channel-bandwidth\" node.\n"); - // oai->tx_gain to be tested - ret = lyd_new_term(tx_carrier_node, NULL, "gain", "0", 0, NULL); + // oai->tx_gain takes the value of att_tx from the RU section of gNB config file + // we assume the same gain is applied to all channels; same as above for the frequency + const double tx_gain_value = ((oai->tx_gain[0] * 10000) < ru_session->xran_mplane.max_tx_gain) ? (oai->tx_gain[0] * 10000) : ru_session->xran_mplane.max_tx_gain; + char tx_gain_str[8]; + snprintf(tx_gain_str, sizeof(tx_gain_str), "%.f", tx_gain_value); + ret = lyd_new_term(tx_carrier_node, NULL, "gain", tx_gain_str, 0, NULL); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"gain\" node.\n"); ret = lyd_new_term(tx_carrier_node, NULL, "downlink-radio-frame-offset", "0", 0, NULL); diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650-mplane.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650-mplane.conf index 72d174cfb3..97459ad55e 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650-mplane.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650-mplane.conf @@ -205,7 +205,7 @@ RUs = ( local_rf = "no"; nb_tx = 8; nb_rx = 8; - att_tx = 0; + att_tx = 35; att_rx = 0; bands = [77]; max_pdschReferenceSignalPower = -27; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-benetel550-mplane.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-benetel550-mplane.conf index be35562fd7..9472ee3cdd 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-benetel550-mplane.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-benetel550-mplane.conf @@ -208,7 +208,7 @@ RUs = ( local_rf = "no"; nb_tx = 4; nb_rx = 4; - att_tx = 0; + att_tx = 24; att_rx = 0; bands = [78]; max_pdschReferenceSignalPower = -27; From 5291afe165e4d9ff8657107fbd8987230c53ccdd Mon Sep 17 00:00:00 2001 From: Teodora Date: Mon, 30 Jun 2025 08:24:06 +0200 Subject: [PATCH 568/964] Add a comment for Rx gain correction Definition in o-ran-uplane-conf.yang model: "Gain correction of RF path linked with array element or array layers. Common part of overall gain_correction. gain_correction = common array-carrier gain-correction + eAxC gain correction." --- radio/fhi_72/mplane/yang/create-yang-config.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/radio/fhi_72/mplane/yang/create-yang-config.c b/radio/fhi_72/mplane/yang/create-yang-config.c index 2092ed19fa..dac1ee810e 100644 --- a/radio/fhi_72/mplane/yang/create-yang-config.c +++ b/radio/fhi_72/mplane/yang/create-yang-config.c @@ -262,7 +262,8 @@ static bool create_uplane_conf_v2(struct ly_ctx **ctx, const ru_session_t *ru_se ret = lyd_new_term(rx_carrier_node, NULL, "downlink-sfn-offset", "0", 0, NULL); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"downlink-sfn-offset\" node.\n"); - // oai->rx_gain_offset is this the correction? if yes, test it later + // gain offset applied uniformly across all array elements or layers + // needs to be within ret = lyd_new_term(rx_carrier_node, NULL, "gain-correction", "0", 0, NULL); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"gain-correction\" node.\n"); From e7db367c9d61f20147738d190fa8478bf21743af Mon Sep 17 00:00:00 2001 From: Teodora Date: Mon, 7 Jul 2025 15:03:59 +0200 Subject: [PATCH 569/964] Rearrange , , and RPCs Refactor these RPCs to facilitate their use in other Management functionalities, not only Configuration Management. --- radio/fhi_72/mplane/config-mplane.c | 44 +++++++++---------- radio/fhi_72/mplane/config-mplane.h | 6 +-- radio/fhi_72/mplane/connect-mplane.c | 5 +++ radio/fhi_72/mplane/init-mplane.c | 18 +++++--- radio/fhi_72/mplane/ru-mplane-api.h | 1 + radio/fhi_72/mplane/yang/create-yang-config.c | 28 ++++++------ radio/fhi_72/mplane/yang/create-yang-config.h | 2 +- radio/fhi_72/mplane/yang/get-yang.c | 4 +- radio/fhi_72/mplane/yang/get-yang.h | 2 +- 9 files changed, 58 insertions(+), 52 deletions(-) diff --git a/radio/fhi_72/mplane/config-mplane.c b/radio/fhi_72/mplane/config-mplane.c index 69ff1fd2b3..da28665023 100644 --- a/radio/fhi_72/mplane/config-mplane.c +++ b/radio/fhi_72/mplane/config-mplane.c @@ -21,14 +21,12 @@ #include "config-mplane.h" #include "rpc-send-recv.h" -#include "yang/get-yang.h" -#include "yang/create-yang-config.h" #include "common/utils/assertions.h" #include #include -bool edit_config_mplane(ru_session_t *ru_session, const char *buffer, const openair0_config_t *oai, const size_t num_rus) +static bool edit_config_mplane(ru_session_t *ru_session, const char *content) { int timeout = CLI_RPC_REPLY_TIMEOUT; struct nc_rpc *rpc; @@ -39,37 +37,21 @@ bool edit_config_mplane(ru_session_t *ru_session, const char *buffer, const open NC_RPC_EDIT_TESTOPT test = NC_RPC_EDIT_TESTOPT_UNKNOWN; NC_RPC_EDIT_ERROPT err = NC_RPC_EDIT_ERROPT_UNKNOWN; - bool success = false; - - struct ly_ctx *ctx = NULL; - success = load_yang_models(ru_session, buffer, &ctx); - AssertError(success, return false, "[MPLANE] Unable to continue.\n"); - - char *content = NULL; - success = configure_ru_from_yang(&ctx, ru_session, oai, num_rus, &content); - AssertError(success, return false, "[MPLANE] Unable to create content for RPC.\n"); - MP_LOG_I("RPC request to RU \"%s\" = :\n%s\n", ru_session->ru_ip_add, content); rpc = nc_rpc_edit(target, op, test, err, content, param); AssertError(rpc != NULL, return false, "[MPLANE] RPC creation failed.\n"); - success = rpc_send_recv((struct nc_session *)ru_session->session, rpc, wd, timeout, NULL); + bool success = rpc_send_recv((struct nc_session *)ru_session->session, rpc, wd, timeout, NULL); AssertError(success, return false, "[MPLANE] Failed to edit configuration for the candidate datastore.\n"); MP_LOG_I("Successfully edited the candidate datastore for RU \"%s\".\n", ru_session->ru_ip_add); nc_rpc_free(rpc); - free(content); -#ifdef MPLANE_V1 - ly_ctx_destroy(ctx, NULL); -#elif defined MPLANE_V2 - ly_ctx_destroy(ctx); -#endif return true; } -bool validate_config_mplane(ru_session_t *ru_session) +static bool validate_config_mplane(ru_session_t *ru_session) { int timeout = CLI_RPC_REPLY_TIMEOUT; struct nc_rpc *rpc; @@ -92,7 +74,7 @@ bool validate_config_mplane(ru_session_t *ru_session) return true; } -bool commit_config_mplane(ru_session_t *ru_session) +static bool commit_config_mplane(ru_session_t *ru_session) { int timeout = CLI_RPC_REPLY_TIMEOUT; struct nc_rpc *rpc; @@ -109,9 +91,25 @@ bool commit_config_mplane(ru_session_t *ru_session) bool success = rpc_send_recv((struct nc_session *)ru_session->session, rpc, wd, timeout, NULL); AssertError(success, return false, "[MPLANE] Failed to commit candidate datastore.\n"); - MP_LOG_I("Successfully commited CU-planes configuration into running datastore for RU \"%s\".\n", ru_session->ru_ip_add); + MP_LOG_I("Successfully commited configuration into running datastore for RU \"%s\".\n", ru_session->ru_ip_add); nc_rpc_free(rpc); return true; } + +bool edit_val_commmit_rpc(ru_session_t *ru_session, const char *content) +{ + bool success = false; + + success = edit_config_mplane(ru_session, content); + AssertError(success, return false, "[MPLANE] Unable to edit the RU configuration.\n"); + + success = validate_config_mplane(ru_session); + AssertError(success, return false, "[MPLANE] Unable to validate the RU configuration.\n"); + + success = commit_config_mplane(ru_session); + AssertError(success, return false, "[MPLANE] Unable to commit the RU configuration.\n"); + + return success; +} diff --git a/radio/fhi_72/mplane/config-mplane.h b/radio/fhi_72/mplane/config-mplane.h index c8451ca8a0..dae2dbea63 100644 --- a/radio/fhi_72/mplane/config-mplane.h +++ b/radio/fhi_72/mplane/config-mplane.h @@ -25,10 +25,6 @@ #include "ru-mplane-api.h" #include "radio/COMMON/common_lib.h" -bool edit_config_mplane(ru_session_t *ru_session, const char *buffer, const openair0_config_t *oai, const size_t num_rus); - -bool validate_config_mplane(ru_session_t *ru_session); - -bool commit_config_mplane(ru_session_t *ru_session); +bool edit_val_commmit_rpc(ru_session_t *ru_session, const char *content); #endif /* CONFIGURE_MPLANE_H */ diff --git a/radio/fhi_72/mplane/connect-mplane.c b/radio/fhi_72/mplane/connect-mplane.c index 08b758bef1..c63cc3d0c1 100644 --- a/radio/fhi_72/mplane/connect-mplane.c +++ b/radio/fhi_72/mplane/connect-mplane.c @@ -67,6 +67,11 @@ void disconnect_mplane(void *rus_disconnect) MP_LOG_I("Disconnecting from RU \"%s\".\n", ru_session->ru_ip_add); nc_session_free(ru_session->session, NULL); ru_session->session = NULL; +#ifdef MPLANE_V1 + ly_ctx_destroy((struct ly_ctx *)ru_session->ctx, NULL); +#elif defined MPLANE_V2 + ly_ctx_destroy((struct ly_ctx *)ru_session->ctx); +#endif } nc_client_destroy(); diff --git a/radio/fhi_72/mplane/init-mplane.c b/radio/fhi_72/mplane/init-mplane.c index 39e8cfb995..200333398d 100644 --- a/radio/fhi_72/mplane/init-mplane.c +++ b/radio/fhi_72/mplane/init-mplane.c @@ -25,6 +25,8 @@ #include "subscribe-mplane.h" #include "config-mplane.h" #include "xml/get-xml.h" +#include "yang/get-yang.h" +#include "yang/create-yang-config.h" #include #include @@ -175,15 +177,17 @@ bool manage_ru(ru_session_t *ru_session, const openair0_config_t *oai, const siz success = get_uplane_info(operational_ds, &ru_session->ru_mplane_config); AssertError(success, return false, "[MPLANE] Unable to get U-plane info from RU operational datastore.\n"); + success = load_yang_models(ru_session, operational_ds); + AssertError(success, return false, "[MPLANE] Unable to load yang models.\n"); + if (ru_session->ru_notif.ptp_state) { - success = edit_config_mplane(ru_session, operational_ds, oai, num_rus); - AssertError(success, return false, "[MPLANE] Unable to edit the RU configuration.\n"); + char *content = NULL; + success = configure_ru_from_yang(ru_session, oai, num_rus, &content); + AssertError(success, return false, "[MPLANE] Unable to create content for RPC for start-up procedure.\n"); - success = validate_config_mplane(ru_session); - AssertError(success, return false, "[MPLANE] Unable to validate the RU configuration.\n"); - - success = commit_config_mplane(ru_session); - AssertError(success, return false, "[MPLANE] Unable to commit the RU configuration.\n"); + success = edit_val_commmit_rpc(ru_session, content); + AssertError(success, return false, "[MPLANE] Unable to continue.\n"); + free(content); } const char *usage_state = get_ru_xml_node(operational_ds, "usage-state"); diff --git a/radio/fhi_72/mplane/ru-mplane-api.h b/radio/fhi_72/mplane/ru-mplane-api.h index df6a89042f..581c0a164d 100644 --- a/radio/fhi_72/mplane/ru-mplane-api.h +++ b/radio/fhi_72/mplane/ru-mplane-api.h @@ -85,6 +85,7 @@ typedef struct { char *ru_ip_add; ru_mplane_config_t ru_mplane_config; void *session; + void *ctx; xran_mplane_t xran_mplane; ru_notif_t ru_notif; diff --git a/radio/fhi_72/mplane/yang/create-yang-config.c b/radio/fhi_72/mplane/yang/create-yang-config.c index dac1ee810e..78281a558a 100644 --- a/radio/fhi_72/mplane/yang/create-yang-config.c +++ b/radio/fhi_72/mplane/yang/create-yang-config.c @@ -26,11 +26,11 @@ const char *scs_name[] = {"KHZ_15", "KHZ_30", "KHZ_60", "KHZ_120", "KHZ_240", NULL}; #ifdef MPLANE_V2 -static bool create_cu_interface_v2(struct ly_ctx **ctx, const ru_session_t *ru_session, const size_t idx, const char *int_name, struct lyd_node **root) +static bool create_cu_interface_v2(const ru_session_t *ru_session, const size_t idx, const char *int_name, struct lyd_node **root) { LY_ERR ret = LY_SUCCESS; - ret = lyd_new_path(NULL, *ctx, "/ietf-interfaces:interfaces", NULL, 0, root); + ret = lyd_new_path(NULL, (struct ly_ctx *)ru_session->ctx, "/ietf-interfaces:interfaces", NULL, 0, root); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create root \"interfaces\" node.\n"); struct lyd_node *interface_node = NULL; @@ -44,7 +44,7 @@ static bool create_cu_interface_v2(struct ly_ctx **ctx, const ru_session_t *ru_s ret = lyd_new_term(interface_node, NULL, "enabled", "true", 0, NULL); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"enabled\" node.\n"); - const struct lys_module *oran_int_mod = ly_ctx_get_module_implemented(*ctx, "o-ran-interfaces"); + const struct lys_module *oran_int_mod = ly_ctx_get_module_implemented((struct ly_ctx *)ru_session->ctx, "o-ran-interfaces"); VERIFY_SUCCESS(oran_int_mod != NULL, "[MPLANE] Failed to get \"o-ran-interfaces\" module.\n"); struct lyd_node *base_int = NULL; @@ -64,11 +64,11 @@ static bool create_cu_interface_v2(struct ly_ctx **ctx, const ru_session_t *ru_s return true; } -static bool create_proc_elem_v2(struct ly_ctx **ctx, const ru_session_t *ru_session, const size_t idx, const char *int_name, struct lyd_node **root) +static bool create_proc_elem_v2(const ru_session_t *ru_session, const size_t idx, const char *int_name, struct lyd_node **root) { LY_ERR ret = LY_SUCCESS; - ret = lyd_new_path(NULL, *ctx, "/o-ran-processing-element:processing-elements", NULL, 0, root); + ret = lyd_new_path(NULL, (struct ly_ctx *)ru_session->ctx, "/o-ran-processing-element:processing-elements", NULL, 0, root); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create root \"processing-elements\" node.\n"); ret = lyd_new_term(*root, NULL, "transport-session-type", "ETH-INTERFACE", 0, NULL); @@ -225,12 +225,12 @@ static bool fill_uplane_ch_tx_v2(const xran_mplane_t *xran_mplane, const openair return true; } -static bool create_uplane_conf_v2(struct ly_ctx **ctx, const ru_session_t *ru_session, const openair0_config_t *oai, const size_t num_rus, const char *u_proc_elem, struct lyd_node **root) +static bool create_uplane_conf_v2(const ru_session_t *ru_session, const openair0_config_t *oai, const size_t num_rus, const char *u_proc_elem, struct lyd_node **root) { LY_ERR ret = LY_SUCCESS; bool success = true; - ret = lyd_new_path(NULL, *ctx, "/o-ran-uplane-conf:user-plane-configuration", NULL, 0, root); + ret = lyd_new_path(NULL, (struct ly_ctx *)ru_session->ctx, "/o-ran-uplane-conf:user-plane-configuration", NULL, 0, root); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create root \"user-plane-configuration\" node.\n"); if (ru_session->ru_mplane_config.rx_carriers.num != 1 || ru_session->ru_mplane_config.tx_carriers.num !=1) @@ -398,7 +398,7 @@ static bool create_uplane_conf_v2(struct ly_ctx **ctx, const ru_session_t *ru_se } #endif -bool configure_ru_from_yang(struct ly_ctx **ctx, const ru_session_t *ru_session, const openair0_config_t *oai, const size_t num_rus, char **result) +bool configure_ru_from_yang(const ru_session_t *ru_session, const openair0_config_t *oai, const size_t num_rus, char **result) { bool success = false; @@ -420,12 +420,12 @@ bool configure_ru_from_yang(struct ly_ctx **ctx, const ru_session_t *ru_session, struct lyd_node *cu_interface = NULL; char int_name[12]; snprintf(int_name, sizeof(int_name), "INTERFACE_%ld", i); - success = create_cu_interface_v2(ctx, ru_session, i, int_name, &cu_interface); + success = create_cu_interface_v2(ru_session, i, int_name, &cu_interface); VERIFY_SUCCESS(success, "[MPLANE] Cannot create CU-plane interface.\n"); // struct lyd_node *proc_elem = NULL; - success = create_proc_elem_v2(ctx, ru_session, i, int_name, &proc_elem); + success = create_proc_elem_v2(ru_session, i, int_name, &proc_elem); VERIFY_SUCCESS(success, "[MPLANE] Cannot create CU-plane processing element.\n"); ret = lyd_merge_siblings(&all_merge, cu_interface, 0); @@ -439,13 +439,13 @@ bool configure_ru_from_yang(struct ly_ctx **ctx, const ru_session_t *ru_session, // struct lyd_node *uplane_conf = NULL; - success = create_uplane_conf_v2(ctx, ru_session, oai, num_rus, "PLANE_0", &uplane_conf); + success = create_uplane_conf_v2(ru_session, oai, num_rus, "PLANE_0", &uplane_conf); VERIFY_SUCCESS(success, "[MPLANE] Cannot create U-plane configuration.\n"); - - ret = lyd_merge_siblings(&uplane_conf, all_merge, 0); + + ret = lyd_merge_siblings(&all_merge, uplane_conf, 0); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Cannot merge CU-plane interface, processing element and U-plane configuration.\n"); - lyd_print_mem(result, uplane_conf, LYD_XML, LYD_PRINT_WITHSIBLINGS); + lyd_print_mem(result, all_merge, LYD_XML, LYD_PRINT_WITHSIBLINGS); lyd_free_siblings(all_merge); lyd_free_siblings(uplane_conf); diff --git a/radio/fhi_72/mplane/yang/create-yang-config.h b/radio/fhi_72/mplane/yang/create-yang-config.h index 9e06bdc923..45c8f6ea1c 100644 --- a/radio/fhi_72/mplane/yang/create-yang-config.h +++ b/radio/fhi_72/mplane/yang/create-yang-config.h @@ -27,6 +27,6 @@ #include -bool configure_ru_from_yang(struct ly_ctx **ctx, const ru_session_t *ru_session, const openair0_config_t *oai, const size_t num_rus, char **result); +bool configure_ru_from_yang(const ru_session_t *ru_session, const openair0_config_t *oai, const size_t num_rus, char **result); #endif /* CREATE_MPLANE_YANG_CONFIG_H */ diff --git a/radio/fhi_72/mplane/yang/get-yang.c b/radio/fhi_72/mplane/yang/get-yang.c index c27454136f..e06128846f 100644 --- a/radio/fhi_72/mplane/yang/get-yang.c +++ b/radio/fhi_72/mplane/yang/get-yang.c @@ -95,8 +95,10 @@ static bool load_from_operational_ds(xmlNode *node, ru_session_t *ru_session, st return false; } -bool load_yang_models(ru_session_t *ru_session, const char *buffer, struct ly_ctx **ctx) +bool load_yang_models(ru_session_t *ru_session, const char *buffer) { + struct ly_ctx **ctx = (struct ly_ctx **)&ru_session->ctx; + // Initialize the xml file size_t len = strlen(buffer) + 1; xmlDoc *doc = xmlReadMemory(buffer, len, NULL, NULL, 0); diff --git a/radio/fhi_72/mplane/yang/get-yang.h b/radio/fhi_72/mplane/yang/get-yang.h index 5956bde203..7ca191d234 100644 --- a/radio/fhi_72/mplane/yang/get-yang.h +++ b/radio/fhi_72/mplane/yang/get-yang.h @@ -26,6 +26,6 @@ #include -bool load_yang_models(ru_session_t *ru_session, const char *buffer, struct ly_ctx **ctx); +bool load_yang_models(ru_session_t *ru_session, const char *buffer); #endif /* GET_MPLANE_YANG_MODELS_H */ From 625b4b0cde9bdf2297029f2afd2674425303a700 Mon Sep 17 00:00:00 2001 From: Teodora Date: Thu, 21 Aug 2025 11:37:49 +0200 Subject: [PATCH 570/964] Add support for RU username parameter for connection to a RU via M-plane The "sudo" access group is required by OAI gNB. --- doc/ORAN_FHI7.2_Tutorial.md | 5 ++++- radio/fhi_72/mplane/connect-mplane.c | 7 +++---- radio/fhi_72/mplane/init-mplane.c | 5 +++++ radio/fhi_72/mplane/ru-mplane-api.h | 1 + radio/fhi_72/oran-params.h | 3 +++ ...u.sa.band77.273prb.fhi72.8x8-benetel650_650-mplane.conf | 1 + .../gnb.sa.band78.273prb.fhi72.4x4-benetel550-mplane.conf | 1 + 7 files changed, 18 insertions(+), 5 deletions(-) diff --git a/doc/ORAN_FHI7.2_Tutorial.md b/doc/ORAN_FHI7.2_Tutorial.md index ed340cc5c1..a0fb30527e 100644 --- a/doc/ORAN_FHI7.2_Tutorial.md +++ b/doc/ORAN_FHI7.2_Tutorial.md @@ -1375,7 +1375,7 @@ Once the mplane service is successfully enabled on the RU, two new users are bei oranbenetel:x:1000:1000::/home/oranbenetel:/bin/sh oranext:x:1001:1001::/home/oranext:/bin/sh ``` -Create `oranbenetel` home directory: +OAI gNB requires the `sudo` access group for NETCONF session. In the case of Benetel O-RUs, the corresponding user is `oranbenetel`. Therefore, please create its home directory: ```bash mkdir /home/oranbenetel && chown oranbenetel:oranbenetel /home/oranbenetel ``` @@ -1404,6 +1404,7 @@ fhi_72 = { du_key_pair = ("/.ssh/id_rsa.pub", "/.ssh/id_rsa"); du_addr = ("00:11:22:33:44:66", "00:11:22:33:44:67"); # only one needed if one VF configured vlan_tag = (9, 9); # only one needed if one VF configured + ru_username = ("oranbenetel"); ru_ip_addr = ("192.168.80.9"); fh_config = ({ T1a_cp_dl = (419, 470); @@ -1423,6 +1424,7 @@ fhi_72 = { du_key_pair = ("/home/oaicicd/.ssh/id_rsa.pub", "/home/oaicicd/.ssh/id_rsa"); du_addr = ("00:11:22:33:44:66", "00:11:22:33:44:67", "00:11:22:33:44:68", "00:11:22:33:44:69"); # only two needed if two VFs configured vlan_tag = (9, 9, 11, 11); # only two needed if two VFs configured + ru_username = ("oranbenetel", "oranbenetel"); ru_ip_addr = ("192.168.80.9", "192.168.80.10"); fh_config = ( # RAN550 #1 @@ -1451,6 +1453,7 @@ fhi_72 = { * `du_key_pair`: ssh public and private keys to authenticate RU with NETCONF * `du_addr`: DU MAC address(es) to create CU-plane interface(s) in the RU * `vlan_tag`: VLAN U and C plane tags to create CU-plane interface(s) in the RU + * `ru_username`: Username with `sudo` access to connect to the RU via M-plane * `ru_ip_addr`: RU IP address to connect to the RU via M-plane * `dpdk_mem_size`: [*] * `dpdk_iova_mode`: [*] diff --git a/radio/fhi_72/mplane/connect-mplane.c b/radio/fhi_72/mplane/connect-mplane.c index c63cc3d0c1..f65de2d6c4 100644 --- a/radio/fhi_72/mplane/connect-mplane.c +++ b/radio/fhi_72/mplane/connect-mplane.c @@ -37,9 +37,8 @@ static int my_auth_hostkey_check(const char *hostname, ssh_session session, void bool connect_mplane(ru_session_t *ru_session) { int port = NC_PORT_SSH; - char *user = "oranbenetel"; - nc_client_ssh_set_username(user); + nc_client_ssh_set_username(ru_session->username); nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PUBLICKEY, 1); // ssh-key identification nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PASSWORD, -1); @@ -47,11 +46,11 @@ bool connect_mplane(ru_session_t *ru_session) nc_client_ssh_set_auth_hostkey_check_clb(my_auth_hostkey_check, "DATA"); // host-key identification - MP_LOG_I("RPC request to RU \"%s\" = with username \"%s\" and port ID \"%d\".\n", ru_session->ru_ip_add, user, port); + MP_LOG_I("RPC request to RU \"%s\" = with username \"%s\" and port ID \"%d\".\n", ru_session->ru_ip_add, ru_session->username, port); ru_session->session = nc_connect_ssh(ru_session->ru_ip_add, port, NULL); AssertError(ru_session->session != NULL, return false, "[MPLANE] RU IP address %s unreachable. Maybe M-plane is disabled on the RU?\n", ru_session->ru_ip_add); - MP_LOG_I("Successfuly connected to RU \"%s\" with username \"%s\" and port ID \"%d\".\n", ru_session->ru_ip_add, user, port); + MP_LOG_I("Successfuly connected to RU \"%s\" with username \"%s\" and port ID \"%d\".\n", ru_session->ru_ip_add, ru_session->username, port); return true; } diff --git a/radio/fhi_72/mplane/init-mplane.c b/radio/fhi_72/mplane/init-mplane.c index 200333398d..f978a4d45f 100644 --- a/radio/fhi_72/mplane/init-mplane.c +++ b/radio/fhi_72/mplane/init-mplane.c @@ -96,11 +96,14 @@ bool init_mplane(ru_session_list_t *ru_session_list) char **ru_ip_addrs = gpd(fhip, nump, ORAN_CONFIG_RU_IP_ADDR)->strlistptr; int num_rus = gpd(fhip, nump, ORAN_CONFIG_RU_IP_ADDR)->numelt; + char **ru_usernames = gpd(fhip, nump, ORAN_CONFIG_RU_USERNAME)->strlistptr; + int num_ru_users = gpd(fhip, nump, ORAN_CONFIG_RU_USERNAME)->numelt; char **du_mac_addr = gpd(fhip, nump, ORAN_CONFIG_DU_ADDR)->strlistptr; int num_dus = gpd(fhip, nump, ORAN_CONFIG_DU_ADDR)->numelt; int32_t *vlan_tag = gpd(fhip, nump, ORAN_CONFIG_VLAN_TAG)->iptr; int num_vlan_tags = gpd(fhip, nump, ORAN_CONFIG_VLAN_TAG)->numelt; + AssertError(num_rus == num_ru_users, return false, "[MPLANE] Number of RUs should be equal to the number of users, one for each.\n"); AssertError(num_dus == num_vlan_tags, return false, "[MPLANE] Number of DU MAC addresses should be equal to the number of VLAN tags.\n"); int num_cu_planes = num_dus / num_rus; @@ -112,6 +115,8 @@ bool init_mplane(ru_session_list_t *ru_session_list) ru_session->session = NULL; ru_session->ru_ip_add = calloc(strlen(ru_ip_addrs[i]) + 1, sizeof(char)); memcpy(ru_session->ru_ip_add, ru_ip_addrs[i], strlen(ru_ip_addrs[i]) + 1); + ru_session->username = calloc(strlen(ru_usernames[i]) + 1, sizeof(char)); + memcpy(ru_session->username, ru_usernames[i], strlen(ru_usernames[i]) + 1); // store DU MAC addresses and VLAN tags ru_session->ru_mplane_config.num_cu_planes = num_cu_planes; diff --git a/radio/fhi_72/mplane/ru-mplane-api.h b/radio/fhi_72/mplane/ru-mplane-api.h index 581c0a164d..33e6453ab6 100644 --- a/radio/fhi_72/mplane/ru-mplane-api.h +++ b/radio/fhi_72/mplane/ru-mplane-api.h @@ -82,6 +82,7 @@ typedef struct { } ru_mplane_config_t; typedef struct { + char *username; char *ru_ip_add; ru_mplane_config_t ru_mplane_config; void *session; diff --git a/radio/fhi_72/oran-params.h b/radio/fhi_72/oran-params.h index 42aabd99bb..baeefbc68d 100644 --- a/radio/fhi_72/oran-params.h +++ b/radio/fhi_72/oran-params.h @@ -35,6 +35,7 @@ #define ORAN_CONFIG_DU_ADDR "du_addr" // only needed for M-plane #define ORAN_CONFIG_VLAN_TAG "vlan_tag" // only needed for M-plane #define ORAN_CONFIG_RU_ADDR "ru_addr" // not needed if M-plane used +#define ORAN_CONFIG_RU_USERNAME "ru_username" // only needed for M-plane #define ORAN_CONFIG_RU_IP_ADDR "ru_ip_addr" // only needed for M-plane #define ORAN_CONFIG_MTU "mtu" // not needed if M-plane used #define ORAN_CONFIG_FILE_PREFIX "file_prefix" @@ -56,6 +57,7 @@ {ORAN_CONFIG_DU_ADDR, "Ether addr of DU\n", PARAMFLAG_MANDATORY, .strlistptr=NULL, .defstrlistval=NULL, TYPE_STRINGLIST, 0}, \ {ORAN_CONFIG_VLAN_TAG, "VLAN tag\n", PARAMFLAG_MANDATORY, .iptr=NULL, .defintarrayval=0, TYPE_INTARRAY, 0}, \ {ORAN_CONFIG_RU_ADDR, "Ether addr of RU\n", PARAMFLAG_MANDATORY, .strlistptr=NULL, .defstrlistval=NULL, TYPE_STRINGLIST, 0}, \ + {ORAN_CONFIG_RU_USERNAME, "Username of RU\n", PARAMFLAG_MANDATORY, .strlistptr=NULL, .defstrlistval=NULL, TYPE_STRINGLIST, 0}, \ {ORAN_CONFIG_RU_IP_ADDR, "IP addr of RU\n", PARAMFLAG_MANDATORY, .strlistptr=NULL, .defstrlistval=NULL, TYPE_STRINGLIST, 0}, \ {ORAN_CONFIG_MTU, "MTU of Eth interface\n", 0, .uptr=NULL, .defuintval=1500, TYPE_UINT, 0}, \ {ORAN_CONFIG_FILE_PREFIX, "DPDK file-prefix\n", 0, .strptr=NULL, .defstrval="wls_0", TYPE_STRING, 0}, \ @@ -82,6 +84,7 @@ { .s5 = { NULL } }, \ { .s5 = { NULL } }, \ { .s5 = { NULL } }, \ + { .s5 = { NULL } }, \ { .s3a = { config_checkstr_assign_integer, \ {"PA", "VA"}, {0, 1}, 2} }, \ { .s5 = { NULL } }, \ diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650-mplane.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650-mplane.conf index 97459ad55e..3dd36be9c7 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650-mplane.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650-mplane.conf @@ -240,6 +240,7 @@ fhi_72 = { du_key_pair = ("/home/eurecom/.ssh/id_rsa.pub", "/home/eurecom/.ssh/id_rsa"); du_addr = ("00:11:22:33:44:66", "00:11:22:33:44:67", "00:11:22:33:44:68", "00:11:22:33:44:69"); vlan_tag = (5, 5, 6, 6); + ru_username = ("oranbenetel", "oranbenetel"); ru_ip_addr = ("192.168.80.5", "192.168.80.6"); fh_config = ( # RAN650 #1 diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-benetel550-mplane.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-benetel550-mplane.conf index 9472ee3cdd..ed996cac27 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-benetel550-mplane.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-benetel550-mplane.conf @@ -260,6 +260,7 @@ fhi_72 = { du_key_pair = ("/home/eurecom/.ssh/id_rsa.pub", "/home/eurecom/.ssh/id_rsa"); du_addr = ("00:11:22:33:44:68","00:11:22:33:44:69"); vlan_tag = (11, 11); + ru_username = ("oranbenetel"); ru_ip_addr = ("192.168.80.10"); fh_config = ({ T1a_cp_dl = (419, 470); From 0367881ba95443c7a9c24427ae4f915e1013ffc3 Mon Sep 17 00:00:00 2001 From: Teodora Date: Mon, 7 Jul 2025 15:15:52 +0200 Subject: [PATCH 571/964] Performance Management implementation Introduced a parameter start_up_timing which indicates if PM activation is supported during the start-up procedure. We initialize this parameter, based on the vendor. Notification interval is set to 10s. --- radio/fhi_72/mplane/connect-mplane.c | 5 + radio/fhi_72/mplane/init-mplane.c | 16 + radio/fhi_72/mplane/init-mplane.h | 2 + radio/fhi_72/mplane/ru-mplane-api.c | 20 + radio/fhi_72/mplane/ru-mplane-api.h | 15 + radio/fhi_72/mplane/subscribe-mplane.c | 38 +- radio/fhi_72/mplane/xml/get-xml.c | 3 +- radio/fhi_72/mplane/yang/create-yang-config.c | 82 + radio/fhi_72/mplane/yang/create-yang-config.h | 2 + radio/fhi_72/mplane/yang/get-yang.c | 2 +- .../mplane/yang/models/ietf-crypto-types.yang | 1783 +++++++++++++++++ .../mplane/yang/models/ietf-netconf-acm.yang | 440 ++++ .../yang/models/o-ran-file-management.yang | 213 ++ .../models/o-ran-performance-management.yang | 1168 +++++++++++ radio/fhi_72/oran_isolate.c | 5 + 15 files changed, 3791 insertions(+), 3 deletions(-) create mode 100644 radio/fhi_72/mplane/yang/models/ietf-crypto-types.yang create mode 100644 radio/fhi_72/mplane/yang/models/ietf-netconf-acm.yang create mode 100644 radio/fhi_72/mplane/yang/models/o-ran-file-management.yang create mode 100644 radio/fhi_72/mplane/yang/models/o-ran-performance-management.yang diff --git a/radio/fhi_72/mplane/connect-mplane.c b/radio/fhi_72/mplane/connect-mplane.c index f65de2d6c4..9744ce01e8 100644 --- a/radio/fhi_72/mplane/connect-mplane.c +++ b/radio/fhi_72/mplane/connect-mplane.c @@ -20,6 +20,7 @@ */ #include "connect-mplane.h" +#include "init-mplane.h" #include "common/utils/assertions.h" #include @@ -63,6 +64,10 @@ void disconnect_mplane(void *rus_disconnect) ru_session_t *ru_session = &ru_session_list->ru_session[i]; if (ru_session->session == NULL) continue; + MP_LOG_I("Sending PM de-activation request for RU \"%s\".\n", ru_session->ru_ip_add); + bool success = pm_conf(ru_session, "false"); + if (success) + MP_LOG_I("Successfully de-activated PM for RU \"%s\".\n", ru_session->ru_ip_add); MP_LOG_I("Disconnecting from RU \"%s\".\n", ru_session->ru_ip_add); nc_session_free(ru_session->session, NULL); ru_session->session = NULL; diff --git a/radio/fhi_72/mplane/init-mplane.c b/radio/fhi_72/mplane/init-mplane.c index f978a4d45f..fc20ba5af4 100644 --- a/radio/fhi_72/mplane/init-mplane.c +++ b/radio/fhi_72/mplane/init-mplane.c @@ -182,6 +182,10 @@ bool manage_ru(ru_session_t *ru_session, const openair0_config_t *oai, const siz success = get_uplane_info(operational_ds, &ru_session->ru_mplane_config); AssertError(success, return false, "[MPLANE] Unable to get U-plane info from RU operational datastore.\n"); + // Performance Management + success = get_pm_object_list(operational_ds, &ru_session->pm_stats); + AssertError(success, return false, "[MPLANE] Unable to retrieve performance measurement names from RU \"%s\".\n", ru_session->ru_ip_add); + success = load_yang_models(ru_session, operational_ds); AssertError(success, return false, "[MPLANE] Unable to load yang models.\n"); @@ -212,3 +216,15 @@ bool manage_ru(ru_session_t *ru_session, const openair0_config_t *oai, const siz return true; } + +bool pm_conf(ru_session_t *ru_session, const char *active) +{ + char *content = get_pm_content(ru_session, active); + + bool success = edit_val_commmit_rpc(ru_session, content); + AssertError(success, return false, "[MPLANE] Cannot continue.\n"); + + free(content); + + return true; +} diff --git a/radio/fhi_72/mplane/init-mplane.h b/radio/fhi_72/mplane/init-mplane.h index 5077908d64..ef6e23610f 100644 --- a/radio/fhi_72/mplane/init-mplane.h +++ b/radio/fhi_72/mplane/init-mplane.h @@ -29,4 +29,6 @@ bool init_mplane(ru_session_list_t *ru_session_list); bool manage_ru(ru_session_t *ru_session, const openair0_config_t *oai, const size_t num_rus); +bool pm_conf(ru_session_t *ru_session, const char *active); + #endif /* OAI_MPLANE_H */ diff --git a/radio/fhi_72/mplane/ru-mplane-api.c b/radio/fhi_72/mplane/ru-mplane-api.c index e6be2e11b5..df4bf3b8ba 100644 --- a/radio/fhi_72/mplane/ru-mplane-api.c +++ b/radio/fhi_72/mplane/ru-mplane-api.c @@ -182,3 +182,23 @@ bool get_uplane_info(const char *buffer, ru_mplane_config_t *ru_mplane_config) return true; } + +bool get_pm_object_list(const char *buffer, pm_stats_t *pm_stats) +{ + const char *ru_vendor = get_ru_xml_node(buffer, "mfg-name"); + if (strcasecmp(ru_vendor, "BENETEL") == 0) { + pm_stats->start_up_timing = false; + } else { + pm_stats->start_up_timing = true; + } + + // Rx window + get_ru_xml_list(buffer, "rx-window-objects", &pm_stats->rx_window_meas, &pm_stats->rx_num); + + // Tx + get_ru_xml_list(buffer, "tx-stats-objects", &pm_stats->tx_meas, &pm_stats->tx_num); + + MP_LOG_I("Successfully retreived all performance measurement names.\n"); + + return true; +} diff --git a/radio/fhi_72/mplane/ru-mplane-api.h b/radio/fhi_72/mplane/ru-mplane-api.h index 33e6453ab6..85fac5515c 100644 --- a/radio/fhi_72/mplane/ru-mplane-api.h +++ b/radio/fhi_72/mplane/ru-mplane-api.h @@ -81,6 +81,18 @@ typedef struct { } ru_mplane_config_t; +typedef struct { + // activation if required at start-up timing + bool start_up_timing; + + size_t rx_num; + char **rx_window_meas; + + size_t tx_num; + char **tx_meas; + +} pm_stats_t; + typedef struct { char *username; char *ru_ip_add; @@ -89,6 +101,7 @@ typedef struct { void *ctx; xran_mplane_t xran_mplane; ru_notif_t ru_notif; + pm_stats_t pm_stats; } ru_session_t; @@ -103,4 +116,6 @@ bool get_config_for_xran(const char *buffer, const int max_num_ant, xran_mplane_ bool get_uplane_info(const char *buffer, ru_mplane_config_t *ru_mplane_config); +bool get_pm_object_list(const char *buffer, pm_stats_t *pm_stats); + #endif /* RU_MPLANE_API_H */ diff --git a/radio/fhi_72/mplane/subscribe-mplane.c b/radio/fhi_72/mplane/subscribe-mplane.c index 9a8e28c4c1..bec7e28a68 100644 --- a/radio/fhi_72/mplane/subscribe-mplane.c +++ b/radio/fhi_72/mplane/subscribe-mplane.c @@ -54,6 +54,37 @@ static void notif_clb_v1(struct nc_session *session, const struct nc_notif *noti recv_notif_v1(notif, answer); } #elif MPLANE_V2 +static void log_v2_pm_info(const char *ru_ip_add, struct lyd_node_inner *stats) +{ + struct lyd_node *child, *field = NULL; + size_t len = 0; + char *meas_list[8], *count_list[8] = {}; + + LY_LIST_FOR(stats->child, child) { + // const char *type = child->schema->name; // e.g. "rx-window-stats", "tx-stats" + struct lyd_node_inner *stats_inner = (struct lyd_node_inner *)child; + LY_LIST_FOR(stats_inner->child, field) { + if (strcmp(field->schema->name, "measurement-object") == 0) { + meas_list[len] = (char *)lyd_get_value(field); + } else if (strcmp(field->schema->name, "count") == 0) { + count_list[len] = (char *)lyd_get_value(field); + len++; + } + } + } + + MP_LOG_I("[PM: \"%s\"][%s %7s][%s %7s][%s %7s][%s %7s][%s %7s][%s %7s][%s %7s][%s %7s]\n", + ru_ip_add, + meas_list[0], count_list[0], + meas_list[1], count_list[1], + meas_list[2], count_list[2], + meas_list[3], count_list[3], + meas_list[4], count_list[4], + meas_list[5], count_list[5], + meas_list[6], count_list[6], + meas_list[7], count_list[7]); +} + static void recv_notif_v2(struct lyd_node_inner *op, ru_notif_t *answer) { const char *notif = op->schema->name; @@ -92,9 +123,14 @@ static void notif_clb_v2(struct nc_session *session, const struct lyd_node *envp char *subs_reply = NULL; lyd_print_mem(&subs_reply, op, output_format, LYD_PRINT_WITHSIBLINGS); const char *ru_ip_add = nc_session_get_host(session); + struct lyd_node_inner *op_inner = (struct lyd_node_inner *)op; + if (strcmp(op_inner->schema->name, "measurement-result-stats") == 0) { + log_v2_pm_info(ru_ip_add, op_inner); + return; + } MP_LOG_I("Received notification from RU \"%s\" at (%s)\n%s\n", ru_ip_add, ((struct lyd_node_opaq *)lyd_child(envp))->value, subs_reply); - recv_notif_v2((struct lyd_node_inner *)op, answer); + recv_notif_v2(op_inner, answer); } #endif diff --git a/radio/fhi_72/mplane/xml/get-xml.c b/radio/fhi_72/mplane/xml/get-xml.c index 616d2e480f..6456219293 100644 --- a/radio/fhi_72/mplane/xml/get-xml.c +++ b/radio/fhi_72/mplane/xml/get-xml.c @@ -68,7 +68,8 @@ static void find_ru_xml_list(xmlNode *node, const char *filter, char ***match_li xmlNode *name_node = NULL; for (xmlNode *cur_node2 = cur_node->children; cur_node2; cur_node2 = cur_node2->next) { - if (cur_node2->type == XML_ELEMENT_NODE && strcmp((const char *)cur_node2->name, "name") == 0) { + const char *name_node_str = (const char *)cur_node2->name; + if (cur_node2->type == XML_ELEMENT_NODE && (strcmp(name_node_str, "name") == 0 || strcmp(name_node_str, "measurement-object") == 0)) { name_node = cur_node2; break; } diff --git a/radio/fhi_72/mplane/yang/create-yang-config.c b/radio/fhi_72/mplane/yang/create-yang-config.c index 78281a558a..187fe5b7c1 100644 --- a/radio/fhi_72/mplane/yang/create-yang-config.c +++ b/radio/fhi_72/mplane/yang/create-yang-config.c @@ -396,6 +396,56 @@ static bool create_uplane_conf_v2(const ru_session_t *ru_session, const openair0 return true; } + +static +bool create_pm_conf_v2(const ru_session_t *ru_session, const char *active, struct lyd_node **root) +{ + LY_ERR ret = LY_SUCCESS; + + ret = lyd_new_path(NULL, (struct ly_ctx *)ru_session->ctx, "/o-ran-performance-management:performance-measurement-objects", NULL, 0, root); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create root \"performance-measurement-objects\" node.\n"); + + ret = lyd_new_term(*root, NULL, "notification-interval", "10", 0, NULL); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"notification-interval\" node.\n"); + + ret = lyd_new_term(*root, NULL, "rx-window-measurement-interval", "10", 0, NULL); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"rx-window-measurement-interval\" node.\n"); + + ret = lyd_new_term(*root, NULL, "tx-measurement-interval", "10", 0, NULL); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"tx-measurement-interval\" node.\n"); + + for (size_t i = 0; i < ru_session->pm_stats.rx_num; i++) { + struct lyd_node *rx_window_meas_objects = NULL; + ret = lyd_new_list(*root, NULL, "rx-window-measurement-objects", 0, &rx_window_meas_objects, ru_session->pm_stats.rx_window_meas[i]); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"rx-window-measurement-objects\" node.\n"); + + ret = lyd_new_term(rx_window_meas_objects, NULL, "active", active, 0, NULL); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"active\" node.\n"); + + ret = lyd_new_term(rx_window_meas_objects, NULL, "object-unit", "RU", 0, NULL); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"object-unit\" node.\n"); + + ret = lyd_new_term(rx_window_meas_objects, NULL, "report-info", "COUNT", 0, NULL); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"report-info\" node.\n"); + } + + for (size_t i = 0; i < ru_session->pm_stats.tx_num; i++) { + struct lyd_node *tx_meas_objects = NULL; + ret = lyd_new_list(*root, NULL, "tx-measurement-objects", 0, &tx_meas_objects, ru_session->pm_stats.tx_meas[i]); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"tx-measurement-objects\" node.\n"); + + ret = lyd_new_term(tx_meas_objects, NULL, "active", active, 0, NULL); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"active\" node.\n"); + + ret = lyd_new_term(tx_meas_objects, NULL, "object-unit", "RU", 0, NULL); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"object-unit\" node.\n"); + + ret = lyd_new_term(tx_meas_objects, NULL, "report-info", "COUNT", 0, NULL); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"report-info\" node.\n"); + } + + return true; +} #endif bool configure_ru_from_yang(const ru_session_t *ru_session, const openair0_config_t *oai, const size_t num_rus, char **result) @@ -445,11 +495,43 @@ bool configure_ru_from_yang(const ru_session_t *ru_session, const openair0_confi ret = lyd_merge_siblings(&all_merge, uplane_conf, 0); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Cannot merge CU-plane interface, processing element and U-plane configuration.\n"); + // + struct lyd_node *pm_conf = NULL; + if (ru_session->pm_stats.start_up_timing) { + success = create_pm_conf_v2(ru_session, "true", &pm_conf); + VERIFY_SUCCESS(success, "[MPLANE] Cannot create PM activation.\n"); + } else { + success = create_pm_conf_v2(ru_session, "false", &pm_conf); + VERIFY_SUCCESS(success, "[MPLANE] Cannot create PM deactivation.\n"); + } + + ret = lyd_merge_siblings(&all_merge, pm_conf, 0); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Cannot merge CU-plane interface, processing element, U-plane configuration and PM configuration.\n"); + lyd_print_mem(result, all_merge, LYD_XML, LYD_PRINT_WITHSIBLINGS); lyd_free_siblings(all_merge); lyd_free_siblings(uplane_conf); + lyd_free_siblings(pm_conf); #endif return true; } + +char *get_pm_content(const ru_session_t *ru_session, const char *active) +{ + bool success = false; + char *content = NULL; + +#ifdef MPLANE_V1 + VERIFY_SUCCESS(success, "[MPLANE] To be implemented and tested.\n"); +#elif defined MPLANE_V2 + struct lyd_node *pm_conf = NULL; + success = create_pm_conf_v2(ru_session, active, &pm_conf); + AssertError(success, return false, "[MPLANE] Cannot create PM configuration.\n"); + lyd_print_mem(&content, pm_conf, LYD_XML, LYD_PRINT_WITHSIBLINGS); + lyd_free_siblings(pm_conf); +#endif + + return content; +} diff --git a/radio/fhi_72/mplane/yang/create-yang-config.h b/radio/fhi_72/mplane/yang/create-yang-config.h index 45c8f6ea1c..2f03a3f774 100644 --- a/radio/fhi_72/mplane/yang/create-yang-config.h +++ b/radio/fhi_72/mplane/yang/create-yang-config.h @@ -29,4 +29,6 @@ bool configure_ru_from_yang(const ru_session_t *ru_session, const openair0_config_t *oai, const size_t num_rus, char **result); +char *get_pm_content(const ru_session_t *ru_session, const char *active); + #endif /* CREATE_MPLANE_YANG_CONFIG_H */ diff --git a/radio/fhi_72/mplane/yang/get-yang.c b/radio/fhi_72/mplane/yang/get-yang.c index e06128846f..60131b34cf 100644 --- a/radio/fhi_72/mplane/yang/get-yang.c +++ b/radio/fhi_72/mplane/yang/get-yang.c @@ -116,7 +116,7 @@ bool load_yang_models(ru_session_t *ru_session, const char *buffer) 1) the yang models order is not good - the dependancy models have to be loaded first 2) earlier O-RAN yang versions (e.g. v4) is not properly defined (i.e. optional parameters should not be included by default) */ const char *yang_dir = YANG_MODELS; - const char *yang_models[] = {"ietf-interfaces", "iana-if-type", "ietf-ip", "iana-hardware", "ietf-hardware", "o-ran-interfaces", "o-ran-module-cap", "o-ran-compression-factors", "o-ran-processing-element", "o-ran-uplane-conf"}; + const char *yang_models[] = {"ietf-interfaces", "iana-if-type", "ietf-ip", "iana-hardware", "ietf-hardware", "o-ran-interfaces", "o-ran-module-cap", "o-ran-compression-factors", "o-ran-processing-element", "o-ran-uplane-conf", "ietf-netconf-acm", "ietf-crypto-types", "o-ran-file-management", "o-ran-performance-management"}; #ifdef MPLANE_V1 *ctx = ly_ctx_new(yang_dir, 0); diff --git a/radio/fhi_72/mplane/yang/models/ietf-crypto-types.yang b/radio/fhi_72/mplane/yang/models/ietf-crypto-types.yang new file mode 100644 index 0000000000..1b94b03176 --- /dev/null +++ b/radio/fhi_72/mplane/yang/models/ietf-crypto-types.yang @@ -0,0 +1,1783 @@ +module ietf-crypto-types { + yang-version 1.1; + namespace "urn:ietf:params:xml:ns:yang:ietf-crypto-types"; + prefix ct; + + import ietf-yang-types { + prefix yang; + reference + "RFC 6991: Common YANG Data Types"; + } + + import ietf-netconf-acm { + prefix nacm; + reference + "RFC 8341: Network Configuration Access Control Model"; + } + + organization + "IETF NETCONF (Network Configuration) Working Group"; + + contact + "WG Web: + WG List: + Author: Kent Watsen + Author: Wang Haiguang "; + + description + "This module defines common YANG types for cryptographic + applications. + + Copyright (c) 2019 IETF Trust and the persons identified + as authors of the code. All rights reserved. + + Redistribution and use in source and binary forms, with + or without modification, is permitted pursuant to, and + subject to the license terms contained in, the Simplified + BSD License set forth in Section 4.c of the IETF Trust's + Legal Provisions Relating to IETF Documents + (https://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC XXXX + (https://www.rfc-editor.org/info/rfcXXXX); see the RFC + itself for full legal notices.; + + The key words 'MUST', 'MUST NOT', 'REQUIRED', 'SHALL', + 'SHALL NOT', 'SHOULD', 'SHOULD NOT', 'RECOMMENDED', + 'NOT RECOMMENDED', 'MAY', and 'OPTIONAL' in this document + are to be interpreted as described in BCP 14 (RFC 2119) + (RFC 8174) when, and only when, they appear in all + capitals, as shown here."; + + revision 2019-04-29 { + description + "Initial version"; + reference + "RFC XXXX: Common YANG Data Types for Cryptography"; + } + + /**************************************/ + /* Identities for Hash Algorithms */ + /**************************************/ + + identity hash-algorithm { + description + "A base identity for hash algorithm verification."; + } + + identity sha-224 { + base hash-algorithm; + description + "The SHA-224 algorithm."; + reference + "RFC 6234: US Secure Hash Algorithms."; + } + identity sha-256 { + base hash-algorithm; + description + "The SHA-256 algorithm."; + reference + "RFC 6234: US Secure Hash Algorithms."; + } + + identity sha-384 { + base hash-algorithm; + description + "The SHA-384 algorithm."; + reference + "RFC 6234: US Secure Hash Algorithms."; + } + + identity sha-512 { + base hash-algorithm; + description + "The SHA-512 algorithm."; + reference + "RFC 6234: US Secure Hash Algorithms."; + } + + /***********************************************/ + /* Identities for Asymmetric Key Algorithms */ + /***********************************************/ + + identity asymmetric-key-algorithm { + description + "Base identity from which all asymmetric key + encryption Algorithm."; + } + + identity rsa1024 { + base asymmetric-key-algorithm; + description + "The RSA algorithm using a 1024-bit key."; + reference + "RFC 8017: + PKCS #1: RSA Cryptography Specifications Version 2.2."; + } + + identity rsa2048 { + base asymmetric-key-algorithm; + description + "The RSA algorithm using a 2048-bit key."; + reference + "RFC 8017: + PKCS #1: RSA Cryptography Specifications Version 2.2."; + } + + identity rsa3072 { + base asymmetric-key-algorithm; + description + "The RSA algorithm using a 3072-bit key."; + reference + "RFC 8017: + PKCS #1: RSA Cryptography Specifications Version 2.2."; + } + + identity rsa4096 { + base asymmetric-key-algorithm; + description + "The RSA algorithm using a 4096-bit key."; + reference + "RFC 8017: + PKCS #1: RSA Cryptography Specifications Version 2.2."; + } + + identity rsa7680 { + base asymmetric-key-algorithm; + description + "The RSA algorithm using a 7680-bit key."; + reference + "RFC 8017: + PKCS #1: RSA Cryptography Specifications Version 2.2."; + } + + identity rsa15360 { + base asymmetric-key-algorithm; + description + "The RSA algorithm using a 15360-bit key."; + reference + "RFC 8017: + PKCS #1: RSA Cryptography Specifications Version 2.2."; + } + + identity secp192r1 { + base asymmetric-key-algorithm; + description + "The ECDSA algorithm using a NIST P256 Curve."; + reference + "RFC 6090: + Fundamental Elliptic Curve Cryptography Algorithms."; + } + identity secp224r1 { + base asymmetric-key-algorithm; + description + "The ECDSA algorithm using a NIST P256 Curve."; + reference + "RFC 6090: + Fundamental Elliptic Curve Cryptography Algorithms."; + } + + identity secp256r1 { + base asymmetric-key-algorithm; + description + "The ECDSA algorithm using a NIST P256 Curve."; + reference + "RFC 6090: + Fundamental Elliptic Curve Cryptography Algorithms."; + } + + identity secp384r1 { + base asymmetric-key-algorithm; + description + "The ECDSA algorithm using a NIST P256 Curve."; + reference + "RFC 6090: + Fundamental Elliptic Curve Cryptography Algorithms."; + } + + identity secp521r1 { + base asymmetric-key-algorithm; + description + "The ECDSA algorithm using a NIST P256 Curve."; + reference + "RFC 6090: + Fundamental Elliptic Curve Cryptography Algorithms."; + } + + /*************************************/ + /* Identities for MAC Algorithms */ + /*************************************/ + + identity mac-algorithm { + description + "A base identity for mac generation."; + } + + identity hmac-sha1 { + base mac-algorithm; + description + "Generating MAC using SHA1 hash function"; + reference + "RFC 3174: US Secure Hash Algorithm 1 (SHA1)"; + } + + identity hmac-sha1-96 { + base mac-algorithm; + description + "Generating MAC using SHA1 hash function"; + reference + "RFC 2404: The Use of HMAC-SHA-1-96 within ESP and AH"; + } + + identity hmac-sha2-224 { + base mac-algorithm; + description + "Generating MAC using SHA2 hash function"; + reference + "RFC 6234: + US Secure Hash Algorithms (SHA and SHA-based HMAC and + HKDF)"; + } + + identity hmac-sha2-256 { + base mac-algorithm; + description + "Generating MAC using SHA2 hash function"; + reference + "RFC 6234: + US Secure Hash Algorithms (SHA and SHA-based HMAC and + HKDF)"; + } + + identity hmac-sha2-256-128 { + base mac-algorithm; + description + "Generating a 256 bits MAC using SHA2 hash function and + truncate it to 128 bits"; + reference + "RFC 4868: + Using HMAC-SHA-256, HMAC-SHA-384, and HMAC-SHA-512 + with IPsec"; + } + + identity hmac-sha2-384 { + base mac-algorithm; + description + "Generating MAC using SHA2 hash function"; + reference + "RFC 6234: + US Secure Hash Algorithms (SHA and SHA-based HMAC and + HKDF)"; + } + + identity hmac-sha2-384-192 { + base mac-algorithm; + description + "Generating a 384 bits MAC using SHA2 hash function and + truncate it to 192 bits"; + reference + "RFC 4868: + Using HMAC-SHA-256, HMAC-SHA-384, and HMAC-SHA-512 with + IPsec"; + } + + identity hmac-sha2-512 { + base mac-algorithm; + description + "Generating MAC using SHA2 hash function"; + reference + "RFC 6234: + US Secure Hash Algorithms (SHA and SHA-based HMAC and + HKDF)"; + } + + identity hmac-sha2-512-256 { + base mac-algorithm; + description + "Generating a 512 bits MAC using SHA2 hash function and + truncating it to 256 bits"; + reference + "RFC 4868: + Using HMAC-SHA-256, HMAC-SHA-384, and HMAC-SHA-512 with + IPsec"; + } + + identity aes-128-gmac { + base mac-algorithm; + description + "Generating MAC using the Advanced Encryption Standard (AES) + Galois Message Authentication Code (GMAC) as a mechanism to + provide data origin authentication"; + reference + "RFC 4543: + The Use of Galois Message Authentication Code (GMAC) in + IPsec ESP and AH"; + } + + identity aes-192-gmac { + base mac-algorithm; + description + "Generating MAC using the Advanced Encryption Standard (AES) + Galois Message Authentication Code (GMAC) as a mechanism to + provide data origin authentication"; + reference + "RFC 4543: + The Use of Galois Message Authentication Code (GMAC) in + IPsec ESP and AH"; + } + + identity aes-256-gmac { + base mac-algorithm; + description + "Generating MAC using the Advanced Encryption Standard (AES) + Galois Message Authentication Code (GMAC) as a mechanism to + provide data origin authentication"; + reference + "RFC 4543: + The Use of Galois Message Authentication Code (GMAC) in + IPsec ESP and AH"; + } + + identity aes-cmac-96 { + base mac-algorithm; + description + "Generating MAC using Advanced Encryption Standard (AES) + Cipher-based Message Authentication Code (CMAC)"; + reference + "RFC 4494: The AES-CMAC-96 Algorithm and its Use with IPsec"; + } + + identity aes-cmac-128 { + base mac-algorithm; + description + "Generating MAC using Advanced Encryption Standard (AES) + Cipher-based Message Authentication Code (CMAC)"; + reference + "RFC 4493: The AES-CMAC Algorithm"; + } + + /********************************************/ + /* Identities for Encryption Algorithms */ + /********************************************/ + + identity encryption-algorithm { + description + "A base identity for encryption algorithm."; + } + + identity aes-128-cbc { + base encryption-algorithm; + description + "Encrypt message with AES algorithm in CBC mode with a key + length of 128 bits"; + reference + "RFC 3565: + Use of the Advanced Encryption Standard (AES) Encryption + Algorithm in Cryptographic Message Syntax (CMS)"; + } + + identity aes-192-cbc { + base encryption-algorithm; + description + "Encrypt message with AES algorithm in CBC mode with a key + length of 192 bits"; + reference + "RFC 3565: + Use of the Advanced Encryption Standard (AES) Encryption + Algorithm in Cryptographic Message Syntax (CMS)"; + } + + identity aes-256-cbc { + base encryption-algorithm; + description + "Encrypt message with AES algorithm in CBC mode with a key + length of 256 bits"; + reference + "RFC 3565: + Use of the Advanced Encryption Standard (AES) Encryption + Algorithm in Cryptographic Message Syntax (CMS)"; + } + + identity aes-128-ctr { + base encryption-algorithm; + description + "Encrypt message with AES algorithm in CTR mode with a key + length of 128 bits"; + reference + "RFC 3686: + Using Advanced Encryption Standard (AES) Counter Mode with + IPsec Encapsulating Security Payload (ESP)"; + } + identity aes-192-ctr { + base encryption-algorithm; + description + "Encrypt message with AES algorithm in CTR mode with a key + length of 192 bits"; + reference + "RFC 3686: + Using Advanced Encryption Standard (AES) Counter Mode with + IPsec Encapsulating Security Payload (ESP)"; + } + + identity aes-256-ctr { + base encryption-algorithm; + description + "Encrypt message with AES algorithm in CTR mode with a key + length of 256 bits"; + reference + "RFC 3686: + Using Advanced Encryption Standard (AES) Counter Mode with + IPsec Encapsulating Security Payload (ESP)"; + } + + /****************************************************/ + /* Identities for Encryption and MAC Algorithms */ + /****************************************************/ + + identity encryption-and-mac-algorithm { + description + "A base identity for encryption and MAC algorithm."; + } + + identity aes-128-ccm { + base encryption-and-mac-algorithm; + description + "Encrypt message with AES algorithm in CCM mode with a key + length of 128 bits; it can also be used for generating MAC"; + reference + "RFC 4309: + Using Advanced Encryption Standard (AES) CCM Mode with + IPsec Encapsulating Security Payload (ESP)"; + } + + identity aes-192-ccm { + base encryption-and-mac-algorithm; + description + "Encrypt message with AES algorithm in CCM mode with a key + length of 192 bits; it can also be used for generating MAC"; + reference + "RFC 4309: + Using Advanced Encryption Standard (AES) CCM Mode with + IPsec Encapsulating Security Payload (ESP)"; + } + + identity aes-256-ccm { + base encryption-and-mac-algorithm; + description + "Encrypt message with AES algorithm in CCM mode with a key + length of 256 bits; it can also be used for generating MAC"; + reference + "RFC 4309: + Using Advanced Encryption Standard (AES) CCM Mode with + IPsec Encapsulating Security Payload (ESP)"; + } + + identity aes-128-gcm { + base encryption-and-mac-algorithm; + description + "Encrypt message with AES algorithm in GCM mode with a key + length of 128 bits; it can also be used for generating MAC"; + reference + "RFC 4106: + The Use of Galois/Counter Mode (GCM) in IPsec Encapsulating + Security Payload (ESP)"; + } + + identity aes-192-gcm { + base encryption-and-mac-algorithm; + description + "Encrypt message with AES algorithm in GCM mode with a key + length of 192 bits; it can also be used for generating MAC"; + reference + "RFC 4106: + The Use of Galois/Counter Mode (GCM) in IPsec Encapsulating + Security Payload (ESP)"; + } + + identity mac-aes-256-gcm { + base encryption-and-mac-algorithm; + description + "Encrypt message with AES algorithm in GCM mode with a key + length of 128 bits; it can also be used for generating MAC"; + reference + "RFC 4106: + The Use of Galois/Counter Mode (GCM) in IPsec Encapsulating + Security Payload (ESP)"; + } + identity chacha20-poly1305 { + base encryption-and-mac-algorithm; + description + "Encrypt message with chacha20 algorithm and generate MAC with + POLY1305; it can also be used for generating MAC"; + reference + "RFC 8439: ChaCha20 and Poly1305 for IETF Protocols"; + } + + /******************************************/ + /* Identities for signature algorithm */ + /******************************************/ + + identity signature-algorithm { + description + "A base identity for asymmetric key encryption algorithm."; + } + + identity dsa-sha1 { + base signature-algorithm; + description + "The signature algorithm using DSA algorithm with SHA1 hash + algorithm"; + reference + "RFC 4253: The Secure Shell (SSH) Transport Layer Protocol"; + } + + identity rsassa-pkcs1-sha1 { + base signature-algorithm; + description + "The signature algorithm using RSASSA-PKCS1-v1_5 with the SHA1 + hash algorithm."; + reference + "RFC 4253: The Secure Shell (SSH) Transport Layer Protocol"; + } + + identity rsassa-pkcs1-sha256 { + base signature-algorithm; + description + "The signature algorithm using RSASSA-PKCS1-v1_5 with the + SHA256 hash algorithm."; + reference + "RFC 8332: + Use of RSA Keys with SHA-256 and SHA-512 in the Secure Shell + (SSH) Protocol + RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + identity rsassa-pkcs1-sha384 { + base signature-algorithm; + description + "The signature algorithm using RSASSA-PKCS1-v1_5 with the + SHA384 hash algorithm."; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity rsassa-pkcs1-sha512 { + base signature-algorithm; + description + "The signature algorithm using RSASSA-PKCS1-v1_5 with the + SHA512 hash algorithm."; + reference + "RFC 8332: + Use of RSA Keys with SHA-256 and SHA-512 in the Secure Shell + (SSH) Protocol + RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity rsassa-pss-rsae-sha256 { + base signature-algorithm; + description + "The signature algorithm using RSASSA-PSS with mask generation + function 1 and SHA256 hash algorithm. If the public key is + carried in an X.509 certificate, it MUST use the rsaEncryption + OID"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity rsassa-pss-rsae-sha384 { + base signature-algorithm; + description + "The signature algorithm using RSASSA-PSS with mask generation + function 1 and SHA384 hash algorithm. If the public key is + carried in an X.509 certificate, it MUST use the rsaEncryption + OID"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity rsassa-pss-rsae-sha512 { + base signature-algorithm; + description + "The signature algorithm using RSASSA-PSS with mask generation + function 1 and SHA512 hash algorithm. If the public key is + carried in an X.509 certificate, it MUST use the rsaEncryption + OID"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity rsassa-pss-pss-sha256 { + base signature-algorithm; + description + "The signature algorithm using RSASSA-PSS with mask generation + function 1 and SHA256 hash algorithm. If the public key is + carried in an X.509 certificate, it MUST use the RSASSA-PSS + OID"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity rsassa-pss-pss-sha384 { + base signature-algorithm; + description + "The signature algorithm using RSASSA-PSS with mask generation + function 1 and SHA256 hash algorithm. If the public key is + carried in an X.509 certificate, it MUST use the RSASSA-PSS + OID"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity rsassa-pss-pss-sha512 { + base signature-algorithm; + description + "The signature algorithm using RSASSA-PSS with mask generation + function 1 and SHA256 hash algorithm. If the public key is + carried in an X.509 certificate, it MUST use the RSASSA-PSS + OID"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity ecdsa-secp256r1-sha256 { + base signature-algorithm; + description + "The signature algorithm using ECDSA with curve name secp256r1 + and SHA256 hash algorithm."; + reference + "RFC 5656: Elliptic Curve Algorithm Integration in the + Secure Shell Transport Layer + RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity ecdsa-secp384r1-sha384 { + base signature-algorithm; + description + "The signature algorithm using ECDSA with curve name secp384r1 + and SHA384 hash algorithm."; + reference + "RFC 5656: Elliptic Curve Algorithm Integration in the + Secure Shell Transport Layer + RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity ecdsa-secp521r1-sha512 { + base signature-algorithm; + description + "The signature algorithm using ECDSA with curve name secp521r1 + and SHA512 hash algorithm."; + reference + "RFC 5656: Elliptic Curve Algorithm Integration in the + Secure Shell Transport Layer + RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity ed25519 { + base signature-algorithm; + description + "The signature algorithm using EdDSA as defined in RFC 8032 or + its successors."; + reference + "RFC 8032: Edwards-Curve Digital Signature Algorithm (EdDSA)"; + } + + identity ed448 { + base signature-algorithm; + description + "The signature algorithm using EdDSA as defined in RFC 8032 or + its successors."; + reference + "RFC 8032: Edwards-Curve Digital Signature Algorithm (EdDSA)"; + } + + identity eccsi { + base signature-algorithm; + description + "The signature algorithm using ECCSI signature as defined in + RFC 6507."; + reference + "RFC 6507: + Elliptic Curve-Based Certificateless Signatures for + Identity-based Encryption (ECCSI)"; + } + + /**********************************************/ + /* Identities for key exchange algorithms */ + /**********************************************/ + + identity key-exchange-algorithm { + description + "A base identity for Diffie-Hellman based key exchange + algorithm."; + } + + identity psk-only { + base key-exchange-algorithm; + description + "Using Pre-shared key for authentication and key exchange"; + reference + "RFC 4279: + Pre-Shared Key cipher suites for Transport Layer Security + (TLS)"; + } + + identity dhe-ffdhe2048 { + base key-exchange-algorithm; + description + "Ephemeral Diffie Hellman key exchange with 2048 bit + finite field"; + reference + "RFC 7919: + Negotiated Finite Field Diffie-Hellman Ephemeral Parameters + for Transport Layer Security (TLS)"; + } + + identity dhe-ffdhe3072 { + base key-exchange-algorithm; + description + "Ephemeral Diffie Hellman key exchange with 3072 bit finite + field"; + reference + "RFC 7919: + Negotiated Finite Field Diffie-Hellman Ephemeral Parameters + for Transport Layer Security (TLS)"; + } + + identity dhe-ffdhe4096 { + base key-exchange-algorithm; + description + "Ephemeral Diffie Hellman key exchange with 4096 bit + finite field"; + reference + "RFC 7919: + Negotiated Finite Field Diffie-Hellman Ephemeral Parameters + for Transport Layer Security (TLS)"; + } + + identity dhe-ffdhe6144 { + base key-exchange-algorithm; + description + "Ephemeral Diffie Hellman key exchange with 6144 bit + finite field"; + reference + "RFC 7919: + Negotiated Finite Field Diffie-Hellman Ephemeral Parameters + for Transport Layer Security (TLS)"; + } + + identity dhe-ffdhe8192 { + base key-exchange-algorithm; + description + "Ephemeral Diffie Hellman key exchange with 8192 bit + finite field"; + reference + "RFC 7919: + Negotiated Finite Field Diffie-Hellman Ephemeral Parameters + for Transport Layer Security (TLS)"; + } + + identity psk-dhe-ffdhe2048 { + base key-exchange-algorithm; + description + "Key exchange using pre-shared key with Diffie-Hellman key + generation mechanism, where the DH group is FFDHE2048"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity psk-dhe-ffdhe3072 { + base key-exchange-algorithm; + description + "Key exchange using pre-shared key with Diffie-Hellman key + generation mechanism, where the DH group is FFDHE3072"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity psk-dhe-ffdhe4096 { + base key-exchange-algorithm; + description + "Key exchange using pre-shared key with Diffie-Hellman key + generation mechanism, where the DH group is FFDHE4096"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity psk-dhe-ffdhe6144 { + base key-exchange-algorithm; + description + "Key exchange using pre-shared key with Diffie-Hellman key + generation mechanism, where the DH group is FFDHE6144"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity psk-dhe-ffdhe8192 { + base key-exchange-algorithm; + description + "Key exchange using pre-shared key with Diffie-Hellman key + generation mechanism, where the DH group is FFDHE8192"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity ecdhe-secp256r1 { + base key-exchange-algorithm; + description + "Ephemeral Diffie Hellman key exchange with elliptic group + over curve secp256r1"; + reference + "RFC 8422: + Elliptic Curve Cryptography (ECC) Cipher Suites for + Transport Layer Security (TLS) Versions 1.2 and Earlier"; + } + + identity ecdhe-secp384r1 { + base key-exchange-algorithm; + description + "Ephemeral Diffie Hellman key exchange with elliptic group + over curve secp384r1"; + reference + "RFC 8422: + Elliptic Curve Cryptography (ECC) Cipher Suites for + Transport Layer Security (TLS) Versions 1.2 and Earlier"; + } + + identity ecdhe-secp521r1 { + base key-exchange-algorithm; + description + "Ephemeral Diffie Hellman key exchange with elliptic group + over curve secp521r1"; + reference + "RFC 8422: + Elliptic Curve Cryptography (ECC) Cipher Suites for + Transport Layer Security (TLS) Versions 1.2 and Earlier"; + } + + identity ecdhe-x25519 { + base key-exchange-algorithm; + description + "Ephemeral Diffie Hellman key exchange with elliptic group + over curve x25519"; + reference + "RFC 8422: + Elliptic Curve Cryptography (ECC) Cipher Suites for + Transport Layer Security (TLS) Versions 1.2 and Earlier"; + } + + identity ecdhe-x448 { + base key-exchange-algorithm; + description + "Ephemeral Diffie Hellman key exchange with elliptic group + over curve x448"; + reference + "RFC 8422: + Elliptic Curve Cryptography (ECC) Cipher Suites for + Transport Layer Security (TLS) Versions 1.2 and Earlier"; + } + + identity psk-ecdhe-secp256r1 { + base key-exchange-algorithm; + description + "Key exchange using pre-shared key with elliptic group-based + Ephemeral Diffie Hellman key exchange over curve secp256r1"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity psk-ecdhe-secp384r1 { + base key-exchange-algorithm; + description + "Key exchange using pre-shared key with elliptic group-based + Ephemeral Diffie Hellman key exchange over curve secp384r1"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity psk-ecdhe-secp521r1 { + base key-exchange-algorithm; + description + "Key exchange using pre-shared key with elliptic group-based + Ephemeral Diffie Hellman key exchange over curve secp521r1"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity psk-ecdhe-x25519 { + base key-exchange-algorithm; + description + "Key exchange using pre-shared key with elliptic group-based + Ephemeral Diffie Hellman key exchange over curve x25519"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity psk-ecdhe-x448 { + base key-exchange-algorithm; + description + "Key exchange using pre-shared key with elliptic group-based + Ephemeral Diffie Hellman key exchange over curve x448"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity diffie-hellman-group14-sha1 { + base key-exchange-algorithm; + description + "Using DH group14 and SHA1 for key exchange"; + reference + "RFC 4253: The Secure Shell (SSH) Transport Layer Protocol"; + } + + identity diffie-hellman-group14-sha256 { + base key-exchange-algorithm; + description + "Using DH group14 and SHA256 for key exchange"; + reference + "RFC 8268: + More Modular Exponentiation (MODP) Diffie-Hellman (DH) + Key Exchange (KEX) Groups for Secure Shell (SSH)"; + } + + identity diffie-hellman-group15-sha512 { + base key-exchange-algorithm; + description + "Using DH group15 and SHA512 for key exchange"; + reference + "RFC 8268: + More Modular Exponentiation (MODP) Diffie-Hellman (DH) + Key Exchange (KEX) Groups for Secure Shell (SSH)"; + } + + identity diffie-hellman-group16-sha512 { + base key-exchange-algorithm; + description + "Using DH group16 and SHA512 for key exchange"; + reference + "RFC 8268: + More Modular Exponentiation (MODP) Diffie-Hellman (DH) + Key Exchange (KEX) Groups for Secure Shell (SSH)"; + } + + identity diffie-hellman-group17-sha512 { + base key-exchange-algorithm; + description + "Using DH group17 and SHA512 for key exchange"; + + reference + "RFC 8268: + More Modular Exponentiation (MODP) Diffie-Hellman (DH) + Key Exchange (KEX) Groups for Secure Shell (SSH)"; + } + + identity diffie-hellman-group18-sha512 { + base key-exchange-algorithm; + description + "Using DH group18 and SHA512 for key exchange"; + reference + "RFC 8268: + More Modular Exponentiation (MODP) Diffie-Hellman (DH) + Key Exchange (KEX) Groups for Secure Shell (SSH)"; + } + + identity ecdh-sha2-secp256r1 { + base key-exchange-algorithm; + description + "Elliptic curve-based Diffie Hellman key exchange over curve + secp256r1 and using SHA2 for MAC generation"; + reference + "RFC 6239: Suite B Cryptographic Suites for Secure Shell + (SSH)"; + } + + identity ecdh-sha2-secp384r1 { + base key-exchange-algorithm; + description + "Elliptic curve-based Diffie Hellman key exchange over curve + secp384r1 and using SHA2 for MAC generation"; + reference + "RFC 6239: Suite B Cryptographic Suites for Secure Shell + (SSH)"; + } + + identity rsaes-oaep { + base key-exchange-algorithm; + description + "RSAES-OAEP combines the RSAEP and RSADP primitives with the + EME-OAEP encoding method"; + reference + "RFC 8017: + PKCS #1: RSA Cryptography Specifications Version 2.2."; + } + + identity rsaes-pkcs1-v1_5 { + base key-exchange-algorithm; + description + " RSAES-PKCS1-v1_5 combines the RSAEP and RSADP primitives + with the EME-PKCS1-v1_5 encoding method"; + reference + "RFC 8017: + PKCS #1: RSA Cryptography Specifications Version 2.2."; + } + + /**********************************************************/ + /* Typedefs for identityrefs to above base identities */ + /**********************************************************/ + + typedef hash-algorithm-ref { + type identityref { + base hash-algorithm; + } + description + "This typedef enables importing modules to easily define an + identityref to the 'hash-algorithm' base identity."; + } + + typedef signature-algorithm-ref { + type identityref { + base signature-algorithm; + } + description + "This typedef enables importing modules to easily define an + identityref to the 'signature-algorithm' base identity."; + } + + typedef mac-algorithm-ref { + type identityref { + base mac-algorithm; + } + description + "This typedef enables importing modules to easily define an + identityref to the 'mac-algorithm' base identity."; + } + + typedef encryption-algorithm-ref { + type identityref { + base encryption-algorithm; + } + description + "This typedef enables importing modules to easily define an + identityref to the 'encryption-algorithm' + base identity."; + } + + typedef encryption-and-mac-algorithm-ref { + type identityref { + base encryption-and-mac-algorithm; + } + description + "This typedef enables importing modules to easily define an + identityref to the 'encryption-and-mac-algorithm' + base identity."; + } + + typedef asymmetric-key-algorithm-ref { + type identityref { + base asymmetric-key-algorithm; + } + description + "This typedef enables importing modules to easily define an + identityref to the 'asymmetric-key-algorithm' + base identity."; + } + + typedef key-exchange-algorithm-ref { + type identityref { + base key-exchange-algorithm; + } + description + "This typedef enables importing modules to easily define an + identityref to the 'key-exchange-algorithm' base identity."; + } + + /***************************************************/ + /* Typedefs for ASN.1 structures from RFC 5280 */ + /***************************************************/ + + typedef x509 { + type binary; + description + "A Certificate structure, as specified in RFC 5280, + encoded using ASN.1 distinguished encoding rules (DER), + as specified in ITU-T X.690."; + reference + "RFC 5280: + Internet X.509 Public Key Infrastructure Certificate + and Certificate Revocation List (CRL) Profile + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER)."; + } + + typedef crl { + type binary; + description + "A CertificateList structure, as specified in RFC 5280, + encoded using ASN.1 distinguished encoding rules (DER), + as specified in ITU-T X.690."; + reference + "RFC 5280: + Internet X.509 Public Key Infrastructure Certificate + and Certificate Revocation List (CRL) Profile + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER)."; + } + + /***********************************************/ + /* Typedefs for ASN.1 structures from 5652 */ + /***********************************************/ + + typedef cms { + type binary; + description + "A ContentInfo structure, as specified in RFC 5652, + encoded using ASN.1 distinguished encoding rules (DER), + as specified in ITU-T X.690."; + reference + "RFC 5652: + Cryptographic Message Syntax (CMS) + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER)."; + } + + typedef data-content-cms { + type cms; + description + "A CMS structure whose top-most content type MUST be the + data content type, as described by Section 4 in RFC 5652."; + reference + "RFC 5652: Cryptographic Message Syntax (CMS)"; + } + + typedef signed-data-cms { + type cms; + description + "A CMS structure whose top-most content type MUST be the + signed-data content type, as described by Section 5 in + RFC 5652."; + reference + "RFC 5652: Cryptographic Message Syntax (CMS)"; + } + + typedef enveloped-data-cms { + type cms; + description + "A CMS structure whose top-most content type MUST be the + enveloped-data content type, as described by Section 6 + in RFC 5652."; + reference + "RFC 5652: Cryptographic Message Syntax (CMS)"; + } + + typedef digested-data-cms { + type cms; + description + "A CMS structure whose top-most content type MUST be the + digested-data content type, as described by Section 7 + in RFC 5652."; + reference + "RFC 5652: Cryptographic Message Syntax (CMS)"; + } + + typedef encrypted-data-cms { + type cms; + description + "A CMS structure whose top-most content type MUST be the + encrypted-data content type, as described by Section 8 + in RFC 5652."; + reference + "RFC 5652: Cryptographic Message Syntax (CMS)"; + } + + typedef authenticated-data-cms { + type cms; + description + "A CMS structure whose top-most content type MUST be the + authenticated-data content type, as described by Section 9 + in RFC 5652."; + reference + "RFC 5652: Cryptographic Message Syntax (CMS)"; + } + + /***************************************************/ + /* Typedefs for structures related to RFC 4253 */ + /***************************************************/ + + typedef ssh-host-key { + type binary; + description + "The binary public key data for this SSH key, as + specified by RFC 4253, Section 6.6, i.e.: + + string certificate or public key format + identifier + byte[n] key/certificate data."; + reference + "RFC 4253: The Secure Shell (SSH) Transport Layer + Protocol"; + } + + /*********************************************************/ + /* Typedefs for ASN.1 structures related to RFC 5280 */ + /*********************************************************/ + + typedef trust-anchor-cert-x509 { + type x509; + description + "A Certificate structure that MUST encode a self-signed + root certificate."; + } + + typedef end-entity-cert-x509 { + type x509; + description + "A Certificate structure that MUST encode a certificate + that is neither self-signed nor having Basic constraint + CA true."; + } + + /*********************************************************/ + /* Typedefs for ASN.1 structures related to RFC 5652 */ + /*********************************************************/ + + typedef trust-anchor-cert-cms { + type signed-data-cms; + description + "A CMS SignedData structure that MUST contain the chain of + X.509 certificates needed to authenticate the certificate + presented by a client or end-entity. + + The CMS MUST contain only a single chain of certificates. + The client or end-entity certificate MUST only authenticate + to last intermediate CA certificate listed in the chain. + + In all cases, the chain MUST include a self-signed root + certificate. In the case where the root certificate is + itself the issuer of the client or end-entity certificate, + only one certificate is present. + + This CMS structure MAY (as applicable where this type is + used) also contain suitably fresh (as defined by local + policy) revocation objects with which the device can + verify the revocation status of the certificates. + + This CMS encodes the degenerate form of the SignedData + structure that is commonly used to disseminate X.509 + certificates and revocation objects (RFC 5280)."; + reference + "RFC 5280: + Internet X.509 Public Key Infrastructure Certificate + and Certificate Revocation List (CRL) Profile."; + } + + typedef end-entity-cert-cms { + type signed-data-cms; + description + "A CMS SignedData structure that MUST contain the end + entity certificate itself, and MAY contain any number + of intermediate certificates leading up to a trust + anchor certificate. The trust anchor certificate + MAY be included as well. + + The CMS MUST contain a single end entity certificate. + The CMS MUST NOT contain any spurious certificates. + + This CMS structure MAY (as applicable where this type is + used) also contain suitably fresh (as defined by local + policy) revocation objects with which the device can + verify the revocation status of the certificates. + + This CMS encodes the degenerate form of the SignedData + structure that is commonly used to disseminate X.509 + certificates and revocation objects (RFC 5280)."; + reference + "RFC 5280: + Internet X.509 Public Key Infrastructure Certificate + and Certificate Revocation List (CRL) Profile."; + } + + /**********************************************/ + /* Groupings for keys and/or certificates */ + /**********************************************/ + + grouping public-key-grouping { + description + "A public key. + + The 'algorithm' and 'public-key' nodes are not + mandatory because they MAY be defined in . + Implementations SHOULD assert that these values are + either configured or that they exist in ."; + leaf algorithm { + nacm:default-deny-write; + type asymmetric-key-algorithm-ref; + must '../public-key'; + description + "Identifies the key's algorithm. More specifically, + this leaf specifies how the 'public-key' binary leaf + is encoded."; + reference + "RFC CCCC: Common YANG Data Types for Cryptography"; + } + leaf public-key { + nacm:default-deny-write; + type binary; + must '../algorithm'; + description + "A binary that contains the value of the public key. The + interpretation of the content is defined by the key + algorithm. For example, a DSA key is an integer, an RSA + key is represented as RSAPublicKey as defined in + RFC 8017, and an Elliptic Curve Cryptography (ECC) key + is represented using the 'publicKey' described in + RFC 5915."; + reference + "RFC 8017: Public-Key Cryptography Standards (PKCS) #1: + RSA Cryptography Specifications Version 2.2. + RFC 5915: Elliptic Curve Private Key Structure."; + } + } + + grouping asymmetric-key-pair-grouping { + description + "A private/public key pair. + The 'algorithm', 'public-key', and 'private-key' nodes are + not mandatory because they MAY be defined in . + Implementations SHOULD assert that these values are either + configured or that they exist in ."; + uses public-key-grouping; + leaf private-key { + nacm:default-deny-all; + type union { + type binary; + type enumeration { + enum permanently-hidden { + description + "The private key is inaccessible due to being + protected by the system (e.g., a cryptographic + hardware module). + + How such keys are backed-up and restored, if + at all, is implementation specific. + + Servers MUST fail any attempt by a client to + configure this value directly. This value is + not set by clients, but rather is set by the + 'generate-hidden-key' and 'install-hidden-key' + actions."; + } + } + } + must '../public-key'; + description + "A binary that contains the value of the private key. The + interpretation of the content is defined by the key + algorithm. For example, a DSA key is an integer, an RSA + key is represented as RSAPrivateKey as defined in + RFC 8017, and an Elliptic Curve Cryptography (ECC) key + is represented as ECPrivateKey as defined in RFC 5915."; + reference + "RFC 8017: Public-Key Cryptography Standards (PKCS) #1: + RSA Cryptography Specifications Version 2.2. + RFC 5915: Elliptic Curve Private Key Structure."; + } // private-key + + action generate-hidden-key { + nacm:default-deny-all; + description + "Requests the device to generate a hidden key using the + specified asymmetric key algorithm. This action is + used to request the system to generate a key that is + 'permanently-hidden', perhaps protected by a cryptographic + hardware module. The resulting asymmetric key values are + considered operational state and hence present only in + and bound to the lifetime of the parent + 'config true' node. Subsequent invocations of this or + the 'install-hidden-key' action are denied with error-tag + 'data-exists'."; + input { + leaf algorithm { + type asymmetric-key-algorithm-ref; + mandatory true; + description + "The algorithm to be used when generating the + asymmetric key."; + reference + "RFC CCCC: Common YANG Data Types for Cryptography"; + } + } + } // generate-hidden-key + + action install-hidden-key { + nacm:default-deny-all; + description + "Requests the device to load the specified values into + a hidden key. The resulting asymmetric key values are + considered operational state and hence present only in + and bound to the lifetime of the parent + 'config true' node. Subsequent invocations of this + or the 'generate-hidden-key' action are denied with + error-tag 'data-exists'."; + input { + leaf algorithm { + type asymmetric-key-algorithm-ref; + mandatory true; + description + "The algorithm to be used when generating the + asymmetric key."; + reference + "RFC CCCC: Common YANG Data Types for Cryptography"; + } + leaf public-key { + type binary; + description + "A binary that contains the value of the public key. + The interpretation of the content is defined by the key + algorithm. For example, a DSA key is an integer, an + RSA key is represented as RSAPublicKey as defined in + RFC 8017, and an Elliptic Curve Cryptography (ECC) key + is represented using the 'publicKey' described in + RFC 5915."; + reference + "RFC 8017: Public-Key Cryptography Standards (PKCS) #1: + RSA Cryptography Specifications Version 2.2. + RFC 5915: Elliptic Curve Private Key Structure."; + } + leaf private-key { + type binary; + description + "A binary that contains the value of the private key. + The interpretation of the content is defined by the key + algorithm. For example, a DSA key is an integer, an RSA + key is represented as RSAPrivateKey as defined in + RFC 8017, and an Elliptic Curve Cryptography (ECC) key + is represented as ECPrivateKey as defined in RFC 5915."; + reference + "RFC 8017: Public-Key Cryptography Standards (PKCS) #1: + RSA Cryptography Specifications Version 2.2. + RFC 5915: Elliptic Curve Private Key Structure."; + } + } + } // install-hidden-key + } // asymmetric-key-pair-grouping + + + grouping trust-anchor-cert-grouping { + description + "A trust anchor certificate, and a notification for when + it is about to (or already has) expire."; + leaf cert { + nacm:default-deny-write; + type trust-anchor-cert-cms; + description + "The binary certificate data for this certificate."; + reference + "RFC YYYY: Common YANG Data Types for Cryptography"; + } + notification certificate-expiration { + description + "A notification indicating that the configured certificate + is either about to expire or has already expired. When to + send notifications is an implementation specific decision, + but it is RECOMMENDED that a notification be sent once a + month for 3 months, then once a week for four weeks, and + then once a day thereafter until the issue is resolved."; + leaf expiration-date { + type yang:date-and-time; + mandatory true; + description + "Identifies the expiration date on the certificate."; + } + } + } + + grouping trust-anchor-certs-grouping { + description + "A list of trust anchor certificates, and a notification + for when one is about to (or already has) expire."; + leaf-list cert { + nacm:default-deny-write; + type trust-anchor-cert-cms; + description + "The binary certificate data for this certificate."; + reference + "RFC YYYY: Common YANG Data Types for Cryptography"; + } + notification certificate-expiration { + description + "A notification indicating that the configured certificate + is either about to expire or has already expired. When to + send notifications is an implementation specific decision, + but it is RECOMMENDED that a notification be sent once a + month for 3 months, then once a week for four weeks, and + then once a day thereafter until the issue is resolved."; + leaf expiration-date { + type yang:date-and-time; + mandatory true; + description + "Identifies the expiration date on the certificate."; + } + } + } + + grouping end-entity-cert-grouping { + description + "An end entity certificate, and a notification for when + it is about to (or already has) expire."; + leaf cert { + nacm:default-deny-write; + type end-entity-cert-cms; + description + "The binary certificate data for this certificate."; + reference + "RFC YYYY: Common YANG Data Types for Cryptography"; + } + notification certificate-expiration { + description + "A notification indicating that the configured certificate + is either about to expire or has already expired. When to + send notifications is an implementation specific decision, + but it is RECOMMENDED that a notification be sent once a + month for 3 months, then once a week for four weeks, and + then once a day thereafter until the issue is resolved."; + leaf expiration-date { + type yang:date-and-time; + mandatory true; + description + "Identifies the expiration date on the certificate."; + } + } + } + + grouping end-entity-certs-grouping { + description + "A list of end entity certificates, and a notification for + when one is about to (or already has) expire."; + leaf-list cert { + nacm:default-deny-write; + type end-entity-cert-cms; + description + "The binary certificate data for this certificate."; + reference + "RFC YYYY: Common YANG Data Types for Cryptography"; + } + notification certificate-expiration { + description + "A notification indicating that the configured certificate + is either about to expire or has already expired. When to + send notifications is an implementation specific decision, + but it is RECOMMENDED that a notification be sent once a + month for 3 months, then once a week for four weeks, and + then once a day thereafter until the issue is resolved."; + leaf expiration-date { + type yang:date-and-time; + mandatory true; + description + "Identifies the expiration date on the certificate."; + } + } + } + + grouping asymmetric-key-pair-with-cert-grouping { + description + "A private/public key pair and an associated certificate."; + uses asymmetric-key-pair-grouping; + uses end-entity-cert-grouping; + + action generate-certificate-signing-request { + nacm:default-deny-all; + description + "Generates a certificate signing request structure for + the associated asymmetric key using the passed subject + and attribute values. The specified assertions need + to be appropriate for the certificate's use. For + example, an entity certificate for a TLS server + SHOULD have values that enable clients to satisfy + RFC 6125 processing."; + input { + leaf subject { + type binary; + mandatory true; + description + "The 'subject' field per the CertificationRequestInfo + structure as specified by RFC 2986, Section 4.1 + encoded using the ASN.1 distinguished encoding + rules (DER), as specified in ITU-T X.690."; + reference + "RFC 2986: + PKCS #10: Certification Request Syntax + Specification Version 1.7. + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER)."; + } + leaf attributes { + type binary; + description + "The 'attributes' field from the structure + CertificationRequestInfo as specified by RFC 2986, + Section 4.1 encoded using the ASN.1 distinguished + encoding rules (DER), as specified in ITU-T X.690."; + reference + "RFC 2986: + PKCS #10: Certification Request Syntax + Specification Version 1.7. + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER)."; + } + } + output { + leaf certificate-signing-request { + type binary; + mandatory true; + description + "A CertificationRequest structure as specified by + RFC 2986, Section 4.2 encoded using the ASN.1 + distinguished encoding rules (DER), as specified + in ITU-T X.690."; + reference + "RFC 2986: + PKCS #10: Certification Request Syntax + Specification Version 1.7. + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER)."; + } + } + } // generate-certificate-signing-request + } // asymmetric-key-pair-with-cert-grouping + + + grouping asymmetric-key-pair-with-certs-grouping { + description + "A private/public key pair and associated certificates."; + uses asymmetric-key-pair-grouping; + container certificates { + nacm:default-deny-write; + description + "Certificates associated with this asymmetric key. + More than one certificate supports, for instance, + a TPM-protected asymmetric key that has both IDevID + and LDevID certificates associated."; + list certificate { + key "name"; + description + "A certificate for this asymmetric key."; + leaf name { + type string; + description + "An arbitrary name for the certificate. If the name + matches the name of a certificate that exists + independently in (i.e., an IDevID), + then the 'cert' node MUST NOT be configured."; + } + uses end-entity-cert-grouping; + } + } // certificates + + action generate-certificate-signing-request { + nacm:default-deny-all; + description + "Generates a certificate signing request structure for + the associated asymmetric key using the passed subject + and attribute values. The specified assertions need + to be appropriate for the certificate's use. For + example, an entity certificate for a TLS server + SHOULD have values that enable clients to satisfy + RFC 6125 processing."; + input { + leaf subject { + type binary; + mandatory true; + description + "The 'subject' field per the CertificationRequestInfo + structure as specified by RFC 2986, Section 4.1 + encoded using the ASN.1 distinguished encoding + rules (DER), as specified in ITU-T X.690."; + reference + "RFC 2986: + PKCS #10: Certification Request Syntax + Specification Version 1.7. + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER)."; + } + leaf attributes { + type binary; + description + "The 'attributes' field from the structure + CertificationRequestInfo as specified by RFC 2986, + Section 4.1 encoded using the ASN.1 distinguished + encoding rules (DER), as specified in ITU-T X.690."; + reference + "RFC 2986: + PKCS #10: Certification Request Syntax + Specification Version 1.7. + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER)."; + } + } + output { + leaf certificate-signing-request { + type binary; + mandatory true; + description + "A CertificationRequest structure as specified by + RFC 2986, Section 4.2 encoded using the ASN.1 + distinguished encoding rules (DER), as specified + in ITU-T X.690."; + reference + "RFC 2986: + PKCS #10: Certification Request Syntax + Specification Version 1.7. + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER)."; + } + } + } // generate-certificate-signing-request + } // asymmetric-key-pair-with-certs-grouping +} diff --git a/radio/fhi_72/mplane/yang/models/ietf-netconf-acm.yang b/radio/fhi_72/mplane/yang/models/ietf-netconf-acm.yang new file mode 100644 index 0000000000..ec9687a9d7 --- /dev/null +++ b/radio/fhi_72/mplane/yang/models/ietf-netconf-acm.yang @@ -0,0 +1,440 @@ +module ietf-netconf-acm { + + namespace "urn:ietf:params:xml:ns:yang:ietf-netconf-acm"; + + prefix nacm; + + import ietf-yang-types { + prefix yang; + } + + organization + "IETF NETCONF (Network Configuration) Working Group"; + + contact + "WG Web: + WG List: + Author: Andy Bierman + + Author: Martin Bjorklund + "; + + description + "Network Configuration Access Control Model. + Copyright (c) 2012 - 2018 IETF Trust and the persons + identified as authors of the code. All rights reserved. + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject + to the license terms contained in, the Simplified BSD + License set forth in Section 4.c of the IETF Trust's + Legal Provisions Relating to IETF Documents + (https://trustee.ietf.org/license-info). + This version of this YANG module is part of RFC 8341; see + the RFC itself for full legal notices."; + + revision "2018-02-14" { + description + "Added support for YANG 1.1 actions and notifications tied to + data nodes. Clarified how NACM extensions can be used by + other data models."; + reference + "RFC 8341: Network Configuration Access Control Model"; + } + + revision "2012-02-22" { + description + "Initial version."; + reference + "RFC 6536: Network Configuration Protocol (NETCONF) + Access Control Model"; + } + + /* + * Extension statements + */ + + extension default-deny-write { + description + "Used to indicate that the data model node + represents a sensitive security system parameter. + If present, the NETCONF server will only allow the designated + 'recovery session' to have write access to the node. An + explicit access control rule is required for all other users. + If the NACM module is used, then it must be enabled (i.e., + /nacm/enable-nacm object equals 'true'), or this extension + is ignored. + The 'default-deny-write' extension MAY appear within a data + definition statement. It is ignored otherwise."; + } + + extension default-deny-all { + description + "Used to indicate that the data model node + controls a very sensitive security system parameter. + If present, the NETCONF server will only allow the designated + 'recovery session' to have read, write, or execute access to + the node. An explicit access control rule is required for all + other users. + If the NACM module is used, then it must be enabled (i.e., + /nacm/enable-nacm object equals 'true'), or this extension + is ignored. + The 'default-deny-all' extension MAY appear within a data + definition statement, 'rpc' statement, or 'notification' + statement. It is ignored otherwise."; + } + + /* + * Derived types + */ + + typedef user-name-type { + type string { + length "1..max"; + } + description + "General-purpose username string."; + } + + typedef matchall-string-type { + type string { + pattern '\*'; + } + description + "The string containing a single asterisk '*' is used + to conceptually represent all possible values + for the particular leaf using this data type."; + } + + typedef access-operations-type { + type bits { + bit create { + description + "Any protocol operation that creates a + new data node."; + } + bit read { + description + "Any protocol operation or notification that + returns the value of a data node."; + } + bit update { + description + "Any protocol operation that alters an existing + data node."; + } + bit delete { + description + "Any protocol operation that removes a data node."; + } + bit exec { + description + "Execution access to the specified protocol operation."; + } + } + description + "Access operation."; + } + + typedef group-name-type { + type string { + length "1..max"; + pattern '[^\*].*'; + } + description + "Name of administrative group to which + users can be assigned."; + } + + typedef action-type { + type enumeration { + enum permit { + description + "Requested action is permitted."; + } + enum deny { + description + "Requested action is denied."; + } + } + description + "Action taken by the server when a particular + rule matches."; + } + + typedef node-instance-identifier { + type yang:xpath1.0; + description + "Path expression used to represent a special + data node, action, or notification instance-identifier + string. + A node-instance-identifier value is an + unrestricted YANG instance-identifier expression. + All the same rules as an instance-identifier apply, + except that predicates for keys are optional. If a key + predicate is missing, then the node-instance-identifier + represents all possible server instances for that key. + This XML Path Language (XPath) expression is evaluated in the + following context: + o The set of namespace declarations are those in scope on + the leaf element where this type is used. + o The set of variable bindings contains one variable, + 'USER', which contains the name of the user of the + current session. + o The function library is the core function library, but + note that due to the syntax restrictions of an + instance-identifier, no functions are allowed. + o The context node is the root node in the data tree. + The accessible tree includes actions and notifications tied + to data nodes."; + } + + /* + * Data definition statements + */ + + container nacm { + nacm:default-deny-all; + + description + "Parameters for NETCONF access control model."; + + leaf enable-nacm { + type boolean; + default "true"; + description + "Enables or disables all NETCONF access control + enforcement. If 'true', then enforcement + is enabled. If 'false', then enforcement + is disabled."; + } + + leaf read-default { + type action-type; + default "permit"; + description + "Controls whether read access is granted if + no appropriate rule is found for a + particular read request."; + } + + leaf write-default { + type action-type; + default "deny"; + description + "Controls whether create, update, or delete access + is granted if no appropriate rule is found for a + particular write request."; + } + + leaf exec-default { + type action-type; + default "permit"; + description + "Controls whether exec access is granted if no appropriate + rule is found for a particular protocol operation request."; + } + + leaf enable-external-groups { + type boolean; + default "true"; + description + "Controls whether the server uses the groups reported by the + NETCONF transport layer when it assigns the user to a set of + NACM groups. If this leaf has the value 'false', any group + names reported by the transport layer are ignored by the + server."; + } + + leaf denied-operations { + type yang:zero-based-counter32; + config false; + mandatory true; + description + "Number of times since the server last restarted that a + protocol operation request was denied."; + } + + leaf denied-data-writes { + type yang:zero-based-counter32; + config false; + mandatory true; + description + "Number of times since the server last restarted that a + protocol operation request to alter + a configuration datastore was denied."; + } + + leaf denied-notifications { + type yang:zero-based-counter32; + config false; + mandatory true; + description + "Number of times since the server last restarted that + a notification was dropped for a subscription because + access to the event type was denied."; + } + + container groups { + description + "NETCONF access control groups."; + + list group { + key name; + + description + "One NACM group entry. This list will only contain + configured entries, not any entries learned from + any transport protocols."; + + leaf name { + type group-name-type; + description + "Group name associated with this entry."; + } + + leaf-list user-name { + type user-name-type; + description + "Each entry identifies the username of + a member of the group associated with + this entry."; + } + } + } + + list rule-list { + key name; + ordered-by user; + description + "An ordered collection of access control rules."; + + leaf name { + type string { + length "1..max"; + } + description + "Arbitrary name assigned to the rule-list."; + } + leaf-list group { + type union { + type matchall-string-type; + type group-name-type; + } + description + "List of administrative groups that will be + assigned the associated access rights + defined by the 'rule' list. + The string '*' indicates that all groups apply to the + entry."; + } + + list rule { + key name; + ordered-by user; + description + "One access control rule. + Rules are processed in user-defined order until a match is + found. A rule matches if 'module-name', 'rule-type', and + 'access-operations' match the request. If a rule + matches, the 'action' leaf determines whether or not + access is granted."; + + leaf name { + type string { + length "1..max"; + } + description + "Arbitrary name assigned to the rule."; + } + + leaf module-name { + type union { + type matchall-string-type; + type string; + } + default "*"; + description + "Name of the module associated with this rule. + This leaf matches if it has the value '*' or if the + object being accessed is defined in the module with the + specified module name."; + } + choice rule-type { + description + "This choice matches if all leafs present in the rule + match the request. If no leafs are present, the + choice matches all requests."; + case protocol-operation { + leaf rpc-name { + type union { + type matchall-string-type; + type string; + } + description + "This leaf matches if it has the value '*' or if + its value equals the requested protocol operation + name."; + } + } + case notification { + leaf notification-name { + type union { + type matchall-string-type; + type string; + } + description + "This leaf matches if it has the value '*' or if its + value equals the requested notification name."; + } + } + + case data-node { + leaf path { + type node-instance-identifier; + mandatory true; + description + "Data node instance-identifier associated with the + data node, action, or notification controlled by + this rule. + Configuration data or state data + instance-identifiers start with a top-level + data node. A complete instance-identifier is + required for this type of path value. + The special value '/' refers to all possible + datastore contents."; + } + } + } + + leaf access-operations { + type union { + type matchall-string-type; + type access-operations-type; + } + default "*"; + description + "Access operations associated with this rule. + This leaf matches if it has the value '*' or if the + bit corresponding to the requested operation is set."; + } + + leaf action { + type action-type; + mandatory true; + description + "The access control action associated with the + rule. If a rule has been determined to match a + particular request, then this object is used + to determine whether to permit or deny the + request."; + } + + leaf comment { + type string; + description + "A textual description of the access rule."; + } + } + } + } +} diff --git a/radio/fhi_72/mplane/yang/models/o-ran-file-management.yang b/radio/fhi_72/mplane/yang/models/o-ran-file-management.yang new file mode 100644 index 0000000000..ee07645a44 --- /dev/null +++ b/radio/fhi_72/mplane/yang/models/o-ran-file-management.yang @@ -0,0 +1,213 @@ +module o-ran-file-management { + yang-version 1.1; + namespace "urn:o-ran:file-management:1.0"; + prefix "o-ran-file-mgmt"; + + import ietf-crypto-types { + prefix "ct"; + } + + + organization "O-RAN Alliance"; + + contact + "www.o-ran.org"; + + description + "This module defines the configuration and operations for handling upload. + + Copyright 2019 the O-RAN Alliance. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the above disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the above disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the Members of the O-RAN Alliance nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission."; + + revision "2019-07-03" { + description + "version 1.1.0 + + 1) backward compatible changes to correct sFTP Server Authentication . + 2) minor fixes according to lack of descriptions + 3) backward compatible changes to introduce groupings"; + + reference "ORAN-WG4.M.0-v01.00"; + } + + revision "2019-02-04" { + description + "version 1.0.0 + + 1) imported model from xRAN + 2) changed namespace and reference from xran to o-ran"; + + reference "ORAN-WG4.M.0-v01.00"; + } + + grouping file-path-grouping { + description "Complete logical path of the file to upload/download + (no wildcard is allowed) ex : /o-RAN/log/syslog.1"; + + leaf local-logical-file-path { + type string; + mandatory true; + description "Local logical file path"; + } + + leaf remote-file-path { + type string; + mandatory true; + description "URI specifying the remote-file-path on O-DU/NMS. + Format:sftp://@[:port]/path"; + } + } + + grouping output-status-grouping { + description "Status grouping"; + + leaf status { + type enumeration { + enum SUCCESS { + description "";} + enum FAILURE { + description "";} + } + description "Operation status"; + } + + leaf reject-reason { + when "../status = 'FAILURE'"; + type string; + description ""; + } + } + + grouping credential-information { + description "Type of authentication to use for SFTP upload or download."; + choice credentials { + case password { + container password { + presence true; + leaf password { + type string; + mandatory true; + description + "password needed for O-RU authentication."; + } + description + "password for O-RU authentication method in use"; + } + container server { + list keys { + key algorithm; + ordered-by user; + uses ct:public-key-grouping; + description + "List of allowed algorithms with its keys"; + } + description + "Key for sFTP server authentication"; + } + } + case certificate { + container certificate { + presence true; + description + "certificate authentication method in use"; + } + } + description ""; + } + } + + grouping retrieve-input { + description "Grouping for information retrieval RPC input"; + leaf logical-path { + type string; + mandatory true; + description "O-RAN unit of which the files are to be listed. + ex : O-RAN/log, o-RAN/PM, O-RAN/transceiver"; + } + leaf file-name-filter { + type string; + description "Filter which are to be applied on the result list of file names (* is allowed as wild-card)."; + } + } + + grouping retrieve-output { + description "Grouping for information retrieval RPC output"; + uses output-status-grouping; + leaf-list file-list { + when "../status = 'SUCCESS'"; + type string; + description "List of files in the unit with the filter applied."; + } + } + +// RPCs + + rpc file-upload { + description "File upload over SFTP from equipment to NETCONF client"; + input { + uses file-path-grouping; + uses credential-information; + } + output { + uses output-status-grouping; + } + } + + rpc retrieve-file-list { + description "List all the files in the logical O-RAN unit (* is allowed as wild-card)."; + input { + uses retrieve-input; + + } + output { + uses retrieve-output; + } + } + + notification file-upload-notification { + uses file-path-grouping; + uses output-status-grouping; + description ""; + } + + rpc file-download { + description + "Management plane triggered to generate the download file of O-RU."; + input { + uses file-path-grouping; + uses credential-information; + } + output { + uses output-status-grouping; + } + } + + notification file-download-event { + uses file-path-grouping; + uses output-status-grouping; + description ""; + } +} diff --git a/radio/fhi_72/mplane/yang/models/o-ran-performance-management.yang b/radio/fhi_72/mplane/yang/models/o-ran-performance-management.yang new file mode 100644 index 0000000000..fb8298f663 --- /dev/null +++ b/radio/fhi_72/mplane/yang/models/o-ran-performance-management.yang @@ -0,0 +1,1168 @@ +module o-ran-performance-management { + yang-version 1.1; + namespace "urn:o-ran:performance-management:1.0"; + prefix "o-ran-pm"; + + import ietf-yang-types { + prefix "yang-types"; + revision-date 2013-07-15; + } + + // import idetifier for O-RU + import ietf-hardware { + prefix "hw"; + } + + // import ietf-interface + import ietf-interfaces { + prefix "if"; + } + + // import ietf-inet-type + import ietf-inet-types { + prefix "inet"; + } + + // import port-number + import o-ran-interfaces { + prefix "o-ran-int"; + } + + // import ru-mac-address, o-du-mac-address and vlan-id + import o-ran-processing-element { + prefix "o-ran-elements"; + } + + import o-ran-file-management { + prefix "o-ran-fm"; + } + + import iana-hardware { + prefix ianahw; + } + + organization "O-RAN Alliance"; + + contact + "www.o-ran.org"; + + description + "This module defines the configuration for performance measurement for + transceiver and rx-window measurement objects. + + NOTE, whereas this YANG model may define support of schema nodes associated + with O-RU measurements as optional, the CU-Plane specification may further + specify whether, according to a particular version of the CU plane + specification, which specific measurements are mandatory to support + from an O-RU perspective. In such a situation, the definition of mandatory + performance counters in sub-section 7.1 of the CU-plane specification shall + take precedence. + + Copyright 2020 the O-RAN Alliance. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the above disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the above disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the Members of the O-RAN Alliance nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission."; + + revision "2020-04-17" { + description + "version 3.0.0 + + 1) updated top level model description concerning optionality of measurements + 2) added new rx window counters + 3) added new TX stats measurements + 4) added new EPE measurements + 5) fixed typo in enumeration - TX_POPWER + 6) introduced config false data indicating which type of measurmeents are supported"; + + reference "ORAN-WG4.M.0-v03.00"; + } + + revision "2019-07-03" { + description + "version 2.0.0 + + 1) added new measurement objects for QSFP + 2) backward compatible changes to correct sFTP Server Authentication. + 3) simplifying file management and authentication to reuse from o-ran-file-management module + 4) minor fixes according to lack of descriptions and reference + 5) added to descriptions to indicate applicability of leafs and Containers + to separate O-RAN use cases + 6) backward compatible changes to introduce groupings."; + + reference "ORAN-WG4.M.0-v02.00"; + } + + revision "2019-02-04" { + description + "version 1.0.0 + + 1) imported model from xRAN + 2) changed namespace and reference from xran to o-ran"; + + reference "ORAN-WG4.M.0-v01.00"; + } + + + feature GRANULARITY-TRANSPORT-MEASUREMENT { + description + "This feature indicates that the O-RU supports an optional object-unit TRANSPORT in rx-window-measurement."; + } + + feature GRANULARITY-EAXC-ID-MEASUREMENT { + description + "This feature indicates that the O-RU supports an optional object-unit EAXC_ID in rx-window-measurement."; + } + + grouping start-and-end-time { + description + "Definition for start and end time for an event"; + + leaf start-time { + type yang-types:date-and-time; + description + "Start time for measurement of object stats"; + } + leaf end-time { + type yang-types:date-and-time; + description + "End time for measurement of object stats"; + } + } + + grouping epe-measurement-result-grouping { + description + "energy, power and environmental measurement-result are listed for O-RU"; + + list epe-measurement-result { + key "object-unit-id"; + config false; + leaf object-unit-id { + type leafref { + path "/hw:hardware/hw:component/hw:class"; + } + + description + "the hardware component type is used for the object-unit-id for the + EPE measurements. For example, the object-unit-id will be set to + or-hw:O-RAN-RADIO if the measurement applies to the complete O-RU + self-contained sub-system. + + Other hardware-classes include: or-hw:O-RU-POWER-AMPLIFIER, + ianahw:power-supply, ianahw:fan, ianahw:cpu"; + } + leaf min { + type decimal64 { + fraction-digits 4; + } + + description + "minimum value for the measurment-object"; + } + leaf max { + type decimal64 { + fraction-digits 4; + } + description + "maximum value for the measurment-object"; + } + leaf average { + type decimal64 { + fraction-digits 4; + } + description + "average value of the measurement-object"; + } + } + } + + grouping transceiver-measurement-result-grouping { + description + "transceiver-measurement-result are listed per port-number"; + + list transceiver-measurement-result { + key "object-unit-id"; + config false; + leaf object-unit-id { + type leafref { + path "/if:interfaces/if:interface/o-ran-int:port-reference/o-ran-int:port-number"; + } + + description + "port-number is used for the object-unit-id for the + transceiver-measurement-result, for which object-unit is + PORT_NUMBER only"; + } + container min { + description + "minimum value with recorded time are included for the + measurement-object"; + + leaf value { + type decimal64 { + fraction-digits 4; + } + + description + "minimum value for the measurment-object"; + } + leaf time { + type yang-types:date-and-time; + + description + "recorded time for the minimum value"; + } + } + container max { + description + "maximum value with recorded time are included for the + measurement-object"; + + leaf value { + type decimal64 { + fraction-digits 4; + } + + description + "maximum value for the measurment-object"; + } + leaf time { + type yang-types:date-and-time; + + description + "recorded time for the maximum value"; + } + } + container first { + description + "first value with the recorded time are included for the + measurement-object"; + + leaf value { + type decimal64 { + fraction-digits 4; + } + + description + "first value of the measurement-object"; + } + leaf time { + type yang-types:date-and-time; + + description + "recorded time for the first value"; + } + } + container latest { + description + "latest value with the recorded time are included for the + measurement-object"; + + leaf value { + type decimal64 { + fraction-digits 4; + } + + description + "latest value of the measurement-object"; + } + leaf time { + type yang-types:date-and-time; + + description + "recorded time for the latest value"; + } + } + leaf-list frequeny-table { + type uint32; + + description + "frequency-table for the measurment-object are included per bin. + The configuration parameters for this frequency-table are defined + by bin-count, lower-bound and upper-bound"; + } + + description + "List of transceiver measurement results"; + } + } + + grouping rx-window-measurement-result-grouping{ + description + "Group of measurement reasults for rx window measurements"; + + choice object-unit-id { + config false; + case RU { + leaf name{ + type leafref { + path "/hw:hardware/hw:component/hw:name"; + } + + description + "the name of O-RU module or one of its child ports + in ietf-hardware/component is used when O-RU is selected as + object-unit for the reception window stats."; + } + leaf count { + type uint64; + mandatory true; + + description + "the number of data packet are counted for the reception + window stats per O-RU."; + } + } + + case TRANSPORT { + list tr-measured-result{ + leaf name{ + type leafref{ + path "/o-ran-elements:processing-elements/o-ran-elements:ru-elements/o-ran-elements:name"; + } + + description + "the name of ru-elements in o-ran-processing-elements + when TRANSPORT is selected as object-unit for the reception + window stats."; + } + leaf count { + type uint64; + mandatory true; + + description + "the number of data packet are counted for the reception + window stats."; + } + + description + "the number of data packet are counted for the reception + window stats per TRANSPORT."; + } + } + + case EAXC_ID { + list eaxc-measured-result { + leaf eaxc-id{ + type uint16; + + description + "eaxc-id is used + when EAXC_ID is selected as object-unit for the reception + window stats. + EAXC_ID consists of DU-Port-Id, Band-Selector, CC-id and + RU-Port-Id to be used in header of C/U-plane data packet."; + } + leaf count { + type uint64; + mandatory true; + + description + "the number of data packet are counted for the reception + window stats."; + } + leaf transport-name { + type leafref{ + path "/o-ran-elements:processing-elements/o-ran-elements:ru-elements/o-ran-elements:name"; + } + + description + "the name of ru-elements in o-ran-processing-elements for the + transport information corresponding to this eaxc-id"; + } + + description + "the number of data packet are counted for the reception + window stats per EAXC-ID."; + } + } + + description + "measurement-result for the reception window stats depends on the + configured object-unit, RU, TRANSPORT or EAXC_ID"; + } + } + + grouping tx-measurement-result-grouping{ + description + "Group of measurement reasults for tx stats"; + + choice object-unit-id { + config false; + case RU { + leaf name{ + type leafref { + path "/hw:hardware/hw:component/hw:name"; + } + + description + "the name of O-RU module or one of its child ports + in ietf-hardware/component is used when O-RU is selected as + object-unit for the reception window stats."; + } + leaf count { + type uint64; + mandatory true; + + description + "the number of data packet are counted for the tx stats per O-RU."; + } + } + + case TRANSPORT { + list tr-measured-result{ + leaf name{ + type leafref{ + path "/o-ran-elements:processing-elements/o-ran-elements:ru-elements/o-ran-elements:name"; + } + + description + "the name of ru-elements in o-ran-processing-elements + when TRANSPORT is selected as object-unit for the tx stats."; + } + leaf count { + type uint64; + mandatory true; + + description + "the number of data packet are counted for the tx stats."; + } + + description + "the number of data packet are counted for the tx stats per TRANSPORT."; + } + } + + case EAXC_ID { + list eaxc-measured-result { + leaf eaxc-id{ + type uint16; + + description + "eaxc-id is used + when EAXC_ID is selected as object-unit for the tx stats. + EAXC_ID consists of DU-Port-Id, Band-Selector, CC-id and + RU-Port-Id to be used in header of C/U-plane data packet."; + } + leaf count { + type uint64; + mandatory true; + + description + "the number of data packet are counted for the tx stats."; + } + leaf transport-name { + type leafref{ + path "/o-ran-elements:processing-elements/o-ran-elements:ru-elements/o-ran-elements:name"; + } + + description + "the name of ru-elements in o-ran-processing-elements for the + transport information corresponding to this eaxc-id"; + } + + description + "the number of data packet are counted for the tx stats per EAXC-ID."; + } + } + + description + "measurement-result for the tx stats depends on the + configured object-unit, RU, TRANSPORT or EAXC_ID"; + } + } + + + grouping measurement-group { + description + "Group of measurement results"; + + uses measurement-capabilities; + leaf enable-SFTP-upload { + type boolean; + default false; + description + "Flag to enable upload of performance measurement result files."; + } + + leaf enable-random-file-upload { + type boolean; + default false; + description + "Flag to enable upload of performance measurement result files at + random within file-upload-interval."; + } + + list remote-SFTP-uploads { + key remote-SFTP-upload-path; + description + "SFTP upload can be done to one or more than one SFTP servers"; + + leaf remote-SFTP-upload-path { + type inet:uri; + description + "URI specifying the remote location where the files are to uploaded. + The following format is possible: + sftp://@[:]/path"; + } + + uses o-ran-fm:credential-information; + } + +// transceiver measurements applicable to all O-RAN HW functions + + leaf transceiver-measurement-interval { + type uint16; + units seconds; + description + "measurement interval to measure the performance of transceiver + measurement objects periodically."; + } + +// EPE measurements applicable to all O-RAN HW functions + + leaf epe-measurement-interval { + type uint16; + units seconds; + description + "measurement interval to measure the energy, power and environmental + measurement objects periodically."; + } + +// RX Window measurements applicable to O-RAN WG4 defined functions + + leaf rx-window-measurement-interval { + type uint16; + units seconds; + description + "measurement interval to measure the performance of reception + window measurement objects periodically."; + } + + leaf tx-measurement-interval { + type uint16; + units seconds; + description + "measurement interval to measure the tx (outbound) + window measurement objects periodically."; + } + + leaf notification-interval { + type uint16; + units seconds; + description + "notification interval for the measurement result to be notified + periodically."; + } + + leaf file-upload-interval { + type uint16; + units seconds; + description + "file upload interval for the measurement result file to be + uploaded periodically."; + } + + leaf max-bin-count{ + type uint16; + config false; + mandatory true; + description + "indicates the maximum value of configurable bin-count for frequency + table in transceiver-measurement-objects as one of module + capabilities."; + } + + list transceiver-measurement-objects { + key "measurement-object"; + description + "optional list used to report transceiver measurements + applicable to any O-RAN defined hardware function"; + leaf measurement-object { + type enumeration { + enum RX_POWER { + description + "Measured Rx input power in mW for SFP or lane 1 of QSFP"; + } + enum RX_POWER_LANE_2 { + description + "Measured Rx input power in mW for lane 2 of QSFP"; + } + enum RX_POWER_LANE_3 { + description + "Measured Rx input power in mW for lane 3 of QSFP"; + } + enum RX_POWER_LANE_4 { + description + "Measured Rx input power in mW for lane 4 of QSFP"; + } + enum TX_POPWER { + status deprecated; + description + "Measured Tx input power in mW."; + } + enum TX_POWER { + description + "Measured Tx input power in mW."; + } + enum TX_POWER_LANE_2 { + description + "Measured Tx input power in mW for lane 2 of QSFP"; + } + enum TX_POWER_LANE_3 { + description + "Measured Tx input power in mW for lane 3 of QSFP"; + } + enum TX_POWER_LANE_4 { + description + "Measured Tx input power in mW for lane 4 of QSFP"; + } + enum TX_BIAS_COUNT { + description + "Internally measured Tx Bias Current in mA for SFP or lane 1 of QSFP"; + } + enum TX_BIAS_COUNT_LANE_2 { + description + "Internally measured Tx Bias Current in mA for lane 2 of QSFP"; + } + enum TX_BIAS_COUNT_LANE_3 { + description + "Internally measured Tx Bias Current in mA for lane 3 of QSFP"; + } + enum TX_BIAS_COUNT_LANE_4 { + description + "Internally measured Tx Bias Current in mA for lane 4 of QSFP"; + } + enum VOLTAGE { + description + "Internally measured transceiver supply voltage in mV"; + } + enum TEMPERATURE { + description + "Internally measured optional laser temperature in degrees Celsius."; + } + } + description "Target metric to measure the performance"; + } + + leaf active { + type boolean; + default false; + description + "Enable/disable the performance measurement per Object"; + } + + leaf-list report-info { + type enumeration { + enum MAXIMUM { + description + "to report maximum value and its recorded time within the + measurement-interval for the measurement-object."; + } + enum MINIMUM { + description + "to report minimum value and its recorded time within the + measurement-interval for the measurement-object."; + } + enum FIRST { + description + "to report first value and its recorded time within the + measurement-interval for the measurement-object."; + } + enum LATEST { + description + "to report latest value and its recorded time within the + measurement-interval for the measurement-object."; + } + enum FREQUENCY_TABLE { + description + "to report frequency bin table within the + measurement-interval for the measurement-object."; + } + } + description "The reporting info to the measurement object."; + } + + leaf object-unit { + type enumeration { + enum PORT_NUMBER { + description + "unit to measure the performance per object-id"; + } + } + mandatory true; + description "unit to measure the performance per object-id."; + } + + leaf function { + type enumeration { + enum RAW { + description + "the value is expressed by real value."; + } + enum LOG_10 { + description + "the value is expressed by logarithm with base 10."; + } + } + + description + "the value to be recorded for transceiver-measurement + by real value or log 10."; + } + + leaf bin-count { + type uint16; + + description + "the number of bin for the frequency table. + This value shall be less than max-bin-count"; + } + + leaf lower-bound { + type decimal64 { + fraction-digits 4; + } + + description + "the lower value of the first bin of frequency table."; + } + + leaf upper-bound { + type decimal64 { + fraction-digits 4; + } + + description + "the upper value of the last bin of frequency table."; + } + uses transceiver-measurement-result-grouping; +// configuration and measurement result for the transceiver-measurement + + } + + list rx-window-measurement-objects { + key "measurement-object"; + description + "optional list used to report RX Window measurements + applicable to O-RAN WG4 define O-RU functions"; + leaf measurement-object { + type enumeration { + enum RX_ON_TIME { + description + "the number of data packets, received on time within + the reception window."; + } + enum RX_EARLY { + description + "the number of data packets, received before + the reception window."; + } + enum RX_LATE { + description + "the number of data packets, received after + the reception window."; + } + enum RX_CORRUPT { + description + "the number of data packets, which are corrupt or whose header + is incorrect."; + } + enum RX_DUPL { + status deprecated; + description + "the number of data packets, which is duplicated with other packets, + received within the measurement period."; + } + enum RX_TOTAL { + description + "the total number of received packets (data and control) within the measurement period."; + } + enum RX_ON_TIME_C { + description + "the number of control packets, received on time within + the reception window."; + } + enum RX_EARLY_C { + description + "the number of control packets, received before + the reception window."; + } + enum RX_LATE_C { + description + "the number of control packets, received after + the reception window."; + } + enum RX_SEQID_ERR { + description + "the number of data packets, received with an erroneous sequence ID."; + } + enum RX_SEQID_ERR_C { + description + "the number of control packets, received with an erroneous sequence ID."; + } + enum RX_ERR_DROP { + description + "The total number of inbound messages which are discarded by the receiving + O-RAN entity for any reason."; + } + } + description + "target reception window metric to measure the performance."; + } + + leaf active { + type boolean; + default false; + description + "Enable/disable the performance measurement per reception window + measurement object."; + } + + leaf object-unit { + type enumeration { + enum RU { + description + "the reception window stats are counted per hardware component. + This may be the parent 'module' or child 'port' component."; + } + enum TRANSPORT { + if-feature GRANULARITY-TRANSPORT-MEASUREMENT; + description + "the reception window stats are counted per transport flow. + When there are multiple transport flows between O-DU and O-RU, + e.g. multiple sets of o-du mac address, ru mac address and + vlan-id, the reception window stats per transport flow + are counted in this case. + This configuration is allowed only when O-RU supports + a feature GRANULARITY-TRANSPORT-MEASUREMENT."; + } + enum EAXC_ID { + if-feature GRANULARITY-EAXC-ID-MEASUREMENT; + + description + "the reception window stats are counted per eAxC ID, which is + used in the header of receivd data packet. + This configuration is allowed only when O-RU supports + a feature GRANULARITY-EAXC-ID-MEASUREMENT."; + } + } + description + "unit to measure the performance per object-id."; + } + + leaf report-info { + type enumeration { + enum COUNT { + description + "the number of data packet are counted for the reception + window stats."; + } + } + description + "The reporting info to the measurement object."; + } + + uses rx-window-measurement-result-grouping; +// configuration and measurement result for the reception window stats + + } + + + list tx-measurement-objects { + key "measurement-object"; + description + "optional list used to report TX measurements + applicable to O-RAN WG4 define O-RU functions"; + leaf measurement-object { + type enumeration { + enum TX_TOTAL { + description + "the number of outbound packets (data and control), transmitted within + the measurement period"; + } + enum TX_TOTAL_C { + description + "the number of outbound control packets, transmitted within + the measurement period. + This counter is required only if RU supports LAA/LBT capabilities."; + } + } + description + "CU-plane transmission counters"; + } + + leaf active { + type boolean; + default false; + description + "Enable/disable the measurement per measurement object."; + } + + leaf object-unit { + type enumeration { + enum RU { + description + "the transmission stats are counted per hardware component. + This may be the parent 'module' or child 'port' component."; + } + enum TRANSPORT { + if-feature GRANULARITY-TRANSPORT-MEASUREMENT; + description + "the transmission stats are counted per transport flow. + When there are multiple transport flows between O-DU and O-RU, + e.g. multiple sets of o-du mac address, ru mac address and + vlan-id, the transmission stats per transport flow + are counted in this case. + This configuration is allowed only when O-RU supports + a feature GRANULARITY-TRANSPORT-MEASUREMENT."; + } + enum EAXC_ID { + if-feature GRANULARITY-EAXC-ID-MEASUREMENT; + + description + "the transmission stats are counted per eAxC ID, which is + used in the header of receivd data packet. + This configuration is allowed only when O-RU supports + a feature GRANULARITY-EAXC-ID-MEASUREMENT."; + } + } + description + "unit to measure the performance per object-id."; + } + + leaf report-info { + type enumeration { + enum COUNT { + description + "the number of data packet are counted for the reception + window stats."; + } + } + description + "The reporting info to the measurement object."; + } + + uses tx-measurement-result-grouping; + // configuration and measurement result for the tx stats + + } + + list epe-measurement-objects { + key "measurement-object"; + description + "optional list used to report energy, power and environmental + measurements applicable to any O-RAN defined hardware function"; + leaf measurement-object { + type enumeration { + enum TEMPERATURE { + description + "Measured temperature in degrees celcius"; + } + enum POWER { + description + "Measured power consumed, in watts (W)"; + } + } + description "Target metric to measure the performance"; + } + + leaf active { + type boolean; + default false; + description + "Enable/disable the performance measurement per Object"; + } + + leaf-list report-info { + type enumeration { + enum MAXIMUM { + description + "to report maximum value and its recorded time within the + measurement-interval for the measurement-object."; + } + enum MINIMUM { + description + "to report minimum value and its recorded time within the + measurement-interval for the measurement-object."; + } + enum AVERAGE { + description + "to report average value within the + measurement-interval for the measurement-object."; + } + } + description "The reporting info to the measurement object."; + } + + + uses epe-measurement-result-grouping; + // configuration and measurement result for the epe-measurement + + } + + + } + + grouping measurement-capabilities { + container measurement-capabilitites { + config false; + description "the type of measurement objects supported by the O-RU"; + + list transceiver-objects { + key measurement-object; + leaf measurement-object { + type leafref { + path "/performance-measurement-objects/transceiver-measurement-objects/measurement-object"; + } + } + } + list rx-window-objects { + key measurement-object; + leaf measurement-object { + type leafref { + path "/performance-measurement-objects/rx-window-measurement-objects/measurement-object"; + } + } + } + list tx-stats-objects { + key measurement-object; + leaf measurement-object { + type leafref { + path "/performance-measurement-objects/tx-measurement-objects/measurement-object"; + } + } + } + list epe-stats-objects { + key "measurement-object"; + description + "An optional list describing the energy, power and environmental measurements supported + by the O-RU. Measurements are defined per hardware component."; + leaf measurement-object { + type leafref { + path "/performance-measurement-objects/epe-measurement-objects/measurement-object"; + } + } + leaf-list component-class { + type identityref { + base ianahw:hardware-class; + } + description + "An indication of the general hardware type of the + component for which EPE measurements are supported."; + + } + } + } + } + + grouping measurement-notification { + list transceiver-stats { + key "measurement-object"; + leaf measurement-object { + type leafref { + path "/performance-measurement-objects/transceiver-measurement-objects/measurement-object"; + } + + description + "measurement-object for the transceiver-measurement"; + } + + uses start-and-end-time; + uses transceiver-measurement-result-grouping; + + description + "measurement result of transceiver-measurement per measurement-object"; + } + + list rx-window-stats { + key "measurement-object"; + leaf measurement-object { + type leafref { + path "/performance-measurement-objects/rx-window-measurement-objects/measurement-object"; + } + + description + "measurement-object for the reception window measurement"; + } + uses start-and-end-time; + uses rx-window-measurement-result-grouping; + + description + "measurement result for the reception window measurement per + measurement-object"; + + } + + list tx-stats { + key "measurement-object"; + leaf measurement-object { + type leafref { + path "/performance-measurement-objects/tx-measurement-objects/measurement-object"; + } + + description + "measurement-object for the tx stats measurement"; + } + uses start-and-end-time; + uses tx-measurement-result-grouping; + + description + "measurement result for the tx stats measurement per + measurement-object"; + + } + + container epe-stats { + description + "container for the epe stats measurement"; + + uses start-and-end-time; + uses epe-measurement-result-grouping; + + + } + + description + "notification may contain measurement result for transceiver-stats + and/or rx-window-stats"; + } + + // Top level container + + container performance-measurement-objects { + description + "configuration for performance management and measurement-result are + included"; + uses measurement-group; + } + +// Notifications + + notification measurement-result-stats { + description + "Notification may contain measurement results for transceiver-stats + and/or rx-window-stats"; + uses measurement-notification; + } +} diff --git a/radio/fhi_72/oran_isolate.c b/radio/fhi_72/oran_isolate.c index 4a141275d7..3bdbe1df12 100644 --- a/radio/fhi_72/oran_isolate.c +++ b/radio/fhi_72/oran_isolate.c @@ -338,6 +338,11 @@ __attribute__((__visibility__("default"))) int transport_init(openair0_device *d if (!ru_ready[i] && ru_session->ru_notif.config_change && ru_session->ru_notif.rx_carrier_state && ru_session->ru_notif.tx_carrier_state) { MP_LOG_I("RU \"%s\" is now ready.\n", ru_session->ru_ip_add); ru_ready[i] = true; + if (!ru_session->pm_stats.start_up_timing) { + success = pm_conf(ru_session, "true"); + if (success) + MP_LOG_I("Sucessfully activated PM after start-up procedure for RU \"%s\".\n", ru_session->ru_ip_add); + } } else { all_rus_ready = false; break; From 995cccc760989f25d5db580373a9784b60dee1bc Mon Sep 17 00:00:00 2001 From: Teodora Date: Thu, 24 Jul 2025 14:36:42 +0200 Subject: [PATCH 572/964] Update the FHI M-plane doc Performance Management support explanation. Example run modified according to: - modification of the frequency offset, frame structure, fft size, cyclic prefix, and Tx gain; - addition of the managed delay node; for Tx/Rx endpoints. --- doc/ORAN_FHI7.2_Tutorial.md | 249 +++++++++++++++++++++++++++++++----- 1 file changed, 219 insertions(+), 30 deletions(-) diff --git a/doc/ORAN_FHI7.2_Tutorial.md b/doc/ORAN_FHI7.2_Tutorial.md index a0fb30527e..1d7169f29f 100644 --- a/doc/ORAN_FHI7.2_Tutorial.md +++ b/doc/ORAN_FHI7.2_Tutorial.md @@ -1235,7 +1235,13 @@ You should be able to connect a UE now. # OAI Management Plane -We support Configuration Management in OAI gNB, where gNB configures CU-planes, interfaces, TX/RX antennas, and TX/RX carriers for the RU. +In OAI gNB, we support: +* Configuration Management: interface(s) creation, configuration of RU CU-planes, Tx/Rx antennas, and Tx/Rx carriers. +* Performance Management: activation/deactivation of available RU performance measurements and its notification reception with 10s periodicity: +```bash +[HW] [MPLANE] [PM: "192.168.80.9"][RX_ON_TIME 773428][RX_EARLY 0][RX_LATE 0][RX_TOTAL 878881][RX_ON_TIME_C 104744][RX_EARLY_C 0][RX_LATE_C 0][TX_TOTAL 435922] +``` + The reference specifications: * `O-RAN.WG4.MP.0-v05.00` * `O-RAN.WG4.MP-YANGs-v04.00` @@ -1560,7 +1566,9 @@ sequenceDiagram note over du: DU configures xran - du->ru: 12. DU and RU exchange packets + du->ru: 12. DU activates Performance Measurements + + du->ru: 13. DU and RU exchange packets ``` @@ -1599,7 +1607,9 @@ sequenceDiagram Band sector ID 0 CC ID 0 RU port ID 0 + max Tx gain 24.0 [HW] [MPLANE] Successfully retrieved all the U-plane info - interface name, TX/RX carrier names, and TX/RX endpoint names. +[HW] [MPLANE] Successfully retreived all performance measurement names. [HW] [MPLANE] RPC request to RU "192.168.80.9" = for module "ietf-yang-metadata". [HW] [MPLANE] RPC request to RU "192.168.80.9" = for module "yang". [HW] [MPLANE] RPC request to RU "192.168.80.9" = for module "ietf-inet-types". @@ -1639,6 +1649,59 @@ sequenceDiagram 9 + + 10 + 10 + 10 + + RX_ON_TIME + false + RU + COUNT + + + RX_EARLY + false + RU + COUNT + + + RX_LATE + false + RU + COUNT + + + RX_TOTAL + false + RU + COUNT + + + RX_ON_TIME_C + false + RU + COUNT + + + RX_EARLY_C + false + RU + COUNT + + + RX_LATE_C + false + RU + COUNT + + + TX_TOTAL + false + RU + COUNT + + ETH-INTERFACE @@ -1732,8 +1795,10 @@ sequenceDiagram 9 STATIC - 0 - 0 + 193 + NORMAL + 352 + 288 0 61440 @@ -1749,8 +1814,10 @@ sequenceDiagram 9 STATIC - 0 - 0 + 193 + NORMAL + 352 + 288 0 61440 @@ -1766,8 +1833,10 @@ sequenceDiagram 9 STATIC - 0 - 0 + 193 + NORMAL + 352 + 288 0 61440 @@ -1783,8 +1852,10 @@ sequenceDiagram 9 STATIC - 0 - 0 + 193 + NORMAL + 352 + 288 0 61440 @@ -1800,9 +1871,15 @@ sequenceDiagram 9 STATIC - 0 - 0 + 193 + NORMAL + 352 + 288 0 + + KHZ_30 + 0 + 61440 3840 @@ -1810,6 +1887,7 @@ sequenceDiagram 15 0 + true LowLevelRxPrachEndpoint0 @@ -1817,9 +1895,15 @@ sequenceDiagram 9 STATIC - 0 - 0 + 193 + NORMAL + 352 + 288 0 + + KHZ_30 + 0 + 61440 3840 @@ -1827,6 +1911,7 @@ sequenceDiagram 15 4 + true LowLevelRxEndpoint1 @@ -1834,9 +1919,15 @@ sequenceDiagram 9 STATIC - 0 - 0 + 193 + NORMAL + 352 + 288 0 + + KHZ_30 + 0 + 61440 3840 @@ -1844,6 +1935,7 @@ sequenceDiagram 15 1 + true LowLevelRxPrachEndpoint1 @@ -1851,9 +1943,15 @@ sequenceDiagram 9 STATIC - 0 - 0 + 193 + NORMAL + 352 + 288 0 + + KHZ_30 + 0 + 61440 3840 @@ -1861,6 +1959,7 @@ sequenceDiagram 15 5 + true LowLevelRxEndpoint2 @@ -1868,9 +1967,15 @@ sequenceDiagram 9 STATIC - 0 - 0 + 193 + NORMAL + 352 + 288 0 + + KHZ_30 + 0 + 61440 3840 @@ -1878,6 +1983,7 @@ sequenceDiagram 15 2 + true LowLevelRxPrachEndpoint2 @@ -1885,9 +1991,15 @@ sequenceDiagram 9 STATIC - 0 - 0 + 193 + NORMAL + 352 + 288 0 + + KHZ_30 + 0 + 61440 3840 @@ -1895,6 +2007,7 @@ sequenceDiagram 15 6 + true LowLevelRxEndpoint3 @@ -1902,9 +2015,15 @@ sequenceDiagram 9 STATIC - 0 - 0 + 193 + NORMAL + 352 + 288 0 + + KHZ_30 + 0 + 61440 3840 @@ -1912,6 +2031,7 @@ sequenceDiagram 15 3 + true LowLevelRxPrachEndpoint3 @@ -1919,9 +2039,15 @@ sequenceDiagram 9 STATIC - 0 - 0 + 193 + NORMAL + 352 + 288 0 + + KHZ_30 + 0 + 61440 3840 @@ -1929,6 +2055,7 @@ sequenceDiagram 15 7 + true TxArray0 @@ -1936,7 +2063,7 @@ sequenceDiagram 3950400000 100000000 ACTIVE - 0.0 + 24.0 0 0 @@ -1960,7 +2087,7 @@ sequenceDiagram [HW] [MPLANE] Successfully validated candidate datastore for RU "192.168.80.9". [HW] [MPLANE] RPC request to RU "192.168.80.9" = candidate datastore. [HW] [MPLANE] RPC reply = OK. -[HW] [MPLANE] Successfully commited CU-planes configuration into running datastore for RU "192.168.80.9". +[HW] [MPLANE] Successfully commited configuration into running datastore for RU "192.168.80.9". [HW] [MPLANE] Usage state = "idle" for RU "192.168.80.9". [HW] [MPLANE] Received notification from RU "192.168.80.9" at (2025-03-29T12:40:23.049085102+00:00) { @@ -2028,9 +2155,71 @@ sequenceDiagram "operation": "create" }, ... -} - [HW] [MPLANE] RU "192.168.80.9" is now ready. +[HW] [MPLANE] RPC request to RU "192.168.80.9" = : + + 10 + 10 + 10 + + RX_ON_TIME + true + RU + COUNT + + + RX_EARLY + true + RU + COUNT + + + RX_LATE + true + RU + COUNT + + + RX_TOTAL + true + RU + COUNT + + + RX_ON_TIME_C + true + RU + COUNT + + + RX_EARLY_C + true + RU + COUNT + + + RX_LATE_C + true + RU + COUNT + + + TX_TOTAL + true + RU + COUNT + + + +[HW] [MPLANE] RPC reply = OK. +[HW] [MPLANE] Successfully edited the candidate datastore for RU "192.168.80.9". +[HW] [MPLANE] RPC request to RU "192.168.80.9" = candidate datastore. +[HW] [MPLANE] RPC reply = OK. +[HW] [MPLANE] Successfully validated candidate datastore for RU "192.168.80.9". +[HW] [MPLANE] RPC request to RU "192.168.80.9" = candidate datastore. +[HW] [MPLANE] RPC reply = OK. +[HW] [MPLANE] Successfully commited configuration into running datastore for RU "192.168.80.9". +[HW] [MPLANE] Sucessfully activated PM after start-up procedure for RU "192.168.80.9". ``` From 318d901ef63b9a1f075d0004ff9d76f55532a609 Mon Sep 17 00:00:00 2001 From: Bartosz Podrygajlo Date: Sat, 17 May 2025 13:06:42 +0200 Subject: [PATCH 573/964] Refactor RRC->MAC Communication: Replace ITTI with notifiedFIFO for Multi-UE Support - Replaced ITTI message queues with notifiedFIFO for RRC to MAC communication in UE. - Enables correct message delivery to multiple MAC instances running in parallel threads. - Introduced `nr_mac_rrc_message_t` union for MAC-RRC messages. - Updated all relevant message handling and initialization code to use notifiedFIFO. --- executables/nr-ue.c | 24 ++-- executables/nr-uesoftmodem.c | 14 ++- openair2/COMMON/rrc_messages_def.h | 8 -- openair2/COMMON/rrc_messages_types.h | 27 ++++- openair2/LAYER2/NR_MAC_UE/mac_defs.h | 1 + openair2/LAYER2/NR_MAC_UE/main_ue_nr.c | 1 + openair2/RRC/NR_UE/L2_interface_ue.c | 38 +++--- openair2/RRC/NR_UE/L2_interface_ue.h | 2 +- openair2/RRC/NR_UE/rrc_UE.c | 158 +++++++++++++++---------- openair2/RRC/NR_UE/rrc_defs.h | 2 + openair2/RRC/NR_UE/rrc_proto.h | 2 + 11 files changed, 165 insertions(+), 112 deletions(-) diff --git a/executables/nr-ue.c b/executables/nr-ue.c index 4a534df3b6..3c41338326 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -731,12 +731,14 @@ static int UE_dl_preprocessing(PHY_VARS_NR_UE *UE, fp = &UE->SL_UE_PHY_PARAMS.sl_frame_params; // process what RRC thread sent to MAC - MessageDef *msg = NULL; do { - itti_poll_msg(TASK_MAC_UE, &msg); - if (msg) - process_msg_rcc_to_mac(msg); - } while (msg); + notifiedFIFO_elt_t *elt = pollNotifiedFIFO(&get_mac_inst(UE->Mod_id)->input_nf); + if (!elt) { + break; + } + process_msg_rcc_to_mac(NotifiedFifoData(elt), UE->Mod_id); + delNotifiedFIFO_elt(elt); + } while (true); if (UE->if_inst) UE->if_inst->slot_indication(UE->Mod_id, false); @@ -1032,12 +1034,10 @@ void *UE_thread(void *arg) decoded_frame_rx = UE->SL_UE_PHY_PARAMS.sync_params.DFN; else { // We must wait the RRC layer decoded the MIB and sent us the frame number - MessageDef *msg = NULL; - itti_receive_msg(TASK_MAC_UE, &msg); - if (msg) - process_msg_rcc_to_mac(msg); - else - LOG_E(PHY, "It seems we arbort while trying to sync\n"); + notifiedFIFO_elt_t *elt = pullNotifiedFIFO(&mac->input_nf); + AssertFatal(elt != NULL, "fifo error while waiting for MIB"); + process_msg_rcc_to_mac(NotifiedFifoData(elt), UE->Mod_id); + delNotifiedFIFO_elt(elt); decoded_frame_rx = mac->mib_frame; } LOG_A(PHY, @@ -1287,6 +1287,8 @@ void init_NR_UE(int nb_inst, char *uecap_file, char *reconfig_file, char *rbconf for (int instance_id = 0; instance_id < nb_inst; instance_id++) { NR_UE_RRC_INST_t* rrc = nr_rrc_init_ue(uecap_file, instance_id, get_nrUE_params()->nb_antennas_tx); NR_UE_MAC_INST_t *mac = nr_l2_init_ue(instance_id); + + nr_rrc_set_mac_queue(instance_id, &mac->input_nf); mac->if_module = nr_ue_if_module_init(instance_id); AssertFatal(mac->if_module, "can not initialize IF module\n"); if (!IS_SA_MODE(get_softmodem_params()) && !get_softmodem_params()->sl_mode) { diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index 6a5fcf2394..e2523dda2f 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -500,12 +500,14 @@ int main(int argc, char **argv) get_softmodem_params()->numerology, nr_band); } else { - MessageDef *msg = NULL; - do { - itti_poll_msg(TASK_MAC_UE, &msg); - if (msg) - process_msg_rcc_to_mac(msg); - } while (msg); + do { + notifiedFIFO_elt_t *elt = pollNotifiedFIFO(&mac->input_nf); + if (!elt) { + break; + } + process_msg_rcc_to_mac(NotifiedFifoData(elt), inst); + delNotifiedFIFO_elt(elt); + } while (true); fapi_nr_config_request_t *nrUE_config = &UE[CC_id]->nrUE_config; nr_init_frame_parms_ue(&UE[CC_id]->frame_parms, nrUE_config, mac->nr_band); } diff --git a/openair2/COMMON/rrc_messages_def.h b/openair2/COMMON/rrc_messages_def.h index df295e2011..33d6b7b59e 100644 --- a/openair2/COMMON/rrc_messages_def.h +++ b/openair2/COMMON/rrc_messages_def.h @@ -85,14 +85,6 @@ MESSAGE_DEF(NAS_INIT_NOS1_IF, MESSAGE_PRIORITY_MED, nas_nos1_msg_t, nas_init_nos MESSAGE_DEF(RRC_SUBFRAME_PROCESS, MESSAGE_PRIORITY_MED, RrcSubframeProcess, rrc_subframe_process) MESSAGE_DEF(NRRRC_FRAME_PROCESS, MESSAGE_PRIORITY_MED, NRRrcFrameProcess, nr_rrc_frame_process) -// 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) - // eNB: RLC -> RRC messages MESSAGE_DEF(RLC_SDU_INDICATION, MESSAGE_PRIORITY_MED, RlcSduIndication, rlc_sdu_indication) MESSAGE_DEF(NAS_PDU_SESSION_REQ, MESSAGE_PRIORITY_MED, nas_pdu_session_req_t, nas_pdu_session_req) diff --git a/openair2/COMMON/rrc_messages_types.h b/openair2/COMMON/rrc_messages_types.h index 1d35619ecc..e1656a3d7f 100644 --- a/openair2/COMMON/rrc_messages_types.h +++ b/openair2/COMMON/rrc_messages_types.h @@ -105,12 +105,6 @@ #define NAS_OAI_TUN_NSA(mSGpTR) (mSGpTR)->ittiMsg.nas_oai_tun_nsa #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 #define NR_RRC_RLC_MAXRTX(mSGpTR) (mSGpTR)->ittiMsg.nr_rlc_maxrtx_indication @@ -497,4 +491,25 @@ typedef struct { bool can_start_ra; } nr_mac_rrc_config_other_sib_t; +enum payload_type { + NR_MAC_RRC_CONFIG_RESET, + NR_MAC_RRC_CONFIG_CG, + NR_MAC_RRC_CONFIG_MIB, + NR_MAC_RRC_CONFIG_SIB1, + NR_MAC_RRC_CONFIG_OTHER_SIB, + NR_MAC_RRC_RESUME_RB +}; + +typedef struct { + enum payload_type payload_type; + union { + nr_mac_rrc_config_reset_t config_reset; + nr_mac_rrc_config_cg_t config_cg; + nr_mac_rrc_config_mib_t config_mib; + nr_mac_rrc_config_sib1_t config_sib1; + nr_mac_rrc_config_other_sib_t config_other_sib; + nr_mac_rrc_resume_rb_t resume_rb; + } payload; +} nr_mac_rrc_message_t; + #endif /* RRC_MESSAGES_TYPES_H_ */ diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index 2d88708bfe..d734870f52 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -654,6 +654,7 @@ typedef struct NR_UE_MAC_INST_s { bool msg3_C_RNTI; pthread_mutex_t if_mutex; ue_mac_stats_t stats; + notifiedFIFO_t input_nf; } NR_UE_MAC_INST_t; static inline int GET_NTN_UE_K_OFFSET(const ntn_timing_advance_componets_t *ntn_ta, int scs) diff --git a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c index 78328461b4..1a43dd2972 100644 --- a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c +++ b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c @@ -70,6 +70,7 @@ void nr_ue_init_mac(NR_UE_MAC_INST_t *mac) mac->p_Max_alt = INT_MIN; mac->msg3_C_RNTI = false; mac->ntn_ta.ntn_params_changed = false; + initNotifiedFIFO(&mac->input_nf); reset_mac_inst(mac); // need to inizialize because might not been setup (optional timer) diff --git a/openair2/RRC/NR_UE/L2_interface_ue.c b/openair2/RRC/NR_UE/L2_interface_ue.c index 6271957f4f..b751f31670 100644 --- a/openair2/RRC/NR_UE/L2_interface_ue.c +++ b/openair2/RRC/NR_UE/L2_interface_ue.c @@ -121,42 +121,40 @@ void nr_mac_rrc_data_ind_ue(const module_id_t module_id, } } -void process_msg_rcc_to_mac(MessageDef *msg) +void process_msg_rcc_to_mac(nr_mac_rrc_message_t *msg, int instance_id) { - instance_t ue_id = ITTI_MSG_DESTINATION_INSTANCE(msg); - switch (ITTI_MSG_ID(msg)) { + switch (msg->payload_type) { case NR_MAC_RRC_CONFIG_RESET: - nr_rrc_mac_config_req_reset(ue_id, NR_MAC_RRC_CONFIG_RESET(msg).cause); + nr_rrc_mac_config_req_reset(instance_id, msg->payload.config_reset.cause); break; case NR_MAC_RRC_CONFIG_CG: - nr_rrc_mac_config_req_cg(ue_id, 0, NR_MAC_RRC_CONFIG_CG(msg).cellGroupConfig, NR_MAC_RRC_CONFIG_CG(msg).UE_NR_Capability); - asn1cFreeStruc(asn_DEF_NR_CellGroupConfig, NR_MAC_RRC_CONFIG_CG(msg).cellGroupConfig); + nr_rrc_mac_config_req_cg(instance_id, 0, msg->payload.config_cg.cellGroupConfig, msg->payload.config_cg.UE_NR_Capability); + asn1cFreeStruc(asn_DEF_NR_CellGroupConfig, msg->payload.config_cg.cellGroupConfig); break; case NR_MAC_RRC_CONFIG_MIB: - nr_rrc_mac_config_req_mib(ue_id, + nr_rrc_mac_config_req_mib(instance_id, 0, - NR_MAC_RRC_CONFIG_MIB(msg).bcch->message.choice.mib, - NR_MAC_RRC_CONFIG_MIB(msg).get_sib, - NR_MAC_RRC_CONFIG_MIB(msg).access_barred); - ASN_STRUCT_FREE(asn_DEF_NR_BCCH_BCH_Message, NR_MAC_RRC_CONFIG_MIB(msg).bcch); + msg->payload.config_mib.bcch->message.choice.mib, + msg->payload.config_mib.get_sib, + msg->payload.config_mib.access_barred); + ASN_STRUCT_FREE(asn_DEF_NR_BCCH_BCH_Message, msg->payload.config_mib.bcch); break; case NR_MAC_RRC_CONFIG_SIB1: { - NR_SIB1_t *sib1 = NR_MAC_RRC_CONFIG_SIB1(msg).sib1; - bool can_start_ra = NR_MAC_RRC_CONFIG_SIB1(msg).can_start_ra; - nr_rrc_mac_config_req_sib1(ue_id, 0, sib1, can_start_ra); - SEQUENCE_free(&asn_DEF_NR_SIB1, NR_MAC_RRC_CONFIG_SIB1(msg).sib1, ASFM_FREE_EVERYTHING); + NR_SIB1_t *sib1 = msg->payload.config_sib1.sib1; + bool can_start_ra = msg->payload.config_sib1.can_start_ra; + nr_rrc_mac_config_req_sib1(instance_id, 0, sib1, can_start_ra); + SEQUENCE_free(&asn_DEF_NR_SIB1, msg->payload.config_sib1.sib1, ASFM_FREE_EVERYTHING); } break; case NR_MAC_RRC_CONFIG_OTHER_SIB: { - 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); + bool can_start_ra = msg->payload.config_other_sib.can_start_ra; + nr_rrc_mac_config_other_sib(instance_id, msg->payload.config_other_sib.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); + nr_rrc_mac_resume_rb(instance_id, msg->payload.resume_rb.is_srb, msg->payload.resume_rb.rb_id); break; default: - LOG_E(NR_MAC, "Unexpected msg from RRC: %d\n", ITTI_MSG_ID(msg)); + LOG_E(NR_MAC, "Unexpected msg from RRC: %d\n", msg->payload_type); } - itti_free(ITTI_MSG_ORIGIN_ID(msg), msg); } void nr_mac_rrc_inactivity_timer_ind(const module_id_t mod_id) diff --git a/openair2/RRC/NR_UE/L2_interface_ue.h b/openair2/RRC/NR_UE/L2_interface_ue.h index e36f6d83fb..daaed50e65 100644 --- a/openair2/RRC/NR_UE/L2_interface_ue.h +++ b/openair2/RRC/NR_UE/L2_interface_ue.h @@ -42,6 +42,6 @@ void nr_mac_rrc_msg3_ind(const module_id_t mod_id, const int rnti, bool prepare_ void nr_ue_rrc_timer_trigger(int instance, int frame, int gnb_id); void nr_mac_rrc_ra_ind(const module_id_t mod_id, bool success); void nsa_sendmsg_to_lte_ue(const void *message, size_t msg_len, Rrc_Msg_Type_t msg_type); -void process_msg_rcc_to_mac(MessageDef *msg); +void process_msg_rcc_to_mac(nr_mac_rrc_message_t *msg, int instance_id); #endif diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index df95a177d6..52d9ecb50a 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -149,6 +149,21 @@ static void nr_rrc_ue_process_masterCellGroup(NR_UE_RRC_INST_t *rrc, static void nr_rrc_ue_process_measConfig(rrcPerNB_t *rrc, NR_MeasConfig_t *const measConfig, NR_UE_Timers_Constants_t *timers); +/** + * @brief Sends an RRC message to the connected UE MAC instance. + * + * @param rrc UE RRC instance structure + * @param msg RRC message to be sent to MAC + */ +static void nr_rrc_send_msg_to_mac(NR_UE_RRC_INST_t *rrc, nr_mac_rrc_message_t *msg) +{ + AssertFatal(rrc->mac_input_nf != NULL, "MAC input NF is NULL for UE %ld\n", rrc->ue_id); + notifiedFIFO_elt_t *nf_msg = newNotifiedFIFO_elt(sizeof(nr_mac_rrc_message_t), 0, NULL, NULL); + nr_mac_rrc_message_t *rrc_msg = NotifiedFifoData(nf_msg); + memcpy(rrc_msg, msg, sizeof(nr_mac_rrc_message_t)); + pushNotifiedFIFO(rrc->mac_input_nf, nf_msg); +} + NR_UE_RRC_INST_t *get_NR_UE_rrc_inst(int instance) { AssertFatal(instance >= 0 && instance < MAX_NUM_NR_UE_INST, "RRC instance %d out of bounds\n", instance); @@ -286,7 +301,6 @@ static void nr_rrc_process_ntnconfig(NR_UE_RRC_INST_t *rrc, NR_UE_RRC_SI_INFO *S 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); // Dump contents @@ -370,10 +384,12 @@ static void nr_decode_SI(NR_UE_RRC_SI_INFO *SI_info, NR_SystemInformation_t *si, } if (sib19) { - MessageDef *msg = itti_alloc_new_message(TASK_RRC_NRUE, 0, NR_MAC_RRC_CONFIG_OTHER_SIB); - asn_copy(&asn_DEF_NR_SIB19_r17, (void **)&NR_MAC_RRC_CONFIG_OTHER_SIB(msg).sib19, sib19); - NR_MAC_RRC_CONFIG_OTHER_SIB(msg).can_start_ra = rrc->is_NTN_UE; - itti_send_msg_to_task(TASK_MAC_UE, ue_id, msg); + nr_mac_rrc_message_t rrc_msg = {0}; + rrc_msg.payload_type = NR_MAC_RRC_CONFIG_OTHER_SIB; + nr_mac_rrc_config_other_sib_t *sib19_msg = &rrc_msg.payload.config_other_sib; + asn_copy(&asn_DEF_NR_SIB19_r17, (void **)&sib19_msg->sib19, sib19); + sib19_msg->can_start_ra = rrc->is_NTN_UE; + nr_rrc_send_msg_to_mac(rrc, &rrc_msg); } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_UE_DECODE_SI, VCD_FUNCTION_OUT); } @@ -507,10 +523,13 @@ static void nr_rrc_process_sib1(NR_UE_RRC_INST_t *rrc, NR_UE_RRC_SI_INFO *SI_inf nr_rrc_set_sib1_timers_and_constants(&rrc->timers_and_constants, sib1); // RRC storage of SIB1 timers and constants (eg needed in re-establishment) UPDATE_IE(rrc->timers_and_constants.sib1_TimersAndConstants, sib1->ue_TimersAndConstants, NR_UE_TimersAndConstants_t); - MessageDef *msg = itti_alloc_new_message(TASK_RRC_NRUE, 0, NR_MAC_RRC_CONFIG_SIB1); - NR_MAC_RRC_CONFIG_SIB1(msg).sib1 = sib1; - NR_MAC_RRC_CONFIG_SIB1(msg).can_start_ra = !rrc->is_NTN_UE; - itti_send_msg_to_task(TASK_MAC_UE, rrc->ue_id, msg); + + nr_mac_rrc_message_t rrc_msg = {0}; + rrc_msg.payload_type = NR_MAC_RRC_CONFIG_SIB1; + nr_mac_rrc_config_sib1_t *config_sib1 = &rrc_msg.payload.config_sib1; + config_sib1->sib1 = sib1; + config_sib1->can_start_ra = !rrc->is_NTN_UE; + nr_rrc_send_msg_to_mac(rrc, &rrc_msg); } static void nr_rrc_process_reconfiguration_v1530(NR_UE_RRC_INST_t *rrc, NR_RRCReconfiguration_v1530_IEs_t *rec_1530, int gNB_index) @@ -649,12 +668,12 @@ static void nr_rrc_ue_process_rrcReconfiguration(NR_UE_RRC_INST_t *rrc, int gNB_ 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); - // cellGroupConfig will be managed by MAC - NR_MAC_RRC_CONFIG_CG(msg).cellGroupConfig = cellGroupConfig; - // UE_NR_Capability remain a race condition between this rrc thread and mac thread - NR_MAC_RRC_CONFIG_CG(msg).UE_NR_Capability = rrc->UECap.UE_NR_Capability; - itti_send_msg_to_task(TASK_MAC_UE, rrc->ue_id, msg); + nr_mac_rrc_message_t rrc_msg = {0}; + rrc_msg.payload_type = NR_MAC_RRC_CONFIG_CG; + nr_mac_rrc_config_cg_t *config_cg = &rrc_msg.payload.config_cg; + config_cg->cellGroupConfig = cellGroupConfig; + config_cg->UE_NR_Capability = rrc->UECap.UE_NR_Capability; + nr_rrc_send_msg_to_mac(rrc, &rrc_msg); } if (ie->measConfig) { LOG_I(NR_RRC, "RRCReconfiguration includes Measurement Configuration\n"); @@ -974,12 +993,13 @@ static void nr_rrc_ue_decode_NR_BCCH_BCH_Message(NR_UE_RRC_INST_t *rrc, SI_info->sib_pending = true; } if (bcch_message->message.present == NR_BCCH_BCH_MessageType_PR_mib) { - MessageDef *msg = itti_alloc_new_message(TASK_RRC_NRUE, 0, NR_MAC_RRC_CONFIG_MIB); - // mac will manage the pointer - NR_MAC_RRC_CONFIG_MIB(msg).bcch = bcch_message; - NR_MAC_RRC_CONFIG_MIB(msg).get_sib = get_sib; - NR_MAC_RRC_CONFIG_MIB(msg).access_barred = barred; - itti_send_msg_to_task(TASK_MAC_UE, rrc->ue_id, msg); + nr_mac_rrc_message_t rrc_msg = {0}; + rrc_msg.payload_type = NR_MAC_RRC_CONFIG_MIB; + nr_mac_rrc_config_mib_t *config_mib = &rrc_msg.payload.config_mib; + config_mib->bcch = bcch_message; + config_mib->get_sib = get_sib; + config_mib->access_barred = barred; + nr_rrc_send_msg_to_mac(rrc, &rrc_msg); } else { LOG_E(NR_RRC, "RRC-received BCCH message is not a MIB\n"); ASN_STRUCT_FREE(asn_DEF_NR_BCCH_BCH_Message, bcch_message); @@ -1037,10 +1057,11 @@ 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); + nr_mac_rrc_message_t rrc_msg = {0}; + rrc_msg.payload_type = NR_MAC_RRC_RESUME_RB; + rrc_msg.payload.resume_rb.is_srb = true; + rrc_msg.payload.resume_rb.rb_id = 1; + nr_rrc_send_msg_to_mac(rrc, &rrc_msg); break; case DURING_HANDOVER: AssertFatal(1==0, "ra_trigger not implemented yet!\n"); @@ -1261,10 +1282,12 @@ static void nr_rrc_ue_process_masterCellGroup(NR_UE_RRC_INST_t *rrc, 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); - NR_MAC_RRC_CONFIG_CG(msg).cellGroupConfig = cellGroupConfig; - NR_MAC_RRC_CONFIG_CG(msg).UE_NR_Capability = rrc->UECap.UE_NR_Capability; - itti_send_msg_to_task(TASK_MAC_UE, rrc->ue_id, msg); + nr_mac_rrc_message_t rrc_msg = {0}; + rrc_msg.payload_type = NR_MAC_RRC_CONFIG_CG; + nr_mac_rrc_config_cg_t *mac_msg = &rrc_msg.payload.config_cg; + mac_msg->cellGroupConfig = cellGroupConfig; + mac_msg->UE_NR_Capability = rrc->UECap.UE_NR_Capability; + nr_rrc_send_msg_to_mac(rrc, &rrc_msg); } static void rrc_ue_generate_RRCSetupComplete(const NR_UE_RRC_INST_t *rrc, const uint8_t Transaction_id) @@ -1346,9 +1369,10 @@ static void nr_rrc_rrcsetup_fallback(NR_UE_RRC_INST_t *rrc) // 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); + nr_mac_rrc_message_t rrc_msg = {0}; + rrc_msg.payload_type = NR_MAC_RRC_CONFIG_RESET; + rrc_msg.payload.config_reset.cause = cause; + nr_rrc_send_msg_to_mac(rrc, &rrc_msg); // indicate to upper layers fallback of the RRC connection // TODO @@ -1412,9 +1436,10 @@ static void nr_rrc_process_rrcreject(NR_UE_RRC_INST_t *rrc, const NR_RRCReject_t // reset MAC and release the default MAC Cell Group configuration NR_UE_MAC_reset_cause_t cause = REJECT; - 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); + nr_mac_rrc_message_t rrc_msg = {0}; + rrc_msg.payload_type = NR_MAC_RRC_CONFIG_RESET; + rrc_msg.payload.config_reset.cause = cause; + nr_rrc_send_msg_to_mac(rrc, &rrc_msg); // if waitTime is configured in the RRCReject: start timer T302, with the timer value set to the waitTime NR_RejectWaitTime_t *waitTime = NULL; @@ -2122,18 +2147,20 @@ static int nr_rrc_ue_decode_dcch(NR_UE_RRC_INST_t *rrc, // resume SRB2 and DRBs that are 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); + nr_mac_rrc_message_t rrc_msg = {0}; + rrc_msg.payload_type = NR_MAC_RRC_RESUME_RB; + rrc_msg.payload.resume_rb.is_srb = true; + rrc_msg.payload.resume_rb.rb_id = 2; + nr_rrc_send_msg_to_mac(rrc, &rrc_msg); } for (int i = 1; i <= MAX_DRBS_PER_UE; i++) { 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); + nr_mac_rrc_message_t rrc_msg = {0}; + rrc_msg.payload_type = NR_MAC_RRC_RESUME_RB; + rrc_msg.payload.resume_rb.is_srb = true; + rrc_msg.payload.resume_rb.rb_id = i; + nr_rrc_send_msg_to_mac(rrc, &rrc_msg); } } rrc->reconfig_after_reestab = false; @@ -2336,11 +2363,11 @@ void *rrc_nrue(void *notUsed) case NR_RRC_DCCH_DATA_IND: nr_rrc_ue_decode_dcch(rrc, - NR_RRC_DCCH_DATA_IND(msg_p).dcch_index, - NR_RRC_DCCH_DATA_IND(msg_p).sdu_p, - NR_RRC_DCCH_DATA_IND(msg_p).sdu_size, - NR_RRC_DCCH_DATA_IND(msg_p).gNB_index, - &NR_RRC_DCCH_DATA_IND(msg_p).msg_integrity); + NR_RRC_DCCH_DATA_IND(msg_p).dcch_index, + NR_RRC_DCCH_DATA_IND(msg_p).sdu_p, + NR_RRC_DCCH_DATA_IND(msg_p).sdu_size, + NR_RRC_DCCH_DATA_IND(msg_p).gNB_index, + &NR_RRC_DCCH_DATA_IND(msg_p).msg_integrity); /* this is allocated by itti_malloc in PDCP task (deliver_sdu_srb) then passed to the RRC task and freed after use */ free(NR_RRC_DCCH_DATA_IND(msg_p).sdu_p); @@ -2512,9 +2539,10 @@ static void nr_rrc_initiate_rrcReestablishment(NR_UE_RRC_INST_t *rrc, NR_Reestab // reset MAC // release spCellConfig, if configured // perform cell selection in accordance with the cell selection process - MessageDef *msg = itti_alloc_new_message(TASK_RRC_NRUE, 0, NR_MAC_RRC_CONFIG_RESET); - NR_MAC_RRC_CONFIG_RESET(msg).cause = RE_ESTABLISHMENT; - itti_send_msg_to_task(TASK_MAC_UE, rrc->ue_id, msg); + nr_mac_rrc_message_t rrc_msg = {0}; + rrc_msg.payload_type = NR_MAC_RRC_CONFIG_RESET; + rrc_msg.payload.config_reset.cause = RE_ESTABLISHMENT; + nr_rrc_send_msg_to_mac(rrc, &rrc_msg); } static void nr_rrc_ue_generate_rrcReestablishmentComplete(const NR_UE_RRC_INST_t *rrc, @@ -2887,9 +2915,10 @@ void nr_rrc_going_to_IDLE(NR_UE_RRC_INST_t *rrc, // reset MAC NR_UE_MAC_reset_cause_t cause = (rrc->nrRrcState == RRC_STATE_DETACH_NR) ? DETACH : GO_TO_IDLE; - 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); + nr_mac_rrc_message_t rrc_msg = {0}; + rrc_msg.payload_type = NR_MAC_RRC_CONFIG_RESET; + rrc_msg.payload.config_reset.cause = cause; + nr_rrc_send_msg_to_mac(rrc, &rrc_msg); // enter RRC_IDLE LOG_I(NR_RRC, "RRC moved into IDLE state\n"); @@ -2918,9 +2947,11 @@ void handle_t300_expiry(NR_UE_RRC_INST_t *rrc) // reset MAC, release the MAC configuration NR_UE_MAC_reset_cause_t cause = T300_EXPIRY; - 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); + nr_mac_rrc_message_t rrc_msg = {0}; + rrc_msg.payload_type = NR_MAC_RRC_CONFIG_RESET; + rrc_msg.payload.config_reset.cause = cause; + nr_rrc_send_msg_to_mac(rrc, &rrc_msg); + // TODO handle connEstFailureControl // TODO inform upper layers about the failure to establish the RRC connection } @@ -2936,9 +2967,10 @@ void handle_t430_expiry(NR_UE_RRC_INST_t *rrc) } // 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); + nr_mac_rrc_message_t rrc_msg = {0}; + rrc_msg.payload_type = NR_MAC_RRC_CONFIG_RESET; + rrc_msg.payload.config_reset.cause = cause; + nr_rrc_send_msg_to_mac(rrc, &rrc_msg); } //This calls the sidelink preconf message after RRC, MAC instances are created. @@ -2954,3 +2986,9 @@ void start_sidelink(int instance) } } + +void nr_rrc_set_mac_queue(instance_t instance, notifiedFIFO_t *mac_input_nf) +{ + NR_UE_RRC_INST_t *rrc = get_NR_UE_rrc_inst(instance); + rrc->mac_input_nf = mac_input_nf; +} diff --git a/openair2/RRC/NR_UE/rrc_defs.h b/openair2/RRC/NR_UE/rrc_defs.h index c71f7697a2..bc645f7cc1 100644 --- a/openair2/RRC/NR_UE/rrc_defs.h +++ b/openair2/RRC/NR_UE/rrc_defs.h @@ -63,6 +63,7 @@ #include "RRC/NR/nr_rrc_common.h" #include "as_message.h" #include "common/utils/nr/nr_common.h" +#include "notified_fifo.h" #define NB_CNX_UE 2//MAX_MANAGED_RG_PER_MOBILE #define MAX_MEAS_OBJ 64 @@ -248,6 +249,7 @@ typedef struct NR_UE_RRC_INST_s { NR_SL_PreconfigurationNR_r16_t *sl_preconfig; // NTN params bool is_NTN_UE; + notifiedFIFO_t *mac_input_nf; } NR_UE_RRC_INST_t; #endif diff --git a/openair2/RRC/NR_UE/rrc_proto.h b/openair2/RRC/NR_UE/rrc_proto.h index bc7f7001af..ba853f546d 100644 --- a/openair2/RRC/NR_UE/rrc_proto.h +++ b/openair2/RRC/NR_UE/rrc_proto.h @@ -106,6 +106,8 @@ void nr_rrc_ue_decode_NR_SBCCH_SL_BCH_Message(NR_UE_RRC_INST_t *rrc, const sdu_size_t pdu_len, const uint16_t rx_slss_id); +void nr_rrc_set_mac_queue(instance_t instance, notifiedFIFO_t *mac_input_nf); + /** @}*/ #endif From 62bcd822c516b4eb09d174ee0d51596eab2ffb5f Mon Sep 17 00:00:00 2001 From: Bartosz Podrygajlo Date: Thu, 8 May 2025 14:27:44 +0200 Subject: [PATCH 574/964] Make map_current_symbol thread safe Use local function pointers instead of static global variables. --- openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c | 28 ++++++++++++++-------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c index ebfd6f6352..97e8109dec 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c @@ -91,8 +91,8 @@ The function pointers are set once before calling the mapping funcion for all symbols based on different parameters. Then the mapping is done for each symbol by calling the function pointers. */ -static void (*map_dmrs_ptr)(const unsigned int, const c16_t *, c16_t *); -static void (*map_data_dmrs_ptr)(const unsigned int num_cdm_no_data, const c16_t *, c16_t *); +typedef void (*map_dmrs_func_t)(const unsigned int, const c16_t *, c16_t *); +typedef void (*map_data_dmrs_func_t)(const unsigned int, const c16_t *, c16_t *); /* The following set of functions map dmrs and/or data REs in one RB based on @@ -191,7 +191,9 @@ static void map_over_dc(const unsigned int right_dc, const c16_t **ptrs, const c16_t **dmrs, const c16_t **data, - c16_t **out) + c16_t **out, + map_dmrs_func_t map_data_dmrs_ptr, + map_dmrs_func_t map_dmrs_ptr) { // if first RE is DC no need to map in this function if (right_dc == 0) @@ -277,7 +279,9 @@ static void map_current_symbol(const nr_phy_pxsch_params_t p, const c16_t *dmrs_seq, const c16_t *ptrs_seq, const c16_t **data, - c16_t *out) + c16_t *out, + map_dmrs_func_t map_dmrs_ptr, + map_data_dmrs_func_t map_data_dmrs_ptr) { const unsigned int abs_start_rb = p.bwp_start + p.start_rb; const unsigned int start_sc = (p.first_sc_offset + abs_start_rb * NR_NB_SC_PER_RB) % p.fft_size; @@ -297,7 +301,7 @@ static void map_current_symbol(const nr_phy_pxsch_params_t p, // map RB at DC if (rb_over_dc) { // if DC is in middle of RB, the following function handles it. - map_over_dc(rb_over_dc, n_cdm, p.fft_size, dmrs_per_rb, data_per_rb, p.delta, 0, NULL, &p_mod_dmrs, NULL, &out_tmp); + map_over_dc(rb_over_dc, n_cdm, p.fft_size, dmrs_per_rb, data_per_rb, p.delta, 0, NULL, &p_mod_dmrs, NULL, &out_tmp, map_data_dmrs_ptr, map_dmrs_ptr); continue; } else { // else just move the pointer and following function will map the rb @@ -315,7 +319,7 @@ static void map_current_symbol(const nr_phy_pxsch_params_t p, for (unsigned int rb = 0; rb < p.nb_rb; rb++) { if (rb == dc_rb) { if (rb_over_dc) { - map_over_dc(rb_over_dc, n_cdm, p.fft_size, dmrs_per_rb, data_per_rb, p.delta, 0, NULL, &p_mod_dmrs, &data_tmp, &out_tmp); + map_over_dc(rb_over_dc, n_cdm, p.fft_size, dmrs_per_rb, data_per_rb, p.delta, 0, NULL, &p_mod_dmrs, &data_tmp, &out_tmp, map_data_dmrs_ptr, map_dmrs_ptr); continue; } else { out_tmp -= p.fft_size; @@ -339,7 +343,7 @@ static void map_current_symbol(const nr_phy_pxsch_params_t p, if (rb < non_ptrs_rb || ptrs_idx_rb % p.K_ptrs) { if (rb == dc_rb) { if (rb_over_dc) { - map_over_dc(rb_over_dc, n_cdm, p.fft_size, 0, 0, p.delta, 0, NULL, NULL, &data_tmp, &out_tmp); + map_over_dc(rb_over_dc, n_cdm, p.fft_size, 0, 0, p.delta, 0, NULL, NULL, &data_tmp, &out_tmp, map_data_dmrs_ptr, map_dmrs_ptr); continue; } else { out_tmp -= p.fft_size; @@ -351,7 +355,7 @@ static void map_current_symbol(const nr_phy_pxsch_params_t p, } else { if (rb == dc_rb) { if (rb_over_dc) { - map_over_dc(rb_over_dc, n_cdm, p.fft_size, 0, 0, p.delta, ptrs_idx_re, &p_mod_ptrs, NULL, &data_tmp, &out_tmp); + map_over_dc(rb_over_dc, n_cdm, p.fft_size, 0, 0, p.delta, ptrs_idx_re, &p_mod_ptrs, NULL, &data_tmp, &out_tmp, map_data_dmrs_ptr, map_dmrs_ptr); continue; } else { out_tmp -= p.fft_size; @@ -370,7 +374,7 @@ static void map_current_symbol(const nr_phy_pxsch_params_t p, for (unsigned int rb = 0; rb < p.nb_rb; rb++) { if (rb == dc_rb) { if (rb_over_dc) { - map_over_dc(rb_over_dc, n_cdm, p.fft_size, 0, 0, p.delta, 0, NULL, NULL, &data_tmp, &out_tmp); + map_over_dc(rb_over_dc, n_cdm, p.fft_size, 0, 0, p.delta, 0, NULL, NULL, &data_tmp, &out_tmp, map_data_dmrs_ptr, map_dmrs_ptr); continue; } else { out_tmp -= p.fft_size; @@ -420,6 +424,8 @@ static void map_symbols(const nr_phy_pxsch_params_t p, c16_t *out) { // asign the function pointers + map_dmrs_func_t map_dmrs_ptr = NULL; + map_data_dmrs_func_t map_data_dmrs_ptr = NULL; if (p.dmrs_type == pusch_dmrs_type1) { map_dmrs_ptr = map_dmrs_type1_cdm1_rb; map_data_dmrs_ptr = (p.num_cdm_no_data == 1) ? map_data_dmrs_type1_cdm1_rb : NULL; @@ -460,7 +466,9 @@ static void map_symbols(const nr_phy_pxsch_params_t p, mod_dmrs_amp, mod_ptrs_amp, &cur_data, // increments every symbol - out + l * p.fft_size); + out + l * p.fft_size, + map_dmrs_ptr, + map_data_dmrs_ptr); } } From 86937cd8b19dba934db4c3ac74867f7a5ad93e48 Mon Sep 17 00:00:00 2001 From: alexjiao Date: Wed, 27 Aug 2025 16:11:57 +0800 Subject: [PATCH 575/964] Fix for function compute_csi_rm_unav_res --- openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index e31d0491bc..9a4b1c0eb7 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -698,7 +698,7 @@ static uint32_t compute_csi_rm_unav_res(fapi_nr_dl_config_dlsch_pdu_rel15_t *dls int num_symb = num_l0[csi_pdu->row - 1]; for (int s = 0; s < num_symb; s++) { int l0_symb = csi_pdu->symb_l0 + s; - if (l0_symb >= dlsch_config->start_symbol && l0_symb <= dlsch_config->start_symbol + dlsch_config->number_symbols) + if (l0_symb >= dlsch_config->start_symbol && l0_symb < dlsch_config->start_symbol + dlsch_config->number_symbols) num_overlap_symb++; } // check also l1 if relevant @@ -706,7 +706,7 @@ static uint32_t compute_csi_rm_unav_res(fapi_nr_dl_config_dlsch_pdu_rel15_t *dls num_symb += 2; for (int s = 0; s < 2; s++) { // two consecutive symbols including l1 int l1_symb = csi_pdu->symb_l1 + s; - if (l1_symb >= dlsch_config->start_symbol && l1_symb <= dlsch_config->start_symbol + dlsch_config->number_symbols) + if (l1_symb >= dlsch_config->start_symbol && l1_symb < dlsch_config->start_symbol + dlsch_config->number_symbols) num_overlap_symb++; } } From d72ee11b32439ddc0a3c773f7b1a58198b29e45d Mon Sep 17 00:00:00 2001 From: Bartosz Podrygajlo Date: Sat, 17 May 2025 14:23:30 +0200 Subject: [PATCH 576/964] Make openair0_cfg thread safe Move openair0_cfg to PHY_VARS_NR_UE making it UE instance specific and thread safe. --- executables/nr-softmodem-common.h | 1 - executables/nr-ue.c | 10 +-- executables/nr-uesoftmodem.c | 67 +++++++++---------- .../nr_dl_channel_estimation.c | 11 +-- openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h | 3 +- .../PHY/NR_UE_ESTIMATION/nr_ue_measurements.c | 13 ++-- openair1/PHY/NR_UE_TRANSPORT/csi_rx.c | 2 +- .../PHY/NR_UE_TRANSPORT/nr_initial_sync_sl.c | 2 +- openair1/PHY/defs_nr_UE.h | 1 + .../SCHED_NR_UE/phy_procedures_nr_ue_sl.c | 2 +- 10 files changed, 59 insertions(+), 53 deletions(-) diff --git a/executables/nr-softmodem-common.h b/executables/nr-softmodem-common.h index 61823d43cd..8541135bb6 100644 --- a/executables/nr-softmodem-common.h +++ b/executables/nr-softmodem-common.h @@ -126,7 +126,6 @@ extern int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; extern int oai_exit; -extern openair0_config_t openair0_cfg[MAX_CARDS]; extern pthread_cond_t sync_cond; extern pthread_mutex_t sync_mutex; extern int sync_var; diff --git a/executables/nr-ue.c b/executables/nr-ue.c index 3c41338326..588465133b 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -414,7 +414,7 @@ static void UE_synch(void *arg) { syncData_t *syncD = (syncData_t *)arg; PHY_VARS_NR_UE *UE = syncD->UE; UE->is_synchronized = 0; - openair0_config_t *cfg0 = &openair0_cfg[UE->rf_map.card]; + openair0_config_t *cfg0 = &UE->openair0_cfg[UE->rf_map.card]; if (UE->target_Nid_cell != -1) { LOG_W(NR_PHY, "Starting re-sync detection for target Nid_cell %i\n", UE->target_Nid_cell); @@ -523,7 +523,7 @@ static void RU_write(nr_rxtx_thread_data_t *rxtxD, bool sl_tx_action, c16_t **tx radio_tx_burst_flag_t flags = TX_BURST_INVALID; if (UE->received_config_request) { - if (openair0_cfg[0].duplex_mode == duplex_mode_FDD || get_softmodem_params()->continuous_tx) { + if (UE->openair0_cfg[0].duplex_mode == duplex_mode_FDD || get_softmodem_params()->continuous_tx) { flags = TX_BURST_MIDDLE; // In case of Sidelink, USRP write needed only in case transmission // needs to be done in this slot and not based on tdd ULDL configuration. @@ -696,8 +696,8 @@ static int handle_sync_req_from_mac(PHY_VARS_NR_UE *UE) if (dl_CarrierFreq != fp->dl_CarrierFreq || ul_CarrierFreq != fp->ul_CarrierFreq) { fp->dl_CarrierFreq = dl_CarrierFreq; fp->ul_CarrierFreq = ul_CarrierFreq; - nr_rf_card_config_freq(&openair0_cfg[UE->rf_map.card], ul_CarrierFreq, dl_CarrierFreq, 0); - UE->rfdevice.trx_set_freq_func(&UE->rfdevice, &openair0_cfg[0]); + nr_rf_card_config_freq(&UE->openair0_cfg[UE->rf_map.card], ul_CarrierFreq, dl_CarrierFreq, 0); + UE->rfdevice.trx_set_freq_func(&UE->rfdevice, &UE->openair0_cfg[UE->rf_map.card]); init_symbol_rotation(fp); } @@ -968,7 +968,7 @@ void *UE_thread(void *arg) void *rxp[NB_ANTENNAS_RX]; enum stream_status_e stream_status = STREAM_STATUS_UNSYNC; fapi_nr_config_request_t *cfg = &UE->nrUE_config; - int tmp = openair0_device_load(&(UE->rfdevice), &openair0_cfg[0]); + int tmp = openair0_device_load(&(UE->rfdevice), &UE->openair0_cfg[0]); AssertFatal(tmp == 0, "Could not load the device\n"); NR_DL_FRAME_PARMS *fp = &UE->frame_parms; sl_nr_phy_config_request_t *sl_cfg = NULL; diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index e2523dda2f..ac7b23382f 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -121,8 +121,6 @@ int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; uint64_t sidelink_frequency[MAX_NUM_CCs][4]; // UE and OAI config variables - -openair0_config_t openair0_cfg[MAX_CARDS]; int16_t node_synch_ref[MAX_NUM_CCs]; int otg_enabled; double cpuf; @@ -249,41 +247,42 @@ void set_options(int CC_id, PHY_VARS_NR_UE *UE){ } -static void init_openair0() +void init_openair0(PHY_VARS_NR_UE *ue) { int card; int freq_off = 0; - NR_DL_FRAME_PARMS *frame_parms = &PHY_vars_UE_g[0][0]->frame_parms; + NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; bool is_sidelink = (get_softmodem_params()->sl_mode) ? true : false; if (is_sidelink) - frame_parms = &PHY_vars_UE_g[0][0]->SL_UE_PHY_PARAMS.sl_frame_params; + frame_parms = &ue->SL_UE_PHY_PARAMS.sl_frame_params; for (card=0; cardopenair0_cfg[card]; uint64_t dl_carrier, ul_carrier; - openair0_cfg[card].configFilename = NULL; - openair0_cfg[card].sample_rate = frame_parms->samples_per_subframe * 1e3; - openair0_cfg[card].samples_per_frame = frame_parms->samples_per_frame; + cfg->configFilename = NULL; + cfg->sample_rate = frame_parms->samples_per_subframe * 1e3; + cfg->samples_per_frame = frame_parms->samples_per_frame; if (frame_parms->frame_type==TDD) - openair0_cfg[card].duplex_mode = duplex_mode_TDD; + cfg->duplex_mode = duplex_mode_TDD; else - openair0_cfg[card].duplex_mode = duplex_mode_FDD; + cfg->duplex_mode = duplex_mode_FDD; - openair0_cfg[card].Mod_id = 0; - openair0_cfg[card].num_rb_dl = frame_parms->N_RB_DL; - openair0_cfg[card].clock_source = get_softmodem_params()->clock_source; - openair0_cfg[card].time_source = get_softmodem_params()->timing_source; - openair0_cfg[card].tune_offset = get_softmodem_params()->tune_offset; - openair0_cfg[card].tx_num_channels = min(4, frame_parms->nb_antennas_tx); - openair0_cfg[card].rx_num_channels = min(4, frame_parms->nb_antennas_rx); + cfg->Mod_id = 0; + cfg->num_rb_dl = frame_parms->N_RB_DL; + cfg->clock_source = get_softmodem_params()->clock_source; + cfg->time_source = get_softmodem_params()->timing_source; + cfg->tune_offset = get_softmodem_params()->tune_offset; + cfg->tx_num_channels = min(4, frame_parms->nb_antennas_tx); + cfg->rx_num_channels = min(4, frame_parms->nb_antennas_rx); LOG_I(PHY, "HW: Configuring card %d, sample_rate %f, tx/rx num_channels %d/%d, duplex_mode %s\n", card, - openair0_cfg[card].sample_rate, - openair0_cfg[card].tx_num_channels, - openair0_cfg[card].rx_num_channels, - duplex_mode_txt[openair0_cfg[card].duplex_mode]); + cfg->sample_rate, + cfg->tx_num_channels, + cfg->rx_num_channels, + duplex_mode_txt[cfg->duplex_mode]); if (is_sidelink) { dl_carrier = frame_parms->dl_CarrierFreq; @@ -291,16 +290,18 @@ static void init_openair0() } else nr_get_carrier_frequencies(PHY_vars_UE_g[0][0], &dl_carrier, &ul_carrier); - nr_rf_card_config_freq(&openair0_cfg[card], ul_carrier, dl_carrier, freq_off); + nr_rf_card_config_freq(cfg, ul_carrier, dl_carrier, freq_off); - nr_rf_card_config_gain(&openair0_cfg[card], rx_gain_off); + nr_rf_card_config_gain(cfg, rx_gain_off); - openair0_cfg[card].configFilename = get_softmodem_params()->rf_config_file; - - if (get_nrUE_params()->usrp_args) openair0_cfg[card].sdr_addrs = get_nrUE_params()->usrp_args; - if (get_nrUE_params()->tx_subdev) openair0_cfg[card].tx_subdev = get_nrUE_params()->tx_subdev; - if (get_nrUE_params()->rx_subdev) openair0_cfg[card].rx_subdev = get_nrUE_params()->rx_subdev; + cfg->configFilename = get_softmodem_params()->rf_config_file; + if (get_nrUE_params()->usrp_args) + cfg->sdr_addrs = get_nrUE_params()->usrp_args; + if (get_nrUE_params()->tx_subdev) + cfg->tx_subdev = get_nrUE_params()->tx_subdev; + if (get_nrUE_params()->rx_subdev) + cfg->rx_subdev = get_nrUE_params()->rx_subdev; } } @@ -388,7 +389,6 @@ int main(int argc, char **argv) } //set_softmodem_sighandler(); CONFIG_SETRTFLAG(CONFIG_NOEXITONHELP); - memset(openair0_cfg,0,sizeof(openair0_config_t)*MAX_CARDS); memset(tx_max_power,0,sizeof(int)*MAX_NUM_CCs); // initialize logging logInit(); @@ -427,12 +427,11 @@ int main(int argc, char **argv) char *pckg = strdup(OAI_PACKAGE_VERSION); LOG_I(HW, "Version: %s\n", pckg); - PHY_vars_UE_g = malloc(sizeof(*PHY_vars_UE_g) * NB_UE_INST); + PHY_vars_UE_g = calloc_or_fail(NB_UE_INST, sizeof(*PHY_vars_UE_g)); for (int inst = 0; inst < NB_UE_INST; inst++) { - PHY_vars_UE_g[inst] = malloc(sizeof(*PHY_vars_UE_g[inst]) * MAX_NUM_CCs); + PHY_vars_UE_g[inst] = calloc_or_fail(MAX_NUM_CCs, sizeof(*PHY_vars_UE_g[inst])); for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { - PHY_vars_UE_g[inst][CC_id] = malloc(sizeof(*PHY_vars_UE_g[inst][CC_id])); - memset(PHY_vars_UE_g[inst][CC_id], 0, sizeof(*PHY_vars_UE_g[inst][CC_id])); + PHY_vars_UE_g[inst][CC_id] = calloc_or_fail(1, sizeof(*PHY_vars_UE_g[inst][CC_id])); // All instances use the same coding interface PHY_vars_UE_g[inst][CC_id]->nrLDPC_coding_interface = nrLDPC_coding_interface; } @@ -542,10 +541,10 @@ int main(int argc, char **argv) get_nrUE_params()->ofdm_offset_divisor); sl_ue_phy_init(UE[CC_id]); } + init_openair0(UE[CC_id]); } } - init_openair0(); lock_memory_to_ram(); if (IS_SOFTMODEM_DOSCOPE) { diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c index 0e186a3bc3..0c617dd79a 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c @@ -448,12 +448,15 @@ int nr_prs_channel_estimation(uint8_t gNB_id, peak_estimator(&chT_interpol[rxAnt][0], NR_PRS_IDFT_OVERSAMP_FACTOR * frame_params->ofdm_symbol_size, &prs_toa, &ch_pwr, mean_val); // adjusting the rx_gains for channel peak power - ch_pwr_dbm = 10 * log10(ch_pwr) + 30 - SQ15_SQUARED_NORM_FACTOR_DB - ((int)openair0_cfg[0].rx_gain[0] - (int)openair0_cfg[0].rx_gain_offset[0]) - dB_fixed(frame_params->ofdm_symbol_size); + ch_pwr_dbm = 10 * log10(ch_pwr) + 30 - SQ15_SQUARED_NORM_FACTOR_DB + - ((int)ue->openair0_cfg[0].rx_gain[0] - (int)ue->openair0_cfg[0].rx_gain_offset[0]) + - dB_fixed(frame_params->ofdm_symbol_size); - prs_meas[rxAnt]->rsrp_dBm = - 10 * log10(prs_meas[rxAnt]->rsrp) + 30 - SQ15_SQUARED_NORM_FACTOR_DB - ((int)openair0_cfg[0].rx_gain[0] - (int)openair0_cfg[0].rx_gain_offset[0]) - dB_fixed(ue->frame_parms.ofdm_symbol_size); + prs_meas[rxAnt]->rsrp_dBm = 10 * log10(prs_meas[rxAnt]->rsrp) + 30 - SQ15_SQUARED_NORM_FACTOR_DB + - ((int)ue->openair0_cfg[0].rx_gain[0] - (int)ue->openair0_cfg[0].rx_gain_offset[0]) + - dB_fixed(ue->frame_parms.ofdm_symbol_size); - //prs measurements + // prs measurements prs_meas[rxAnt]->gNB_id = gNB_id; prs_meas[rxAnt]->sfn = proc->frame_rx; prs_meas[rxAnt]->slot = proc->nr_slot_rx; diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h index da6fd31eb5..212a5d4916 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h @@ -151,6 +151,7 @@ float_t get_nr_RSRP(module_id_t Mod_id,uint8_t CC_id,uint8_t gNB_index); int nr_sl_psbch_rsrp_measurements(sl_nr_ue_phy_params_t *sl_phy_params, NR_DL_FRAME_PARMS *fp, c16_t rxdataF[][fp->samples_per_slot_wCP], - bool use_SSS); + bool use_SSS, + openair0_config_t *openair0_cfg); /** @}*/ #endif diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c b/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c index b6aeba7f76..fcf5484ed7 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c @@ -157,7 +157,9 @@ void nr_ue_measurements(PHY_VARS_NR_UE *ue, ue->measurements.rx_power_avg_dB[gNB_id] = dB_fixed( ue->measurements.rx_power_avg[gNB_id]); ue->measurements.wideband_cqi_tot[gNB_id] = ue->measurements.rx_power_tot_dB[gNB_id] - ue->measurements.n0_power_tot_dB; ue->measurements.wideband_cqi_avg[gNB_id] = ue->measurements.rx_power_avg_dB[gNB_id] - dB_fixed(ue->measurements.n0_power_avg); - ue->measurements.rx_rssi_dBm[gNB_id] = ue->measurements.rx_power_avg_dB[gNB_id] + 30 - SQ15_SQUARED_NORM_FACTOR_DB - ((int)openair0_cfg[0].rx_gain[0] - (int)openair0_cfg[0].rx_gain_offset[0]) - dB_fixed(ue->frame_parms.ofdm_symbol_size); + ue->measurements.rx_rssi_dBm[gNB_id] = ue->measurements.rx_power_avg_dB[gNB_id] + 30 - SQ15_SQUARED_NORM_FACTOR_DB + - ((int)ue->openair0_cfg[0].rx_gain[0] - (int)ue->openair0_cfg[0].rx_gain_offset[0]) + - dB_fixed(ue->frame_parms.ofdm_symbol_size); LOG_D(PHY, "[gNB %d] Slot %d, RSSI %d dB (%d dBm/RE), WBandCQI %d dB, rxPwrAvg %d, n0PwrAvg %d\n", gNB_id, @@ -235,7 +237,7 @@ void nr_ue_ssb_rsrp_measurements(PHY_VARS_NR_UE *ue, uint32_t rsrp_avg = nr_ue_calculate_ssb_rsrp(fp, proc, rxdataF, symbol_offset, fp->ssb_start_subcarrier); float rsrp_db_per_re = 10 * log10(rsrp_avg); - openair0_config_t *cfg0 = &openair0_cfg[0]; + openair0_config_t *cfg0 = &ue->openair0_cfg[0]; ue->measurements.ssb_rsrp_dBm[ssb_index] = rsrp_db_per_re + 30 - SQ15_SQUARED_NORM_FACTOR_DB - ((int)cfg0->rx_gain[0] - (int)cfg0->rx_gain_offset[0]) @@ -271,8 +273,8 @@ void nr_ue_rrc_measurements(PHY_VARS_NR_UE *ue, const uint8_t k_length = 8; uint8_t l_sss = (ue->symbol_offset + 2) % ue->frame_parms.symbols_per_slot; unsigned int ssb_offset = ue->frame_parms.first_carrier_offset + ue->frame_parms.ssb_start_subcarrier; - double rx_gain = openair0_cfg[0].rx_gain[0]; - double rx_gain_offset = openair0_cfg[0].rx_gain_offset[0]; + double rx_gain = ue->openair0_cfg[0].rx_gain[0]; + double rx_gain_offset = ue->openair0_cfg[0].rx_gain_offset[0]; ue->measurements.n0_power_tot = 0; @@ -344,7 +346,8 @@ void nr_ue_rrc_measurements(PHY_VARS_NR_UE *ue, int nr_sl_psbch_rsrp_measurements(sl_nr_ue_phy_params_t *sl_phy_params, NR_DL_FRAME_PARMS *fp, c16_t rxdataF[][fp->samples_per_slot_wCP], - bool use_SSS) + bool use_SSS, + openair0_config_t *openair0_cfg) { SL_NR_UE_PSBCH_t *psbch_rx = &sl_phy_params->psbch; uint8_t numsym = (fp->Ncp) ? SL_NR_NUM_SYMBOLS_SSB_EXT_CP : SL_NR_NUM_SYMBOLS_SSB_NORMAL_CP; diff --git a/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c b/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c index bb576460f6..295718e22c 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c +++ b/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c @@ -238,7 +238,7 @@ static int nr_get_csi_rs_signal(const PHY_VARS_NR_UE *ue, *rsrp = rsrp_sum/meas_count; *rsrp_dBm = dB_fixed(*rsrp) + 30 - SQ15_SQUARED_NORM_FACTOR_DB - - ((int)openair0_cfg[0].rx_gain[0] - (int)openair0_cfg[0].rx_gain_offset[0]) - dB_fixed(ue->frame_parms.ofdm_symbol_size); + - ((int)ue->openair0_cfg[0].rx_gain[0] - (int)ue->openair0_cfg[0].rx_gain_offset[0]) - dB_fixed(ue->frame_parms.ofdm_symbol_size); #ifdef NR_CSIRS_DEBUG LOG_I(NR_PHY, "RSRP = %i (%i dBm)\n", *rsrp, *rsrp_dBm); diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync_sl.c b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync_sl.c index 2568a54a37..2a2200557e 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync_sl.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync_sl.c @@ -518,7 +518,7 @@ nr_initial_sync_t sl_nr_slss_search(PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc, sync_params->DFN, sync_params->slot_offset); - UE->adjust_rxgain = nr_sl_psbch_rsrp_measurements(sl_ue, frame_parms, rxdataF, false); + UE->adjust_rxgain = nr_sl_psbch_rsrp_measurements(sl_ue, frame_parms, rxdataF, false, UE->openair0_cfg); UE->init_sync_frame = sync_params->remaining_frames; result.rx_offset = sync_params->rx_offset; diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h index 9d8683481d..6ae3ddc37a 100644 --- a/openair1/PHY/defs_nr_UE.h +++ b/openair1/PHY/defs_nr_UE.h @@ -336,6 +336,7 @@ typedef struct { /// Top-level PHY Data Structure for UE typedef struct PHY_VARS_NR_UE_s { + openair0_config_t openair0_cfg[MAX_CARDS]; /// \brief Module ID indicator for this instance uint8_t Mod_id; /// \brief Component carrier ID for this PHY instance diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue_sl.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue_sl.c index 13b081385d..bd2ac08b81 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue_sl.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue_sl.c @@ -227,7 +227,7 @@ int psbch_pscch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr sym = (sym == 0) ? 5 : sym + 1; } - ue->adjust_rxgain = nr_sl_psbch_rsrp_measurements(sl_phy_params, fp, rxdataF, false); + ue->adjust_rxgain = nr_sl_psbch_rsrp_measurements(sl_phy_params, fp, rxdataF, false, ue->openair0_cfg); LOG_D(NR_PHY, " ------ Decode SL-MIB: frame.slot %d.%d ------ \n", frame_rx % 1024, nr_slot_rx); From acb2ae93bd9cb392358add33460525a957c40ed1 Mon Sep 17 00:00:00 2001 From: Bartosz Podrygajlo Date: Sat, 17 May 2025 14:24:47 +0200 Subject: [PATCH 577/964] Add RFSim 10 UEs/process RFSim test Add an RFSim test for 10 UEs in a single process. --- ci-scripts/ci_infra.yaml | 90 ++++++++ .../xml_files/container_5g_rfsim_multiue.xml | 210 ++++++++++++++++++ .../docker-compose.yaml | 144 ++++++++++++ .../5g_rfsimulator_multiue/nrue.uicc.conf | 75 +++++++ 4 files changed, 519 insertions(+) create mode 100644 ci-scripts/xml_files/container_5g_rfsim_multiue.xml create mode 100644 ci-scripts/yaml_files/5g_rfsimulator_multiue/docker-compose.yaml create mode 100644 ci-scripts/yaml_files/5g_rfsimulator_multiue/nrue.uicc.conf diff --git a/ci-scripts/ci_infra.yaml b/ci-scripts/ci_infra.yaml index aabba119ec..7a6999f503 100644 --- a/ci-scripts/ci_infra.yaml +++ b/ci-scripts/ci_infra.yaml @@ -455,3 +455,93 @@ l2sim4g_ext_dn: Host: "%%current_host%%" NetworkScript: docker exec l2sim4g-trf-gen ip a show dev eth0 CmdPrefix: docker exec l2sim4g-trf-gen + +rfsim5g_multiue1: + Host: "%%current_host%%" + NetworkScript: docker exec rfsim5g-oai-nr-ue ip a show dev oaitun_ue1 + CmdPrefix: docker exec rfsim5g-oai-nr-ue + IF: oaitun_ue1 + AttachScript: docker start rfsim5g-oai-nr-ue + DetachScript: docker stop rfsim5g-oai-nr-ue + MTU: 1500 + +rfsim5g_multiue2: + Host: "%%current_host%%" + NetworkScript: docker exec rfsim5g-oai-nr-ue ip a show dev oaitun_ue2 + CmdPrefix: docker exec rfsim5g-oai-nr-ue + IF: oaitun_ue2 + AttachScript: true + DetachScript: true + MTU: 1500 + +rfsim5g_multiue3: + Host: "%%current_host%%" + NetworkScript: docker exec rfsim5g-oai-nr-ue ip a show dev oaitun_ue3 + CmdPrefix: docker exec rfsim5g-oai-nr-ue + IF: oaitun_ue3 + AttachScript: "true" + DetachScript: "true" + MTU: 1500 + +rfsim5g_multiue4: + Host: "%%current_host%%" + NetworkScript: docker exec rfsim5g-oai-nr-ue ip a show dev oaitun_ue4 + CmdPrefix: docker exec rfsim5g-oai-nr-ue + IF: oaitun_ue4 + AttachScript: "true" + DetachScript: "true" + MTU: 1500 + +rfsim5g_multiue5: + Host: "%%current_host%%" + NetworkScript: docker exec rfsim5g-oai-nr-ue ip a show dev oaitun_ue5 + CmdPrefix: docker exec rfsim5g-oai-nr-ue + IF: oaitun_ue5 + AttachScript: "true" + DetachScript: "true" + MTU: 1500 + +rfsim5g_multiue6: + Host: "%%current_host%%" + NetworkScript: docker exec rfsim5g-oai-nr-ue ip a show dev oaitun_ue6 + CmdPrefix: docker exec rfsim5g-oai-nr-ue + IF: oaitun_ue6 + AttachScript: "true" + DetachScript: "true" + MTU: 1500 + +rfsim5g_multiue7: + Host: "%%current_host%%" + NetworkScript: docker exec rfsim5g-oai-nr-ue ip a show dev oaitun_ue7 + CmdPrefix: docker exec rfsim5g-oai-nr-ue + IF: oaitun_ue7 + AttachScript: "true" + DetachScript: "true" + MTU: 1500 + +rfsim5g_multiue8: + Host: "%%current_host%%" + NetworkScript: docker exec rfsim5g-oai-nr-ue ip a show dev oaitun_ue8 + CmdPrefix: docker exec rfsim5g-oai-nr-ue + IF: oaitun_ue8 + AttachScript: "true" + DetachScript: "true" + MTU: 1500 + +rfsim5g_multiue9: + Host: "%%current_host%%" + NetworkScript: docker exec rfsim5g-oai-nr-ue ip a show dev oaitun_ue9 + CmdPrefix: docker exec rfsim5g-oai-nr-ue + IF: oaitun_ue9 + AttachScript: "true" + DetachScript: "true" + MTU: 1500 + +rfsim5g_multiue10: + Host: "%%current_host%%" + NetworkScript: docker exec rfsim5g-oai-nr-ue ip a show dev oaitun_ue10 + CmdPrefix: docker exec rfsim5g-oai-nr-ue + IF: oaitun_ue10 + AttachScript: "true" + DetachScript: "true" + MTU: 1500 diff --git a/ci-scripts/xml_files/container_5g_rfsim_multiue.xml b/ci-scripts/xml_files/container_5g_rfsim_multiue.xml new file mode 100644 index 0000000000..e7376ad840 --- /dev/null +++ b/ci-scripts/xml_files/container_5g_rfsim_multiue.xml @@ -0,0 +1,210 @@ + + + rfsim-5gnr-tdd-multiue + Monolithic SA TDD gNB multiue + wrench + + 111111 + 800813 + 000001 + 000002 + 000003 + 000008 + 020001 + 020002 + 020003 + 020004 + 020105 + 444445 + 030001 + 030002 + 444444 + 100001 + 222222 + + + + + Pull_Local_Registry + Pull Images from Local Registry + 0 + oai-gnb-asan oai-nr-ue + + + Create_Workspace + Create new Workspace + 0 + 0 + + + Deploy_Object + Deploy OAI 5G CoreNetwork + ci-scripts/yaml_files/5g_rfsimulator_multiue + mysql oai-amf oai-smf oai-upf oai-ext-dn + 0 + 0 + + + + Deploy_Object + Deploy OAI 5G gNB RF sim SA + ci-scripts/yaml_files/5g_rfsimulator_multiue + oai-gnb + 0 + 0 + + + + Deploy_Object + Deploy OAI 5G NR-UE RF sim SA + ci-scripts/yaml_files/5g_rfsimulator_multiue + oai-nr-ue + 0 + 0 + + + + Attach_UE + Attach OAI UE (Wait for IP) + rfsim5g_multiue1 rfsim5g_multiue2 rfsim5g_multiue3 rfsim5g_multiue4 rfsim5g_multiue5 rfsim5g_multiue6 rfsim5g_multiue7 rfsim5g_multiue8 rfsim5g_multiue9 rfsim5g_multiue10 + cacofonix cacofonix cacofonix cacofonix cacofonix cacofonix cacofonix cacofonix cacofonix cacofonix + + + + Ping + Ping ext-dn from NR-UE + rfsim5g_multiue1 + cacofonix + rfsim5g_ext_dn + cacofonix + -c 20 -i 0.25 + 5 + + + + Ping + Ping NR-UE from ext-dn + rfsim5g_ext_dn + cacofonix + rfsim5g_multiue1 + cacofonix + -c 20 -i 0.25 + 5 + + + + Ping + Ping ext-dn from Second NR-UE + rfsim5g_multiue2 + cacofonix + rfsim5g_ext_dn + cacofonix + -c 20 -i 0.25 + 5 + + + + Ping + Ping Second NR-UE from ext-dn + rfsim5g_ext_dn + cacofonix + rfsim5g_multiue2 + cacofonix + -c 20 -i 0.25 + 5 + + + + Ping + Ping ext-dn from both UEs + rfsim5g_multiue1 rfsim5g_multiue2 + cacofonix cacofonix + rfsim5g_ext_dn + cacofonix + -c 20 -i 0.25 + 5 + + + + Ping + Ping ext-dn from all UEs + rfsim5g_multiue1 rfsim5g_multiue2 rfsim5g_multiue3 rfsim5g_multiue4 rfsim5g_multiue5 rfsim5g_multiue6 rfsim5g_multiue7 rfsim5g_multiue8 rfsim5g_multiue9 rfsim5g_multiue10 + cacofonix cacofonix cacofonix cacofonix cacofonix cacofonix cacofonix cacofonix cacofonix cacofonix + rfsim5g_ext_dn + cacofonix + -c 20 -i 0.25 -s 1016 + 5 + + + + Iperf + Iperf (DL/3Mbps/UDP)(30 sec) + -u -b 3M -t 20 -R + rfsim5g_multiue1 + cacofonix + rfsim5g_ext_dn + cacofonix + 5 + 90 + + + + Iperf + Iperf (UL/1Mbps/UDP)(30 sec) + -u -b 1M -t 20 + rfsim5g_multiue1 + cacofonix + rfsim5g_ext_dn + cacofonix + 5 + 90 + + + + Detach_UE + Detach OAI UEs + rfsim5g_multiue1 + cacofonix + + + + Undeploy_Object + true + Undeploy all OAI 5G stack + ci-scripts/yaml_files/5g_rfsimulator_multiue + 1,0,0,0 + 1,0,0,0 + 0 + 0 + + + + Clean_Test_Server_Images + true + Clean Test Images on Test Server + 0 + oai-gnb-asan oai-nr-ue + + + diff --git a/ci-scripts/yaml_files/5g_rfsimulator_multiue/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_multiue/docker-compose.yaml new file mode 100644 index 0000000000..6f5bc337bc --- /dev/null +++ b/ci-scripts/yaml_files/5g_rfsimulator_multiue/docker-compose.yaml @@ -0,0 +1,144 @@ +services: + mysql: + container_name: "rfsim5g-mysql" + image: mysql:8.0 + volumes: + - ../5g_rfsimulator/oai_db.sql:/docker-entrypoint-initdb.d/oai_db.sql + - ../5g_rfsimulator/mysql-healthcheck.sh:/tmp/mysql-healthcheck.sh + environment: + - TZ=Europe/Paris + - MYSQL_DATABASE=oai_db + - MYSQL_USER=test + - MYSQL_PASSWORD=test + - MYSQL_ROOT_PASSWORD=linux + healthcheck: + test: /bin/bash -c "/tmp/mysql-healthcheck.sh" + interval: 10s + timeout: 5s + retries: 30 + networks: + public_net: + ipv4_address: 192.168.71.131 + oai-amf: + container_name: "rfsim5g-oai-amf" + image: oaisoftwarealliance/oai-amf:v2.1.10 + environment: + - TZ=Europe/paris + volumes: + - ../5g_rfsimulator/mini_nonrf_config.yaml:/openair-amf/etc/config.yaml + depends_on: + - mysql + networks: + public_net: + ipv4_address: 192.168.71.132 + oai-smf: + container_name: "rfsim5g-oai-smf" + image: oaisoftwarealliance/oai-smf:v2.1.10 + environment: + - TZ=Europe/Paris + volumes: + - ../5g_rfsimulator/mini_nonrf_config.yaml:/openair-smf/etc/config.yaml + depends_on: + - oai-amf + networks: + public_net: + ipv4_address: 192.168.71.133 + oai-upf: + container_name: "rfsim5g-oai-upf" + image: oaisoftwarealliance/oai-upf:v2.1.10 + environment: + - TZ=Europe/Paris + volumes: + - ../5g_rfsimulator/mini_nonrf_config.yaml:/openair-upf/etc/config.yaml + depends_on: + - oai-smf + cap_add: + - NET_ADMIN + - SYS_ADMIN + cap_drop: + - ALL + privileged: true + networks: + public_net: + ipv4_address: 192.168.71.134 + traffic_net: + ipv4_address: 192.168.72.134 + oai-ext-dn: + privileged: true + container_name: rfsim5g-oai-ext-dn + image: oaisoftwarealliance/trf-gen-cn5g:focal + entrypoint: /bin/bash -c \ + "iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE;"\ + "ip route add 12.1.1.0/24 via 192.168.72.134 dev eth0; sleep infinity" + depends_on: + - oai-upf + networks: + traffic_net: + ipv4_address: 192.168.72.135 + healthcheck: + test: /bin/bash -c "ping -c 2 192.168.72.134" + interval: 10s + timeout: 5s + retries: 5 + oai-gnb: + image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop} + container_name: rfsim5g-oai-gnb + cap_drop: + - ALL + environment: + USE_ADDITIONAL_OPTIONS: -E --rfsim --log_config.global_log_options level,nocolor,time + ASAN_OPTIONS: detect_leaks=0 + depends_on: + - oai-ext-dn + networks: + public_net: + ipv4_address: 192.168.71.140 + volumes: + - ../../conf_files/gnb.sa.band78.106prb.rfsim.yaml:/opt/oai-gnb/etc/gnb.yaml + healthcheck: + test: /bin/bash -c "pgrep nr-softmodem" + interval: 10s + timeout: 5s + retries: 5 + oai-nr-ue: + image: ${REGISTRY:-oaisoftwarealliance}/${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} + container_name: rfsim5g-oai-nr-ue + cap_drop: + - ALL + cap_add: + - NET_ADMIN # for interface bringup + - NET_RAW # for ping + environment: + USE_ADDITIONAL_OPTIONS: -E --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001100 -C 3319680000 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time --num-ues 10 + depends_on: + - oai-gnb + networks: + public_net: + ipv4_address: 192.168.71.150 + devices: + - /dev/net/tun:/dev/net/tun + volumes: + - ./nrue.uicc.conf:/opt/oai-nr-ue/etc/nr-ue.conf + healthcheck: + test: /bin/bash -c "pgrep nr-uesoftmodem" + interval: 10s + timeout: 5s + retries: 5 + +networks: + public_net: + driver: bridge + name: rfsim5g-oai-public-net + ipam: + config: + - subnet: 192.168.71.128/26 + driver_opts: + com.docker.network.bridge.name: "rfsim5g-public" + traffic_net: + driver: bridge + name: rfsim5g-oai-traffic-net + ipam: + config: + - subnet: 192.168.72.128/26 + driver_opts: + com.docker.network.bridge.name: "rfsim5g-traffic" diff --git a/ci-scripts/yaml_files/5g_rfsimulator_multiue/nrue.uicc.conf b/ci-scripts/yaml_files/5g_rfsimulator_multiue/nrue.uicc.conf new file mode 100644 index 0000000000..92ccf9dca2 --- /dev/null +++ b/ci-scripts/yaml_files/5g_rfsimulator_multiue/nrue.uicc.conf @@ -0,0 +1,75 @@ +uicc0 = { + imsi = "208990100001100"; + key = "fec86ba6eb707ed08905757b1bb44b8f"; + opc= "C42449363BBAD02B66D16BC975D77CC1"; + dnn= "oai"; + nssai_sst=1; +} +uicc1 = { + imsi = "208990100001101"; + key = "fec86ba6eb707ed08905757b1bb44b8f"; + opc= "C42449363BBAD02B66D16BC975D77CC1"; + dnn= "oai"; + nssai_sst=1; +} +uicc2 = { + imsi = "208990100001102"; + key = "fec86ba6eb707ed08905757b1bb44b8f"; + opc= "C42449363BBAD02B66D16BC975D77CC1"; + dnn= "oai"; + nssai_sst=1; +} +uicc3 = { + imsi = "208990100001103"; + key = "fec86ba6eb707ed08905757b1bb44b8f"; + opc= "C42449363BBAD02B66D16BC975D77CC1"; + dnn= "oai"; + nssai_sst=1; +} +uicc4 = { + imsi = "208990100001104"; + key = "fec86ba6eb707ed08905757b1bb44b8f"; + opc= "C42449363BBAD02B66D16BC975D77CC1"; + dnn= "oai"; + nssai_sst=1; +} +uicc5 = { + imsi = "208990100001105"; + key = "fec86ba6eb707ed08905757b1bb44b8f"; + opc= "C42449363BBAD02B66D16BC975D77CC1"; + dnn= "oai"; + nssai_sst=1; +} +uicc6 = { + imsi = "208990100001106"; + key = "fec86ba6eb707ed08905757b1bb44b8f"; + opc= "C42449363BBAD02B66D16BC975D77CC1"; + dnn= "oai"; + nssai_sst=1; +} +uicc7 = { + imsi = "208990100001107"; + key = "fec86ba6eb707ed08905757b1bb44b8f"; + opc= "C42449363BBAD02B66D16BC975D77CC1"; + dnn= "oai"; + nssai_sst=1; +} +uicc8 = { + imsi = "208990100001108"; + key = "fec86ba6eb707ed08905757b1bb44b8f"; + opc= "C42449363BBAD02B66D16BC975D77CC1"; + dnn= "oai"; + nssai_sst=1; +} +uicc9 = { + imsi = "208990100001109"; + key = "fec86ba6eb707ed08905757b1bb44b8f"; + opc= "C42449363BBAD02B66D16BC975D77CC1"; + dnn= "oai"; + nssai_sst=1; +} + + + +thread-pool: "-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1" + From cd67c33ba296cdc7c790f82bcd012f8def28da96 Mon Sep 17 00:00:00 2001 From: Bartosz Podrygajlo Date: Mon, 26 May 2025 09:52:10 +0200 Subject: [PATCH 578/964] Fix NR UE mislabeling MSG2 as DLSCH PDU --- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 9 +++++++-- openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 783ae0489f..741842319e 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -755,8 +755,13 @@ static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac, dlsch_pdu->SubcarrierSpacing = mac->mib->subCarrierSpacingCommon + 2; } else { dlsch_pdu->SubcarrierSpacing = current_DL_BWP->scs; - if (nr_timer_is_active(&mac->ra.response_window_timer) && rnti_type == TYPE_RA_RNTI_) { - dl_conf_req->pdu_type = FAPI_NR_DL_CONFIG_TYPE_RA_DLSCH; + if (rnti_type == TYPE_RA_RNTI_) { + if (nr_timer_is_active(&mac->ra.response_window_timer)) { + dl_conf_req->pdu_type = FAPI_NR_DL_CONFIG_TYPE_RA_DLSCH; + } else { + // Discard the DCI + return -1; + } } else { dl_conf_req->pdu_type = FAPI_NR_DL_CONFIG_TYPE_DLSCH; } diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c index de5ae571ca..dcd4a85f5d 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c @@ -1312,7 +1312,7 @@ static uint32_t nr_ue_dl_processing(NR_UE_MAC_INST_t *mac, nr_downlink_indicatio // resume RAR response window timer if MSG2 decoding failed nr_timer_suspension(&mac->ra.response_window_timer); } else { - LOG_I(PHY, "RAR-Msg2 decoded\n"); + LOG_I(PHY, "[UE %d] RAR-Msg2 decoded\n", mac->ue_id); } ret_mask |= (handle_dlsch(mac, dl_info, i)) << FAPI_NR_RX_PDU_TYPE_RAR; break; From 433d5c109947a218f41cca2c587d0c1aabfd6313 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Fri, 25 Jul 2025 17:44:05 +0200 Subject: [PATCH 579/964] CI: update XML and yaml files for 10 UEs/process RFSim test --- .../xml_files/container_5g_rfsim_multiue.xml | 36 +++++++++---------- .../docker-compose.yaml | 2 ++ 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/ci-scripts/xml_files/container_5g_rfsim_multiue.xml b/ci-scripts/xml_files/container_5g_rfsim_multiue.xml index e7376ad840..79d85e154c 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_multiue.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_multiue.xml @@ -88,16 +88,16 @@ Attach_UE Attach OAI UE (Wait for IP) rfsim5g_multiue1 rfsim5g_multiue2 rfsim5g_multiue3 rfsim5g_multiue4 rfsim5g_multiue5 rfsim5g_multiue6 rfsim5g_multiue7 rfsim5g_multiue8 rfsim5g_multiue9 rfsim5g_multiue10 - cacofonix cacofonix cacofonix cacofonix cacofonix cacofonix cacofonix cacofonix cacofonix cacofonix + acamas acamas acamas acamas acamas acamas acamas acamas acamas acamas Ping Ping ext-dn from NR-UE rfsim5g_multiue1 - cacofonix + acamas rfsim5g_ext_dn - cacofonix + acamas -c 20 -i 0.25 5 @@ -106,9 +106,9 @@ Ping Ping NR-UE from ext-dn rfsim5g_ext_dn - cacofonix + acamas rfsim5g_multiue1 - cacofonix + acamas -c 20 -i 0.25 5 @@ -117,9 +117,9 @@ Ping Ping ext-dn from Second NR-UE rfsim5g_multiue2 - cacofonix + acamas rfsim5g_ext_dn - cacofonix + acamas -c 20 -i 0.25 5 @@ -128,9 +128,9 @@ Ping Ping Second NR-UE from ext-dn rfsim5g_ext_dn - cacofonix + acamas rfsim5g_multiue2 - cacofonix + acamas -c 20 -i 0.25 5 @@ -139,9 +139,9 @@ Ping Ping ext-dn from both UEs rfsim5g_multiue1 rfsim5g_multiue2 - cacofonix cacofonix + acamas acamas rfsim5g_ext_dn - cacofonix + acamas -c 20 -i 0.25 5 @@ -150,9 +150,9 @@ Ping Ping ext-dn from all UEs rfsim5g_multiue1 rfsim5g_multiue2 rfsim5g_multiue3 rfsim5g_multiue4 rfsim5g_multiue5 rfsim5g_multiue6 rfsim5g_multiue7 rfsim5g_multiue8 rfsim5g_multiue9 rfsim5g_multiue10 - cacofonix cacofonix cacofonix cacofonix cacofonix cacofonix cacofonix cacofonix cacofonix cacofonix + acamas acamas acamas acamas acamas acamas acamas acamas acamas acamas rfsim5g_ext_dn - cacofonix + acamas -c 20 -i 0.25 -s 1016 5 @@ -162,9 +162,9 @@ Iperf (DL/3Mbps/UDP)(30 sec) -u -b 3M -t 20 -R rfsim5g_multiue1 - cacofonix + acamas rfsim5g_ext_dn - cacofonix + acamas 5 90 @@ -174,9 +174,9 @@ Iperf (UL/1Mbps/UDP)(30 sec) -u -b 1M -t 20 rfsim5g_multiue1 - cacofonix + acamas rfsim5g_ext_dn - cacofonix + acamas 5 90 @@ -185,7 +185,7 @@ Detach_UE Detach OAI UEs rfsim5g_multiue1 - cacofonix + acamas diff --git a/ci-scripts/yaml_files/5g_rfsimulator_multiue/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_multiue/docker-compose.yaml index 6f5bc337bc..d0b76fc165 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_multiue/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_multiue/docker-compose.yaml @@ -61,8 +61,10 @@ services: networks: public_net: ipv4_address: 192.168.71.134 + interface_name: eth0 traffic_net: ipv4_address: 192.168.72.134 + interface_name: eth1 oai-ext-dn: privileged: true container_name: rfsim5g-oai-ext-dn From fcd001398165dd47494b375749321a0ce031f449 Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Mon, 21 Jul 2025 16:28:09 +0200 Subject: [PATCH 580/964] T: add a tracer 'gnb_mac' To see MAC scheduling decisions. May be useful for debugging. --- common/utils/T/.gitignore | 1 + common/utils/T/tracer/CMakeLists.txt | 6 +- common/utils/T/tracer/Makefile | 17 +- common/utils/T/tracer/gnb_mac.c | 332 +++++++++++++++++++++++++++ 4 files changed, 349 insertions(+), 7 deletions(-) create mode 100644 common/utils/T/tracer/gnb_mac.c diff --git a/common/utils/T/.gitignore b/common/utils/T/.gitignore index 60264a9c4a..7ac6cc75bd 100644 --- a/common/utils/T/.gitignore +++ b/common/utils/T/.gitignore @@ -3,6 +3,7 @@ genids tracer/enb tracer/gnb +tracer/gnb_mac tracer/extract_config tracer/record tracer/replay diff --git a/common/utils/T/tracer/CMakeLists.txt b/common/utils/T/tracer/CMakeLists.txt index 60266b5fa9..56568c905e 100644 --- a/common/utils/T/tracer/CMakeLists.txt +++ b/common/utils/T/tracer/CMakeLists.txt @@ -62,6 +62,10 @@ if(T_TRACER_GUI) tracer_logger tracer_view tracer_events) target_link_libraries(gnb PRIVATE png) + add_executable(gnb_mac gnb_mac.c) + target_link_libraries(gnb_mac PRIVATE tracer_utils tracer_filter tracer_gui + tracer_logger tracer_view tracer_events) + add_executable(ue ue.c) target_link_libraries(ue PRIVATE tracer_utils tracer_view tracer_gui tracer_logger tracer_filter tracer_events) @@ -77,5 +81,5 @@ if(T_TRACER_GUI) add_subdirectory(gui) - add_dependencies(T_tools enb gnb ue vcd to_vcd) + add_dependencies(T_tools enb gnb gnb_mac ue vcd to_vcd) endif() diff --git a/common/utils/T/tracer/Makefile b/common/utils/T/tracer/Makefile index 6777be7152..ce99eabbe8 100644 --- a/common/utils/T/tracer/Makefile +++ b/common/utils/T/tracer/Makefile @@ -8,7 +8,7 @@ XLIBS=-lX11 -lpng -lXft all: record replay extract_config textlog enb ue vcd macpdu2wireshark \ extract_input_subframe extract_output_subframe to_vcd extract multi \ - gnb t_tracer_app_gnb t_tracer_app_ue + gnb t_tracer_app_gnb t_tracer_app_ue gnb_mac record: utils.o record.o database.o configuration.o $(CC) $(CFLAGS) -o record $^ $(LIBS) @@ -65,14 +65,18 @@ gnb: utils.o gnb.o database.o event.o handler.o configuration.o \ filter/filter.a $(CC) $(CFLAGS) -o gnb $^ $(LIBS) $(XLIBS) -t_tracer_app_gnb: utils.o t_tracer_app_gnb.o database.o event.o handler.o configuration.o \ - logger/logger.a filter/filter.a +t_tracer_app_gnb: utils.o t_tracer_app_gnb.o database.o event.o handler.o \ + configuration.o logger/logger.a filter/filter.a $(CC) $(CFLAGS) -o t_tracer_app_gnb $^ $(LIBS) $(XLIBS) -t_tracer_app_ue: utils.o t_tracer_app_ue.o database.o event.o handler.o configuration.o \ - logger/logger.a filter/filter.a +t_tracer_app_ue: utils.o t_tracer_app_ue.o database.o event.o handler.o \ + configuration.o logger/logger.a filter/filter.a $(CC) $(CFLAGS) -o t_tracer_app_ue $^ $(LIBS) $(XLIBS) +gnb_mac: gnb_mac.o gui/gui.a view/view.a logger/logger.a filter/filter.a \ + utils.o database.o configuration.o handler.o event.o + $(CC) $(CFLAGS) -o gnb_mac $^ $(LIBS) $(XLIBS) + multi.o: ../incgen/T_IDs.h ../incgen/T_IDs.h: ../T_messages.txt @@ -98,7 +102,8 @@ filter/filter.a: clean: rm -f *.o core tracer_remote textlog enb ue vcd record replay rm -f extract_config macpdu2wireshark extract_input_subframe - rm -f extract_output_subframe to_vcd extract multi gnb t_tracer_app_gnb t_tracer_app_ue + rm -f extract_output_subframe to_vcd extract multi gnb + rm -f t_tracer_app_gnb t_tracer_app_ue gnb_mac cd gui && $(MAKE) clean cd view && $(MAKE) clean cd logger && $(MAKE) clean diff --git a/common/utils/T/tracer/gnb_mac.c b/common/utils/T/tracer/gnb_mac.c new file mode 100644 index 0000000000..84f29b8f82 --- /dev/null +++ b/common/utils/T/tracer/gnb_mac.c @@ -0,0 +1,332 @@ +#include +#include +#include +#include + +#include "utils.h" +#include "gui/gui.h" +#include "view/view.h" +#include "logger/logger.h" +#include "filter/filter.h" +#include "database.h" +#include "configuration.h" +#include "handler.h" + +typedef struct { + int used; +} ue_list_item; + +typedef struct { + widget *container; +} gnb_gui; + +typedef struct { + int socket; + gui *g; + gnb_gui *gg; + event_handler *h; + void *database; + ue_list_item ues[65536]; + int rnti_arg; +} gnb_data; + +void *gui_thread(void *_g) +{ + gui *g = _g; + gui_loop(g); + return 0; +} + +void add_ue(gnb_data *gd, int rnti, int lcid) +{ + event_handler *h = gd->h; + void *database = gd->database; + gnb_gui *gg = gd->gg; + gui *g = gd->g; + widget *line; + widget *w, *w2, *col; + view *v; + logger *l; + + gd->ues[rnti].used = 1; + + line = new_container(g, HORIZONTAL); + widget_add_child(g, gg->container, line, -1); + + /* label */ + char s[512]; + sprintf(s, "UE %d", rnti); + widget *label = new_label(g, s); + widget_add_child(g, line, label, -1); + + /* DL MCS */ + w = new_xy_plot(g, 128, 55, "DL mcs", 20); + xy_plot_set_range(g, w, 0, 1024*20, -2, 30); + widget_add_child(g, line, w, -1); + l = new_ticked_ttilog(h, database, "GNB_PHY_DL_TICK", "frame", "slot", + "GNB_MAC_DL", "mcs", 0, -1); + v = new_view_tti(10, g, w, new_color(g, "#0c0c72"), 20); + logger_add_view(l, v); + logger_set_filter(l, + filter_eq( + filter_evarg(database, "GNB_MAC_DL", "rnti"), + filter_int(rnti))); + + /* DL TBS */ + col = new_container(g, VERTICAL); + widget_add_child(g, line, col, -1); + w = new_xy_plot(g, 70, 10, "DL tbs", 35); + w2 = new_textarea(g, 70, 11, 64); + xy_plot_set_range(g, w, 0, 1024*20, 0, 1000); + xy_plot_set_tick_type(g, w, XY_PLOT_SCROLL_TICK); + widget_add_child(g, col, w2, -1); + widget_add_child(g, col, w, -1); + container_set_child_growable(g, col, w, 1); + l = new_ticked_ttilog(h, database, "GNB_PHY_DL_TICK", "frame", "slot", + "GNB_MAC_DL", "tbs", 0, -1); + v = new_view_tti(10, g, w, new_color(g, "#0c0c72"), 20); + view_tti_enable_automax(v, w2); + logger_add_view(l, v); + logger_set_filter(l, + filter_eq( + filter_evarg(database, "GNB_MAC_DL", "rnti"), + filter_int(rnti))); + + /* DL lcid throughput */ + col = new_container(g, VERTICAL); + widget_add_child(g, line, col, -1); + sprintf(s, "DL lcid %d", lcid); + w = new_xy_plot(g, 70, 10, s, 35); + w2 = new_textarea(g, 70, 11, 64); + xy_plot_set_range(g, w, 0, 1000, 0, 100000); + xy_plot_set_tick_type(g, w, XY_PLOT_SCROLL_TICK); + widget_add_child(g, col, w2, -1); + widget_add_child(g, col, w, -1); + container_set_child_growable(g, col, w, 1); + l = new_throughputlog(h, database, "GNB_PHY_DL_TICK", "frame", "slot", + "GNB_MAC_LCID_DL", "data_size", 20); + v = new_view_scrolltti(10, g, w, new_color(g, "#0c0c72"), w2, 20); + logger_add_view(l, v); + logger_set_filter(l, + filter_and( + filter_eq( + filter_evarg(database, "GNB_MAC_LCID_DL", "rnti"), + filter_int(rnti)), + filter_eq( + filter_evarg(database, "GNB_MAC_LCID_DL", "lcid"), + filter_int(lcid)))); + + /* UL MCS */ + w = new_xy_plot(g, 128, 55, "UL mcs", 20); + xy_plot_set_range(g, w, 0, 1024*20, -2, 30); + widget_add_child(g, line, w, -1); + /* GNB_PHY_DL_TICK (and not UL) because GNB_MAC_UL is from DCI */ + l = new_ticked_ttilog(h, database, "GNB_PHY_DL_TICK", "frame", "slot", + "GNB_MAC_UL", "mcs", 0, -1); + v = new_view_tti(10, g, w, new_color(g, "#0c0c72"), 20); + logger_add_view(l, v); + logger_set_filter(l, + filter_eq( + filter_evarg(database, "GNB_MAC_UL", "rnti"), + filter_int(rnti))); + + /* UL TBS */ + col = new_container(g, VERTICAL); + widget_add_child(g, line, col, -1); + w = new_xy_plot(g, 70, 10, "UL tbs", 35); + w2 = new_textarea(g, 70, 11, 64); + xy_plot_set_range(g, w, 0, 1024*20, 0, 1000); + xy_plot_set_tick_type(g, w, XY_PLOT_SCROLL_TICK); + widget_add_child(g, col, w2, -1); + widget_add_child(g, col, w, -1); + container_set_child_growable(g, col, w, 1); + /* GNB_PHY_DL_TICK (and not UL) because GNB_MAC_UL is from DCI */ + l = new_ticked_ttilog(h, database, "GNB_PHY_DL_TICK", "frame", "slot", + "GNB_MAC_UL", "tbs", 0, -1); + v = new_view_tti(10, g, w, new_color(g, "#0c0c72"), 20); + view_tti_enable_automax(v, w2); + logger_add_view(l, v); + logger_set_filter(l, + filter_eq( + filter_evarg(database, "GNB_MAC_UL", "rnti"), + filter_int(rnti))); + + /* UL lcid throughput */ + col = new_container(g, VERTICAL); + widget_add_child(g, line, col, -1); + sprintf(s, "UL lcid %d", lcid); + w = new_xy_plot(g, 70, 10, s, 35); + w2 = new_textarea(g, 70, 11, 64); + xy_plot_set_range(g, w, 0, 1000, 0, 100000); + xy_plot_set_tick_type(g, w, XY_PLOT_SCROLL_TICK); + widget_add_child(g, col, w2, -1); + widget_add_child(g, col, w, -1); + container_set_child_growable(g, col, w, 1); + l = new_throughputlog(h, database, "GNB_PHY_UL_TICK", "frame", "slot", + "GNB_MAC_LCID_UL", "data_size", 20); + v = new_view_scrolltti(10, g, w, new_color(g, "#0c0c72"), w2, 20); + logger_add_view(l, v); + logger_set_filter(l, + filter_and( + filter_eq( + filter_evarg(database, "GNB_MAC_LCID_UL", "rnti"), + filter_int(rnti)), + filter_eq( + filter_evarg(database, "GNB_MAC_LCID_UL", "lcid"), + filter_int(lcid)))); + + /* lcid RLC tx buffer occupancy */ + col = new_container(g, VERTICAL); + widget_add_child(g, line, col, -1); + sprintf(s, "rlc tx %d", lcid); + w = new_xy_plot(g, 70, 10, s, 35); + w2 = new_textarea(g, 70, 11, 64); + xy_plot_set_range(g, w, 0, 1024*20, 0, 1000); + xy_plot_set_tick_type(g, w, XY_PLOT_SCROLL_TICK); + widget_add_child(g, col, w2, -1); + widget_add_child(g, col, w, -1); + container_set_child_growable(g, col, w, 1); + l = new_ticked_ttilog(h, database, "GNB_PHY_DL_TICK", "frame", "slot", + "GNB_MAC_LCID_DL", "tx_list_occupancy", 0, -1); + v = new_view_tti(10, g, w, new_color(g, "#0c0c72"), 20); + view_tti_enable_automax(v, w2); + logger_add_view(l, v); + logger_set_filter(l, + filter_and( + filter_eq( + filter_evarg(database, "GNB_MAC_LCID_DL", "rnti"), + filter_int(rnti)), + filter_eq( + filter_evarg(database, "GNB_MAC_LCID_DL", "lcid"), + filter_int(lcid)))); +} + +void build_gui(gnb_gui *gg, gui *g) +{ + widget *main_window; + + main_window = new_toplevel_window(g, 900, 1000, "gNB MAC tracer"); + gg->container = new_container(g, VERTICAL); + widget_add_child(g, main_window, gg->container, -1); +} + +void usage(void) +{ + printf( +"options:\n" +" -d this option is mandatory\n" +" -ip connect to given IP address (default %s)\n" +" -p connect to given port (default %d)\n", + DEFAULT_REMOTE_IP, + DEFAULT_REMOTE_PORT + ); + exit(1); +} + +void check_new_ue(void *_gd, event e) +{ + gnb_data *gd = _gd; + int rnti = e.e[gd->rnti_arg].i; + if (!gd->ues[rnti].used) + add_ue(gd, rnti, 4); +} + +int main(int n, char **v) +{ + gui *g; + gnb_gui gg; + gnb_data *gd; + char *database_filename = NULL; + void *database; + char *ip = DEFAULT_REMOTE_IP; + int port = DEFAULT_REMOTE_PORT; + event_handler *h; + int *is_on; + int number_of_events; + int i; + + for (i = 1; i < n; i++) { + if (!strcmp(v[i], "-h") || !strcmp(v[i], "--help")) usage(); + if (!strcmp(v[i], "-d")) { if (i > n-2) usage(); database_filename = v[++i]; continue; } + if (!strcmp(v[i], "-ip")) { if (i > n-2) usage(); ip = v[++i]; continue; } + if (!strcmp(v[i], "-p")) { if (i > n-2) usage(); port = atoi(v[++i]); continue; } + usage(); + } + + if (database_filename == NULL) { + printf("ERROR: provide a database file (-d)\n"); + exit(1); + } + + database = parse_database(database_filename); + + load_config_file(database_filename); + + number_of_events = number_of_ids(database); + is_on = calloc(number_of_events, sizeof(int)); + if (is_on == NULL) abort(); + + on_off(database, "GNB_PHY_DL_TICK", is_on, 1); + on_off(database, "GNB_MAC_DL", is_on, 1); + on_off(database, "GNB_MAC_LCID_DL", is_on, 1); + on_off(database, "GNB_PHY_UL_TICK", is_on, 1); + on_off(database, "GNB_MAC_UL", is_on, 1); + on_off(database, "GNB_MAC_LCID_UL", is_on, 1); + + gd = calloc(1, sizeof(*gd)); if (!gd) abort(); + + h = new_handler(database); + + g = gui_init(); + new_thread(gui_thread, g); + + build_gui(&gg, g); + + gd->g = g; + gd->gg = ≫ + gd->h = h; + gd->database = database; + + /* get rnti_arg from event GNB_MAC_DL */ + int event_id = event_id_from_name(database, "GNB_MAC_DL"); + database_event_format f = get_format(database, event_id); + gd->rnti_arg = -1; + for (i = 0; i < f.count; i++) { + if (!strcmp(f.name[i], "rnti")) gd->rnti_arg = i; + } + if (gd->rnti_arg == -1) { + printf("fatal: event 'GNB_MAC_DL' does not have argument 'rnti'\n"); + exit(1); + } + if (strcmp(f.type[gd->rnti_arg], "int") != 0) { + printf("fatal: argument 'rnti' of event 'GNB_MAC_DL' is not 'int'\n"); + exit(1); + } + + register_handler_function(h, event_id, check_new_ue, gd); + + OBUF ebuf = {.osize = 0, .omaxsize = 0, .obuf = NULL}; + + gd->socket = -1; + +restart: + clear_remote_config(); + if (gd->socket != -1) close(gd->socket); + gd->socket = connect_to(ip, port); + + /* send the first message - activate selected traces */ + int t = 1; + if (socket_send(gd->socket, &t, 1) == -1 || + socket_send(gd->socket, &number_of_events, sizeof(int)) == -1 || + socket_send(gd->socket, is_on, number_of_events * sizeof(int)) == -1) + goto restart; + + while (1) { + event e; + e = get_event(gd->socket, &ebuf, database); + if (e.type == -1) goto restart; + handle_event(h, e); + } + + return 0; +} From c8aea1b97021f45372ac1fa33b71dee599e6047f Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Mon, 18 Aug 2025 11:21:31 +0200 Subject: [PATCH 581/964] T: replace 'subframe' by 'tick' Some code in T tracers is used by both LTE and NR. In LTE, we expect 10 subframes per frame, and the logging is done with this assumption. We have one tick per subframe. In NR, we deal with slots, not subframes. And we have n ticks per frame (depending on mu). As of today, only n=20 is tested (corresponding to mu=1). A previous commit introduced 'subframes_per_frame' which had the correct meaning for LTE but was truly 'slots per frame' for NR. This creates confusion. Let's replace 'subframe' by 'tick' to reduce confusion. --- common/utils/T/tracer/logger/logger.h | 4 +- common/utils/T/tracer/logger/throughputlog.c | 70 ++++++++++---------- common/utils/T/tracer/view/scrolltti.c | 42 ++++++------ common/utils/T/tracer/view/tti.c | 32 ++++----- common/utils/T/tracer/view/view.h | 4 +- 5 files changed, 76 insertions(+), 76 deletions(-) diff --git a/common/utils/T/tracer/logger/logger.h b/common/utils/T/tracer/logger/logger.h index 8508032ec0..b78fa1b359 100644 --- a/common/utils/T/tracer/logger/logger.h +++ b/common/utils/T/tracer/logger/logger.h @@ -15,8 +15,8 @@ logger *new_ticked_ttilog(void *event_handler, void *database, char *event_name, char *data_varname, int convert_to_dB, float empty_value); logger *new_throughputlog(void *event_handler, void *database, - char *tick_event_name, char *frame_varname, char *subframe_varname, - char *event_name, char *data_varname, int subframes_per_frame); + char *tick_event_name, char *frame_varname, char *tick_varname, + char *event_name, char *data_varname, int ticks_per_frame); logger *new_timelog(void *event_handler, void *database, char *event_name); logger *new_ticklog(void *event_handler, void *database, char *event_name, char *frame_name, char *subframe_name); diff --git a/common/utils/T/tracer/logger/throughputlog.c b/common/utils/T/tracer/logger/throughputlog.c index e7b48f6e2f..5f066df343 100644 --- a/common/utils/T/tracer/logger/throughputlog.c +++ b/common/utils/T/tracer/logger/throughputlog.c @@ -13,13 +13,13 @@ struct throughputlog { struct logger common; void *database; int tick_frame_arg; - int tick_subframe_arg; + int tick_tick_arg; int data_frame_arg; - int data_subframe_arg; + int data_tick_arg; int data_arg; int last_tick_frame; - int last_tick_subframe; - int subframes_per_frame; + int last_tick_tick; + int ticks_per_frame; unsigned long *bits; unsigned long total; int insert_point; @@ -33,16 +33,16 @@ static void _event(void *p, event e) { struct throughputlog *l = p; int frame; - int subframe; + int tick; unsigned long value; if (l->common.filter != NULL && filter_eval(l->common.filter, e) == 0) return; frame = e.e[l->data_frame_arg].i; - subframe = e.e[l->data_subframe_arg].i; + tick = e.e[l->data_tick_arg].i; - if (frame != l->last_tick_frame || subframe != l->last_tick_subframe) { + if (frame != l->last_tick_frame || tick != l->last_tick_tick) { printf("WARNING: %s:%d: data comes without previous tick!\n", __FILE__, __LINE__); return; @@ -63,24 +63,24 @@ static void _tick_event(void *p, event e) struct throughputlog *l = p; int i; int frame; - int subframe; + int tick; if (l->tick_filter != NULL && filter_eval(l->tick_filter, e) == 0) return; frame = e.e[l->tick_frame_arg].i; - subframe = e.e[l->tick_subframe_arg].i; + tick = e.e[l->tick_tick_arg].i; for (i = 0; i < l->common.vsize; i++) - l->common.v[i]->append(l->common.v[i], frame, subframe, (double)l->total); + l->common.v[i]->append(l->common.v[i], frame, tick, (double)l->total); - while (l->last_tick_frame != frame || l->last_tick_subframe != subframe) { - l->insert_point = (l->insert_point + 1) % (100 * l->subframes_per_frame); + while (l->last_tick_frame != frame || l->last_tick_tick != tick) { + l->insert_point = (l->insert_point + 1) % (100 * l->ticks_per_frame); l->total -= l->bits[l->insert_point]; l->bits[l->insert_point] = 0; - l->last_tick_subframe++; - if (l->last_tick_subframe == l->subframes_per_frame) { - l->last_tick_subframe = 0; + l->last_tick_tick++; + if (l->last_tick_tick == l->ticks_per_frame) { + l->last_tick_tick = 0; l->last_tick_frame++; l->last_tick_frame %= 1024; } @@ -89,8 +89,8 @@ static void _tick_event(void *p, event e) } logger *new_throughputlog(event_handler *h, void *database, - char *tick_event_name, char *frame_varname, char *subframe_varname, - char *event_name, char *data_varname, int subframes_per_frame) + char *tick_event_name, char *frame_varname, char *tick_varname, + char *event_name, char *data_varname, int ticks_per_frame) { struct throughputlog *ret; int event_id; @@ -113,21 +113,21 @@ logger *new_throughputlog(event_handler *h, void *database, f = get_format(database, event_id); - /* look for frame and subframe */ + /* look for frame and tick */ ret->tick_frame_arg = -1; - ret->tick_subframe_arg = -1; + ret->tick_tick_arg = -1; for (i = 0; i < f.count; i++) { if (!strcmp(f.name[i], frame_varname)) ret->tick_frame_arg = i; - if (!strcmp(f.name[i], subframe_varname)) ret->tick_subframe_arg = i; + if (!strcmp(f.name[i], tick_varname)) ret->tick_tick_arg = i; } if (ret->tick_frame_arg == -1) { printf("%s:%d: frame argument '%s' not found in event '%s'\n", __FILE__, __LINE__, frame_varname, event_name); abort(); } - if (ret->tick_subframe_arg == -1) { - printf("%s:%d: subframe argument '%s' not found in event '%s'\n", - __FILE__, __LINE__, subframe_varname, event_name); + if (ret->tick_tick_arg == -1) { + printf("%s:%d: tick argument '%s' not found in event '%s'\n", + __FILE__, __LINE__, tick_varname, event_name); abort(); } if (strcmp(f.type[ret->tick_frame_arg], "int") != 0) { @@ -135,9 +135,9 @@ logger *new_throughputlog(event_handler *h, void *database, __FILE__, __LINE__, frame_varname); abort(); } - if (strcmp(f.type[ret->tick_subframe_arg], "int") != 0) { + if (strcmp(f.type[ret->tick_tick_arg], "int") != 0) { printf("%s:%d: argument '%s' has wrong type (should be 'int')\n", - __FILE__, __LINE__, subframe_varname); + __FILE__, __LINE__, tick_varname); abort(); } @@ -148,13 +148,13 @@ logger *new_throughputlog(event_handler *h, void *database, f = get_format(database, event_id); - /* look for frame, subframe and data args */ + /* look for frame, tick and data args */ ret->data_frame_arg = -1; - ret->data_subframe_arg = -1; + ret->data_tick_arg = -1; ret->data_arg = -1; for (i = 0; i < f.count; i++) { if (!strcmp(f.name[i], frame_varname)) ret->data_frame_arg = i; - if (!strcmp(f.name[i], subframe_varname)) ret->data_subframe_arg = i; + if (!strcmp(f.name[i], tick_varname)) ret->data_tick_arg = i; if (!strcmp(f.name[i], data_varname)) ret->data_arg = i; } if (ret->data_frame_arg == -1) { @@ -162,9 +162,9 @@ logger *new_throughputlog(event_handler *h, void *database, __FILE__, __LINE__, frame_varname, event_name); abort(); } - if (ret->data_subframe_arg == -1) { - printf("%s:%d: subframe argument '%s' not found in event '%s'\n", - __FILE__, __LINE__, subframe_varname, event_name); + if (ret->data_tick_arg == -1) { + printf("%s:%d: tick argument '%s' not found in event '%s'\n", + __FILE__, __LINE__, tick_varname, event_name); abort(); } if (ret->data_arg == -1) { @@ -177,9 +177,9 @@ logger *new_throughputlog(event_handler *h, void *database, __FILE__, __LINE__, frame_varname); abort(); } - if (strcmp(f.type[ret->data_subframe_arg], "int") != 0) { + if (strcmp(f.type[ret->data_tick_arg], "int") != 0) { printf("%s:%d: argument '%s' has wrong type (should be 'int')\n", - __FILE__, __LINE__, subframe_varname); + __FILE__, __LINE__, tick_varname); abort(); } if (strcmp(f.type[ret->data_arg], "int") != 0 && @@ -190,8 +190,8 @@ logger *new_throughputlog(event_handler *h, void *database, abort(); } - ret->subframes_per_frame = subframes_per_frame; - ret->bits = calloc(100 * subframes_per_frame, sizeof(unsigned long)); + ret->ticks_per_frame = ticks_per_frame; + ret->bits = calloc(100 * ticks_per_frame, sizeof(unsigned long)); if (ret->bits == NULL) abort(); return ret; diff --git a/common/utils/T/tracer/view/scrolltti.c b/common/utils/T/tracer/view/scrolltti.c index 66fe0b3f02..3bf1c93bd2 100644 --- a/common/utils/T/tracer/view/scrolltti.c +++ b/common/utils/T/tracer/view/scrolltti.c @@ -15,14 +15,14 @@ struct scrolltti { int plot; float refresh_rate; pthread_mutex_t lock; - int subframes_per_frame; + int ticks_per_frame; unsigned long *data; unsigned long total; /* sum data[0..n] to have smoother value printed */ float *xout; float *yout; int insert_point; int next_tick_frame; - int next_tick_subframe; + int next_tick_tick; }; /* this array is used to get Y range 1000, 2000, 5000, 10000, ... */ @@ -41,21 +41,21 @@ static void *scrolltti_thread(void *_this) /* TODO: optimize */ p = this->insert_point; max = 0; - for (i = 0; i < this->subframes_per_frame * 100; i++) { + for (i = 0; i < this->ticks_per_frame * 100; i++) { this->xout[i] = i; this->yout[i] = this->data[p]; if (this->data[p] > max) max = this->data[p]; - p = (p + 1) % (this->subframes_per_frame * 100); + p = (p + 1) % (this->ticks_per_frame * 100); } - bps(o, this->total/(this->subframes_per_frame * 100.), "b/s"); + bps(o, this->total/(this->ticks_per_frame * 100.), "b/s"); textarea_set_text(this->g, this->throughput_textarea, o); /* for Y range we want 1000, 2000, 5000, 10000, 20000, 50000, etc. */ if (max < 1000) max = 1000; mlog = pow(10, floor(log10(max))); max = tolog[(int)ceil(max/mlog)] * mlog; - xy_plot_set_range(this->g, this->w, 0, this->subframes_per_frame * 100, 0, max); + xy_plot_set_range(this->g, this->w, 0, this->ticks_per_frame * 100, 0, max); xy_plot_set_points(this->g, this->w, this->plot, - this->subframes_per_frame * 100, this->xout, this->yout); + this->ticks_per_frame * 100, this->xout, this->yout); if (pthread_mutex_unlock(&this->lock)) abort(); sleepms(1000/this->refresh_rate); } @@ -73,35 +73,35 @@ static void insert(struct scrolltti *this, double value) this->total -= this->data[this->insert_point]; this->data[this->insert_point] = value; this->total += this->data[this->insert_point]; - this->insert_point = (this->insert_point + 1) % (this->subframes_per_frame * 100); + this->insert_point = (this->insert_point + 1) % (this->ticks_per_frame * 100); } -static void next_subframe(struct scrolltti *this) +static void next_tick(struct scrolltti *this) { - this->next_tick_subframe++; - if (this->next_tick_subframe == this->subframes_per_frame) { - this->next_tick_subframe = 0; + this->next_tick_tick++; + if (this->next_tick_tick == this->ticks_per_frame) { + this->next_tick_tick = 0; this->next_tick_frame++; this->next_tick_frame %= 1024; } } -static void append(view *_this, int frame, int subframe, double value) +static void append(view *_this, int frame, int tick, double value) { struct scrolltti *this = (struct scrolltti *)_this; if (pthread_mutex_lock(&this->lock)) abort(); - while (this->next_tick_frame != frame || this->next_tick_subframe != subframe) { + while (this->next_tick_frame != frame || this->next_tick_tick != tick) { insert(this, 0); - next_subframe(this); + next_tick(this); } insert(this, value); - next_subframe(this); + next_tick(this); if (pthread_mutex_unlock(&this->lock)) abort(); } view *new_view_scrolltti(float refresh_rate, gui *g, widget *w, int color, - widget *throughput_textarea, int subframes_per_frame) + widget *throughput_textarea, int ticks_per_frame) { struct scrolltti *ret = calloc(1, sizeof(struct scrolltti)); if (ret == NULL) abort(); @@ -115,12 +115,12 @@ view *new_view_scrolltti(float refresh_rate, gui *g, widget *w, int color, ret->throughput_textarea = throughput_textarea; ret->plot = xy_plot_new_plot(g, w, color); - ret->subframes_per_frame = subframes_per_frame; - ret->data = calloc(subframes_per_frame * 100, sizeof(unsigned long)); + ret->ticks_per_frame = ticks_per_frame; + ret->data = calloc(ticks_per_frame * 100, sizeof(unsigned long)); if (ret->data == NULL) abort(); - ret->xout = calloc(subframes_per_frame * 100, sizeof(float)); + ret->xout = calloc(ticks_per_frame * 100, sizeof(float)); if (ret->xout == NULL) abort(); - ret->yout = calloc(subframes_per_frame * 100, sizeof(float)); + ret->yout = calloc(ticks_per_frame * 100, sizeof(float)); if (ret->yout == NULL) abort(); if (pthread_mutex_init(&ret->lock, NULL)) abort(); diff --git a/common/utils/T/tracer/view/tti.c b/common/utils/T/tracer/view/tti.c index 6c352d08d5..73d43b539b 100644 --- a/common/utils/T/tracer/view/tti.c +++ b/common/utils/T/tracer/view/tti.c @@ -21,20 +21,20 @@ struct tti { float *xout; float *yout; int last_insert_point; - int subframes_per_frame; + int ticks_per_frame; }; static int far_enough(int i, int last_insert, int plot_width, - int subframes_per_frame) + int ticks_per_frame) { int p1; int p2; int hole_size_px; int hole_size_tti; hole_size_px = 10; - hole_size_tti = 1024 * subframes_per_frame * hole_size_px / plot_width; + hole_size_tti = 1024 * ticks_per_frame * hole_size_px / plot_width; p1 = last_insert; - p2 = (last_insert + hole_size_tti) % (1024 * subframes_per_frame); + p2 = (last_insert + hole_size_tti) % (1024 * ticks_per_frame); if (p1 < p2) { return !(i > p1 && i < p2); } @@ -55,11 +55,11 @@ static void *tti_thread(void *_this) length = 0; double max = 0; /* TODO: optimize */ - for (i = 0; i < 1024 * this->subframes_per_frame; i++) + for (i = 0; i < 1024 * this->ticks_per_frame; i++) /* do not take points too close after last insertion point */ if (this->valid[i] && far_enough(i, this->last_insert_point, plot_width, - this->subframes_per_frame)) { + this->ticks_per_frame)) { this->xout[length] = i; this->yout[length] = this->data[i]; if (this->data[i] > max) max = this->data[i]; @@ -92,11 +92,11 @@ static void clear(view *this) /* TODO */ } -static void append(view *_this, int frame, int subframe, double value) +static void append(view *_this, int frame, int tick, double value) { struct tti *this = (struct tti *)_this; int i; - int index = frame * this->subframes_per_frame + subframe; + int index = frame * this->ticks_per_frame + tick; if (pthread_mutex_lock(&this->lock)) abort(); @@ -105,10 +105,10 @@ static void append(view *_this, int frame, int subframe, double value) * this may be wrong if delay between two append is * greater than 1024 frames (something like that) */ - i = (this->last_insert_point + 1) % (1024 * this->subframes_per_frame); + i = (this->last_insert_point + 1) % (1024 * this->ticks_per_frame); while (i != index) { this->valid[i] = 0; - i = (i + 1) % (1024 * this->subframes_per_frame); + i = (i + 1) % (1024 * this->ticks_per_frame); } this->data[index] = value; @@ -120,7 +120,7 @@ static void append(view *_this, int frame, int subframe, double value) } view *new_view_tti(float refresh_rate, gui *g, widget *w, int color, - int subframes_per_frame) + int ticks_per_frame) { struct tti *ret = calloc(1, sizeof(struct tti)); if (ret == NULL) abort(); @@ -137,14 +137,14 @@ view *new_view_tti(float refresh_rate, gui *g, widget *w, int color, if (pthread_mutex_init(&ret->lock, NULL)) abort(); - ret->subframes_per_frame = subframes_per_frame; - ret->data = calloc(subframes_per_frame * 1024, sizeof(float)); + ret->ticks_per_frame = ticks_per_frame; + ret->data = calloc(ticks_per_frame * 1024, sizeof(float)); if (ret->data == NULL) abort(); - ret->valid = calloc(subframes_per_frame * 1024, sizeof(int)); + ret->valid = calloc(ticks_per_frame * 1024, sizeof(int)); if (ret->valid == NULL) abort(); - ret->xout = calloc(subframes_per_frame * 1024, sizeof(float)); + ret->xout = calloc(ticks_per_frame * 1024, sizeof(float)); if (ret->xout == NULL) abort(); - ret->yout = calloc(subframes_per_frame * 1024, sizeof(float)); + ret->yout = calloc(ticks_per_frame * 1024, sizeof(float)); if (ret->yout == NULL) abort(); new_thread(tti_thread, ret); diff --git a/common/utils/T/tracer/view/view.h b/common/utils/T/tracer/view/view.h index 7f131efbb5..bc37e654d1 100644 --- a/common/utils/T/tracer/view/view.h +++ b/common/utils/T/tracer/view/view.h @@ -18,9 +18,9 @@ view *new_view_textlist(int maxsize, float refresh_rate, gui *g, widget *w); view *new_view_xy(int length, float refresh_rate, gui *g, widget *w, int color, enum xy_mode mode); view *new_view_tti(float refresh_rate, gui *g, widget *w, int color, - int subframes_per_frame); + int ticks_per_frame); view *new_view_scrolltti(float refresh_rate, gui *g, widget *w, - int color, widget *throughput_label, int subframes_per_frame); + int color, widget *throughput_label, int ticks_per_frame); view *new_view_time(int number_of_seconds, float refresh_rate, gui *g, widget *w); view *new_subview_time(view *time, int line, int color, int size); From 69cb71eddc3a19336603acd265b8c384659be001 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 28 Aug 2025 09:13:02 +0200 Subject: [PATCH 582/964] Adjust configuration for OAI OTA test --- .../conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf b/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf index 7b0d176b3d..643380bd0a 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf @@ -112,7 +112,7 @@ gNBs = # 0 = neither, 1= group hopping, 2=sequence hopping pucchGroupHopping = 0; hoppingId = 40; - p0_nominal = -70; + p0_nominal = -80; ssb_PositionsInBurst_Bitmap = 1; @@ -175,7 +175,7 @@ MACRLCs = ( num_cc = 1; tr_s_preference = "local_L1"; tr_n_preference = "local_RRC"; - pusch_TargetSNRx10 = 180; + pusch_TargetSNRx10 = 150; pucch_TargetSNRx10 = 200; } ); @@ -184,7 +184,7 @@ L1s = ( { num_cc = 1; tr_n_preference = "local_mac"; - prach_dtx_threshold = 120; + prach_dtx_threshold = 130; #pucch0_dtx_threshold = 150; } ); @@ -198,7 +198,7 @@ RUs = ( att_rx = 0; bands = [78]; max_pdschReferenceSignalPower = -27; - max_rxgain = 65; + max_rxgain = 75; eNB_instances = [0]; sf_extension = 0 sdr_addrs = "addr=192.168.80.52,clock_source=internal,time_source=internal" From 0942927308d1fba5aa0a27112a56db6d971f0d6b Mon Sep 17 00:00:00 2001 From: ndomingues Date: Thu, 28 Aug 2025 16:49:52 +0100 Subject: [PATCH 583/964] Fix RA 2-Step MgsB Ack at UE Update condition to prepare MsgB Ack the same way as Msg4 Ack --- openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c | 2 +- 1 file changed, 1 insertion(+), 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 de5ae571ca..8bf781a7df 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c @@ -1190,7 +1190,7 @@ void update_harq_status(NR_UE_MAC_INST_t *mac, uint8_t harq_pid, uint8_t ack_nac if (current_harq->active) { LOG_D(PHY,"Updating harq_status for harq_id %d, ack/nak %d\n", harq_pid, current_harq->ack); // we can prepare feedback for MSG4 in advance - if (mac->ra.ra_state == nrRA_WAIT_CONTENTION_RESOLUTION) + if (mac->ra.ra_state == nrRA_WAIT_CONTENTION_RESOLUTION || mac->ra.ra_state == nrRA_WAIT_MSGB) prepare_msg4_msgb_feedback(mac, harq_pid, ack_nack); else { current_harq->ack = ack_nack; From 47d2ba17933087f791689c82c7c27abc8fcc1e99 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 29 Aug 2025 14:37:37 +0200 Subject: [PATCH 584/964] Fix RX gain for OAIUE-OTA pipeline Adjust to avoid increased ULSCH DTX, probably because of saturation. Fixes: 69cb71eddc3a ("Adjust configuration for OAI OTA test") --- ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf b/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf index 643380bd0a..2f994ab25e 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf @@ -198,7 +198,7 @@ RUs = ( att_rx = 0; bands = [78]; max_pdschReferenceSignalPower = -27; - max_rxgain = 75; + max_rxgain = 70; eNB_instances = [0]; sf_extension = 0 sdr_addrs = "addr=192.168.80.52,clock_source=internal,time_source=internal" From 2b75e09151aa7b766a4ce095e3674ee6511cadc9 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 29 Aug 2025 14:52:48 +0200 Subject: [PATCH 585/964] Increase DL UDP traffic for OAIUE OTA pipeline --- ci-scripts/xml_files/container_sa_n310_nrue.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ci-scripts/xml_files/container_sa_n310_nrue.xml b/ci-scripts/xml_files/container_sa_n310_nrue.xml index 4d9e9a2039..63088afc1c 100644 --- a/ci-scripts/xml_files/container_sa_n310_nrue.xml +++ b/ci-scripts/xml_files/container_sa_n310_nrue.xml @@ -109,8 +109,8 @@ Iperf - iperf (DL/30Mbps/UDP)(30 sec) - -u -b 30M -t 30 -i 1 -R + iperf (DL/60Mbps/UDP)(30 sec) + -u -b 60M -t 30 -i 1 -R oai_ue_caracal oc-cn5g 25 From 169de8cdca7c290b1bcc18869922669051b55518 Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 29 Aug 2025 15:04:55 +0200 Subject: [PATCH 586/964] remove unnecessary input in get_cce_index --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 4 +--- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 2 -- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c | 2 -- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c | 3 +-- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 2 -- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 1 - 6 files changed, 2 insertions(+), 12 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 6e93e0467c..16bf8c5009 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -915,7 +915,6 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP, ss, coreset, &UE->UE_sched_ctrl.sched_pdcch, - true, 0); if (CCEIndex < 0) { LOG_E(NR_MAC, "UE %04x cannot find free CCE!\n", UE->rnti); @@ -1507,7 +1506,7 @@ static void nr_generate_Msg2(module_id_t module_idP, } uint8_t aggregation_level; - int CCEIndex = get_cce_index(nr_mac, CC_id, slotP, 0, &aggregation_level, beam.idx, ss, coreset, &sched_ctrl->sched_pdcch, true, 0); + int CCEIndex = get_cce_index(nr_mac, CC_id, slotP, 0, &aggregation_level, beam.idx, ss, coreset, &sched_ctrl->sched_pdcch, 0); if (CCEIndex < 0) { LOG_W(NR_MAC, "UE %04x: %d.%d cannot find free CCE for Msg2!\n", UE->rnti, frameP, slotP); @@ -1707,7 +1706,6 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, ss, coreset, &sched_ctrl->sched_pdcch, - true, 0); if (CCEIndex < 0) { diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index 8befbe4833..d60ba6174d 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -551,7 +551,6 @@ static bool allocate_dl_retransmission(module_id_t module_id, sched_ctrl->search_space, sched_ctrl->coreset, &sched_ctrl->sched_pdcch, - false, sched_ctrl->pdcch_cl_adjust); if (CCEIndex<0) { sched_ctrl->dl_cce_fail++; @@ -811,7 +810,6 @@ static void pf_dl(module_id_t module_id, sched_ctrl->search_space, sched_ctrl->coreset, &sched_ctrl->sched_pdcch, - false, sched_ctrl->pdcch_cl_adjust); if (CCEIndex < 0) { sched_ctrl->dl_cce_fail++; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c index 26b48ab998..5ec7bf781d 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c @@ -139,7 +139,6 @@ void nr_preprocessor_phytest(module_id_t module_id, frame_t frame, slot_t slot) sched_ctrl->search_space, sched_ctrl->coreset, &sched_ctrl->sched_pdcch, - false, 0); AssertFatal(CCEIndex >= 0, "Could not find CCE for UE %04x\n", UE->rnti); @@ -286,7 +285,6 @@ void nr_ul_preprocessor_phytest(gNB_MAC_INST *nr_mac, post_process_pusch_t *pp_p sched_ctrl->search_space, sched_ctrl->coreset, &sched_ctrl->sched_pdcch, - false, 0); if (CCEIndex < 0) { LOG_E(MAC, "%s(): CCE list not empty, couldn't schedule PUSCH\n", __func__); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 264150f314..cb3329b34b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -572,10 +572,9 @@ int get_cce_index(const gNB_MAC_INST *nrmac, const NR_SearchSpace_t *ss, const NR_ControlResourceSet_t *coreset, NR_sched_pdcch_t *sched_pdcch, - bool is_common, float pdcch_cl_adjust) { - const uint32_t Y = is_common ? 0 : get_Y(ss, slot, rnti); + const uint32_t Y = get_Y(ss, slot, rnti); uint8_t nr_of_candidates; int agg_level_search_order[NUM_PDCCH_AGG_LEVELS]; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 09044e9170..e1a312d9e0 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -1876,7 +1876,6 @@ static bool allocate_ul_retransmission(gNB_MAC_INST *nrmac, sched_ctrl->search_space, sched_ctrl->coreset, &sched_ctrl->sched_pdcch, - false, sched_ctrl->pdcch_cl_adjust); if (CCEIndex<0) { LOG_D(NR_MAC, "[UE %04x][%4d.%2d] no free CCE for retransmission UL DCI UE\n", UE->rnti, frame, slot); @@ -2125,7 +2124,6 @@ static int pf_ul(gNB_MAC_INST *nrmac, sched_ctrl->search_space, sched_ctrl->coreset, &sched_ctrl->sched_pdcch, - false, sched_ctrl->pdcch_cl_adjust); if (CCEIndex < 0) { diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index ff827ab68a..84a0923e8b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -431,7 +431,6 @@ int get_cce_index(const gNB_MAC_INST *nrmac, const NR_SearchSpace_t *ss, const NR_ControlResourceSet_t *coreset, NR_sched_pdcch_t *sched_pdcch, - bool is_common, float pdcch_cl_adjust); bool nr_find_nb_rb(uint16_t Qm, From 15bb046f9cbc10be0e95955c7bfe7f075af1de60 Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 1 Sep 2025 17:25:01 +0200 Subject: [PATCH 587/964] adding a missing beam reaset in pf_dl --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 1 + 1 file changed, 1 insertion(+) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index d60ba6174d..df5c8e1474 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -797,6 +797,7 @@ static void pf_dl(module_id_t module_id, rbStart, max_rbSize, rbStop); + reset_beam_status(&mac->beam_info, frame, slot, iterator->UE->UE_beam_index, slots_per_frame, beam.new_beam); iterator++; continue; } From 2e1543073105830780c32de797b1d2c51c1c00bf Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 1 Sep 2025 18:46:22 +0200 Subject: [PATCH 588/964] adding other missing beam reaset in RA functions --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 16bf8c5009..715feb5b33 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -856,6 +856,8 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP, } if (rbStart > (sched_pusch.bwp_info.bwpSize - ra->msg3_nb_rb)) { // cannot find free vrb_map for msg3 retransmission in this slot + reset_beam_status(&nr_mac->beam_info, sched_frame, sched_slot, UE->UE_beam_index, slots_frame, beam_ul.new_beam); + reset_beam_status(&nr_mac->beam_info, frame, slot, UE->UE_beam_index, slots_frame, beam_dci.new_beam); return; } @@ -918,6 +920,8 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP, 0); if (CCEIndex < 0) { LOG_E(NR_MAC, "UE %04x cannot find free CCE!\n", UE->rnti); + reset_beam_status(&nr_mac->beam_info, sched_frame, sched_slot, UE->UE_beam_index, slots_frame, beam_ul.new_beam); + reset_beam_status(&nr_mac->beam_info, frame, slot, UE->UE_beam_index, slots_frame, beam_dci.new_beam); return; } @@ -1733,8 +1737,10 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, TYPE_TC_RNTI_, coreset->controlResourceSetId, false); - if (!msg4_tda.valid_tda) + if (!msg4_tda.valid_tda) { + reset_beam_status(&nr_mac->beam_info, frameP, slotP, UE->UE_beam_index, n_slots_frame, beam.new_beam); return; + } NR_pdsch_dmrs_t dmrs_info = get_dl_dmrs_params(scc, dl_bwp, &msg4_tda, 1); bwp_info_t bwp_info = get_pdsch_bwp_start_size(nr_mac, UE); From 741e9ffae9c7bf144b5d02328678633601d2d3cd Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 1 Sep 2025 13:57:52 +0200 Subject: [PATCH 589/964] Simplify cross-compilation Dockerfile Redirect to files and manual analysis as done in this Dockerfile is not necessary since we just output all relevant build files to stdout. Simplify to do the same here. See: 35361db76b91 ("build_oai: don't redirect compilations to a file") --- docker/Dockerfile.build.ubuntu.cross-arm64 | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/docker/Dockerfile.build.ubuntu.cross-arm64 b/docker/Dockerfile.build.ubuntu.cross-arm64 index a7978bb6fa..b7bc7d6dbb 100644 --- a/docker/Dockerfile.build.ubuntu.cross-arm64 +++ b/docker/Dockerfile.build.ubuntu.cross-arm64 @@ -37,20 +37,11 @@ RUN /bin/sh oaienv && \ mkdir -p log ran_build/build ran_build/build-cross && \ cd ran_build/build && \ cmake ../../.. -GNinja && \ - echo "====== Start of log for host-tools ======" && \ - ninja ldpc_generators generate_T > ../../log/host-tools.txt 2>&1 && \ - echo "====== End of log for host-tools ======" && \ + ninja ldpc_generators generate_T && \ cd ../build-cross/ && \ # install missing libyaml-cpp-dev for arm64 apt install -y libyaml-cpp-dev:arm64 && \ cmake ../../.. -GNinja -DENABLE_TELNETSRV=ON \ -DCMAKE_TOOLCHAIN_FILE=../../../cmake_targets/cross-arm.cmake -DNATIVE_DIR=../build \ -DCMAKE_C_FLAGS="-Werror" -DCMAKE_CXX_FLAGS="-Werror" && \ - echo "====== Start of log for cross-build executables ======" && \ - # making always passing so we can analyze the all.txt file - ninja -k10 dlsim ulsim ldpctest polartest smallblocktest nr_pbchsim nr_dlschsim nr_ulschsim nr_dlsim nr_ulsim nr_pucchsim nr_prachsim lte-softmodem nr-softmodem nr-cuup oairu lte-uesoftmodem nr-uesoftmodem params_libconfig coding rfsimulator telnetsrv > ../../log/all.txt 2>&1; \ - # displaying errors and warnings - grep -E -A3 "warning:|error:" ../../log/all.txt || true && \ - # will fail only if string "errors:" is found - grep -E "error:" -vqz ../../log/all.txt && \ - echo "====== End of log for cross-build executables ======" + ninja -k10 dlsim ulsim ldpctest polartest smallblocktest nr_pbchsim nr_dlschsim nr_ulschsim nr_dlsim nr_ulsim nr_pucchsim nr_prachsim lte-softmodem nr-softmodem nr-cuup oairu lte-uesoftmodem nr-uesoftmodem params_libconfig coding rfsimulator telnetsrv From 53813f522cb6e1c0cbf629412e9f7d308c38f650 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Mon, 1 Sep 2025 16:02:31 +0200 Subject: [PATCH 590/964] Change target architecture in arm container build to armv8.2-a This enables some additional instructions needed in the follow-up commit. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a71b1c3ea2..fa2d497589 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -170,7 +170,7 @@ endif() if (NOT CROSS_COMPILE) set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -march=native") else () - set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -march=armv8-a") + set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -march=armv8.2-a") endif() # add autotools definitions that were maybe used! From 5e3e8a70ff0d21460b381b2b90bd6449b8776e7d Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Wed, 27 Aug 2025 20:06:47 +0000 Subject: [PATCH 591/964] addition of aarch64 native implementation for rotate_cpx_vector for the case output_shift=15 --- openair1/PHY/TOOLS/tools_defs.h | 46 ++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/openair1/PHY/TOOLS/tools_defs.h b/openair1/PHY/TOOLS/tools_defs.h index 15c646c20e..9ee558c72b 100644 --- a/openair1/PHY/TOOLS/tools_defs.h +++ b/openair1/PHY/TOOLS/tools_defs.h @@ -828,6 +828,47 @@ static inline void rotate_cpx_vector(const c16_t *const x, const c16_t *const al // log2_amp - increase the output amplitude by a factor 2^log2_amp (default is 0) // WARNING: log2_amp>0 can cause overflow!! + +#ifdef __aarch64__ + if (output_shift == 15) { // allows specific NEON instruction + + int16x8_t ar = (int16x8_t)vdupq_n_s16(alpha->r); + int16x8_t ai = (int16x8_t)vdupq_n_s16(alpha->i); + int16x8_t *y_128 = (int16x8_t *)y; + int16x8_t *x_128 = (int16x8_t *)x; + for (uint32_t i = 0; i < (N >> 2); i++) { + // Split interleaved -> separate real/imag + int16x8_t br = vuzp1q_s16(x_128[i], x_128[i]); + int16x8_t bi = vuzp2q_s16(x_128[i], x_128[i]); + + // Start with the two “diagonal” products using high-half, doubling, sat: + // x = round( (2*ar*br) / 2^16 ), y = round( (2*ar*bi) / 2^16 ) + int16x8_t real = vqdmulhq_s16(ar, br); + int16x8_t imag = vqdmulhq_s16(ar, bi); + + // real -= round( (2*ai*bi) / 2^16 ) + real = vqrdmlshq_s16(real, ai, bi); + + // imag += round( (2*ai*br) / 2^16 ) + imag = vqrdmlahq_s16(imag, ai, br); + + // Re-interleave [real, imag] + int16x8x2_t z = vzipq_s16(real, imag); + + y_128[i] = z.val[0]; + /* + printf("y : (%d %d) (%d %d) (%d %d) (%d %d)\n", + vgetq_lane_s16(y_128[i],0), + vgetq_lane_s16(y_128[i],1), + vgetq_lane_s16(y_128[i],2), + vgetq_lane_s16(y_128[i],3), + vgetq_lane_s16(y_128[i],4), + vgetq_lane_s16(y_128[i],5), + vgetq_lane_s16(y_128[i],6), + vgetq_lane_s16(y_128[i],7));*/ + } + } else { +#endif uint32_t i; // loop counter simd_q15_t *y_128, alpha_128; @@ -859,7 +900,10 @@ static inline void rotate_cpx_vector(const c16_t *const x, const c16_t *const al shift)); // print_ints("y_128[0]=", &y_128[0]); } -#if defined(__x86__) || defined(__x86_64__) +#ifdef __aarch64__ + } +#endif //__aarch64__ +#if defined(__x86_64__) || defined(__i386__) } #endif } From 48d19e8a9192567ae694fa949f17f028f2902192 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Tue, 2 Sep 2025 08:47:42 +0200 Subject: [PATCH 592/964] Add reset of dlsch_precoding timing counter in nr_dlsim --- openair1/SIMULATION/NR_PHY/dlsim.c | 1 + 1 file changed, 1 insertion(+) diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index 0f21fdb145..611af32ac5 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -1033,6 +1033,7 @@ printf("%d\n", slot); reset_meas(&gNB->dlsch_rate_matching_stats); reset_meas(&gNB->dlsch_segmentation_stats); reset_meas(&gNB->dlsch_modulation_stats); + reset_meas(&gNB->dlsch_precoding_stats); reset_meas(&gNB->dlsch_encoding_stats); reset_meas(&gNB->dci_generation_stats); reset_meas(&gNB->tinput); From 0e09c7c3471a01a7b7f9723235ce744cea1fca49 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Wed, 27 Aug 2025 19:54:07 +0000 Subject: [PATCH 593/964] Add changes for avx512/aarch64 ldpc encoder optimizations newly-generated files for innermost part of the parity bit generation which, for AVX512, uses the mm512_permutex2var_epi8 instruction and for 128-bit (aarch64) the mm_alignr_epi8 (vextq_s8) in the computation corresponding to each non-zero bit of the H matrix. It is generated with ldpctest -n0 -g1. the changes for this are in a future MR. I did these changes to compare with the GPU version (ldpc_encoder_cuda), so that the CPU version is as fast as possible. The generator will come when we merge the GPU encoder/decoder which also has a generator for the CUDA version. it was difficult to extract the changes in ldpctest/ldpc_encoder.c so I just took the generated file. This allows for removing a very large memcpy and reduces the memory demand for the parity matrix computation. For the moment this is limited to largest case in BG1, namely Zc=384. This is the only format used when the number of segments after codeblock segmentation is large (>8). This improves the timing required for ldpc parity bits generation by more than a factor 2 with AVX512. This significantly reduces the total time to generate the DLSCH/PDSCH --- .../nrLDPC_encoder/ldpc384_alignr_byte_128.c | 153 ++++++++++++ .../ldpc384_simd512_alignr_byte.c | 151 ++++++++++++ .../ldpc384_simd512_permutex_byte.c | 218 ++++++++++++++++++ .../nrLDPC_encoder/ldpc_encode_parity_check.c | 25 +- 4 files changed, 544 insertions(+), 3 deletions(-) create mode 100644 openair1/PHY/CODING/nrLDPC_encoder/ldpc384_alignr_byte_128.c create mode 100644 openair1/PHY/CODING/nrLDPC_encoder/ldpc384_simd512_alignr_byte.c create mode 100644 openair1/PHY/CODING/nrLDPC_encoder/ldpc384_simd512_permutex_byte.c diff --git a/openair1/PHY/CODING/nrLDPC_encoder/ldpc384_alignr_byte_128.c b/openair1/PHY/CODING/nrLDPC_encoder/ldpc384_alignr_byte_128.c new file mode 100644 index 0000000000..493a33c735 --- /dev/null +++ b/openair1/PHY/CODING/nrLDPC_encoder/ldpc384_alignr_byte_128.c @@ -0,0 +1,153 @@ +#ifndef __AVX2__ +#include "PHY/sse_intrin.h" +// generated code for Zc=384, byte encoding +static inline void ldpc384_byte(uint8_t *c,uint8_t *d) { + simde__m128i *csimd=(simde__m128i *)c,*dsimd=(simde__m128i *)d; + + simde__m128i *c2,*d2; + + int i2; + for (i2=0; i2<24; i2++) { + c2=&csimd[i2]; + d2=&dsimd[i2]; + +//row: 0 + d2[0]=simde_mm_xor_si128(simde_mm_alignr_epi8(c2[20],c2[19],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[5],c2[4],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[13],c2[12],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[18],c2[17],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[50],c2[49],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[64],c2[63],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[54],c2[53],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[100],c2[99],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[101],c2[100],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[117],c2[116],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[168],c2[167],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[149],c2[148],9),simde_mm_xor_si128(c2[144],simde_mm_xor_si128(c2[210],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[213],c2[212],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[210],c2[209],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[252],c2[251],5),simde_mm_xor_si128(c2[249],simde_mm_xor_si128(c2[256],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[302],c2[301],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[299],c2[298],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[301],c2[300],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[357],c2[356],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[353],c2[352],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[346],c2[345],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[405],c2[404],11),simde_mm_xor_si128(c2[394],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[388],c2[387],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[452],c2[451],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[444],c2[443],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[436],c2[435],15),simde_mm_xor_si128(c2[498],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[489],c2[488],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[489],c2[488],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[535],c2[534],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[547],c2[546],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[548],c2[547],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[578],c2[577],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[598],c2[597],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[591],c2[590],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[647],c2[646],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[637],c2[636],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[646],c2[645],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[686],c2[685],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[678],c2[677],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[686],c2[685],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[734],c2[733],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[727],c2[726],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[724],c2[723],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[775],c2[774],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[791],c2[790],2),simde_mm_xor_si128(c2[787],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[824],c2[823],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[825],c2[824],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[835],c2[834],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[880],c2[879],2),simde_mm_xor_si128(c2[879],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[881],c2[880],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[924],c2[923],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[933],c2[932],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[925],c2[924],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[981],c2[980],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[961],c2[960],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[963],c2[962],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1030],c2[1029],10),simde_mm_xor_si128(c2[1015],simde_mm_alignr_epi8(c2[1031],c2[1030],5))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 1 + d2[24]=simde_mm_xor_si128(simde_mm_alignr_epi8(c2[20],c2[19],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[20],c2[19],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[5],c2[4],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[13],c2[12],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[18],c2[17],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[50],c2[49],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[50],c2[49],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[64],c2[63],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[54],c2[53],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[100],c2[99],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[100],c2[99],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[101],c2[100],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[117],c2[116],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[168],c2[167],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[168],c2[167],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[149],c2[148],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[145],c2[144],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[211],c2[210],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[213],c2[212],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[210],c2[209],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[252],c2[251],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[252],c2[251],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[250],c2[249],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[257],c2[256],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[302],c2[301],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[302],c2[301],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[299],c2[298],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[301],c2[300],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[357],c2[356],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[353],c2[352],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[346],c2[345],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[405],c2[404],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[395],c2[394],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[388],c2[387],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[452],c2[451],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[452],c2[451],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[444],c2[443],3),simde_mm_xor_si128(c2[436],simde_mm_xor_si128(c2[498],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[499],c2[498],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[489],c2[488],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[489],c2[488],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[535],c2[534],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[535],c2[534],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[547],c2[546],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[548],c2[547],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[578],c2[577],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[578],c2[577],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[598],c2[597],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[591],c2[590],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[647],c2[646],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[647],c2[646],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[637],c2[636],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[646],c2[645],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[686],c2[685],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[678],c2[677],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[686],c2[685],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[734],c2[733],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[734],c2[733],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[727],c2[726],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[724],c2[723],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[775],c2[774],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[775],c2[774],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[791],c2[790],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[788],c2[787],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[824],c2[823],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[825],c2[824],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[835],c2[834],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[880],c2[879],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[880],c2[879],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[880],c2[879],1),simde_mm_xor_si128(c2[881],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[924],c2[923],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[924],c2[923],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[933],c2[932],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[925],c2[924],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[981],c2[980],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[981],c2[980],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[961],c2[960],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[963],c2[962],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1030],c2[1029],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1030],c2[1029],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1016],c2[1015],1),simde_mm_alignr_epi8(c2[1031],c2[1030],6)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 2 + d2[48]=simde_mm_xor_si128(simde_mm_alignr_epi8(c2[20],c2[19],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[5],c2[4],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[13],c2[12],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[13],c2[12],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[18],c2[17],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[18],c2[17],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[50],c2[49],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[64],c2[63],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[64],c2[63],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[54],c2[53],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[54],c2[53],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[100],c2[99],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[101],c2[100],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[117],c2[116],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[117],c2[116],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[168],c2[167],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[149],c2[148],10),simde_mm_xor_si128(c2[144],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[145],c2[144],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[211],c2[210],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[213],c2[212],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[213],c2[212],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[210],c2[209],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[210],c2[209],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[252],c2[251],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[250],c2[249],1),simde_mm_xor_si128(c2[256],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[257],c2[256],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[302],c2[301],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[299],c2[298],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[299],c2[298],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[301],c2[300],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[301],c2[300],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[357],c2[356],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[353],c2[352],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[353],c2[352],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[346],c2[345],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[346],c2[345],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[405],c2[404],12),simde_mm_xor_si128(c2[394],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[395],c2[394],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[388],c2[387],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[388],c2[387],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[452],c2[451],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[444],c2[443],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[436],c2[435],15),simde_mm_xor_si128(c2[436],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[499],c2[498],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[489],c2[488],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[489],c2[488],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[489],c2[488],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[489],c2[488],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[535],c2[534],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[547],c2[546],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[548],c2[547],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[548],c2[547],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[578],c2[577],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[598],c2[597],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[591],c2[590],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[591],c2[590],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[647],c2[646],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[637],c2[636],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[637],c2[636],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[646],c2[645],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[646],c2[645],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[686],c2[685],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[678],c2[677],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[678],c2[677],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[686],c2[685],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[686],c2[685],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[734],c2[733],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[727],c2[726],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[724],c2[723],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[724],c2[723],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[775],c2[774],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[791],c2[790],3),simde_mm_xor_si128(c2[787],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[788],c2[787],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[824],c2[823],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[825],c2[824],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[825],c2[824],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[835],c2[834],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[835],c2[834],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[880],c2[879],3),simde_mm_xor_si128(c2[879],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[880],c2[879],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[881],c2[880],15),simde_mm_xor_si128(c2[881],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[924],c2[923],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[933],c2[932],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[925],c2[924],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[925],c2[924],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[981],c2[980],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[961],c2[960],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[961],c2[960],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[963],c2[962],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[963],c2[962],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1030],c2[1029],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1016],c2[1015],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1031],c2[1030],5),simde_mm_alignr_epi8(c2[1031],c2[1030],6))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 3 + d2[72]=simde_mm_xor_si128(simde_mm_alignr_epi8(c2[20],c2[19],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[5],c2[4],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[13],c2[12],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[18],c2[17],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[18],c2[17],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[50],c2[49],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[64],c2[63],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[54],c2[53],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[54],c2[53],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[100],c2[99],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[101],c2[100],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[117],c2[116],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[168],c2[167],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[149],c2[148],10),simde_mm_xor_si128(c2[144],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[145],c2[144],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[211],c2[210],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[213],c2[212],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[210],c2[209],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[210],c2[209],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[252],c2[251],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[250],c2[249],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[257],c2[256],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[302],c2[301],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[299],c2[298],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[301],c2[300],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[301],c2[300],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[357],c2[356],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[353],c2[352],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[346],c2[345],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[346],c2[345],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[405],c2[404],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[395],c2[394],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[388],c2[387],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[388],c2[387],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[452],c2[451],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[444],c2[443],3),simde_mm_xor_si128(c2[436],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[499],c2[498],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[489],c2[488],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[489],c2[488],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[489],c2[488],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[535],c2[534],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[547],c2[546],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[548],c2[547],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[548],c2[547],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[578],c2[577],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[598],c2[597],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[591],c2[590],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[591],c2[590],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[647],c2[646],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[637],c2[636],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[646],c2[645],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[646],c2[645],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[686],c2[685],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[678],c2[677],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[686],c2[685],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[686],c2[685],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[734],c2[733],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[727],c2[726],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[724],c2[723],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[775],c2[774],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[791],c2[790],3),simde_mm_xor_si128(c2[787],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[788],c2[787],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[824],c2[823],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[825],c2[824],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[835],c2[834],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[835],c2[834],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[880],c2[879],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[880],c2[879],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[881],c2[880],15),simde_mm_xor_si128(c2[881],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[924],c2[923],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[933],c2[932],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[925],c2[924],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[981],c2[980],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[961],c2[960],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[963],c2[962],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[963],c2[962],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1030],c2[1029],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1016],c2[1015],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1031],c2[1030],5),simde_mm_alignr_epi8(c2[1031],c2[1030],6)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 4 + d2[96]=simde_mm_xor_si128(simde_mm_alignr_epi8(c2[21],c2[20],12),simde_mm_alignr_epi8(c2[60],c2[59],5)); + +//row: 5 + d2[120]=simde_mm_xor_si128(c2[5],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[15],c2[14],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[23],c2[22],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[4],c2[3],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[13],c2[12],3),simde_mm_xor_si128(c2[59],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[50],c2[49],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[64],c2[63],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[49],c2[48],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[109],c2[108],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[111],c2[110],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[103],c2[102],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[153],c2[152],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[159],c2[158],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[154],c2[153],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[152],c2[151],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[196],c2[195],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[199],c2[198],9),simde_mm_xor_si128(c2[195],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[262],c2[261],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[259],c2[258],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[242],c2[241],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[312],c2[311],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[308],c2[307],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[311],c2[310],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[343],c2[342],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[339],c2[338],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[356],c2[355],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[391],c2[390],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[404],c2[403],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[398],c2[397],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[438],c2[437],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[453],c2[452],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[446],c2[445],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[484],c2[483],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[498],c2[497],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[499],c2[498],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[545],c2[544],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[533],c2[532],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[533],c2[532],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[587],c2[586],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[584],c2[583],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[577],c2[576],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[587],c2[586],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[633],c2[632],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[647],c2[646],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[632],c2[631],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[696],c2[695],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[688],c2[687],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[696],c2[695],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[744],c2[743],4),simde_mm_xor_si128(c2[736],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[734],c2[733],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[785],c2[784],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[776],c2[775],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[773],c2[772],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[784],c2[783],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[833],c2[832],15),simde_mm_xor_si128(c2[834],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[821],c2[820],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[865],c2[864],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[865],c2[864],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[867],c2[866],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[934],c2[933],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[919],c2[918],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[935],c2[934],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[967],c2[966],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[971],c2[970],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[973],c2[972],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1016],c2[1015],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1025],c2[1024],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1017],c2[1016],2),simde_mm_alignr_epi8(c2[1012],c2[1011],3))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 6 + d2[144]=simde_mm_xor_si128(simde_mm_alignr_epi8(c2[18],c2[17],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[305],c2[304],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[481],c2[480],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[550],c2[549],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[630],c2[629],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[832],c2[831],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[866],c2[865],2),simde_mm_alignr_epi8(c2[975],c2[974],1)))))))); + +//row: 7 + d2[168]=simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1],c2[0],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[52],c2[51],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[212],c2[211],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[357],c2[356],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[403],c2[402],2),simde_mm_alignr_epi8(c2[680],c2[679],2)))))); + +//row: 8 + d2[192]=simde_mm_xor_si128(simde_mm_alignr_epi8(c2[24],c2[23],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[6],c2[5],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[9],c2[8],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[16],c2[15],7),simde_mm_xor_si128(c2[17],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[24],c2[23],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[24],c2[23],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[22],c2[21],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[4],c2[3],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[4],c2[3],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[20],c2[19],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[54],c2[53],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[60],c2[59],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[68],c2[67],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[51],c2[50],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[51],c2[50],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[58],c2[57],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[65],c2[64],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[65],c2[64],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[60],c2[59],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[104],c2[103],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[110],c2[109],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[105],c2[104],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[112],c2[111],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[97],c2[96],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[104],c2[103],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[104],c2[103],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[148],c2[147],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[154],c2[153],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[153],c2[152],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[160],c2[159],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[149],c2[148],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[155],c2[154],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[155],c2[154],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[155],c2[154],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[215],c2[214],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[197],c2[196],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[193],c2[192],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[200],c2[199],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[200],c2[199],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[214],c2[213],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[196],c2[195],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[196],c2[195],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[256],c2[255],8),simde_mm_xor_si128(c2[262],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[254],c2[253],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[260],c2[259],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[261],c2[260],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[243],c2[242],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[243],c2[242],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[306],c2[305],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[289],c2[288],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[303],c2[302],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[309],c2[308],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[309],c2[308],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[305],c2[304],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[312],c2[311],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[312],c2[311],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[337],c2[336],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[344],c2[343],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[357],c2[356],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[340],c2[339],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[340],c2[339],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[350],c2[349],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[357],c2[356],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[357],c2[356],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[385],c2[384],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[392],c2[391],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[399],c2[398],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[405],c2[404],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[405],c2[404],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[392],c2[391],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[399],c2[398],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[399],c2[398],3),simde_mm_xor_si128(c2[432],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[439],c2[438],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[448],c2[447],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[454],c2[453],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[441],c2[440],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[447],c2[446],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[447],c2[446],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[503],c2[502],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[485],c2[484],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[493],c2[492],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[499],c2[498],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[499],c2[498],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[493],c2[492],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[499],c2[498],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[499],c2[498],15),simde_mm_xor_si128(c2[539],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[546],c2[545],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[551],c2[550],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[534],c2[533],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[552],c2[551],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[534],c2[533],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[534],c2[533],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[582],c2[581],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[588],c2[587],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[578],c2[577],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[585],c2[584],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[595],c2[594],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[578],c2[577],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[578],c2[577],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[578],c2[577],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[627],c2[626],8),simde_mm_xor_si128(c2[633],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[641],c2[640],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[648],c2[647],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[648],c2[647],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[626],c2[625],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[632],c2[631],15),simde_mm_xor_si128(c2[632],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[690],c2[689],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[673],c2[672],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[682],c2[681],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[689],c2[688],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[689],c2[688],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[690],c2[689],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[696],c2[695],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[696],c2[695],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[738],c2[737],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[721],c2[720],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[731],c2[730],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[737],c2[736],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[728],c2[727],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[734],c2[733],15),simde_mm_xor_si128(c2[734],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[779],c2[778],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[786],c2[785],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[771],c2[770],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[777],c2[776],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[792],c2[791],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[774],c2[773],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[774],c2[773],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[771],c2[770],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[828],c2[827],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[834],c2[833],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[829],c2[828],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[835],c2[834],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[835],c2[834],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[839],c2[838],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[822],c2[821],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[822],c2[821],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[884],c2[883],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[866],c2[865],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[884],c2[883],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[866],c2[865],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[866],c2[865],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[886],c2[885],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[868],c2[867],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[868],c2[867],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[928],c2[927],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[934],c2[933],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[913],c2[912],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[920],c2[919],6),simde_mm_xor_si128(c2[929],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[936],c2[935],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[936],c2[935],8),simde_mm_xor_si128(c2[926],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[961],c2[960],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[968],c2[967],5),simde_mm_xor_si128(c2[965],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[972],c2[971],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[972],c2[971],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[967],c2[966],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[974],c2[973],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[974],c2[973],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1010],c2[1009],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1017],c2[1016],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1020],c2[1019],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1026],c2[1025],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1011],c2[1010],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1017],c2[1016],15),simde_mm_xor_si128(c2[1017],c2[1031])))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 9 + d2[216]=simde_mm_xor_si128(simde_mm_alignr_epi8(c2[23],c2[22],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[63],c2[62],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[501],c2[500],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[537],c2[536],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[628],c2[627],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[835],c2[834],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[868],c2[867],15),simde_mm_alignr_epi8(c2[966],c2[965],2)))))))); + +//row: 10 + d2[240]=simde_mm_xor_si128(simde_mm_alignr_epi8(c2[55],c2[54],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[118],c2[117],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[210],c2[209],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[343],c2[342],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[408],c2[407],15),simde_mm_alignr_epi8(c2[695],c2[694],2)))))); + +//row: 11 + d2[264]=simde_mm_xor_si128(simde_mm_alignr_epi8(c2[17],c2[16],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[3],c2[2],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[3],c2[2],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[2],c2[1],10),simde_mm_xor_si128(c2[12],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[10],c2[9],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[21],c2[20],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[15],c2[14],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1],c2[0],8),simde_mm_xor_si128(c2[3],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[71],c2[70],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[57],c2[56],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[57],c2[56],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[61],c2[60],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[71],c2[70],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[51],c2[50],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[61],c2[60],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[55],c2[54],6),simde_mm_xor_si128(c2[96],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[107],c2[106],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[107],c2[106],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[98],c2[97],10),simde_mm_xor_si128(c2[108],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[114],c2[113],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[100],c2[99],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[164],c2[163],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[151],c2[150],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[151],c2[150],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[146],c2[145],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[156],c2[155],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[165],c2[164],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[152],c2[151],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[207],c2[206],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[194],c2[193],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[210],c2[209],10),simde_mm_xor_si128(c2[196],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[207],c2[206],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[193],c2[192],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[249],c2[248],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[259],c2[258],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[259],c2[258],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[246],c2[245],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[257],c2[256],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[253],c2[252],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[264],c2[263],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[299],c2[298],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[309],c2[308],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[309],c2[308],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[295],c2[294],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[306],c2[305],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[298],c2[297],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[308],c2[307],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[354],c2[353],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[340],c2[339],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[350],c2[349],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[360],c2[359],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[343],c2[342],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[353],c2[352],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[402],c2[401],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[388],c2[387],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[391],c2[390],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[402],c2[401],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[385],c2[384],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[395],c2[394],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[449],c2[448],11),simde_mm_xor_si128(c2[435],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[436],c2[435],1),simde_mm_xor_si128(c2[440],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[451],c2[450],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[433],c2[432],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[444],c2[443],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[495],c2[494],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[482],c2[481],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[482],c2[481],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[485],c2[484],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[496],c2[495],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[486],c2[485],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[496],c2[495],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[532],c2[531],11),simde_mm_xor_si128(c2[542],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[543],c2[542],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[544],c2[543],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[530],c2[529],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[544],c2[543],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[531],c2[530],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[598],c2[597],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[585],c2[584],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[585],c2[584],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[595],c2[594],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[581],c2[580],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[588],c2[587],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[598],c2[597],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[577],c2[576],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[644],c2[643],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[630],c2[629],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[630],c2[629],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[634],c2[633],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[644],c2[643],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[643],c2[642],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[629],c2[628],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[683],c2[682],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[693],c2[692],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[675],c2[674],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[685],c2[684],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[683],c2[682],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[693],c2[692],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[731],c2[730],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[741],c2[740],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[741],c2[740],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[724],c2[723],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[734],c2[733],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[721],c2[720],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[731],c2[730],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[772],c2[771],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[782],c2[781],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[782],c2[781],14),simde_mm_xor_si128(c2[787],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[774],c2[773],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[784],c2[783],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[771],c2[770],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[771],c2[770],15),simde_mm_xor_si128(c2[820],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[831],c2[830],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[822],c2[821],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[832],c2[831],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[832],c2[831],10),simde_mm_xor_si128(c2[818],simde_mm_xor_si128(c2[876],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[887],c2[886],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[887],c2[886],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[876],c2[875],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[887],c2[886],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[878],c2[877],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[865],c2[864],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[921],c2[920],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[931],c2[930],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[931],c2[930],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[930],c2[929],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[916],c2[915],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[922],c2[921],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[933],c2[932],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[978],c2[977],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[964],c2[963],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[964],c2[963],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[982],c2[981],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[969],c2[968],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[984],c2[983],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[970],c2[969],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1027],c2[1026],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1013],c2[1012],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1013],c2[1012],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1012],c2[1011],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1023],c2[1022],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1028],c2[1027],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1014],c2[1013],9),simde_mm_alignr_epi8(c2[1020],c2[1019],12)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 12 + d2[288]=simde_mm_xor_si128(simde_mm_alignr_epi8(c2[5],c2[4],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[60],c2[59],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[491],c2[490],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[543],c2[542],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[628],c2[627],2),simde_mm_alignr_epi8(c2[869],c2[868],10)))))); + +//row: 13 + d2[312]=simde_mm_xor_si128(simde_mm_alignr_epi8(c2[19],c2[18],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[19],c2[18],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[4],c2[3],15),simde_mm_xor_si128(c2[12],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[17],c2[16],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[20],c2[19],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[49],c2[48],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[49],c2[48],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[63],c2[62],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[53],c2[52],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[99],c2[98],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[99],c2[98],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[100],c2[99],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[116],c2[115],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[167],c2[166],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[167],c2[166],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[148],c2[147],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[168],c2[167],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[156],c2[155],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[210],c2[209],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[212],c2[211],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[209],c2[208],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[251],c2[250],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[251],c2[250],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[249],c2[248],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[256],c2[255],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[301],c2[300],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[301],c2[300],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[298],c2[297],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[300],c2[299],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[356],c2[355],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[352],c2[351],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[345],c2[344],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[353],c2[352],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[404],c2[403],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[394],c2[393],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[387],c2[386],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[451],c2[450],15),simde_mm_xor_si128(c2[451],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[443],c2[442],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[436],c2[435],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[498],c2[497],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[498],c2[497],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[488],c2[487],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[488],c2[487],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[534],c2[533],15),simde_mm_xor_si128(c2[534],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[546],c2[545],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[547],c2[546],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[577],c2[576],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[577],c2[576],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[597],c2[596],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[590],c2[589],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[646],c2[645],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[646],c2[645],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[636],c2[635],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[645],c2[644],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[685],c2[684],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[677],c2[676],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[685],c2[684],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[733],c2[732],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[733],c2[732],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[726],c2[725],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[723],c2[722],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[774],c2[773],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[774],c2[773],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[790],c2[789],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[787],c2[786],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[823],c2[822],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[824],c2[823],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[834],c2[833],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[879],c2[878],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[879],c2[878],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[879],c2[878],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[881],c2[880],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[923],c2[922],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[923],c2[922],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[932],c2[931],14),simde_mm_xor_si128(c2[924],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[980],c2[979],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[980],c2[979],13),simde_mm_xor_si128(c2[960],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[962],c2[961],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[968],c2[967],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1029],c2[1028],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1029],c2[1028],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1015],c2[1014],3),simde_mm_alignr_epi8(c2[1030],c2[1029],8)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 14 + d2[336]=simde_mm_xor_si128(simde_mm_alignr_epi8(c2[9],c2[8],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[592],c2[591],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[729],c2[728],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[774],c2[773],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[838],c2[837],11),simde_mm_alignr_epi8(c2[1009],c2[1008],12)))))); + +//row: 15 + d2[360]=simde_mm_xor_si128(simde_mm_alignr_epi8(c2[13],c2[12],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[22],c2[21],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[6],c2[5],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[11],c2[10],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[11],c2[10],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[16],c2[15],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[67],c2[66],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[57],c2[56],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[71],c2[70],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[71],c2[70],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[49],c2[48],2),simde_mm_xor_si128(c2[116],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[118],c2[117],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[110],c2[109],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[160],c2[159],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[166],c2[165],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[161],c2[160],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[161],c2[160],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[203],c2[202],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[206],c2[205],10),simde_mm_xor_si128(c2[202],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[203],c2[202],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[245],c2[244],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[242],c2[241],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[249],c2[248],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[295],c2[294],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[291],c2[290],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[294],c2[293],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[294],c2[293],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[350],c2[349],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[346],c2[345],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[339],c2[338],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[339],c2[338],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[398],c2[397],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[387],c2[386],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[405],c2[404],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[405],c2[404],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[445],c2[444],11),simde_mm_xor_si128(c2[436],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[453],c2[452],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[491],c2[490],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[481],c2[480],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[482],c2[481],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[482],c2[481],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[494],c2[493],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[552],c2[551],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[540],c2[539],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[540],c2[539],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[540],c2[539],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[594],c2[593],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[591],c2[590],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[584],c2[583],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[584],c2[583],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[640],c2[639],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[630],c2[629],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[639],c2[638],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[639],c2[638],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[644],c2[643],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[679],c2[678],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[695],c2[694],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[679],c2[678],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[679],c2[678],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[727],c2[726],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[744],c2[743],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[741],c2[740],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[792],c2[791],8),simde_mm_xor_si128(c2[783],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[780],c2[779],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[780],c2[779],14),simde_mm_xor_si128(c2[816],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[818],c2[817],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[828],c2[827],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[828],c2[827],10),simde_mm_xor_si128(c2[872],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[872],c2[871],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[874],c2[873],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[874],c2[873],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[868],c2[867],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[917],c2[916],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[926],c2[925],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[918],c2[917],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[974],c2[973],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[978],c2[977],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[980],c2[979],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[980],c2[979],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1023],c2[1022],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1032],c2[1031],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1024],c2[1023],2),simde_mm_alignr_epi8(c2[1024],c2[1023],3))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 16 + d2[384]=simde_mm_xor_si128(simde_mm_alignr_epi8(c2[23],c2[22],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[9],c2[8],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[17],c2[16],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[21],c2[20],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[53],c2[52],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[68],c2[67],3),simde_mm_xor_si128(c2[57],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[49],c2[48],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[103],c2[102],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[105],c2[104],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[97],c2[96],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[147],c2[146],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[153],c2[152],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[148],c2[147],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[166],c2[165],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[214],c2[213],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[193],c2[192],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[213],c2[212],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[255],c2[254],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[253],c2[252],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[260],c2[259],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[306],c2[305],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[302],c2[301],10),simde_mm_xor_si128(c2[304],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[337],c2[336],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[357],c2[356],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[350],c2[349],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[385],c2[384],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[398],c2[397],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[392],c2[391],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[456],c2[455],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[447],c2[446],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[440],c2[439],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[502],c2[501],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[492],c2[491],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[492],c2[491],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[539],c2[538],6),simde_mm_xor_si128(c2[550],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[551],c2[550],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[532],c2[531],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[581],c2[580],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[577],c2[576],15),simde_mm_xor_si128(c2[594],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[626],c2[625],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[641],c2[640],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[625],c2[624],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[690],c2[689],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[682],c2[681],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[689],c2[688],13),simde_mm_xor_si128(c2[737],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[730],c2[729],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[727],c2[726],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[779],c2[778],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[770],c2[769],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[791],c2[790],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[827],c2[826],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[828],c2[827],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[839],c2[838],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[883],c2[882],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[883],c2[882],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[885],c2[884],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[927],c2[926],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[913],c2[912],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[929],c2[928],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[961],c2[960],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[965],c2[964],6),simde_mm_xor_si128(c2[966],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[979],c2[978],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1010],c2[1009],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1019],c2[1018],9),simde_mm_alignr_epi8(c2[1010],c2[1009],14))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 17 + d2[408]=simde_mm_xor_si128(simde_mm_alignr_epi8(c2[17],c2[16],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[691],c2[690],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[774],c2[773],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[839],c2[838],6),simde_mm_alignr_epi8(c2[1032],c2[1031],7))))); + +//row: 18 + d2[432]=simde_mm_xor_si128(simde_mm_alignr_epi8(c2[57],c2[56],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[587],c2[586],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[642],c2[641],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[873],c2[872],4),simde_mm_alignr_epi8(c2[913],c2[912],4))))); + +//row: 19 + d2[456]=simde_mm_xor_si128(simde_mm_alignr_epi8(c2[10],c2[9],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[62],c2[61],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[358],c2[357],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[400],c2[399],2),simde_mm_alignr_epi8(c2[493],c2[492],5))))); + +//row: 20 + d2[480]=simde_mm_xor_si128(simde_mm_alignr_epi8(c2[23],c2[22],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[9],c2[8],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[17],c2[16],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[21],c2[20],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[12],c2[11],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[53],c2[52],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[68],c2[67],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[58],c2[57],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[103],c2[102],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[105],c2[104],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[97],c2[96],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[147],c2[146],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[153],c2[152],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[148],c2[147],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[157],c2[156],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[214],c2[213],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[193],c2[192],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[213],c2[212],14),simde_mm_xor_si128(c2[255],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[253],c2[252],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[260],c2[259],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[306],c2[305],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[302],c2[301],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[305],c2[304],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[337],c2[336],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[357],c2[356],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[350],c2[349],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[385],c2[384],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[398],c2[397],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[392],c2[391],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[456],c2[455],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[447],c2[446],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[440],c2[439],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[449],c2[448],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[502],c2[501],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[492],c2[491],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[492],c2[491],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[539],c2[538],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[551],c2[550],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[551],c2[550],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[550],c2[549],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[581],c2[580],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[578],c2[577],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[595],c2[594],2),simde_mm_xor_si128(c2[626],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[641],c2[640],3),simde_mm_xor_si128(c2[625],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[690],c2[689],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[682],c2[681],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[689],c2[688],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[738],c2[737],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[730],c2[729],14),simde_mm_xor_si128(c2[727],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[779],c2[778],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[770],c2[769],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[791],c2[790],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[827],c2[826],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[828],c2[827],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[839],c2[838],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[883],c2[882],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[883],c2[882],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[885],c2[884],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[927],c2[926],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[913],c2[912],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[929],c2[928],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[961],c2[960],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[965],c2[964],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[967],c2[966],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1010],c2[1009],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1019],c2[1018],11),c2[1010])))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 21 + d2[504]=simde_mm_xor_si128(simde_mm_alignr_epi8(c2[61],c2[60],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[247],c2[246],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[789],c2[788],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[974],c2[973],5),simde_mm_alignr_epi8(c2[1015],c2[1014],1))))); + +//row: 22 + d2[528]=simde_mm_xor_si128(simde_mm_alignr_epi8(c2[2],c2[1],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[577],c2[576],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[639],c2[638],9),simde_mm_alignr_epi8(c2[818],c2[817],6)))); + +//row: 23 + d2[552]=simde_mm_xor_si128(simde_mm_alignr_epi8(c2[50],c2[49],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[102],c2[101],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[484],c2[483],13),simde_mm_alignr_epi8(c2[866],c2[865],11)))); + +//row: 24 + d2[576]=simde_mm_xor_si128(simde_mm_alignr_epi8(c2[10],c2[9],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[20],c2[19],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[4],c2[3],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[8],c2[7],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[19],c2[18],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[64],c2[63],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[55],c2[54],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[69],c2[68],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[114],c2[113],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[116],c2[115],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[108],c2[107],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[158],c2[157],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[164],c2[163],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[159],c2[158],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[154],c2[153],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[201],c2[200],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[204],c2[203],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[200],c2[199],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[207],c2[206],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[242],c2[241],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[264],c2[263],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[247],c2[246],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[293],c2[292],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[289],c2[288],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[292],c2[291],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[348],c2[347],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[344],c2[343],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[337],c2[336],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[396],c2[395],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[385],c2[384],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[403],c2[402],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[443],c2[442],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[434],c2[433],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[451],c2[450],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[489],c2[488],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[503],c2[502],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[503],c2[502],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[550],c2[549],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[538],c2[537],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[538],c2[537],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[550],c2[549],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[592],c2[591],11),simde_mm_xor_si128(c2[588],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[582],c2[581],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[637],c2[636],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[628],c2[627],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[636],c2[635],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[677],c2[676],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[693],c2[692],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[676],c2[675],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[725],c2[724],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[741],c2[740],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[738],c2[737],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[790],c2[789],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[781],c2[780],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[778],c2[777],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[838],c2[837],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[839],c2[838],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[826],c2[825],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[870],c2[869],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[870],c2[869],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[872],c2[871],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[914],c2[913],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[924],c2[923],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[916],c2[915],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[972],c2[971],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[976],c2[975],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[978],c2[977],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1021],c2[1020],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1030],c2[1029],10),simde_mm_alignr_epi8(c2[1021],c2[1020],15))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 25 + d2[600]=simde_mm_xor_si128(simde_mm_alignr_epi8(c2[53],c2[52],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[290],c2[289],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[360],c2[359],15),simde_mm_alignr_epi8(c2[692],c2[691],8)))); + +//row: 26 + d2[624]=simde_mm_xor_si128(simde_mm_alignr_epi8(c2[5],c2[4],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[102],c2[101],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[197],c2[196],12),simde_mm_alignr_epi8(c2[729],c2[728],8)))); + +//row: 27 + d2[648]=simde_mm_xor_si128(simde_mm_alignr_epi8(c2[61],c2[60],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[301],c2[300],2),simde_mm_alignr_epi8(c2[391],c2[390],5))); + +//row: 28 + d2[672]=simde_mm_xor_si128(simde_mm_alignr_epi8(c2[14],c2[13],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[194],c2[193],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[928],c2[927],4),simde_mm_alignr_epi8(c2[1026],c2[1025],2)))); + +//row: 29 + d2[696]=simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1],c2[0],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[10],c2[9],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[18],c2[17],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[23],c2[22],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[23],c2[22],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[55],c2[54],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[69],c2[68],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[59],c2[58],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[59],c2[58],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[64],c2[63],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[105],c2[104],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[106],c2[105],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[98],c2[97],7),simde_mm_xor_si128(c2[148],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[154],c2[153],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[149],c2[148],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[149],c2[148],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[215],c2[214],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[194],c2[193],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[215],c2[214],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[215],c2[214],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[257],c2[256],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[254],c2[253],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[261],c2[260],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[307],c2[306],7),simde_mm_xor_si128(c2[303],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[306],c2[305],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[306],c2[305],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[338],c2[337],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[358],c2[357],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[351],c2[350],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[351],c2[350],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[386],c2[385],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[399],c2[398],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[393],c2[392],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[393],c2[392],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[433],c2[432],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[449],c2[448],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[441],c2[440],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[503],c2[502],15),simde_mm_xor_si128(c2[493],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[494],c2[493],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[494],c2[493],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[540],c2[539],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[552],c2[551],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[552],c2[551],15),simde_mm_xor_si128(c2[528],simde_mm_xor_si128(c2[582],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[579],c2[578],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[596],c2[595],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[596],c2[595],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[628],c2[627],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[642],c2[641],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[627],c2[626],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[627],c2[626],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[691],c2[690],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[683],c2[682],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[691],c2[690],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[691],c2[690],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[673],c2[672],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[739],c2[738],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[732],c2[731],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[729],c2[728],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[780],c2[779],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[772],c2[771],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[792],c2[791],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[792],c2[791],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[829],c2[828],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[830],c2[829],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[840],c2[839],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[840],c2[839],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[885],c2[884],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[884],c2[883],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[886],c2[885],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[886],c2[885],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[874],c2[873],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[929],c2[928],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[914],c2[913],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[930],c2[929],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[962],c2[961],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[966],c2[965],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[968],c2[967],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[968],c2[967],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1011],c2[1010],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1020],c2[1019],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1012],c2[1011],3),simde_mm_alignr_epi8(c2[1012],c2[1011],4))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 30 + d2[720]=simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1],c2[0],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[11],c2[10],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[19],c2[18],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[19],c2[18],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[23],c2[22],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[23],c2[22],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[10],c2[9],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[55],c2[54],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[70],c2[69],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[70],c2[69],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[60],c2[59],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[60],c2[59],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[105],c2[104],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[107],c2[106],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[99],c2[98],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[99],c2[98],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[149],c2[148],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[155],c2[154],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[150],c2[149],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[150],c2[149],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[216],c2[215],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[195],c2[194],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[195],c2[194],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[215],c2[214],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[215],c2[214],14),simde_mm_xor_si128(c2[257],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[255],c2[254],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[262],c2[261],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[262],c2[261],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[308],c2[307],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[304],c2[303],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[304],c2[303],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[307],c2[306],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[307],c2[306],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[339],c2[338],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[359],c2[358],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[359],c2[358],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[352],c2[351],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[352],c2[351],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[387],c2[386],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[400],c2[399],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[400],c2[399],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[394],c2[393],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[394],c2[393],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[434],c2[433],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[449],c2[448],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[442],c2[441],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[442],c2[441],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[504],c2[503],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[494],c2[493],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[494],c2[493],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[494],c2[493],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[494],c2[493],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[495],c2[494],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[541],c2[540],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[529],c2[528],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[529],c2[528],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[529],c2[528],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[583],c2[582],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[580],c2[579],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[597],c2[596],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[597],c2[596],2),simde_mm_xor_si128(c2[628],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[643],c2[642],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[643],c2[642],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[627],c2[626],15),simde_mm_xor_si128(c2[627],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[641],c2[640],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[692],c2[691],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[684],c2[683],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[684],c2[683],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[691],c2[690],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[691],c2[690],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[740],c2[739],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[732],c2[731],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[729],c2[728],15),simde_mm_xor_si128(c2[729],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[781],c2[780],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[772],c2[771],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[769],c2[768],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[769],c2[768],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[829],c2[828],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[830],c2[829],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[830],c2[829],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[817],c2[816],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[817],c2[816],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[885],c2[884],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[885],c2[884],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[885],c2[884],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[887],c2[886],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[887],c2[886],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[929],c2[928],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[915],c2[914],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[931],c2[930],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[931],c2[930],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[963],c2[962],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[967],c2[966],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[967],c2[966],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[969],c2[968],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[969],c2[968],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1012],c2[1011],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1021],c2[1020],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1012],c2[1011],15),c2[1012]))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 31 + d2[744]=simde_mm_xor_si128(simde_mm_alignr_epi8(c2[12],c2[11],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[12],c2[11],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[21],c2[20],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[21],c2[20],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[5],c2[4],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[5],c2[4],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[10],c2[9],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[10],c2[9],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[10],c2[9],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[66],c2[65],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[66],c2[65],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[56],c2[55],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[56],c2[55],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[70],c2[69],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[70],c2[69],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[70],c2[69],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[55],c2[54],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[116],c2[115],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[116],c2[115],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[117],c2[116],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[117],c2[116],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[109],c2[108],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[109],c2[108],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[160],c2[159],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[160],c2[159],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[165],c2[164],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[165],c2[164],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[161],c2[160],2),simde_mm_xor_si128(c2[160],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[161],c2[160],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[203],c2[202],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[203],c2[202],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[205],c2[204],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[205],c2[204],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[202],c2[201],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[202],c2[201],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[202],c2[201],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[244],c2[243],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[244],c2[243],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[242],c2[241],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[242],c2[241],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[249],c2[248],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[249],c2[248],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[294],c2[293],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[294],c2[293],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[291],c2[290],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[291],c2[290],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[293],c2[292],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[293],c2[292],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[293],c2[292],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[349],c2[348],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[349],c2[348],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[345],c2[344],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[345],c2[344],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[338],c2[337],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[338],c2[337],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[338],c2[337],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[350],c2[349],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[397],c2[396],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[397],c2[396],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[387],c2[386],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[387],c2[386],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[404],c2[403],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[404],c2[403],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[404],c2[403],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[444],c2[443],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[444],c2[443],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[436],c2[435],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[436],c2[435],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[453],c2[452],1),simde_mm_xor_si128(c2[452],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[491],c2[490],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[491],c2[490],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[481],c2[480],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[481],c2[480],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[481],c2[480],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[481],c2[480],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[481],c2[480],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[551],c2[550],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[551],c2[550],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[539],c2[538],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[539],c2[538],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[540],c2[539],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[540],c2[539],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[540],c2[539],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[594],c2[593],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[594],c2[593],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[590],c2[589],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[590],c2[589],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[583],c2[582],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[583],c2[582],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[583],c2[582],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[639],c2[638],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[639],c2[638],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[629],c2[628],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[629],c2[628],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[638],c2[637],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[638],c2[637],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[638],c2[637],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[678],c2[677],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[678],c2[677],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[694],c2[693],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[694],c2[693],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[678],c2[677],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[678],c2[677],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[678],c2[677],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[726],c2[725],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[726],c2[725],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[743],c2[742],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[743],c2[742],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[740],c2[739],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[740],c2[739],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[791],c2[790],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[791],c2[790],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[783],c2[782],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[783],c2[782],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[780],c2[779],2),simde_mm_xor_si128(c2[779],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[780],c2[779],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[840],c2[839],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[840],c2[839],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[817],c2[816],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[817],c2[816],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[827],c2[826],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[827],c2[826],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[827],c2[826],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[872],c2[871],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[872],c2[871],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[872],c2[871],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[872],c2[871],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[874],c2[873],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[873],c2[872],15),simde_mm_xor_si128(c2[873],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[916],c2[915],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[916],c2[915],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[925],c2[924],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[925],c2[924],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[917],c2[916],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[917],c2[916],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[973],c2[972],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[973],c2[972],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[977],c2[976],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[977],c2[976],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[979],c2[978],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[979],c2[978],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[979],c2[978],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1022],c2[1021],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1022],c2[1021],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1032],c2[1031],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1032],c2[1031],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1023],c2[1022],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1023],c2[1022],5),simde_mm_alignr_epi8(c2[1023],c2[1022],6))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 32 + d2[768]=simde_mm_xor_si128(simde_mm_alignr_epi8(c2[14],c2[13],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[23],c2[22],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[7],c2[6],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[7],c2[6],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[12],c2[11],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[12],c2[11],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[7],c2[6],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[68],c2[67],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[58],c2[57],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[58],c2[57],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[72],c2[71],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[72],c2[71],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[118],c2[117],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[119],c2[118],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[111],c2[110],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[111],c2[110],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[162],c2[161],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[167],c2[166],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[162],c2[161],15),simde_mm_xor_si128(c2[162],simde_mm_xor_si128(c2[204],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[207],c2[206],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[207],c2[206],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[204],c2[203],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[204],c2[203],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[246],c2[245],5),simde_mm_xor_si128(c2[243],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[250],c2[249],15),simde_mm_xor_si128(c2[250],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[296],c2[295],8),simde_mm_xor_si128(c2[292],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[293],c2[292],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[295],c2[294],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[295],c2[294],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[351],c2[350],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[347],c2[346],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[347],c2[346],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[340],c2[339],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[340],c2[339],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[399],c2[398],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[388],c2[387],15),simde_mm_xor_si128(c2[388],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[406],c2[405],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[406],c2[405],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[446],c2[445],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[438],c2[437],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[454],c2[453],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[454],c2[453],15),simde_mm_xor_si128(c2[492],simde_mm_xor_si128(c2[482],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[483],c2[482],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[483],c2[482],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[483],c2[482],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[529],c2[528],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[541],c2[540],7),simde_mm_xor_si128(c2[541],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[542],c2[541],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[596],c2[595],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[592],c2[591],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[585],c2[584],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[585],c2[584],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[589],c2[588],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[641],c2[640],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[631],c2[630],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[631],c2[630],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[640],c2[639],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[640],c2[639],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[680],c2[679],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[696],c2[695],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[696],c2[695],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[680],c2[679],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[680],c2[679],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[683],c2[682],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[728],c2[727],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[721],c2[720],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[742],c2[741],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[742],c2[741],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[769],c2[768],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[785],c2[784],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[781],c2[780],15),simde_mm_xor_si128(c2[781],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[818],c2[817],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[819],c2[818],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[819],c2[818],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[829],c2[828],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[829],c2[828],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[874],c2[873],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[873],c2[872],15),simde_mm_xor_si128(c2[873],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[875],c2[874],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[875],c2[874],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[918],c2[917],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[927],c2[926],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[919],c2[918],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[919],c2[918],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[975],c2[974],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[979],c2[978],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[979],c2[978],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[981],c2[980],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[981],c2[980],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1024],c2[1023],10),simde_mm_xor_si128(c2[1009],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1025],c2[1024],4),simde_mm_alignr_epi8(c2[1025],c2[1024],5)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 33 + d2[792]=simde_mm_xor_si128(simde_mm_alignr_epi8(c2[69],c2[68],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[97],c2[96],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[551],c2[550],9),simde_mm_alignr_epi8(c2[1015],c2[1014],9)))); + +//row: 34 + d2[816]=simde_mm_xor_si128(simde_mm_alignr_epi8(c2[15],c2[14],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[346],c2[345],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[733],c2[732],10),simde_mm_alignr_epi8(c2[836],c2[835],8)))); + +//row: 35 + d2[840]=simde_mm_xor_si128(simde_mm_alignr_epi8(c2[12],c2[11],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[22],c2[21],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[6],c2[5],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[10],c2[9],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[66],c2[65],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[57],c2[56],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[71],c2[70],1),simde_mm_xor_si128(c2[68],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[116],c2[115],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[118],c2[117],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[110],c2[109],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[160],c2[159],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[166],c2[165],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[161],c2[160],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[203],c2[202],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[206],c2[205],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[202],c2[201],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[244],c2[243],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[242],c2[241],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[249],c2[248],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[295],c2[294],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[291],c2[290],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[294],c2[293],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[309],c2[308],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[350],c2[349],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[346],c2[345],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[339],c2[338],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[398],c2[397],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[387],c2[386],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[405],c2[404],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[445],c2[444],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[436],c2[435],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[453],c2[452],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[491],c2[490],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[481],c2[480],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[481],c2[480],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[552],c2[551],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[540],c2[539],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[540],c2[539],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[594],c2[593],11),simde_mm_xor_si128(c2[590],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[584],c2[583],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[577],c2[576],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[639],c2[638],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[630],c2[629],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[638],c2[637],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[679],c2[678],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[695],c2[694],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[678],c2[677],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[727],c2[726],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[743],c2[742],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[740],c2[739],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[792],c2[791],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[783],c2[782],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[780],c2[779],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[840],c2[839],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[817],c2[816],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[828],c2[827],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[872],c2[871],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[872],c2[871],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[874],c2[873],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[916],c2[915],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[926],c2[925],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[918],c2[917],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[974],c2[973],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[978],c2[977],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[980],c2[979],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1023],c2[1022],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1032],c2[1031],10),simde_mm_alignr_epi8(c2[1023],c2[1022],15)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 36 + d2[864]=simde_mm_xor_si128(simde_mm_alignr_epi8(c2[14],c2[13],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[692],c2[691],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[739],c2[738],9),simde_mm_alignr_epi8(c2[866],c2[865],5)))); + +//row: 37 + d2[888]=simde_mm_xor_si128(simde_mm_alignr_epi8(c2[3],c2[2],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[3],c2[2],7),simde_mm_xor_si128(c2[12],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[21],c2[20],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1],c2[0],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[57],c2[56],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[57],c2[56],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[71],c2[70],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[61],c2[60],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[65],c2[64],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[107],c2[106],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[107],c2[106],6),simde_mm_xor_si128(c2[108],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[100],c2[99],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[151],c2[150],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[151],c2[150],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[156],c2[155],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[152],c2[151],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[194],c2[193],4),simde_mm_xor_si128(c2[196],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[193],c2[192],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[259],c2[258],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[259],c2[258],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[257],c2[256],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[264],c2[263],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[309],c2[308],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[309],c2[308],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[306],c2[305],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[308],c2[307],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[340],c2[339],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[360],c2[359],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[353],c2[352],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[388],c2[387],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[402],c2[401],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[395],c2[394],12),simde_mm_xor_si128(c2[435],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[436],c2[435],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[451],c2[450],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[444],c2[443],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[482],c2[481],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[482],c2[481],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[496],c2[495],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[496],c2[495],8),simde_mm_xor_si128(c2[542],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[543],c2[542],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[530],c2[529],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[531],c2[530],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[585],c2[584],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[585],c2[584],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[581],c2[580],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[598],c2[597],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[630],c2[629],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[630],c2[629],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[644],c2[643],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[629],c2[628],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[630],c2[629],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[693],c2[692],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[685],c2[684],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[693],c2[692],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[741],c2[740],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[741],c2[740],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[734],c2[733],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[731],c2[730],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[782],c2[781],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[782],c2[781],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[774],c2[773],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[771],c2[770],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[831],c2[830],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[832],c2[831],7),simde_mm_xor_si128(c2[818],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[887],c2[886],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[887],c2[886],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[887],c2[886],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[865],c2[864],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[931],c2[930],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[931],c2[930],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[916],c2[915],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[933],c2[932],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[964],c2[963],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[964],c2[963],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[969],c2[968],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[970],c2[969],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1013],c2[1012],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1013],c2[1012],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1023],c2[1022],4),simde_mm_alignr_epi8(c2[1014],c2[1013],9)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 38 + d2[912]=simde_mm_xor_si128(simde_mm_alignr_epi8(c2[12],c2[11],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[444],c2[443],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[499],c2[498],1),simde_mm_alignr_epi8(c2[590],c2[589],6)))); + +//row: 39 + d2[936]=simde_mm_xor_si128(simde_mm_alignr_epi8(c2[65],c2[64],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[150],c2[149],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[358],c2[357],10),simde_mm_alignr_epi8(c2[931],c2[930],9)))); + +//row: 40 + d2[960]=simde_mm_xor_si128(simde_mm_alignr_epi8(c2[11],c2[10],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[387],c2[386],5),simde_mm_alignr_epi8(c2[836],c2[835],8))); + +//row: 41 + d2[984]=simde_mm_xor_si128(simde_mm_alignr_epi8(c2[52],c2[51],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[164],c2[163],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[441],c2[440],11),c2[882]))); + +//row: 42 + d2[1008]=simde_mm_xor_si128(simde_mm_alignr_epi8(c2[9],c2[8],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[19],c2[18],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[3],c2[2],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[3],c2[2],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[7],c2[6],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[7],c2[6],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[8],c2[7],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[63],c2[62],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[54],c2[53],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[54],c2[53],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[68],c2[67],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[68],c2[67],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[113],c2[112],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[115],c2[114],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[107],c2[106],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[107],c2[106],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[157],c2[156],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[163],c2[162],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[158],c2[157],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[158],c2[157],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[200],c2[199],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[203],c2[202],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[203],c2[202],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[199],c2[198],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[199],c2[198],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[193],c2[192],14),simde_mm_xor_si128(c2[241],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[263],c2[262],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[246],c2[245],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[246],c2[245],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[292],c2[291],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[312],c2[311],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[312],c2[311],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[291],c2[290],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[291],c2[290],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[347],c2[346],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[343],c2[342],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[343],c2[342],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[360],c2[359],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[360],c2[359],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[395],c2[394],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[408],c2[407],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[408],c2[407],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[402],c2[401],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[402],c2[401],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[442],c2[441],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[433],c2[432],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[450],c2[449],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[450],c2[449],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[488],c2[487],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[502],c2[501],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[502],c2[501],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[502],c2[501],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[502],c2[501],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[549],c2[548],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[537],c2[536],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[537],c2[536],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[537],c2[536],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[591],c2[590],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[588],c2[587],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[581],c2[580],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[581],c2[580],2),simde_mm_xor_si128(c2[636],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[627],c2[626],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[627],c2[626],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[635],c2[634],15),simde_mm_xor_si128(c2[635],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[676],c2[675],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[692],c2[691],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[692],c2[691],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[675],c2[674],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[675],c2[674],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[724],c2[723],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[740],c2[739],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[737],c2[736],15),simde_mm_xor_si128(c2[737],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[789],c2[788],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[780],c2[779],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[777],c2[776],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[777],c2[776],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[837],c2[836],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[838],c2[837],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[838],c2[837],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[825],c2[824],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[825],c2[824],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[869],c2[868],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[869],c2[868],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[869],c2[868],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[871],c2[870],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[871],c2[870],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[913],c2[912],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[923],c2[922],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[915],c2[914],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[915],c2[914],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[971],c2[970],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[975],c2[974],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[975],c2[974],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[977],c2[976],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[977],c2[976],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1020],c2[1019],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1029],c2[1028],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1020],c2[1019],15),c2[1020])))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 43 + d2[1032]=simde_mm_xor_si128(simde_mm_alignr_epi8(c2[6],c2[5],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[16],c2[15],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[24],c2[23],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[4],c2[3],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[4],c2[3],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[60],c2[59],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[51],c2[50],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[64],c2[63],15),simde_mm_xor_si128(c2[64],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[56],c2[55],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[110],c2[109],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[112],c2[111],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[104],c2[103],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[154],c2[153],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[160],c2[159],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[155],c2[154],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[155],c2[154],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[197],c2[196],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[200],c2[199],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[196],c2[195],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[196],c2[195],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[262],c2[261],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[260],c2[259],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[243],c2[242],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[289],c2[288],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[309],c2[308],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[311],c2[310],15),simde_mm_xor_si128(c2[311],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[344],c2[343],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[340],c2[339],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[357],c2[356],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[357],c2[356],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[392],c2[391],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[405],c2[404],9),simde_mm_xor_si128(c2[398],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[399],c2[398],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[439],c2[438],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[454],c2[453],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[447],c2[446],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[485],c2[484],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[499],c2[498],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[499],c2[498],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[499],c2[498],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[546],c2[545],6),simde_mm_xor_si128(c2[533],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[534],c2[533],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[534],c2[533],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[588],c2[587],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[584],c2[583],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[577],c2[576],15),simde_mm_xor_si128(c2[577],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[633],c2[632],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[648],c2[647],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[632],c2[631],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[632],c2[631],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[673],c2[672],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[689],c2[688],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[696],c2[695],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[696],c2[695],13),simde_mm_xor_si128(c2[720],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[737],c2[736],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[734],c2[733],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[786],c2[785],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[777],c2[776],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[774],c2[773],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[774],c2[773],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[777],c2[776],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[834],c2[833],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[835],c2[834],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[822],c2[821],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[822],c2[821],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[866],c2[865],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[866],c2[865],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[868],c2[867],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[868],c2[867],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[872],c2[871],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[934],c2[933],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[920],c2[919],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[936],c2[935],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[968],c2[967],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[972],c2[971],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[973],c2[972],15),simde_mm_xor_si128(c2[973],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1017],c2[1016],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1026],c2[1025],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1017],c2[1016],13),simde_mm_alignr_epi8(c2[1017],c2[1016],14))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 44 + d2[1056]=simde_mm_xor_si128(simde_mm_alignr_epi8(c2[13],c2[12],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[22],c2[21],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[6],c2[5],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[11],c2[10],6),simde_mm_xor_si128(c2[5],simde_mm_xor_si128(simde_mm_alignr_epi8(c2[67],c2[66],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[57],c2[56],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[71],c2[70],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[117],c2[116],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[118],c2[117],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[110],c2[109],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[161],c2[160],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[166],c2[165],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[162],c2[161],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[204],c2[203],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[206],c2[205],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[203],c2[202],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[245],c2[244],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[243],c2[242],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[250],c2[249],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[295],c2[294],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[292],c2[291],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[294],c2[293],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[350],c2[349],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[346],c2[345],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[339],c2[338],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[341],c2[340],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[398],c2[397],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[388],c2[387],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[405],c2[404],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[445],c2[444],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[437],c2[436],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[454],c2[453],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[443],c2[442],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[492],c2[491],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[482],c2[481],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[482],c2[481],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[552],c2[551],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[540],c2[539],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[541],c2[540],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[595],c2[594],3),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[591],c2[590],8),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[584],c2[583],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[640],c2[639],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[630],c2[629],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[639],c2[638],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[679],c2[678],11),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[695],c2[694],10),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[679],c2[678],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[727],c2[726],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[744],c2[743],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[741],c2[740],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[792],c2[791],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[784],c2[783],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[781],c2[780],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[817],c2[816],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[818],c2[817],5),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[828],c2[827],14),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[873],c2[872],4),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[873],c2[872],2),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[875],c2[874],1),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[917],c2[916],6),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[926],c2[925],13),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[918],c2[917],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[974],c2[973],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[978],c2[977],15),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[980],c2[979],9),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1023],c2[1022],12),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[1009],c2[1008],2),simde_mm_alignr_epi8(c2[1024],c2[1023],7)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 45 + d2[1080]=simde_mm_xor_si128(simde_mm_alignr_epi8(c2[57],c2[56],7),simde_mm_xor_si128(simde_mm_alignr_epi8(c2[298],c2[297],5),simde_mm_alignr_epi8(c2[481],c2[480],15))); + } +} +#endif diff --git a/openair1/PHY/CODING/nrLDPC_encoder/ldpc384_simd512_alignr_byte.c b/openair1/PHY/CODING/nrLDPC_encoder/ldpc384_simd512_alignr_byte.c new file mode 100644 index 0000000000..96b83f4e28 --- /dev/null +++ b/openair1/PHY/CODING/nrLDPC_encoder/ldpc384_simd512_alignr_byte.c @@ -0,0 +1,151 @@ +#include "PHY/sse_intrin.h" +// generated code for Zc=384, byte encoding +static inline void ldpc384_byte(uint8_t *c,uint8_t *d) { + __m512i *csimd=(__m512i *)c,*dsimd=(__m512i *)d; + + __m512i *c2,*d2; + + int i2; + for (i2=0; i2<6; i2++) { + c2=&csimd[i2]; + d2=&dsimd[i2]; + +//row: 0 + d2[0]=_mm512_xor_si512(_mm512_alignr_epi8(c2[5],c2[4],51),_mm512_xor_si512(_mm512_alignr_epi8(c2[2],c2[1],12),_mm512_xor_si512(_mm512_alignr_epi8(c2[4],c2[3],13),_mm512_xor_si512(_mm512_alignr_epi8(c2[5],c2[4],20),_mm512_xor_si512(_mm512_alignr_epi8(c2[13],c2[12],19),_mm512_xor_si512(_mm512_alignr_epi8(c2[16],c2[15],58),_mm512_xor_si512(_mm512_alignr_epi8(c2[14],c2[13],23),_mm512_xor_si512(_mm512_alignr_epi8(c2[25],c2[24],50),_mm512_xor_si512(_mm512_alignr_epi8(c2[26],c2[25],12),_mm512_xor_si512(_mm512_alignr_epi8(c2[30],c2[29],8),_mm512_xor_si512(_mm512_alignr_epi8(c2[42],c2[41],49),_mm512_xor_si512(_mm512_alignr_epi8(c2[38],c2[37],9),_mm512_xor_si512(c2[36],_mm512_xor_si512(_mm512_alignr_epi8(c2[53],c2[52],32),_mm512_xor_si512(_mm512_alignr_epi8(c2[54],c2[53],12),_mm512_xor_si512(_mm512_alignr_epi8(c2[53],c2[52],19),_mm512_xor_si512(_mm512_alignr_epi8(c2[63],c2[62],53),_mm512_xor_si512(_mm512_alignr_epi8(c2[63],c2[62],16),_mm512_xor_si512(c2[64],_mm512_xor_si512(_mm512_alignr_epi8(c2[76],c2[75],24),_mm512_xor_si512(_mm512_alignr_epi8(c2[75],c2[74],33),_mm512_xor_si512(_mm512_alignr_epi8(c2[76],c2[75],7),_mm512_xor_si512(_mm512_alignr_epi8(c2[90],c2[89],11),_mm512_xor_si512(_mm512_alignr_epi8(c2[89],c2[88],11),_mm512_xor_si512(_mm512_alignr_epi8(c2[87],c2[86],25),_mm512_xor_si512(_mm512_alignr_epi8(c2[102],c2[101],11),_mm512_xor_si512(_mm512_alignr_epi8(c2[99],c2[98],32),_mm512_xor_si512(_mm512_alignr_epi8(c2[97],c2[96],56),_mm512_xor_si512(_mm512_alignr_epi8(c2[113],c2[112],61),_mm512_xor_si512(_mm512_alignr_epi8(c2[111],c2[110],50),_mm512_xor_si512(_mm512_alignr_epi8(c2[109],c2[108],63),_mm512_xor_si512(_mm512_alignr_epi8(c2[125],c2[124],32),_mm512_xor_si512(_mm512_alignr_epi8(c2[123],c2[122],1),_mm512_xor_si512(_mm512_alignr_epi8(c2[123],c2[122],4),_mm512_xor_si512(_mm512_alignr_epi8(c2[134],c2[133],45),_mm512_xor_si512(_mm512_alignr_epi8(c2[137],c2[136],39),_mm512_xor_si512(_mm512_alignr_epi8(c2[137],c2[136],49),_mm512_xor_si512(_mm512_alignr_epi8(c2[145],c2[144],17),_mm512_xor_si512(_mm512_alignr_epi8(c2[150],c2[149],22),_mm512_xor_si512(_mm512_alignr_epi8(c2[148],c2[147],39),_mm512_xor_si512(_mm512_alignr_epi8(c2[162],c2[161],37),_mm512_xor_si512(_mm512_alignr_epi8(c2[160],c2[159],8),_mm512_xor_si512(_mm512_alignr_epi8(c2[162],c2[161],21),_mm512_xor_si512(_mm512_alignr_epi8(c2[172],c2[171],25),_mm512_xor_si512(_mm512_alignr_epi8(c2[170],c2[169],24),_mm512_xor_si512(_mm512_alignr_epi8(c2[172],c2[171],20),_mm512_xor_si512(_mm512_alignr_epi8(c2[184],c2[183],23),_mm512_xor_si512(_mm512_alignr_epi8(c2[182],c2[181],35),_mm512_xor_si512(_mm512_alignr_epi8(c2[181],c2[180],53),_mm512_xor_si512(_mm512_alignr_epi8(c2[194],c2[193],42),_mm512_xor_si512(_mm512_alignr_epi8(c2[198],c2[197],34),_mm512_xor_si512(_mm512_alignr_epi8(c2[197],c2[196],48),_mm512_xor_si512(_mm512_alignr_epi8(c2[206],c2[205],50),_mm512_xor_si512(_mm512_alignr_epi8(c2[207],c2[206],3),_mm512_xor_si512(_mm512_alignr_epi8(c2[209],c2[208],44),_mm512_xor_si512(_mm512_alignr_epi8(c2[220],c2[219],50),_mm512_xor_si512(_mm512_alignr_epi8(c2[220],c2[219],48),_mm512_xor_si512(_mm512_alignr_epi8(c2[221],c2[220],15),_mm512_xor_si512(_mm512_alignr_epi8(c2[231],c2[230],52),_mm512_xor_si512(_mm512_alignr_epi8(c2[234],c2[233],11),_mm512_xor_si512(_mm512_alignr_epi8(c2[232],c2[231],13),_mm512_xor_si512(_mm512_alignr_epi8(c2[246],c2[245],10),_mm512_xor_si512(_mm512_alignr_epi8(c2[241],c2[240],13),_mm512_xor_si512(_mm512_alignr_epi8(c2[241],c2[240],39),_mm512_xor_si512(_mm512_alignr_epi8(c2[258],c2[257],26),_mm512_xor_si512(_mm512_alignr_epi8(c2[254],c2[253],48),_mm512_alignr_epi8(c2[258],c2[257],37))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 1 + d2[6]=_mm512_xor_si512(_mm512_alignr_epi8(c2[5],c2[4],51),_mm512_xor_si512(_mm512_alignr_epi8(c2[5],c2[4],52),_mm512_xor_si512(_mm512_alignr_epi8(c2[2],c2[1],13),_mm512_xor_si512(_mm512_alignr_epi8(c2[4],c2[3],14),_mm512_xor_si512(_mm512_alignr_epi8(c2[5],c2[4],21),_mm512_xor_si512(_mm512_alignr_epi8(c2[13],c2[12],19),_mm512_xor_si512(_mm512_alignr_epi8(c2[13],c2[12],20),_mm512_xor_si512(_mm512_alignr_epi8(c2[16],c2[15],59),_mm512_xor_si512(_mm512_alignr_epi8(c2[14],c2[13],24),_mm512_xor_si512(_mm512_alignr_epi8(c2[25],c2[24],50),_mm512_xor_si512(_mm512_alignr_epi8(c2[25],c2[24],51),_mm512_xor_si512(_mm512_alignr_epi8(c2[26],c2[25],13),_mm512_xor_si512(_mm512_alignr_epi8(c2[30],c2[29],9),_mm512_xor_si512(_mm512_alignr_epi8(c2[42],c2[41],49),_mm512_xor_si512(_mm512_alignr_epi8(c2[42],c2[41],50),_mm512_xor_si512(_mm512_alignr_epi8(c2[38],c2[37],10),_mm512_xor_si512(_mm512_alignr_epi8(c2[37],c2[36],1),_mm512_xor_si512(_mm512_alignr_epi8(c2[53],c2[52],33),_mm512_xor_si512(_mm512_alignr_epi8(c2[54],c2[53],13),_mm512_xor_si512(_mm512_alignr_epi8(c2[53],c2[52],20),_mm512_xor_si512(_mm512_alignr_epi8(c2[63],c2[62],53),_mm512_xor_si512(_mm512_alignr_epi8(c2[63],c2[62],54),_mm512_xor_si512(_mm512_alignr_epi8(c2[63],c2[62],17),_mm512_xor_si512(_mm512_alignr_epi8(c2[65],c2[64],1),_mm512_xor_si512(_mm512_alignr_epi8(c2[76],c2[75],24),_mm512_xor_si512(_mm512_alignr_epi8(c2[76],c2[75],25),_mm512_xor_si512(_mm512_alignr_epi8(c2[75],c2[74],34),_mm512_xor_si512(_mm512_alignr_epi8(c2[76],c2[75],8),_mm512_xor_si512(_mm512_alignr_epi8(c2[90],c2[89],12),_mm512_xor_si512(_mm512_alignr_epi8(c2[89],c2[88],12),_mm512_xor_si512(_mm512_alignr_epi8(c2[87],c2[86],26),_mm512_xor_si512(_mm512_alignr_epi8(c2[102],c2[101],12),_mm512_xor_si512(_mm512_alignr_epi8(c2[99],c2[98],33),_mm512_xor_si512(_mm512_alignr_epi8(c2[97],c2[96],57),_mm512_xor_si512(_mm512_alignr_epi8(c2[113],c2[112],61),_mm512_xor_si512(_mm512_alignr_epi8(c2[113],c2[112],62),_mm512_xor_si512(_mm512_alignr_epi8(c2[111],c2[110],51),_mm512_xor_si512(c2[109],_mm512_xor_si512(_mm512_alignr_epi8(c2[125],c2[124],32),_mm512_xor_si512(_mm512_alignr_epi8(c2[125],c2[124],33),_mm512_xor_si512(_mm512_alignr_epi8(c2[123],c2[122],2),_mm512_xor_si512(_mm512_alignr_epi8(c2[123],c2[122],5),_mm512_xor_si512(_mm512_alignr_epi8(c2[134],c2[133],45),_mm512_xor_si512(_mm512_alignr_epi8(c2[134],c2[133],46),_mm512_xor_si512(_mm512_alignr_epi8(c2[137],c2[136],40),_mm512_xor_si512(_mm512_alignr_epi8(c2[137],c2[136],50),_mm512_xor_si512(_mm512_alignr_epi8(c2[145],c2[144],17),_mm512_xor_si512(_mm512_alignr_epi8(c2[145],c2[144],18),_mm512_xor_si512(_mm512_alignr_epi8(c2[150],c2[149],23),_mm512_xor_si512(_mm512_alignr_epi8(c2[148],c2[147],40),_mm512_xor_si512(_mm512_alignr_epi8(c2[162],c2[161],37),_mm512_xor_si512(_mm512_alignr_epi8(c2[162],c2[161],38),_mm512_xor_si512(_mm512_alignr_epi8(c2[160],c2[159],9),_mm512_xor_si512(_mm512_alignr_epi8(c2[162],c2[161],22),_mm512_xor_si512(_mm512_alignr_epi8(c2[172],c2[171],26),_mm512_xor_si512(_mm512_alignr_epi8(c2[170],c2[169],25),_mm512_xor_si512(_mm512_alignr_epi8(c2[172],c2[171],21),_mm512_xor_si512(_mm512_alignr_epi8(c2[184],c2[183],23),_mm512_xor_si512(_mm512_alignr_epi8(c2[184],c2[183],24),_mm512_xor_si512(_mm512_alignr_epi8(c2[182],c2[181],36),_mm512_xor_si512(_mm512_alignr_epi8(c2[181],c2[180],54),_mm512_xor_si512(_mm512_alignr_epi8(c2[194],c2[193],42),_mm512_xor_si512(_mm512_alignr_epi8(c2[194],c2[193],43),_mm512_xor_si512(_mm512_alignr_epi8(c2[198],c2[197],35),_mm512_xor_si512(_mm512_alignr_epi8(c2[197],c2[196],49),_mm512_xor_si512(_mm512_alignr_epi8(c2[206],c2[205],51),_mm512_xor_si512(_mm512_alignr_epi8(c2[207],c2[206],4),_mm512_xor_si512(_mm512_alignr_epi8(c2[209],c2[208],45),_mm512_xor_si512(_mm512_alignr_epi8(c2[220],c2[219],50),_mm512_xor_si512(_mm512_alignr_epi8(c2[220],c2[219],51),_mm512_xor_si512(_mm512_alignr_epi8(c2[220],c2[219],49),_mm512_xor_si512(_mm512_alignr_epi8(c2[221],c2[220],16),_mm512_xor_si512(_mm512_alignr_epi8(c2[231],c2[230],52),_mm512_xor_si512(_mm512_alignr_epi8(c2[231],c2[230],53),_mm512_xor_si512(_mm512_alignr_epi8(c2[234],c2[233],12),_mm512_xor_si512(_mm512_alignr_epi8(c2[232],c2[231],14),_mm512_xor_si512(_mm512_alignr_epi8(c2[246],c2[245],10),_mm512_xor_si512(_mm512_alignr_epi8(c2[246],c2[245],11),_mm512_xor_si512(_mm512_alignr_epi8(c2[241],c2[240],14),_mm512_xor_si512(_mm512_alignr_epi8(c2[241],c2[240],40),_mm512_xor_si512(_mm512_alignr_epi8(c2[258],c2[257],26),_mm512_xor_si512(_mm512_alignr_epi8(c2[258],c2[257],27),_mm512_xor_si512(_mm512_alignr_epi8(c2[254],c2[253],49),_mm512_alignr_epi8(c2[258],c2[257],38)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 2 + d2[12]=_mm512_xor_si512(_mm512_alignr_epi8(c2[5],c2[4],52),_mm512_xor_si512(_mm512_alignr_epi8(c2[2],c2[1],13),_mm512_xor_si512(_mm512_alignr_epi8(c2[4],c2[3],13),_mm512_xor_si512(_mm512_alignr_epi8(c2[4],c2[3],14),_mm512_xor_si512(_mm512_alignr_epi8(c2[5],c2[4],20),_mm512_xor_si512(_mm512_alignr_epi8(c2[5],c2[4],21),_mm512_xor_si512(_mm512_alignr_epi8(c2[13],c2[12],20),_mm512_xor_si512(_mm512_alignr_epi8(c2[16],c2[15],58),_mm512_xor_si512(_mm512_alignr_epi8(c2[16],c2[15],59),_mm512_xor_si512(_mm512_alignr_epi8(c2[14],c2[13],23),_mm512_xor_si512(_mm512_alignr_epi8(c2[14],c2[13],24),_mm512_xor_si512(_mm512_alignr_epi8(c2[25],c2[24],51),_mm512_xor_si512(_mm512_alignr_epi8(c2[26],c2[25],13),_mm512_xor_si512(_mm512_alignr_epi8(c2[30],c2[29],8),_mm512_xor_si512(_mm512_alignr_epi8(c2[30],c2[29],9),_mm512_xor_si512(_mm512_alignr_epi8(c2[42],c2[41],50),_mm512_xor_si512(_mm512_alignr_epi8(c2[38],c2[37],10),_mm512_xor_si512(c2[36],_mm512_xor_si512(_mm512_alignr_epi8(c2[37],c2[36],1),_mm512_xor_si512(_mm512_alignr_epi8(c2[53],c2[52],33),_mm512_xor_si512(_mm512_alignr_epi8(c2[54],c2[53],12),_mm512_xor_si512(_mm512_alignr_epi8(c2[54],c2[53],13),_mm512_xor_si512(_mm512_alignr_epi8(c2[53],c2[52],19),_mm512_xor_si512(_mm512_alignr_epi8(c2[53],c2[52],20),_mm512_xor_si512(_mm512_alignr_epi8(c2[63],c2[62],54),_mm512_xor_si512(_mm512_alignr_epi8(c2[63],c2[62],17),_mm512_xor_si512(c2[64],_mm512_xor_si512(_mm512_alignr_epi8(c2[65],c2[64],1),_mm512_xor_si512(_mm512_alignr_epi8(c2[76],c2[75],25),_mm512_xor_si512(_mm512_alignr_epi8(c2[75],c2[74],33),_mm512_xor_si512(_mm512_alignr_epi8(c2[75],c2[74],34),_mm512_xor_si512(_mm512_alignr_epi8(c2[76],c2[75],7),_mm512_xor_si512(_mm512_alignr_epi8(c2[76],c2[75],8),_mm512_xor_si512(_mm512_alignr_epi8(c2[90],c2[89],12),_mm512_xor_si512(_mm512_alignr_epi8(c2[89],c2[88],11),_mm512_xor_si512(_mm512_alignr_epi8(c2[89],c2[88],12),_mm512_xor_si512(_mm512_alignr_epi8(c2[87],c2[86],25),_mm512_xor_si512(_mm512_alignr_epi8(c2[87],c2[86],26),_mm512_xor_si512(_mm512_alignr_epi8(c2[102],c2[101],12),_mm512_xor_si512(_mm512_alignr_epi8(c2[99],c2[98],32),_mm512_xor_si512(_mm512_alignr_epi8(c2[99],c2[98],33),_mm512_xor_si512(_mm512_alignr_epi8(c2[97],c2[96],56),_mm512_xor_si512(_mm512_alignr_epi8(c2[97],c2[96],57),_mm512_xor_si512(_mm512_alignr_epi8(c2[113],c2[112],62),_mm512_xor_si512(_mm512_alignr_epi8(c2[111],c2[110],51),_mm512_xor_si512(_mm512_alignr_epi8(c2[109],c2[108],63),_mm512_xor_si512(c2[109],_mm512_xor_si512(_mm512_alignr_epi8(c2[125],c2[124],33),_mm512_xor_si512(_mm512_alignr_epi8(c2[123],c2[122],1),_mm512_xor_si512(_mm512_alignr_epi8(c2[123],c2[122],2),_mm512_xor_si512(_mm512_alignr_epi8(c2[123],c2[122],4),_mm512_xor_si512(_mm512_alignr_epi8(c2[123],c2[122],5),_mm512_xor_si512(_mm512_alignr_epi8(c2[134],c2[133],46),_mm512_xor_si512(_mm512_alignr_epi8(c2[137],c2[136],40),_mm512_xor_si512(_mm512_alignr_epi8(c2[137],c2[136],49),_mm512_xor_si512(_mm512_alignr_epi8(c2[137],c2[136],50),_mm512_xor_si512(_mm512_alignr_epi8(c2[145],c2[144],18),_mm512_xor_si512(_mm512_alignr_epi8(c2[150],c2[149],23),_mm512_xor_si512(_mm512_alignr_epi8(c2[148],c2[147],39),_mm512_xor_si512(_mm512_alignr_epi8(c2[148],c2[147],40),_mm512_xor_si512(_mm512_alignr_epi8(c2[162],c2[161],38),_mm512_xor_si512(_mm512_alignr_epi8(c2[160],c2[159],8),_mm512_xor_si512(_mm512_alignr_epi8(c2[160],c2[159],9),_mm512_xor_si512(_mm512_alignr_epi8(c2[162],c2[161],21),_mm512_xor_si512(_mm512_alignr_epi8(c2[162],c2[161],22),_mm512_xor_si512(_mm512_alignr_epi8(c2[172],c2[171],26),_mm512_xor_si512(_mm512_alignr_epi8(c2[170],c2[169],24),_mm512_xor_si512(_mm512_alignr_epi8(c2[170],c2[169],25),_mm512_xor_si512(_mm512_alignr_epi8(c2[172],c2[171],20),_mm512_xor_si512(_mm512_alignr_epi8(c2[172],c2[171],21),_mm512_xor_si512(_mm512_alignr_epi8(c2[184],c2[183],24),_mm512_xor_si512(_mm512_alignr_epi8(c2[182],c2[181],36),_mm512_xor_si512(_mm512_alignr_epi8(c2[181],c2[180],53),_mm512_xor_si512(_mm512_alignr_epi8(c2[181],c2[180],54),_mm512_xor_si512(_mm512_alignr_epi8(c2[194],c2[193],43),_mm512_xor_si512(_mm512_alignr_epi8(c2[198],c2[197],35),_mm512_xor_si512(_mm512_alignr_epi8(c2[197],c2[196],48),_mm512_xor_si512(_mm512_alignr_epi8(c2[197],c2[196],49),_mm512_xor_si512(_mm512_alignr_epi8(c2[206],c2[205],51),_mm512_xor_si512(_mm512_alignr_epi8(c2[207],c2[206],3),_mm512_xor_si512(_mm512_alignr_epi8(c2[207],c2[206],4),_mm512_xor_si512(_mm512_alignr_epi8(c2[209],c2[208],44),_mm512_xor_si512(_mm512_alignr_epi8(c2[209],c2[208],45),_mm512_xor_si512(_mm512_alignr_epi8(c2[220],c2[219],51),_mm512_xor_si512(_mm512_alignr_epi8(c2[220],c2[219],48),_mm512_xor_si512(_mm512_alignr_epi8(c2[220],c2[219],49),_mm512_xor_si512(_mm512_alignr_epi8(c2[221],c2[220],15),_mm512_xor_si512(_mm512_alignr_epi8(c2[221],c2[220],16),_mm512_xor_si512(_mm512_alignr_epi8(c2[231],c2[230],53),_mm512_xor_si512(_mm512_alignr_epi8(c2[234],c2[233],12),_mm512_xor_si512(_mm512_alignr_epi8(c2[232],c2[231],13),_mm512_xor_si512(_mm512_alignr_epi8(c2[232],c2[231],14),_mm512_xor_si512(_mm512_alignr_epi8(c2[246],c2[245],11),_mm512_xor_si512(_mm512_alignr_epi8(c2[241],c2[240],13),_mm512_xor_si512(_mm512_alignr_epi8(c2[241],c2[240],14),_mm512_xor_si512(_mm512_alignr_epi8(c2[241],c2[240],39),_mm512_xor_si512(_mm512_alignr_epi8(c2[241],c2[240],40),_mm512_xor_si512(_mm512_alignr_epi8(c2[258],c2[257],27),_mm512_xor_si512(_mm512_alignr_epi8(c2[254],c2[253],49),_mm512_xor_si512(_mm512_alignr_epi8(c2[258],c2[257],37),_mm512_alignr_epi8(c2[258],c2[257],38))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 3 + d2[18]=_mm512_xor_si512(_mm512_alignr_epi8(c2[5],c2[4],52),_mm512_xor_si512(_mm512_alignr_epi8(c2[2],c2[1],13),_mm512_xor_si512(_mm512_alignr_epi8(c2[4],c2[3],14),_mm512_xor_si512(_mm512_alignr_epi8(c2[5],c2[4],20),_mm512_xor_si512(_mm512_alignr_epi8(c2[5],c2[4],21),_mm512_xor_si512(_mm512_alignr_epi8(c2[13],c2[12],20),_mm512_xor_si512(_mm512_alignr_epi8(c2[16],c2[15],59),_mm512_xor_si512(_mm512_alignr_epi8(c2[14],c2[13],23),_mm512_xor_si512(_mm512_alignr_epi8(c2[14],c2[13],24),_mm512_xor_si512(_mm512_alignr_epi8(c2[25],c2[24],51),_mm512_xor_si512(_mm512_alignr_epi8(c2[26],c2[25],13),_mm512_xor_si512(_mm512_alignr_epi8(c2[30],c2[29],9),_mm512_xor_si512(_mm512_alignr_epi8(c2[42],c2[41],50),_mm512_xor_si512(_mm512_alignr_epi8(c2[38],c2[37],10),_mm512_xor_si512(c2[36],_mm512_xor_si512(_mm512_alignr_epi8(c2[37],c2[36],1),_mm512_xor_si512(_mm512_alignr_epi8(c2[53],c2[52],33),_mm512_xor_si512(_mm512_alignr_epi8(c2[54],c2[53],13),_mm512_xor_si512(_mm512_alignr_epi8(c2[53],c2[52],19),_mm512_xor_si512(_mm512_alignr_epi8(c2[53],c2[52],20),_mm512_xor_si512(_mm512_alignr_epi8(c2[63],c2[62],54),_mm512_xor_si512(_mm512_alignr_epi8(c2[63],c2[62],17),_mm512_xor_si512(_mm512_alignr_epi8(c2[65],c2[64],1),_mm512_xor_si512(_mm512_alignr_epi8(c2[76],c2[75],25),_mm512_xor_si512(_mm512_alignr_epi8(c2[75],c2[74],34),_mm512_xor_si512(_mm512_alignr_epi8(c2[76],c2[75],7),_mm512_xor_si512(_mm512_alignr_epi8(c2[76],c2[75],8),_mm512_xor_si512(_mm512_alignr_epi8(c2[90],c2[89],12),_mm512_xor_si512(_mm512_alignr_epi8(c2[89],c2[88],12),_mm512_xor_si512(_mm512_alignr_epi8(c2[87],c2[86],25),_mm512_xor_si512(_mm512_alignr_epi8(c2[87],c2[86],26),_mm512_xor_si512(_mm512_alignr_epi8(c2[102],c2[101],12),_mm512_xor_si512(_mm512_alignr_epi8(c2[99],c2[98],33),_mm512_xor_si512(_mm512_alignr_epi8(c2[97],c2[96],56),_mm512_xor_si512(_mm512_alignr_epi8(c2[97],c2[96],57),_mm512_xor_si512(_mm512_alignr_epi8(c2[113],c2[112],62),_mm512_xor_si512(_mm512_alignr_epi8(c2[111],c2[110],51),_mm512_xor_si512(c2[109],_mm512_xor_si512(_mm512_alignr_epi8(c2[125],c2[124],33),_mm512_xor_si512(_mm512_alignr_epi8(c2[123],c2[122],2),_mm512_xor_si512(_mm512_alignr_epi8(c2[123],c2[122],4),_mm512_xor_si512(_mm512_alignr_epi8(c2[123],c2[122],5),_mm512_xor_si512(_mm512_alignr_epi8(c2[134],c2[133],46),_mm512_xor_si512(_mm512_alignr_epi8(c2[137],c2[136],40),_mm512_xor_si512(_mm512_alignr_epi8(c2[137],c2[136],49),_mm512_xor_si512(_mm512_alignr_epi8(c2[137],c2[136],50),_mm512_xor_si512(_mm512_alignr_epi8(c2[145],c2[144],18),_mm512_xor_si512(_mm512_alignr_epi8(c2[150],c2[149],23),_mm512_xor_si512(_mm512_alignr_epi8(c2[148],c2[147],39),_mm512_xor_si512(_mm512_alignr_epi8(c2[148],c2[147],40),_mm512_xor_si512(_mm512_alignr_epi8(c2[162],c2[161],38),_mm512_xor_si512(_mm512_alignr_epi8(c2[160],c2[159],9),_mm512_xor_si512(_mm512_alignr_epi8(c2[162],c2[161],21),_mm512_xor_si512(_mm512_alignr_epi8(c2[162],c2[161],22),_mm512_xor_si512(_mm512_alignr_epi8(c2[172],c2[171],26),_mm512_xor_si512(_mm512_alignr_epi8(c2[170],c2[169],25),_mm512_xor_si512(_mm512_alignr_epi8(c2[172],c2[171],20),_mm512_xor_si512(_mm512_alignr_epi8(c2[172],c2[171],21),_mm512_xor_si512(_mm512_alignr_epi8(c2[184],c2[183],24),_mm512_xor_si512(_mm512_alignr_epi8(c2[182],c2[181],36),_mm512_xor_si512(_mm512_alignr_epi8(c2[181],c2[180],54),_mm512_xor_si512(_mm512_alignr_epi8(c2[194],c2[193],43),_mm512_xor_si512(_mm512_alignr_epi8(c2[198],c2[197],35),_mm512_xor_si512(_mm512_alignr_epi8(c2[197],c2[196],48),_mm512_xor_si512(_mm512_alignr_epi8(c2[197],c2[196],49),_mm512_xor_si512(_mm512_alignr_epi8(c2[206],c2[205],51),_mm512_xor_si512(_mm512_alignr_epi8(c2[207],c2[206],4),_mm512_xor_si512(_mm512_alignr_epi8(c2[209],c2[208],44),_mm512_xor_si512(_mm512_alignr_epi8(c2[209],c2[208],45),_mm512_xor_si512(_mm512_alignr_epi8(c2[220],c2[219],51),_mm512_xor_si512(_mm512_alignr_epi8(c2[220],c2[219],49),_mm512_xor_si512(_mm512_alignr_epi8(c2[221],c2[220],15),_mm512_xor_si512(_mm512_alignr_epi8(c2[221],c2[220],16),_mm512_xor_si512(_mm512_alignr_epi8(c2[231],c2[230],53),_mm512_xor_si512(_mm512_alignr_epi8(c2[234],c2[233],12),_mm512_xor_si512(_mm512_alignr_epi8(c2[232],c2[231],14),_mm512_xor_si512(_mm512_alignr_epi8(c2[246],c2[245],11),_mm512_xor_si512(_mm512_alignr_epi8(c2[241],c2[240],14),_mm512_xor_si512(_mm512_alignr_epi8(c2[241],c2[240],39),_mm512_xor_si512(_mm512_alignr_epi8(c2[241],c2[240],40),_mm512_xor_si512(_mm512_alignr_epi8(c2[258],c2[257],27),_mm512_xor_si512(_mm512_alignr_epi8(c2[254],c2[253],49),_mm512_xor_si512(_mm512_alignr_epi8(c2[258],c2[257],37),_mm512_alignr_epi8(c2[258],c2[257],38)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 4 + d2[24]=_mm512_xor_si512(_mm512_alignr_epi8(c2[6],c2[5],12),_mm512_alignr_epi8(c2[15],c2[14],53)); + +//row: 5 + d2[30]=_mm512_xor_si512(_mm512_alignr_epi8(c2[2],c2[1],16),_mm512_xor_si512(_mm512_alignr_epi8(c2[4],c2[3],41),_mm512_xor_si512(_mm512_alignr_epi8(c2[6],c2[5],42),_mm512_xor_si512(_mm512_alignr_epi8(c2[1],c2[0],49),_mm512_xor_si512(_mm512_alignr_epi8(c2[4],c2[3],3),_mm512_xor_si512(_mm512_alignr_epi8(c2[15],c2[14],48),_mm512_xor_si512(_mm512_alignr_epi8(c2[13],c2[12],23),_mm512_xor_si512(_mm512_alignr_epi8(c2[16],c2[15],52),_mm512_xor_si512(_mm512_alignr_epi8(c2[13],c2[12],14),_mm512_xor_si512(_mm512_alignr_epi8(c2[28],c2[27],15),_mm512_xor_si512(_mm512_alignr_epi8(c2[28],c2[27],41),_mm512_xor_si512(_mm512_alignr_epi8(c2[26],c2[25],37),_mm512_xor_si512(_mm512_alignr_epi8(c2[39],c2[38],14),_mm512_xor_si512(_mm512_alignr_epi8(c2[40],c2[39],38),_mm512_xor_si512(_mm512_alignr_epi8(c2[39],c2[38],29),_mm512_xor_si512(_mm512_alignr_epi8(c2[38],c2[37],51),_mm512_xor_si512(_mm512_alignr_epi8(c2[49],c2[48],61),_mm512_xor_si512(_mm512_alignr_epi8(c2[50],c2[49],41),_mm512_xor_si512(_mm512_alignr_epi8(c2[49],c2[48],48),_mm512_xor_si512(_mm512_alignr_epi8(c2[66],c2[65],18),_mm512_xor_si512(_mm512_alignr_epi8(c2[65],c2[64],45),_mm512_xor_si512(_mm512_alignr_epi8(c2[61],c2[60],29),_mm512_xor_si512(_mm512_alignr_epi8(c2[78],c2[77],53),_mm512_xor_si512(_mm512_alignr_epi8(c2[77],c2[76],62),_mm512_xor_si512(_mm512_alignr_epi8(c2[78],c2[77],36),_mm512_xor_si512(_mm512_alignr_epi8(c2[86],c2[85],40),_mm512_xor_si512(_mm512_alignr_epi8(c2[85],c2[84],40),_mm512_xor_si512(_mm512_alignr_epi8(c2[89],c2[88],54),_mm512_xor_si512(_mm512_alignr_epi8(c2[98],c2[97],40),_mm512_xor_si512(_mm512_alignr_epi8(c2[101],c2[100],61),_mm512_xor_si512(_mm512_alignr_epi8(c2[100],c2[99],21),_mm512_xor_si512(_mm512_alignr_epi8(c2[110],c2[109],26),_mm512_xor_si512(_mm512_alignr_epi8(c2[114],c2[113],15),_mm512_xor_si512(_mm512_alignr_epi8(c2[112],c2[111],28),_mm512_xor_si512(_mm512_alignr_epi8(c2[121],c2[120],61),_mm512_xor_si512(_mm512_alignr_epi8(c2[125],c2[124],30),_mm512_xor_si512(_mm512_alignr_epi8(c2[125],c2[124],33),_mm512_xor_si512(_mm512_alignr_epi8(c2[137],c2[136],10),_mm512_xor_si512(_mm512_alignr_epi8(c2[134],c2[133],4),_mm512_xor_si512(_mm512_alignr_epi8(c2[134],c2[133],14),_mm512_xor_si512(_mm512_alignr_epi8(c2[147],c2[146],46),_mm512_xor_si512(_mm512_alignr_epi8(c2[146],c2[145],51),_mm512_xor_si512(_mm512_alignr_epi8(c2[145],c2[144],4),_mm512_xor_si512(_mm512_alignr_epi8(c2[147],c2[146],38),_mm512_xor_si512(_mm512_alignr_epi8(c2[159],c2[158],2),_mm512_xor_si512(_mm512_alignr_epi8(c2[162],c2[161],37),_mm512_xor_si512(_mm512_alignr_epi8(c2[158],c2[157],50),_mm512_xor_si512(_mm512_alignr_epi8(c2[174],c2[173],54),_mm512_xor_si512(_mm512_alignr_epi8(c2[172],c2[171],53),_mm512_xor_si512(_mm512_alignr_epi8(c2[174],c2[173],49),_mm512_xor_si512(_mm512_alignr_epi8(c2[186],c2[185],52),_mm512_xor_si512(c2[184],_mm512_xor_si512(_mm512_alignr_epi8(c2[184],c2[183],18),_mm512_xor_si512(_mm512_alignr_epi8(c2[197],c2[196],7),_mm512_xor_si512(_mm512_alignr_epi8(c2[194],c2[193],63),_mm512_xor_si512(_mm512_alignr_epi8(c2[194],c2[193],13),_mm512_xor_si512(_mm512_alignr_epi8(c2[196],c2[195],49),_mm512_xor_si512(_mm512_alignr_epi8(c2[209],c2[208],15),_mm512_xor_si512(_mm512_alignr_epi8(c2[209],c2[208],32),_mm512_xor_si512(_mm512_alignr_epi8(c2[206],c2[205],9),_mm512_xor_si512(_mm512_alignr_epi8(c2[217],c2[216],15),_mm512_xor_si512(_mm512_alignr_epi8(c2[217],c2[216],13),_mm512_xor_si512(_mm512_alignr_epi8(c2[217],c2[216],44),_mm512_xor_si512(_mm512_alignr_epi8(c2[234],c2[233],17),_mm512_xor_si512(_mm512_alignr_epi8(c2[230],c2[229],40),_mm512_xor_si512(_mm512_alignr_epi8(c2[234],c2[233],42),_mm512_xor_si512(_mm512_alignr_epi8(c2[242],c2[241],39),_mm512_xor_si512(_mm512_alignr_epi8(c2[243],c2[242],42),_mm512_xor_si512(_mm512_alignr_epi8(c2[244],c2[243],4),_mm512_xor_si512(_mm512_alignr_epi8(c2[254],c2[253],55),_mm512_xor_si512(_mm512_alignr_epi8(c2[257],c2[256],13),_mm512_xor_si512(_mm512_alignr_epi8(c2[255],c2[254],2),_mm512_alignr_epi8(c2[253],c2[252],51))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 6 + d2[36]=_mm512_xor_si512(_mm512_alignr_epi8(c2[5],c2[4],22),_mm512_xor_si512(_mm512_alignr_epi8(c2[77],c2[76],1),_mm512_xor_si512(_mm512_alignr_epi8(c2[121],c2[120],1),_mm512_xor_si512(_mm512_alignr_epi8(c2[138],c2[137],31),_mm512_xor_si512(_mm512_alignr_epi8(c2[158],c2[157],28),_mm512_xor_si512(_mm512_alignr_epi8(c2[208],c2[207],61),_mm512_xor_si512(_mm512_alignr_epi8(c2[217],c2[216],18),_mm512_alignr_epi8(c2[244],c2[243],33)))))))); + +//row: 7 + d2[42]=_mm512_xor_si512(_mm512_alignr_epi8(c2[1],c2[0],9),_mm512_xor_si512(_mm512_alignr_epi8(c2[13],c2[12],62),_mm512_xor_si512(_mm512_alignr_epi8(c2[53],c2[52],60),_mm512_xor_si512(_mm512_alignr_epi8(c2[90],c2[89],13),_mm512_xor_si512(_mm512_alignr_epi8(c2[101],c2[100],34),_mm512_alignr_epi8(c2[170],c2[169],50)))))); + +//row: 8 + d2[48]=_mm512_xor_si512(_mm512_alignr_epi8(c2[6],c2[5],54),_mm512_xor_si512(_mm512_alignr_epi8(c2[2],c2[1],30),_mm512_xor_si512(_mm512_alignr_epi8(c2[3],c2[2],15),_mm512_xor_si512(_mm512_alignr_epi8(c2[4],c2[3],55),_mm512_xor_si512(_mm512_alignr_epi8(c2[5],c2[4],16),_mm512_xor_si512(_mm512_alignr_epi8(c2[6],c2[5],55),_mm512_xor_si512(_mm512_alignr_epi8(c2[6],c2[5],56),_mm512_xor_si512(_mm512_alignr_epi8(c2[6],c2[5],23),_mm512_xor_si512(_mm512_alignr_epi8(c2[1],c2[0],62),_mm512_xor_si512(_mm512_alignr_epi8(c2[1],c2[0],63),_mm512_xor_si512(_mm512_alignr_epi8(c2[5],c2[4],51),_mm512_xor_si512(_mm512_alignr_epi8(c2[14],c2[13],22),_mm512_xor_si512(_mm512_alignr_epi8(c2[15],c2[14],62),_mm512_xor_si512(_mm512_alignr_epi8(c2[17],c2[16],61),_mm512_xor_si512(_mm512_alignr_epi8(c2[13],c2[12],36),_mm512_xor_si512(_mm512_alignr_epi8(c2[13],c2[12],37),_mm512_xor_si512(_mm512_alignr_epi8(c2[15],c2[14],26),_mm512_xor_si512(_mm512_alignr_epi8(c2[17],c2[16],1),_mm512_xor_si512(_mm512_alignr_epi8(c2[17],c2[16],2),_mm512_xor_si512(_mm512_alignr_epi8(c2[15],c2[14],51),_mm512_xor_si512(_mm512_alignr_epi8(c2[26],c2[25],53),_mm512_xor_si512(_mm512_alignr_epi8(c2[28],c2[27],29),_mm512_xor_si512(_mm512_alignr_epi8(c2[27],c2[26],15),_mm512_xor_si512(_mm512_alignr_epi8(c2[28],c2[27],55),_mm512_xor_si512(_mm512_alignr_epi8(c2[25],c2[24],11),_mm512_xor_si512(_mm512_alignr_epi8(c2[26],c2[25],50),_mm512_xor_si512(_mm512_alignr_epi8(c2[26],c2[25],51),_mm512_xor_si512(_mm512_alignr_epi8(c2[37],c2[36],52),_mm512_xor_si512(_mm512_alignr_epi8(c2[39],c2[38],28),_mm512_xor_si512(_mm512_alignr_epi8(c2[39],c2[38],12),_mm512_xor_si512(_mm512_alignr_epi8(c2[40],c2[39],52),_mm512_xor_si512(_mm512_alignr_epi8(c2[38],c2[37],3),_mm512_xor_si512(_mm512_alignr_epi8(c2[39],c2[38],42),_mm512_xor_si512(_mm512_alignr_epi8(c2[39],c2[38],43),_mm512_xor_si512(_mm512_alignr_epi8(c2[39],c2[38],37),_mm512_xor_si512(_mm512_alignr_epi8(c2[54],c2[53],35),_mm512_xor_si512(_mm512_alignr_epi8(c2[50],c2[49],11),_mm512_xor_si512(_mm512_alignr_epi8(c2[49],c2[48],15),_mm512_xor_si512(_mm512_alignr_epi8(c2[50],c2[49],54),_mm512_xor_si512(_mm512_alignr_epi8(c2[50],c2[49],55),_mm512_xor_si512(_mm512_alignr_epi8(c2[54],c2[53],22),_mm512_xor_si512(_mm512_alignr_epi8(c2[49],c2[48],61),_mm512_xor_si512(_mm512_alignr_epi8(c2[49],c2[48],62),_mm512_xor_si512(_mm512_alignr_epi8(c2[64],c2[63],56),_mm512_xor_si512(_mm512_alignr_epi8(c2[66],c2[65],32),_mm512_xor_si512(_mm512_alignr_epi8(c2[64],c2[63],19),_mm512_xor_si512(_mm512_alignr_epi8(c2[65],c2[64],59),_mm512_xor_si512(_mm512_alignr_epi8(c2[66],c2[65],3),_mm512_xor_si512(_mm512_alignr_epi8(c2[61],c2[60],42),_mm512_xor_si512(_mm512_alignr_epi8(c2[61],c2[60],43),_mm512_xor_si512(_mm512_alignr_epi8(c2[77],c2[76],27),_mm512_xor_si512(_mm512_alignr_epi8(c2[73],c2[72],3),_mm512_xor_si512(_mm512_alignr_epi8(c2[76],c2[75],36),_mm512_xor_si512(_mm512_alignr_epi8(c2[78],c2[77],11),_mm512_xor_si512(_mm512_alignr_epi8(c2[78],c2[77],12),_mm512_xor_si512(_mm512_alignr_epi8(c2[77],c2[76],10),_mm512_xor_si512(_mm512_alignr_epi8(c2[78],c2[77],49),_mm512_xor_si512(_mm512_alignr_epi8(c2[78],c2[77],50),_mm512_xor_si512(_mm512_alignr_epi8(c2[85],c2[84],14),_mm512_xor_si512(_mm512_alignr_epi8(c2[86],c2[85],54),_mm512_xor_si512(_mm512_alignr_epi8(c2[90],c2[89],14),_mm512_xor_si512(_mm512_alignr_epi8(c2[85],c2[84],53),_mm512_xor_si512(_mm512_alignr_epi8(c2[85],c2[84],54),_mm512_xor_si512(_mm512_alignr_epi8(c2[88],c2[87],28),_mm512_xor_si512(_mm512_alignr_epi8(c2[90],c2[89],3),_mm512_xor_si512(_mm512_alignr_epi8(c2[90],c2[89],4),_mm512_xor_si512(_mm512_alignr_epi8(c2[97],c2[96],14),_mm512_xor_si512(_mm512_alignr_epi8(c2[98],c2[97],54),_mm512_xor_si512(_mm512_alignr_epi8(c2[100],c2[99],35),_mm512_xor_si512(_mm512_alignr_epi8(c2[102],c2[101],10),_mm512_xor_si512(_mm512_alignr_epi8(c2[102],c2[101],11),_mm512_xor_si512(_mm512_alignr_epi8(c2[98],c2[97],59),_mm512_xor_si512(_mm512_alignr_epi8(c2[100],c2[99],34),_mm512_xor_si512(_mm512_alignr_epi8(c2[100],c2[99],35),_mm512_xor_si512(c2[108],_mm512_xor_si512(_mm512_alignr_epi8(c2[110],c2[109],40),_mm512_xor_si512(_mm512_alignr_epi8(c2[112],c2[111],53),_mm512_xor_si512(_mm512_alignr_epi8(c2[114],c2[113],29),_mm512_xor_si512(_mm512_alignr_epi8(c2[111],c2[110],2),_mm512_xor_si512(_mm512_alignr_epi8(c2[112],c2[111],41),_mm512_xor_si512(_mm512_alignr_epi8(c2[112],c2[111],42),_mm512_xor_si512(_mm512_alignr_epi8(c2[126],c2[125],35),_mm512_xor_si512(_mm512_alignr_epi8(c2[122],c2[121],11),_mm512_xor_si512(_mm512_alignr_epi8(c2[124],c2[123],4),_mm512_xor_si512(_mm512_alignr_epi8(c2[125],c2[124],43),_mm512_xor_si512(_mm512_alignr_epi8(c2[125],c2[124],44),_mm512_xor_si512(_mm512_alignr_epi8(c2[124],c2[123],7),_mm512_xor_si512(_mm512_alignr_epi8(c2[125],c2[124],46),_mm512_xor_si512(_mm512_alignr_epi8(c2[125],c2[124],47),_mm512_xor_si512(_mm512_alignr_epi8(c2[135],c2[134],48),_mm512_xor_si512(_mm512_alignr_epi8(c2[137],c2[136],24),_mm512_xor_si512(_mm512_alignr_epi8(c2[138],c2[137],42),_mm512_xor_si512(_mm512_alignr_epi8(c2[134],c2[133],18),_mm512_xor_si512(_mm512_alignr_epi8(c2[138],c2[137],52),_mm512_xor_si512(_mm512_alignr_epi8(c2[134],c2[133],27),_mm512_xor_si512(_mm512_alignr_epi8(c2[134],c2[133],28),_mm512_xor_si512(_mm512_alignr_epi8(c2[146],c2[145],20),_mm512_xor_si512(_mm512_alignr_epi8(c2[147],c2[146],60),_mm512_xor_si512(_mm512_alignr_epi8(c2[145],c2[144],25),_mm512_xor_si512(_mm512_alignr_epi8(c2[147],c2[146],1),_mm512_xor_si512(_mm512_alignr_epi8(c2[149],c2[148],42),_mm512_xor_si512(_mm512_alignr_epi8(c2[145],c2[144],17),_mm512_xor_si512(_mm512_alignr_epi8(c2[145],c2[144],18),_mm512_xor_si512(_mm512_alignr_epi8(c2[145],c2[144],18),_mm512_xor_si512(_mm512_alignr_epi8(c2[157],c2[156],40),_mm512_xor_si512(_mm512_alignr_epi8(c2[159],c2[158],16),_mm512_xor_si512(_mm512_alignr_epi8(c2[161],c2[160],11),_mm512_xor_si512(_mm512_alignr_epi8(c2[162],c2[161],50),_mm512_xor_si512(_mm512_alignr_epi8(c2[162],c2[161],51),_mm512_xor_si512(_mm512_alignr_epi8(c2[157],c2[156],24),_mm512_xor_si512(_mm512_alignr_epi8(c2[158],c2[157],63),_mm512_xor_si512(c2[158],_mm512_xor_si512(_mm512_alignr_epi8(c2[173],c2[172],28),_mm512_xor_si512(_mm512_alignr_epi8(c2[169],c2[168],4),_mm512_xor_si512(_mm512_alignr_epi8(c2[171],c2[170],27),_mm512_xor_si512(_mm512_alignr_epi8(c2[173],c2[172],2),_mm512_xor_si512(_mm512_alignr_epi8(c2[173],c2[172],3),_mm512_xor_si512(_mm512_alignr_epi8(c2[173],c2[172],23),_mm512_xor_si512(_mm512_alignr_epi8(c2[174],c2[173],62),_mm512_xor_si512(_mm512_alignr_epi8(c2[174],c2[173],63),_mm512_xor_si512(_mm512_alignr_epi8(c2[185],c2[184],26),_mm512_xor_si512(_mm512_alignr_epi8(c2[181],c2[180],2),_mm512_xor_si512(_mm512_alignr_epi8(c2[183],c2[182],38),_mm512_xor_si512(_mm512_alignr_epi8(c2[185],c2[184],14),_mm512_xor_si512(_mm512_alignr_epi8(c2[182],c2[181],56),_mm512_xor_si512(_mm512_alignr_epi8(c2[184],c2[183],31),_mm512_xor_si512(_mm512_alignr_epi8(c2[184],c2[183],32),_mm512_xor_si512(_mm512_alignr_epi8(c2[195],c2[194],45),_mm512_xor_si512(_mm512_alignr_epi8(c2[197],c2[196],21),_mm512_xor_si512(_mm512_alignr_epi8(c2[193],c2[192],37),_mm512_xor_si512(_mm512_alignr_epi8(c2[195],c2[194],13),_mm512_xor_si512(_mm512_alignr_epi8(c2[198],c2[197],51),_mm512_xor_si512(_mm512_alignr_epi8(c2[194],c2[193],26),_mm512_xor_si512(_mm512_alignr_epi8(c2[194],c2[193],27),_mm512_xor_si512(_mm512_alignr_epi8(c2[193],c2[192],39),_mm512_xor_si512(_mm512_alignr_epi8(c2[207],c2[206],53),_mm512_xor_si512(_mm512_alignr_epi8(c2[209],c2[208],29),_mm512_xor_si512(_mm512_alignr_epi8(c2[208],c2[207],6),_mm512_xor_si512(_mm512_alignr_epi8(c2[209],c2[208],45),_mm512_xor_si512(_mm512_alignr_epi8(c2[209],c2[208],46),_mm512_xor_si512(_mm512_alignr_epi8(c2[210],c2[209],47),_mm512_xor_si512(_mm512_alignr_epi8(c2[206],c2[205],22),_mm512_xor_si512(_mm512_alignr_epi8(c2[206],c2[205],23),_mm512_xor_si512(_mm512_alignr_epi8(c2[221],c2[220],53),_mm512_xor_si512(_mm512_alignr_epi8(c2[217],c2[216],29),_mm512_xor_si512(_mm512_alignr_epi8(c2[221],c2[220],51),_mm512_xor_si512(_mm512_alignr_epi8(c2[217],c2[216],26),_mm512_xor_si512(_mm512_alignr_epi8(c2[217],c2[216],27),_mm512_xor_si512(_mm512_alignr_epi8(c2[222],c2[221],18),_mm512_xor_si512(_mm512_alignr_epi8(c2[217],c2[216],57),_mm512_xor_si512(_mm512_alignr_epi8(c2[217],c2[216],58),_mm512_xor_si512(_mm512_alignr_epi8(c2[232],c2[231],55),_mm512_xor_si512(_mm512_alignr_epi8(c2[234],c2[233],31),_mm512_xor_si512(_mm512_alignr_epi8(c2[229],c2[228],14),_mm512_xor_si512(_mm512_alignr_epi8(c2[230],c2[229],54),_mm512_xor_si512(_mm512_alignr_epi8(c2[233],c2[232],16),_mm512_xor_si512(_mm512_alignr_epi8(c2[234],c2[233],55),_mm512_xor_si512(_mm512_alignr_epi8(c2[234],c2[233],56),_mm512_xor_si512(_mm512_alignr_epi8(c2[232],c2[231],32),_mm512_xor_si512(_mm512_alignr_epi8(c2[241],c2[240],13),_mm512_xor_si512(_mm512_alignr_epi8(c2[242],c2[241],53),_mm512_xor_si512(_mm512_alignr_epi8(c2[242],c2[241],16),_mm512_xor_si512(_mm512_alignr_epi8(c2[243],c2[242],55),_mm512_xor_si512(_mm512_alignr_epi8(c2[243],c2[242],56),_mm512_xor_si512(_mm512_alignr_epi8(c2[242],c2[241],42),_mm512_xor_si512(_mm512_alignr_epi8(c2[244],c2[243],17),_mm512_xor_si512(_mm512_alignr_epi8(c2[244],c2[243],18),_mm512_xor_si512(_mm512_alignr_epi8(c2[253],c2[252],29),_mm512_xor_si512(_mm512_alignr_epi8(c2[255],c2[254],5),_mm512_xor_si512(_mm512_alignr_epi8(c2[255],c2[254],51),_mm512_xor_si512(_mm512_alignr_epi8(c2[257],c2[256],27),_mm512_xor_si512(_mm512_alignr_epi8(c2[253],c2[252],40),_mm512_xor_si512(_mm512_alignr_epi8(c2[255],c2[254],15),_mm512_xor_si512(_mm512_alignr_epi8(c2[255],c2[254],16),_mm512_alignr_epi8(c2[258],c2[257],48))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 9 + d2[54]=_mm512_xor_si512(_mm512_alignr_epi8(c2[6],c2[5],46),_mm512_xor_si512(_mm512_alignr_epi8(c2[16],c2[15],40),_mm512_xor_si512(_mm512_alignr_epi8(c2[126],c2[125],1),_mm512_xor_si512(_mm512_alignr_epi8(c2[135],c2[134],5),_mm512_xor_si512(_mm512_alignr_epi8(c2[157],c2[156],57),_mm512_xor_si512(_mm512_alignr_epi8(c2[209],c2[208],47),_mm512_xor_si512(_mm512_alignr_epi8(c2[217],c2[216],63),_mm512_alignr_epi8(c2[242],c2[241],18)))))))); + +//row: 10 + d2[60]=_mm512_xor_si512(_mm512_alignr_epi8(c2[14],c2[13],37),_mm512_xor_si512(_mm512_alignr_epi8(c2[30],c2[29],19),_mm512_xor_si512(_mm512_alignr_epi8(c2[53],c2[52],18),_mm512_xor_si512(_mm512_alignr_epi8(c2[86],c2[85],47),_mm512_xor_si512(_mm512_alignr_epi8(c2[102],c2[101],63),_mm512_alignr_epi8(c2[174],c2[173],34)))))); + +//row: 11 + d2[66]=_mm512_xor_si512(_mm512_alignr_epi8(c2[5],c2[4],1),_mm512_xor_si512(_mm512_alignr_epi8(c2[1],c2[0],38),_mm512_xor_si512(_mm512_alignr_epi8(c2[1],c2[0],39),_mm512_xor_si512(_mm512_alignr_epi8(c2[1],c2[0],26),_mm512_xor_si512(c2[3],_mm512_xor_si512(_mm512_alignr_epi8(c2[3],c2[2],27),_mm512_xor_si512(_mm512_alignr_epi8(c2[6],c2[5],1),_mm512_xor_si512(_mm512_alignr_epi8(c2[4],c2[3],34),_mm512_xor_si512(_mm512_alignr_epi8(c2[1],c2[0],8),_mm512_xor_si512(_mm512_alignr_epi8(c2[1],c2[0],48),_mm512_xor_si512(_mm512_alignr_epi8(c2[18],c2[17],33),_mm512_xor_si512(_mm512_alignr_epi8(c2[15],c2[14],6),_mm512_xor_si512(_mm512_alignr_epi8(c2[15],c2[14],7),_mm512_xor_si512(_mm512_alignr_epi8(c2[16],c2[15],8),_mm512_xor_si512(_mm512_alignr_epi8(c2[18],c2[17],46),_mm512_xor_si512(_mm512_alignr_epi8(c2[13],c2[12],37),_mm512_xor_si512(_mm512_alignr_epi8(c2[16],c2[15],11),_mm512_xor_si512(_mm512_alignr_epi8(c2[14],c2[13],38),_mm512_xor_si512(c2[24],_mm512_xor_si512(_mm512_alignr_epi8(c2[27],c2[26],37),_mm512_xor_si512(_mm512_alignr_epi8(c2[27],c2[26],38),_mm512_xor_si512(_mm512_alignr_epi8(c2[25],c2[24],26),_mm512_xor_si512(c2[27],_mm512_xor_si512(_mm512_alignr_epi8(c2[29],c2[28],22),_mm512_xor_si512(_mm512_alignr_epi8(c2[25],c2[24],60),_mm512_xor_si512(_mm512_alignr_epi8(c2[41],c2[40],63),_mm512_xor_si512(_mm512_alignr_epi8(c2[38],c2[37],36),_mm512_xor_si512(_mm512_alignr_epi8(c2[38],c2[37],37),_mm512_xor_si512(_mm512_alignr_epi8(c2[37],c2[36],23),_mm512_xor_si512(_mm512_alignr_epi8(c2[39],c2[38],61),_mm512_xor_si512(_mm512_alignr_epi8(c2[42],c2[41],14),_mm512_xor_si512(_mm512_alignr_epi8(c2[38],c2[37],52),_mm512_xor_si512(_mm512_alignr_epi8(c2[52],c2[51],46),_mm512_xor_si512(_mm512_alignr_epi8(c2[49],c2[48],20),_mm512_xor_si512(_mm512_alignr_epi8(c2[53],c2[52],26),_mm512_xor_si512(c2[49],_mm512_xor_si512(_mm512_alignr_epi8(c2[52],c2[51],33),_mm512_xor_si512(_mm512_alignr_epi8(c2[49],c2[48],7),_mm512_xor_si512(_mm512_alignr_epi8(c2[63],c2[62],3),_mm512_xor_si512(_mm512_alignr_epi8(c2[65],c2[64],40),_mm512_xor_si512(_mm512_alignr_epi8(c2[65],c2[64],41),_mm512_xor_si512(_mm512_alignr_epi8(c2[62],c2[61],30),_mm512_xor_si512(_mm512_alignr_epi8(c2[65],c2[64],4),_mm512_xor_si512(_mm512_alignr_epi8(c2[64],c2[63],14),_mm512_xor_si512(_mm512_alignr_epi8(c2[66],c2[65],52),_mm512_xor_si512(_mm512_alignr_epi8(c2[75],c2[74],38),_mm512_xor_si512(_mm512_alignr_epi8(c2[78],c2[77],11),_mm512_xor_si512(_mm512_alignr_epi8(c2[78],c2[77],12),_mm512_xor_si512(_mm512_alignr_epi8(c2[74],c2[73],47),_mm512_xor_si512(_mm512_alignr_epi8(c2[77],c2[76],21),_mm512_xor_si512(_mm512_alignr_epi8(c2[75],c2[74],21),_mm512_xor_si512(_mm512_alignr_epi8(c2[77],c2[76],59),_mm512_xor_si512(_mm512_alignr_epi8(c2[89],c2[88],25),_mm512_xor_si512(_mm512_alignr_epi8(c2[85],c2[84],63),_mm512_xor_si512(_mm512_alignr_epi8(c2[88],c2[87],25),_mm512_xor_si512(_mm512_alignr_epi8(c2[90],c2[89],63),_mm512_xor_si512(_mm512_alignr_epi8(c2[86],c2[85],39),_mm512_xor_si512(_mm512_alignr_epi8(c2[89],c2[88],13),_mm512_xor_si512(_mm512_alignr_epi8(c2[101],c2[100],25),_mm512_xor_si512(_mm512_alignr_epi8(c2[97],c2[96],63),_mm512_xor_si512(_mm512_alignr_epi8(c2[98],c2[97],46),_mm512_xor_si512(_mm512_alignr_epi8(c2[101],c2[100],20),_mm512_xor_si512(_mm512_alignr_epi8(c2[97],c2[96],6),_mm512_xor_si512(_mm512_alignr_epi8(c2[99],c2[98],44),_mm512_xor_si512(_mm512_alignr_epi8(c2[113],c2[112],11),_mm512_xor_si512(_mm512_alignr_epi8(c2[109],c2[108],48),_mm512_xor_si512(_mm512_alignr_epi8(c2[109],c2[108],49),_mm512_xor_si512(c2[110],_mm512_xor_si512(_mm512_alignr_epi8(c2[113],c2[112],38),_mm512_xor_si512(_mm512_alignr_epi8(c2[109],c2[108],13),_mm512_xor_si512(_mm512_alignr_epi8(c2[111],c2[110],51),_mm512_xor_si512(_mm512_alignr_epi8(c2[124],c2[123],46),_mm512_xor_si512(_mm512_alignr_epi8(c2[121],c2[120],19),_mm512_xor_si512(_mm512_alignr_epi8(c2[121],c2[120],20),_mm512_xor_si512(_mm512_alignr_epi8(c2[122],c2[121],15),_mm512_xor_si512(_mm512_alignr_epi8(c2[124],c2[123],53),_mm512_xor_si512(_mm512_alignr_epi8(c2[122],c2[121],18),_mm512_xor_si512(_mm512_alignr_epi8(c2[124],c2[123],56),_mm512_xor_si512(_mm512_alignr_epi8(c2[133],c2[132],59),_mm512_xor_si512(_mm512_alignr_epi8(c2[136],c2[135],32),_mm512_xor_si512(_mm512_alignr_epi8(c2[136],c2[135],33),_mm512_xor_si512(_mm512_alignr_epi8(c2[136],c2[135],53),_mm512_xor_si512(_mm512_alignr_epi8(c2[133],c2[132],27),_mm512_xor_si512(_mm512_alignr_epi8(c2[136],c2[135],63),_mm512_xor_si512(_mm512_alignr_epi8(c2[133],c2[132],37),_mm512_xor_si512(_mm512_alignr_epi8(c2[150],c2[149],31),_mm512_xor_si512(_mm512_alignr_epi8(c2[147],c2[146],4),_mm512_xor_si512(_mm512_alignr_epi8(c2[147],c2[146],5),_mm512_xor_si512(_mm512_alignr_epi8(c2[149],c2[148],36),_mm512_xor_si512(_mm512_alignr_epi8(c2[146],c2[145],10),_mm512_xor_si512(_mm512_alignr_epi8(c2[147],c2[146],53),_mm512_xor_si512(_mm512_alignr_epi8(c2[150],c2[149],27),_mm512_xor_si512(_mm512_alignr_epi8(c2[145],c2[144],8),_mm512_xor_si512(_mm512_alignr_epi8(c2[161],c2[160],51),_mm512_xor_si512(_mm512_alignr_epi8(c2[158],c2[157],24),_mm512_xor_si512(_mm512_alignr_epi8(c2[158],c2[157],25),_mm512_xor_si512(_mm512_alignr_epi8(c2[159],c2[158],22),_mm512_xor_si512(_mm512_alignr_epi8(c2[161],c2[160],60),_mm512_xor_si512(_mm512_alignr_epi8(c2[161],c2[160],35),_mm512_xor_si512(_mm512_alignr_epi8(c2[158],c2[157],9),_mm512_xor_si512(_mm512_alignr_epi8(c2[171],c2[170],39),_mm512_xor_si512(_mm512_alignr_epi8(c2[174],c2[173],13),_mm512_xor_si512(_mm512_alignr_epi8(c2[169],c2[168],38),_mm512_xor_si512(_mm512_alignr_epi8(c2[172],c2[171],12),_mm512_xor_si512(_mm512_alignr_epi8(c2[171],c2[170],34),_mm512_xor_si512(_mm512_alignr_epi8(c2[174],c2[173],8),_mm512_xor_si512(_mm512_alignr_epi8(c2[183],c2[182],37),_mm512_xor_si512(_mm512_alignr_epi8(c2[186],c2[185],10),_mm512_xor_si512(_mm512_alignr_epi8(c2[186],c2[185],11),_mm512_xor_si512(_mm512_alignr_epi8(c2[181],c2[180],49),_mm512_xor_si512(_mm512_alignr_epi8(c2[184],c2[183],23),_mm512_xor_si512(_mm512_alignr_epi8(c2[181],c2[180],3),_mm512_xor_si512(_mm512_alignr_epi8(c2[183],c2[182],41),_mm512_xor_si512(_mm512_alignr_epi8(c2[193],c2[192],56),_mm512_xor_si512(_mm512_alignr_epi8(c2[196],c2[195],29),_mm512_xor_si512(_mm512_alignr_epi8(c2[196],c2[195],30),_mm512_xor_si512(_mm512_alignr_epi8(c2[197],c2[196],48),_mm512_xor_si512(_mm512_alignr_epi8(c2[194],c2[193],22),_mm512_xor_si512(_mm512_alignr_epi8(c2[196],c2[195],62),_mm512_xor_si512(_mm512_alignr_epi8(c2[193],c2[192],36),_mm512_xor_si512(_mm512_alignr_epi8(c2[193],c2[192],47),_mm512_xor_si512(c2[205],_mm512_xor_si512(_mm512_alignr_epi8(c2[208],c2[207],38),_mm512_xor_si512(_mm512_alignr_epi8(c2[206],c2[205],17),_mm512_xor_si512(_mm512_alignr_epi8(c2[208],c2[207],55),_mm512_xor_si512(_mm512_alignr_epi8(c2[208],c2[207],58),_mm512_xor_si512(_mm512_alignr_epi8(c2[205],c2[204],32),_mm512_xor_si512(c2[219],_mm512_xor_si512(_mm512_alignr_epi8(c2[222],c2[221],37),_mm512_xor_si512(_mm512_alignr_epi8(c2[222],c2[221],38),_mm512_xor_si512(_mm512_alignr_epi8(c2[219],c2[218],62),_mm512_xor_si512(_mm512_alignr_epi8(c2[222],c2[221],36),_mm512_xor_si512(_mm512_alignr_epi8(c2[220],c2[219],29),_mm512_xor_si512(_mm512_alignr_epi8(c2[217],c2[216],3),_mm512_xor_si512(_mm512_alignr_epi8(c2[231],c2[230],2),_mm512_xor_si512(_mm512_alignr_epi8(c2[233],c2[232],39),_mm512_xor_si512(_mm512_alignr_epi8(c2[233],c2[232],40),_mm512_xor_si512(_mm512_alignr_epi8(c2[233],c2[232],25),_mm512_xor_si512(_mm512_alignr_epi8(c2[229],c2[228],63),_mm512_xor_si512(_mm512_alignr_epi8(c2[231],c2[230],27),_mm512_xor_si512(_mm512_alignr_epi8(c2[234],c2[233],1),_mm512_xor_si512(_mm512_alignr_epi8(c2[245],c2[244],24),_mm512_xor_si512(_mm512_alignr_epi8(c2[241],c2[240],61),_mm512_xor_si512(_mm512_alignr_epi8(c2[241],c2[240],62),_mm512_xor_si512(_mm512_alignr_epi8(c2[246],c2[245],27),_mm512_xor_si512(_mm512_alignr_epi8(c2[243],c2[242],1),_mm512_xor_si512(_mm512_alignr_epi8(c2[246],c2[245],53),_mm512_xor_si512(_mm512_alignr_epi8(c2[243],c2[242],27),_mm512_xor_si512(_mm512_alignr_epi8(c2[257],c2[256],40),_mm512_xor_si512(_mm512_alignr_epi8(c2[254],c2[253],13),_mm512_xor_si512(_mm512_alignr_epi8(c2[254],c2[253],14),_mm512_xor_si512(_mm512_alignr_epi8(c2[253],c2[252],62),_mm512_xor_si512(_mm512_alignr_epi8(c2[256],c2[255],36),_mm512_xor_si512(_mm512_alignr_epi8(c2[257],c2[256],51),_mm512_xor_si512(_mm512_alignr_epi8(c2[254],c2[253],25),_mm512_alignr_epi8(c2[255],c2[254],60)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 12 + d2[72]=_mm512_xor_si512(_mm512_alignr_epi8(c2[2],c2[1],13),_mm512_xor_si512(_mm512_alignr_epi8(c2[15],c2[14],58),_mm512_xor_si512(_mm512_alignr_epi8(c2[123],c2[122],46),_mm512_xor_si512(_mm512_alignr_epi8(c2[136],c2[135],40),_mm512_xor_si512(_mm512_alignr_epi8(c2[157],c2[156],50),_mm512_alignr_epi8(c2[218],c2[217],10)))))); + +//row: 13 + d2[78]=_mm512_xor_si512(_mm512_alignr_epi8(c2[5],c2[4],37),_mm512_xor_si512(_mm512_alignr_epi8(c2[5],c2[4],38),_mm512_xor_si512(_mm512_alignr_epi8(c2[1],c2[0],63),_mm512_xor_si512(c2[3],_mm512_xor_si512(_mm512_alignr_epi8(c2[5],c2[4],7),_mm512_xor_si512(_mm512_alignr_epi8(c2[5],c2[4],57),_mm512_xor_si512(_mm512_alignr_epi8(c2[13],c2[12],5),_mm512_xor_si512(_mm512_alignr_epi8(c2[13],c2[12],6),_mm512_xor_si512(_mm512_alignr_epi8(c2[16],c2[15],45),_mm512_xor_si512(_mm512_alignr_epi8(c2[14],c2[13],10),_mm512_xor_si512(_mm512_alignr_epi8(c2[25],c2[24],36),_mm512_xor_si512(_mm512_alignr_epi8(c2[25],c2[24],37),_mm512_xor_si512(_mm512_alignr_epi8(c2[25],c2[24],63),_mm512_xor_si512(_mm512_alignr_epi8(c2[29],c2[28],59),_mm512_xor_si512(_mm512_alignr_epi8(c2[42],c2[41],35),_mm512_xor_si512(_mm512_alignr_epi8(c2[42],c2[41],36),_mm512_xor_si512(_mm512_alignr_epi8(c2[37],c2[36],60),_mm512_xor_si512(_mm512_alignr_epi8(c2[42],c2[41],51),_mm512_xor_si512(_mm512_alignr_epi8(c2[39],c2[38],49),_mm512_xor_si512(_mm512_alignr_epi8(c2[53],c2[52],19),_mm512_xor_si512(_mm512_alignr_epi8(c2[53],c2[52],63),_mm512_xor_si512(_mm512_alignr_epi8(c2[53],c2[52],6),_mm512_xor_si512(_mm512_alignr_epi8(c2[63],c2[62],39),_mm512_xor_si512(_mm512_alignr_epi8(c2[63],c2[62],40),_mm512_xor_si512(_mm512_alignr_epi8(c2[63],c2[62],3),_mm512_xor_si512(_mm512_alignr_epi8(c2[64],c2[63],51),_mm512_xor_si512(_mm512_alignr_epi8(c2[76],c2[75],10),_mm512_xor_si512(_mm512_alignr_epi8(c2[76],c2[75],11),_mm512_xor_si512(_mm512_alignr_epi8(c2[75],c2[74],20),_mm512_xor_si512(_mm512_alignr_epi8(c2[75],c2[74],58),_mm512_xor_si512(_mm512_alignr_epi8(c2[89],c2[88],62),_mm512_xor_si512(_mm512_alignr_epi8(c2[88],c2[87],62),_mm512_xor_si512(_mm512_alignr_epi8(c2[87],c2[86],12),_mm512_xor_si512(_mm512_alignr_epi8(c2[89],c2[88],10),_mm512_xor_si512(_mm512_alignr_epi8(c2[101],c2[100],62),_mm512_xor_si512(_mm512_alignr_epi8(c2[99],c2[98],19),_mm512_xor_si512(_mm512_alignr_epi8(c2[97],c2[96],43),_mm512_xor_si512(_mm512_alignr_epi8(c2[113],c2[112],47),_mm512_xor_si512(_mm512_alignr_epi8(c2[113],c2[112],48),_mm512_xor_si512(_mm512_alignr_epi8(c2[111],c2[110],37),_mm512_xor_si512(_mm512_alignr_epi8(c2[109],c2[108],50),_mm512_xor_si512(_mm512_alignr_epi8(c2[125],c2[124],18),_mm512_xor_si512(_mm512_alignr_epi8(c2[125],c2[124],19),_mm512_xor_si512(_mm512_alignr_epi8(c2[122],c2[121],52),_mm512_xor_si512(_mm512_alignr_epi8(c2[122],c2[121],55),_mm512_xor_si512(_mm512_alignr_epi8(c2[134],c2[133],31),_mm512_xor_si512(_mm512_alignr_epi8(c2[134],c2[133],32),_mm512_xor_si512(_mm512_alignr_epi8(c2[137],c2[136],26),_mm512_xor_si512(_mm512_alignr_epi8(c2[137],c2[136],36),_mm512_xor_si512(_mm512_alignr_epi8(c2[145],c2[144],3),_mm512_xor_si512(_mm512_alignr_epi8(c2[145],c2[144],4),_mm512_xor_si512(_mm512_alignr_epi8(c2[150],c2[149],9),_mm512_xor_si512(_mm512_alignr_epi8(c2[148],c2[147],26),_mm512_xor_si512(_mm512_alignr_epi8(c2[162],c2[161],23),_mm512_xor_si512(_mm512_alignr_epi8(c2[162],c2[161],24),_mm512_xor_si512(_mm512_alignr_epi8(c2[159],c2[158],59),_mm512_xor_si512(_mm512_alignr_epi8(c2[162],c2[161],8),_mm512_xor_si512(_mm512_alignr_epi8(c2[172],c2[171],12),_mm512_xor_si512(_mm512_alignr_epi8(c2[170],c2[169],11),_mm512_xor_si512(_mm512_alignr_epi8(c2[172],c2[171],7),_mm512_xor_si512(_mm512_alignr_epi8(c2[184],c2[183],9),_mm512_xor_si512(_mm512_alignr_epi8(c2[184],c2[183],10),_mm512_xor_si512(_mm512_alignr_epi8(c2[182],c2[181],22),_mm512_xor_si512(_mm512_alignr_epi8(c2[181],c2[180],40),_mm512_xor_si512(_mm512_alignr_epi8(c2[194],c2[193],28),_mm512_xor_si512(_mm512_alignr_epi8(c2[194],c2[193],29),_mm512_xor_si512(_mm512_alignr_epi8(c2[198],c2[197],21),_mm512_xor_si512(_mm512_alignr_epi8(c2[197],c2[196],35),_mm512_xor_si512(_mm512_alignr_epi8(c2[206],c2[205],37),_mm512_xor_si512(_mm512_alignr_epi8(c2[206],c2[205],54),_mm512_xor_si512(_mm512_alignr_epi8(c2[209],c2[208],31),_mm512_xor_si512(_mm512_alignr_epi8(c2[220],c2[219],36),_mm512_xor_si512(_mm512_alignr_epi8(c2[220],c2[219],37),_mm512_xor_si512(_mm512_alignr_epi8(c2[220],c2[219],35),_mm512_xor_si512(_mm512_alignr_epi8(c2[221],c2[220],2),_mm512_xor_si512(_mm512_alignr_epi8(c2[231],c2[230],38),_mm512_xor_si512(_mm512_alignr_epi8(c2[231],c2[230],39),_mm512_xor_si512(_mm512_alignr_epi8(c2[233],c2[232],62),_mm512_xor_si512(c2[231],_mm512_xor_si512(_mm512_alignr_epi8(c2[245],c2[244],60),_mm512_xor_si512(_mm512_alignr_epi8(c2[245],c2[244],61),_mm512_xor_si512(c2[240],_mm512_xor_si512(_mm512_alignr_epi8(c2[241],c2[240],26),_mm512_xor_si512(_mm512_alignr_epi8(c2[242],c2[241],51),_mm512_xor_si512(_mm512_alignr_epi8(c2[258],c2[257],12),_mm512_xor_si512(_mm512_alignr_epi8(c2[258],c2[257],13),_mm512_xor_si512(_mm512_alignr_epi8(c2[254],c2[253],35),_mm512_alignr_epi8(c2[258],c2[257],24)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 14 + d2[84]=_mm512_xor_si512(_mm512_alignr_epi8(c2[3],c2[2],14),_mm512_xor_si512(_mm512_alignr_epi8(c2[148],c2[147],56),_mm512_xor_si512(_mm512_alignr_epi8(c2[183],c2[182],9),_mm512_xor_si512(_mm512_alignr_epi8(c2[194],c2[193],25),_mm512_xor_si512(_mm512_alignr_epi8(c2[210],c2[209],27),_mm512_alignr_epi8(c2[253],c2[252],12)))))); + +//row: 15 + d2[90]=_mm512_xor_si512(_mm512_alignr_epi8(c2[4],c2[3],1),_mm512_xor_si512(_mm512_alignr_epi8(c2[6],c2[5],26),_mm512_xor_si512(_mm512_alignr_epi8(c2[2],c2[1],27),_mm512_xor_si512(_mm512_alignr_epi8(c2[3],c2[2],33),_mm512_xor_si512(_mm512_alignr_epi8(c2[3],c2[2],34),_mm512_xor_si512(_mm512_alignr_epi8(c2[4],c2[3],49),_mm512_xor_si512(_mm512_alignr_epi8(c2[17],c2[16],33),_mm512_xor_si512(_mm512_alignr_epi8(c2[15],c2[14],8),_mm512_xor_si512(_mm512_alignr_epi8(c2[18],c2[17],36),_mm512_xor_si512(_mm512_alignr_epi8(c2[18],c2[17],37),_mm512_xor_si512(_mm512_alignr_epi8(c2[13],c2[12],2),_mm512_xor_si512(c2[29],_mm512_xor_si512(_mm512_alignr_epi8(c2[30],c2[29],26),_mm512_xor_si512(_mm512_alignr_epi8(c2[28],c2[27],22),_mm512_xor_si512(_mm512_alignr_epi8(c2[40],c2[39],63),_mm512_xor_si512(_mm512_alignr_epi8(c2[42],c2[41],23),_mm512_xor_si512(_mm512_alignr_epi8(c2[41],c2[40],13),_mm512_xor_si512(_mm512_alignr_epi8(c2[41],c2[40],14),_mm512_xor_si512(_mm512_alignr_epi8(c2[51],c2[50],46),_mm512_xor_si512(_mm512_alignr_epi8(c2[52],c2[51],26),_mm512_xor_si512(_mm512_alignr_epi8(c2[51],c2[50],32),_mm512_xor_si512(_mm512_alignr_epi8(c2[51],c2[50],33),_mm512_xor_si512(_mm512_alignr_epi8(c2[62],c2[61],3),_mm512_xor_si512(_mm512_alignr_epi8(c2[61],c2[60],30),_mm512_xor_si512(_mm512_alignr_epi8(c2[63],c2[62],14),_mm512_xor_si512(_mm512_alignr_epi8(c2[74],c2[73],38),_mm512_xor_si512(_mm512_alignr_epi8(c2[73],c2[72],47),_mm512_xor_si512(_mm512_alignr_epi8(c2[74],c2[73],20),_mm512_xor_si512(_mm512_alignr_epi8(c2[74],c2[73],21),_mm512_xor_si512(_mm512_alignr_epi8(c2[88],c2[87],25),_mm512_xor_si512(_mm512_alignr_epi8(c2[87],c2[86],25),_mm512_xor_si512(_mm512_alignr_epi8(c2[85],c2[84],38),_mm512_xor_si512(_mm512_alignr_epi8(c2[85],c2[84],39),_mm512_xor_si512(_mm512_alignr_epi8(c2[100],c2[99],25),_mm512_xor_si512(_mm512_alignr_epi8(c2[97],c2[96],46),_mm512_xor_si512(_mm512_alignr_epi8(c2[102],c2[101],5),_mm512_xor_si512(_mm512_alignr_epi8(c2[102],c2[101],6),_mm512_xor_si512(_mm512_alignr_epi8(c2[112],c2[111],11),_mm512_xor_si512(c2[109],_mm512_xor_si512(_mm512_alignr_epi8(c2[114],c2[113],13),_mm512_xor_si512(_mm512_alignr_epi8(c2[123],c2[122],46),_mm512_xor_si512(_mm512_alignr_epi8(c2[121],c2[120],15),_mm512_xor_si512(_mm512_alignr_epi8(c2[121],c2[120],17),_mm512_xor_si512(_mm512_alignr_epi8(c2[121],c2[120],18),_mm512_xor_si512(_mm512_alignr_epi8(c2[124],c2[123],18),_mm512_xor_si512(_mm512_alignr_epi8(c2[138],c2[137],59),_mm512_xor_si512(_mm512_alignr_epi8(c2[135],c2[134],53),_mm512_xor_si512(_mm512_alignr_epi8(c2[135],c2[134],62),_mm512_xor_si512(_mm512_alignr_epi8(c2[135],c2[134],63),_mm512_xor_si512(_mm512_alignr_epi8(c2[149],c2[148],31),_mm512_xor_si512(_mm512_alignr_epi8(c2[148],c2[147],36),_mm512_xor_si512(_mm512_alignr_epi8(c2[146],c2[145],52),_mm512_xor_si512(_mm512_alignr_epi8(c2[146],c2[145],53),_mm512_xor_si512(_mm512_alignr_epi8(c2[160],c2[159],51),_mm512_xor_si512(_mm512_alignr_epi8(c2[158],c2[157],22),_mm512_xor_si512(_mm512_alignr_epi8(c2[160],c2[159],34),_mm512_xor_si512(_mm512_alignr_epi8(c2[160],c2[159],35),_mm512_xor_si512(_mm512_alignr_epi8(c2[161],c2[160],62),_mm512_xor_si512(_mm512_alignr_epi8(c2[170],c2[169],39),_mm512_xor_si512(_mm512_alignr_epi8(c2[174],c2[173],38),_mm512_xor_si512(_mm512_alignr_epi8(c2[170],c2[169],33),_mm512_xor_si512(_mm512_alignr_epi8(c2[170],c2[169],34),_mm512_xor_si512(_mm512_alignr_epi8(c2[182],c2[181],37),_mm512_xor_si512(_mm512_alignr_epi8(c2[186],c2[185],49),_mm512_xor_si512(_mm512_alignr_epi8(c2[186],c2[185],3),_mm512_xor_si512(_mm512_alignr_epi8(c2[198],c2[197],56),_mm512_xor_si512(_mm512_alignr_epi8(c2[196],c2[195],48),_mm512_xor_si512(_mm512_alignr_epi8(c2[195],c2[194],61),_mm512_xor_si512(_mm512_alignr_epi8(c2[195],c2[194],62),_mm512_xor_si512(c2[204],_mm512_xor_si512(_mm512_alignr_epi8(c2[205],c2[204],17),_mm512_xor_si512(_mm512_alignr_epi8(c2[207],c2[206],57),_mm512_xor_si512(_mm512_alignr_epi8(c2[207],c2[206],58),_mm512_xor_si512(c2[218],_mm512_xor_si512(_mm512_alignr_epi8(c2[218],c2[217],62),_mm512_xor_si512(_mm512_alignr_epi8(c2[219],c2[218],28),_mm512_xor_si512(_mm512_alignr_epi8(c2[219],c2[218],29),_mm512_xor_si512(_mm512_alignr_epi8(c2[217],c2[216],55),_mm512_xor_si512(_mm512_alignr_epi8(c2[230],c2[229],2),_mm512_xor_si512(_mm512_alignr_epi8(c2[232],c2[231],25),_mm512_xor_si512(_mm512_alignr_epi8(c2[230],c2[229],27),_mm512_xor_si512(_mm512_alignr_epi8(c2[244],c2[243],24),_mm512_xor_si512(_mm512_alignr_epi8(c2[245],c2[244],27),_mm512_xor_si512(_mm512_alignr_epi8(c2[245],c2[244],52),_mm512_xor_si512(_mm512_alignr_epi8(c2[245],c2[244],53),_mm512_xor_si512(_mm512_alignr_epi8(c2[256],c2[255],40),_mm512_xor_si512(_mm512_alignr_epi8(c2[258],c2[257],62),_mm512_xor_si512(_mm512_alignr_epi8(c2[256],c2[255],50),_mm512_alignr_epi8(c2[256],c2[255],51))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 16 + d2[96]=_mm512_xor_si512(_mm512_alignr_epi8(c2[6],c2[5],44),_mm512_xor_si512(_mm512_alignr_epi8(c2[3],c2[2],5),_mm512_xor_si512(_mm512_alignr_epi8(c2[5],c2[4],6),_mm512_xor_si512(_mm512_alignr_epi8(c2[6],c2[5],13),_mm512_xor_si512(_mm512_alignr_epi8(c2[14],c2[13],12),_mm512_xor_si512(_mm512_alignr_epi8(c2[17],c2[16],51),_mm512_xor_si512(_mm512_alignr_epi8(c2[15],c2[14],16),_mm512_xor_si512(_mm512_alignr_epi8(c2[13],c2[12],13),_mm512_xor_si512(_mm512_alignr_epi8(c2[26],c2[25],43),_mm512_xor_si512(_mm512_alignr_epi8(c2[27],c2[26],5),_mm512_xor_si512(_mm512_alignr_epi8(c2[25],c2[24],1),_mm512_xor_si512(_mm512_alignr_epi8(c2[37],c2[36],42),_mm512_xor_si512(_mm512_alignr_epi8(c2[39],c2[38],2),_mm512_xor_si512(_mm512_alignr_epi8(c2[37],c2[36],57),_mm512_xor_si512(_mm512_alignr_epi8(c2[42],c2[41],18),_mm512_xor_si512(_mm512_alignr_epi8(c2[54],c2[53],25),_mm512_xor_si512(_mm512_alignr_epi8(c2[49],c2[48],5),_mm512_xor_si512(_mm512_alignr_epi8(c2[54],c2[53],12),_mm512_xor_si512(_mm512_alignr_epi8(c2[64],c2[63],46),_mm512_xor_si512(_mm512_alignr_epi8(c2[64],c2[63],9),_mm512_xor_si512(_mm512_alignr_epi8(c2[65],c2[64],57),_mm512_xor_si512(_mm512_alignr_epi8(c2[77],c2[76],17),_mm512_xor_si512(_mm512_alignr_epi8(c2[76],c2[75],26),_mm512_xor_si512(c2[76],_mm512_xor_si512(_mm512_alignr_epi8(c2[85],c2[84],4),_mm512_xor_si512(_mm512_alignr_epi8(c2[90],c2[89],4),_mm512_xor_si512(_mm512_alignr_epi8(c2[88],c2[87],18),_mm512_xor_si512(_mm512_alignr_epi8(c2[97],c2[96],4),_mm512_xor_si512(_mm512_alignr_epi8(c2[100],c2[99],25),_mm512_xor_si512(_mm512_alignr_epi8(c2[98],c2[97],49),_mm512_xor_si512(_mm512_alignr_epi8(c2[114],c2[113],54),_mm512_xor_si512(_mm512_alignr_epi8(c2[112],c2[111],43),_mm512_xor_si512(_mm512_alignr_epi8(c2[110],c2[109],56),_mm512_xor_si512(_mm512_alignr_epi8(c2[126],c2[125],25),_mm512_xor_si512(_mm512_alignr_epi8(c2[123],c2[122],58),_mm512_xor_si512(_mm512_alignr_epi8(c2[123],c2[122],61),_mm512_xor_si512(_mm512_alignr_epi8(c2[135],c2[134],38),_mm512_xor_si512(_mm512_alignr_epi8(c2[138],c2[137],32),_mm512_xor_si512(_mm512_alignr_epi8(c2[138],c2[137],42),_mm512_xor_si512(_mm512_alignr_epi8(c2[133],c2[132],57),_mm512_xor_si512(_mm512_alignr_epi8(c2[146],c2[145],10),_mm512_xor_si512(_mm512_alignr_epi8(c2[145],c2[144],15),_mm512_xor_si512(_mm512_alignr_epi8(c2[149],c2[148],32),_mm512_xor_si512(_mm512_alignr_epi8(c2[157],c2[156],30),_mm512_xor_si512(_mm512_alignr_epi8(c2[161],c2[160],1),_mm512_xor_si512(_mm512_alignr_epi8(c2[157],c2[156],14),_mm512_xor_si512(_mm512_alignr_epi8(c2[173],c2[172],18),_mm512_xor_si512(_mm512_alignr_epi8(c2[171],c2[170],17),_mm512_xor_si512(_mm512_alignr_epi8(c2[173],c2[172],13),_mm512_xor_si512(_mm512_alignr_epi8(c2[185],c2[184],16),_mm512_xor_si512(_mm512_alignr_epi8(c2[183],c2[182],28),_mm512_xor_si512(_mm512_alignr_epi8(c2[182],c2[181],46),_mm512_xor_si512(_mm512_alignr_epi8(c2[195],c2[194],35),_mm512_xor_si512(_mm512_alignr_epi8(c2[193],c2[192],27),_mm512_xor_si512(_mm512_alignr_epi8(c2[198],c2[197],41),_mm512_xor_si512(_mm512_alignr_epi8(c2[207],c2[206],43),_mm512_xor_si512(_mm512_alignr_epi8(c2[207],c2[206],60),_mm512_xor_si512(_mm512_alignr_epi8(c2[210],c2[209],37),_mm512_xor_si512(_mm512_alignr_epi8(c2[221],c2[220],43),_mm512_xor_si512(_mm512_alignr_epi8(c2[221],c2[220],41),_mm512_xor_si512(_mm512_alignr_epi8(c2[222],c2[221],8),_mm512_xor_si512(_mm512_alignr_epi8(c2[232],c2[231],45),_mm512_xor_si512(_mm512_alignr_epi8(c2[229],c2[228],4),_mm512_xor_si512(_mm512_alignr_epi8(c2[233],c2[232],6),_mm512_xor_si512(_mm512_alignr_epi8(c2[241],c2[240],3),_mm512_xor_si512(_mm512_alignr_epi8(c2[242],c2[241],6),_mm512_xor_si512(_mm512_alignr_epi8(c2[242],c2[241],32),_mm512_xor_si512(_mm512_alignr_epi8(c2[245],c2[244],33),_mm512_xor_si512(_mm512_alignr_epi8(c2[253],c2[252],19),_mm512_xor_si512(_mm512_alignr_epi8(c2[255],c2[254],41),_mm512_alignr_epi8(c2[253],c2[252],30))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 17 + d2[102]=_mm512_xor_si512(_mm512_alignr_epi8(c2[5],c2[4],4),_mm512_xor_si512(_mm512_alignr_epi8(c2[173],c2[172],47),_mm512_xor_si512(_mm512_alignr_epi8(c2[194],c2[193],17),_mm512_xor_si512(_mm512_alignr_epi8(c2[210],c2[209],38),_mm512_alignr_epi8(c2[258],c2[257],55))))); + +//row: 18 + d2[108]=_mm512_xor_si512(_mm512_alignr_epi8(c2[15],c2[14],2),_mm512_xor_si512(_mm512_alignr_epi8(c2[147],c2[146],35),_mm512_xor_si512(_mm512_alignr_epi8(c2[161],c2[160],24),_mm512_xor_si512(_mm512_alignr_epi8(c2[219],c2[218],4),_mm512_alignr_epi8(c2[229],c2[228],4))))); + +//row: 19 + d2[114]=_mm512_xor_si512(_mm512_alignr_epi8(c2[3],c2[2],17),_mm512_xor_si512(_mm512_alignr_epi8(c2[16],c2[15],21),_mm512_xor_si512(_mm512_alignr_epi8(c2[90],c2[89],24),_mm512_xor_si512(_mm512_alignr_epi8(c2[100],c2[99],50),_mm512_alignr_epi8(c2[124],c2[123],5))))); + +//row: 20 + d2[120]=_mm512_xor_si512(_mm512_alignr_epi8(c2[6],c2[5],46),_mm512_xor_si512(_mm512_alignr_epi8(c2[3],c2[2],7),_mm512_xor_si512(_mm512_alignr_epi8(c2[5],c2[4],8),_mm512_xor_si512(_mm512_alignr_epi8(c2[6],c2[5],15),_mm512_xor_si512(_mm512_alignr_epi8(c2[3],c2[2],59),_mm512_xor_si512(_mm512_alignr_epi8(c2[14],c2[13],14),_mm512_xor_si512(_mm512_alignr_epi8(c2[17],c2[16],53),_mm512_xor_si512(_mm512_alignr_epi8(c2[15],c2[14],18),_mm512_xor_si512(_mm512_alignr_epi8(c2[26],c2[25],45),_mm512_xor_si512(_mm512_alignr_epi8(c2[27],c2[26],7),_mm512_xor_si512(_mm512_alignr_epi8(c2[25],c2[24],3),_mm512_xor_si512(_mm512_alignr_epi8(c2[37],c2[36],44),_mm512_xor_si512(_mm512_alignr_epi8(c2[39],c2[38],4),_mm512_xor_si512(_mm512_alignr_epi8(c2[37],c2[36],59),_mm512_xor_si512(_mm512_alignr_epi8(c2[40],c2[39],14),_mm512_xor_si512(_mm512_alignr_epi8(c2[54],c2[53],27),_mm512_xor_si512(_mm512_alignr_epi8(c2[49],c2[48],7),_mm512_xor_si512(_mm512_alignr_epi8(c2[54],c2[53],14),_mm512_xor_si512(_mm512_alignr_epi8(c2[64],c2[63],48),_mm512_xor_si512(_mm512_alignr_epi8(c2[64],c2[63],11),_mm512_xor_si512(_mm512_alignr_epi8(c2[65],c2[64],59),_mm512_xor_si512(_mm512_alignr_epi8(c2[77],c2[76],19),_mm512_xor_si512(_mm512_alignr_epi8(c2[76],c2[75],28),_mm512_xor_si512(_mm512_alignr_epi8(c2[77],c2[76],2),_mm512_xor_si512(_mm512_alignr_epi8(c2[85],c2[84],6),_mm512_xor_si512(_mm512_alignr_epi8(c2[90],c2[89],6),_mm512_xor_si512(_mm512_alignr_epi8(c2[88],c2[87],20),_mm512_xor_si512(_mm512_alignr_epi8(c2[97],c2[96],6),_mm512_xor_si512(_mm512_alignr_epi8(c2[100],c2[99],27),_mm512_xor_si512(_mm512_alignr_epi8(c2[98],c2[97],51),_mm512_xor_si512(_mm512_alignr_epi8(c2[114],c2[113],56),_mm512_xor_si512(_mm512_alignr_epi8(c2[112],c2[111],45),_mm512_xor_si512(_mm512_alignr_epi8(c2[110],c2[109],58),_mm512_xor_si512(_mm512_alignr_epi8(c2[113],c2[112],8),_mm512_xor_si512(_mm512_alignr_epi8(c2[126],c2[125],27),_mm512_xor_si512(_mm512_alignr_epi8(c2[123],c2[122],60),_mm512_xor_si512(_mm512_alignr_epi8(c2[123],c2[122],63),_mm512_xor_si512(_mm512_alignr_epi8(c2[135],c2[134],40),_mm512_xor_si512(_mm512_alignr_epi8(c2[138],c2[137],34),_mm512_xor_si512(_mm512_alignr_epi8(c2[138],c2[137],44),_mm512_xor_si512(_mm512_alignr_epi8(c2[138],c2[137],21),_mm512_xor_si512(_mm512_alignr_epi8(c2[146],c2[145],12),_mm512_xor_si512(_mm512_alignr_epi8(c2[145],c2[144],17),_mm512_xor_si512(_mm512_alignr_epi8(c2[149],c2[148],34),_mm512_xor_si512(_mm512_alignr_epi8(c2[157],c2[156],32),_mm512_xor_si512(_mm512_alignr_epi8(c2[161],c2[160],3),_mm512_xor_si512(_mm512_alignr_epi8(c2[157],c2[156],16),_mm512_xor_si512(_mm512_alignr_epi8(c2[173],c2[172],20),_mm512_xor_si512(_mm512_alignr_epi8(c2[171],c2[170],19),_mm512_xor_si512(_mm512_alignr_epi8(c2[173],c2[172],15),_mm512_xor_si512(_mm512_alignr_epi8(c2[185],c2[184],18),_mm512_xor_si512(_mm512_alignr_epi8(c2[183],c2[182],30),_mm512_xor_si512(_mm512_alignr_epi8(c2[182],c2[181],48),_mm512_xor_si512(_mm512_alignr_epi8(c2[195],c2[194],37),_mm512_xor_si512(_mm512_alignr_epi8(c2[193],c2[192],29),_mm512_xor_si512(_mm512_alignr_epi8(c2[198],c2[197],43),_mm512_xor_si512(_mm512_alignr_epi8(c2[207],c2[206],45),_mm512_xor_si512(_mm512_alignr_epi8(c2[207],c2[206],62),_mm512_xor_si512(_mm512_alignr_epi8(c2[210],c2[209],39),_mm512_xor_si512(_mm512_alignr_epi8(c2[221],c2[220],45),_mm512_xor_si512(_mm512_alignr_epi8(c2[221],c2[220],43),_mm512_xor_si512(_mm512_alignr_epi8(c2[222],c2[221],10),_mm512_xor_si512(_mm512_alignr_epi8(c2[232],c2[231],47),_mm512_xor_si512(_mm512_alignr_epi8(c2[229],c2[228],6),_mm512_xor_si512(_mm512_alignr_epi8(c2[233],c2[232],8),_mm512_xor_si512(_mm512_alignr_epi8(c2[241],c2[240],5),_mm512_xor_si512(_mm512_alignr_epi8(c2[242],c2[241],8),_mm512_xor_si512(_mm512_alignr_epi8(c2[242],c2[241],34),_mm512_xor_si512(_mm512_alignr_epi8(c2[253],c2[252],21),_mm512_xor_si512(_mm512_alignr_epi8(c2[255],c2[254],43),_mm512_alignr_epi8(c2[253],c2[252],32))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 21 + d2[126]=_mm512_xor_si512(_mm512_alignr_epi8(c2[16],c2[15],13),_mm512_xor_si512(_mm512_alignr_epi8(c2[62],c2[61],38),_mm512_xor_si512(_mm512_alignr_epi8(c2[198],c2[197],8),_mm512_xor_si512(_mm512_alignr_epi8(c2[244],c2[243],21),_mm512_alignr_epi8(c2[254],c2[253],33))))); + +//row: 22 + d2[132]=_mm512_xor_si512(_mm512_alignr_epi8(c2[1],c2[0],30),_mm512_xor_si512(_mm512_alignr_epi8(c2[145],c2[144],11),_mm512_xor_si512(_mm512_alignr_epi8(c2[160],c2[159],41),_mm512_alignr_epi8(c2[205],c2[204],22)))); + +//row: 23 + d2[138]=_mm512_xor_si512(_mm512_alignr_epi8(c2[13],c2[12],24),_mm512_xor_si512(_mm512_alignr_epi8(c2[26],c2[25],25),_mm512_xor_si512(_mm512_alignr_epi8(c2[121],c2[120],61),_mm512_alignr_epi8(c2[217],c2[216],27)))); + +//row: 24 + d2[144]=_mm512_xor_si512(_mm512_alignr_epi8(c2[3],c2[2],29),_mm512_xor_si512(_mm512_alignr_epi8(c2[5],c2[4],54),_mm512_xor_si512(_mm512_alignr_epi8(c2[1],c2[0],55),_mm512_xor_si512(_mm512_alignr_epi8(c2[2],c2[1],62),_mm512_xor_si512(_mm512_alignr_epi8(c2[5],c2[4],42),_mm512_xor_si512(_mm512_alignr_epi8(c2[16],c2[15],61),_mm512_xor_si512(_mm512_alignr_epi8(c2[14],c2[13],36),_mm512_xor_si512(_mm512_alignr_epi8(c2[18],c2[17],1),_mm512_xor_si512(_mm512_alignr_epi8(c2[29],c2[28],28),_mm512_xor_si512(_mm512_alignr_epi8(c2[29],c2[28],54),_mm512_xor_si512(_mm512_alignr_epi8(c2[27],c2[26],50),_mm512_xor_si512(_mm512_alignr_epi8(c2[40],c2[39],27),_mm512_xor_si512(_mm512_alignr_epi8(c2[41],c2[40],51),_mm512_xor_si512(_mm512_alignr_epi8(c2[40],c2[39],42),_mm512_xor_si512(_mm512_alignr_epi8(c2[39],c2[38],30),_mm512_xor_si512(_mm512_alignr_epi8(c2[51],c2[50],10),_mm512_xor_si512(_mm512_alignr_epi8(c2[51],c2[50],54),_mm512_xor_si512(_mm512_alignr_epi8(c2[50],c2[49],61),_mm512_xor_si512(_mm512_alignr_epi8(c2[52],c2[51],43),_mm512_xor_si512(_mm512_alignr_epi8(c2[61],c2[60],31),_mm512_xor_si512(_mm512_alignr_epi8(c2[66],c2[65],58),_mm512_xor_si512(_mm512_alignr_epi8(c2[62],c2[61],42),_mm512_xor_si512(_mm512_alignr_epi8(c2[74],c2[73],2),_mm512_xor_si512(_mm512_alignr_epi8(c2[73],c2[72],11),_mm512_xor_si512(_mm512_alignr_epi8(c2[73],c2[72],49),_mm512_xor_si512(_mm512_alignr_epi8(c2[87],c2[86],53),_mm512_xor_si512(_mm512_alignr_epi8(c2[86],c2[85],53),_mm512_xor_si512(_mm512_alignr_epi8(c2[85],c2[84],3),_mm512_xor_si512(_mm512_alignr_epi8(c2[99],c2[98],53),_mm512_xor_si512(_mm512_alignr_epi8(c2[97],c2[96],10),_mm512_xor_si512(_mm512_alignr_epi8(c2[101],c2[100],34),_mm512_xor_si512(_mm512_alignr_epi8(c2[111],c2[110],39),_mm512_xor_si512(_mm512_alignr_epi8(c2[109],c2[108],28),_mm512_xor_si512(_mm512_alignr_epi8(c2[113],c2[112],41),_mm512_xor_si512(_mm512_alignr_epi8(c2[123],c2[122],10),_mm512_xor_si512(_mm512_alignr_epi8(c2[126],c2[125],43),_mm512_xor_si512(_mm512_alignr_epi8(c2[126],c2[125],46),_mm512_xor_si512(_mm512_alignr_epi8(c2[138],c2[137],23),_mm512_xor_si512(_mm512_alignr_epi8(c2[135],c2[134],17),_mm512_xor_si512(_mm512_alignr_epi8(c2[135],c2[134],27),_mm512_xor_si512(_mm512_alignr_epi8(c2[138],c2[137],19),_mm512_xor_si512(_mm512_alignr_epi8(c2[148],c2[147],59),_mm512_xor_si512(c2[147],_mm512_xor_si512(_mm512_alignr_epi8(c2[146],c2[145],17),_mm512_xor_si512(_mm512_alignr_epi8(c2[160],c2[159],15),_mm512_xor_si512(_mm512_alignr_epi8(c2[157],c2[156],50),_mm512_xor_si512(_mm512_alignr_epi8(c2[159],c2[158],63),_mm512_xor_si512(_mm512_alignr_epi8(c2[170],c2[169],3),_mm512_xor_si512(_mm512_alignr_epi8(c2[174],c2[173],2),_mm512_xor_si512(_mm512_alignr_epi8(c2[169],c2[168],62),_mm512_xor_si512(_mm512_alignr_epi8(c2[182],c2[181],1),_mm512_xor_si512(_mm512_alignr_epi8(c2[186],c2[185],13),_mm512_xor_si512(_mm512_alignr_epi8(c2[185],c2[184],31),_mm512_xor_si512(_mm512_alignr_epi8(c2[198],c2[197],20),_mm512_xor_si512(_mm512_alignr_epi8(c2[196],c2[195],12),_mm512_xor_si512(_mm512_alignr_epi8(c2[195],c2[194],26),_mm512_xor_si512(_mm512_alignr_epi8(c2[210],c2[209],28),_mm512_xor_si512(_mm512_alignr_epi8(c2[210],c2[209],45),_mm512_xor_si512(_mm512_alignr_epi8(c2[207],c2[206],22),_mm512_xor_si512(_mm512_alignr_epi8(c2[218],c2[217],28),_mm512_xor_si512(_mm512_alignr_epi8(c2[218],c2[217],26),_mm512_xor_si512(_mm512_alignr_epi8(c2[218],c2[217],57),_mm512_xor_si512(_mm512_alignr_epi8(c2[229],c2[228],30),_mm512_xor_si512(_mm512_alignr_epi8(c2[231],c2[230],53),_mm512_xor_si512(_mm512_alignr_epi8(c2[229],c2[228],55),_mm512_xor_si512(_mm512_alignr_epi8(c2[243],c2[242],52),_mm512_xor_si512(_mm512_alignr_epi8(c2[244],c2[243],55),_mm512_xor_si512(_mm512_alignr_epi8(c2[245],c2[244],17),_mm512_xor_si512(_mm512_alignr_epi8(c2[256],c2[255],4),_mm512_xor_si512(_mm512_alignr_epi8(c2[258],c2[257],26),_mm512_alignr_epi8(c2[256],c2[255],15))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 25 + d2[150]=_mm512_xor_si512(_mm512_alignr_epi8(c2[14],c2[13],8),_mm512_xor_si512(_mm512_alignr_epi8(c2[73],c2[72],17),_mm512_xor_si512(_mm512_alignr_epi8(c2[90],c2[89],63),_mm512_alignr_epi8(c2[173],c2[172],56)))); + +//row: 26 + d2[156]=_mm512_xor_si512(_mm512_alignr_epi8(c2[2],c2[1],7),_mm512_xor_si512(_mm512_alignr_epi8(c2[26],c2[25],17),_mm512_xor_si512(_mm512_alignr_epi8(c2[50],c2[49],12),_mm512_alignr_epi8(c2[183],c2[182],8)))); + +//row: 27 + d2[162]=_mm512_xor_si512(_mm512_alignr_epi8(c2[16],c2[15],2),_mm512_xor_si512(_mm512_alignr_epi8(c2[76],c2[75],2),_mm512_alignr_epi8(c2[98],c2[97],37))); + +//row: 28 + d2[168]=_mm512_xor_si512(_mm512_alignr_epi8(c2[4],c2[3],30),_mm512_xor_si512(_mm512_alignr_epi8(c2[49],c2[48],19),_mm512_xor_si512(_mm512_alignr_epi8(c2[232],c2[231],52),_mm512_alignr_epi8(c2[257],c2[256],18)))); + +//row: 29 + d2[174]=_mm512_xor_si512(_mm512_alignr_epi8(c2[1],c2[0],2),_mm512_xor_si512(_mm512_alignr_epi8(c2[3],c2[2],27),_mm512_xor_si512(_mm512_alignr_epi8(c2[5],c2[4],28),_mm512_xor_si512(_mm512_alignr_epi8(c2[6],c2[5],34),_mm512_xor_si512(_mm512_alignr_epi8(c2[6],c2[5],35),_mm512_xor_si512(_mm512_alignr_epi8(c2[14],c2[13],34),_mm512_xor_si512(_mm512_alignr_epi8(c2[18],c2[17],9),_mm512_xor_si512(_mm512_alignr_epi8(c2[15],c2[14],37),_mm512_xor_si512(_mm512_alignr_epi8(c2[15],c2[14],38),_mm512_xor_si512(_mm512_alignr_epi8(c2[16],c2[15],60),_mm512_xor_si512(_mm512_alignr_epi8(c2[27],c2[26],1),_mm512_xor_si512(_mm512_alignr_epi8(c2[27],c2[26],27),_mm512_xor_si512(_mm512_alignr_epi8(c2[25],c2[24],23),_mm512_xor_si512(c2[37],_mm512_xor_si512(_mm512_alignr_epi8(c2[39],c2[38],24),_mm512_xor_si512(_mm512_alignr_epi8(c2[38],c2[37],14),_mm512_xor_si512(_mm512_alignr_epi8(c2[38],c2[37],15),_mm512_xor_si512(_mm512_alignr_epi8(c2[54],c2[53],47),_mm512_xor_si512(_mm512_alignr_epi8(c2[49],c2[48],27),_mm512_xor_si512(_mm512_alignr_epi8(c2[54],c2[53],33),_mm512_xor_si512(_mm512_alignr_epi8(c2[54],c2[53],34),_mm512_xor_si512(_mm512_alignr_epi8(c2[65],c2[64],4),_mm512_xor_si512(_mm512_alignr_epi8(c2[64],c2[63],31),_mm512_xor_si512(_mm512_alignr_epi8(c2[66],c2[65],15),_mm512_xor_si512(_mm512_alignr_epi8(c2[77],c2[76],39),_mm512_xor_si512(_mm512_alignr_epi8(c2[76],c2[75],48),_mm512_xor_si512(_mm512_alignr_epi8(c2[77],c2[76],21),_mm512_xor_si512(_mm512_alignr_epi8(c2[77],c2[76],22),_mm512_xor_si512(_mm512_alignr_epi8(c2[85],c2[84],26),_mm512_xor_si512(_mm512_alignr_epi8(c2[90],c2[89],26),_mm512_xor_si512(_mm512_alignr_epi8(c2[88],c2[87],39),_mm512_xor_si512(_mm512_alignr_epi8(c2[88],c2[87],40),_mm512_xor_si512(_mm512_alignr_epi8(c2[97],c2[96],26),_mm512_xor_si512(_mm512_alignr_epi8(c2[100],c2[99],47),_mm512_xor_si512(_mm512_alignr_epi8(c2[99],c2[98],6),_mm512_xor_si512(_mm512_alignr_epi8(c2[99],c2[98],7),_mm512_xor_si512(_mm512_alignr_epi8(c2[109],c2[108],12),_mm512_xor_si512(_mm512_alignr_epi8(c2[113],c2[112],1),_mm512_xor_si512(_mm512_alignr_epi8(c2[111],c2[110],14),_mm512_xor_si512(_mm512_alignr_epi8(c2[126],c2[125],47),_mm512_xor_si512(_mm512_alignr_epi8(c2[124],c2[123],16),_mm512_xor_si512(_mm512_alignr_epi8(c2[124],c2[123],18),_mm512_xor_si512(_mm512_alignr_epi8(c2[124],c2[123],19),_mm512_xor_si512(_mm512_alignr_epi8(c2[135],c2[134],60),_mm512_xor_si512(_mm512_alignr_epi8(c2[138],c2[137],54),_mm512_xor_si512(_mm512_alignr_epi8(c2[138],c2[137],63),_mm512_xor_si512(c2[132],_mm512_xor_si512(_mm512_alignr_epi8(c2[146],c2[145],32),_mm512_xor_si512(_mm512_alignr_epi8(c2[145],c2[144],37),_mm512_xor_si512(_mm512_alignr_epi8(c2[149],c2[148],53),_mm512_xor_si512(_mm512_alignr_epi8(c2[149],c2[148],54),_mm512_xor_si512(_mm512_alignr_epi8(c2[157],c2[156],52),_mm512_xor_si512(_mm512_alignr_epi8(c2[161],c2[160],23),_mm512_xor_si512(_mm512_alignr_epi8(c2[157],c2[156],35),_mm512_xor_si512(_mm512_alignr_epi8(c2[157],c2[156],36),_mm512_xor_si512(_mm512_alignr_epi8(c2[173],c2[172],40),_mm512_xor_si512(_mm512_alignr_epi8(c2[171],c2[170],39),_mm512_xor_si512(_mm512_alignr_epi8(c2[173],c2[172],34),_mm512_xor_si512(_mm512_alignr_epi8(c2[173],c2[172],35),_mm512_xor_si512(_mm512_alignr_epi8(c2[169],c2[168],5),_mm512_xor_si512(_mm512_alignr_epi8(c2[185],c2[184],38),_mm512_xor_si512(_mm512_alignr_epi8(c2[183],c2[182],50),_mm512_xor_si512(_mm512_alignr_epi8(c2[183],c2[182],4),_mm512_xor_si512(_mm512_alignr_epi8(c2[195],c2[194],57),_mm512_xor_si512(_mm512_alignr_epi8(c2[193],c2[192],49),_mm512_xor_si512(_mm512_alignr_epi8(c2[198],c2[197],62),_mm512_xor_si512(_mm512_alignr_epi8(c2[198],c2[197],63),_mm512_xor_si512(_mm512_alignr_epi8(c2[208],c2[207],1),_mm512_xor_si512(_mm512_alignr_epi8(c2[208],c2[207],18),_mm512_xor_si512(_mm512_alignr_epi8(c2[210],c2[209],58),_mm512_xor_si512(_mm512_alignr_epi8(c2[210],c2[209],59),_mm512_xor_si512(_mm512_alignr_epi8(c2[222],c2[221],1),_mm512_xor_si512(_mm512_alignr_epi8(c2[221],c2[220],63),_mm512_xor_si512(_mm512_alignr_epi8(c2[222],c2[221],29),_mm512_xor_si512(_mm512_alignr_epi8(c2[222],c2[221],30),_mm512_xor_si512(_mm512_alignr_epi8(c2[219],c2[218],19),_mm512_xor_si512(_mm512_alignr_epi8(c2[233],c2[232],3),_mm512_xor_si512(_mm512_alignr_epi8(c2[229],c2[228],26),_mm512_xor_si512(_mm512_alignr_epi8(c2[233],c2[232],28),_mm512_xor_si512(_mm512_alignr_epi8(c2[241],c2[240],25),_mm512_xor_si512(_mm512_alignr_epi8(c2[242],c2[241],28),_mm512_xor_si512(_mm512_alignr_epi8(c2[242],c2[241],53),_mm512_xor_si512(_mm512_alignr_epi8(c2[242],c2[241],54),_mm512_xor_si512(_mm512_alignr_epi8(c2[253],c2[252],41),_mm512_xor_si512(_mm512_alignr_epi8(c2[255],c2[254],63),_mm512_xor_si512(_mm512_alignr_epi8(c2[253],c2[252],51),_mm512_alignr_epi8(c2[253],c2[252],52))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 30 + d2[180]=_mm512_xor_si512(_mm512_alignr_epi8(c2[1],c2[0],14),_mm512_xor_si512(_mm512_alignr_epi8(c2[3],c2[2],39),_mm512_xor_si512(_mm512_alignr_epi8(c2[5],c2[4],39),_mm512_xor_si512(_mm512_alignr_epi8(c2[5],c2[4],40),_mm512_xor_si512(_mm512_alignr_epi8(c2[6],c2[5],46),_mm512_xor_si512(_mm512_alignr_epi8(c2[6],c2[5],47),_mm512_xor_si512(_mm512_alignr_epi8(c2[3],c2[2],31),_mm512_xor_si512(_mm512_alignr_epi8(c2[14],c2[13],46),_mm512_xor_si512(_mm512_alignr_epi8(c2[18],c2[17],20),_mm512_xor_si512(_mm512_alignr_epi8(c2[18],c2[17],21),_mm512_xor_si512(_mm512_alignr_epi8(c2[15],c2[14],49),_mm512_xor_si512(_mm512_alignr_epi8(c2[15],c2[14],50),_mm512_xor_si512(_mm512_alignr_epi8(c2[27],c2[26],13),_mm512_xor_si512(_mm512_alignr_epi8(c2[27],c2[26],39),_mm512_xor_si512(_mm512_alignr_epi8(c2[25],c2[24],34),_mm512_xor_si512(_mm512_alignr_epi8(c2[25],c2[24],35),_mm512_xor_si512(_mm512_alignr_epi8(c2[38],c2[37],12),_mm512_xor_si512(_mm512_alignr_epi8(c2[39],c2[38],36),_mm512_xor_si512(_mm512_alignr_epi8(c2[38],c2[37],26),_mm512_xor_si512(_mm512_alignr_epi8(c2[38],c2[37],27),_mm512_xor_si512(_mm512_alignr_epi8(c2[54],c2[53],59),_mm512_xor_si512(_mm512_alignr_epi8(c2[49],c2[48],38),_mm512_xor_si512(_mm512_alignr_epi8(c2[49],c2[48],39),_mm512_xor_si512(_mm512_alignr_epi8(c2[54],c2[53],45),_mm512_xor_si512(_mm512_alignr_epi8(c2[54],c2[53],46),_mm512_xor_si512(_mm512_alignr_epi8(c2[65],c2[64],16),_mm512_xor_si512(_mm512_alignr_epi8(c2[64],c2[63],43),_mm512_xor_si512(_mm512_alignr_epi8(c2[66],c2[65],26),_mm512_xor_si512(_mm512_alignr_epi8(c2[66],c2[65],27),_mm512_xor_si512(_mm512_alignr_epi8(c2[77],c2[76],51),_mm512_xor_si512(_mm512_alignr_epi8(c2[76],c2[75],59),_mm512_xor_si512(_mm512_alignr_epi8(c2[76],c2[75],60),_mm512_xor_si512(_mm512_alignr_epi8(c2[77],c2[76],33),_mm512_xor_si512(_mm512_alignr_epi8(c2[77],c2[76],34),_mm512_xor_si512(_mm512_alignr_epi8(c2[85],c2[84],38),_mm512_xor_si512(_mm512_alignr_epi8(c2[90],c2[89],37),_mm512_xor_si512(_mm512_alignr_epi8(c2[90],c2[89],38),_mm512_xor_si512(_mm512_alignr_epi8(c2[88],c2[87],51),_mm512_xor_si512(_mm512_alignr_epi8(c2[88],c2[87],52),_mm512_xor_si512(_mm512_alignr_epi8(c2[97],c2[96],38),_mm512_xor_si512(_mm512_alignr_epi8(c2[100],c2[99],58),_mm512_xor_si512(_mm512_alignr_epi8(c2[100],c2[99],59),_mm512_xor_si512(_mm512_alignr_epi8(c2[99],c2[98],18),_mm512_xor_si512(_mm512_alignr_epi8(c2[99],c2[98],19),_mm512_xor_si512(_mm512_alignr_epi8(c2[109],c2[108],24),_mm512_xor_si512(_mm512_alignr_epi8(c2[113],c2[112],13),_mm512_xor_si512(_mm512_alignr_epi8(c2[111],c2[110],25),_mm512_xor_si512(_mm512_alignr_epi8(c2[111],c2[110],26),_mm512_xor_si512(_mm512_alignr_epi8(c2[126],c2[125],59),_mm512_xor_si512(_mm512_alignr_epi8(c2[124],c2[123],27),_mm512_xor_si512(_mm512_alignr_epi8(c2[124],c2[123],28),_mm512_xor_si512(_mm512_alignr_epi8(c2[124],c2[123],30),_mm512_xor_si512(_mm512_alignr_epi8(c2[124],c2[123],31),_mm512_xor_si512(_mm512_alignr_epi8(c2[124],c2[123],37),_mm512_xor_si512(_mm512_alignr_epi8(c2[136],c2[135],8),_mm512_xor_si512(_mm512_alignr_epi8(c2[133],c2[132],2),_mm512_xor_si512(_mm512_alignr_epi8(c2[133],c2[132],11),_mm512_xor_si512(_mm512_alignr_epi8(c2[133],c2[132],12),_mm512_xor_si512(_mm512_alignr_epi8(c2[146],c2[145],44),_mm512_xor_si512(_mm512_alignr_epi8(c2[145],c2[144],49),_mm512_xor_si512(_mm512_alignr_epi8(c2[150],c2[149],1),_mm512_xor_si512(_mm512_alignr_epi8(c2[150],c2[149],2),_mm512_xor_si512(c2[157],_mm512_xor_si512(_mm512_alignr_epi8(c2[161],c2[160],34),_mm512_xor_si512(_mm512_alignr_epi8(c2[161],c2[160],35),_mm512_xor_si512(_mm512_alignr_epi8(c2[157],c2[156],47),_mm512_xor_si512(_mm512_alignr_epi8(c2[157],c2[156],48),_mm512_xor_si512(_mm512_alignr_epi8(c2[161],c2[160],4),_mm512_xor_si512(_mm512_alignr_epi8(c2[173],c2[172],52),_mm512_xor_si512(_mm512_alignr_epi8(c2[171],c2[170],50),_mm512_xor_si512(_mm512_alignr_epi8(c2[171],c2[170],51),_mm512_xor_si512(_mm512_alignr_epi8(c2[173],c2[172],46),_mm512_xor_si512(_mm512_alignr_epi8(c2[173],c2[172],47),_mm512_xor_si512(_mm512_alignr_epi8(c2[185],c2[184],50),_mm512_xor_si512(_mm512_alignr_epi8(c2[183],c2[182],62),_mm512_xor_si512(_mm512_alignr_epi8(c2[183],c2[182],15),_mm512_xor_si512(_mm512_alignr_epi8(c2[183],c2[182],16),_mm512_xor_si512(_mm512_alignr_epi8(c2[196],c2[195],5),_mm512_xor_si512(_mm512_alignr_epi8(c2[193],c2[192],61),_mm512_xor_si512(_mm512_alignr_epi8(c2[193],c2[192],10),_mm512_xor_si512(_mm512_alignr_epi8(c2[193],c2[192],11),_mm512_xor_si512(_mm512_alignr_epi8(c2[208],c2[207],13),_mm512_xor_si512(_mm512_alignr_epi8(c2[208],c2[207],29),_mm512_xor_si512(_mm512_alignr_epi8(c2[208],c2[207],30),_mm512_xor_si512(_mm512_alignr_epi8(c2[205],c2[204],6),_mm512_xor_si512(_mm512_alignr_epi8(c2[205],c2[204],7),_mm512_xor_si512(_mm512_alignr_epi8(c2[222],c2[221],13),_mm512_xor_si512(_mm512_alignr_epi8(c2[222],c2[221],10),_mm512_xor_si512(_mm512_alignr_epi8(c2[222],c2[221],11),_mm512_xor_si512(_mm512_alignr_epi8(c2[222],c2[221],41),_mm512_xor_si512(_mm512_alignr_epi8(c2[222],c2[221],42),_mm512_xor_si512(_mm512_alignr_epi8(c2[233],c2[232],15),_mm512_xor_si512(_mm512_alignr_epi8(c2[229],c2[228],38),_mm512_xor_si512(_mm512_alignr_epi8(c2[233],c2[232],39),_mm512_xor_si512(_mm512_alignr_epi8(c2[233],c2[232],40),_mm512_xor_si512(_mm512_alignr_epi8(c2[241],c2[240],37),_mm512_xor_si512(_mm512_alignr_epi8(c2[242],c2[241],39),_mm512_xor_si512(_mm512_alignr_epi8(c2[242],c2[241],40),_mm512_xor_si512(_mm512_alignr_epi8(c2[243],c2[242],1),_mm512_xor_si512(_mm512_alignr_epi8(c2[243],c2[242],2),_mm512_xor_si512(_mm512_alignr_epi8(c2[253],c2[252],53),_mm512_xor_si512(_mm512_alignr_epi8(c2[256],c2[255],11),_mm512_xor_si512(_mm512_alignr_epi8(c2[253],c2[252],63),c2[253]))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 31 + d2[186]=_mm512_xor_si512(_mm512_alignr_epi8(c2[3],c2[2],53),_mm512_xor_si512(_mm512_alignr_epi8(c2[3],c2[2],52),_mm512_xor_si512(_mm512_alignr_epi8(c2[6],c2[5],14),_mm512_xor_si512(_mm512_alignr_epi8(c2[6],c2[5],13),_mm512_xor_si512(_mm512_alignr_epi8(c2[2],c2[1],15),_mm512_xor_si512(_mm512_alignr_epi8(c2[2],c2[1],14),_mm512_xor_si512(_mm512_alignr_epi8(c2[3],c2[2],22),_mm512_xor_si512(_mm512_alignr_epi8(c2[3],c2[2],20),_mm512_xor_si512(_mm512_alignr_epi8(c2[3],c2[2],21),_mm512_xor_si512(_mm512_alignr_epi8(c2[17],c2[16],21),_mm512_xor_si512(_mm512_alignr_epi8(c2[17],c2[16],20),_mm512_xor_si512(_mm512_alignr_epi8(c2[14],c2[13],60),_mm512_xor_si512(_mm512_alignr_epi8(c2[14],c2[13],59),_mm512_xor_si512(_mm512_alignr_epi8(c2[18],c2[17],25),_mm512_xor_si512(_mm512_alignr_epi8(c2[18],c2[17],23),_mm512_xor_si512(_mm512_alignr_epi8(c2[18],c2[17],24),_mm512_xor_si512(_mm512_alignr_epi8(c2[14],c2[13],36),_mm512_xor_si512(_mm512_alignr_epi8(c2[29],c2[28],52),_mm512_xor_si512(_mm512_alignr_epi8(c2[29],c2[28],51),_mm512_xor_si512(_mm512_alignr_epi8(c2[30],c2[29],14),_mm512_xor_si512(_mm512_alignr_epi8(c2[30],c2[29],13),_mm512_xor_si512(_mm512_alignr_epi8(c2[28],c2[27],10),_mm512_xor_si512(_mm512_alignr_epi8(c2[28],c2[27],9),_mm512_xor_si512(_mm512_alignr_epi8(c2[40],c2[39],51),_mm512_xor_si512(_mm512_alignr_epi8(c2[40],c2[39],50),_mm512_xor_si512(_mm512_alignr_epi8(c2[42],c2[41],11),_mm512_xor_si512(_mm512_alignr_epi8(c2[42],c2[41],10),_mm512_xor_si512(_mm512_alignr_epi8(c2[41],c2[40],2),_mm512_xor_si512(c2[40],_mm512_xor_si512(_mm512_alignr_epi8(c2[41],c2[40],1),_mm512_xor_si512(_mm512_alignr_epi8(c2[51],c2[50],34),_mm512_xor_si512(_mm512_alignr_epi8(c2[51],c2[50],33),_mm512_xor_si512(_mm512_alignr_epi8(c2[52],c2[51],14),_mm512_xor_si512(_mm512_alignr_epi8(c2[52],c2[51],13),_mm512_xor_si512(_mm512_alignr_epi8(c2[51],c2[50],21),_mm512_xor_si512(_mm512_alignr_epi8(c2[51],c2[50],19),_mm512_xor_si512(_mm512_alignr_epi8(c2[51],c2[50],20),_mm512_xor_si512(_mm512_alignr_epi8(c2[61],c2[60],55),_mm512_xor_si512(_mm512_alignr_epi8(c2[61],c2[60],54),_mm512_xor_si512(_mm512_alignr_epi8(c2[61],c2[60],18),_mm512_xor_si512(_mm512_alignr_epi8(c2[61],c2[60],17),_mm512_xor_si512(_mm512_alignr_epi8(c2[63],c2[62],2),_mm512_xor_si512(_mm512_alignr_epi8(c2[63],c2[62],1),_mm512_xor_si512(_mm512_alignr_epi8(c2[74],c2[73],26),_mm512_xor_si512(_mm512_alignr_epi8(c2[74],c2[73],25),_mm512_xor_si512(_mm512_alignr_epi8(c2[73],c2[72],35),_mm512_xor_si512(_mm512_alignr_epi8(c2[73],c2[72],34),_mm512_xor_si512(_mm512_alignr_epi8(c2[74],c2[73],9),_mm512_xor_si512(_mm512_alignr_epi8(c2[74],c2[73],7),_mm512_xor_si512(_mm512_alignr_epi8(c2[74],c2[73],8),_mm512_xor_si512(_mm512_alignr_epi8(c2[88],c2[87],13),_mm512_xor_si512(_mm512_alignr_epi8(c2[88],c2[87],12),_mm512_xor_si512(_mm512_alignr_epi8(c2[87],c2[86],13),_mm512_xor_si512(_mm512_alignr_epi8(c2[87],c2[86],12),_mm512_xor_si512(_mm512_alignr_epi8(c2[85],c2[84],27),_mm512_xor_si512(_mm512_alignr_epi8(c2[85],c2[84],25),_mm512_xor_si512(_mm512_alignr_epi8(c2[85],c2[84],26),_mm512_xor_si512(_mm512_alignr_epi8(c2[88],c2[87],23),_mm512_xor_si512(_mm512_alignr_epi8(c2[100],c2[99],13),_mm512_xor_si512(_mm512_alignr_epi8(c2[100],c2[99],12),_mm512_xor_si512(_mm512_alignr_epi8(c2[97],c2[96],34),_mm512_xor_si512(_mm512_alignr_epi8(c2[97],c2[96],33),_mm512_xor_si512(_mm512_alignr_epi8(c2[101],c2[100],58),_mm512_xor_si512(_mm512_alignr_epi8(c2[101],c2[100],56),_mm512_xor_si512(_mm512_alignr_epi8(c2[101],c2[100],57),_mm512_xor_si512(_mm512_alignr_epi8(c2[111],c2[110],63),_mm512_xor_si512(_mm512_alignr_epi8(c2[111],c2[110],62),_mm512_xor_si512(_mm512_alignr_epi8(c2[109],c2[108],52),_mm512_xor_si512(_mm512_alignr_epi8(c2[109],c2[108],51),_mm512_xor_si512(_mm512_alignr_epi8(c2[114],c2[113],1),_mm512_xor_si512(c2[113],_mm512_xor_si512(_mm512_alignr_epi8(c2[123],c2[122],34),_mm512_xor_si512(_mm512_alignr_epi8(c2[123],c2[122],33),_mm512_xor_si512(_mm512_alignr_epi8(c2[121],c2[120],3),_mm512_xor_si512(_mm512_alignr_epi8(c2[121],c2[120],2),_mm512_xor_si512(_mm512_alignr_epi8(c2[121],c2[120],6),_mm512_xor_si512(_mm512_alignr_epi8(c2[121],c2[120],4),_mm512_xor_si512(_mm512_alignr_epi8(c2[121],c2[120],5),_mm512_xor_si512(_mm512_alignr_epi8(c2[138],c2[137],47),_mm512_xor_si512(_mm512_alignr_epi8(c2[138],c2[137],46),_mm512_xor_si512(_mm512_alignr_epi8(c2[135],c2[134],41),_mm512_xor_si512(_mm512_alignr_epi8(c2[135],c2[134],40),_mm512_xor_si512(_mm512_alignr_epi8(c2[135],c2[134],51),_mm512_xor_si512(_mm512_alignr_epi8(c2[135],c2[134],49),_mm512_xor_si512(_mm512_alignr_epi8(c2[135],c2[134],50),_mm512_xor_si512(_mm512_alignr_epi8(c2[149],c2[148],19),_mm512_xor_si512(_mm512_alignr_epi8(c2[149],c2[148],18),_mm512_xor_si512(_mm512_alignr_epi8(c2[148],c2[147],24),_mm512_xor_si512(_mm512_alignr_epi8(c2[148],c2[147],23),_mm512_xor_si512(_mm512_alignr_epi8(c2[146],c2[145],41),_mm512_xor_si512(_mm512_alignr_epi8(c2[146],c2[145],39),_mm512_xor_si512(_mm512_alignr_epi8(c2[146],c2[145],40),_mm512_xor_si512(_mm512_alignr_epi8(c2[160],c2[159],39),_mm512_xor_si512(_mm512_alignr_epi8(c2[160],c2[159],38),_mm512_xor_si512(_mm512_alignr_epi8(c2[158],c2[157],10),_mm512_xor_si512(_mm512_alignr_epi8(c2[158],c2[157],9),_mm512_xor_si512(_mm512_alignr_epi8(c2[160],c2[159],23),_mm512_xor_si512(_mm512_alignr_epi8(c2[160],c2[159],21),_mm512_xor_si512(_mm512_alignr_epi8(c2[160],c2[159],22),_mm512_xor_si512(_mm512_alignr_epi8(c2[170],c2[169],27),_mm512_xor_si512(_mm512_alignr_epi8(c2[170],c2[169],26),_mm512_xor_si512(_mm512_alignr_epi8(c2[174],c2[173],26),_mm512_xor_si512(_mm512_alignr_epi8(c2[174],c2[173],25),_mm512_xor_si512(_mm512_alignr_epi8(c2[170],c2[169],22),_mm512_xor_si512(_mm512_alignr_epi8(c2[170],c2[169],20),_mm512_xor_si512(_mm512_alignr_epi8(c2[170],c2[169],21),_mm512_xor_si512(_mm512_alignr_epi8(c2[182],c2[181],25),_mm512_xor_si512(_mm512_alignr_epi8(c2[182],c2[181],24),_mm512_xor_si512(_mm512_alignr_epi8(c2[186],c2[185],37),_mm512_xor_si512(_mm512_alignr_epi8(c2[186],c2[185],36),_mm512_xor_si512(_mm512_alignr_epi8(c2[185],c2[184],55),_mm512_xor_si512(_mm512_alignr_epi8(c2[185],c2[184],54),_mm512_xor_si512(_mm512_alignr_epi8(c2[198],c2[197],44),_mm512_xor_si512(_mm512_alignr_epi8(c2[198],c2[197],43),_mm512_xor_si512(_mm512_alignr_epi8(c2[196],c2[195],36),_mm512_xor_si512(_mm512_alignr_epi8(c2[196],c2[195],35),_mm512_xor_si512(_mm512_alignr_epi8(c2[195],c2[194],50),_mm512_xor_si512(_mm512_alignr_epi8(c2[195],c2[194],48),_mm512_xor_si512(_mm512_alignr_epi8(c2[195],c2[194],49),_mm512_xor_si512(_mm512_alignr_epi8(c2[210],c2[209],52),_mm512_xor_si512(_mm512_alignr_epi8(c2[210],c2[209],51),_mm512_xor_si512(_mm512_alignr_epi8(c2[205],c2[204],5),_mm512_xor_si512(_mm512_alignr_epi8(c2[205],c2[204],4),_mm512_xor_si512(_mm512_alignr_epi8(c2[207],c2[206],46),_mm512_xor_si512(_mm512_alignr_epi8(c2[207],c2[206],44),_mm512_xor_si512(_mm512_alignr_epi8(c2[207],c2[206],45),_mm512_xor_si512(_mm512_alignr_epi8(c2[218],c2[217],52),_mm512_xor_si512(_mm512_alignr_epi8(c2[218],c2[217],51),_mm512_xor_si512(_mm512_alignr_epi8(c2[218],c2[217],50),_mm512_xor_si512(_mm512_alignr_epi8(c2[218],c2[217],49),_mm512_xor_si512(_mm512_alignr_epi8(c2[219],c2[218],17),_mm512_xor_si512(_mm512_alignr_epi8(c2[219],c2[218],15),_mm512_xor_si512(_mm512_alignr_epi8(c2[219],c2[218],16),_mm512_xor_si512(_mm512_alignr_epi8(c2[229],c2[228],54),_mm512_xor_si512(_mm512_alignr_epi8(c2[229],c2[228],53),_mm512_xor_si512(_mm512_alignr_epi8(c2[232],c2[231],13),_mm512_xor_si512(_mm512_alignr_epi8(c2[232],c2[231],12),_mm512_xor_si512(_mm512_alignr_epi8(c2[230],c2[229],15),_mm512_xor_si512(_mm512_alignr_epi8(c2[230],c2[229],14),_mm512_xor_si512(_mm512_alignr_epi8(c2[244],c2[243],12),_mm512_xor_si512(_mm512_alignr_epi8(c2[244],c2[243],11),_mm512_xor_si512(_mm512_alignr_epi8(c2[245],c2[244],15),_mm512_xor_si512(_mm512_alignr_epi8(c2[245],c2[244],14),_mm512_xor_si512(_mm512_alignr_epi8(c2[245],c2[244],41),_mm512_xor_si512(_mm512_alignr_epi8(c2[245],c2[244],39),_mm512_xor_si512(_mm512_alignr_epi8(c2[245],c2[244],40),_mm512_xor_si512(_mm512_alignr_epi8(c2[256],c2[255],28),_mm512_xor_si512(_mm512_alignr_epi8(c2[256],c2[255],27),_mm512_xor_si512(_mm512_alignr_epi8(c2[258],c2[257],50),_mm512_xor_si512(_mm512_alignr_epi8(c2[258],c2[257],49),_mm512_xor_si512(_mm512_alignr_epi8(c2[256],c2[255],39),_mm512_xor_si512(_mm512_alignr_epi8(c2[256],c2[255],37),_mm512_alignr_epi8(c2[256],c2[255],38))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 32 + d2[192]=_mm512_xor_si512(_mm512_alignr_epi8(c2[4],c2[3],19),_mm512_xor_si512(_mm512_alignr_epi8(c2[6],c2[5],44),_mm512_xor_si512(_mm512_alignr_epi8(c2[2],c2[1],44),_mm512_xor_si512(_mm512_alignr_epi8(c2[2],c2[1],45),_mm512_xor_si512(_mm512_alignr_epi8(c2[3],c2[2],51),_mm512_xor_si512(_mm512_alignr_epi8(c2[3],c2[2],52),_mm512_xor_si512(_mm512_alignr_epi8(c2[2],c2[1],38),_mm512_xor_si512(_mm512_alignr_epi8(c2[17],c2[16],51),_mm512_xor_si512(_mm512_alignr_epi8(c2[15],c2[14],25),_mm512_xor_si512(_mm512_alignr_epi8(c2[15],c2[14],26),_mm512_xor_si512(_mm512_alignr_epi8(c2[18],c2[17],54),_mm512_xor_si512(_mm512_alignr_epi8(c2[18],c2[17],55),_mm512_xor_si512(_mm512_alignr_epi8(c2[30],c2[29],18),_mm512_xor_si512(_mm512_alignr_epi8(c2[30],c2[29],44),_mm512_xor_si512(_mm512_alignr_epi8(c2[28],c2[27],39),_mm512_xor_si512(_mm512_alignr_epi8(c2[28],c2[27],40),_mm512_xor_si512(_mm512_alignr_epi8(c2[41],c2[40],17),_mm512_xor_si512(_mm512_alignr_epi8(c2[42],c2[41],41),_mm512_xor_si512(_mm512_alignr_epi8(c2[41],c2[40],31),_mm512_xor_si512(_mm512_alignr_epi8(c2[41],c2[40],32),_mm512_xor_si512(c2[51],_mm512_xor_si512(_mm512_alignr_epi8(c2[52],c2[51],43),_mm512_xor_si512(_mm512_alignr_epi8(c2[52],c2[51],44),_mm512_xor_si512(_mm512_alignr_epi8(c2[51],c2[50],50),_mm512_xor_si512(_mm512_alignr_epi8(c2[51],c2[50],51),_mm512_xor_si512(_mm512_alignr_epi8(c2[62],c2[61],21),_mm512_xor_si512(_mm512_alignr_epi8(c2[61],c2[60],48),_mm512_xor_si512(_mm512_alignr_epi8(c2[63],c2[62],31),_mm512_xor_si512(_mm512_alignr_epi8(c2[63],c2[62],32),_mm512_xor_si512(_mm512_alignr_epi8(c2[74],c2[73],56),_mm512_xor_si512(c2[73],_mm512_xor_si512(_mm512_alignr_epi8(c2[74],c2[73],1),_mm512_xor_si512(_mm512_alignr_epi8(c2[74],c2[73],38),_mm512_xor_si512(_mm512_alignr_epi8(c2[74],c2[73],39),_mm512_xor_si512(_mm512_alignr_epi8(c2[88],c2[87],43),_mm512_xor_si512(_mm512_alignr_epi8(c2[87],c2[86],42),_mm512_xor_si512(_mm512_alignr_epi8(c2[87],c2[86],43),_mm512_xor_si512(_mm512_alignr_epi8(c2[85],c2[84],56),_mm512_xor_si512(_mm512_alignr_epi8(c2[85],c2[84],57),_mm512_xor_si512(_mm512_alignr_epi8(c2[100],c2[99],43),_mm512_xor_si512(_mm512_alignr_epi8(c2[97],c2[96],63),_mm512_xor_si512(c2[97],_mm512_xor_si512(_mm512_alignr_epi8(c2[102],c2[101],23),_mm512_xor_si512(_mm512_alignr_epi8(c2[102],c2[101],24),_mm512_xor_si512(_mm512_alignr_epi8(c2[112],c2[111],29),_mm512_xor_si512(_mm512_alignr_epi8(c2[110],c2[109],18),_mm512_xor_si512(_mm512_alignr_epi8(c2[114],c2[113],30),_mm512_xor_si512(_mm512_alignr_epi8(c2[114],c2[113],31),_mm512_xor_si512(c2[123],_mm512_xor_si512(_mm512_alignr_epi8(c2[121],c2[120],32),_mm512_xor_si512(_mm512_alignr_epi8(c2[121],c2[120],33),_mm512_xor_si512(_mm512_alignr_epi8(c2[121],c2[120],35),_mm512_xor_si512(_mm512_alignr_epi8(c2[121],c2[120],36),_mm512_xor_si512(_mm512_alignr_epi8(c2[133],c2[132],13),_mm512_xor_si512(_mm512_alignr_epi8(c2[136],c2[135],7),_mm512_xor_si512(_mm512_alignr_epi8(c2[136],c2[135],16),_mm512_xor_si512(_mm512_alignr_epi8(c2[136],c2[135],17),_mm512_xor_si512(_mm512_alignr_epi8(c2[149],c2[148],49),_mm512_xor_si512(_mm512_alignr_epi8(c2[148],c2[147],54),_mm512_xor_si512(_mm512_alignr_epi8(c2[147],c2[146],6),_mm512_xor_si512(_mm512_alignr_epi8(c2[147],c2[146],7),_mm512_xor_si512(_mm512_alignr_epi8(c2[148],c2[147],9),_mm512_xor_si512(_mm512_alignr_epi8(c2[161],c2[160],5),_mm512_xor_si512(_mm512_alignr_epi8(c2[158],c2[157],39),_mm512_xor_si512(_mm512_alignr_epi8(c2[158],c2[157],40),_mm512_xor_si512(_mm512_alignr_epi8(c2[160],c2[159],52),_mm512_xor_si512(_mm512_alignr_epi8(c2[160],c2[159],53),_mm512_xor_si512(_mm512_alignr_epi8(c2[170],c2[169],57),_mm512_xor_si512(_mm512_alignr_epi8(c2[174],c2[173],55),_mm512_xor_si512(_mm512_alignr_epi8(c2[174],c2[173],56),_mm512_xor_si512(_mm512_alignr_epi8(c2[170],c2[169],51),_mm512_xor_si512(_mm512_alignr_epi8(c2[170],c2[169],52),_mm512_xor_si512(_mm512_alignr_epi8(c2[171],c2[170],47),_mm512_xor_si512(_mm512_alignr_epi8(c2[182],c2[181],55),_mm512_xor_si512(_mm512_alignr_epi8(c2[181],c2[180],3),_mm512_xor_si512(_mm512_alignr_epi8(c2[186],c2[185],20),_mm512_xor_si512(_mm512_alignr_epi8(c2[186],c2[185],21),_mm512_xor_si512(_mm512_alignr_epi8(c2[193],c2[192],10),_mm512_xor_si512(_mm512_alignr_epi8(c2[197],c2[196],2),_mm512_xor_si512(_mm512_alignr_epi8(c2[196],c2[195],15),_mm512_xor_si512(_mm512_alignr_epi8(c2[196],c2[195],16),_mm512_xor_si512(_mm512_alignr_epi8(c2[205],c2[204],18),_mm512_xor_si512(_mm512_alignr_epi8(c2[205],c2[204],34),_mm512_xor_si512(_mm512_alignr_epi8(c2[205],c2[204],35),_mm512_xor_si512(_mm512_alignr_epi8(c2[208],c2[207],11),_mm512_xor_si512(_mm512_alignr_epi8(c2[208],c2[207],12),_mm512_xor_si512(_mm512_alignr_epi8(c2[219],c2[218],18),_mm512_xor_si512(_mm512_alignr_epi8(c2[219],c2[218],15),_mm512_xor_si512(_mm512_alignr_epi8(c2[219],c2[218],16),_mm512_xor_si512(_mm512_alignr_epi8(c2[219],c2[218],46),_mm512_xor_si512(_mm512_alignr_epi8(c2[219],c2[218],47),_mm512_xor_si512(_mm512_alignr_epi8(c2[230],c2[229],20),_mm512_xor_si512(_mm512_alignr_epi8(c2[232],c2[231],43),_mm512_xor_si512(_mm512_alignr_epi8(c2[230],c2[229],44),_mm512_xor_si512(_mm512_alignr_epi8(c2[230],c2[229],45),_mm512_xor_si512(_mm512_alignr_epi8(c2[244],c2[243],42),_mm512_xor_si512(_mm512_alignr_epi8(c2[245],c2[244],44),_mm512_xor_si512(_mm512_alignr_epi8(c2[245],c2[244],45),_mm512_xor_si512(_mm512_alignr_epi8(c2[246],c2[245],6),_mm512_xor_si512(_mm512_alignr_epi8(c2[246],c2[245],7),_mm512_xor_si512(_mm512_alignr_epi8(c2[256],c2[255],58),_mm512_xor_si512(_mm512_alignr_epi8(c2[253],c2[252],16),_mm512_xor_si512(_mm512_alignr_epi8(c2[257],c2[256],4),_mm512_alignr_epi8(c2[257],c2[256],5)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 33 + d2[198]=_mm512_xor_si512(_mm512_alignr_epi8(c2[18],c2[17],3),_mm512_xor_si512(_mm512_alignr_epi8(c2[25],c2[24],8),_mm512_xor_si512(_mm512_alignr_epi8(c2[138],c2[137],41),_mm512_alignr_epi8(c2[254],c2[253],41)))); + +//row: 34 + d2[204]=_mm512_xor_si512(_mm512_alignr_epi8(c2[4],c2[3],38),_mm512_xor_si512(_mm512_alignr_epi8(c2[87],c2[86],20),_mm512_xor_si512(_mm512_alignr_epi8(c2[184],c2[183],10),_mm512_alignr_epi8(c2[209],c2[208],56)))); + +//row: 35 + d2[210]=_mm512_xor_si512(_mm512_alignr_epi8(c2[3],c2[2],61),_mm512_xor_si512(_mm512_alignr_epi8(c2[6],c2[5],22),_mm512_xor_si512(_mm512_alignr_epi8(c2[2],c2[1],23),_mm512_xor_si512(_mm512_alignr_epi8(c2[3],c2[2],30),_mm512_xor_si512(_mm512_alignr_epi8(c2[17],c2[16],29),_mm512_xor_si512(_mm512_alignr_epi8(c2[15],c2[14],4),_mm512_xor_si512(_mm512_alignr_epi8(c2[18],c2[17],33),_mm512_xor_si512(c2[17],_mm512_xor_si512(_mm512_alignr_epi8(c2[29],c2[28],60),_mm512_xor_si512(_mm512_alignr_epi8(c2[30],c2[29],22),_mm512_xor_si512(_mm512_alignr_epi8(c2[28],c2[27],18),_mm512_xor_si512(_mm512_alignr_epi8(c2[40],c2[39],59),_mm512_xor_si512(_mm512_alignr_epi8(c2[42],c2[41],19),_mm512_xor_si512(_mm512_alignr_epi8(c2[41],c2[40],10),_mm512_xor_si512(_mm512_alignr_epi8(c2[51],c2[50],42),_mm512_xor_si512(_mm512_alignr_epi8(c2[52],c2[51],22),_mm512_xor_si512(_mm512_alignr_epi8(c2[51],c2[50],29),_mm512_xor_si512(_mm512_alignr_epi8(c2[61],c2[60],63),_mm512_xor_si512(_mm512_alignr_epi8(c2[61],c2[60],26),_mm512_xor_si512(_mm512_alignr_epi8(c2[63],c2[62],10),_mm512_xor_si512(_mm512_alignr_epi8(c2[74],c2[73],34),_mm512_xor_si512(_mm512_alignr_epi8(c2[73],c2[72],43),_mm512_xor_si512(_mm512_alignr_epi8(c2[74],c2[73],17),_mm512_xor_si512(_mm512_alignr_epi8(c2[78],c2[77],15),_mm512_xor_si512(_mm512_alignr_epi8(c2[88],c2[87],21),_mm512_xor_si512(_mm512_alignr_epi8(c2[87],c2[86],21),_mm512_xor_si512(_mm512_alignr_epi8(c2[85],c2[84],35),_mm512_xor_si512(_mm512_alignr_epi8(c2[100],c2[99],21),_mm512_xor_si512(_mm512_alignr_epi8(c2[97],c2[96],42),_mm512_xor_si512(_mm512_alignr_epi8(c2[102],c2[101],2),_mm512_xor_si512(_mm512_alignr_epi8(c2[112],c2[111],7),_mm512_xor_si512(_mm512_alignr_epi8(c2[109],c2[108],60),_mm512_xor_si512(_mm512_alignr_epi8(c2[114],c2[113],9),_mm512_xor_si512(_mm512_alignr_epi8(c2[123],c2[122],42),_mm512_xor_si512(_mm512_alignr_epi8(c2[121],c2[120],11),_mm512_xor_si512(_mm512_alignr_epi8(c2[121],c2[120],14),_mm512_xor_si512(_mm512_alignr_epi8(c2[138],c2[137],55),_mm512_xor_si512(_mm512_alignr_epi8(c2[135],c2[134],49),_mm512_xor_si512(_mm512_alignr_epi8(c2[135],c2[134],59),_mm512_xor_si512(_mm512_alignr_epi8(c2[149],c2[148],27),_mm512_xor_si512(_mm512_alignr_epi8(c2[148],c2[147],32),_mm512_xor_si512(_mm512_alignr_epi8(c2[146],c2[145],49),_mm512_xor_si512(_mm512_alignr_epi8(c2[145],c2[144],2),_mm512_xor_si512(_mm512_alignr_epi8(c2[160],c2[159],47),_mm512_xor_si512(_mm512_alignr_epi8(c2[158],c2[157],18),_mm512_xor_si512(_mm512_alignr_epi8(c2[160],c2[159],31),_mm512_xor_si512(_mm512_alignr_epi8(c2[170],c2[169],35),_mm512_xor_si512(_mm512_alignr_epi8(c2[174],c2[173],34),_mm512_xor_si512(_mm512_alignr_epi8(c2[170],c2[169],30),_mm512_xor_si512(_mm512_alignr_epi8(c2[182],c2[181],33),_mm512_xor_si512(_mm512_alignr_epi8(c2[186],c2[185],45),_mm512_xor_si512(_mm512_alignr_epi8(c2[185],c2[184],63),_mm512_xor_si512(_mm512_alignr_epi8(c2[198],c2[197],52),_mm512_xor_si512(_mm512_alignr_epi8(c2[196],c2[195],44),_mm512_xor_si512(_mm512_alignr_epi8(c2[195],c2[194],58),_mm512_xor_si512(_mm512_alignr_epi8(c2[210],c2[209],60),_mm512_xor_si512(_mm512_alignr_epi8(c2[205],c2[204],13),_mm512_xor_si512(_mm512_alignr_epi8(c2[207],c2[206],54),_mm512_xor_si512(_mm512_alignr_epi8(c2[218],c2[217],60),_mm512_xor_si512(_mm512_alignr_epi8(c2[218],c2[217],58),_mm512_xor_si512(_mm512_alignr_epi8(c2[219],c2[218],25),_mm512_xor_si512(_mm512_alignr_epi8(c2[229],c2[228],62),_mm512_xor_si512(_mm512_alignr_epi8(c2[232],c2[231],21),_mm512_xor_si512(_mm512_alignr_epi8(c2[230],c2[229],23),_mm512_xor_si512(_mm512_alignr_epi8(c2[244],c2[243],20),_mm512_xor_si512(_mm512_alignr_epi8(c2[245],c2[244],23),_mm512_xor_si512(_mm512_alignr_epi8(c2[245],c2[244],49),_mm512_xor_si512(_mm512_alignr_epi8(c2[256],c2[255],36),_mm512_xor_si512(_mm512_alignr_epi8(c2[258],c2[257],58),_mm512_alignr_epi8(c2[256],c2[255],47)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 36 + d2[216]=_mm512_xor_si512(_mm512_alignr_epi8(c2[4],c2[3],18),_mm512_xor_si512(_mm512_alignr_epi8(c2[173],c2[172],57),_mm512_xor_si512(_mm512_alignr_epi8(c2[185],c2[184],41),_mm512_alignr_epi8(c2[217],c2[216],21)))); + +//row: 37 + d2[222]=_mm512_xor_si512(_mm512_alignr_epi8(c2[1],c2[0],38),_mm512_xor_si512(_mm512_alignr_epi8(c2[1],c2[0],39),_mm512_xor_si512(c2[3],_mm512_xor_si512(_mm512_alignr_epi8(c2[6],c2[5],1),_mm512_xor_si512(_mm512_alignr_epi8(c2[1],c2[0],8),_mm512_xor_si512(_mm512_alignr_epi8(c2[15],c2[14],6),_mm512_xor_si512(_mm512_alignr_epi8(c2[15],c2[14],7),_mm512_xor_si512(_mm512_alignr_epi8(c2[18],c2[17],46),_mm512_xor_si512(_mm512_alignr_epi8(c2[16],c2[15],11),_mm512_xor_si512(_mm512_alignr_epi8(c2[17],c2[16],13),_mm512_xor_si512(_mm512_alignr_epi8(c2[27],c2[26],37),_mm512_xor_si512(_mm512_alignr_epi8(c2[27],c2[26],38),_mm512_xor_si512(c2[27],_mm512_xor_si512(_mm512_alignr_epi8(c2[25],c2[24],60),_mm512_xor_si512(_mm512_alignr_epi8(c2[38],c2[37],36),_mm512_xor_si512(_mm512_alignr_epi8(c2[38],c2[37],37),_mm512_xor_si512(_mm512_alignr_epi8(c2[39],c2[38],61),_mm512_xor_si512(_mm512_alignr_epi8(c2[38],c2[37],52),_mm512_xor_si512(_mm512_alignr_epi8(c2[49],c2[48],20),_mm512_xor_si512(c2[49],_mm512_xor_si512(_mm512_alignr_epi8(c2[49],c2[48],7),_mm512_xor_si512(_mm512_alignr_epi8(c2[65],c2[64],40),_mm512_xor_si512(_mm512_alignr_epi8(c2[65],c2[64],41),_mm512_xor_si512(_mm512_alignr_epi8(c2[65],c2[64],4),_mm512_xor_si512(_mm512_alignr_epi8(c2[66],c2[65],52),_mm512_xor_si512(_mm512_alignr_epi8(c2[78],c2[77],11),_mm512_xor_si512(_mm512_alignr_epi8(c2[78],c2[77],12),_mm512_xor_si512(_mm512_alignr_epi8(c2[77],c2[76],21),_mm512_xor_si512(_mm512_alignr_epi8(c2[77],c2[76],59),_mm512_xor_si512(_mm512_alignr_epi8(c2[85],c2[84],63),_mm512_xor_si512(_mm512_alignr_epi8(c2[90],c2[89],63),_mm512_xor_si512(_mm512_alignr_epi8(c2[89],c2[88],13),_mm512_xor_si512(_mm512_alignr_epi8(c2[97],c2[96],63),_mm512_xor_si512(_mm512_alignr_epi8(c2[101],c2[100],20),_mm512_xor_si512(_mm512_alignr_epi8(c2[99],c2[98],44),_mm512_xor_si512(_mm512_alignr_epi8(c2[109],c2[108],48),_mm512_xor_si512(_mm512_alignr_epi8(c2[109],c2[108],49),_mm512_xor_si512(_mm512_alignr_epi8(c2[113],c2[112],38),_mm512_xor_si512(_mm512_alignr_epi8(c2[111],c2[110],51),_mm512_xor_si512(_mm512_alignr_epi8(c2[121],c2[120],19),_mm512_xor_si512(_mm512_alignr_epi8(c2[121],c2[120],20),_mm512_xor_si512(_mm512_alignr_epi8(c2[124],c2[123],53),_mm512_xor_si512(_mm512_alignr_epi8(c2[124],c2[123],56),_mm512_xor_si512(_mm512_alignr_epi8(c2[136],c2[135],32),_mm512_xor_si512(_mm512_alignr_epi8(c2[136],c2[135],33),_mm512_xor_si512(_mm512_alignr_epi8(c2[133],c2[132],27),_mm512_xor_si512(_mm512_alignr_epi8(c2[133],c2[132],37),_mm512_xor_si512(_mm512_alignr_epi8(c2[147],c2[146],4),_mm512_xor_si512(_mm512_alignr_epi8(c2[147],c2[146],5),_mm512_xor_si512(_mm512_alignr_epi8(c2[146],c2[145],10),_mm512_xor_si512(_mm512_alignr_epi8(c2[150],c2[149],27),_mm512_xor_si512(_mm512_alignr_epi8(c2[158],c2[157],24),_mm512_xor_si512(_mm512_alignr_epi8(c2[158],c2[157],25),_mm512_xor_si512(_mm512_alignr_epi8(c2[161],c2[160],60),_mm512_xor_si512(_mm512_alignr_epi8(c2[158],c2[157],9),_mm512_xor_si512(_mm512_alignr_epi8(c2[158],c2[157],18),_mm512_xor_si512(_mm512_alignr_epi8(c2[174],c2[173],13),_mm512_xor_si512(_mm512_alignr_epi8(c2[172],c2[171],12),_mm512_xor_si512(_mm512_alignr_epi8(c2[174],c2[173],8),_mm512_xor_si512(_mm512_alignr_epi8(c2[186],c2[185],10),_mm512_xor_si512(_mm512_alignr_epi8(c2[186],c2[185],11),_mm512_xor_si512(_mm512_alignr_epi8(c2[184],c2[183],23),_mm512_xor_si512(_mm512_alignr_epi8(c2[183],c2[182],41),_mm512_xor_si512(_mm512_alignr_epi8(c2[196],c2[195],29),_mm512_xor_si512(_mm512_alignr_epi8(c2[196],c2[195],30),_mm512_xor_si512(_mm512_alignr_epi8(c2[194],c2[193],22),_mm512_xor_si512(_mm512_alignr_epi8(c2[193],c2[192],36),_mm512_xor_si512(_mm512_alignr_epi8(c2[208],c2[207],38),_mm512_xor_si512(_mm512_alignr_epi8(c2[208],c2[207],55),_mm512_xor_si512(_mm512_alignr_epi8(c2[205],c2[204],32),_mm512_xor_si512(_mm512_alignr_epi8(c2[222],c2[221],37),_mm512_xor_si512(_mm512_alignr_epi8(c2[222],c2[221],38),_mm512_xor_si512(_mm512_alignr_epi8(c2[222],c2[221],36),_mm512_xor_si512(_mm512_alignr_epi8(c2[217],c2[216],3),_mm512_xor_si512(_mm512_alignr_epi8(c2[233],c2[232],39),_mm512_xor_si512(_mm512_alignr_epi8(c2[233],c2[232],40),_mm512_xor_si512(_mm512_alignr_epi8(c2[229],c2[228],63),_mm512_xor_si512(_mm512_alignr_epi8(c2[234],c2[233],1),_mm512_xor_si512(_mm512_alignr_epi8(c2[241],c2[240],61),_mm512_xor_si512(_mm512_alignr_epi8(c2[241],c2[240],62),_mm512_xor_si512(_mm512_alignr_epi8(c2[243],c2[242],1),_mm512_xor_si512(_mm512_alignr_epi8(c2[243],c2[242],27),_mm512_xor_si512(_mm512_alignr_epi8(c2[254],c2[253],13),_mm512_xor_si512(_mm512_alignr_epi8(c2[254],c2[253],14),_mm512_xor_si512(_mm512_alignr_epi8(c2[256],c2[255],36),_mm512_alignr_epi8(c2[254],c2[253],25)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 38 + d2[228]=_mm512_xor_si512(_mm512_alignr_epi8(c2[3],c2[2],57),_mm512_xor_si512(_mm512_alignr_epi8(c2[111],c2[110],49),_mm512_xor_si512(_mm512_alignr_epi8(c2[125],c2[124],33),_mm512_alignr_epi8(c2[148],c2[147],22)))); + +//row: 39 + d2[234]=_mm512_xor_si512(_mm512_alignr_epi8(c2[17],c2[16],2),_mm512_xor_si512(_mm512_alignr_epi8(c2[38],c2[37],29),_mm512_xor_si512(_mm512_alignr_epi8(c2[90],c2[89],26),_mm512_alignr_epi8(c2[233],c2[232],41)))); + +//row: 40 + d2[240]=_mm512_xor_si512(_mm512_alignr_epi8(c2[3],c2[2],47),_mm512_xor_si512(_mm512_alignr_epi8(c2[97],c2[96],37),_mm512_alignr_epi8(c2[209],c2[208],56))); + +//row: 41 + d2[246]=_mm512_xor_si512(_mm512_alignr_epi8(c2[13],c2[12],52),_mm512_xor_si512(_mm512_alignr_epi8(c2[41],c2[40],58),_mm512_xor_si512(_mm512_alignr_epi8(c2[111],c2[110],11),_mm512_alignr_epi8(c2[221],c2[220],32)))); + +//row: 42 + d2[252]=_mm512_xor_si512(_mm512_alignr_epi8(c2[3],c2[2],14),_mm512_xor_si512(_mm512_alignr_epi8(c2[5],c2[4],39),_mm512_xor_si512(_mm512_alignr_epi8(c2[1],c2[0],39),_mm512_xor_si512(_mm512_alignr_epi8(c2[1],c2[0],40),_mm512_xor_si512(_mm512_alignr_epi8(c2[2],c2[1],46),_mm512_xor_si512(_mm512_alignr_epi8(c2[2],c2[1],47),_mm512_xor_si512(_mm512_alignr_epi8(c2[2],c2[1],49),_mm512_xor_si512(_mm512_alignr_epi8(c2[16],c2[15],46),_mm512_xor_si512(_mm512_alignr_epi8(c2[14],c2[13],20),_mm512_xor_si512(_mm512_alignr_epi8(c2[14],c2[13],21),_mm512_xor_si512(_mm512_alignr_epi8(c2[17],c2[16],49),_mm512_xor_si512(_mm512_alignr_epi8(c2[17],c2[16],50),_mm512_xor_si512(_mm512_alignr_epi8(c2[29],c2[28],13),_mm512_xor_si512(_mm512_alignr_epi8(c2[29],c2[28],39),_mm512_xor_si512(_mm512_alignr_epi8(c2[27],c2[26],34),_mm512_xor_si512(_mm512_alignr_epi8(c2[27],c2[26],35),_mm512_xor_si512(_mm512_alignr_epi8(c2[40],c2[39],12),_mm512_xor_si512(_mm512_alignr_epi8(c2[41],c2[40],36),_mm512_xor_si512(_mm512_alignr_epi8(c2[40],c2[39],26),_mm512_xor_si512(_mm512_alignr_epi8(c2[40],c2[39],27),_mm512_xor_si512(_mm512_alignr_epi8(c2[50],c2[49],59),_mm512_xor_si512(_mm512_alignr_epi8(c2[51],c2[50],38),_mm512_xor_si512(_mm512_alignr_epi8(c2[51],c2[50],39),_mm512_xor_si512(_mm512_alignr_epi8(c2[50],c2[49],45),_mm512_xor_si512(_mm512_alignr_epi8(c2[50],c2[49],46),_mm512_xor_si512(_mm512_alignr_epi8(c2[49],c2[48],14),_mm512_xor_si512(_mm512_alignr_epi8(c2[61],c2[60],16),_mm512_xor_si512(_mm512_alignr_epi8(c2[66],c2[65],43),_mm512_xor_si512(_mm512_alignr_epi8(c2[62],c2[61],26),_mm512_xor_si512(_mm512_alignr_epi8(c2[62],c2[61],27),_mm512_xor_si512(_mm512_alignr_epi8(c2[73],c2[72],51),_mm512_xor_si512(_mm512_alignr_epi8(c2[78],c2[77],59),_mm512_xor_si512(_mm512_alignr_epi8(c2[78],c2[77],60),_mm512_xor_si512(_mm512_alignr_epi8(c2[73],c2[72],33),_mm512_xor_si512(_mm512_alignr_epi8(c2[73],c2[72],34),_mm512_xor_si512(_mm512_alignr_epi8(c2[87],c2[86],38),_mm512_xor_si512(_mm512_alignr_epi8(c2[86],c2[85],37),_mm512_xor_si512(_mm512_alignr_epi8(c2[86],c2[85],38),_mm512_xor_si512(_mm512_alignr_epi8(c2[90],c2[89],51),_mm512_xor_si512(_mm512_alignr_epi8(c2[90],c2[89],52),_mm512_xor_si512(_mm512_alignr_epi8(c2[99],c2[98],38),_mm512_xor_si512(_mm512_alignr_epi8(c2[102],c2[101],58),_mm512_xor_si512(_mm512_alignr_epi8(c2[102],c2[101],59),_mm512_xor_si512(_mm512_alignr_epi8(c2[101],c2[100],18),_mm512_xor_si512(_mm512_alignr_epi8(c2[101],c2[100],19),_mm512_xor_si512(_mm512_alignr_epi8(c2[111],c2[110],24),_mm512_xor_si512(_mm512_alignr_epi8(c2[109],c2[108],13),_mm512_xor_si512(_mm512_alignr_epi8(c2[113],c2[112],25),_mm512_xor_si512(_mm512_alignr_epi8(c2[113],c2[112],26),_mm512_xor_si512(_mm512_alignr_epi8(c2[122],c2[121],59),_mm512_xor_si512(_mm512_alignr_epi8(c2[126],c2[125],27),_mm512_xor_si512(_mm512_alignr_epi8(c2[126],c2[125],28),_mm512_xor_si512(_mm512_alignr_epi8(c2[126],c2[125],30),_mm512_xor_si512(_mm512_alignr_epi8(c2[126],c2[125],31),_mm512_xor_si512(_mm512_alignr_epi8(c2[138],c2[137],8),_mm512_xor_si512(_mm512_alignr_epi8(c2[135],c2[134],2),_mm512_xor_si512(_mm512_alignr_epi8(c2[135],c2[134],11),_mm512_xor_si512(_mm512_alignr_epi8(c2[135],c2[134],12),_mm512_xor_si512(_mm512_alignr_epi8(c2[148],c2[147],44),_mm512_xor_si512(_mm512_alignr_epi8(c2[147],c2[146],49),_mm512_xor_si512(_mm512_alignr_epi8(c2[146],c2[145],1),_mm512_xor_si512(_mm512_alignr_epi8(c2[146],c2[145],2),_mm512_xor_si512(c2[159],_mm512_xor_si512(_mm512_alignr_epi8(c2[157],c2[156],34),_mm512_xor_si512(_mm512_alignr_epi8(c2[157],c2[156],35),_mm512_xor_si512(_mm512_alignr_epi8(c2[159],c2[158],47),_mm512_xor_si512(_mm512_alignr_epi8(c2[159],c2[158],48),_mm512_xor_si512(_mm512_alignr_epi8(c2[169],c2[168],52),_mm512_xor_si512(_mm512_alignr_epi8(c2[173],c2[172],50),_mm512_xor_si512(_mm512_alignr_epi8(c2[173],c2[172],51),_mm512_xor_si512(_mm512_alignr_epi8(c2[169],c2[168],46),_mm512_xor_si512(_mm512_alignr_epi8(c2[169],c2[168],47),_mm512_xor_si512(_mm512_alignr_epi8(c2[181],c2[180],50),_mm512_xor_si512(_mm512_alignr_epi8(c2[185],c2[184],62),_mm512_xor_si512(_mm512_alignr_epi8(c2[185],c2[184],15),_mm512_xor_si512(_mm512_alignr_epi8(c2[185],c2[184],16),_mm512_xor_si512(_mm512_alignr_epi8(c2[198],c2[197],5),_mm512_xor_si512(_mm512_alignr_epi8(c2[195],c2[194],61),_mm512_xor_si512(_mm512_alignr_epi8(c2[195],c2[194],10),_mm512_xor_si512(_mm512_alignr_epi8(c2[195],c2[194],11),_mm512_xor_si512(_mm512_alignr_epi8(c2[210],c2[209],13),_mm512_xor_si512(_mm512_alignr_epi8(c2[210],c2[209],29),_mm512_xor_si512(_mm512_alignr_epi8(c2[210],c2[209],30),_mm512_xor_si512(_mm512_alignr_epi8(c2[207],c2[206],6),_mm512_xor_si512(_mm512_alignr_epi8(c2[207],c2[206],7),_mm512_xor_si512(_mm512_alignr_epi8(c2[218],c2[217],13),_mm512_xor_si512(_mm512_alignr_epi8(c2[218],c2[217],10),_mm512_xor_si512(_mm512_alignr_epi8(c2[218],c2[217],11),_mm512_xor_si512(_mm512_alignr_epi8(c2[218],c2[217],41),_mm512_xor_si512(_mm512_alignr_epi8(c2[218],c2[217],42),_mm512_xor_si512(_mm512_alignr_epi8(c2[229],c2[228],15),_mm512_xor_si512(_mm512_alignr_epi8(c2[231],c2[230],38),_mm512_xor_si512(_mm512_alignr_epi8(c2[229],c2[228],39),_mm512_xor_si512(_mm512_alignr_epi8(c2[229],c2[228],40),_mm512_xor_si512(_mm512_alignr_epi8(c2[243],c2[242],37),_mm512_xor_si512(_mm512_alignr_epi8(c2[244],c2[243],39),_mm512_xor_si512(_mm512_alignr_epi8(c2[244],c2[243],40),_mm512_xor_si512(_mm512_alignr_epi8(c2[245],c2[244],1),_mm512_xor_si512(_mm512_alignr_epi8(c2[245],c2[244],2),_mm512_xor_si512(_mm512_alignr_epi8(c2[255],c2[254],53),_mm512_xor_si512(_mm512_alignr_epi8(c2[258],c2[257],11),_mm512_xor_si512(_mm512_alignr_epi8(c2[255],c2[254],63),c2[255])))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 43 + d2[258]=_mm512_xor_si512(_mm512_alignr_epi8(c2[2],c2[1],28),_mm512_xor_si512(_mm512_alignr_epi8(c2[4],c2[3],53),_mm512_xor_si512(_mm512_alignr_epi8(c2[6],c2[5],54),_mm512_xor_si512(_mm512_alignr_epi8(c2[1],c2[0],60),_mm512_xor_si512(_mm512_alignr_epi8(c2[1],c2[0],61),_mm512_xor_si512(_mm512_alignr_epi8(c2[15],c2[14],60),_mm512_xor_si512(_mm512_alignr_epi8(c2[13],c2[12],35),_mm512_xor_si512(_mm512_alignr_epi8(c2[16],c2[15],63),_mm512_xor_si512(c2[16],_mm512_xor_si512(_mm512_alignr_epi8(c2[14],c2[13],49),_mm512_xor_si512(_mm512_alignr_epi8(c2[28],c2[27],27),_mm512_xor_si512(_mm512_alignr_epi8(c2[28],c2[27],53),_mm512_xor_si512(_mm512_alignr_epi8(c2[26],c2[25],49),_mm512_xor_si512(_mm512_alignr_epi8(c2[39],c2[38],26),_mm512_xor_si512(_mm512_alignr_epi8(c2[40],c2[39],50),_mm512_xor_si512(_mm512_alignr_epi8(c2[39],c2[38],40),_mm512_xor_si512(_mm512_alignr_epi8(c2[39],c2[38],41),_mm512_xor_si512(_mm512_alignr_epi8(c2[50],c2[49],9),_mm512_xor_si512(_mm512_alignr_epi8(c2[50],c2[49],53),_mm512_xor_si512(_mm512_alignr_epi8(c2[49],c2[48],59),_mm512_xor_si512(_mm512_alignr_epi8(c2[49],c2[48],60),_mm512_xor_si512(_mm512_alignr_epi8(c2[66],c2[65],30),_mm512_xor_si512(_mm512_alignr_epi8(c2[65],c2[64],57),_mm512_xor_si512(_mm512_alignr_epi8(c2[61],c2[60],41),_mm512_xor_si512(_mm512_alignr_epi8(c2[73],c2[72],1),_mm512_xor_si512(_mm512_alignr_epi8(c2[78],c2[77],10),_mm512_xor_si512(_mm512_alignr_epi8(c2[78],c2[77],47),_mm512_xor_si512(_mm512_alignr_epi8(c2[78],c2[77],48),_mm512_xor_si512(_mm512_alignr_epi8(c2[86],c2[85],52),_mm512_xor_si512(_mm512_alignr_epi8(c2[85],c2[84],52),_mm512_xor_si512(_mm512_alignr_epi8(c2[90],c2[89],1),_mm512_xor_si512(_mm512_alignr_epi8(c2[90],c2[89],2),_mm512_xor_si512(_mm512_alignr_epi8(c2[98],c2[97],52),_mm512_xor_si512(_mm512_alignr_epi8(c2[102],c2[101],9),_mm512_xor_si512(_mm512_alignr_epi8(c2[100],c2[99],32),_mm512_xor_si512(_mm512_alignr_epi8(c2[100],c2[99],33),_mm512_xor_si512(_mm512_alignr_epi8(c2[110],c2[109],38),_mm512_xor_si512(_mm512_alignr_epi8(c2[114],c2[113],27),_mm512_xor_si512(_mm512_alignr_epi8(c2[112],c2[111],40),_mm512_xor_si512(_mm512_alignr_epi8(c2[122],c2[121],9),_mm512_xor_si512(_mm512_alignr_epi8(c2[125],c2[124],42),_mm512_xor_si512(_mm512_alignr_epi8(c2[125],c2[124],44),_mm512_xor_si512(_mm512_alignr_epi8(c2[125],c2[124],45),_mm512_xor_si512(_mm512_alignr_epi8(c2[137],c2[136],22),_mm512_xor_si512(_mm512_alignr_epi8(c2[134],c2[133],16),_mm512_xor_si512(_mm512_alignr_epi8(c2[134],c2[133],25),_mm512_xor_si512(_mm512_alignr_epi8(c2[134],c2[133],26),_mm512_xor_si512(_mm512_alignr_epi8(c2[147],c2[146],58),_mm512_xor_si512(_mm512_alignr_epi8(c2[146],c2[145],63),_mm512_xor_si512(_mm512_alignr_epi8(c2[145],c2[144],15),_mm512_xor_si512(_mm512_alignr_epi8(c2[145],c2[144],16),_mm512_xor_si512(_mm512_alignr_epi8(c2[159],c2[158],14),_mm512_xor_si512(_mm512_alignr_epi8(c2[162],c2[161],49),_mm512_xor_si512(_mm512_alignr_epi8(c2[158],c2[157],61),_mm512_xor_si512(_mm512_alignr_epi8(c2[158],c2[157],62),_mm512_xor_si512(_mm512_alignr_epi8(c2[169],c2[168],2),_mm512_xor_si512(_mm512_alignr_epi8(c2[173],c2[172],1),_mm512_xor_si512(_mm512_alignr_epi8(c2[174],c2[173],60),_mm512_xor_si512(_mm512_alignr_epi8(c2[174],c2[173],61),_mm512_xor_si512(c2[180],_mm512_xor_si512(_mm512_alignr_epi8(c2[185],c2[184],12),_mm512_xor_si512(_mm512_alignr_epi8(c2[184],c2[183],30),_mm512_xor_si512(_mm512_alignr_epi8(c2[197],c2[196],19),_mm512_xor_si512(_mm512_alignr_epi8(c2[195],c2[194],11),_mm512_xor_si512(_mm512_alignr_epi8(c2[194],c2[193],24),_mm512_xor_si512(_mm512_alignr_epi8(c2[194],c2[193],25),_mm512_xor_si512(_mm512_alignr_epi8(c2[195],c2[194],4),_mm512_xor_si512(_mm512_alignr_epi8(c2[209],c2[208],27),_mm512_xor_si512(_mm512_alignr_epi8(c2[209],c2[208],44),_mm512_xor_si512(_mm512_alignr_epi8(c2[206],c2[205],20),_mm512_xor_si512(_mm512_alignr_epi8(c2[206],c2[205],21),_mm512_xor_si512(_mm512_alignr_epi8(c2[217],c2[216],27),_mm512_xor_si512(_mm512_alignr_epi8(c2[217],c2[216],25),_mm512_xor_si512(_mm512_alignr_epi8(c2[217],c2[216],55),_mm512_xor_si512(_mm512_alignr_epi8(c2[217],c2[216],56),_mm512_xor_si512(_mm512_alignr_epi8(c2[218],c2[217],50),_mm512_xor_si512(_mm512_alignr_epi8(c2[234],c2[233],29),_mm512_xor_si512(_mm512_alignr_epi8(c2[230],c2[229],52),_mm512_xor_si512(_mm512_alignr_epi8(c2[234],c2[233],54),_mm512_xor_si512(_mm512_alignr_epi8(c2[242],c2[241],51),_mm512_xor_si512(_mm512_alignr_epi8(c2[243],c2[242],54),_mm512_xor_si512(_mm512_alignr_epi8(c2[244],c2[243],15),_mm512_xor_si512(_mm512_alignr_epi8(c2[244],c2[243],16),_mm512_xor_si512(_mm512_alignr_epi8(c2[255],c2[254],3),_mm512_xor_si512(_mm512_alignr_epi8(c2[257],c2[256],25),_mm512_xor_si512(_mm512_alignr_epi8(c2[255],c2[254],13),_mm512_alignr_epi8(c2[255],c2[254],14))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 44 + d2[264]=_mm512_xor_si512(_mm512_alignr_epi8(c2[4],c2[3],5),_mm512_xor_si512(_mm512_alignr_epi8(c2[6],c2[5],30),_mm512_xor_si512(_mm512_alignr_epi8(c2[2],c2[1],31),_mm512_xor_si512(_mm512_alignr_epi8(c2[3],c2[2],38),_mm512_xor_si512(_mm512_alignr_epi8(c2[2],c2[1],16),_mm512_xor_si512(_mm512_alignr_epi8(c2[17],c2[16],37),_mm512_xor_si512(_mm512_alignr_epi8(c2[15],c2[14],12),_mm512_xor_si512(_mm512_alignr_epi8(c2[18],c2[17],41),_mm512_xor_si512(_mm512_alignr_epi8(c2[30],c2[29],4),_mm512_xor_si512(_mm512_alignr_epi8(c2[30],c2[29],30),_mm512_xor_si512(_mm512_alignr_epi8(c2[28],c2[27],26),_mm512_xor_si512(_mm512_alignr_epi8(c2[41],c2[40],3),_mm512_xor_si512(_mm512_alignr_epi8(c2[42],c2[41],27),_mm512_xor_si512(_mm512_alignr_epi8(c2[41],c2[40],18),_mm512_xor_si512(_mm512_alignr_epi8(c2[51],c2[50],50),_mm512_xor_si512(_mm512_alignr_epi8(c2[52],c2[51],30),_mm512_xor_si512(_mm512_alignr_epi8(c2[51],c2[50],37),_mm512_xor_si512(_mm512_alignr_epi8(c2[62],c2[61],7),_mm512_xor_si512(_mm512_alignr_epi8(c2[61],c2[60],34),_mm512_xor_si512(_mm512_alignr_epi8(c2[63],c2[62],18),_mm512_xor_si512(_mm512_alignr_epi8(c2[74],c2[73],42),_mm512_xor_si512(_mm512_alignr_epi8(c2[73],c2[72],51),_mm512_xor_si512(_mm512_alignr_epi8(c2[74],c2[73],25),_mm512_xor_si512(_mm512_alignr_epi8(c2[88],c2[87],29),_mm512_xor_si512(_mm512_alignr_epi8(c2[87],c2[86],29),_mm512_xor_si512(_mm512_alignr_epi8(c2[85],c2[84],43),_mm512_xor_si512(_mm512_alignr_epi8(c2[86],c2[85],14),_mm512_xor_si512(_mm512_alignr_epi8(c2[100],c2[99],29),_mm512_xor_si512(_mm512_alignr_epi8(c2[97],c2[96],50),_mm512_xor_si512(_mm512_alignr_epi8(c2[102],c2[101],10),_mm512_xor_si512(_mm512_alignr_epi8(c2[112],c2[111],15),_mm512_xor_si512(_mm512_alignr_epi8(c2[110],c2[109],4),_mm512_xor_si512(_mm512_alignr_epi8(c2[114],c2[113],17),_mm512_xor_si512(_mm512_alignr_epi8(c2[111],c2[110],35),_mm512_xor_si512(_mm512_alignr_epi8(c2[123],c2[122],50),_mm512_xor_si512(_mm512_alignr_epi8(c2[121],c2[120],19),_mm512_xor_si512(_mm512_alignr_epi8(c2[121],c2[120],22),_mm512_xor_si512(_mm512_alignr_epi8(c2[138],c2[137],63),_mm512_xor_si512(_mm512_alignr_epi8(c2[135],c2[134],57),_mm512_xor_si512(_mm512_alignr_epi8(c2[136],c2[135],3),_mm512_xor_si512(_mm512_alignr_epi8(c2[149],c2[148],35),_mm512_xor_si512(_mm512_alignr_epi8(c2[148],c2[147],40),_mm512_xor_si512(_mm512_alignr_epi8(c2[146],c2[145],57),_mm512_xor_si512(_mm512_alignr_epi8(c2[160],c2[159],55),_mm512_xor_si512(_mm512_alignr_epi8(c2[158],c2[157],26),_mm512_xor_si512(_mm512_alignr_epi8(c2[160],c2[159],39),_mm512_xor_si512(_mm512_alignr_epi8(c2[170],c2[169],43),_mm512_xor_si512(_mm512_alignr_epi8(c2[174],c2[173],42),_mm512_xor_si512(_mm512_alignr_epi8(c2[170],c2[169],38),_mm512_xor_si512(_mm512_alignr_epi8(c2[182],c2[181],41),_mm512_xor_si512(_mm512_alignr_epi8(c2[186],c2[185],53),_mm512_xor_si512(_mm512_alignr_epi8(c2[186],c2[185],7),_mm512_xor_si512(_mm512_alignr_epi8(c2[198],c2[197],60),_mm512_xor_si512(_mm512_alignr_epi8(c2[196],c2[195],52),_mm512_xor_si512(_mm512_alignr_epi8(c2[196],c2[195],2),_mm512_xor_si512(_mm512_alignr_epi8(c2[205],c2[204],4),_mm512_xor_si512(_mm512_alignr_epi8(c2[205],c2[204],21),_mm512_xor_si512(_mm512_alignr_epi8(c2[207],c2[206],62),_mm512_xor_si512(_mm512_alignr_epi8(c2[219],c2[218],4),_mm512_xor_si512(_mm512_alignr_epi8(c2[219],c2[218],2),_mm512_xor_si512(_mm512_alignr_epi8(c2[219],c2[218],33),_mm512_xor_si512(_mm512_alignr_epi8(c2[230],c2[229],6),_mm512_xor_si512(_mm512_alignr_epi8(c2[232],c2[231],29),_mm512_xor_si512(_mm512_alignr_epi8(c2[230],c2[229],31),_mm512_xor_si512(_mm512_alignr_epi8(c2[244],c2[243],28),_mm512_xor_si512(_mm512_alignr_epi8(c2[245],c2[244],31),_mm512_xor_si512(_mm512_alignr_epi8(c2[245],c2[244],57),_mm512_xor_si512(_mm512_alignr_epi8(c2[256],c2[255],44),_mm512_xor_si512(_mm512_alignr_epi8(c2[253],c2[252],2),_mm512_alignr_epi8(c2[256],c2[255],55)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 45 + d2[270]=_mm512_xor_si512(_mm512_alignr_epi8(c2[15],c2[14],7),_mm512_xor_si512(_mm512_alignr_epi8(c2[75],c2[74],21),_mm512_alignr_epi8(c2[121],c2[120],15))); + } +} diff --git a/openair1/PHY/CODING/nrLDPC_encoder/ldpc384_simd512_permutex_byte.c b/openair1/PHY/CODING/nrLDPC_encoder/ldpc384_simd512_permutex_byte.c new file mode 100644 index 0000000000..d0649a1e88 --- /dev/null +++ b/openair1/PHY/CODING/nrLDPC_encoder/ldpc384_simd512_permutex_byte.c @@ -0,0 +1,218 @@ +#include "PHY/sse_intrin.h" +// generated code for Zc=384, byte encoding + const uint8_t abshift_bytes[64][64] __attribute__((aligned(64)))= { +{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63}, +{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64}, +{2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65}, +{3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66}, +{4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67}, +{5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68}, +{6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69}, +{7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70}, +{8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71}, +{9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72}, +{10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73}, +{11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74}, +{12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75}, +{13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76}, +{14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77}, +{15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78}, +{16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79}, +{17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80}, +{18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81}, +{19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82}, +{20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83}, +{21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84}, +{22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85}, +{23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86}, +{24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87}, +{25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88}, +{26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89}, +{27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90}, +{28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91}, +{29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92}, +{30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93}, +{31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94}, +{32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95}, +{33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96}, +{34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97}, +{35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98}, +{36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99}, +{37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100}, +{38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101}, +{39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102}, +{40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103}, +{41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104}, +{42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105}, +{43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106}, +{44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107}, +{45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108}, +{46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109}, +{47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110}, +{48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111}, +{49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112}, +{50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113}, +{51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114}, +{52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115}, +{53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116}, +{54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117}, +{55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118}, +{56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119}, +{57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120}, +{58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121}, +{59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122}, +{60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123}, +{61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124}, +{62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125}, +{63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126}}; +#define abshift_get(r) (*(const __m512i *) abshift_bytes[r]) + +static void ldpc384_byte(uint8_t *c,uint8_t *d) { + __m512i *csimd=(__m512i *)c,*dsimd=(__m512i *)d; + + __m512i *c2,*d2; + + int i2; + for (i2=0; i2<6; i2++) { + c2=&csimd[i2]; + d2=&dsimd[i2]; + +//row: 0 + d2[0]=_mm512_xor_si512(_mm512_permutex2var_epi8(c2[4],abshift_get(51),c2[5]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[1],abshift_get(12),c2[2]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[3],abshift_get(13),c2[4]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[4],abshift_get(20),c2[5]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[12],abshift_get(19),c2[13]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[15],abshift_get(58),c2[16]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[13],abshift_get(23),c2[14]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[24],abshift_get(50),c2[25]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[25],abshift_get(12),c2[26]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[29],abshift_get(8),c2[30]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[41],abshift_get(49),c2[42]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[37],abshift_get(9),c2[38]),_mm512_xor_si512(c2[36],_mm512_xor_si512(_mm512_permutex2var_epi8(c2[52],abshift_get(32),c2[53]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[53],abshift_get(12),c2[54]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[52],abshift_get(19),c2[53]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[62],abshift_get(53),c2[63]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[62],abshift_get(16),c2[63]),_mm512_xor_si512(c2[64],_mm512_xor_si512(_mm512_permutex2var_epi8(c2[75],abshift_get(24),c2[76]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[74],abshift_get(33),c2[75]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[75],abshift_get(7),c2[76]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[89],abshift_get(11),c2[90]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[88],abshift_get(11),c2[89]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[86],abshift_get(25),c2[87]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[101],abshift_get(11),c2[102]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[98],abshift_get(32),c2[99]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[96],abshift_get(56),c2[97]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[112],abshift_get(61),c2[113]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[110],abshift_get(50),c2[111]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[108],abshift_get(63),c2[109]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[124],abshift_get(32),c2[125]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[122],abshift_get(1),c2[123]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[122],abshift_get(4),c2[123]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[133],abshift_get(45),c2[134]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[136],abshift_get(39),c2[137]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[136],abshift_get(49),c2[137]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[144],abshift_get(17),c2[145]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[149],abshift_get(22),c2[150]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[147],abshift_get(39),c2[148]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[161],abshift_get(37),c2[162]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[159],abshift_get(8),c2[160]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[161],abshift_get(21),c2[162]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[171],abshift_get(25),c2[172]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[169],abshift_get(24),c2[170]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[171],abshift_get(20),c2[172]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[183],abshift_get(23),c2[184]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[181],abshift_get(35),c2[182]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[180],abshift_get(53),c2[181]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[193],abshift_get(42),c2[194]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[197],abshift_get(34),c2[198]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[196],abshift_get(48),c2[197]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[205],abshift_get(50),c2[206]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[206],abshift_get(3),c2[207]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[208],abshift_get(44),c2[209]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[219],abshift_get(50),c2[220]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[219],abshift_get(48),c2[220]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[220],abshift_get(15),c2[221]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[230],abshift_get(52),c2[231]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[233],abshift_get(11),c2[234]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[231],abshift_get(13),c2[232]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[245],abshift_get(10),c2[246]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[240],abshift_get(13),c2[241]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[240],abshift_get(39),c2[241]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[257],abshift_get(26),c2[258]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[253],abshift_get(48),c2[254]),_mm512_permutex2var_epi8(c2[257],abshift_get(37),c2[258]))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 1 + d2[6]=_mm512_xor_si512(_mm512_permutex2var_epi8(c2[4],abshift_get(51),c2[5]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[4],abshift_get(52),c2[5]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[1],abshift_get(13),c2[2]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[3],abshift_get(14),c2[4]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[4],abshift_get(21),c2[5]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[12],abshift_get(19),c2[13]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[12],abshift_get(20),c2[13]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[15],abshift_get(59),c2[16]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[13],abshift_get(24),c2[14]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[24],abshift_get(50),c2[25]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[24],abshift_get(51),c2[25]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[25],abshift_get(13),c2[26]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[29],abshift_get(9),c2[30]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[41],abshift_get(49),c2[42]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[41],abshift_get(50),c2[42]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[37],abshift_get(10),c2[38]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[36],abshift_get(1),c2[37]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[52],abshift_get(33),c2[53]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[53],abshift_get(13),c2[54]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[52],abshift_get(20),c2[53]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[62],abshift_get(53),c2[63]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[62],abshift_get(54),c2[63]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[62],abshift_get(17),c2[63]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[64],abshift_get(1),c2[65]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[75],abshift_get(24),c2[76]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[75],abshift_get(25),c2[76]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[74],abshift_get(34),c2[75]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[75],abshift_get(8),c2[76]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[89],abshift_get(12),c2[90]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[88],abshift_get(12),c2[89]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[86],abshift_get(26),c2[87]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[101],abshift_get(12),c2[102]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[98],abshift_get(33),c2[99]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[96],abshift_get(57),c2[97]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[112],abshift_get(61),c2[113]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[112],abshift_get(62),c2[113]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[110],abshift_get(51),c2[111]),_mm512_xor_si512(c2[109],_mm512_xor_si512(_mm512_permutex2var_epi8(c2[124],abshift_get(32),c2[125]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[124],abshift_get(33),c2[125]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[122],abshift_get(2),c2[123]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[122],abshift_get(5),c2[123]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[133],abshift_get(45),c2[134]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[133],abshift_get(46),c2[134]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[136],abshift_get(40),c2[137]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[136],abshift_get(50),c2[137]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[144],abshift_get(17),c2[145]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[144],abshift_get(18),c2[145]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[149],abshift_get(23),c2[150]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[147],abshift_get(40),c2[148]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[161],abshift_get(37),c2[162]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[161],abshift_get(38),c2[162]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[159],abshift_get(9),c2[160]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[161],abshift_get(22),c2[162]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[171],abshift_get(26),c2[172]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[169],abshift_get(25),c2[170]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[171],abshift_get(21),c2[172]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[183],abshift_get(23),c2[184]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[183],abshift_get(24),c2[184]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[181],abshift_get(36),c2[182]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[180],abshift_get(54),c2[181]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[193],abshift_get(42),c2[194]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[193],abshift_get(43),c2[194]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[197],abshift_get(35),c2[198]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[196],abshift_get(49),c2[197]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[205],abshift_get(51),c2[206]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[206],abshift_get(4),c2[207]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[208],abshift_get(45),c2[209]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[219],abshift_get(50),c2[220]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[219],abshift_get(51),c2[220]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[219],abshift_get(49),c2[220]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[220],abshift_get(16),c2[221]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[230],abshift_get(52),c2[231]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[230],abshift_get(53),c2[231]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[233],abshift_get(12),c2[234]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[231],abshift_get(14),c2[232]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[245],abshift_get(10),c2[246]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[245],abshift_get(11),c2[246]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[240],abshift_get(14),c2[241]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[240],abshift_get(40),c2[241]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[257],abshift_get(26),c2[258]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[257],abshift_get(27),c2[258]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[253],abshift_get(49),c2[254]),_mm512_permutex2var_epi8(c2[257],abshift_get(38),c2[258])))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 2 + d2[12]=_mm512_xor_si512(_mm512_permutex2var_epi8(c2[4],abshift_get(52),c2[5]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[1],abshift_get(13),c2[2]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[3],abshift_get(13),c2[4]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[3],abshift_get(14),c2[4]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[4],abshift_get(20),c2[5]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[4],abshift_get(21),c2[5]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[12],abshift_get(20),c2[13]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[15],abshift_get(58),c2[16]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[15],abshift_get(59),c2[16]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[13],abshift_get(23),c2[14]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[13],abshift_get(24),c2[14]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[24],abshift_get(51),c2[25]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[25],abshift_get(13),c2[26]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[29],abshift_get(8),c2[30]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[29],abshift_get(9),c2[30]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[41],abshift_get(50),c2[42]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[37],abshift_get(10),c2[38]),_mm512_xor_si512(c2[36],_mm512_xor_si512(_mm512_permutex2var_epi8(c2[36],abshift_get(1),c2[37]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[52],abshift_get(33),c2[53]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[53],abshift_get(12),c2[54]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[53],abshift_get(13),c2[54]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[52],abshift_get(19),c2[53]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[52],abshift_get(20),c2[53]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[62],abshift_get(54),c2[63]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[62],abshift_get(17),c2[63]),_mm512_xor_si512(c2[64],_mm512_xor_si512(_mm512_permutex2var_epi8(c2[64],abshift_get(1),c2[65]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[75],abshift_get(25),c2[76]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[74],abshift_get(33),c2[75]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[74],abshift_get(34),c2[75]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[75],abshift_get(7),c2[76]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[75],abshift_get(8),c2[76]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[89],abshift_get(12),c2[90]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[88],abshift_get(11),c2[89]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[88],abshift_get(12),c2[89]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[86],abshift_get(25),c2[87]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[86],abshift_get(26),c2[87]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[101],abshift_get(12),c2[102]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[98],abshift_get(32),c2[99]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[98],abshift_get(33),c2[99]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[96],abshift_get(56),c2[97]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[96],abshift_get(57),c2[97]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[112],abshift_get(62),c2[113]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[110],abshift_get(51),c2[111]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[108],abshift_get(63),c2[109]),_mm512_xor_si512(c2[109],_mm512_xor_si512(_mm512_permutex2var_epi8(c2[124],abshift_get(33),c2[125]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[122],abshift_get(1),c2[123]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[122],abshift_get(2),c2[123]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[122],abshift_get(4),c2[123]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[122],abshift_get(5),c2[123]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[133],abshift_get(46),c2[134]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[136],abshift_get(40),c2[137]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[136],abshift_get(49),c2[137]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[136],abshift_get(50),c2[137]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[144],abshift_get(18),c2[145]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[149],abshift_get(23),c2[150]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[147],abshift_get(39),c2[148]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[147],abshift_get(40),c2[148]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[161],abshift_get(38),c2[162]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[159],abshift_get(8),c2[160]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[159],abshift_get(9),c2[160]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[161],abshift_get(21),c2[162]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[161],abshift_get(22),c2[162]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[171],abshift_get(26),c2[172]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[169],abshift_get(24),c2[170]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[169],abshift_get(25),c2[170]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[171],abshift_get(20),c2[172]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[171],abshift_get(21),c2[172]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[183],abshift_get(24),c2[184]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[181],abshift_get(36),c2[182]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[180],abshift_get(53),c2[181]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[180],abshift_get(54),c2[181]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[193],abshift_get(43),c2[194]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[197],abshift_get(35),c2[198]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[196],abshift_get(48),c2[197]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[196],abshift_get(49),c2[197]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[205],abshift_get(51),c2[206]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[206],abshift_get(3),c2[207]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[206],abshift_get(4),c2[207]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[208],abshift_get(44),c2[209]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[208],abshift_get(45),c2[209]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[219],abshift_get(51),c2[220]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[219],abshift_get(48),c2[220]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[219],abshift_get(49),c2[220]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[220],abshift_get(15),c2[221]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[220],abshift_get(16),c2[221]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[230],abshift_get(53),c2[231]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[233],abshift_get(12),c2[234]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[231],abshift_get(13),c2[232]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[231],abshift_get(14),c2[232]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[245],abshift_get(11),c2[246]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[240],abshift_get(13),c2[241]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[240],abshift_get(14),c2[241]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[240],abshift_get(39),c2[241]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[240],abshift_get(40),c2[241]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[257],abshift_get(27),c2[258]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[253],abshift_get(49),c2[254]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[257],abshift_get(37),c2[258]),_mm512_permutex2var_epi8(c2[257],abshift_get(38),c2[258]))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 3 + d2[18]=_mm512_xor_si512(_mm512_permutex2var_epi8(c2[4],abshift_get(52),c2[5]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[1],abshift_get(13),c2[2]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[3],abshift_get(14),c2[4]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[4],abshift_get(20),c2[5]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[4],abshift_get(21),c2[5]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[12],abshift_get(20),c2[13]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[15],abshift_get(59),c2[16]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[13],abshift_get(23),c2[14]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[13],abshift_get(24),c2[14]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[24],abshift_get(51),c2[25]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[25],abshift_get(13),c2[26]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[29],abshift_get(9),c2[30]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[41],abshift_get(50),c2[42]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[37],abshift_get(10),c2[38]),_mm512_xor_si512(c2[36],_mm512_xor_si512(_mm512_permutex2var_epi8(c2[36],abshift_get(1),c2[37]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[52],abshift_get(33),c2[53]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[53],abshift_get(13),c2[54]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[52],abshift_get(19),c2[53]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[52],abshift_get(20),c2[53]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[62],abshift_get(54),c2[63]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[62],abshift_get(17),c2[63]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[64],abshift_get(1),c2[65]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[75],abshift_get(25),c2[76]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[74],abshift_get(34),c2[75]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[75],abshift_get(7),c2[76]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[75],abshift_get(8),c2[76]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[89],abshift_get(12),c2[90]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[88],abshift_get(12),c2[89]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[86],abshift_get(25),c2[87]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[86],abshift_get(26),c2[87]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[101],abshift_get(12),c2[102]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[98],abshift_get(33),c2[99]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[96],abshift_get(56),c2[97]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[96],abshift_get(57),c2[97]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[112],abshift_get(62),c2[113]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[110],abshift_get(51),c2[111]),_mm512_xor_si512(c2[109],_mm512_xor_si512(_mm512_permutex2var_epi8(c2[124],abshift_get(33),c2[125]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[122],abshift_get(2),c2[123]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[122],abshift_get(4),c2[123]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[122],abshift_get(5),c2[123]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[133],abshift_get(46),c2[134]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[136],abshift_get(40),c2[137]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[136],abshift_get(49),c2[137]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[136],abshift_get(50),c2[137]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[144],abshift_get(18),c2[145]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[149],abshift_get(23),c2[150]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[147],abshift_get(39),c2[148]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[147],abshift_get(40),c2[148]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[161],abshift_get(38),c2[162]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[159],abshift_get(9),c2[160]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[161],abshift_get(21),c2[162]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[161],abshift_get(22),c2[162]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[171],abshift_get(26),c2[172]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[169],abshift_get(25),c2[170]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[171],abshift_get(20),c2[172]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[171],abshift_get(21),c2[172]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[183],abshift_get(24),c2[184]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[181],abshift_get(36),c2[182]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[180],abshift_get(54),c2[181]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[193],abshift_get(43),c2[194]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[197],abshift_get(35),c2[198]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[196],abshift_get(48),c2[197]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[196],abshift_get(49),c2[197]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[205],abshift_get(51),c2[206]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[206],abshift_get(4),c2[207]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[208],abshift_get(44),c2[209]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[208],abshift_get(45),c2[209]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[219],abshift_get(51),c2[220]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[219],abshift_get(49),c2[220]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[220],abshift_get(15),c2[221]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[220],abshift_get(16),c2[221]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[230],abshift_get(53),c2[231]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[233],abshift_get(12),c2[234]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[231],abshift_get(14),c2[232]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[245],abshift_get(11),c2[246]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[240],abshift_get(14),c2[241]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[240],abshift_get(39),c2[241]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[240],abshift_get(40),c2[241]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[257],abshift_get(27),c2[258]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[253],abshift_get(49),c2[254]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[257],abshift_get(37),c2[258]),_mm512_permutex2var_epi8(c2[257],abshift_get(38),c2[258])))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 4 + d2[24]=_mm512_xor_si512(_mm512_permutex2var_epi8(c2[5],abshift_get(12),c2[6]),_mm512_permutex2var_epi8(c2[14],abshift_get(53),c2[15])); + +//row: 5 + d2[30]=_mm512_xor_si512(_mm512_permutex2var_epi8(c2[1],abshift_get(16),c2[2]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[3],abshift_get(41),c2[4]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[5],abshift_get(42),c2[6]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[0],abshift_get(49),c2[1]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[3],abshift_get(3),c2[4]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[14],abshift_get(48),c2[15]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[12],abshift_get(23),c2[13]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[15],abshift_get(52),c2[16]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[12],abshift_get(14),c2[13]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[27],abshift_get(15),c2[28]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[27],abshift_get(41),c2[28]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[25],abshift_get(37),c2[26]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[38],abshift_get(14),c2[39]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[39],abshift_get(38),c2[40]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[38],abshift_get(29),c2[39]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[37],abshift_get(51),c2[38]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[48],abshift_get(61),c2[49]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[49],abshift_get(41),c2[50]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[48],abshift_get(48),c2[49]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[65],abshift_get(18),c2[66]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[64],abshift_get(45),c2[65]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[60],abshift_get(29),c2[61]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[77],abshift_get(53),c2[78]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[76],abshift_get(62),c2[77]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[77],abshift_get(36),c2[78]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[85],abshift_get(40),c2[86]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[84],abshift_get(40),c2[85]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[88],abshift_get(54),c2[89]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[97],abshift_get(40),c2[98]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[100],abshift_get(61),c2[101]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[99],abshift_get(21),c2[100]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[109],abshift_get(26),c2[110]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[113],abshift_get(15),c2[114]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[111],abshift_get(28),c2[112]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[120],abshift_get(61),c2[121]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[124],abshift_get(30),c2[125]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[124],abshift_get(33),c2[125]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[136],abshift_get(10),c2[137]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[133],abshift_get(4),c2[134]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[133],abshift_get(14),c2[134]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[146],abshift_get(46),c2[147]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[145],abshift_get(51),c2[146]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[144],abshift_get(4),c2[145]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[146],abshift_get(38),c2[147]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[158],abshift_get(2),c2[159]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[161],abshift_get(37),c2[162]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[157],abshift_get(50),c2[158]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[173],abshift_get(54),c2[174]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[171],abshift_get(53),c2[172]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[173],abshift_get(49),c2[174]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[185],abshift_get(52),c2[186]),_mm512_xor_si512(c2[184],_mm512_xor_si512(_mm512_permutex2var_epi8(c2[183],abshift_get(18),c2[184]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[196],abshift_get(7),c2[197]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[193],abshift_get(63),c2[194]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[193],abshift_get(13),c2[194]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[195],abshift_get(49),c2[196]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[208],abshift_get(15),c2[209]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[208],abshift_get(32),c2[209]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[205],abshift_get(9),c2[206]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[216],abshift_get(15),c2[217]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[216],abshift_get(13),c2[217]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[216],abshift_get(44),c2[217]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[233],abshift_get(17),c2[234]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[229],abshift_get(40),c2[230]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[233],abshift_get(42),c2[234]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[241],abshift_get(39),c2[242]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[242],abshift_get(42),c2[243]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[243],abshift_get(4),c2[244]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[253],abshift_get(55),c2[254]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[256],abshift_get(13),c2[257]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[254],abshift_get(2),c2[255]),_mm512_permutex2var_epi8(c2[252],abshift_get(51),c2[253]))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 6 + d2[36]=_mm512_xor_si512(_mm512_permutex2var_epi8(c2[4],abshift_get(22),c2[5]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[76],abshift_get(1),c2[77]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[120],abshift_get(1),c2[121]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[137],abshift_get(31),c2[138]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[157],abshift_get(28),c2[158]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[207],abshift_get(61),c2[208]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[216],abshift_get(18),c2[217]),_mm512_permutex2var_epi8(c2[243],abshift_get(33),c2[244])))))))); + +//row: 7 + d2[42]=_mm512_xor_si512(_mm512_permutex2var_epi8(c2[0],abshift_get(9),c2[1]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[12],abshift_get(62),c2[13]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[52],abshift_get(60),c2[53]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[89],abshift_get(13),c2[90]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[100],abshift_get(34),c2[101]),_mm512_permutex2var_epi8(c2[169],abshift_get(50),c2[170])))))); + +//row: 8 + d2[48]=_mm512_xor_si512(_mm512_permutex2var_epi8(c2[5],abshift_get(54),c2[6]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[1],abshift_get(30),c2[2]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[2],abshift_get(15),c2[3]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[3],abshift_get(55),c2[4]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[4],abshift_get(16),c2[5]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[5],abshift_get(55),c2[6]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[5],abshift_get(56),c2[6]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[5],abshift_get(23),c2[6]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[0],abshift_get(62),c2[1]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[0],abshift_get(63),c2[1]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[4],abshift_get(51),c2[5]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[13],abshift_get(22),c2[14]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[14],abshift_get(62),c2[15]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[16],abshift_get(61),c2[17]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[12],abshift_get(36),c2[13]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[12],abshift_get(37),c2[13]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[14],abshift_get(26),c2[15]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[16],abshift_get(1),c2[17]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[16],abshift_get(2),c2[17]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[14],abshift_get(51),c2[15]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[25],abshift_get(53),c2[26]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[27],abshift_get(29),c2[28]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[26],abshift_get(15),c2[27]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[27],abshift_get(55),c2[28]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[24],abshift_get(11),c2[25]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[25],abshift_get(50),c2[26]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[25],abshift_get(51),c2[26]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[36],abshift_get(52),c2[37]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[38],abshift_get(28),c2[39]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[38],abshift_get(12),c2[39]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[39],abshift_get(52),c2[40]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[37],abshift_get(3),c2[38]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[38],abshift_get(42),c2[39]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[38],abshift_get(43),c2[39]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[38],abshift_get(37),c2[39]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[53],abshift_get(35),c2[54]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[49],abshift_get(11),c2[50]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[48],abshift_get(15),c2[49]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[49],abshift_get(54),c2[50]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[49],abshift_get(55),c2[50]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[53],abshift_get(22),c2[54]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[48],abshift_get(61),c2[49]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[48],abshift_get(62),c2[49]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[63],abshift_get(56),c2[64]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[65],abshift_get(32),c2[66]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[63],abshift_get(19),c2[64]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[64],abshift_get(59),c2[65]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[65],abshift_get(3),c2[66]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[60],abshift_get(42),c2[61]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[60],abshift_get(43),c2[61]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[76],abshift_get(27),c2[77]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[72],abshift_get(3),c2[73]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[75],abshift_get(36),c2[76]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[77],abshift_get(11),c2[78]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[77],abshift_get(12),c2[78]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[76],abshift_get(10),c2[77]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[77],abshift_get(49),c2[78]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[77],abshift_get(50),c2[78]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[84],abshift_get(14),c2[85]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[85],abshift_get(54),c2[86]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[89],abshift_get(14),c2[90]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[84],abshift_get(53),c2[85]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[84],abshift_get(54),c2[85]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[87],abshift_get(28),c2[88]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[89],abshift_get(3),c2[90]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[89],abshift_get(4),c2[90]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[96],abshift_get(14),c2[97]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[97],abshift_get(54),c2[98]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[99],abshift_get(35),c2[100]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[101],abshift_get(10),c2[102]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[101],abshift_get(11),c2[102]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[97],abshift_get(59),c2[98]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[99],abshift_get(34),c2[100]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[99],abshift_get(35),c2[100]),_mm512_xor_si512(c2[108],_mm512_xor_si512(_mm512_permutex2var_epi8(c2[109],abshift_get(40),c2[110]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[111],abshift_get(53),c2[112]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[113],abshift_get(29),c2[114]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[110],abshift_get(2),c2[111]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[111],abshift_get(41),c2[112]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[111],abshift_get(42),c2[112]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[125],abshift_get(35),c2[126]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[121],abshift_get(11),c2[122]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[123],abshift_get(4),c2[124]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[124],abshift_get(43),c2[125]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[124],abshift_get(44),c2[125]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[123],abshift_get(7),c2[124]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[124],abshift_get(46),c2[125]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[124],abshift_get(47),c2[125]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[134],abshift_get(48),c2[135]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[136],abshift_get(24),c2[137]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[137],abshift_get(42),c2[138]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[133],abshift_get(18),c2[134]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[137],abshift_get(52),c2[138]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[133],abshift_get(27),c2[134]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[133],abshift_get(28),c2[134]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[145],abshift_get(20),c2[146]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[146],abshift_get(60),c2[147]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[144],abshift_get(25),c2[145]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[146],abshift_get(1),c2[147]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[148],abshift_get(42),c2[149]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[144],abshift_get(17),c2[145]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[144],abshift_get(18),c2[145]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[144],abshift_get(18),c2[145]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[156],abshift_get(40),c2[157]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[158],abshift_get(16),c2[159]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[160],abshift_get(11),c2[161]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[161],abshift_get(50),c2[162]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[161],abshift_get(51),c2[162]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[156],abshift_get(24),c2[157]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[157],abshift_get(63),c2[158]),_mm512_xor_si512(c2[158],_mm512_xor_si512(_mm512_permutex2var_epi8(c2[172],abshift_get(28),c2[173]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[168],abshift_get(4),c2[169]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[170],abshift_get(27),c2[171]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[172],abshift_get(2),c2[173]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[172],abshift_get(3),c2[173]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[172],abshift_get(23),c2[173]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[173],abshift_get(62),c2[174]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[173],abshift_get(63),c2[174]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[184],abshift_get(26),c2[185]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[180],abshift_get(2),c2[181]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[182],abshift_get(38),c2[183]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[184],abshift_get(14),c2[185]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[181],abshift_get(56),c2[182]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[183],abshift_get(31),c2[184]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[183],abshift_get(32),c2[184]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[194],abshift_get(45),c2[195]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[196],abshift_get(21),c2[197]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[192],abshift_get(37),c2[193]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[194],abshift_get(13),c2[195]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[197],abshift_get(51),c2[198]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[193],abshift_get(26),c2[194]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[193],abshift_get(27),c2[194]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[192],abshift_get(39),c2[193]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[206],abshift_get(53),c2[207]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[208],abshift_get(29),c2[209]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[207],abshift_get(6),c2[208]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[208],abshift_get(45),c2[209]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[208],abshift_get(46),c2[209]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[209],abshift_get(47),c2[210]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[205],abshift_get(22),c2[206]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[205],abshift_get(23),c2[206]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[220],abshift_get(53),c2[221]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[216],abshift_get(29),c2[217]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[220],abshift_get(51),c2[221]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[216],abshift_get(26),c2[217]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[216],abshift_get(27),c2[217]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[221],abshift_get(18),c2[222]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[216],abshift_get(57),c2[217]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[216],abshift_get(58),c2[217]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[231],abshift_get(55),c2[232]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[233],abshift_get(31),c2[234]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[228],abshift_get(14),c2[229]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[229],abshift_get(54),c2[230]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[232],abshift_get(16),c2[233]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[233],abshift_get(55),c2[234]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[233],abshift_get(56),c2[234]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[231],abshift_get(32),c2[232]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[240],abshift_get(13),c2[241]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[241],abshift_get(53),c2[242]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[241],abshift_get(16),c2[242]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[242],abshift_get(55),c2[243]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[242],abshift_get(56),c2[243]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[241],abshift_get(42),c2[242]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[243],abshift_get(17),c2[244]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[243],abshift_get(18),c2[244]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[252],abshift_get(29),c2[253]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[254],abshift_get(5),c2[255]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[254],abshift_get(51),c2[255]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[256],abshift_get(27),c2[257]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[252],abshift_get(40),c2[253]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[254],abshift_get(15),c2[255]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[254],abshift_get(16),c2[255]),_mm512_permutex2var_epi8(c2[257],abshift_get(48),c2[258]))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 9 + d2[54]=_mm512_xor_si512(_mm512_permutex2var_epi8(c2[5],abshift_get(46),c2[6]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[15],abshift_get(40),c2[16]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[125],abshift_get(1),c2[126]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[134],abshift_get(5),c2[135]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[156],abshift_get(57),c2[157]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[208],abshift_get(47),c2[209]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[216],abshift_get(63),c2[217]),_mm512_permutex2var_epi8(c2[241],abshift_get(18),c2[242])))))))); + +//row: 10 + d2[60]=_mm512_xor_si512(_mm512_permutex2var_epi8(c2[13],abshift_get(37),c2[14]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[29],abshift_get(19),c2[30]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[52],abshift_get(18),c2[53]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[85],abshift_get(47),c2[86]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[101],abshift_get(63),c2[102]),_mm512_permutex2var_epi8(c2[173],abshift_get(34),c2[174])))))); + +//row: 11 + d2[66]=_mm512_xor_si512(_mm512_permutex2var_epi8(c2[4],abshift_get(1),c2[5]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[0],abshift_get(38),c2[1]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[0],abshift_get(39),c2[1]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[0],abshift_get(26),c2[1]),_mm512_xor_si512(c2[3],_mm512_xor_si512(_mm512_permutex2var_epi8(c2[2],abshift_get(27),c2[3]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[5],abshift_get(1),c2[6]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[3],abshift_get(34),c2[4]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[0],abshift_get(8),c2[1]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[0],abshift_get(48),c2[1]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[17],abshift_get(33),c2[18]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[14],abshift_get(6),c2[15]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[14],abshift_get(7),c2[15]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[15],abshift_get(8),c2[16]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[17],abshift_get(46),c2[18]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[12],abshift_get(37),c2[13]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[15],abshift_get(11),c2[16]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[13],abshift_get(38),c2[14]),_mm512_xor_si512(c2[24],_mm512_xor_si512(_mm512_permutex2var_epi8(c2[26],abshift_get(37),c2[27]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[26],abshift_get(38),c2[27]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[24],abshift_get(26),c2[25]),_mm512_xor_si512(c2[27],_mm512_xor_si512(_mm512_permutex2var_epi8(c2[28],abshift_get(22),c2[29]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[24],abshift_get(60),c2[25]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[40],abshift_get(63),c2[41]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[37],abshift_get(36),c2[38]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[37],abshift_get(37),c2[38]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[36],abshift_get(23),c2[37]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[38],abshift_get(61),c2[39]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[41],abshift_get(14),c2[42]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[37],abshift_get(52),c2[38]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[51],abshift_get(46),c2[52]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[48],abshift_get(20),c2[49]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[52],abshift_get(26),c2[53]),_mm512_xor_si512(c2[49],_mm512_xor_si512(_mm512_permutex2var_epi8(c2[51],abshift_get(33),c2[52]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[48],abshift_get(7),c2[49]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[62],abshift_get(3),c2[63]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[64],abshift_get(40),c2[65]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[64],abshift_get(41),c2[65]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[61],abshift_get(30),c2[62]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[64],abshift_get(4),c2[65]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[63],abshift_get(14),c2[64]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[65],abshift_get(52),c2[66]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[74],abshift_get(38),c2[75]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[77],abshift_get(11),c2[78]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[77],abshift_get(12),c2[78]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[73],abshift_get(47),c2[74]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[76],abshift_get(21),c2[77]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[74],abshift_get(21),c2[75]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[76],abshift_get(59),c2[77]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[88],abshift_get(25),c2[89]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[84],abshift_get(63),c2[85]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[87],abshift_get(25),c2[88]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[89],abshift_get(63),c2[90]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[85],abshift_get(39),c2[86]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[88],abshift_get(13),c2[89]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[100],abshift_get(25),c2[101]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[96],abshift_get(63),c2[97]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[97],abshift_get(46),c2[98]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[100],abshift_get(20),c2[101]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[96],abshift_get(6),c2[97]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[98],abshift_get(44),c2[99]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[112],abshift_get(11),c2[113]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[108],abshift_get(48),c2[109]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[108],abshift_get(49),c2[109]),_mm512_xor_si512(c2[110],_mm512_xor_si512(_mm512_permutex2var_epi8(c2[112],abshift_get(38),c2[113]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[108],abshift_get(13),c2[109]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[110],abshift_get(51),c2[111]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[123],abshift_get(46),c2[124]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[120],abshift_get(19),c2[121]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[120],abshift_get(20),c2[121]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[121],abshift_get(15),c2[122]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[123],abshift_get(53),c2[124]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[121],abshift_get(18),c2[122]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[123],abshift_get(56),c2[124]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[132],abshift_get(59),c2[133]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[135],abshift_get(32),c2[136]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[135],abshift_get(33),c2[136]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[135],abshift_get(53),c2[136]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[132],abshift_get(27),c2[133]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[135],abshift_get(63),c2[136]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[132],abshift_get(37),c2[133]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[149],abshift_get(31),c2[150]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[146],abshift_get(4),c2[147]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[146],abshift_get(5),c2[147]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[148],abshift_get(36),c2[149]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[145],abshift_get(10),c2[146]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[146],abshift_get(53),c2[147]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[149],abshift_get(27),c2[150]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[144],abshift_get(8),c2[145]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[160],abshift_get(51),c2[161]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[157],abshift_get(24),c2[158]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[157],abshift_get(25),c2[158]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[158],abshift_get(22),c2[159]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[160],abshift_get(60),c2[161]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[160],abshift_get(35),c2[161]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[157],abshift_get(9),c2[158]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[170],abshift_get(39),c2[171]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[173],abshift_get(13),c2[174]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[168],abshift_get(38),c2[169]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[171],abshift_get(12),c2[172]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[170],abshift_get(34),c2[171]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[173],abshift_get(8),c2[174]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[182],abshift_get(37),c2[183]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[185],abshift_get(10),c2[186]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[185],abshift_get(11),c2[186]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[180],abshift_get(49),c2[181]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[183],abshift_get(23),c2[184]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[180],abshift_get(3),c2[181]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[182],abshift_get(41),c2[183]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[192],abshift_get(56),c2[193]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[195],abshift_get(29),c2[196]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[195],abshift_get(30),c2[196]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[196],abshift_get(48),c2[197]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[193],abshift_get(22),c2[194]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[195],abshift_get(62),c2[196]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[192],abshift_get(36),c2[193]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[192],abshift_get(47),c2[193]),_mm512_xor_si512(c2[205],_mm512_xor_si512(_mm512_permutex2var_epi8(c2[207],abshift_get(38),c2[208]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[205],abshift_get(17),c2[206]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[207],abshift_get(55),c2[208]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[207],abshift_get(58),c2[208]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[204],abshift_get(32),c2[205]),_mm512_xor_si512(c2[219],_mm512_xor_si512(_mm512_permutex2var_epi8(c2[221],abshift_get(37),c2[222]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[221],abshift_get(38),c2[222]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[218],abshift_get(62),c2[219]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[221],abshift_get(36),c2[222]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[219],abshift_get(29),c2[220]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[216],abshift_get(3),c2[217]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[230],abshift_get(2),c2[231]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[232],abshift_get(39),c2[233]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[232],abshift_get(40),c2[233]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[232],abshift_get(25),c2[233]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[228],abshift_get(63),c2[229]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[230],abshift_get(27),c2[231]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[233],abshift_get(1),c2[234]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[244],abshift_get(24),c2[245]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[240],abshift_get(61),c2[241]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[240],abshift_get(62),c2[241]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[245],abshift_get(27),c2[246]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[242],abshift_get(1),c2[243]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[245],abshift_get(53),c2[246]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[242],abshift_get(27),c2[243]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[256],abshift_get(40),c2[257]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[253],abshift_get(13),c2[254]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[253],abshift_get(14),c2[254]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[252],abshift_get(62),c2[253]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[255],abshift_get(36),c2[256]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[256],abshift_get(51),c2[257]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[253],abshift_get(25),c2[254]),_mm512_permutex2var_epi8(c2[254],abshift_get(60),c2[255])))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 12 + d2[72]=_mm512_xor_si512(_mm512_permutex2var_epi8(c2[1],abshift_get(13),c2[2]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[14],abshift_get(58),c2[15]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[122],abshift_get(46),c2[123]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[135],abshift_get(40),c2[136]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[156],abshift_get(50),c2[157]),_mm512_permutex2var_epi8(c2[217],abshift_get(10),c2[218])))))); + +//row: 13 + d2[78]=_mm512_xor_si512(_mm512_permutex2var_epi8(c2[4],abshift_get(37),c2[5]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[4],abshift_get(38),c2[5]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[0],abshift_get(63),c2[1]),_mm512_xor_si512(c2[3],_mm512_xor_si512(_mm512_permutex2var_epi8(c2[4],abshift_get(7),c2[5]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[4],abshift_get(57),c2[5]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[12],abshift_get(5),c2[13]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[12],abshift_get(6),c2[13]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[15],abshift_get(45),c2[16]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[13],abshift_get(10),c2[14]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[24],abshift_get(36),c2[25]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[24],abshift_get(37),c2[25]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[24],abshift_get(63),c2[25]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[28],abshift_get(59),c2[29]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[41],abshift_get(35),c2[42]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[41],abshift_get(36),c2[42]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[36],abshift_get(60),c2[37]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[41],abshift_get(51),c2[42]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[38],abshift_get(49),c2[39]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[52],abshift_get(19),c2[53]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[52],abshift_get(63),c2[53]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[52],abshift_get(6),c2[53]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[62],abshift_get(39),c2[63]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[62],abshift_get(40),c2[63]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[62],abshift_get(3),c2[63]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[63],abshift_get(51),c2[64]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[75],abshift_get(10),c2[76]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[75],abshift_get(11),c2[76]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[74],abshift_get(20),c2[75]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[74],abshift_get(58),c2[75]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[88],abshift_get(62),c2[89]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[87],abshift_get(62),c2[88]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[86],abshift_get(12),c2[87]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[88],abshift_get(10),c2[89]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[100],abshift_get(62),c2[101]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[98],abshift_get(19),c2[99]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[96],abshift_get(43),c2[97]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[112],abshift_get(47),c2[113]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[112],abshift_get(48),c2[113]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[110],abshift_get(37),c2[111]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[108],abshift_get(50),c2[109]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[124],abshift_get(18),c2[125]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[124],abshift_get(19),c2[125]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[121],abshift_get(52),c2[122]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[121],abshift_get(55),c2[122]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[133],abshift_get(31),c2[134]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[133],abshift_get(32),c2[134]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[136],abshift_get(26),c2[137]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[136],abshift_get(36),c2[137]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[144],abshift_get(3),c2[145]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[144],abshift_get(4),c2[145]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[149],abshift_get(9),c2[150]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[147],abshift_get(26),c2[148]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[161],abshift_get(23),c2[162]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[161],abshift_get(24),c2[162]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[158],abshift_get(59),c2[159]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[161],abshift_get(8),c2[162]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[171],abshift_get(12),c2[172]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[169],abshift_get(11),c2[170]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[171],abshift_get(7),c2[172]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[183],abshift_get(9),c2[184]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[183],abshift_get(10),c2[184]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[181],abshift_get(22),c2[182]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[180],abshift_get(40),c2[181]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[193],abshift_get(28),c2[194]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[193],abshift_get(29),c2[194]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[197],abshift_get(21),c2[198]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[196],abshift_get(35),c2[197]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[205],abshift_get(37),c2[206]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[205],abshift_get(54),c2[206]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[208],abshift_get(31),c2[209]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[219],abshift_get(36),c2[220]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[219],abshift_get(37),c2[220]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[219],abshift_get(35),c2[220]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[220],abshift_get(2),c2[221]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[230],abshift_get(38),c2[231]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[230],abshift_get(39),c2[231]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[232],abshift_get(62),c2[233]),_mm512_xor_si512(c2[231],_mm512_xor_si512(_mm512_permutex2var_epi8(c2[244],abshift_get(60),c2[245]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[244],abshift_get(61),c2[245]),_mm512_xor_si512(c2[240],_mm512_xor_si512(_mm512_permutex2var_epi8(c2[240],abshift_get(26),c2[241]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[241],abshift_get(51),c2[242]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[257],abshift_get(12),c2[258]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[257],abshift_get(13),c2[258]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[253],abshift_get(35),c2[254]),_mm512_permutex2var_epi8(c2[257],abshift_get(24),c2[258])))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 14 + d2[84]=_mm512_xor_si512(_mm512_permutex2var_epi8(c2[2],abshift_get(14),c2[3]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[147],abshift_get(56),c2[148]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[182],abshift_get(9),c2[183]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[193],abshift_get(25),c2[194]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[209],abshift_get(27),c2[210]),_mm512_permutex2var_epi8(c2[252],abshift_get(12),c2[253])))))); + +//row: 15 + d2[90]=_mm512_xor_si512(_mm512_permutex2var_epi8(c2[3],abshift_get(1),c2[4]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[5],abshift_get(26),c2[6]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[1],abshift_get(27),c2[2]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[2],abshift_get(33),c2[3]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[2],abshift_get(34),c2[3]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[3],abshift_get(49),c2[4]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[16],abshift_get(33),c2[17]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[14],abshift_get(8),c2[15]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[17],abshift_get(36),c2[18]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[17],abshift_get(37),c2[18]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[12],abshift_get(2),c2[13]),_mm512_xor_si512(c2[29],_mm512_xor_si512(_mm512_permutex2var_epi8(c2[29],abshift_get(26),c2[30]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[27],abshift_get(22),c2[28]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[39],abshift_get(63),c2[40]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[41],abshift_get(23),c2[42]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[40],abshift_get(13),c2[41]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[40],abshift_get(14),c2[41]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[50],abshift_get(46),c2[51]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[51],abshift_get(26),c2[52]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[50],abshift_get(32),c2[51]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[50],abshift_get(33),c2[51]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[61],abshift_get(3),c2[62]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[60],abshift_get(30),c2[61]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[62],abshift_get(14),c2[63]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[73],abshift_get(38),c2[74]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[72],abshift_get(47),c2[73]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[73],abshift_get(20),c2[74]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[73],abshift_get(21),c2[74]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[87],abshift_get(25),c2[88]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[86],abshift_get(25),c2[87]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[84],abshift_get(38),c2[85]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[84],abshift_get(39),c2[85]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[99],abshift_get(25),c2[100]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[96],abshift_get(46),c2[97]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[101],abshift_get(5),c2[102]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[101],abshift_get(6),c2[102]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[111],abshift_get(11),c2[112]),_mm512_xor_si512(c2[109],_mm512_xor_si512(_mm512_permutex2var_epi8(c2[113],abshift_get(13),c2[114]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[122],abshift_get(46),c2[123]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[120],abshift_get(15),c2[121]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[120],abshift_get(17),c2[121]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[120],abshift_get(18),c2[121]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[123],abshift_get(18),c2[124]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[137],abshift_get(59),c2[138]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[134],abshift_get(53),c2[135]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[134],abshift_get(62),c2[135]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[134],abshift_get(63),c2[135]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[148],abshift_get(31),c2[149]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[147],abshift_get(36),c2[148]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[145],abshift_get(52),c2[146]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[145],abshift_get(53),c2[146]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[159],abshift_get(51),c2[160]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[157],abshift_get(22),c2[158]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[159],abshift_get(34),c2[160]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[159],abshift_get(35),c2[160]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[160],abshift_get(62),c2[161]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[169],abshift_get(39),c2[170]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[173],abshift_get(38),c2[174]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[169],abshift_get(33),c2[170]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[169],abshift_get(34),c2[170]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[181],abshift_get(37),c2[182]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[185],abshift_get(49),c2[186]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[185],abshift_get(3),c2[186]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[197],abshift_get(56),c2[198]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[195],abshift_get(48),c2[196]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[194],abshift_get(61),c2[195]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[194],abshift_get(62),c2[195]),_mm512_xor_si512(c2[204],_mm512_xor_si512(_mm512_permutex2var_epi8(c2[204],abshift_get(17),c2[205]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[206],abshift_get(57),c2[207]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[206],abshift_get(58),c2[207]),_mm512_xor_si512(c2[218],_mm512_xor_si512(_mm512_permutex2var_epi8(c2[217],abshift_get(62),c2[218]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[218],abshift_get(28),c2[219]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[218],abshift_get(29),c2[219]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[216],abshift_get(55),c2[217]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[229],abshift_get(2),c2[230]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[231],abshift_get(25),c2[232]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[229],abshift_get(27),c2[230]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[243],abshift_get(24),c2[244]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[244],abshift_get(27),c2[245]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[244],abshift_get(52),c2[245]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[244],abshift_get(53),c2[245]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[255],abshift_get(40),c2[256]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[257],abshift_get(62),c2[258]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[255],abshift_get(50),c2[256]),_mm512_permutex2var_epi8(c2[255],abshift_get(51),c2[256]))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 16 + d2[96]=_mm512_xor_si512(_mm512_permutex2var_epi8(c2[5],abshift_get(44),c2[6]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[2],abshift_get(5),c2[3]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[4],abshift_get(6),c2[5]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[5],abshift_get(13),c2[6]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[13],abshift_get(12),c2[14]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[16],abshift_get(51),c2[17]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[14],abshift_get(16),c2[15]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[12],abshift_get(13),c2[13]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[25],abshift_get(43),c2[26]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[26],abshift_get(5),c2[27]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[24],abshift_get(1),c2[25]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[36],abshift_get(42),c2[37]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[38],abshift_get(2),c2[39]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[36],abshift_get(57),c2[37]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[41],abshift_get(18),c2[42]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[53],abshift_get(25),c2[54]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[48],abshift_get(5),c2[49]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[53],abshift_get(12),c2[54]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[63],abshift_get(46),c2[64]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[63],abshift_get(9),c2[64]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[64],abshift_get(57),c2[65]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[76],abshift_get(17),c2[77]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[75],abshift_get(26),c2[76]),_mm512_xor_si512(c2[76],_mm512_xor_si512(_mm512_permutex2var_epi8(c2[84],abshift_get(4),c2[85]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[89],abshift_get(4),c2[90]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[87],abshift_get(18),c2[88]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[96],abshift_get(4),c2[97]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[99],abshift_get(25),c2[100]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[97],abshift_get(49),c2[98]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[113],abshift_get(54),c2[114]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[111],abshift_get(43),c2[112]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[109],abshift_get(56),c2[110]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[125],abshift_get(25),c2[126]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[122],abshift_get(58),c2[123]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[122],abshift_get(61),c2[123]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[134],abshift_get(38),c2[135]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[137],abshift_get(32),c2[138]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[137],abshift_get(42),c2[138]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[132],abshift_get(57),c2[133]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[145],abshift_get(10),c2[146]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[144],abshift_get(15),c2[145]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[148],abshift_get(32),c2[149]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[156],abshift_get(30),c2[157]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[160],abshift_get(1),c2[161]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[156],abshift_get(14),c2[157]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[172],abshift_get(18),c2[173]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[170],abshift_get(17),c2[171]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[172],abshift_get(13),c2[173]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[184],abshift_get(16),c2[185]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[182],abshift_get(28),c2[183]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[181],abshift_get(46),c2[182]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[194],abshift_get(35),c2[195]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[192],abshift_get(27),c2[193]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[197],abshift_get(41),c2[198]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[206],abshift_get(43),c2[207]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[206],abshift_get(60),c2[207]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[209],abshift_get(37),c2[210]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[220],abshift_get(43),c2[221]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[220],abshift_get(41),c2[221]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[221],abshift_get(8),c2[222]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[231],abshift_get(45),c2[232]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[228],abshift_get(4),c2[229]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[232],abshift_get(6),c2[233]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[240],abshift_get(3),c2[241]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[241],abshift_get(6),c2[242]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[241],abshift_get(32),c2[242]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[244],abshift_get(33),c2[245]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[252],abshift_get(19),c2[253]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[254],abshift_get(41),c2[255]),_mm512_permutex2var_epi8(c2[252],abshift_get(30),c2[253]))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 17 + d2[102]=_mm512_xor_si512(_mm512_permutex2var_epi8(c2[4],abshift_get(4),c2[5]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[172],abshift_get(47),c2[173]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[193],abshift_get(17),c2[194]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[209],abshift_get(38),c2[210]),_mm512_permutex2var_epi8(c2[257],abshift_get(55),c2[258]))))); + +//row: 18 + d2[108]=_mm512_xor_si512(_mm512_permutex2var_epi8(c2[14],abshift_get(2),c2[15]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[146],abshift_get(35),c2[147]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[160],abshift_get(24),c2[161]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[218],abshift_get(4),c2[219]),_mm512_permutex2var_epi8(c2[228],abshift_get(4),c2[229]))))); + +//row: 19 + d2[114]=_mm512_xor_si512(_mm512_permutex2var_epi8(c2[2],abshift_get(17),c2[3]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[15],abshift_get(21),c2[16]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[89],abshift_get(24),c2[90]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[99],abshift_get(50),c2[100]),_mm512_permutex2var_epi8(c2[123],abshift_get(5),c2[124]))))); + +//row: 20 + d2[120]=_mm512_xor_si512(_mm512_permutex2var_epi8(c2[5],abshift_get(46),c2[6]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[2],abshift_get(7),c2[3]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[4],abshift_get(8),c2[5]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[5],abshift_get(15),c2[6]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[2],abshift_get(59),c2[3]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[13],abshift_get(14),c2[14]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[16],abshift_get(53),c2[17]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[14],abshift_get(18),c2[15]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[25],abshift_get(45),c2[26]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[26],abshift_get(7),c2[27]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[24],abshift_get(3),c2[25]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[36],abshift_get(44),c2[37]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[38],abshift_get(4),c2[39]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[36],abshift_get(59),c2[37]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[39],abshift_get(14),c2[40]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[53],abshift_get(27),c2[54]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[48],abshift_get(7),c2[49]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[53],abshift_get(14),c2[54]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[63],abshift_get(48),c2[64]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[63],abshift_get(11),c2[64]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[64],abshift_get(59),c2[65]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[76],abshift_get(19),c2[77]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[75],abshift_get(28),c2[76]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[76],abshift_get(2),c2[77]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[84],abshift_get(6),c2[85]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[89],abshift_get(6),c2[90]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[87],abshift_get(20),c2[88]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[96],abshift_get(6),c2[97]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[99],abshift_get(27),c2[100]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[97],abshift_get(51),c2[98]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[113],abshift_get(56),c2[114]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[111],abshift_get(45),c2[112]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[109],abshift_get(58),c2[110]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[112],abshift_get(8),c2[113]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[125],abshift_get(27),c2[126]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[122],abshift_get(60),c2[123]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[122],abshift_get(63),c2[123]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[134],abshift_get(40),c2[135]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[137],abshift_get(34),c2[138]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[137],abshift_get(44),c2[138]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[137],abshift_get(21),c2[138]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[145],abshift_get(12),c2[146]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[144],abshift_get(17),c2[145]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[148],abshift_get(34),c2[149]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[156],abshift_get(32),c2[157]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[160],abshift_get(3),c2[161]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[156],abshift_get(16),c2[157]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[172],abshift_get(20),c2[173]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[170],abshift_get(19),c2[171]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[172],abshift_get(15),c2[173]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[184],abshift_get(18),c2[185]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[182],abshift_get(30),c2[183]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[181],abshift_get(48),c2[182]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[194],abshift_get(37),c2[195]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[192],abshift_get(29),c2[193]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[197],abshift_get(43),c2[198]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[206],abshift_get(45),c2[207]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[206],abshift_get(62),c2[207]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[209],abshift_get(39),c2[210]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[220],abshift_get(45),c2[221]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[220],abshift_get(43),c2[221]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[221],abshift_get(10),c2[222]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[231],abshift_get(47),c2[232]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[228],abshift_get(6),c2[229]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[232],abshift_get(8),c2[233]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[240],abshift_get(5),c2[241]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[241],abshift_get(8),c2[242]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[241],abshift_get(34),c2[242]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[252],abshift_get(21),c2[253]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[254],abshift_get(43),c2[255]),_mm512_permutex2var_epi8(c2[252],abshift_get(32),c2[253]))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 21 + d2[126]=_mm512_xor_si512(_mm512_permutex2var_epi8(c2[15],abshift_get(13),c2[16]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[61],abshift_get(38),c2[62]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[197],abshift_get(8),c2[198]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[243],abshift_get(21),c2[244]),_mm512_permutex2var_epi8(c2[253],abshift_get(33),c2[254]))))); + +//row: 22 + d2[132]=_mm512_xor_si512(_mm512_permutex2var_epi8(c2[0],abshift_get(30),c2[1]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[144],abshift_get(11),c2[145]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[159],abshift_get(41),c2[160]),_mm512_permutex2var_epi8(c2[204],abshift_get(22),c2[205])))); + +//row: 23 + d2[138]=_mm512_xor_si512(_mm512_permutex2var_epi8(c2[12],abshift_get(24),c2[13]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[25],abshift_get(25),c2[26]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[120],abshift_get(61),c2[121]),_mm512_permutex2var_epi8(c2[216],abshift_get(27),c2[217])))); + +//row: 24 + d2[144]=_mm512_xor_si512(_mm512_permutex2var_epi8(c2[2],abshift_get(29),c2[3]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[4],abshift_get(54),c2[5]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[0],abshift_get(55),c2[1]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[1],abshift_get(62),c2[2]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[4],abshift_get(42),c2[5]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[15],abshift_get(61),c2[16]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[13],abshift_get(36),c2[14]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[17],abshift_get(1),c2[18]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[28],abshift_get(28),c2[29]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[28],abshift_get(54),c2[29]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[26],abshift_get(50),c2[27]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[39],abshift_get(27),c2[40]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[40],abshift_get(51),c2[41]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[39],abshift_get(42),c2[40]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[38],abshift_get(30),c2[39]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[50],abshift_get(10),c2[51]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[50],abshift_get(54),c2[51]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[49],abshift_get(61),c2[50]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[51],abshift_get(43),c2[52]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[60],abshift_get(31),c2[61]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[65],abshift_get(58),c2[66]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[61],abshift_get(42),c2[62]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[73],abshift_get(2),c2[74]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[72],abshift_get(11),c2[73]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[72],abshift_get(49),c2[73]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[86],abshift_get(53),c2[87]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[85],abshift_get(53),c2[86]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[84],abshift_get(3),c2[85]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[98],abshift_get(53),c2[99]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[96],abshift_get(10),c2[97]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[100],abshift_get(34),c2[101]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[110],abshift_get(39),c2[111]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[108],abshift_get(28),c2[109]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[112],abshift_get(41),c2[113]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[122],abshift_get(10),c2[123]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[125],abshift_get(43),c2[126]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[125],abshift_get(46),c2[126]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[137],abshift_get(23),c2[138]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[134],abshift_get(17),c2[135]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[134],abshift_get(27),c2[135]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[137],abshift_get(19),c2[138]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[147],abshift_get(59),c2[148]),_mm512_xor_si512(c2[147],_mm512_xor_si512(_mm512_permutex2var_epi8(c2[145],abshift_get(17),c2[146]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[159],abshift_get(15),c2[160]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[156],abshift_get(50),c2[157]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[158],abshift_get(63),c2[159]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[169],abshift_get(3),c2[170]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[173],abshift_get(2),c2[174]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[168],abshift_get(62),c2[169]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[181],abshift_get(1),c2[182]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[185],abshift_get(13),c2[186]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[184],abshift_get(31),c2[185]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[197],abshift_get(20),c2[198]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[195],abshift_get(12),c2[196]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[194],abshift_get(26),c2[195]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[209],abshift_get(28),c2[210]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[209],abshift_get(45),c2[210]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[206],abshift_get(22),c2[207]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[217],abshift_get(28),c2[218]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[217],abshift_get(26),c2[218]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[217],abshift_get(57),c2[218]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[228],abshift_get(30),c2[229]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[230],abshift_get(53),c2[231]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[228],abshift_get(55),c2[229]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[242],abshift_get(52),c2[243]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[243],abshift_get(55),c2[244]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[244],abshift_get(17),c2[245]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[255],abshift_get(4),c2[256]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[257],abshift_get(26),c2[258]),_mm512_permutex2var_epi8(c2[255],abshift_get(15),c2[256]))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 25 + d2[150]=_mm512_xor_si512(_mm512_permutex2var_epi8(c2[13],abshift_get(8),c2[14]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[72],abshift_get(17),c2[73]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[89],abshift_get(63),c2[90]),_mm512_permutex2var_epi8(c2[172],abshift_get(56),c2[173])))); + +//row: 26 + d2[156]=_mm512_xor_si512(_mm512_permutex2var_epi8(c2[1],abshift_get(7),c2[2]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[25],abshift_get(17),c2[26]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[49],abshift_get(12),c2[50]),_mm512_permutex2var_epi8(c2[182],abshift_get(8),c2[183])))); + +//row: 27 + d2[162]=_mm512_xor_si512(_mm512_permutex2var_epi8(c2[15],abshift_get(2),c2[16]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[75],abshift_get(2),c2[76]),_mm512_permutex2var_epi8(c2[97],abshift_get(37),c2[98]))); + +//row: 28 + d2[168]=_mm512_xor_si512(_mm512_permutex2var_epi8(c2[3],abshift_get(30),c2[4]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[48],abshift_get(19),c2[49]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[231],abshift_get(52),c2[232]),_mm512_permutex2var_epi8(c2[256],abshift_get(18),c2[257])))); + +//row: 29 + d2[174]=_mm512_xor_si512(_mm512_permutex2var_epi8(c2[0],abshift_get(2),c2[1]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[2],abshift_get(27),c2[3]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[4],abshift_get(28),c2[5]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[5],abshift_get(34),c2[6]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[5],abshift_get(35),c2[6]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[13],abshift_get(34),c2[14]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[17],abshift_get(9),c2[18]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[14],abshift_get(37),c2[15]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[14],abshift_get(38),c2[15]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[15],abshift_get(60),c2[16]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[26],abshift_get(1),c2[27]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[26],abshift_get(27),c2[27]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[24],abshift_get(23),c2[25]),_mm512_xor_si512(c2[37],_mm512_xor_si512(_mm512_permutex2var_epi8(c2[38],abshift_get(24),c2[39]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[37],abshift_get(14),c2[38]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[37],abshift_get(15),c2[38]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[53],abshift_get(47),c2[54]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[48],abshift_get(27),c2[49]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[53],abshift_get(33),c2[54]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[53],abshift_get(34),c2[54]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[64],abshift_get(4),c2[65]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[63],abshift_get(31),c2[64]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[65],abshift_get(15),c2[66]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[76],abshift_get(39),c2[77]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[75],abshift_get(48),c2[76]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[76],abshift_get(21),c2[77]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[76],abshift_get(22),c2[77]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[84],abshift_get(26),c2[85]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[89],abshift_get(26),c2[90]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[87],abshift_get(39),c2[88]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[87],abshift_get(40),c2[88]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[96],abshift_get(26),c2[97]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[99],abshift_get(47),c2[100]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[98],abshift_get(6),c2[99]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[98],abshift_get(7),c2[99]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[108],abshift_get(12),c2[109]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[112],abshift_get(1),c2[113]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[110],abshift_get(14),c2[111]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[125],abshift_get(47),c2[126]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[123],abshift_get(16),c2[124]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[123],abshift_get(18),c2[124]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[123],abshift_get(19),c2[124]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[134],abshift_get(60),c2[135]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[137],abshift_get(54),c2[138]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[137],abshift_get(63),c2[138]),_mm512_xor_si512(c2[132],_mm512_xor_si512(_mm512_permutex2var_epi8(c2[145],abshift_get(32),c2[146]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[144],abshift_get(37),c2[145]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[148],abshift_get(53),c2[149]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[148],abshift_get(54),c2[149]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[156],abshift_get(52),c2[157]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[160],abshift_get(23),c2[161]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[156],abshift_get(35),c2[157]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[156],abshift_get(36),c2[157]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[172],abshift_get(40),c2[173]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[170],abshift_get(39),c2[171]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[172],abshift_get(34),c2[173]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[172],abshift_get(35),c2[173]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[168],abshift_get(5),c2[169]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[184],abshift_get(38),c2[185]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[182],abshift_get(50),c2[183]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[182],abshift_get(4),c2[183]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[194],abshift_get(57),c2[195]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[192],abshift_get(49),c2[193]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[197],abshift_get(62),c2[198]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[197],abshift_get(63),c2[198]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[207],abshift_get(1),c2[208]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[207],abshift_get(18),c2[208]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[209],abshift_get(58),c2[210]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[209],abshift_get(59),c2[210]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[221],abshift_get(1),c2[222]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[220],abshift_get(63),c2[221]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[221],abshift_get(29),c2[222]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[221],abshift_get(30),c2[222]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[218],abshift_get(19),c2[219]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[232],abshift_get(3),c2[233]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[228],abshift_get(26),c2[229]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[232],abshift_get(28),c2[233]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[240],abshift_get(25),c2[241]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[241],abshift_get(28),c2[242]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[241],abshift_get(53),c2[242]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[241],abshift_get(54),c2[242]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[252],abshift_get(41),c2[253]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[254],abshift_get(63),c2[255]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[252],abshift_get(51),c2[253]),_mm512_permutex2var_epi8(c2[252],abshift_get(52),c2[253]))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 30 + d2[180]=_mm512_xor_si512(_mm512_permutex2var_epi8(c2[0],abshift_get(14),c2[1]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[2],abshift_get(39),c2[3]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[4],abshift_get(39),c2[5]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[4],abshift_get(40),c2[5]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[5],abshift_get(46),c2[6]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[5],abshift_get(47),c2[6]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[2],abshift_get(31),c2[3]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[13],abshift_get(46),c2[14]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[17],abshift_get(20),c2[18]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[17],abshift_get(21),c2[18]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[14],abshift_get(49),c2[15]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[14],abshift_get(50),c2[15]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[26],abshift_get(13),c2[27]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[26],abshift_get(39),c2[27]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[24],abshift_get(34),c2[25]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[24],abshift_get(35),c2[25]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[37],abshift_get(12),c2[38]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[38],abshift_get(36),c2[39]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[37],abshift_get(26),c2[38]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[37],abshift_get(27),c2[38]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[53],abshift_get(59),c2[54]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[48],abshift_get(38),c2[49]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[48],abshift_get(39),c2[49]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[53],abshift_get(45),c2[54]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[53],abshift_get(46),c2[54]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[64],abshift_get(16),c2[65]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[63],abshift_get(43),c2[64]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[65],abshift_get(26),c2[66]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[65],abshift_get(27),c2[66]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[76],abshift_get(51),c2[77]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[75],abshift_get(59),c2[76]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[75],abshift_get(60),c2[76]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[76],abshift_get(33),c2[77]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[76],abshift_get(34),c2[77]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[84],abshift_get(38),c2[85]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[89],abshift_get(37),c2[90]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[89],abshift_get(38),c2[90]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[87],abshift_get(51),c2[88]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[87],abshift_get(52),c2[88]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[96],abshift_get(38),c2[97]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[99],abshift_get(58),c2[100]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[99],abshift_get(59),c2[100]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[98],abshift_get(18),c2[99]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[98],abshift_get(19),c2[99]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[108],abshift_get(24),c2[109]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[112],abshift_get(13),c2[113]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[110],abshift_get(25),c2[111]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[110],abshift_get(26),c2[111]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[125],abshift_get(59),c2[126]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[123],abshift_get(27),c2[124]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[123],abshift_get(28),c2[124]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[123],abshift_get(30),c2[124]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[123],abshift_get(31),c2[124]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[123],abshift_get(37),c2[124]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[135],abshift_get(8),c2[136]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[132],abshift_get(2),c2[133]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[132],abshift_get(11),c2[133]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[132],abshift_get(12),c2[133]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[145],abshift_get(44),c2[146]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[144],abshift_get(49),c2[145]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[149],abshift_get(1),c2[150]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[149],abshift_get(2),c2[150]),_mm512_xor_si512(c2[157],_mm512_xor_si512(_mm512_permutex2var_epi8(c2[160],abshift_get(34),c2[161]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[160],abshift_get(35),c2[161]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[156],abshift_get(47),c2[157]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[156],abshift_get(48),c2[157]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[160],abshift_get(4),c2[161]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[172],abshift_get(52),c2[173]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[170],abshift_get(50),c2[171]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[170],abshift_get(51),c2[171]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[172],abshift_get(46),c2[173]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[172],abshift_get(47),c2[173]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[184],abshift_get(50),c2[185]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[182],abshift_get(62),c2[183]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[182],abshift_get(15),c2[183]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[182],abshift_get(16),c2[183]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[195],abshift_get(5),c2[196]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[192],abshift_get(61),c2[193]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[192],abshift_get(10),c2[193]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[192],abshift_get(11),c2[193]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[207],abshift_get(13),c2[208]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[207],abshift_get(29),c2[208]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[207],abshift_get(30),c2[208]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[204],abshift_get(6),c2[205]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[204],abshift_get(7),c2[205]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[221],abshift_get(13),c2[222]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[221],abshift_get(10),c2[222]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[221],abshift_get(11),c2[222]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[221],abshift_get(41),c2[222]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[221],abshift_get(42),c2[222]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[232],abshift_get(15),c2[233]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[228],abshift_get(38),c2[229]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[232],abshift_get(39),c2[233]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[232],abshift_get(40),c2[233]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[240],abshift_get(37),c2[241]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[241],abshift_get(39),c2[242]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[241],abshift_get(40),c2[242]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[242],abshift_get(1),c2[243]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[242],abshift_get(2),c2[243]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[252],abshift_get(53),c2[253]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[255],abshift_get(11),c2[256]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[252],abshift_get(63),c2[253]),c2[253]))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 31 + d2[186]=_mm512_xor_si512(_mm512_permutex2var_epi8(c2[2],abshift_get(53),c2[3]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[2],abshift_get(52),c2[3]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[5],abshift_get(14),c2[6]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[5],abshift_get(13),c2[6]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[1],abshift_get(15),c2[2]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[1],abshift_get(14),c2[2]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[2],abshift_get(22),c2[3]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[2],abshift_get(20),c2[3]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[2],abshift_get(21),c2[3]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[16],abshift_get(21),c2[17]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[16],abshift_get(20),c2[17]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[13],abshift_get(60),c2[14]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[13],abshift_get(59),c2[14]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[17],abshift_get(25),c2[18]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[17],abshift_get(23),c2[18]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[17],abshift_get(24),c2[18]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[13],abshift_get(36),c2[14]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[28],abshift_get(52),c2[29]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[28],abshift_get(51),c2[29]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[29],abshift_get(14),c2[30]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[29],abshift_get(13),c2[30]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[27],abshift_get(10),c2[28]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[27],abshift_get(9),c2[28]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[39],abshift_get(51),c2[40]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[39],abshift_get(50),c2[40]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[41],abshift_get(11),c2[42]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[41],abshift_get(10),c2[42]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[40],abshift_get(2),c2[41]),_mm512_xor_si512(c2[40],_mm512_xor_si512(_mm512_permutex2var_epi8(c2[40],abshift_get(1),c2[41]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[50],abshift_get(34),c2[51]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[50],abshift_get(33),c2[51]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[51],abshift_get(14),c2[52]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[51],abshift_get(13),c2[52]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[50],abshift_get(21),c2[51]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[50],abshift_get(19),c2[51]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[50],abshift_get(20),c2[51]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[60],abshift_get(55),c2[61]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[60],abshift_get(54),c2[61]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[60],abshift_get(18),c2[61]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[60],abshift_get(17),c2[61]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[62],abshift_get(2),c2[63]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[62],abshift_get(1),c2[63]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[73],abshift_get(26),c2[74]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[73],abshift_get(25),c2[74]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[72],abshift_get(35),c2[73]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[72],abshift_get(34),c2[73]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[73],abshift_get(9),c2[74]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[73],abshift_get(7),c2[74]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[73],abshift_get(8),c2[74]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[87],abshift_get(13),c2[88]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[87],abshift_get(12),c2[88]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[86],abshift_get(13),c2[87]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[86],abshift_get(12),c2[87]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[84],abshift_get(27),c2[85]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[84],abshift_get(25),c2[85]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[84],abshift_get(26),c2[85]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[87],abshift_get(23),c2[88]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[99],abshift_get(13),c2[100]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[99],abshift_get(12),c2[100]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[96],abshift_get(34),c2[97]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[96],abshift_get(33),c2[97]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[100],abshift_get(58),c2[101]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[100],abshift_get(56),c2[101]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[100],abshift_get(57),c2[101]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[110],abshift_get(63),c2[111]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[110],abshift_get(62),c2[111]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[108],abshift_get(52),c2[109]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[108],abshift_get(51),c2[109]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[113],abshift_get(1),c2[114]),_mm512_xor_si512(c2[113],_mm512_xor_si512(_mm512_permutex2var_epi8(c2[122],abshift_get(34),c2[123]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[122],abshift_get(33),c2[123]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[120],abshift_get(3),c2[121]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[120],abshift_get(2),c2[121]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[120],abshift_get(6),c2[121]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[120],abshift_get(4),c2[121]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[120],abshift_get(5),c2[121]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[137],abshift_get(47),c2[138]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[137],abshift_get(46),c2[138]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[134],abshift_get(41),c2[135]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[134],abshift_get(40),c2[135]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[134],abshift_get(51),c2[135]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[134],abshift_get(49),c2[135]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[134],abshift_get(50),c2[135]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[148],abshift_get(19),c2[149]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[148],abshift_get(18),c2[149]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[147],abshift_get(24),c2[148]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[147],abshift_get(23),c2[148]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[145],abshift_get(41),c2[146]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[145],abshift_get(39),c2[146]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[145],abshift_get(40),c2[146]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[159],abshift_get(39),c2[160]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[159],abshift_get(38),c2[160]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[157],abshift_get(10),c2[158]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[157],abshift_get(9),c2[158]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[159],abshift_get(23),c2[160]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[159],abshift_get(21),c2[160]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[159],abshift_get(22),c2[160]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[169],abshift_get(27),c2[170]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[169],abshift_get(26),c2[170]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[173],abshift_get(26),c2[174]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[173],abshift_get(25),c2[174]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[169],abshift_get(22),c2[170]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[169],abshift_get(20),c2[170]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[169],abshift_get(21),c2[170]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[181],abshift_get(25),c2[182]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[181],abshift_get(24),c2[182]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[185],abshift_get(37),c2[186]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[185],abshift_get(36),c2[186]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[184],abshift_get(55),c2[185]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[184],abshift_get(54),c2[185]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[197],abshift_get(44),c2[198]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[197],abshift_get(43),c2[198]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[195],abshift_get(36),c2[196]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[195],abshift_get(35),c2[196]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[194],abshift_get(50),c2[195]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[194],abshift_get(48),c2[195]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[194],abshift_get(49),c2[195]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[209],abshift_get(52),c2[210]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[209],abshift_get(51),c2[210]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[204],abshift_get(5),c2[205]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[204],abshift_get(4),c2[205]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[206],abshift_get(46),c2[207]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[206],abshift_get(44),c2[207]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[206],abshift_get(45),c2[207]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[217],abshift_get(52),c2[218]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[217],abshift_get(51),c2[218]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[217],abshift_get(50),c2[218]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[217],abshift_get(49),c2[218]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[218],abshift_get(17),c2[219]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[218],abshift_get(15),c2[219]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[218],abshift_get(16),c2[219]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[228],abshift_get(54),c2[229]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[228],abshift_get(53),c2[229]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[231],abshift_get(13),c2[232]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[231],abshift_get(12),c2[232]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[229],abshift_get(15),c2[230]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[229],abshift_get(14),c2[230]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[243],abshift_get(12),c2[244]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[243],abshift_get(11),c2[244]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[244],abshift_get(15),c2[245]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[244],abshift_get(14),c2[245]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[244],abshift_get(41),c2[245]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[244],abshift_get(39),c2[245]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[244],abshift_get(40),c2[245]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[255],abshift_get(28),c2[256]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[255],abshift_get(27),c2[256]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[257],abshift_get(50),c2[258]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[257],abshift_get(49),c2[258]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[255],abshift_get(39),c2[256]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[255],abshift_get(37),c2[256]),_mm512_permutex2var_epi8(c2[255],abshift_get(38),c2[256]))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 32 + d2[192]=_mm512_xor_si512(_mm512_permutex2var_epi8(c2[3],abshift_get(19),c2[4]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[5],abshift_get(44),c2[6]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[1],abshift_get(44),c2[2]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[1],abshift_get(45),c2[2]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[2],abshift_get(51),c2[3]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[2],abshift_get(52),c2[3]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[1],abshift_get(38),c2[2]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[16],abshift_get(51),c2[17]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[14],abshift_get(25),c2[15]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[14],abshift_get(26),c2[15]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[17],abshift_get(54),c2[18]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[17],abshift_get(55),c2[18]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[29],abshift_get(18),c2[30]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[29],abshift_get(44),c2[30]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[27],abshift_get(39),c2[28]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[27],abshift_get(40),c2[28]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[40],abshift_get(17),c2[41]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[41],abshift_get(41),c2[42]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[40],abshift_get(31),c2[41]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[40],abshift_get(32),c2[41]),_mm512_xor_si512(c2[51],_mm512_xor_si512(_mm512_permutex2var_epi8(c2[51],abshift_get(43),c2[52]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[51],abshift_get(44),c2[52]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[50],abshift_get(50),c2[51]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[50],abshift_get(51),c2[51]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[61],abshift_get(21),c2[62]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[60],abshift_get(48),c2[61]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[62],abshift_get(31),c2[63]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[62],abshift_get(32),c2[63]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[73],abshift_get(56),c2[74]),_mm512_xor_si512(c2[73],_mm512_xor_si512(_mm512_permutex2var_epi8(c2[73],abshift_get(1),c2[74]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[73],abshift_get(38),c2[74]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[73],abshift_get(39),c2[74]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[87],abshift_get(43),c2[88]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[86],abshift_get(42),c2[87]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[86],abshift_get(43),c2[87]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[84],abshift_get(56),c2[85]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[84],abshift_get(57),c2[85]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[99],abshift_get(43),c2[100]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[96],abshift_get(63),c2[97]),_mm512_xor_si512(c2[97],_mm512_xor_si512(_mm512_permutex2var_epi8(c2[101],abshift_get(23),c2[102]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[101],abshift_get(24),c2[102]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[111],abshift_get(29),c2[112]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[109],abshift_get(18),c2[110]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[113],abshift_get(30),c2[114]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[113],abshift_get(31),c2[114]),_mm512_xor_si512(c2[123],_mm512_xor_si512(_mm512_permutex2var_epi8(c2[120],abshift_get(32),c2[121]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[120],abshift_get(33),c2[121]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[120],abshift_get(35),c2[121]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[120],abshift_get(36),c2[121]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[132],abshift_get(13),c2[133]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[135],abshift_get(7),c2[136]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[135],abshift_get(16),c2[136]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[135],abshift_get(17),c2[136]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[148],abshift_get(49),c2[149]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[147],abshift_get(54),c2[148]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[146],abshift_get(6),c2[147]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[146],abshift_get(7),c2[147]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[147],abshift_get(9),c2[148]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[160],abshift_get(5),c2[161]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[157],abshift_get(39),c2[158]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[157],abshift_get(40),c2[158]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[159],abshift_get(52),c2[160]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[159],abshift_get(53),c2[160]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[169],abshift_get(57),c2[170]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[173],abshift_get(55),c2[174]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[173],abshift_get(56),c2[174]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[169],abshift_get(51),c2[170]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[169],abshift_get(52),c2[170]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[170],abshift_get(47),c2[171]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[181],abshift_get(55),c2[182]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[180],abshift_get(3),c2[181]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[185],abshift_get(20),c2[186]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[185],abshift_get(21),c2[186]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[192],abshift_get(10),c2[193]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[196],abshift_get(2),c2[197]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[195],abshift_get(15),c2[196]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[195],abshift_get(16),c2[196]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[204],abshift_get(18),c2[205]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[204],abshift_get(34),c2[205]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[204],abshift_get(35),c2[205]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[207],abshift_get(11),c2[208]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[207],abshift_get(12),c2[208]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[218],abshift_get(18),c2[219]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[218],abshift_get(15),c2[219]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[218],abshift_get(16),c2[219]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[218],abshift_get(46),c2[219]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[218],abshift_get(47),c2[219]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[229],abshift_get(20),c2[230]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[231],abshift_get(43),c2[232]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[229],abshift_get(44),c2[230]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[229],abshift_get(45),c2[230]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[243],abshift_get(42),c2[244]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[244],abshift_get(44),c2[245]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[244],abshift_get(45),c2[245]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[245],abshift_get(6),c2[246]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[245],abshift_get(7),c2[246]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[255],abshift_get(58),c2[256]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[252],abshift_get(16),c2[253]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[256],abshift_get(4),c2[257]),_mm512_permutex2var_epi8(c2[256],abshift_get(5),c2[257])))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 33 + d2[198]=_mm512_xor_si512(_mm512_permutex2var_epi8(c2[17],abshift_get(3),c2[18]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[24],abshift_get(8),c2[25]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[137],abshift_get(41),c2[138]),_mm512_permutex2var_epi8(c2[253],abshift_get(41),c2[254])))); + +//row: 34 + d2[204]=_mm512_xor_si512(_mm512_permutex2var_epi8(c2[3],abshift_get(38),c2[4]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[86],abshift_get(20),c2[87]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[183],abshift_get(10),c2[184]),_mm512_permutex2var_epi8(c2[208],abshift_get(56),c2[209])))); + +//row: 35 + d2[210]=_mm512_xor_si512(_mm512_permutex2var_epi8(c2[2],abshift_get(61),c2[3]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[5],abshift_get(22),c2[6]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[1],abshift_get(23),c2[2]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[2],abshift_get(30),c2[3]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[16],abshift_get(29),c2[17]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[14],abshift_get(4),c2[15]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[17],abshift_get(33),c2[18]),_mm512_xor_si512(c2[17],_mm512_xor_si512(_mm512_permutex2var_epi8(c2[28],abshift_get(60),c2[29]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[29],abshift_get(22),c2[30]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[27],abshift_get(18),c2[28]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[39],abshift_get(59),c2[40]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[41],abshift_get(19),c2[42]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[40],abshift_get(10),c2[41]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[50],abshift_get(42),c2[51]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[51],abshift_get(22),c2[52]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[50],abshift_get(29),c2[51]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[60],abshift_get(63),c2[61]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[60],abshift_get(26),c2[61]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[62],abshift_get(10),c2[63]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[73],abshift_get(34),c2[74]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[72],abshift_get(43),c2[73]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[73],abshift_get(17),c2[74]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[77],abshift_get(15),c2[78]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[87],abshift_get(21),c2[88]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[86],abshift_get(21),c2[87]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[84],abshift_get(35),c2[85]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[99],abshift_get(21),c2[100]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[96],abshift_get(42),c2[97]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[101],abshift_get(2),c2[102]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[111],abshift_get(7),c2[112]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[108],abshift_get(60),c2[109]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[113],abshift_get(9),c2[114]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[122],abshift_get(42),c2[123]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[120],abshift_get(11),c2[121]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[120],abshift_get(14),c2[121]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[137],abshift_get(55),c2[138]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[134],abshift_get(49),c2[135]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[134],abshift_get(59),c2[135]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[148],abshift_get(27),c2[149]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[147],abshift_get(32),c2[148]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[145],abshift_get(49),c2[146]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[144],abshift_get(2),c2[145]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[159],abshift_get(47),c2[160]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[157],abshift_get(18),c2[158]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[159],abshift_get(31),c2[160]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[169],abshift_get(35),c2[170]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[173],abshift_get(34),c2[174]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[169],abshift_get(30),c2[170]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[181],abshift_get(33),c2[182]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[185],abshift_get(45),c2[186]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[184],abshift_get(63),c2[185]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[197],abshift_get(52),c2[198]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[195],abshift_get(44),c2[196]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[194],abshift_get(58),c2[195]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[209],abshift_get(60),c2[210]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[204],abshift_get(13),c2[205]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[206],abshift_get(54),c2[207]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[217],abshift_get(60),c2[218]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[217],abshift_get(58),c2[218]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[218],abshift_get(25),c2[219]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[228],abshift_get(62),c2[229]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[231],abshift_get(21),c2[232]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[229],abshift_get(23),c2[230]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[243],abshift_get(20),c2[244]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[244],abshift_get(23),c2[245]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[244],abshift_get(49),c2[245]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[255],abshift_get(36),c2[256]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[257],abshift_get(58),c2[258]),_mm512_permutex2var_epi8(c2[255],abshift_get(47),c2[256])))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 36 + d2[216]=_mm512_xor_si512(_mm512_permutex2var_epi8(c2[3],abshift_get(18),c2[4]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[172],abshift_get(57),c2[173]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[184],abshift_get(41),c2[185]),_mm512_permutex2var_epi8(c2[216],abshift_get(21),c2[217])))); + +//row: 37 + d2[222]=_mm512_xor_si512(_mm512_permutex2var_epi8(c2[0],abshift_get(38),c2[1]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[0],abshift_get(39),c2[1]),_mm512_xor_si512(c2[3],_mm512_xor_si512(_mm512_permutex2var_epi8(c2[5],abshift_get(1),c2[6]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[0],abshift_get(8),c2[1]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[14],abshift_get(6),c2[15]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[14],abshift_get(7),c2[15]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[17],abshift_get(46),c2[18]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[15],abshift_get(11),c2[16]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[16],abshift_get(13),c2[17]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[26],abshift_get(37),c2[27]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[26],abshift_get(38),c2[27]),_mm512_xor_si512(c2[27],_mm512_xor_si512(_mm512_permutex2var_epi8(c2[24],abshift_get(60),c2[25]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[37],abshift_get(36),c2[38]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[37],abshift_get(37),c2[38]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[38],abshift_get(61),c2[39]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[37],abshift_get(52),c2[38]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[48],abshift_get(20),c2[49]),_mm512_xor_si512(c2[49],_mm512_xor_si512(_mm512_permutex2var_epi8(c2[48],abshift_get(7),c2[49]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[64],abshift_get(40),c2[65]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[64],abshift_get(41),c2[65]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[64],abshift_get(4),c2[65]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[65],abshift_get(52),c2[66]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[77],abshift_get(11),c2[78]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[77],abshift_get(12),c2[78]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[76],abshift_get(21),c2[77]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[76],abshift_get(59),c2[77]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[84],abshift_get(63),c2[85]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[89],abshift_get(63),c2[90]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[88],abshift_get(13),c2[89]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[96],abshift_get(63),c2[97]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[100],abshift_get(20),c2[101]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[98],abshift_get(44),c2[99]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[108],abshift_get(48),c2[109]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[108],abshift_get(49),c2[109]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[112],abshift_get(38),c2[113]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[110],abshift_get(51),c2[111]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[120],abshift_get(19),c2[121]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[120],abshift_get(20),c2[121]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[123],abshift_get(53),c2[124]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[123],abshift_get(56),c2[124]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[135],abshift_get(32),c2[136]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[135],abshift_get(33),c2[136]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[132],abshift_get(27),c2[133]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[132],abshift_get(37),c2[133]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[146],abshift_get(4),c2[147]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[146],abshift_get(5),c2[147]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[145],abshift_get(10),c2[146]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[149],abshift_get(27),c2[150]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[157],abshift_get(24),c2[158]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[157],abshift_get(25),c2[158]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[160],abshift_get(60),c2[161]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[157],abshift_get(9),c2[158]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[157],abshift_get(18),c2[158]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[173],abshift_get(13),c2[174]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[171],abshift_get(12),c2[172]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[173],abshift_get(8),c2[174]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[185],abshift_get(10),c2[186]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[185],abshift_get(11),c2[186]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[183],abshift_get(23),c2[184]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[182],abshift_get(41),c2[183]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[195],abshift_get(29),c2[196]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[195],abshift_get(30),c2[196]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[193],abshift_get(22),c2[194]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[192],abshift_get(36),c2[193]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[207],abshift_get(38),c2[208]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[207],abshift_get(55),c2[208]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[204],abshift_get(32),c2[205]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[221],abshift_get(37),c2[222]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[221],abshift_get(38),c2[222]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[221],abshift_get(36),c2[222]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[216],abshift_get(3),c2[217]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[232],abshift_get(39),c2[233]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[232],abshift_get(40),c2[233]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[228],abshift_get(63),c2[229]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[233],abshift_get(1),c2[234]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[240],abshift_get(61),c2[241]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[240],abshift_get(62),c2[241]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[242],abshift_get(1),c2[243]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[242],abshift_get(27),c2[243]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[253],abshift_get(13),c2[254]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[253],abshift_get(14),c2[254]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[255],abshift_get(36),c2[256]),_mm512_permutex2var_epi8(c2[253],abshift_get(25),c2[254])))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 38 + d2[228]=_mm512_xor_si512(_mm512_permutex2var_epi8(c2[2],abshift_get(57),c2[3]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[110],abshift_get(49),c2[111]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[124],abshift_get(33),c2[125]),_mm512_permutex2var_epi8(c2[147],abshift_get(22),c2[148])))); + +//row: 39 + d2[234]=_mm512_xor_si512(_mm512_permutex2var_epi8(c2[16],abshift_get(2),c2[17]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[37],abshift_get(29),c2[38]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[89],abshift_get(26),c2[90]),_mm512_permutex2var_epi8(c2[232],abshift_get(41),c2[233])))); + +//row: 40 + d2[240]=_mm512_xor_si512(_mm512_permutex2var_epi8(c2[2],abshift_get(47),c2[3]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[96],abshift_get(37),c2[97]),_mm512_permutex2var_epi8(c2[208],abshift_get(56),c2[209]))); + +//row: 41 + d2[246]=_mm512_xor_si512(_mm512_permutex2var_epi8(c2[12],abshift_get(52),c2[13]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[40],abshift_get(58),c2[41]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[110],abshift_get(11),c2[111]),_mm512_permutex2var_epi8(c2[220],abshift_get(32),c2[221])))); + +//row: 42 + d2[252]=_mm512_xor_si512(_mm512_permutex2var_epi8(c2[2],abshift_get(14),c2[3]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[4],abshift_get(39),c2[5]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[0],abshift_get(39),c2[1]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[0],abshift_get(40),c2[1]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[1],abshift_get(46),c2[2]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[1],abshift_get(47),c2[2]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[1],abshift_get(49),c2[2]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[15],abshift_get(46),c2[16]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[13],abshift_get(20),c2[14]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[13],abshift_get(21),c2[14]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[16],abshift_get(49),c2[17]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[16],abshift_get(50),c2[17]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[28],abshift_get(13),c2[29]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[28],abshift_get(39),c2[29]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[26],abshift_get(34),c2[27]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[26],abshift_get(35),c2[27]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[39],abshift_get(12),c2[40]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[40],abshift_get(36),c2[41]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[39],abshift_get(26),c2[40]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[39],abshift_get(27),c2[40]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[49],abshift_get(59),c2[50]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[50],abshift_get(38),c2[51]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[50],abshift_get(39),c2[51]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[49],abshift_get(45),c2[50]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[49],abshift_get(46),c2[50]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[48],abshift_get(14),c2[49]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[60],abshift_get(16),c2[61]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[65],abshift_get(43),c2[66]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[61],abshift_get(26),c2[62]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[61],abshift_get(27),c2[62]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[72],abshift_get(51),c2[73]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[77],abshift_get(59),c2[78]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[77],abshift_get(60),c2[78]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[72],abshift_get(33),c2[73]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[72],abshift_get(34),c2[73]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[86],abshift_get(38),c2[87]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[85],abshift_get(37),c2[86]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[85],abshift_get(38),c2[86]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[89],abshift_get(51),c2[90]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[89],abshift_get(52),c2[90]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[98],abshift_get(38),c2[99]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[101],abshift_get(58),c2[102]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[101],abshift_get(59),c2[102]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[100],abshift_get(18),c2[101]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[100],abshift_get(19),c2[101]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[110],abshift_get(24),c2[111]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[108],abshift_get(13),c2[109]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[112],abshift_get(25),c2[113]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[112],abshift_get(26),c2[113]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[121],abshift_get(59),c2[122]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[125],abshift_get(27),c2[126]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[125],abshift_get(28),c2[126]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[125],abshift_get(30),c2[126]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[125],abshift_get(31),c2[126]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[137],abshift_get(8),c2[138]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[134],abshift_get(2),c2[135]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[134],abshift_get(11),c2[135]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[134],abshift_get(12),c2[135]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[147],abshift_get(44),c2[148]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[146],abshift_get(49),c2[147]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[145],abshift_get(1),c2[146]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[145],abshift_get(2),c2[146]),_mm512_xor_si512(c2[159],_mm512_xor_si512(_mm512_permutex2var_epi8(c2[156],abshift_get(34),c2[157]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[156],abshift_get(35),c2[157]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[158],abshift_get(47),c2[159]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[158],abshift_get(48),c2[159]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[168],abshift_get(52),c2[169]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[172],abshift_get(50),c2[173]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[172],abshift_get(51),c2[173]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[168],abshift_get(46),c2[169]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[168],abshift_get(47),c2[169]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[180],abshift_get(50),c2[181]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[184],abshift_get(62),c2[185]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[184],abshift_get(15),c2[185]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[184],abshift_get(16),c2[185]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[197],abshift_get(5),c2[198]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[194],abshift_get(61),c2[195]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[194],abshift_get(10),c2[195]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[194],abshift_get(11),c2[195]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[209],abshift_get(13),c2[210]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[209],abshift_get(29),c2[210]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[209],abshift_get(30),c2[210]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[206],abshift_get(6),c2[207]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[206],abshift_get(7),c2[207]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[217],abshift_get(13),c2[218]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[217],abshift_get(10),c2[218]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[217],abshift_get(11),c2[218]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[217],abshift_get(41),c2[218]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[217],abshift_get(42),c2[218]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[228],abshift_get(15),c2[229]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[230],abshift_get(38),c2[231]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[228],abshift_get(39),c2[229]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[228],abshift_get(40),c2[229]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[242],abshift_get(37),c2[243]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[243],abshift_get(39),c2[244]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[243],abshift_get(40),c2[244]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[244],abshift_get(1),c2[245]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[244],abshift_get(2),c2[245]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[254],abshift_get(53),c2[255]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[257],abshift_get(11),c2[258]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[254],abshift_get(63),c2[255]),c2[255])))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 43 + d2[258]=_mm512_xor_si512(_mm512_permutex2var_epi8(c2[1],abshift_get(28),c2[2]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[3],abshift_get(53),c2[4]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[5],abshift_get(54),c2[6]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[0],abshift_get(60),c2[1]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[0],abshift_get(61),c2[1]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[14],abshift_get(60),c2[15]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[12],abshift_get(35),c2[13]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[15],abshift_get(63),c2[16]),_mm512_xor_si512(c2[16],_mm512_xor_si512(_mm512_permutex2var_epi8(c2[13],abshift_get(49),c2[14]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[27],abshift_get(27),c2[28]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[27],abshift_get(53),c2[28]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[25],abshift_get(49),c2[26]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[38],abshift_get(26),c2[39]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[39],abshift_get(50),c2[40]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[38],abshift_get(40),c2[39]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[38],abshift_get(41),c2[39]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[49],abshift_get(9),c2[50]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[49],abshift_get(53),c2[50]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[48],abshift_get(59),c2[49]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[48],abshift_get(60),c2[49]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[65],abshift_get(30),c2[66]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[64],abshift_get(57),c2[65]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[60],abshift_get(41),c2[61]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[72],abshift_get(1),c2[73]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[77],abshift_get(10),c2[78]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[77],abshift_get(47),c2[78]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[77],abshift_get(48),c2[78]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[85],abshift_get(52),c2[86]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[84],abshift_get(52),c2[85]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[89],abshift_get(1),c2[90]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[89],abshift_get(2),c2[90]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[97],abshift_get(52),c2[98]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[101],abshift_get(9),c2[102]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[99],abshift_get(32),c2[100]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[99],abshift_get(33),c2[100]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[109],abshift_get(38),c2[110]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[113],abshift_get(27),c2[114]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[111],abshift_get(40),c2[112]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[121],abshift_get(9),c2[122]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[124],abshift_get(42),c2[125]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[124],abshift_get(44),c2[125]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[124],abshift_get(45),c2[125]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[136],abshift_get(22),c2[137]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[133],abshift_get(16),c2[134]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[133],abshift_get(25),c2[134]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[133],abshift_get(26),c2[134]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[146],abshift_get(58),c2[147]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[145],abshift_get(63),c2[146]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[144],abshift_get(15),c2[145]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[144],abshift_get(16),c2[145]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[158],abshift_get(14),c2[159]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[161],abshift_get(49),c2[162]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[157],abshift_get(61),c2[158]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[157],abshift_get(62),c2[158]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[168],abshift_get(2),c2[169]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[172],abshift_get(1),c2[173]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[173],abshift_get(60),c2[174]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[173],abshift_get(61),c2[174]),_mm512_xor_si512(c2[180],_mm512_xor_si512(_mm512_permutex2var_epi8(c2[184],abshift_get(12),c2[185]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[183],abshift_get(30),c2[184]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[196],abshift_get(19),c2[197]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[194],abshift_get(11),c2[195]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[193],abshift_get(24),c2[194]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[193],abshift_get(25),c2[194]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[194],abshift_get(4),c2[195]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[208],abshift_get(27),c2[209]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[208],abshift_get(44),c2[209]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[205],abshift_get(20),c2[206]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[205],abshift_get(21),c2[206]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[216],abshift_get(27),c2[217]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[216],abshift_get(25),c2[217]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[216],abshift_get(55),c2[217]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[216],abshift_get(56),c2[217]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[217],abshift_get(50),c2[218]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[233],abshift_get(29),c2[234]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[229],abshift_get(52),c2[230]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[233],abshift_get(54),c2[234]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[241],abshift_get(51),c2[242]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[242],abshift_get(54),c2[243]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[243],abshift_get(15),c2[244]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[243],abshift_get(16),c2[244]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[254],abshift_get(3),c2[255]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[256],abshift_get(25),c2[257]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[254],abshift_get(13),c2[255]),_mm512_permutex2var_epi8(c2[254],abshift_get(14),c2[255]))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 44 + d2[264]=_mm512_xor_si512(_mm512_permutex2var_epi8(c2[3],abshift_get(5),c2[4]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[5],abshift_get(30),c2[6]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[1],abshift_get(31),c2[2]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[2],abshift_get(38),c2[3]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[1],abshift_get(16),c2[2]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[16],abshift_get(37),c2[17]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[14],abshift_get(12),c2[15]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[17],abshift_get(41),c2[18]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[29],abshift_get(4),c2[30]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[29],abshift_get(30),c2[30]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[27],abshift_get(26),c2[28]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[40],abshift_get(3),c2[41]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[41],abshift_get(27),c2[42]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[40],abshift_get(18),c2[41]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[50],abshift_get(50),c2[51]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[51],abshift_get(30),c2[52]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[50],abshift_get(37),c2[51]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[61],abshift_get(7),c2[62]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[60],abshift_get(34),c2[61]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[62],abshift_get(18),c2[63]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[73],abshift_get(42),c2[74]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[72],abshift_get(51),c2[73]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[73],abshift_get(25),c2[74]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[87],abshift_get(29),c2[88]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[86],abshift_get(29),c2[87]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[84],abshift_get(43),c2[85]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[85],abshift_get(14),c2[86]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[99],abshift_get(29),c2[100]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[96],abshift_get(50),c2[97]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[101],abshift_get(10),c2[102]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[111],abshift_get(15),c2[112]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[109],abshift_get(4),c2[110]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[113],abshift_get(17),c2[114]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[110],abshift_get(35),c2[111]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[122],abshift_get(50),c2[123]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[120],abshift_get(19),c2[121]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[120],abshift_get(22),c2[121]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[137],abshift_get(63),c2[138]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[134],abshift_get(57),c2[135]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[135],abshift_get(3),c2[136]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[148],abshift_get(35),c2[149]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[147],abshift_get(40),c2[148]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[145],abshift_get(57),c2[146]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[159],abshift_get(55),c2[160]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[157],abshift_get(26),c2[158]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[159],abshift_get(39),c2[160]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[169],abshift_get(43),c2[170]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[173],abshift_get(42),c2[174]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[169],abshift_get(38),c2[170]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[181],abshift_get(41),c2[182]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[185],abshift_get(53),c2[186]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[185],abshift_get(7),c2[186]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[197],abshift_get(60),c2[198]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[195],abshift_get(52),c2[196]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[195],abshift_get(2),c2[196]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[204],abshift_get(4),c2[205]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[204],abshift_get(21),c2[205]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[206],abshift_get(62),c2[207]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[218],abshift_get(4),c2[219]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[218],abshift_get(2),c2[219]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[218],abshift_get(33),c2[219]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[229],abshift_get(6),c2[230]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[231],abshift_get(29),c2[232]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[229],abshift_get(31),c2[230]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[243],abshift_get(28),c2[244]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[244],abshift_get(31),c2[245]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[244],abshift_get(57),c2[245]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[255],abshift_get(44),c2[256]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[252],abshift_get(2),c2[253]),_mm512_permutex2var_epi8(c2[255],abshift_get(55),c2[256])))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + +//row: 45 + d2[270]=_mm512_xor_si512(_mm512_permutex2var_epi8(c2[14],abshift_get(7),c2[15]),_mm512_xor_si512(_mm512_permutex2var_epi8(c2[74],abshift_get(21),c2[75]),_mm512_permutex2var_epi8(c2[120],abshift_get(15),c2[121]))); + } +} diff --git a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_encode_parity_check.c b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_encode_parity_check.c index 94eb0a4d92..70bc03b953 100644 --- a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_encode_parity_check.c +++ b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_encode_parity_check.c @@ -36,13 +36,27 @@ #include "assertions.h" #include "common/utils/LOG/log.h" - +#define USE_PERMUTEX +#ifdef __aarch64__ +#define USE_ALIGNR +#endif #ifdef __AVX512F__ +#if defined(__AVX512VBMI__) && defined(USE_PERMUTEX) +// For AVX512 machines, use an AVX512 version of the encoder for Zc=384 only for now. This is used almost exclusively for +// high-throughput cases. The version with "permutex2var" instruction uses less memory (i.e. 1/64th of the memory to store the +// input), but uses more reads instead of creating 64 shifts of the input with memcpy +#include "ldpc384_simd512_permutex_byte.c" +#else #include "ldpc384_simd512_byte.c" +#endif #else #include "ldpc384_byte.c" #endif +#ifdef USE_ALIGNR +#include "ldpc384_alignr_byte_128.c" +#else #include "ldpc384_byte_128.c" +#endif #include "ldpc352_byte.c" #include "ldpc352_byte_128.c" #include "ldpc320_byte.c" @@ -96,8 +110,13 @@ static void encode_parity_check_part_optim(uint8_t *cc, uint8_t *d, short BG,sho memcpy(&c[2 * i1 * Zc], &cc[i1 * Zc], Zc * sizeof(unsigned char)); memcpy(&c[(2 * i1 + 1) * Zc], &cc[i1 * Zc], Zc * sizeof(unsigned char)); } - for (int i1 = 1; i1 < simd_size; i1++) { - memcpy(&c[(2 * ncols * Zc * i1)], &c[i1], (2 * ncols * Zc * sizeof(unsigned char)) - i1); +#if (defined(USE_PERMUTEX) && defined(__AVX512VBMI__)) || defined(USE_ALIGNR) + if (Zc < 384 || BG == 2) +#endif + { + for (int i1 = 1; i1 < simd_size; i1++) { + memcpy(&c[(2 * ncols * Zc * i1)], &c[i1], (2 * ncols * Zc * sizeof(unsigned char)) - i1); + } } if (BG == 1) { switch (Zc) { From 69de8cbc24e56ea73f344df6bfb7242c104b6744 Mon Sep 17 00:00:00 2001 From: Reem Bahsoun Date: Tue, 2 Sep 2025 09:52:23 +0200 Subject: [PATCH 594/964] Change cuBB tag to release 25-2 in YAML and documentation --- ci-scripts/yaml_files/sa_gnb_aerial/docker-compose.yaml | 2 +- doc/Aerial_FAPI_Split_Tutorial.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ci-scripts/yaml_files/sa_gnb_aerial/docker-compose.yaml b/ci-scripts/yaml_files/sa_gnb_aerial/docker-compose.yaml index d11a97c186..efc4d15b72 100644 --- a/ci-scripts/yaml_files/sa_gnb_aerial/docker-compose.yaml +++ b/ci-scripts/yaml_files/sa_gnb_aerial/docker-compose.yaml @@ -23,7 +23,7 @@ services: - ../../../cmake_targets/share:/opt/cuBB/share userns_mode: host ipc: "shareable" - image: cubb-build:25-1 + image: cubb-build:25-2 environment: - cuBB_SDK=/opt/nvidia/cuBB command: bash -c "sudo rm -rf /tmp/phy.log && sudo chmod +x /opt/nvidia/cuBB/aerial_l1_entrypoint.sh && /opt/nvidia/cuBB/aerial_l1_entrypoint.sh" diff --git a/doc/Aerial_FAPI_Split_Tutorial.md b/doc/Aerial_FAPI_Split_Tutorial.md index 4192a8689f..942b706d37 100644 --- a/doc/Aerial_FAPI_Split_Tutorial.md +++ b/doc/Aerial_FAPI_Split_Tutorial.md @@ -230,10 +230,10 @@ After preparing the L1 software, the container needs to be committed to create a In this file the RU MAC address needs to be specified before commiting the image. ```bash -~$ docker commit nv-cubb cubb-build:25-1 +~$ docker commit nv-cubb cubb-build:25-2 ~$ docker image ls .. -cubb-build 25-1 824156e0334c 2 weeks ago 23.9GB +cubb-build 25-2 824156e0334c 2 weeks ago 23.9GB -.. ``` From e69ef1d8ccfe125b2c9d13fd63c3b995881e8667 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 28 Aug 2025 10:42:39 +0200 Subject: [PATCH 595/964] UL scheduler log: print TDA, it has more info --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index e1a312d9e0..b08e703076 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -2442,7 +2442,7 @@ void post_process_ulsch(gNB_MAC_INST *nr_mac, post_process_pusch_t *pusch, NR_UE sched_ctrl->last_ul_slot = sched_pusch->slot; LOG_D(NR_MAC, - "ULSCH/PUSCH: %4d.%2d RNTI %04x UL sched %4d.%2d DCI L %d start %2d RBS %3d startSymbol %2d nb_symbol %2d dmrs_pos %x MCS " + "ULSCH/PUSCH: %4d.%2d RNTI %04x UL sched %4d.%2d DCI L %d start %2d RBS %3d TDA %2d dmrs_pos %x MCS " "Table %2d MCS %2d nrOfLayers %2d num_dmrs_cdm_grps_no_data %2d TBS %4d HARQ PID %2d round %d RV %d NDI %d est %6d sched " "%6d est BSR %6d TPC %d\n", frame, @@ -2453,8 +2453,7 @@ void post_process_ulsch(gNB_MAC_INST *nr_mac, post_process_pusch_t *pusch, NR_UE sched_ctrl->aggregation_level, sched_pusch->rbStart, sched_pusch->rbSize, - sched_pusch->tda_info.startSymbolIndex, - sched_pusch->tda_info.nrOfSymbols, + sched_pusch->time_domain_allocation, sched_pusch->dmrs_info.ul_dmrs_symb_pos, current_BWP->mcs_table, sched_pusch->mcs, From 225e640ca4cc3b4f87930d4c0da443bf655b3614 Mon Sep 17 00:00:00 2001 From: francescomani Date: Sun, 10 Aug 2025 10:15:02 +0200 Subject: [PATCH 596/964] fix max feedback time parameter (needs to be computed every time we have that information) --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 264150f314..84d5bd9f37 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -2518,7 +2518,7 @@ void set_max_fb_time(NR_UE_UL_BWP_t *UL_BWP, const NR_UE_DL_BWP_t *DL_BWP) { UL_BWP->max_fb_time = 8; // default value // take the maximum in dl_DataToUL_ACK list - if (DL_BWP->dci_format != NR_DL_DCI_FORMAT_1_0 && UL_BWP->pucch_Config) { + if (UL_BWP->pucch_Config) { const struct NR_PUCCH_Config__dl_DataToUL_ACK *fb_times = UL_BWP->pucch_Config->dl_DataToUL_ACK; for (int i = 0; i < fb_times->list.count; i++) { if(*fb_times->list.array[i] > UL_BWP->max_fb_time) From 206e44ae54b0b2b68833f147a32fa76582adbc5e Mon Sep 17 00:00:00 2001 From: Reem Bahsoun Date: Tue, 2 Sep 2025 10:01:19 +0200 Subject: [PATCH 597/964] Replace old nvIPC library with the new one --- ci-scripts/cls_containerize.py | 4 ++-- docker/Dockerfile.gNB.aerial.ubuntu | 2 +- docker/Dockerfile.gNB.aerial.ubuntu.sanitize-address | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index cc057a60d9..7ee8dc4746 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -389,13 +389,13 @@ class Containerize(): elif image != 'ran-build': cmd.run(f'sed -i -e "s#ran-build:latest#ran-build:{imageTag}#" docker/Dockerfile.{pattern}{self.dockerfileprefix}') if image == 'oai-gnb-aerial': - cmd.run('cp -f /opt/nvidia-ipc/nvipc.src.2025.05.20.tar.gz .') + cmd.run('cp -f /opt/nvidia-ipc/nvipc_src.2025.08.27.tar.gz .') logfile = f'{lSourcePath}/cmake_targets/log/{name}.docker.log' ret = cmd.run(f'{self.cli} build {self.cliBuildOptions} --target {image} --tag {name}:{imageTag} --file docker/Dockerfile.{pattern}{self.dockerfileprefix} {option} . > {logfile} 2>&1', timeout=1200) t = (name, archiveArtifact(cmd, ctx, logfile)) log_files.append(t) if image == 'oai-gnb-aerial': - cmd.run('rm -f nvipc.src.2025.05.20.tar.gz') + cmd.run('rm -f nvipc_src.2025.08.27.tar.gz') # check the status of the build ret = cmd.run(f"{self.cli} image inspect --format=\'Size = {{{{.Size}}}} bytes\' {name}:{imageTag}") if ret.returncode != 0: diff --git a/docker/Dockerfile.gNB.aerial.ubuntu b/docker/Dockerfile.gNB.aerial.ubuntu index c31025e039..04bed658fe 100644 --- a/docker/Dockerfile.gNB.aerial.ubuntu +++ b/docker/Dockerfile.gNB.aerial.ubuntu @@ -45,7 +45,7 @@ WORKDIR /oai-ran COPY . . RUN /bin/sh oaienv && \ - tar -xvzf nvipc* && \ + tar -xvzf nvipc_src.*.tar.gz && \ cd nvipc_src.* && \ rm -rf build && mkdir build && cd build && \ cmake .. -DNVIPC_DPDK_ENABLE=OFF -DNVIPC_DOCA_ENABLE=OFF -DNVIPC_CUDA_ENABLE=OFF -DENABLE_SLT_RSP=ON && \ diff --git a/docker/Dockerfile.gNB.aerial.ubuntu.sanitize-address b/docker/Dockerfile.gNB.aerial.ubuntu.sanitize-address index c2bbe7ac88..07b6d7111b 100644 --- a/docker/Dockerfile.gNB.aerial.ubuntu.sanitize-address +++ b/docker/Dockerfile.gNB.aerial.ubuntu.sanitize-address @@ -45,7 +45,7 @@ WORKDIR /oai-ran COPY . . RUN /bin/sh oaienv && \ - tar -xvzf nvipc* && \ + tar -xvzf nvipc_src.*.tar.gz && \ cd nvipc_src.* && \ rm -rf build && mkdir build && cd build && \ cmake .. -DNVIPC_DPDK_ENABLE=OFF -DNVIPC_DOCA_ENABLE=OFF -DNVIPC_CUDA_ENABLE=OFF -DENABLE_SLT_RSP=ON && \ From 705f04f58e448ea8526d68bf3cf55450c14d17d5 Mon Sep 17 00:00:00 2001 From: Romain Beurdouche Date: Tue, 2 Sep 2025 15:00:18 +0000 Subject: [PATCH 598/964] feat(ldpc_aal): Do not initialize EAL if it is already initialized When FHI 7.2 is enabled, the EAL initialization is done by the FHI and the attempt to init EAL by ldpc_aal will fail. In that case, it is not necessary neither to provide a DPDK core list for BBDEV. This commit offers to skip EAL initialization if it is already initialized in order to allow dropping the useless DPDK cores argument in that case. The change relies on `rte_dev_probe` to detect if EAL was already initialized. --- .../nrLDPC_coding_aal/nrLDPC_coding_aal.c | 35 ++++++++++++------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_aal/nrLDPC_coding_aal.c b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_aal/nrLDPC_coding_aal.c index 815ec9ce26..31ca0b387b 100644 --- a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_aal/nrLDPC_coding_aal.c +++ b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_aal/nrLDPC_coding_aal.c @@ -1079,7 +1079,6 @@ int32_t nrLDPC_coding_init() "could not find mandatory --nrLDPC_coding_aal.dpdk_dev. If you used --nrLDPC_coding_t2.*, please rename all options to " "--nrLDPC_coding_aal.*\n"); AssertFatal(dpdk_dev != NULL, "nrLDPC_coding_aal.dpdk_dev was not provided"); - AssertFatal(dpdk_core_list != NULL, "nrLDPC_coding_aal.dpdk_core_list was not provided"); char dpdk_dev_full[32]; if (normalize_dpdk_dev(dpdk_dev, dpdk_dev_full, sizeof(dpdk_dev_full)) != 0) { @@ -1087,20 +1086,30 @@ int32_t nrLDPC_coding_init() return -1; } - int argc = 7; - char *argv[11] = {"bbdev", "-l", dpdk_core_list, "-a", dpdk_dev_full, "--file-prefix", dpdk_file_prefix, "--", "--", "--", "--"}; - if (vfio_vf_token != NULL) { - argc += 2; - argv[7] = "--vfio-vf-token"; - argv[8] = vfio_vf_token; - } - ret = rte_eal_init(argc, argv); - if (ret < 0) { - LOG_W(NR_PHY, "EAL initialization failed, probing DPDK device %s\n", dpdk_dev_full); - if (rte_dev_probe(dpdk_dev_full) != 0) { - LOG_E(NR_PHY, "bbdev %s not found\n", dpdk_dev_full); + // Detect if EAL was initialized by probing the device + LOG_I(NR_PHY, "Probing DPDK device %s to know if EAL is initialized. This may generate EAL error messages\n", dpdk_dev_full); + if (rte_dev_probe(dpdk_dev_full) != 0) { + LOG_I(NR_PHY, "Probing DPDK device %s failed, initializing EAL before continuing\n", dpdk_dev_full); + // EAL was not initialized yet + // We initialize EAL + AssertFatal(dpdk_core_list != NULL, "nrLDPC_coding_aal.dpdk_core_list was not provided"); + + int argc = 7; + char *argv[11] = + {"bbdev", "-l", dpdk_core_list, "-a", dpdk_dev_full, "--file-prefix", dpdk_file_prefix, "--", "--", "--", "--"}; + if (vfio_vf_token != NULL) { + argc += 2; + argv[7] = "--vfio-vf-token"; + argv[8] = vfio_vf_token; + } + ret = rte_eal_init(argc, argv); + if (ret < 0) { + LOG_E(NR_PHY, "EAL initialization failed\n"); return (-1); } + } else { + // EAL was already initialized + LOG_I(NR_PHY, "Probing DPDK device %s succeeded, skipping EAL initialization\n", dpdk_dev_full); } uint16_t nb_bbdevs = rte_bbdev_count(); AssertFatal(nb_bbdevs > 0, "no bbdev found"); From 6647af41168621bebb2c59c47bbf5c030b29e62f Mon Sep 17 00:00:00 2001 From: Romain Beurdouche Date: Tue, 2 Sep 2025 15:40:33 +0000 Subject: [PATCH 599/964] fix(ldpc_aal): Update documentation Update the documentation to reflect that the DPDK core list is not anymore necessary when using FHI 7.2. --- doc/LDPC_OFFLOAD_SETUP.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/doc/LDPC_OFFLOAD_SETUP.md b/doc/LDPC_OFFLOAD_SETUP.md index cabac2cf39..c792d916e7 100644 --- a/doc/LDPC_OFFLOAD_SETUP.md +++ b/doc/LDPC_OFFLOAD_SETUP.md @@ -284,6 +284,10 @@ sudo ./nr_dlsim -n300 -s30 -R 106 -e 27 --loader.ldpc.shlibversion _aal --nrLDPC ### Running OAI gNB with USRP B210/FHI72 +When running the gNB **with FHI 7.2**, it is not necessary to provide the `--nrLDPC_coding_aal.dpdk_core_list` argument +since the core list specified for FHI 7.2 will be used for DPDK. +If it is provided, the AAL core list wil be ignored. + Example command: ```bash cd ~/openairinterface5g @@ -294,12 +298,6 @@ sudo ./nr-softmodem -O ~/gnb.conf --loader.ldpc.shlibversion _aal --nrLDPC_codin # Known Issue(s) -## BBDEV CPU Usage - -When running the E2E setup (this applies to both USRP and FHI72), BBDEV may not be using the list of CPU cores as specified by `nrLDPC_coding_aal.dpdk_core_list` accordingly. -This is an issue under investigation, and subject for future fixes. -In the meantime, we recommend allocating idle, and isolated CPU cores in the configuration for BBDEV. - ## Potential Low Throughput The current implementation has been tested to work in an end-to-end setup and is functional. From 79c113373625f55d8bd01fa0728e49b085d4619f Mon Sep 17 00:00:00 2001 From: Romain Beurdouche Date: Tue, 2 Sep 2025 15:49:19 +0000 Subject: [PATCH 600/964] fix(ldpc_aal): Documentation The tuning of the BLER is necessary for Intel ACC, not for the T2. --- doc/LDPC_OFFLOAD_SETUP.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/LDPC_OFFLOAD_SETUP.md b/doc/LDPC_OFFLOAD_SETUP.md index c792d916e7..c7473fffe2 100644 --- a/doc/LDPC_OFFLOAD_SETUP.md +++ b/doc/LDPC_OFFLOAD_SETUP.md @@ -301,10 +301,12 @@ sudo ./nr-softmodem -O ~/gnb.conf --loader.ldpc.shlibversion _aal --nrLDPC_codin ## Potential Low Throughput The current implementation has been tested to work in an end-to-end setup and is functional. -However, there are still opportunities for optimization, particularly in LDPC decoding performance, which is an area of ongoing improvement. +However, depending on the accelerator in use, +there are still opportunities for optimization, particularly in LDPC decoding performance, which is an area of ongoing improvement. As such, downlink/uplink throughput may be suboptimal with the default configurations, but enhancements are actively being explored. -To achieve better E2E performance with the current implementation, we recommend the following adjustments: +For example, to achieve better E2E performance with the current implementation with Intel ACC 100 and 200 (vRAN Boost), +we recommend the following adjustments: 1. Increasing the number of LDPC decoding iterations of the L1, e.g., `max_ldpc_iterations` to 200. 2. Increasing the BLER targets of the MAC scheduler. From 8bae60c9381977441d3d6dba875a5c1227727f53 Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 4 Sep 2025 14:21:16 +0200 Subject: [PATCH 601/964] reset MSG3 C-RNTI flag in case of MAC reset --- openair2/LAYER2/NR_MAC_UE/main_ue_nr.c | 1 + 1 file changed, 1 insertion(+) diff --git a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c index 1a43dd2972..3348c6b278 100644 --- a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c +++ b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c @@ -198,6 +198,7 @@ void reset_mac_inst(NR_UE_MAC_INST_t *nr_mac) // stop any ongoing RACH procedure if (nr_mac->ra.RA_active) { + nr_mac->msg3_C_RNTI = false; nr_mac->ra.ra_state = nrRA_UE_IDLE; nr_mac->ra.RA_active = false; } From a73dd193811d5306d00be1aebb9abe475f35d958 Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 21 Aug 2025 15:09:49 +0200 Subject: [PATCH 602/964] rework PTRS configuration via file --- openair2/GNB_APP/RRC_nr_paramsvalues.h | 32 +-- openair2/GNB_APP/gnb_config.c | 215 ++++-------------- openair2/GNB_APP/gnb_paramdef.h | 54 +++++ openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 19 ++ openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c | 154 +++++++++++-- .../gnb.band78.tm1.106PRB.PTRS.usrpx300.conf | 4 +- 6 files changed, 261 insertions(+), 217 deletions(-) diff --git a/openair2/GNB_APP/RRC_nr_paramsvalues.h b/openair2/GNB_APP/RRC_nr_paramsvalues.h index 1525c31b9a..85aa8d979f 100644 --- a/openair2/GNB_APP/RRC_nr_paramsvalues.h +++ b/openair2/GNB_APP/RRC_nr_paramsvalues.h @@ -139,22 +139,6 @@ /* Serving Cell Config Dedicated */ #define GNB_CONFIG_STRING_SERVINGCELLCONFIGDEDICATED "servingCellConfigDedicated" -#define GNB_CONFIG_STRING_DLPTRSFREQDENSITY0_0 "dl_ptrsFreqDensity0_0" -#define GNB_CONFIG_STRING_DLPTRSFREQDENSITY1_0 "dl_ptrsFreqDensity1_0" -#define GNB_CONFIG_STRING_DLPTRSTIMEDENSITY0_0 "dl_ptrsTimeDensity0_0" -#define GNB_CONFIG_STRING_DLPTRSTIMEDENSITY1_0 "dl_ptrsTimeDensity1_0" -#define GNB_CONFIG_STRING_DLPTRSTIMEDENSITY2_0 "dl_ptrsTimeDensity2_0" -#define GNB_CONFIG_STRING_DLPTRSEPRERATIO_0 "dl_ptrsEpreRatio_0" -#define GNB_CONFIG_STRING_DLPTRSREOFFSET_0 "dl_ptrsReOffset_0" -#define GNB_CONFIG_STRING_ULPTRSFREQDENSITY0_0 "ul_ptrsFreqDensity0_0" -#define GNB_CONFIG_STRING_ULPTRSFREQDENSITY1_0 "ul_ptrsFreqDensity1_0" -#define GNB_CONFIG_STRING_ULPTRSTIMEDENSITY0_0 "ul_ptrsTimeDensity0_0" -#define GNB_CONFIG_STRING_ULPTRSTIMEDENSITY1_0 "ul_ptrsTimeDensity1_0" -#define GNB_CONFIG_STRING_ULPTRSTIMEDENSITY2_0 "ul_ptrsTimeDensity2_0" -#define GNB_CONFIG_STRING_ULPTRSREOFFSET_0 "ul_ptrsReOffset_0" -#define GNB_CONFIG_STRING_ULPTRSMAXPORTS_0 "ul_ptrsMaxPorts_0" -#define GNB_CONFIG_STRING_ULPTRSPOWER_0 "ul_ptrsPower_0" - #define GNB_CONFIG_STRING_DLBWP1_ID "dl_bwp-Id_1" #define GNB_CONFIG_STRING_DLBWP2_ID "dl_bwp-Id_2" #define GNB_CONFIG_STRING_DLBWP3_ID "dl_bwp-Id_3" @@ -277,21 +261,6 @@ /*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ #define SCDPARAMS_DESC(scd) { \ -{GNB_CONFIG_STRING_DLPTRSFREQDENSITY0_0,NULL,0,.i64ptr=scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->frequencyDensity->list.array[0],.defint64val=-1,TYPE_INT64,0}, \ -{GNB_CONFIG_STRING_DLPTRSFREQDENSITY1_0,NULL,0,.i64ptr=scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->frequencyDensity->list.array[1],.defint64val=-1,TYPE_INT64,0}, \ -{GNB_CONFIG_STRING_DLPTRSTIMEDENSITY0_0,NULL,0,.i64ptr=scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->timeDensity->list.array[0],.defint64val=-1,TYPE_INT64,0}, \ -{GNB_CONFIG_STRING_DLPTRSTIMEDENSITY1_0,NULL,0,.i64ptr=scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->timeDensity->list.array[1],.defint64val=-1,TYPE_INT64,0}, \ -{GNB_CONFIG_STRING_DLPTRSTIMEDENSITY2_0,NULL,0,.i64ptr=scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->timeDensity->list.array[2],.defint64val=-1,TYPE_INT64,0}, \ -{GNB_CONFIG_STRING_DLPTRSEPRERATIO_0,NULL,0,.i64ptr=scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->epre_Ratio,.defint64val=-1,TYPE_INT64,0}, \ -{GNB_CONFIG_STRING_DLPTRSREOFFSET_0,NULL,0,.i64ptr=scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->resourceElementOffset,.defint64val=-1,TYPE_INT64,0}, \ -{GNB_CONFIG_STRING_ULPTRSFREQDENSITY0_0,NULL,0,.i64ptr=scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->frequencyDensity->list.array[0],.defint64val=-1,TYPE_INT64,0}, \ -{GNB_CONFIG_STRING_ULPTRSFREQDENSITY1_0,NULL,0,.i64ptr=scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->frequencyDensity->list.array[1],.defint64val=-1,TYPE_INT64,0}, \ -{GNB_CONFIG_STRING_ULPTRSTIMEDENSITY0_0,NULL,0,.i64ptr=scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->timeDensity->list.array[0],.defint64val=-1,TYPE_INT64,0}, \ -{GNB_CONFIG_STRING_ULPTRSTIMEDENSITY1_0,NULL,0,.i64ptr=scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->timeDensity->list.array[1],.defint64val=-1,TYPE_INT64,0}, \ -{GNB_CONFIG_STRING_ULPTRSTIMEDENSITY2_0,NULL,0,.i64ptr=scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->timeDensity->list.array[2],.defint64val=-1,TYPE_INT64,0}, \ -{GNB_CONFIG_STRING_ULPTRSREOFFSET_0,NULL,0,.i64ptr=scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->resourceElementOffset,.defint64val=-1,TYPE_INT64,0}, \ -{GNB_CONFIG_STRING_ULPTRSMAXPORTS_0,NULL,0,.i64ptr=&scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->maxNrofPorts,.defint64val=0,TYPE_INT64,0}, \ -{GNB_CONFIG_STRING_ULPTRSPOWER_0,NULL,0,.i64ptr=&scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->ptrs_Power,.defint64val=0,TYPE_INT64,0}, \ {GNB_CONFIG_STRING_FIRSTACTIVEDLBWP_ID,NULL,0,.i64ptr=scd->firstActiveDownlinkBWP_Id,.defint64val=1,TYPE_INT64,0}, \ {GNB_CONFIG_STRING_FIRSTACTIVEULBWP_ID,NULL,0,.i64ptr=scd->uplinkConfig->firstActiveUplinkBWP_Id,.defint64val=1,TYPE_INT64,0}, \ {GNB_CONFIG_STRING_DLBWP1_ID,NULL,0,.i64ptr=&scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Id,.defint64val=1,TYPE_INT64,0}, \ @@ -320,6 +289,7 @@ {GNB_CONFIG_STRING_LOCATIONANDBANDWIDTH_ULBWP4,NULL,0,.i64ptr=&scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[3]->bwp_Common->genericParameters.locationAndBandwidth,.defint64val=0,TYPE_INT64,0}, \ {GNB_CONFIG_STRING_DEFAULTDLBWP_ID,NULL,0,.i64ptr=scd->defaultDownlinkBWP_Id,.defint64val=0,TYPE_INT64,0}} + /*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ /* Serving Cell Config Common configuration parameters to apply in RA 2-Step */ /*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 94e9012855..f16ebae210 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -686,80 +686,13 @@ void prepare_scd(NR_ServingCellConfig_t *scd) { bwp->bwp_Common->pdcch_ConfigCommon = calloc_or_fail(1, sizeof(*bwp->bwp_Common->pdcch_ConfigCommon)); bwp->bwp_Common->pdsch_ConfigCommon = calloc_or_fail(1, sizeof(*bwp->bwp_Common->pdsch_ConfigCommon)); bwp->bwp_Dedicated = calloc_or_fail(1, sizeof(*bwp->bwp_Dedicated)); - bwp->bwp_Dedicated->pdsch_Config = calloc_or_fail(1, sizeof(*bwp->bwp_Dedicated->pdsch_Config)); - struct NR_SetupRelease_PDSCH_Config *pdsch_Config = bwp->bwp_Dedicated->pdsch_Config; - pdsch_Config->present = NR_SetupRelease_PDSCH_Config_PR_setup; - pdsch_Config->choice.setup = calloc_or_fail(1, sizeof(*pdsch_Config->choice.setup)); - struct NR_PDSCH_Config *pc_setup = pdsch_Config->choice.setup; - pc_setup->dmrs_DownlinkForPDSCH_MappingTypeA = calloc_or_fail(1, sizeof(*pc_setup->dmrs_DownlinkForPDSCH_MappingTypeA)); - struct NR_SetupRelease_DMRS_DownlinkConfig *typeA = pc_setup->dmrs_DownlinkForPDSCH_MappingTypeA; - typeA->present = NR_SetupRelease_DMRS_DownlinkConfig_PR_setup; - - // Allocate DL DMRS and PTRS configuration - typeA->choice.setup = calloc_or_fail(1, sizeof(*typeA->choice.setup)); - NR_DMRS_DownlinkConfig_t *NR_DMRS_DownlinkCfg = typeA->choice.setup; - NR_DMRS_DownlinkCfg->phaseTrackingRS = calloc_or_fail(1, sizeof(*NR_DMRS_DownlinkCfg->phaseTrackingRS)); - NR_DMRS_DownlinkCfg->phaseTrackingRS->present = NR_SetupRelease_PTRS_DownlinkConfig_PR_setup; - NR_DMRS_DownlinkCfg->phaseTrackingRS->choice.setup = - calloc_or_fail(1, sizeof(*NR_DMRS_DownlinkCfg->phaseTrackingRS->choice.setup)); - NR_PTRS_DownlinkConfig_t *NR_PTRS_DownlinkCfg = NR_DMRS_DownlinkCfg->phaseTrackingRS->choice.setup; - NR_PTRS_DownlinkCfg->frequencyDensity = calloc_or_fail(1, sizeof(*NR_PTRS_DownlinkCfg->frequencyDensity)); - for (int i=0;i<2;i++) { - long *a = calloc_or_fail(1, sizeof(*a)); - asn1cSeqAdd(&NR_PTRS_DownlinkCfg->frequencyDensity->list, a); - } - NR_PTRS_DownlinkCfg->timeDensity = calloc_or_fail(1, sizeof(*NR_PTRS_DownlinkCfg->timeDensity)); - for (int i=0;i<3;i++) { - long *dl_mcs = calloc_or_fail(1, sizeof(*dl_mcs)); - asn1cSeqAdd(&NR_PTRS_DownlinkCfg->timeDensity->list, dl_mcs); - } - NR_PTRS_DownlinkCfg->epre_Ratio = calloc_or_fail(1, sizeof(*NR_PTRS_DownlinkCfg->epre_Ratio)); - NR_PTRS_DownlinkCfg->resourceElementOffset = calloc_or_fail(1, sizeof(*NR_PTRS_DownlinkCfg->resourceElementOffset)); - *NR_PTRS_DownlinkCfg->resourceElementOffset = 0; asn1cSeqAdd(&scd->downlinkBWP_ToAddModList->list,bwp); - // Allocate uplink structures - - NR_PUSCH_Config_t *pusch_Config = calloc_or_fail(1, sizeof(*pusch_Config)); - - // Allocate UL DMRS and PTRS structures - pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB = calloc_or_fail(1, sizeof(*pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB)); - pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->present = NR_SetupRelease_DMRS_UplinkConfig_PR_setup; - pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup = - calloc_or_fail(1, sizeof(*pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup)); - NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup; - NR_DMRS_UplinkConfig->phaseTrackingRS = calloc_or_fail(1, sizeof(*NR_DMRS_UplinkConfig->phaseTrackingRS)); - NR_DMRS_UplinkConfig->phaseTrackingRS->present = NR_SetupRelease_PTRS_UplinkConfig_PR_setup; - NR_DMRS_UplinkConfig->phaseTrackingRS->choice.setup = - calloc_or_fail(1, sizeof(*NR_DMRS_UplinkConfig->phaseTrackingRS->choice.setup)); - NR_PTRS_UplinkConfig_t *NR_PTRS_UplinkConfig = NR_DMRS_UplinkConfig->phaseTrackingRS->choice.setup; - NR_PTRS_UplinkConfig->transformPrecoderDisabled = calloc_or_fail(1, sizeof(*NR_PTRS_UplinkConfig->transformPrecoderDisabled)); - NR_PTRS_UplinkConfig->transformPrecoderDisabled->frequencyDensity = - calloc_or_fail(1, sizeof(*NR_PTRS_UplinkConfig->transformPrecoderDisabled->frequencyDensity)); - for (int i=0;i<2;i++) { - long *n_rbs = calloc_or_fail(1, sizeof(*n_rbs)); - asn1cSeqAdd(&NR_PTRS_UplinkConfig->transformPrecoderDisabled->frequencyDensity->list, n_rbs); - } - NR_PTRS_UplinkConfig->transformPrecoderDisabled->timeDensity = - calloc_or_fail(1, sizeof(*NR_PTRS_UplinkConfig->transformPrecoderDisabled->timeDensity)); - for (int i = 0; i < 3; i++) { - long *ptrs_mcs = calloc_or_fail(1, sizeof(*ptrs_mcs)); - asn1cSeqAdd(&NR_PTRS_UplinkConfig->transformPrecoderDisabled->timeDensity->list, ptrs_mcs); - } - NR_PTRS_UplinkConfig->transformPrecoderDisabled->resourceElementOffset = - calloc_or_fail(1, sizeof(*NR_PTRS_UplinkConfig->transformPrecoderDisabled->resourceElementOffset)); - *NR_PTRS_UplinkConfig->transformPrecoderDisabled->resourceElementOffset = 0; - // UL bandwidth part NR_BWP_Uplink_t *ubwp = calloc_or_fail(1, sizeof(*ubwp)); ubwp->bwp_Id = j+1; ubwp->bwp_Common = calloc_or_fail(1, sizeof(*ubwp->bwp_Common)); ubwp->bwp_Dedicated = calloc_or_fail(1, sizeof(*ubwp->bwp_Dedicated)); - - ubwp->bwp_Dedicated->pusch_Config = calloc_or_fail(1, sizeof(*ubwp->bwp_Dedicated->pusch_Config)); - ubwp->bwp_Dedicated->pusch_Config->present = NR_SetupRelease_PUSCH_Config_PR_setup; - ubwp->bwp_Dedicated->pusch_Config->choice.setup = pusch_Config; - asn1cSeqAdd(&scd->uplinkConfig->uplinkBWP_ToAddModList->list,ubwp); } } @@ -788,93 +721,6 @@ void fix_scd(NR_ServingCellConfig_t *scd) { } } - // Check for DL PTRS parameters validity - for (int bwp_i = 0 ; bwp_idownlinkBWP_ToAddModList->list.count; bwp_i++) { - - NR_DMRS_DownlinkConfig_t *dmrs_dl_config = scd->downlinkBWP_ToAddModList->list.array[bwp_i]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup; - - if (dmrs_dl_config->phaseTrackingRS) { - // If any of the frequencyDensity values are not set or are out of bounds, PTRS is assumed to be not present - for (int i = dmrs_dl_config->phaseTrackingRS->choice.setup->frequencyDensity->list.count - 1; i >= 0; i--) { - if ((*dmrs_dl_config->phaseTrackingRS->choice.setup->frequencyDensity->list.array[i] < 1) - || (*dmrs_dl_config->phaseTrackingRS->choice.setup->frequencyDensity->list.array[i] > 276)) { - LOG_I(GNB_APP, "DL PTRS frequencyDensity %d not set. Assuming PTRS not present! \n", i); - free(dmrs_dl_config->phaseTrackingRS); - dmrs_dl_config->phaseTrackingRS = NULL; - break; - } - } - } - - if (dmrs_dl_config->phaseTrackingRS) { - // If any of the timeDensity values are not set or are out of bounds, PTRS is assumed to be not present - for (int i = dmrs_dl_config->phaseTrackingRS->choice.setup->timeDensity->list.count - 1; i >= 0; i--) { - if ((*dmrs_dl_config->phaseTrackingRS->choice.setup->timeDensity->list.array[i] < 0) - || (*dmrs_dl_config->phaseTrackingRS->choice.setup->timeDensity->list.array[i] > 29)) { - LOG_I(GNB_APP, "DL PTRS timeDensity %d not set. Assuming PTRS not present! \n", i); - free(dmrs_dl_config->phaseTrackingRS); - dmrs_dl_config->phaseTrackingRS = NULL; - break; - } - } - } - - if (dmrs_dl_config->phaseTrackingRS) { - if (*dmrs_dl_config->phaseTrackingRS->choice.setup->resourceElementOffset > 2) { - LOG_I(GNB_APP, "Freeing DL PTRS resourceElementOffset \n"); - free(dmrs_dl_config->phaseTrackingRS->choice.setup->resourceElementOffset); - dmrs_dl_config->phaseTrackingRS->choice.setup->resourceElementOffset = NULL; - } - if (*dmrs_dl_config->phaseTrackingRS->choice.setup->epre_Ratio > 1) { - LOG_I(GNB_APP, "Freeing DL PTRS epre_Ratio \n"); - free(dmrs_dl_config->phaseTrackingRS->choice.setup->epre_Ratio); - dmrs_dl_config->phaseTrackingRS->choice.setup->epre_Ratio = NULL; - } - } - } - - // Check for UL PTRS parameters validity - for (int bwp_i = 0 ; bwp_iuplinkConfig->uplinkBWP_ToAddModList->list.count; bwp_i++) { - - NR_DMRS_UplinkConfig_t *dmrs_ul_config = scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[bwp_i]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup; - - if (dmrs_ul_config->phaseTrackingRS) { - // If any of the frequencyDensity values are not set or are out of bounds, PTRS is assumed to be not present - for (int i = dmrs_ul_config->phaseTrackingRS->choice.setup->transformPrecoderDisabled->frequencyDensity->list.count-1; i >= 0; i--) { - if ((*dmrs_ul_config->phaseTrackingRS->choice.setup->transformPrecoderDisabled->frequencyDensity->list.array[i] < 1) - || (*dmrs_ul_config->phaseTrackingRS->choice.setup->transformPrecoderDisabled->frequencyDensity->list.array[i] > 276)) { - LOG_I(GNB_APP, "UL PTRS frequencyDensity %d not set. Assuming PTRS not present! \n", i); - free(dmrs_ul_config->phaseTrackingRS); - dmrs_ul_config->phaseTrackingRS = NULL; - break; - } - } - } - - if (dmrs_ul_config->phaseTrackingRS) { - // If any of the timeDensity values are not set or are out of bounds, PTRS is assumed to be not present - for (int i = dmrs_ul_config->phaseTrackingRS->choice.setup->transformPrecoderDisabled->timeDensity->list.count-1; i >= 0; i--) { - if ((*dmrs_ul_config->phaseTrackingRS->choice.setup->transformPrecoderDisabled->timeDensity->list.array[i] < 0) - || (*dmrs_ul_config->phaseTrackingRS->choice.setup->transformPrecoderDisabled->timeDensity->list.array[i] > 29)) { - LOG_I(GNB_APP, "UL PTRS timeDensity %d not set. Assuming PTRS not present! \n", i); - free(dmrs_ul_config->phaseTrackingRS); - dmrs_ul_config->phaseTrackingRS = NULL; - break; - } - } - } - - if (dmrs_ul_config->phaseTrackingRS) { - // Check for UL PTRS parameters validity - if (*dmrs_ul_config->phaseTrackingRS->choice.setup->transformPrecoderDisabled->resourceElementOffset > 2) { - LOG_I(GNB_APP, "Freeing UL PTRS resourceElementOffset \n"); - free(dmrs_ul_config->phaseTrackingRS->choice.setup->transformPrecoderDisabled->resourceElementOffset); - dmrs_ul_config->phaseTrackingRS->choice.setup->transformPrecoderDisabled->resourceElementOffset = NULL; - } - } - - } - if (scd->downlinkBWP_ToAddModList->list.count == 0) { free(scd->downlinkBWP_ToAddModList->list.array); free(scd->downlinkBWP_ToAddModList); @@ -1273,21 +1119,6 @@ static NR_ServingCellConfig_t *get_scd_config(configmodule_interface_t *cfg) if (SCDsParamList.numelt > 0) { snprintf(aprefix, sizeof(aprefix), "%s.[%i].%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, 0, GNB_CONFIG_STRING_SERVINGCELLCONFIGDEDICATED, 0); GET_PARAMS(SCDsParams, SCDPARAMS_DESC(scd), aprefix); - const NR_BWP_UplinkDedicated_t *bwp_Dedicated = scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated; - const NR_PTRS_UplinkConfig_t *setup = - bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup; - LOG_I(RRC, - "Read in ServingCellConfigDedicated UL (FreqDensity_0 %ld, FreqDensity_1 %ld, TimeDensity_0 %ld, TimeDensity_1 %ld, " - "TimeDensity_2 %ld, RE offset %ld, First_active_BWP_ID %ld SCS %ld, LocationandBW %ld\n", - *setup->transformPrecoderDisabled->frequencyDensity->list.array[0], - *setup->transformPrecoderDisabled->frequencyDensity->list.array[1], - *setup->transformPrecoderDisabled->timeDensity->list.array[0], - *setup->transformPrecoderDisabled->timeDensity->list.array[1], - *setup->transformPrecoderDisabled->timeDensity->list.array[2], - *setup->transformPrecoderDisabled->resourceElementOffset, - *scd->firstActiveDownlinkBWP_Id, - scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Common->genericParameters.subcarrierSpacing, - scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Common->genericParameters.locationAndBandwidth); } fix_scd(scd); @@ -1465,6 +1296,49 @@ static f1ap_setup_req_t *RC_read_F1Setup(uint64_t id, return req; } +static nr_ptrs_config_t *get_ptrs_config(int gnb_idx) +{ + char aprefix[MAX_OPTNAME_SIZE * 2 + 8]; + snprintf(aprefix, sizeof(aprefix), "%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, 0); + GET_PARAMS_LIST(ptrs_ParamsList, ptrs_Params, GNB_PTRS_PARAMS_DESC, GNB_CONFIG_STRING_PTRS, aprefix); + if (ptrs_ParamsList.numelt == 0) { + LOG_I(GNB_APP, "No PTRS configuration found\n"); + return NULL; + } + nr_ptrs_config_t *ptrs = calloc_or_fail(1, sizeof(*ptrs)); + ptrs->dl_FreqDensity0_0 = *ptrs_ParamsList.paramarray[0][GNB_DLPTRSFREQDENSITY0_0_IDX].iptr; + LOG_I(GNB_APP, "PTRS configuration: dl_FreqDensity0_0 %d\n", ptrs->dl_FreqDensity0_0); + ptrs->dl_FreqDensity1_0 = *ptrs_ParamsList.paramarray[0][GNB_DLPTRSFREQDENSITY1_0_IDX].iptr; + LOG_I(GNB_APP, "PTRS configuration: dl_FreqDensity1_0 %d\n", ptrs->dl_FreqDensity1_0); + ptrs->dl_TimeDensity0_0 = *ptrs_ParamsList.paramarray[0][GNB_DLPTRSTIMEDENSITY0_0_IDX].iptr; + LOG_I(GNB_APP, "PTRS configuration: dl_TimeDensity0_0 %d\n", ptrs->dl_TimeDensity0_0); + ptrs->dl_TimeDensity1_0 = *ptrs_ParamsList.paramarray[0][GNB_DLPTRSTIMEDENSITY1_0_IDX].iptr; + LOG_I(GNB_APP, "PTRS configuration: dl_TimeDensity1_0 %d\n", ptrs->dl_TimeDensity1_0); + ptrs->dl_TimeDensity2_0 = *ptrs_ParamsList.paramarray[0][GNB_DLPTRSTIMEDENSITY2_0_IDX].iptr; + LOG_I(GNB_APP, "PTRS configuration: dl_TimeDensity2_0 %d\n", ptrs->dl_TimeDensity2_0); + ptrs->dl_EpreRatio_0 = *ptrs_ParamsList.paramarray[0][GNB_DLPTRSEPRERATIO_0_IDX].iptr; + LOG_I(GNB_APP, "PTRS configuration: dl_EpreRatio_0 %d\n", ptrs->dl_EpreRatio_0); + ptrs->dl_ReOffset_0 = *ptrs_ParamsList.paramarray[0][GNB_DLPTRSREOFFSET_0_IDX].iptr; + LOG_I(GNB_APP, "PTRS configuration: dl_ReOffset_0 %d\n", ptrs->dl_ReOffset_0); + ptrs->ul_FreqDensity0_0 = *ptrs_ParamsList.paramarray[0][GNB_ULPTRSFREQDENSITY0_0_IDX].iptr; + LOG_I(GNB_APP, "PTRS configuration: ul_FreqDensity0_0 %d\n", ptrs->ul_FreqDensity0_0); + ptrs->ul_FreqDensity1_0 = *ptrs_ParamsList.paramarray[0][GNB_ULPTRSFREQDENSITY1_0_IDX].iptr; + LOG_I(GNB_APP, "PTRS configuration: ul_FreqDensity1_0 %d\n", ptrs->ul_FreqDensity1_0); + ptrs->ul_TimeDensity0_0 = *ptrs_ParamsList.paramarray[0][GNB_ULPTRSTIMEDENSITY0_0_IDX].iptr; + LOG_I(GNB_APP, "PTRS configuration: ul_TimeDensity0_0 %d\n", ptrs->ul_TimeDensity0_0); + ptrs->ul_TimeDensity1_0 = *ptrs_ParamsList.paramarray[0][GNB_ULPTRSTIMEDENSITY1_0_IDX].iptr; + LOG_I(GNB_APP, "PTRS configuration: ul_TimeDensity1_0 %d\n", ptrs->ul_TimeDensity1_0); + ptrs->ul_TimeDensity2_0 = *ptrs_ParamsList.paramarray[0][GNB_ULPTRSTIMEDENSITY2_0_IDX].iptr; + LOG_I(GNB_APP, "PTRS configuration: ul_TimeDensity2_0 %d\n", ptrs->ul_TimeDensity2_0); + ptrs->ul_ReOffset_0 = *ptrs_ParamsList.paramarray[0][GNB_ULPTRSREOFFSET_0_IDX].iptr; + LOG_I(GNB_APP, "PTRS configuration: ul_ReOffset_0 %d\n", ptrs->ul_ReOffset_0); + ptrs->ul_MaxPorts_0 = *ptrs_ParamsList.paramarray[0][GNB_ULPTRSMAXPORTS_0_IDX].iptr; + LOG_I(GNB_APP, "PTRS configuration: ul_MaxPorts_0 %d\n", ptrs->ul_MaxPorts_0); + ptrs->ul_Power_0 = *ptrs_ParamsList.paramarray[0][GNB_ULPTRSPOWER_0_IDX].iptr; + LOG_I(GNB_APP, "PTRS configuration: ul_Power_0 %d\n", ptrs->ul_Power_0); + return ptrs; +} + static nr_redcap_config_t *get_redcap_config(int gnb_idx) { paramdef_t RedCap_Params[] = GNB_REDCAP_PARAMS_DESC; @@ -1479,7 +1353,7 @@ static nr_redcap_config_t *get_redcap_config(int gnb_idx) // Check for default/non-existing values in configuration file if (*RedCap_Params[GNB_REDCAP_CELL_BARRED_REDCAP1_RX_R17_IDX].i8ptr == -1 || *RedCap_Params[GNB_REDCAP_CELL_BARRED_REDCAP2_RX_R17_IDX].i8ptr == -1) { - LOG_I(NR_MAC, "No RedCap configuration found\n"); + LOG_I(GNB_APP, "No RedCap configuration found\n"); return NULL; } @@ -1641,6 +1515,7 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg) AssertFatal(config.maxMIMO_layers != 0 && config.maxMIMO_layers <= tot_ant, "Invalid maxMIMO_layers %d\n", config.maxMIMO_layers); config.redcap = get_redcap_config(0); + config.ptrs = get_ptrs_config(0); char aprefix[MAX_OPTNAME_SIZE * 2 + 8]; snprintf(aprefix, sizeof(aprefix), "%s.[%d].%s", GNB_CONFIG_STRING_GNB_LIST, 0, GNB_CONFIG_STRING_TIMERS_CONFIG); diff --git a/openair2/GNB_APP/gnb_paramdef.h b/openair2/GNB_APP/gnb_paramdef.h index b751d78733..95b4451148 100644 --- a/openair2/GNB_APP/gnb_paramdef.h +++ b/openair2/GNB_APP/gnb_paramdef.h @@ -516,6 +516,60 @@ typedef enum { #define GNB_REDCAP_CELL_BARRED_REDCAP2_RX_R17_IDX 1 #define GNB_REDCAP_INTRA_FREQ_RESELECTION_REDCAP_R17_IDX 2 +/*-------------------------------------------------------------------------------------------------------------------------------------*/ +/* PTRS configuration parameters */ +/*-------------------------------------------------------------------------------------------------------------------------------------*/ + +#define GNB_CONFIG_STRING_PTRS "phaseTrackingRS" +#define GNB_CONFIG_STRING_DLPTRSFREQDENSITY0_0 "dl_ptrsFreqDensity0_0" +#define GNB_CONFIG_STRING_DLPTRSFREQDENSITY1_0 "dl_ptrsFreqDensity1_0" +#define GNB_CONFIG_STRING_DLPTRSTIMEDENSITY0_0 "dl_ptrsTimeDensity0_0" +#define GNB_CONFIG_STRING_DLPTRSTIMEDENSITY1_0 "dl_ptrsTimeDensity1_0" +#define GNB_CONFIG_STRING_DLPTRSTIMEDENSITY2_0 "dl_ptrsTimeDensity2_0" +#define GNB_CONFIG_STRING_DLPTRSEPRERATIO_0 "dl_ptrsEpreRatio_0" +#define GNB_CONFIG_STRING_DLPTRSREOFFSET_0 "dl_ptrsReOffset_0" +#define GNB_CONFIG_STRING_ULPTRSFREQDENSITY0_0 "ul_ptrsFreqDensity0_0" +#define GNB_CONFIG_STRING_ULPTRSFREQDENSITY1_0 "ul_ptrsFreqDensity1_0" +#define GNB_CONFIG_STRING_ULPTRSTIMEDENSITY0_0 "ul_ptrsTimeDensity0_0" +#define GNB_CONFIG_STRING_ULPTRSTIMEDENSITY1_0 "ul_ptrsTimeDensity1_0" +#define GNB_CONFIG_STRING_ULPTRSTIMEDENSITY2_0 "ul_ptrsTimeDensity2_0" +#define GNB_CONFIG_STRING_ULPTRSREOFFSET_0 "ul_ptrsReOffset_0" +#define GNB_CONFIG_STRING_ULPTRSMAXPORTS_0 "ul_ptrsMaxPorts_0" +#define GNB_CONFIG_STRING_ULPTRSPOWER_0 "ul_ptrsPower_0" + +#define GNB_PTRS_PARAMS_DESC { \ +{GNB_CONFIG_STRING_DLPTRSFREQDENSITY0_0, NULL, 0, .iptr=NULL, .defintval=0, TYPE_INT, 0}, \ +{GNB_CONFIG_STRING_DLPTRSFREQDENSITY1_0, NULL, 0, .iptr=NULL, .defintval=0, TYPE_INT, 0}, \ +{GNB_CONFIG_STRING_DLPTRSTIMEDENSITY0_0, NULL, 0, .iptr=NULL, .defintval=-1, TYPE_INT, 0}, \ +{GNB_CONFIG_STRING_DLPTRSTIMEDENSITY1_0, NULL, 0, .iptr=NULL, .defintval=-1, TYPE_INT, 0}, \ +{GNB_CONFIG_STRING_DLPTRSTIMEDENSITY2_0, NULL, 0, .iptr=NULL, .defintval=-1, TYPE_INT, 0}, \ +{GNB_CONFIG_STRING_DLPTRSEPRERATIO_0, NULL, 0, .iptr=NULL, .defintval=-1, TYPE_INT, 0}, \ +{GNB_CONFIG_STRING_DLPTRSREOFFSET_0, NULL, 0, .iptr=NULL, .defintval=-1, TYPE_INT, 0}, \ +{GNB_CONFIG_STRING_ULPTRSFREQDENSITY0_0, NULL, 0, .iptr=NULL, .defintval=0, TYPE_INT, 0}, \ +{GNB_CONFIG_STRING_ULPTRSFREQDENSITY1_0, NULL, 0, .iptr=NULL, .defintval=0, TYPE_INT, 0}, \ +{GNB_CONFIG_STRING_ULPTRSTIMEDENSITY0_0, NULL, 0, .iptr=NULL, .defintval=-1, TYPE_INT, 0}, \ +{GNB_CONFIG_STRING_ULPTRSTIMEDENSITY1_0, NULL, 0, .iptr=NULL, .defintval=-1, TYPE_INT, 0}, \ +{GNB_CONFIG_STRING_ULPTRSTIMEDENSITY2_0, NULL, 0, .iptr=NULL, .defintval=-1, TYPE_INT, 0}, \ +{GNB_CONFIG_STRING_ULPTRSREOFFSET_0, NULL, 0, .iptr=NULL, .defintval=-1, TYPE_INT, 0}, \ +{GNB_CONFIG_STRING_ULPTRSMAXPORTS_0, NULL, 0, .iptr=NULL, .defintval=0, TYPE_INT, 0}, \ +{GNB_CONFIG_STRING_ULPTRSPOWER_0, NULL, 0, .iptr=NULL, .defintval=0, TYPE_INT, 0}} + +#define GNB_DLPTRSFREQDENSITY0_0_IDX 0 +#define GNB_DLPTRSFREQDENSITY1_0_IDX 1 +#define GNB_DLPTRSTIMEDENSITY0_0_IDX 2 +#define GNB_DLPTRSTIMEDENSITY1_0_IDX 3 +#define GNB_DLPTRSTIMEDENSITY2_0_IDX 4 +#define GNB_DLPTRSEPRERATIO_0_IDX 5 +#define GNB_DLPTRSREOFFSET_0_IDX 6 +#define GNB_ULPTRSFREQDENSITY0_0_IDX 7 +#define GNB_ULPTRSFREQDENSITY1_0_IDX 8 +#define GNB_ULPTRSTIMEDENSITY0_0_IDX 9 +#define GNB_ULPTRSTIMEDENSITY1_0_IDX 10 +#define GNB_ULPTRSTIMEDENSITY2_0_IDX 11 +#define GNB_ULPTRSREOFFSET_0_IDX 12 +#define GNB_ULPTRSMAXPORTS_0_IDX 13 +#define GNB_ULPTRSPOWER_0_IDX 14 + /*---------------------------------------------------------------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------------------------------------------------------------*/ /* SCTP configuration parameters section name */ diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 2627c9162b..9964b2be36 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -155,6 +155,24 @@ typedef struct nr_redcap_config { uint8_t intraFreqReselectionRedCap_r17; } nr_redcap_config_t; +typedef struct { +int dl_FreqDensity0_0; +int dl_FreqDensity1_0; +int dl_TimeDensity0_0; +int dl_TimeDensity1_0; +int dl_TimeDensity2_0; +int dl_EpreRatio_0; +int dl_ReOffset_0; +int ul_FreqDensity0_0; +int ul_FreqDensity1_0; +int ul_TimeDensity0_0; +int ul_TimeDensity1_0; +int ul_TimeDensity2_0; +int ul_ReOffset_0; +int ul_MaxPorts_0; +int ul_Power_0; +} nr_ptrs_config_t; + typedef struct nr_mac_config_t { int sib1_tda; nr_pdsch_AntennaPorts_t pdsch_AntennaPorts; @@ -177,6 +195,7 @@ typedef struct nr_mac_config_t { int32_t *bw_list; int num_agg_level_candidates[NUM_PDCCH_AGG_LEVELS]; nr_redcap_config_t *redcap; + nr_ptrs_config_t *ptrs; bool do_SINR; } nr_mac_config_t; diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c index 5fba6dcaaf..b42fb97a8e 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c @@ -1445,12 +1445,60 @@ static void set_dl_mcs_table(int scs, bwp_Dedicated->pdsch_Config->choice.setup->mcs_Table = NULL; } -static struct NR_SetupRelease_PUSCH_Config *config_pusch(NR_PUSCH_Config_t *pusch_Config, - const bool use_deltaMCS, - const NR_ServingCellConfigCommon_t *scc, - const NR_UE_NR_Capability_t *uecap) +static NR_PTRS_UplinkConfig_t *config_ulptrs(const nr_ptrs_config_t *ptrs) { - struct NR_SetupRelease_PUSCH_Config *setup_puschconfig = calloc(1, sizeof(*setup_puschconfig)); + struct NR_PTRS_UplinkConfig__transformPrecoderDisabled *ptrs_config = calloc_or_fail(1, sizeof(*ptrs_config)); + AssertFatal(ptrs->ul_FreqDensity0_0 < 277, "Invalid ul_FreqDensity0_0 %d\n", ptrs->ul_FreqDensity0_0); + if (ptrs->ul_FreqDensity0_0 > 0) { + ptrs_config->frequencyDensity = calloc_or_fail(1, sizeof(*ptrs_config->frequencyDensity)); + asn1cSequenceAdd(ptrs_config->frequencyDensity->list, long, f0); + *f0 = ptrs->ul_FreqDensity0_0; + AssertFatal(ptrs->ul_FreqDensity1_0 < 277, "Invalid ul_FreqDensity1_0 %d\n", ptrs->ul_FreqDensity1_0); + if (ptrs->ul_FreqDensity1_0 > 0) { + asn1cSequenceAdd(ptrs_config->frequencyDensity->list, long, f1); + *f1 = ptrs->ul_FreqDensity1_0; + } + } + + AssertFatal(ptrs->ul_TimeDensity0_0 < 30, "Invalid ul_TimeDensity0_0 %d\n", ptrs->ul_TimeDensity0_0); + if (ptrs->ul_TimeDensity0_0 >= 0) { + ptrs_config->timeDensity = calloc_or_fail(1, sizeof(*ptrs_config->timeDensity)); + asn1cSequenceAdd(ptrs_config->timeDensity->list, long, t0); + *t0 = ptrs->ul_TimeDensity0_0; + AssertFatal(ptrs->ul_TimeDensity1_0 < 30, "Invalid ul_TimeDensity1_0 %d\n", ptrs->ul_TimeDensity1_0); + if (ptrs->ul_TimeDensity1_0 >= 0) { + asn1cSequenceAdd(ptrs_config->timeDensity->list, long, t1); + *t1 = ptrs->ul_TimeDensity1_0; + } + AssertFatal(ptrs->ul_TimeDensity2_0 < 30, "Invalid ul_TimeDensity2_0 %d\n", ptrs->ul_TimeDensity2_0); + if (ptrs->ul_TimeDensity2_0 >= 0) { + asn1cSequenceAdd(ptrs_config->timeDensity->list, long, t2); + *t2 = ptrs->ul_TimeDensity2_0; + } + } + + AssertFatal(ptrs->ul_ReOffset_0 < 3, "Invalid ul_ReOffset_0 %d\n", ptrs->ul_ReOffset_0); + if (ptrs->ul_ReOffset_0 >= 0) { + ptrs_config->resourceElementOffset = calloc_or_fail(1, sizeof(*ptrs_config->resourceElementOffset)); + *ptrs_config->resourceElementOffset = ptrs->ul_ReOffset_0; + } + AssertFatal(ptrs->ul_MaxPorts_0 == 0 || ptrs->ul_MaxPorts_0 == 1, "Invalid ul_MaxPorts_0 %d\n", ptrs->ul_MaxPorts_0); + ptrs_config->maxNrofPorts = ptrs->ul_MaxPorts_0; + AssertFatal(ptrs->ul_Power_0 >= 0 || ptrs->ul_Power_0 < 4, "Invalid ul_Power_0 %d\n", ptrs->ul_Power_0); + ptrs_config->ptrs_Power = ptrs->ul_Power_0; + + NR_PTRS_UplinkConfig_t *ulptrs = calloc_or_fail(1, sizeof(*ptrs_config)); + ulptrs->transformPrecoderDisabled = ptrs_config; + return ulptrs; +} + +static NR_SetupRelease_PUSCH_Config_t *config_pusch(NR_PUSCH_Config_t *pusch_Config, + const bool use_deltaMCS, + const NR_ServingCellConfigCommon_t *scc, + const NR_UE_NR_Capability_t *uecap, + const nr_ptrs_config_t *ptrs) +{ + NR_SetupRelease_PUSCH_Config_t *setup_puschconfig = calloc(1, sizeof(*setup_puschconfig)); setup_puschconfig->present = NR_SetupRelease_PUSCH_Config_PR_setup; if (!pusch_Config) pusch_Config = calloc(1, sizeof(*pusch_Config)); @@ -1467,6 +1515,13 @@ static struct NR_SetupRelease_PUSCH_Config *config_pusch(NR_PUSCH_Config_t *pusc if (!pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup) pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup = calloc(1, sizeof(*pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup)); NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup; + if (ptrs) { + NR_PTRS_UplinkConfig_t *ptrs_config = config_ulptrs(ptrs); + NR_SetupRelease_PTRS_UplinkConfig_t *phaseTrackingRS = calloc(1, sizeof(*phaseTrackingRS)); + phaseTrackingRS->present = NR_SetupRelease_PTRS_UplinkConfig_PR_setup; + phaseTrackingRS->choice.setup = ptrs_config; + NR_DMRS_UplinkConfig->phaseTrackingRS = phaseTrackingRS; + } NR_DMRS_UplinkConfig->dmrs_Type = NULL; NR_DMRS_UplinkConfig->dmrs_AdditionalPosition = NULL; NR_DMRS_UplinkConfig->phaseTrackingRS = NULL; @@ -1531,9 +1586,54 @@ static struct NR_SetupRelease_PUSCH_Config *config_pusch(NR_PUSCH_Config_t *pusc return setup_puschconfig; } -static struct NR_SetupRelease_PDSCH_Config *config_pdsch(uint64_t ssb_bitmap, int bwp_Id, int dl_antenna_ports) +static NR_PTRS_DownlinkConfig_t *config_dlptrs(const nr_ptrs_config_t *ptrs) { - struct NR_SetupRelease_PDSCH_Config *setup_pdsch_Config = calloc(1,sizeof(*setup_pdsch_Config)); + NR_PTRS_DownlinkConfig_t *ptrs_config = calloc_or_fail(1, sizeof(*ptrs_config)); + AssertFatal(ptrs->dl_FreqDensity0_0 < 277, "Invalid dl_FreqDensity0_0 %d\n", ptrs->dl_FreqDensity0_0); + if (ptrs->dl_FreqDensity0_0 > 0) { + ptrs_config->frequencyDensity = calloc_or_fail(1, sizeof(*ptrs_config->frequencyDensity)); + asn1cSequenceAdd(ptrs_config->frequencyDensity->list, long, f0); + *f0 = ptrs->dl_FreqDensity0_0; + AssertFatal(ptrs->dl_FreqDensity1_0 < 277, "Invalid dl_FreqDensity1_0 %d\n", ptrs->dl_FreqDensity1_0); + if (ptrs->dl_FreqDensity1_0 > 0) { + asn1cSequenceAdd(ptrs_config->frequencyDensity->list, long, f1); + *f1 = ptrs->dl_FreqDensity1_0; + } + } + + AssertFatal(ptrs->dl_TimeDensity0_0 < 30, "Invalid dl_TimeDensity0_0 %d\n", ptrs->dl_TimeDensity0_0); + if (ptrs->dl_TimeDensity0_0 >= 0) { + ptrs_config->timeDensity = calloc_or_fail(1, sizeof(*ptrs_config->timeDensity)); + asn1cSequenceAdd(ptrs_config->timeDensity->list, long, t0); + *t0 = ptrs->dl_TimeDensity0_0; + AssertFatal(ptrs->dl_TimeDensity1_0 < 30, "Invalid dl_TimeDensity1_0 %d\n", ptrs->dl_TimeDensity1_0); + if (ptrs->dl_TimeDensity1_0 >= 0) { + asn1cSequenceAdd(ptrs_config->timeDensity->list, long, t1); + *t1 = ptrs->dl_TimeDensity1_0; + } + AssertFatal(ptrs->dl_TimeDensity2_0 < 30, "Invalid dl_TimeDensity2_0 %d\n", ptrs->dl_TimeDensity2_0); + if (ptrs->dl_TimeDensity2_0 >= 0) { + asn1cSequenceAdd(ptrs_config->timeDensity->list, long, t2); + *t2 = ptrs->dl_TimeDensity2_0; + } + } + + AssertFatal(ptrs->dl_EpreRatio_0 < 4, "Invalid dl_EpreRatio_0 %d\n", ptrs->dl_EpreRatio_0); + if (ptrs->dl_EpreRatio_0 >= 0) { + ptrs_config->epre_Ratio = calloc_or_fail(1, sizeof(*ptrs_config->epre_Ratio)); + *ptrs_config->epre_Ratio = ptrs->dl_EpreRatio_0; + } + AssertFatal(ptrs->dl_ReOffset_0 < 3, "Invalid dl_ReOffset_0 %d\n", ptrs->dl_ReOffset_0); + if (ptrs->dl_ReOffset_0 >= 0) { + ptrs_config->resourceElementOffset = calloc_or_fail(1, sizeof(*ptrs_config->resourceElementOffset)); + *ptrs_config->resourceElementOffset = ptrs->dl_ReOffset_0; + } + return ptrs_config; +} + +static NR_SetupRelease_PDSCH_Config_t *config_pdsch(uint64_t ssb_bitmap, int bwp_Id, int dl_antenna_ports, nr_ptrs_config_t *ptrs) +{ + NR_SetupRelease_PDSCH_Config_t *setup_pdsch_Config = calloc(1,sizeof(*setup_pdsch_Config)); setup_pdsch_Config->present = NR_SetupRelease_PDSCH_Config_PR_setup; NR_PDSCH_Config_t *pdsch_Config = calloc(1, sizeof(*pdsch_Config)); setup_pdsch_Config->choice.setup = pdsch_Config; @@ -1541,6 +1641,13 @@ static struct NR_SetupRelease_PDSCH_Config *config_pdsch(uint64_t ssb_bitmap, in pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeA->present = NR_SetupRelease_DMRS_DownlinkConfig_PR_setup; pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup = calloc(1, sizeof(*pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup)); NR_DMRS_DownlinkConfig_t *dmrs_DownlinkForPDSCH_MappingTypeA = pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup; + if (ptrs) { + NR_PTRS_DownlinkConfig_t *ptrs_config = config_dlptrs(ptrs); + NR_SetupRelease_PTRS_DownlinkConfig_t *phaseTrackingRS = calloc(1, sizeof(*phaseTrackingRS)); + phaseTrackingRS->present = NR_SetupRelease_PTRS_DownlinkConfig_PR_setup; + phaseTrackingRS->choice.setup = ptrs_config; + dmrs_DownlinkForPDSCH_MappingTypeA->phaseTrackingRS = phaseTrackingRS; + } dmrs_DownlinkForPDSCH_MappingTypeA->dmrs_Type = NULL; dmrs_DownlinkForPDSCH_MappingTypeA->maxLength = NULL; dmrs_DownlinkForPDSCH_MappingTypeA->scramblingID0 = NULL; @@ -1582,6 +1689,7 @@ static void config_downlinkBWP(NR_BWP_Downlink_t *bwp, bool force_256qam_off, int bwp_loop, bool is_SA, + nr_ptrs_config_t *ptrs, const int num_agg_level_candidates[NUM_PDCCH_AGG_LEVELS]) { bwp->bwp_Common = calloc(1,sizeof(*bwp->bwp_Common)); @@ -1677,7 +1785,7 @@ static void config_downlinkBWP(NR_BWP_Downlink_t *bwp, asn1cSeqAdd(&bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list, ss3); bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToReleaseList = NULL; - bwp->bwp_Dedicated->pdsch_Config = config_pdsch(ssb_bitmap, bwp->bwp_Id, dl_antenna_ports); + bwp->bwp_Dedicated->pdsch_Config = config_pdsch(ssb_bitmap, bwp->bwp_Id, dl_antenna_ports, ptrs); set_dl_mcs_table(bwp->bwp_Common->genericParameters.subcarrierSpacing, force_256qam_off ? NULL : uecap, @@ -1745,7 +1853,11 @@ static void config_uplinkBWP(NR_BWP_Uplink_t *ubwp, pusch_Config = clone_pusch_config(servingcellconfigdedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[bwp_loop] ->bwp_Dedicated->pusch_Config->choice.setup); } - ubwp->bwp_Dedicated->pusch_Config = config_pusch(pusch_Config, configuration->use_deltaMCS, scc, configuration->force_UL256qam_off ? NULL : uecap); + ubwp->bwp_Dedicated->pusch_Config = config_pusch(pusch_Config, + configuration->use_deltaMCS, + scc, + configuration->force_UL256qam_off ? NULL : uecap, + configuration->ptrs); long maxMIMO_Layers = servingcellconfigdedicated && servingcellconfigdedicated->uplinkConfig @@ -3160,7 +3272,7 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid, config_pucch_resset1(pucch_Config, uid, num_pucch2, NULL); set_pucch_power_config(pucch_Config, configuration->do_CSIRS); - initialUplinkBWP->pusch_Config = config_pusch(NULL, configuration->use_deltaMCS, scc, NULL); + initialUplinkBWP->pusch_Config = config_pusch(NULL, configuration->use_deltaMCS, scc, NULL, configuration->ptrs); long maxMIMO_Layers = uplinkConfig && uplinkConfig->pusch_ServingCellConfig && uplinkConfig->pusch_ServingCellConfig->choice.setup->ext1 @@ -3214,7 +3326,7 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid, asn1cSeqAdd(&bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list, ss); asn1cSeqAdd(&bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list, ss2); - bwp_Dedicated->pdsch_Config = config_pdsch(bitmap, 0, pdsch_AntennaPorts); + bwp_Dedicated->pdsch_Config = config_pdsch(bitmap, 0, pdsch_AntennaPorts, configuration->ptrs); SpCellConfig->spCellConfigDedicated->tag_Id = 0; SpCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig = @@ -3255,7 +3367,16 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid, calloc(1, sizeof(*SpCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList)); for (int bwp_loop = 0; bwp_loop < n_dl_bwp; bwp_loop++) { NR_BWP_Downlink_t *bwp = calloc(1, sizeof(*bwp)); - config_downlinkBWP(bwp, scc, servingcellconfigdedicated, NULL, 0, false, bwp_loop, true, configuration->num_agg_level_candidates); + config_downlinkBWP(bwp, + scc, + servingcellconfigdedicated, + NULL, + 0, + false, + bwp_loop, + true, + configuration->ptrs, + configuration->num_agg_level_candidates); asn1cSeqAdd(&SpCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list, bwp); } const NR_BWP_Id_t *firstActiveDownlinkBWP_Id = servingcellconfigdedicated->firstActiveDownlinkBWP_Id; @@ -3825,7 +3946,7 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC calloc(1, sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP)); secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdcch_Config = NULL; secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config = - config_pdsch(bitmap, 0, dl_antenna_ports); + config_pdsch(bitmap, 0, dl_antenna_ports, configuration->ptrs); secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->sps_Config = NULL; // calloc(1,sizeof(struct NR_SetupRelease_SPS_Config)); @@ -3846,7 +3967,11 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC pusch_Config = clone_pusch_config( servingcellconfigdedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup); } - initialUplinkBWP->pusch_Config = config_pusch(pusch_Config, configuration->use_deltaMCS,servingcellconfigcommon, uecap); + initialUplinkBWP->pusch_Config = config_pusch(pusch_Config, + configuration->use_deltaMCS, + servingcellconfigcommon, + uecap, + configuration->ptrs); long maxMIMO_Layers = servingcellconfigdedicated->uplinkConfig && servingcellconfigdedicated->uplinkConfig->pusch_ServingCellConfig @@ -3884,6 +4009,7 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC configuration->force_256qam_off, bwp_loop, false, + configuration->ptrs, configuration->num_agg_level_candidates); asn1cSeqAdd(&secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list, bwp); } diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.PTRS.usrpx300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.PTRS.usrpx300.conf index 58bcdc1d37..2d2a103d43 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.PTRS.usrpx300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.PTRS.usrpx300.conf @@ -144,8 +144,8 @@ gNBs = ); - # Dedicated Serving Cell Configuration - servingCellConfigDedicated = ( + # PTRS Configuration + phaseTrackingRS = ( { # DL PTRS related parameters. # 3GPP TS 38.331 PTRS-DownlinkConfig From e8f53fd5ac8510e5b8a0457a2a01f57d2592b788 Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 21 Aug 2025 18:19:30 +0200 Subject: [PATCH 603/964] function to determine max UL MIMO layers --- openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c | 88 ++++++++++---------- 1 file changed, 42 insertions(+), 46 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c index b42fb97a8e..93962a9659 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c @@ -3726,6 +3726,30 @@ NR_CellGroupConfig_t *get_initial_cellGroupConfig(int uid, return cellGroupConfig; } +static long set_ul_max_layers(const nr_mac_config_t *configuration, const NR_UE_NR_Capability_t *uecap) +{ + long ul_max_layers = 1; + if (uecap && uecap->featureSets + && uecap->featureSets->featureSetsUplinkPerCC + && uecap->featureSets->featureSetsUplinkPerCC->list.count > 0) { + NR_FeatureSetUplinkPerCC_t *ul_feature_setup_per_cc = uecap->featureSets->featureSetsUplinkPerCC->list.array[0]; + if (ul_feature_setup_per_cc->mimo_CB_PUSCH->maxNumberMIMO_LayersCB_PUSCH) { + switch (*ul_feature_setup_per_cc->mimo_CB_PUSCH->maxNumberMIMO_LayersCB_PUSCH) { + case NR_MIMO_LayersUL_twoLayers: + ul_max_layers = 2; + break; + case NR_MIMO_LayersUL_fourLayers: + ul_max_layers = 4; + break; + default: + ul_max_layers = 1; + } + } + ul_max_layers = min(ul_max_layers, configuration->pusch_AntennaPorts); + } + return ul_max_layers; +} + void update_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig, const int uid, const NR_UE_NR_Capability_t *uecap, @@ -3753,46 +3777,24 @@ void update_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig, NR_UplinkConfig_t *uplinkConfig = SpCellConfig && SpCellConfig->spCellConfigDedicated ? SpCellConfig->spCellConfigDedicated->uplinkConfig : NULL; - uint8_t ul_max_layers = 1; - if (uecap && uecap->featureSets && uecap->featureSets->featureSetsUplinkPerCC - && uecap->featureSets->featureSetsUplinkPerCC->list.count > 0) { - NR_FeatureSetUplinkPerCC_t *ul_feature_setup_per_cc = uecap->featureSets->featureSetsUplinkPerCC->list.array[0]; - if (ul_feature_setup_per_cc->mimo_CB_PUSCH->maxNumberMIMO_LayersCB_PUSCH) { - switch (*ul_feature_setup_per_cc->mimo_CB_PUSCH->maxNumberMIMO_LayersCB_PUSCH) { - case NR_MIMO_LayersUL_twoLayers: - ul_max_layers = 2; - break; - case NR_MIMO_LayersUL_fourLayers: - ul_max_layers = 4; - break; - default: - ul_max_layers = 1; - } + long maxMIMO_Layers = set_ul_max_layers(configuration, uecap); + if (uplinkConfig->initialUplinkBWP->pusch_Config) { + NR_PUSCH_Config_t *pusch_Config = uplinkConfig->initialUplinkBWP->pusch_Config->choice.setup; + if (pusch_Config->maxRank == NULL) { + pusch_Config->maxRank = calloc(1, sizeof(*pusch_Config->maxRank)); } - ul_max_layers = min(ul_max_layers, configuration->pusch_AntennaPorts); - if (uplinkConfig->initialUplinkBWP->pusch_Config) { - NR_PUSCH_Config_t *pusch_Config = uplinkConfig->initialUplinkBWP->pusch_Config->choice.setup; - if (pusch_Config->maxRank == NULL) { - pusch_Config->maxRank = calloc(1, sizeof(*pusch_Config->maxRank)); - } - *pusch_Config->maxRank = ul_max_layers; - } - if (!uplinkConfig->pusch_ServingCellConfig) - uplinkConfig->pusch_ServingCellConfig = calloc(1, sizeof(*uplinkConfig->pusch_ServingCellConfig)); - uplinkConfig->pusch_ServingCellConfig->present = NR_SetupRelease_PUSCH_ServingCellConfig_PR_setup; - if (!uplinkConfig->pusch_ServingCellConfig->choice.setup) - uplinkConfig->pusch_ServingCellConfig->choice.setup = calloc(1, sizeof(*uplinkConfig->pusch_ServingCellConfig->choice.setup)); - if (!uplinkConfig->pusch_ServingCellConfig->choice.setup->ext1) - uplinkConfig->pusch_ServingCellConfig->choice.setup->ext1 = - calloc(1, sizeof(*uplinkConfig->pusch_ServingCellConfig->choice.setup->ext1)); - asn1cCallocOne(uplinkConfig->pusch_ServingCellConfig->choice.setup->ext1->maxMIMO_Layers, ul_max_layers); + *pusch_Config->maxRank = maxMIMO_Layers; } + if (!uplinkConfig->pusch_ServingCellConfig) + uplinkConfig->pusch_ServingCellConfig = calloc(1, sizeof(*uplinkConfig->pusch_ServingCellConfig)); + uplinkConfig->pusch_ServingCellConfig->present = NR_SetupRelease_PUSCH_ServingCellConfig_PR_setup; + if (!uplinkConfig->pusch_ServingCellConfig->choice.setup) + uplinkConfig->pusch_ServingCellConfig->choice.setup = calloc(1, sizeof(*uplinkConfig->pusch_ServingCellConfig->choice.setup)); + if (!uplinkConfig->pusch_ServingCellConfig->choice.setup->ext1) + uplinkConfig->pusch_ServingCellConfig->choice.setup->ext1 = + calloc(1, sizeof(*uplinkConfig->pusch_ServingCellConfig->choice.setup->ext1)); + asn1cCallocOne(uplinkConfig->pusch_ServingCellConfig->choice.setup->ext1->maxMIMO_Layers, maxMIMO_Layers); - long maxMIMO_Layers = uplinkConfig && uplinkConfig->pusch_ServingCellConfig - && uplinkConfig->pusch_ServingCellConfig->choice.setup->ext1 - && uplinkConfig->pusch_ServingCellConfig->choice.setup->ext1->maxMIMO_Layers - ? *uplinkConfig->pusch_ServingCellConfig->choice.setup->ext1->maxMIMO_Layers - : 1; // UL and SRS configuration if (configuration->do_SRS && uplinkConfig && uplinkConfig->initialUplinkBWP) { @@ -3837,7 +3839,7 @@ void update_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig, if (pusch_Config->maxRank == NULL) { pusch_Config->maxRank = calloc(1, sizeof(*pusch_Config->maxRank)); } - *pusch_Config->maxRank = ul_max_layers; + *pusch_Config->maxRank = maxMIMO_Layers; } ASN_STRUCT_FREE(asn_DEF_NR_SetupRelease_SRS_Config, ul_bwp->bwp_Dedicated->srs_Config); @@ -3973,13 +3975,7 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC uecap, configuration->ptrs); - long maxMIMO_Layers = - servingcellconfigdedicated->uplinkConfig && servingcellconfigdedicated->uplinkConfig->pusch_ServingCellConfig - && servingcellconfigdedicated->uplinkConfig->pusch_ServingCellConfig->choice.setup->ext1 - && servingcellconfigdedicated->uplinkConfig->pusch_ServingCellConfig->choice.setup->ext1->maxMIMO_Layers - ? *servingcellconfigdedicated->uplinkConfig->pusch_ServingCellConfig->choice.setup->ext1->maxMIMO_Layers - : 1; - + long maxMIMO_Layers = set_ul_max_layers(configuration, uecap); int curr_bwp = NRRIV2BW(servingcellconfigcommon->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); initialUplinkBWP->srs_Config = get_config_srs(servingcellconfigcommon, @@ -4064,7 +4060,7 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC pusch_scc->xOverhead = NULL; if (!pusch_scc->ext1) pusch_scc->ext1 = calloc(1, sizeof(*pusch_scc->ext1)); - asn1cCallocOne(pusch_scc->ext1->maxMIMO_Layers, 1); + asn1cCallocOne(pusch_scc->ext1->maxMIMO_Layers, maxMIMO_Layers); pusch_scc->ext1->processingType2Enabled = NULL; secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->carrierSwitching = NULL; From 9ab0715a5a5aef7e933b69f1e726007e4cc62794 Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 21 Aug 2025 18:38:45 +0200 Subject: [PATCH 604/964] formatting and refactoring with intermediate variable names to avoid too long lines --- openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c | 156 ++++++++----------- 1 file changed, 69 insertions(+), 87 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c index 93962a9659..041e948d55 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c @@ -3253,9 +3253,9 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid, SpCellConfig->rlmInSyncOutOfSyncThreshold = NULL; SpCellConfig->rlf_TimersAndConstants = NULL; - SpCellConfig->spCellConfigDedicated = calloc(1, sizeof(*SpCellConfig->spCellConfigDedicated)); - SpCellConfig->spCellConfigDedicated->uplinkConfig = calloc(1, sizeof(*SpCellConfig->spCellConfigDedicated->uplinkConfig)); - NR_UplinkConfig_t *uplinkConfig = SpCellConfig->spCellConfigDedicated->uplinkConfig; + NR_ServingCellConfig_t *configDedicated = calloc(1, sizeof(*configDedicated)); + configDedicated->uplinkConfig = calloc(1, sizeof(*configDedicated->uplinkConfig)); + NR_UplinkConfig_t *uplinkConfig = configDedicated->uplinkConfig; NR_BWP_UplinkDedicated_t *initialUplinkBWP = calloc(1, sizeof(*initialUplinkBWP)); uplinkConfig->initialUplinkBWP = initialUplinkBWP; @@ -3289,9 +3289,8 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid, configuration->minRXTXTIME, scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing); - SpCellConfig->spCellConfigDedicated->initialDownlinkBWP = - calloc(1, sizeof(*SpCellConfig->spCellConfigDedicated->initialDownlinkBWP)); - NR_BWP_DownlinkDedicated_t *bwp_Dedicated = SpCellConfig->spCellConfigDedicated->initialDownlinkBWP; + configDedicated->initialDownlinkBWP = calloc(1, sizeof(*configDedicated->initialDownlinkBWP)); + NR_BWP_DownlinkDedicated_t *bwp_Dedicated = configDedicated->initialDownlinkBWP; bwp_Dedicated->pdcch_Config = calloc(1, sizeof(*bwp_Dedicated->pdcch_Config)); bwp_Dedicated->pdcch_Config->present = NR_SetupRelease_PDCCH_Config_PR_setup; bwp_Dedicated->pdcch_Config->choice.setup = calloc(1, sizeof(*bwp_Dedicated->pdcch_Config->choice.setup)); @@ -3328,12 +3327,11 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid, bwp_Dedicated->pdsch_Config = config_pdsch(bitmap, 0, pdsch_AntennaPorts, configuration->ptrs); - SpCellConfig->spCellConfigDedicated->tag_Id = 0; - SpCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig = - calloc(1, sizeof(*SpCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig)); + configDedicated->tag_Id = 0; + configDedicated->pdsch_ServingCellConfig = calloc(1, sizeof(*configDedicated->pdsch_ServingCellConfig)); NR_PDSCH_ServingCellConfig_t *pdsch_servingcellconfig = calloc(1, sizeof(*pdsch_servingcellconfig)); - SpCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->present = NR_SetupRelease_PDSCH_ServingCellConfig_PR_setup; - SpCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->choice.setup = pdsch_servingcellconfig; + configDedicated->pdsch_ServingCellConfig->present = NR_SetupRelease_PDSCH_ServingCellConfig_PR_setup; + configDedicated->pdsch_ServingCellConfig->choice.setup = pdsch_servingcellconfig; pdsch_servingcellconfig->codeBlockGroupTransmission = NULL; pdsch_servingcellconfig->xOverhead = NULL; @@ -3363,8 +3361,7 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid, int default_dl_bwp = 0; int first_active_dl_bwp = 0; if (n_dl_bwp > 0) { - SpCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList = - calloc(1, sizeof(*SpCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList)); + configDedicated->downlinkBWP_ToAddModList = calloc(1, sizeof(*configDedicated->downlinkBWP_ToAddModList)); for (int bwp_loop = 0; bwp_loop < n_dl_bwp; bwp_loop++) { NR_BWP_Downlink_t *bwp = calloc(1, sizeof(*bwp)); config_downlinkBWP(bwp, @@ -3377,15 +3374,15 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid, true, configuration->ptrs, configuration->num_agg_level_candidates); - asn1cSeqAdd(&SpCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list, bwp); + asn1cSeqAdd(&configDedicated->downlinkBWP_ToAddModList->list, bwp); } const NR_BWP_Id_t *firstActiveDownlinkBWP_Id = servingcellconfigdedicated->firstActiveDownlinkBWP_Id; first_active_dl_bwp = firstActiveDownlinkBWP_Id ? *firstActiveDownlinkBWP_Id : 1; const NR_BWP_Id_t *defaultDownlinkBWP_Id = servingcellconfigdedicated->defaultDownlinkBWP_Id; default_dl_bwp = defaultDownlinkBWP_Id ? *defaultDownlinkBWP_Id : 1; } - asn1cCallocOne(SpCellConfig->spCellConfigDedicated->firstActiveDownlinkBWP_Id, first_active_dl_bwp); - asn1cCallocOne(SpCellConfig->spCellConfigDedicated->defaultDownlinkBWP_Id, default_dl_bwp); + asn1cCallocOne(configDedicated->firstActiveDownlinkBWP_Id, first_active_dl_bwp); + asn1cCallocOne(configDedicated->defaultDownlinkBWP_Id, default_dl_bwp); // Uplink BWPs int n_ul_bwp = 0; @@ -3407,11 +3404,11 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid, } asn1cCallocOne(uplinkConfig->firstActiveUplinkBWP_Id, first_active_ul_bwp); - SpCellConfig->spCellConfigDedicated->csi_MeasConfig = calloc(1, sizeof(*SpCellConfig->spCellConfigDedicated->csi_MeasConfig)); - SpCellConfig->spCellConfigDedicated->csi_MeasConfig->present = NR_SetupRelease_CSI_MeasConfig_PR_setup; + configDedicated->csi_MeasConfig = calloc(1, sizeof(*configDedicated->csi_MeasConfig)); + configDedicated->csi_MeasConfig->present = NR_SetupRelease_CSI_MeasConfig_PR_setup; NR_CSI_MeasConfig_t *csi_MeasConfig = calloc(1, sizeof(*csi_MeasConfig)); - SpCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup = csi_MeasConfig; + configDedicated->csi_MeasConfig->choice.setup = csi_MeasConfig; csi_MeasConfig->csi_SSB_ResourceSetToAddModList = calloc(1, sizeof(*csi_MeasConfig->csi_SSB_ResourceSetToAddModList)); csi_MeasConfig->csi_SSB_ResourceSetToReleaseList = NULL; @@ -3437,11 +3434,11 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid, int curr_bwp, bwp_id; struct NR_SetupRelease_PDSCH_Config *pdsch_Config; if (bwp_loop == 0) { - pdsch_Config = SpCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config; + pdsch_Config = configDedicated->initialDownlinkBWP->pdsch_Config; curr_bwp = NRRIV2BW(scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); bwp_id = 0; } else { - NR_BWP_Downlink_t *bwp = SpCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[bwp_loop - 1]; + NR_BWP_Downlink_t *bwp = configDedicated->downlinkBWP_ToAddModList->list.array[bwp_loop - 1]; pdsch_Config = bwp->bwp_Dedicated->pdsch_Config; curr_bwp = NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); bwp_id = bwp->bwp_Id; @@ -3522,7 +3519,8 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid, configuration->do_SINR); } - fill_harq_IEs(SpCellConfig->spCellConfigDedicated, configuration->num_dlharq, configuration->num_ulharq); + fill_harq_IEs(configDedicated, configuration->num_dlharq, configuration->num_ulharq); + SpCellConfig->spCellConfigDedicated = configDedicated; if (LOG_DEBUGFLAG(DEBUG_ASN1)) { xer_fprint(stdout, &asn_DEF_NR_SpCellConfig, SpCellConfig); @@ -3938,30 +3936,27 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC NR_RLF_TimersAndConstants__ext1__t311_ms30000; secondaryCellGroup->spCellConfig->rlmInSyncOutOfSyncThreshold = NULL; - secondaryCellGroup->spCellConfig->spCellConfigDedicated = - calloc(1, sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated)); - secondaryCellGroup->spCellConfig->spCellConfigDedicated->tdd_UL_DL_ConfigurationDedicated = NULL; + NR_ServingCellConfig_t *configDedicated = calloc(1, sizeof(*configDedicated)); + configDedicated->tdd_UL_DL_ConfigurationDedicated = NULL; /// initialDownlinkBWP - secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP = - calloc(1, sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP)); - secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdcch_Config = NULL; - secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config = + configDedicated->initialDownlinkBWP = calloc(1, sizeof(*configDedicated->initialDownlinkBWP)); + configDedicated->initialDownlinkBWP->pdcch_Config = NULL; + configDedicated->initialDownlinkBWP->pdsch_Config = config_pdsch(bitmap, 0, dl_antenna_ports, configuration->ptrs); - secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->sps_Config = - NULL; // calloc(1,sizeof(struct NR_SetupRelease_SPS_Config)); + configDedicated->initialDownlinkBWP->sps_Config = NULL; // calloc(1,sizeof(struct NR_SetupRelease_SPS_Config)); - secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->radioLinkMonitoringConfig = NULL; + configDedicated->initialDownlinkBWP->radioLinkMonitoringConfig = NULL; /// initialUplinkBWP - if (!secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig) { - secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig = - calloc(1, sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig)); + if (!configDedicated->uplinkConfig) { + configDedicated->uplinkConfig = calloc(1, sizeof(*configDedicated->uplinkConfig)); } + NR_UplinkConfig_t *ulConfig = configDedicated->uplinkConfig; NR_BWP_UplinkDedicated_t *initialUplinkBWP = calloc(1, sizeof(*initialUplinkBWP)); - secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP = initialUplinkBWP; + ulConfig->initialUplinkBWP = initialUplinkBWP; initialUplinkBWP->pucch_Config = NULL; NR_PUSCH_Config_t *pusch_Config = NULL; @@ -3993,8 +3988,7 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC n_dl_bwp = servingcellconfigdedicated->downlinkBWP_ToAddModList->list.count; } if (n_dl_bwp > 0) { - secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList = - calloc(1, sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList)); + configDedicated->downlinkBWP_ToAddModList = calloc(1, sizeof(*configDedicated->downlinkBWP_ToAddModList)); for (int bwp_loop = 0; bwp_loop < n_dl_bwp; bwp_loop++) { NR_BWP_Downlink_t *bwp = calloc(1, sizeof(*bwp)); config_downlinkBWP(bwp, @@ -4007,15 +4001,13 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC false, configuration->ptrs, configuration->num_agg_level_candidates); - asn1cSeqAdd(&secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list, bwp); + asn1cSeqAdd(&configDedicated->downlinkBWP_ToAddModList->list, bwp); } - secondaryCellGroup->spCellConfig->spCellConfigDedicated->firstActiveDownlinkBWP_Id = - calloc(1, sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->firstActiveDownlinkBWP_Id)); - *secondaryCellGroup->spCellConfig->spCellConfigDedicated->firstActiveDownlinkBWP_Id = + configDedicated->firstActiveDownlinkBWP_Id = calloc(1, sizeof(*configDedicated->firstActiveDownlinkBWP_Id)); + *configDedicated->firstActiveDownlinkBWP_Id = servingcellconfigdedicated->firstActiveDownlinkBWP_Id ? *servingcellconfigdedicated->firstActiveDownlinkBWP_Id : 1; - secondaryCellGroup->spCellConfig->spCellConfigDedicated->defaultDownlinkBWP_Id = - calloc(1, sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->defaultDownlinkBWP_Id)); - *secondaryCellGroup->spCellConfig->spCellConfigDedicated->defaultDownlinkBWP_Id = + configDedicated->defaultDownlinkBWP_Id = calloc(1, sizeof(*configDedicated->defaultDownlinkBWP_Id)); + *configDedicated->defaultDownlinkBWP_Id = servingcellconfigdedicated->defaultDownlinkBWP_Id ? *servingcellconfigdedicated->defaultDownlinkBWP_Id : 1; } @@ -4025,36 +4017,29 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC n_ul_bwp = servingcellconfigdedicated->uplinkConfig->uplinkBWP_ToAddModList->list.count; } if (n_ul_bwp > 0) { - secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList = - calloc(1, sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList)); + ulConfig->uplinkBWP_ToAddModList = calloc(1, sizeof(*ulConfig->uplinkBWP_ToAddModList)); for (int bwp_loop = 0; bwp_loop < n_ul_bwp; bwp_loop++) { NR_BWP_Uplink_t *ubwp = calloc(1, sizeof(*ubwp)); config_uplinkBWP(ubwp, bwp_loop, false, uid, configuration, servingcellconfigdedicated, servingcellconfigcommon, uecap); - asn1cSeqAdd(&secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list, ubwp); + asn1cSeqAdd(&ulConfig->uplinkBWP_ToAddModList->list, ubwp); } - secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->firstActiveUplinkBWP_Id = - calloc(1, sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->firstActiveUplinkBWP_Id)); - *secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->firstActiveUplinkBWP_Id = + ulConfig->firstActiveUplinkBWP_Id = calloc(1, sizeof(*ulConfig->firstActiveUplinkBWP_Id)); + *ulConfig->firstActiveUplinkBWP_Id = servingcellconfigdedicated->uplinkConfig->firstActiveUplinkBWP_Id ? *servingcellconfigdedicated->uplinkConfig->firstActiveUplinkBWP_Id : 1; } - secondaryCellGroup->spCellConfig->spCellConfigDedicated->bwp_InactivityTimer = NULL; - secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToReleaseList = NULL; - secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToReleaseList = NULL; + configDedicated->bwp_InactivityTimer = NULL; + configDedicated->downlinkBWP_ToReleaseList = NULL; + ulConfig->uplinkBWP_ToReleaseList = NULL; - if (!secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->pusch_ServingCellConfig) - secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->pusch_ServingCellConfig = - calloc(1, sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->pusch_ServingCellConfig)); - secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->pusch_ServingCellConfig->present = - NR_SetupRelease_PUSCH_ServingCellConfig_PR_setup; - if (!secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->pusch_ServingCellConfig->choice.setup) - secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->pusch_ServingCellConfig->choice.setup = calloc( - 1, - sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->pusch_ServingCellConfig->choice.setup)); - NR_PUSCH_ServingCellConfig_t *pusch_scc = - secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->pusch_ServingCellConfig->choice.setup; + if (!ulConfig->pusch_ServingCellConfig) + ulConfig->pusch_ServingCellConfig = calloc(1, sizeof(*ulConfig->pusch_ServingCellConfig)); + ulConfig->pusch_ServingCellConfig->present = NR_SetupRelease_PUSCH_ServingCellConfig_PR_setup; + if (!ulConfig->pusch_ServingCellConfig->choice.setup) + ulConfig->pusch_ServingCellConfig->choice.setup = calloc(1, sizeof(*ulConfig->pusch_ServingCellConfig->choice.setup)); + NR_PUSCH_ServingCellConfig_t *pusch_scc = ulConfig->pusch_ServingCellConfig->choice.setup; pusch_scc->codeBlockGroupTransmission = NULL; pusch_scc->rateMatching = NULL; pusch_scc->xOverhead = NULL; @@ -4063,16 +4048,14 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC asn1cCallocOne(pusch_scc->ext1->maxMIMO_Layers, maxMIMO_Layers); pusch_scc->ext1->processingType2Enabled = NULL; - secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->carrierSwitching = NULL; - secondaryCellGroup->spCellConfig->spCellConfigDedicated->supplementaryUplink = NULL; - secondaryCellGroup->spCellConfig->spCellConfigDedicated->pdcch_ServingCellConfig = NULL; + ulConfig->carrierSwitching = NULL; + configDedicated->supplementaryUplink = NULL; + configDedicated->pdcch_ServingCellConfig = NULL; - secondaryCellGroup->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig = - calloc(1, sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig)); + configDedicated->pdsch_ServingCellConfig = calloc(1, sizeof(*configDedicated->pdsch_ServingCellConfig)); NR_PDSCH_ServingCellConfig_t *pdsch_servingcellconfig = calloc(1, sizeof(*pdsch_servingcellconfig)); - secondaryCellGroup->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->present = - NR_SetupRelease_PDSCH_ServingCellConfig_PR_setup; - secondaryCellGroup->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->choice.setup = pdsch_servingcellconfig; + configDedicated->pdsch_ServingCellConfig->present = NR_SetupRelease_PDSCH_ServingCellConfig_PR_setup; + configDedicated->pdsch_ServingCellConfig->choice.setup = pdsch_servingcellconfig; pdsch_servingcellconfig->codeBlockGroupTransmission = NULL; pdsch_servingcellconfig->xOverhead = NULL; asn1cCallocOne(pdsch_servingcellconfig->nrofHARQ_ProcessesForPDSCH, NR_PDSCH_ServingCellConfig__nrofHARQ_ProcessesForPDSCH_n16); @@ -4093,13 +4076,12 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC pdsch_servingcellconfig->ext3->downlinkHARQ_FeedbackDisabled_r17->choice.setup.buf[3] = 0xFF; } - secondaryCellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig = NULL; - secondaryCellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig = - calloc(1, sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig)); - secondaryCellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig->present = NR_SetupRelease_CSI_MeasConfig_PR_setup; + configDedicated->csi_MeasConfig = NULL; + configDedicated->csi_MeasConfig = calloc(1, sizeof(*configDedicated->csi_MeasConfig)); + configDedicated->csi_MeasConfig->present = NR_SetupRelease_CSI_MeasConfig_PR_setup; NR_CSI_MeasConfig_t *csi_MeasConfig = calloc(1, sizeof(*csi_MeasConfig)); - secondaryCellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup = csi_MeasConfig; + configDedicated->csi_MeasConfig->choice.setup = csi_MeasConfig; csi_MeasConfig->csi_ResourceConfigToAddModList = calloc(1, sizeof(*csi_MeasConfig->csi_ResourceConfigToAddModList)); csi_MeasConfig->csi_ResourceConfigToReleaseList = NULL; @@ -4123,8 +4105,7 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC asn1cSeqAdd(&csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list, ssbresset0); for (int bwp_loop = 0; bwp_loop < n_dl_bwp; bwp_loop++) { - NR_BWP_Downlink_t *bwp = - secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[bwp_loop]; + NR_BWP_Downlink_t *bwp = configDedicated->downlinkBWP_ToAddModList->list.array[bwp_loop]; int curr_bwp = NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); config_csirs(servingcellconfigcommon, csi_MeasConfig, dl_antenna_ports, curr_bwp, do_csirs, bwp_loop); @@ -4198,14 +4179,15 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC dl_antenna_ports, configuration->do_SINR); } - secondaryCellGroup->spCellConfig->spCellConfigDedicated->sCellDeactivationTimer = NULL; - secondaryCellGroup->spCellConfig->spCellConfigDedicated->crossCarrierSchedulingConfig = NULL; - secondaryCellGroup->spCellConfig->spCellConfigDedicated->tag_Id = 0; - secondaryCellGroup->spCellConfig->spCellConfigDedicated->dummy1 = NULL; - secondaryCellGroup->spCellConfig->spCellConfigDedicated->pathlossReferenceLinking = NULL; - secondaryCellGroup->spCellConfig->spCellConfigDedicated->servingCellMO = NULL; + configDedicated->sCellDeactivationTimer = NULL; + configDedicated->crossCarrierSchedulingConfig = NULL; + configDedicated->tag_Id = 0; + configDedicated->dummy1 = NULL; + configDedicated->pathlossReferenceLinking = NULL; + configDedicated->servingCellMO = NULL; - fill_harq_IEs(secondaryCellGroup->spCellConfig->spCellConfigDedicated, configuration->num_dlharq, configuration->num_ulharq); + fill_harq_IEs(configDedicated, configuration->num_dlharq, configuration->num_ulharq); + secondaryCellGroup->spCellConfig->spCellConfigDedicated = configDedicated; if (LOG_DEBUGFLAG(DEBUG_ASN1)) { xer_fprint(stdout, &asn_DEF_NR_SpCellConfig, (void *)secondaryCellGroup->spCellConfig); From 3ea02249d66ff253b6321ace77c378bb4564c11f Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 21 Aug 2025 11:47:40 +0200 Subject: [PATCH 605/964] rework BWP configuration via file --- .../gnb-du.sa.band78.106prb.usrpb200.conf | 14 +- .../gnb.sa.band78.106prb.rfsim.neighbour.conf | 62 +----- doc/RUN_NR_multiple_BWPs.md | 27 +-- openair1/SIMULATION/NR_PHY/dlsim.c | 9 +- openair1/SIMULATION/NR_PHY/ulsim.c | 9 +- openair2/GNB_APP/RRC_nr_paramsvalues.h | 64 ------- openair2/GNB_APP/gnb_config.c | 128 ++++--------- openair2/GNB_APP/gnb_paramdef.h | 28 +++ .../NR_MAC_gNB/gNB_scheduler_primitives.c | 3 +- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 1 - .../LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c | 5 +- openair2/LAYER2/NR_MAC_gNB/main.c | 4 - openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 12 +- openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c | 180 ++++++------------ openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h | 2 - ....sa.band78.fr1.106PRB.usrpb210.redcap.yaml | 17 +- 16 files changed, 156 insertions(+), 409 deletions(-) diff --git a/ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf b/ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf index 9b46110547..e4d9127284 100644 --- a/ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf +++ b/ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf @@ -146,18 +146,8 @@ gNBs = ); - servingCellConfigDedicated = ({ - dl_bwp-Id_1 = 1; - dl_bwp1_locationAndBandwidth = 28875; # RBstart=0, L=106 (275*(L-1))+RBstart - dl_bwp1_subcarrierSpacing = 1; - firstActiveDownlinkBWP-Id = 1; - defaultDownlinkBWP-Id = 1; - ul_bwp-Id_1 = 1; - ul_bwp1_locationAndBandwidth = 28875; # RBstart=0, L=106 (275*(L-1))+RBstart - ul_bwp1_subcarrierSpacing = 1; - firstActiveUplinkBWP-Id = 1; - }); - + first_active_bwp = 1; + bwp_list = ({ scs = 1; bwpStart = 0; bwpSize = 106;}); # ------- SCTP definitions SCTP : diff --git a/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.neighbour.conf b/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.neighbour.conf index 0808c4b43d..a0784a6597 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.neighbour.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.neighbour.conf @@ -145,64 +145,10 @@ gNBs = ); - # Dedicated Serving Cell Configuration - servingCellConfigDedicated = ({ - # BWP-Downlink - # BWP 1 Configuration - dl_bwp-Id_1 = 1; - dl_bwp1_locationAndBandwidth = 28875; // RBstart=0, L=106 (40 MHz BW) - # subcarrierSpacing - # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 - dl_bwp1_subcarrierSpacing = 1; - - # BWP 2 Configuration - dl_bwp-Id_2 = 2; - dl_bwp2_locationAndBandwidth = 13750; // RBstart=0, L=51 (20 MHz BW) - # subcarrierSpacing - # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 - dl_bwp2_subcarrierSpacing = 1; - - # BWP 3 Configuration - dl_bwp-Id_3 = 3; - dl_bwp3_locationAndBandwidth = 6325; // RBstart=0, L=24 (10 MHz BW) - # subcarrierSpacing - # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 - dl_bwp3_subcarrierSpacing = 1; - - firstActiveDownlinkBWP-Id = 1; #BWP-Id - defaultDownlinkBWP-Id = 1; #BWP-Id - - # bwp-InactivityTimer ENUMERATED {ms2, ms3, ms4, ms5, ms6, ms8, ms10, ms20, ms30, - # ms40,ms50, ms60, ms80,ms100, ms200,ms300, ms500, - # ms750, ms1280, ms1920, ms2560, spare10, spare9, spare8, - # spare7, spare6, spare5, spare4, spare3, spare2, spare1 } - - # UplinkConfig - # BWP-Uplink - # BWP 1 Configuration - ul_bwp-Id_1 = 1; - ul_bwp1_locationAndBandwidth = 28875; // RBstart=0, L=106 (40 MHz BW) - # subcarrierSpacing - # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 - ul_bwp1_subcarrierSpacing = 1; - - # BWP 2 Configuration - ul_bwp-Id_2 = 2; - ul_bwp2_locationAndBandwidth = 13750; // RBstart=0, L=51 (20 MHz BW) - # subcarrierSpacing - # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 - ul_bwp2_subcarrierSpacing = 1; - - # BWP 3 Configuration - ul_bwp-Id_3 = 3; - ul_bwp3_locationAndBandwidth = 6325; // RBstart=0, L=24 (10 MHz BW) - # subcarrierSpacing - # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 - ul_bwp3_subcarrierSpacing = 1; - - firstActiveUplinkBWP-Id = 1; #BWP-Id - } - ); + first_active_bwp = 1; + bwp_list = ({ scs = 1; bwpStart = 0; bwpSize = 106;}, + { scs = 1; bwpStart = 0; bwpSize = 51;}, + { scs = 1; bwpStart = 0; bwpSize = 24;}); # ------- SCTP definitions diff --git a/doc/RUN_NR_multiple_BWPs.md b/doc/RUN_NR_multiple_BWPs.md index 7b79374fd7..e8598a0445 100644 --- a/doc/RUN_NR_multiple_BWPs.md +++ b/doc/RUN_NR_multiple_BWPs.md @@ -17,35 +17,28 @@ A UE can be configured with a set of 4 BWPs in uplink (UL) and downlink (DL) dir A maximum of 4 dedicated BWPs can be configured for a UE. -To configure multiple BWPs, add the following parameters to the gNB configuration file under "servingCellConfigDedicated": +To configure multiple BWPs, add the following parameters in the physical parameters section: ## Setup of the Configuration files ## + +In the configuration file you have the option to select the 1st active BWP, the RIV and SCS of each BWP in the following way (example with 3 additional BWPs): ``` - firstActiveDownlinkBWP-Id = 1; #BWP-Id - defaultDownlinkBWP-Id = 1; #BWP-Id - firstActiveUplinkBWP-Id = 1; #BWP-Id + first_active_bwp = 1; + bwp_list = ({ scs = 1; bwpStart = 0; bwpSize = 106;}, + { scs = 1; bwpStart = 0; bwpSize = 51;}, + { scs = 1; bwpStart = 0; bwpSize = 24;}); ``` -Each dedicated BWP must have: -``` - # BWP 1 Configuration - dl_bwp-Id_1 = 1; - dl_bwp1_locationAndBandwidth = 28875; // RBstart=0, L=106 (40 MHz BW) - # subcarrierSpacing - # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 - dl_bwp1_subcarrierSpacing = 1; -``` - - Find these parameters in this configuration file: "targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf" +This example configures 3 additional BWPs, with IDs from 1 to 3. Find these parameters in this configuration file: "ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.neighbour.conf" # Testing gNB and UE in RF simulator ## gNB command: ``` - sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf --gNBs.[0].min_rxtxtime 6 --rfsim + sudo ./nr-softmodem -O ../../../ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.neighbour.conf --rfsim --rfsimulator.serveraddr server ``` ## UE command: ``` - sudo ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --rfsim --uicc0.imsi 208990000000001 --rfsimulator.serveraddr 127.0.0.1 + sudo ./nr-uesoftmodem -C 3319680000 -r 106 --numerology 1 --ssb 516 --band 78 --rfsim --rfsimulator.serveraddr 127.0.0.1 ``` diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index 43abb68a12..828ff176ec 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -743,7 +743,7 @@ printf("%d\n", slot); RC.nb_nr_mac_CC = (int*)malloc(RC.nb_nr_macrlc_inst*sizeof(int)); for (i = 0; i < RC.nb_nr_macrlc_inst; i++) RC.nb_nr_mac_CC[i] = 1; - mac_top_init_gNB(ngran_gNB, scc, NULL, &conf, &rlc_config); + mac_top_init_gNB(ngran_gNB, scc, &conf, &rlc_config); gNB_mac = RC.nrmac[0]; nr_mac_config_scc(RC.nrmac[0], scc, &conf); @@ -791,11 +791,6 @@ printf("%d\n", slot); NR_ServingCellConfigCommon_t *scc = secondaryCellGroup->spCellConfig->reconfigurationWithSync->spCellConfigCommon; */ - NR_ServingCellConfig_t *scd = calloc(1,sizeof(*scd)); - prepare_scd(scd); - /* removes unnecessary BWPs, if any */ - fix_scd(scd); - gNB->ap_N1 = pdsch_AntennaPorts.N1; gNB->ap_N2 = pdsch_AntennaPorts.N2; gNB->ap_XP = pdsch_AntennaPorts.XP; @@ -806,7 +801,7 @@ printf("%d\n", slot); prepare_sim_uecap(UE_Capability_nr, scc, mu, N_RB_DL, g_mcsTableIdx, 0); rnti_t rnti = 0x1234; int uid = 0; - NR_CellGroupConfig_t *secondaryCellGroup = get_default_secondaryCellGroup(scc, scd, UE_Capability_nr, 0, 1, &conf, uid); + NR_CellGroupConfig_t *secondaryCellGroup = get_default_secondaryCellGroup(scc, UE_Capability_nr, 0, 1, &conf, uid); secondaryCellGroup->spCellConfig->reconfigurationWithSync = get_reconfiguration_with_sync(rnti, uid, scc); /* -U option modify DMRS */ diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index 466ffc6822..647456d8d6 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -698,19 +698,14 @@ int main(int argc, char *argv[]) RC.nb_nr_mac_CC = (int*)malloc(RC.nb_nr_macrlc_inst*sizeof(int)); for (i = 0; i < RC.nb_nr_macrlc_inst; i++) RC.nb_nr_mac_CC[i] = 1; - mac_top_init_gNB(ngran_gNB, scc, NULL /* scd will be updated further below */, &conf, &rlc_config); + mac_top_init_gNB(ngran_gNB, scc, &conf, &rlc_config); nr_mac_config_scc(RC.nrmac[0], scc, &conf); - NR_ServingCellConfig_t *scd = calloc(1,sizeof(NR_ServingCellConfig_t)); - prepare_scd(scd); - /* removes unnecessary BWPs, if any */ - fix_scd(scd); - NR_UE_NR_Capability_t* UE_Capability_nr = CALLOC(1,sizeof(NR_UE_NR_Capability_t)); prepare_sim_uecap(UE_Capability_nr, scc, mu, N_RB_UL, 0, mcs_table); rnti_t rnti = 0x1234; int uid = 0; - NR_CellGroupConfig_t *secondaryCellGroup = get_default_secondaryCellGroup(scc, scd, UE_Capability_nr, 0, 1, &conf, uid); + NR_CellGroupConfig_t *secondaryCellGroup = get_default_secondaryCellGroup(scc, UE_Capability_nr, 0, 1, &conf, uid); secondaryCellGroup->spCellConfig->reconfigurationWithSync = get_reconfiguration_with_sync(rnti, uid, scc); NR_BCCH_BCH_Message_t *mib = get_new_MIB_NR(scc); diff --git a/openair2/GNB_APP/RRC_nr_paramsvalues.h b/openair2/GNB_APP/RRC_nr_paramsvalues.h index 85aa8d979f..28d5f71ff9 100644 --- a/openair2/GNB_APP/RRC_nr_paramsvalues.h +++ b/openair2/GNB_APP/RRC_nr_paramsvalues.h @@ -136,37 +136,6 @@ #define GNB_CONFIG_STRING_TA_COMMONDRIFT "ta-CommonDrift-r17" #define CARRIERBANDWIDTH_OKVALUES {11,18,24,25,31,32,38,51,52,65,66,78,79,93,106,107,121,132,133,135,160,162,189,216,217,245,264,270,273} - -/* Serving Cell Config Dedicated */ -#define GNB_CONFIG_STRING_SERVINGCELLCONFIGDEDICATED "servingCellConfigDedicated" -#define GNB_CONFIG_STRING_DLBWP1_ID "dl_bwp-Id_1" -#define GNB_CONFIG_STRING_DLBWP2_ID "dl_bwp-Id_2" -#define GNB_CONFIG_STRING_DLBWP3_ID "dl_bwp-Id_3" -#define GNB_CONFIG_STRING_DLBWP4_ID "dl_bwp-Id_4" -#define GNB_CONFIG_STRING_LOCATIONANDBANDWIDTH_DLBWP1 "dl_bwp1_locationAndBandwidth" -#define GNB_CONFIG_STRING_LOCATIONANDBANDWIDTH_DLBWP2 "dl_bwp2_locationAndBandwidth" -#define GNB_CONFIG_STRING_LOCATIONANDBANDWIDTH_DLBWP3 "dl_bwp3_locationAndBandwidth" -#define GNB_CONFIG_STRING_LOCATIONANDBANDWIDTH_DLBWP4 "dl_bwp4_locationAndBandwidth" -#define GNB_CONFIG_STRING_SCS_DLBWP1 "dl_bwp1_subcarrierSpacing" -#define GNB_CONFIG_STRING_SCS_DLBWP2 "dl_bwp2_subcarrierSpacing" -#define GNB_CONFIG_STRING_SCS_DLBWP3 "dl_bwp3_subcarrierSpacing" -#define GNB_CONFIG_STRING_SCS_DLBWP4 "dl_bwp4_subcarrierSpacing" -#define GNB_CONFIG_STRING_FIRSTACTIVEDLBWP_ID "firstActiveDownlinkBWP-Id" -#define GNB_CONFIG_STRING_DEFAULTDLBWP_ID "defaultDownlinkBWP-Id" -#define GNB_CONFIG_STRING_ULBWP1_ID "ul_bwp-Id_1" -#define GNB_CONFIG_STRING_ULBWP2_ID "ul_bwp-Id_2" -#define GNB_CONFIG_STRING_ULBWP3_ID "ul_bwp-Id_3" -#define GNB_CONFIG_STRING_ULBWP4_ID "ul_bwp-Id_4" -#define GNB_CONFIG_STRING_LOCATIONANDBANDWIDTH_ULBWP1 "ul_bwp1_locationAndBandwidth" -#define GNB_CONFIG_STRING_LOCATIONANDBANDWIDTH_ULBWP2 "ul_bwp2_locationAndBandwidth" -#define GNB_CONFIG_STRING_LOCATIONANDBANDWIDTH_ULBWP3 "ul_bwp3_locationAndBandwidth" -#define GNB_CONFIG_STRING_LOCATIONANDBANDWIDTH_ULBWP4 "ul_bwp4_locationAndBandwidth" -#define GNB_CONFIG_STRING_SCS_ULBWP1 "ul_bwp1_subcarrierSpacing" -#define GNB_CONFIG_STRING_SCS_ULBWP2 "ul_bwp2_subcarrierSpacing" -#define GNB_CONFIG_STRING_SCS_ULBWP3 "ul_bwp3_subcarrierSpacing" -#define GNB_CONFIG_STRING_SCS_ULBWP4 "ul_bwp4_subcarrierSpacing" -#define GNB_CONFIG_STRING_FIRSTACTIVEULBWP_ID "firstActiveUplinkBWP-Id" - /*--------------------------------------------------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ @@ -256,39 +225,6 @@ {GNB_CONFIG_STRING_NROFUPLINKSLOTS2,NULL, 0,.i64ptr=&pattern2.nrofUplinkSlots,.defint64val=-1,TYPE_INT64,0},\ {GNB_CONFIG_STRING_NROFUPLINKSYMBOLS2,NULL, 0,.i64ptr=&pattern2.nrofUplinkSymbols,.defint64val=-1,TYPE_INT64,0}} -/*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ -/* Serving Cell Config Dedicated configuration parameters */ -/*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ - -#define SCDPARAMS_DESC(scd) { \ -{GNB_CONFIG_STRING_FIRSTACTIVEDLBWP_ID,NULL,0,.i64ptr=scd->firstActiveDownlinkBWP_Id,.defint64val=1,TYPE_INT64,0}, \ -{GNB_CONFIG_STRING_FIRSTACTIVEULBWP_ID,NULL,0,.i64ptr=scd->uplinkConfig->firstActiveUplinkBWP_Id,.defint64val=1,TYPE_INT64,0}, \ -{GNB_CONFIG_STRING_DLBWP1_ID,NULL,0,.i64ptr=&scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Id,.defint64val=1,TYPE_INT64,0}, \ -{GNB_CONFIG_STRING_DLBWP2_ID,NULL,0,.i64ptr=&scd->downlinkBWP_ToAddModList->list.array[1]->bwp_Id,.defint64val=2,TYPE_INT64,0}, \ -{GNB_CONFIG_STRING_DLBWP3_ID,NULL,0,.i64ptr=&scd->downlinkBWP_ToAddModList->list.array[2]->bwp_Id,.defint64val=3,TYPE_INT64,0}, \ -{GNB_CONFIG_STRING_DLBWP4_ID,NULL,0,.i64ptr=&scd->downlinkBWP_ToAddModList->list.array[3]->bwp_Id,.defint64val=4,TYPE_INT64,0}, \ -{GNB_CONFIG_STRING_SCS_DLBWP1,NULL,0,.i64ptr=&scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Common->genericParameters.subcarrierSpacing,.defint64val=1,TYPE_INT64,0}, \ -{GNB_CONFIG_STRING_SCS_DLBWP2,NULL,0,.i64ptr=&scd->downlinkBWP_ToAddModList->list.array[1]->bwp_Common->genericParameters.subcarrierSpacing,.defint64val=1,TYPE_INT64,0}, \ -{GNB_CONFIG_STRING_SCS_DLBWP3,NULL,0,.i64ptr=&scd->downlinkBWP_ToAddModList->list.array[2]->bwp_Common->genericParameters.subcarrierSpacing,.defint64val=1,TYPE_INT64,0}, \ -{GNB_CONFIG_STRING_SCS_DLBWP4,NULL,0,.i64ptr=&scd->downlinkBWP_ToAddModList->list.array[3]->bwp_Common->genericParameters.subcarrierSpacing,.defint64val=1,TYPE_INT64,0}, \ -{GNB_CONFIG_STRING_LOCATIONANDBANDWIDTH_DLBWP1,NULL,0,.i64ptr=&scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Common->genericParameters.locationAndBandwidth,.defint64val=0,TYPE_INT64,0}, \ -{GNB_CONFIG_STRING_LOCATIONANDBANDWIDTH_DLBWP2,NULL,0,.i64ptr=&scd->downlinkBWP_ToAddModList->list.array[1]->bwp_Common->genericParameters.locationAndBandwidth,.defint64val=0,TYPE_INT64,0}, \ -{GNB_CONFIG_STRING_LOCATIONANDBANDWIDTH_DLBWP3,NULL,0,.i64ptr=&scd->downlinkBWP_ToAddModList->list.array[2]->bwp_Common->genericParameters.locationAndBandwidth,.defint64val=0,TYPE_INT64,0}, \ -{GNB_CONFIG_STRING_LOCATIONANDBANDWIDTH_DLBWP4,NULL,0,.i64ptr=&scd->downlinkBWP_ToAddModList->list.array[3]->bwp_Common->genericParameters.locationAndBandwidth,.defint64val=0,TYPE_INT64,0}, \ -{GNB_CONFIG_STRING_ULBWP1_ID,NULL,0,.i64ptr=&scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Id,.defint64val=1,TYPE_INT64,0}, \ -{GNB_CONFIG_STRING_ULBWP2_ID,NULL,0,.i64ptr=&scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[1]->bwp_Id,.defint64val=2,TYPE_INT64,0}, \ -{GNB_CONFIG_STRING_ULBWP3_ID,NULL,0,.i64ptr=&scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[2]->bwp_Id,.defint64val=3,TYPE_INT64,0}, \ -{GNB_CONFIG_STRING_ULBWP4_ID,NULL,0,.i64ptr=&scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[3]->bwp_Id,.defint64val=4,TYPE_INT64,0}, \ -{GNB_CONFIG_STRING_SCS_ULBWP1,NULL,0,.i64ptr=&scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Common->genericParameters.subcarrierSpacing,.defint64val=1,TYPE_INT64,0}, \ -{GNB_CONFIG_STRING_SCS_ULBWP2,NULL,0,.i64ptr=&scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[1]->bwp_Common->genericParameters.subcarrierSpacing,.defint64val=1,TYPE_INT64,0}, \ -{GNB_CONFIG_STRING_SCS_ULBWP3,NULL,0,.i64ptr=&scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[2]->bwp_Common->genericParameters.subcarrierSpacing,.defint64val=1,TYPE_INT64,0}, \ -{GNB_CONFIG_STRING_SCS_ULBWP4,NULL,0,.i64ptr=&scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[3]->bwp_Common->genericParameters.subcarrierSpacing,.defint64val=1,TYPE_INT64,0}, \ -{GNB_CONFIG_STRING_LOCATIONANDBANDWIDTH_ULBWP1,NULL,0,.i64ptr=&scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Common->genericParameters.locationAndBandwidth,.defint64val=0,TYPE_INT64,0}, \ -{GNB_CONFIG_STRING_LOCATIONANDBANDWIDTH_ULBWP2,NULL,0,.i64ptr=&scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[1]->bwp_Common->genericParameters.locationAndBandwidth,.defint64val=0,TYPE_INT64,0}, \ -{GNB_CONFIG_STRING_LOCATIONANDBANDWIDTH_ULBWP3,NULL,0,.i64ptr=&scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[2]->bwp_Common->genericParameters.locationAndBandwidth,.defint64val=0,TYPE_INT64,0}, \ -{GNB_CONFIG_STRING_LOCATIONANDBANDWIDTH_ULBWP4,NULL,0,.i64ptr=&scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[3]->bwp_Common->genericParameters.locationAndBandwidth,.defint64val=0,TYPE_INT64,0}, \ -{GNB_CONFIG_STRING_DEFAULTDLBWP_ID,NULL,0,.i64ptr=scd->defaultDownlinkBWP_Id,.defint64val=0,TYPE_INT64,0}} - /*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ /* Serving Cell Config Common configuration parameters to apply in RA 2-Step */ diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index f16ebae210..dda303c952 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -661,79 +661,6 @@ void fix_scc(NR_ServingCellConfigCommon_t *scc, uint64_t ssbmap) } } -/* Function to allocate dedicated serving cell config strutures */ -void prepare_scd(NR_ServingCellConfig_t *scd) { - // Allocate downlink structures - scd->downlinkBWP_ToAddModList = calloc_or_fail(1, sizeof(*scd->downlinkBWP_ToAddModList)); - scd->uplinkConfig = calloc_or_fail(1, sizeof(*scd->uplinkConfig)); - scd->uplinkConfig->uplinkBWP_ToAddModList = calloc_or_fail(1, sizeof(*scd->uplinkConfig->uplinkBWP_ToAddModList)); - scd->bwp_InactivityTimer = calloc_or_fail(1, sizeof(*scd->bwp_InactivityTimer)); - scd->uplinkConfig->firstActiveUplinkBWP_Id = calloc_or_fail(1, sizeof(*scd->uplinkConfig->firstActiveUplinkBWP_Id)); - scd->firstActiveDownlinkBWP_Id = calloc_or_fail(1, sizeof(*scd->firstActiveDownlinkBWP_Id)); - *scd->firstActiveDownlinkBWP_Id = 1; - *scd->uplinkConfig->firstActiveUplinkBWP_Id = 1; - scd->defaultDownlinkBWP_Id = calloc_or_fail(1, sizeof(*scd->defaultDownlinkBWP_Id)); - *scd->defaultDownlinkBWP_Id = 0; - - for (int j = 0; j < NR_MAX_NUM_BWP; j++) { - - // Downlink bandwidth part - NR_BWP_Downlink_t *bwp = calloc_or_fail(1, sizeof(*bwp)); - bwp->bwp_Id = j+1; - - // Allocate downlink dedicated bandwidth part and PDSCH structures - bwp->bwp_Common = calloc_or_fail(1, sizeof(*bwp->bwp_Common)); - bwp->bwp_Common->pdcch_ConfigCommon = calloc_or_fail(1, sizeof(*bwp->bwp_Common->pdcch_ConfigCommon)); - bwp->bwp_Common->pdsch_ConfigCommon = calloc_or_fail(1, sizeof(*bwp->bwp_Common->pdsch_ConfigCommon)); - bwp->bwp_Dedicated = calloc_or_fail(1, sizeof(*bwp->bwp_Dedicated)); - asn1cSeqAdd(&scd->downlinkBWP_ToAddModList->list,bwp); - - // UL bandwidth part - NR_BWP_Uplink_t *ubwp = calloc_or_fail(1, sizeof(*ubwp)); - ubwp->bwp_Id = j+1; - ubwp->bwp_Common = calloc_or_fail(1, sizeof(*ubwp->bwp_Common)); - ubwp->bwp_Dedicated = calloc_or_fail(1, sizeof(*ubwp->bwp_Dedicated)); - asn1cSeqAdd(&scd->uplinkConfig->uplinkBWP_ToAddModList->list,ubwp); - } -} - -/* This function checks dedicated serving cell configuration and performs fixes as needed */ -void fix_scd(NR_ServingCellConfig_t *scd) { - - // Remove unused BWPs - int b = 0; - while (bdownlinkBWP_ToAddModList->list.count) { - if (scd->downlinkBWP_ToAddModList->list.array[b]->bwp_Common->genericParameters.locationAndBandwidth == 0) { - ASN_STRUCT_FREE(asn_DEF_NR_BWP_Downlink, scd->downlinkBWP_ToAddModList->list.array[b]); - asn_sequence_del(&scd->downlinkBWP_ToAddModList->list,b,1); - } else { - b++; - } - } - - b = 0; - while (buplinkConfig->uplinkBWP_ToAddModList->list.count) { - if (scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[b]->bwp_Common->genericParameters.locationAndBandwidth == 0) { - ASN_STRUCT_FREE(asn_DEF_NR_BWP_Uplink, scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[b]); - asn_sequence_del(&scd->uplinkConfig->uplinkBWP_ToAddModList->list,b,1); - } else { - b++; - } - } - - if (scd->downlinkBWP_ToAddModList->list.count == 0) { - free(scd->downlinkBWP_ToAddModList->list.array); - free(scd->downlinkBWP_ToAddModList); - scd->downlinkBWP_ToAddModList = NULL; - } - - if (scd->uplinkConfig->uplinkBWP_ToAddModList->list.count == 0) { - free(scd->uplinkConfig->uplinkBWP_ToAddModList->list.array); - free(scd->uplinkConfig->uplinkBWP_ToAddModList); - scd->uplinkConfig->uplinkBWP_ToAddModList = NULL; - } -} - static void verify_gnb_param_notset(paramdef_t *params, int paramidx, const char *paramname) { char aprefix[MAX_OPTNAME_SIZE * 2 + 8]; @@ -1107,24 +1034,6 @@ static NR_ServingCellConfigCommon_t *get_scc_config(configmodule_interface_t *cf return scc; } -static NR_ServingCellConfig_t *get_scd_config(configmodule_interface_t *cfg) -{ - NR_ServingCellConfig_t *scd = calloc(1, sizeof(*scd)); - prepare_scd(scd); - - char aprefix[MAX_OPTNAME_SIZE * 2 + 8]; - snprintf(aprefix, sizeof(aprefix), "%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, 0); - GET_PARAMS_LIST(SCDsParamList, SCDsParams, SCDPARAMS_DESC(scd), GNB_CONFIG_STRING_SERVINGCELLCONFIGDEDICATED, aprefix); - - if (SCDsParamList.numelt > 0) { - snprintf(aprefix, sizeof(aprefix), "%s.[%i].%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, 0, GNB_CONFIG_STRING_SERVINGCELLCONFIGDEDICATED, 0); - GET_PARAMS(SCDsParams, SCDPARAMS_DESC(scd), aprefix); - } - fix_scd(scd); - - return scd; -} - static int read_du_cell_info(configmodule_interface_t *cfg, bool separate_du, uint32_t *gnb_id, @@ -1445,6 +1354,31 @@ void config_pdcp(configmodule_interface_t *cfg, nr_pdcp_configuration_t *pdcp_co pdcp_config->drb.discard_timer = config_get_processedint(cfg, &pdcp_params[CONFIG_NR_PDCP_DRB_DISCARD_TIMER_IDX]); } +static void get_bwp_config(nr_mac_config_t *configuration) +{ + char path[MAX_OPTNAME_SIZE * 2 + 8]; + snprintf(path, sizeof(path), "%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, 0); + GET_PARAMS_LIST(BWPParamList, BWPParams, GNBBWPPARAMS_DESC, GNB_CONFIG_STRING_BWP_LIST, path, BWPPARAMS_CHECK); + configuration->num_additional_bwps = BWPParamList.numelt; + AssertFatal(configuration->num_additional_bwps >= 0 && configuration->num_additional_bwps <= 4, + "Invalid number of additional BWPs %d\n", + configuration->num_additional_bwps); + for (int i = 0; i < configuration->num_additional_bwps; i++) { + configuration->bwp_config[i].id = i + 1; + int bwp_start = *BWPParamList.paramarray[i][GNB_BWP_START_IDX].iptr; + int bwp_size = *BWPParamList.paramarray[i][GNB_BWP_SIZE_IDX].iptr; + configuration->bwp_config[i].location_and_bw = PRBalloc_to_locationandbandwidth(bwp_size, bwp_start); + configuration->bwp_config[i].scs = *BWPParamList.paramarray[i][GNB_BWP_SCS_IDX].iptr; + LOG_I(GNB_APP, + "BWP %d, start PRB %d size %d locationandbandwidth %d, scs %d\n", + configuration->bwp_config[i].id, + bwp_start, + bwp_size, + configuration->bwp_config[i].location_and_bw, + configuration->bwp_config[i].scs); + } +} + void RCconfig_nr_macrlc(configmodule_interface_t *cfg) { int j = 0; @@ -1470,6 +1404,12 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg) config.pdsch_AntennaPorts.XP, config.pusch_AntennaPorts); + // BWP + get_bwp_config(&config); + AssertFatal(config.num_additional_bwps <= 4, "Impossible to configure more than 4 additional BWPs\n"); + config.first_active_bwp = *GNBParamList.paramarray[0][GNB_1ST_ACTIVE_BWP_IDX].iptr; + AssertFatal(config.first_active_bwp <= config.num_additional_bwps, "1st active BWP does not belog to the configured BWPs\n"); + // RU GET_PARAMS_LIST(RUParamList, RUParams, RUPARAMS_DESC, CONFIG_STRING_RU_LIST, NULL); int num_tx = 0; @@ -1478,8 +1418,7 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg) num_tx += *(RUParamList.paramarray[i][RU_NB_TX_IDX].uptr); AssertFatal(num_tx >= config.pdsch_AntennaPorts.XP * config.pdsch_AntennaPorts.N1 * config.pdsch_AntennaPorts.N2, "Number of logical antenna ports (set in config file with pdsch_AntennaPorts) cannot be larger than physical antennas (nb_tx)\n"); - } - else { + } else { // TODO temporary solution for 3rd party RU or nFAPI, in which case we don't have RU section present in the config file num_tx = config.pdsch_AntennaPorts.XP * config.pdsch_AntennaPorts.N1 * config.pdsch_AntennaPorts.N2; LOG_E(GNB_APP, "RU information not present in config file. Assuming physical antenna ports equal to logical antenna ports %d\n", num_tx); @@ -1569,7 +1508,6 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg) NR_ServingCellConfigCommon_t *scc = get_scc_config(cfg, config.minRXTXTIME, config.do_SRS); //xer_fprint(stdout, &asn_DEF_NR_ServingCellConfigCommon, scc); - NR_ServingCellConfig_t *scd = get_scd_config(cfg); if (MacRLC_ParamList.numelt > 0) { /* NR RLC config is needed by mac_top_init_gNB() */ @@ -1577,7 +1515,7 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg) config_rlc(cfg, &default_rlc_config); ngran_node_t node_type = get_node_type(); - mac_top_init_gNB(node_type, scc, scd, &config, &default_rlc_config); + mac_top_init_gNB(node_type, scc, &config, &default_rlc_config); RC.nb_nr_mac_CC = (int *)malloc(RC.nb_nr_macrlc_inst * sizeof(int)); for (j = 0; j < RC.nb_nr_macrlc_inst; j++) { diff --git a/openair2/GNB_APP/gnb_paramdef.h b/openair2/GNB_APP/gnb_paramdef.h index 95b4451148..08ba09e980 100644 --- a/openair2/GNB_APP/gnb_paramdef.h +++ b/openair2/GNB_APP/gnb_paramdef.h @@ -138,6 +138,7 @@ typedef enum { #define GNB_CONFIG_STRING_CU_SIB_LIST "cu_sibs" #define GNB_CONFIG_STRING_DU_SIB_LIST "du_sibs" #define GNB_CONFIG_STRING_DOSINR "do_SINR" +#define GNB_CONFIG_STRING_1ST_ACTIVE_BWP "first_active_bwp" #define GNB_CONFIG_HLP_STRING_ENABLE_SDAP "enable the SDAP layer\n" #define GNB_CONFIG_HLP_FORCE256QAMOFF "suppress activation of 256 QAM despite UE support" @@ -153,6 +154,7 @@ typedef enum { #define GNB_CONFIG_HLP_DU_SIBS "List of DU generated SIBs to be transmitted" #define GNB_CONFIG_HLP_DOSINR "Enable CSI feedback using SINR measurements on SSB" + /*-----------------------------------------------------------------------------------------------------------------------------------------*/ /* cell configuration parameters */ /* optname helpstr paramflags XXXptr defXXXval type numelt */ @@ -199,6 +201,7 @@ typedef enum { {GNB_CONFIG_STRING_CU_SIB_LIST, GNB_CONFIG_HLP_CU_SIBS, 0, .iptr=NULL, .defintarrayval=0, TYPE_INTARRAY, 0}, \ {GNB_CONFIG_STRING_DU_SIB_LIST, GNB_CONFIG_HLP_DU_SIBS, 0, .iptr=NULL, .defintarrayval=0, TYPE_INTARRAY, 0}, \ {GNB_CONFIG_STRING_DOSINR, GNB_CONFIG_HLP_DOSINR, 0, .iptr=NULL, .defintval=0, TYPE_INT, 0}, \ +{GNB_CONFIG_STRING_1ST_ACTIVE_BWP, NULL, 0, .iptr=NULL, .defintval=0, TYPE_INT, 0}, \ } // clang-format on @@ -242,6 +245,7 @@ typedef enum { #define GNB_CU_SIBS_IDX 36 #define GNB_DU_SIBS_IDX 37 #define GNB_DO_SINR_IDX 38 +#define GNB_1ST_ACTIVE_BWP_IDX 39 #define TRACKING_AREA_CODE_OKRANGE {0x0001,0xFFFD} #define NUM_DL_HARQ_OKVALUES {2,4,6,8,10,12,16,32} @@ -287,9 +291,33 @@ typedef enum { { .s5 = { NULL } }, \ { .s5 = { NULL } }, \ { .s5 = { NULL } }, \ + { .s5 = { NULL } }, \ } /*-------------------------------------------------------------------------------------------------------------------------------------------------*/ + +#define GNB_CONFIG_STRING_BWP_LIST "bwp_list" + +#define GNB_CONFIG_STRING_BWP_SCS "scs" +#define GNB_CONFIG_STRING_BWP_START "bwpStart" +#define GNB_CONFIG_STRING_BWP_SIZE "bwpSize" + +#define GNB_BWP_SCS_IDX 0 +#define GNB_BWP_START_IDX 1 +#define GNB_BWP_SIZE_IDX 2 + +#define GNBBWPPARAMS_DESC { \ + {GNB_CONFIG_STRING_BWP_SCS, NULL, 0, .iptr=NULL, .defintarrayval=0, TYPE_INT, 0}, \ + {GNB_CONFIG_STRING_BWP_START, NULL, 0, .iptr=NULL, .defintarrayval=0, TYPE_INT, 0}, \ + {GNB_CONFIG_STRING_BWP_SIZE, NULL, 0, .iptr=NULL, .defintarrayval=0, TYPE_INT, 0}, \ +} + +#define BWPPARAMS_CHECK { \ + { .s5 = { NULL } }, \ + { .s5 = { NULL } }, \ + { .s5 = { NULL } }, \ +} + /*-------------------------------------------------------------------------------------------------------------------------------------------------*/ /* Neighbour Cell Configurations*/ diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 3d2d1254bf..2d045a59a8 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -3744,8 +3744,7 @@ bool prepare_initial_ul_rrc_message(gNB_MAC_INST *mac, NR_UE_info_t *UE) int CC_id = 0; int srb_id = 1; const NR_ServingCellConfigCommon_t *scc = mac->common_channels[CC_id].ServingCellConfigCommon; - const NR_ServingCellConfig_t *sccd = UE->is_redcap ? NULL : mac->common_channels[CC_id].pre_ServingCellConfig; - NR_CellGroupConfig_t *cellGroupConfig = get_initial_cellGroupConfig(UE->uid, scc, sccd, &mac->radio_config, &mac->rlc_config); + NR_CellGroupConfig_t *cellGroupConfig = get_initial_cellGroupConfig(UE->uid, scc, &mac->radio_config, &mac->rlc_config); ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->CellGroup); UE->CellGroup = cellGroupConfig; diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 84a0923e8b..cdedb244e9 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -52,7 +52,6 @@ void delete_nr_ue_data(NR_UE_info_t *UE, NR_COMMON_channels_t *ccPtr, uid_alloca void mac_top_init_gNB(ngran_node_t node_type, NR_ServingCellConfigCommon_t *scc, - NR_ServingCellConfig_t *scd, const nr_mac_config_t *conf, const nr_rlc_configuration_t *default_rlc_config); void mac_top_destroy_gNB(gNB_MAC_INST *mac); diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c index d9b0136069..88083cdbb3 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -569,14 +569,13 @@ static NR_UE_info_t *create_new_UE(gNB_MAC_INST *mac, uint32_t cu_id, const NR_C NR_CellGroupConfig_t *cellGroupConfig = NULL; NR_COMMON_channels_t *cc = &mac->common_channels[CC_id]; const NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; - const NR_ServingCellConfig_t *sccd = cc->pre_ServingCellConfig; const nr_mac_config_t *configuration = &mac->radio_config; if (is_SA) { - cellGroupConfig = get_initial_cellGroupConfig(UE->uid, scc, sccd, &mac->radio_config, &mac->rlc_config); + cellGroupConfig = get_initial_cellGroupConfig(UE->uid, scc, &mac->radio_config, &mac->rlc_config); cellGroupConfig->spCellConfig->reconfigurationWithSync = get_reconfiguration_with_sync(UE->rnti, UE->uid, scc); } else { NR_UE_NR_Capability_t *cap = get_ue_nr_cap_from_cg_config_info(cgci); - cellGroupConfig = get_default_secondaryCellGroup(scc, sccd, cap, 1, 1, configuration, UE->uid); + cellGroupConfig = get_default_secondaryCellGroup(scc, cap, 1, 1, configuration, UE->uid); cellGroupConfig->spCellConfig->reconfigurationWithSync = get_reconfiguration_with_sync(UE->rnti, UE->uid, scc); // TODO: in NSA we assign capabilities here, otherwise outside => not logic UE->capability = cap; diff --git a/openair2/LAYER2/NR_MAC_gNB/main.c b/openair2/LAYER2/NR_MAC_gNB/main.c index e80f852022..b04311eba6 100644 --- a/openair2/LAYER2/NR_MAC_gNB/main.c +++ b/openair2/LAYER2/NR_MAC_gNB/main.c @@ -240,7 +240,6 @@ static void mac_rrc_init(gNB_MAC_INST *mac, ngran_node_t node_type) void mac_top_init_gNB(ngran_node_t node_type, NR_ServingCellConfigCommon_t *scc, - NR_ServingCellConfig_t *scd, const nr_mac_config_t *config, const nr_rlc_configuration_t *default_rlc_config) { @@ -275,8 +274,6 @@ void mac_top_init_gNB(ngran_node_t node_type, RC.nrmac[i]->radio_config = *config; RC.nrmac[i]->rlc_config = *default_rlc_config; - RC.nrmac[i]->common_channels[0].pre_ServingCellConfig = scd; - RC.nrmac[i]->first_MIB = true; RC.nrmac[i]->num_scheduled_prach_rx = 0; RC.nrmac[i]->common_channels[0].mib = get_new_MIB_NR(scc); @@ -330,7 +327,6 @@ void mac_top_destroy_gNB(gNB_MAC_INST *mac) NR_COMMON_channels_t *cc = &mac->common_channels[0]; ASN_STRUCT_FREE(asn_DEF_NR_BCCH_BCH_Message, cc->mib); ASN_STRUCT_FREE(asn_DEF_NR_BCCH_DL_SCH_Message, cc->sib1); - ASN_STRUCT_FREE(asn_DEF_NR_ServingCellConfig, cc->pre_ServingCellConfig); ASN_STRUCT_FREE(asn_DEF_NR_ServingCellConfigCommon, cc->ServingCellConfigCommon); NR_UEs_t *UE_info = &mac->UE_info; for (int i = 0; i < sizeofArray(UE_info->connected_ue_list); ++i) diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 9964b2be36..338d4d8190 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -173,6 +173,12 @@ int ul_MaxPorts_0; int ul_Power_0; } nr_ptrs_config_t; +typedef struct { + int id; + int scs; + int location_and_bw; +} nr_bwp_config_t; + typedef struct nr_mac_config_t { int sib1_tda; nr_pdsch_AntennaPorts_t pdsch_AntennaPorts; @@ -190,6 +196,10 @@ typedef struct nr_mac_config_t { nr_mac_timers_t timer_config; int num_dlharq; int num_ulharq; + // BWP information + int num_additional_bwps; + int first_active_bwp; + nr_bwp_config_t bwp_config[4]; /// beamforming weight matrix size int nb_bfw[2]; int32_t *bw_list; @@ -282,8 +292,6 @@ typedef struct { NR_BCCH_DL_SCH_Message_t *sib1; seq_arr_t *du_SIBs; NR_ServingCellConfigCommon_t *ServingCellConfigCommon; - /// pre-configured ServingCellConfig that is default for every UE - NR_ServingCellConfig_t *pre_ServingCellConfig; /// Outgoing MIB PDU for PHY uint8_t MIB_pdu[3]; /// Outgoing BCCH pdu for PHY diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c index 041e948d55..8798a364d1 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c @@ -210,20 +210,6 @@ static NR_SetupRelease_PDSCH_ConfigCommon_t *clone_pdsch_configcommon(const NR_S return clone; } -static NR_PUSCH_Config_t *clone_pusch_config(const NR_PUSCH_Config_t *pc) -{ - if (pc == NULL) - return NULL; - - uint8_t buf[1024]; - asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_PUSCH_Config, NULL, pc, buf, sizeof(buf)); - AssertFatal(enc_rval.encoded > 0 && enc_rval.encoded < sizeof(buf), "could not clone NR_PUSCH_Config: problem while encoding\n"); - NR_PUSCH_Config_t *clone = NULL; - asn_dec_rval_t dec_rval = uper_decode(NULL, &asn_DEF_NR_PUSCH_Config, (void **)&clone, buf, enc_rval.encoded, 0, 0); - AssertFatal(dec_rval.code == RC_OK && dec_rval.consumed == enc_rval.encoded, "could not clone NR_PUSCH_Config: problem while decoding\n"); - return clone; -} - static int get_nb_pucch2_per_slot(const NR_ServingCellConfigCommon_t *scc, int bwp_size) { const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; @@ -1492,16 +1478,14 @@ static NR_PTRS_UplinkConfig_t *config_ulptrs(const nr_ptrs_config_t *ptrs) return ulptrs; } -static NR_SetupRelease_PUSCH_Config_t *config_pusch(NR_PUSCH_Config_t *pusch_Config, - const bool use_deltaMCS, +static NR_SetupRelease_PUSCH_Config_t *config_pusch(const bool use_deltaMCS, const NR_ServingCellConfigCommon_t *scc, const NR_UE_NR_Capability_t *uecap, const nr_ptrs_config_t *ptrs) { NR_SetupRelease_PUSCH_Config_t *setup_puschconfig = calloc(1, sizeof(*setup_puschconfig)); setup_puschconfig->present = NR_SetupRelease_PUSCH_Config_PR_setup; - if (!pusch_Config) - pusch_Config = calloc(1, sizeof(*pusch_Config)); + NR_PUSCH_Config_t *pusch_Config = calloc(1, sizeof(*pusch_Config)); setup_puschconfig->choice.setup = pusch_Config; pusch_Config->dataScramblingIdentityPUSCH = NULL; @@ -1683,23 +1667,20 @@ static NR_SetupRelease_PDSCH_Config_t *config_pdsch(uint64_t ssb_bitmap, int bwp static void config_downlinkBWP(NR_BWP_Downlink_t *bwp, const NR_ServingCellConfigCommon_t *scc, - const NR_ServingCellConfig_t *servingcellconfigdedicated, const NR_UE_NR_Capability_t *uecap, int dl_antenna_ports, bool force_256qam_off, int bwp_loop, bool is_SA, - nr_ptrs_config_t *ptrs, - const int num_agg_level_candidates[NUM_PDCCH_AGG_LEVELS]) + const nr_mac_config_t *configuration) { bwp->bwp_Common = calloc(1,sizeof(*bwp->bwp_Common)); - - if(servingcellconfigdedicated->downlinkBWP_ToAddModList && - bwp_loop < servingcellconfigdedicated->downlinkBWP_ToAddModList->list.count) { - bwp->bwp_Id = servingcellconfigdedicated->downlinkBWP_ToAddModList->list.array[bwp_loop]->bwp_Id; - bwp->bwp_Common->genericParameters.locationAndBandwidth = servingcellconfigdedicated->downlinkBWP_ToAddModList->list.array[bwp_loop]->bwp_Common->genericParameters.locationAndBandwidth; - bwp->bwp_Common->genericParameters.subcarrierSpacing = servingcellconfigdedicated->downlinkBWP_ToAddModList->list.array[bwp_loop]->bwp_Common->genericParameters.subcarrierSpacing; - bwp->bwp_Common->genericParameters.cyclicPrefix = servingcellconfigdedicated->downlinkBWP_ToAddModList->list.array[bwp_loop]->bwp_Common->genericParameters.cyclicPrefix; + if(configuration->num_additional_bwps > 0) { + const nr_bwp_config_t *bwp_config = &configuration->bwp_config[bwp_loop]; + bwp->bwp_Id = bwp_config->id; + bwp->bwp_Common->genericParameters.locationAndBandwidth = bwp_config->location_and_bw; + bwp->bwp_Common->genericParameters.subcarrierSpacing = bwp_config->scs; + bwp->bwp_Common->genericParameters.cyclicPrefix = NULL; } else { bwp->bwp_Id=bwp_loop+1; bwp->bwp_Common->genericParameters.locationAndBandwidth = PRBalloc_to_locationandbandwidth(scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth,0); @@ -1727,7 +1708,7 @@ static void config_downlinkBWP(NR_BWP_Downlink_t *bwp, NR_SearchSpace_t *ss = NULL; if (!is_SA) { int num_cces = get_coreset_num_cces(coreset->frequencyDomainResources.buf, coreset->duration); - verify_agg_levels(num_cces, num_agg_level_candidates, coreset->controlResourceSetId, agg_level_candidates); + verify_agg_levels(num_cces, configuration->num_agg_level_candidates, coreset->controlResourceSetId, agg_level_candidates); ss = rrc_searchspace_config(true, searchspaceid, coreset->controlResourceSetId, agg_level_candidates); } else { agg_level_candidates[PDCCH_AGG_LEVEL1] = NR_SearchSpace__nrofCandidates__aggregationLevel1_n0; @@ -1773,7 +1754,7 @@ static void config_downlinkBWP(NR_BWP_Downlink_t *bwp, asn1cSeqAdd(&bwp->bwp_Dedicated->pdcch_Config->choice.setup->controlResourceSetToAddModList->list, coreset2); int rrc_num_agg_level_candidates[NUM_PDCCH_AGG_LEVELS]; int num_cces = get_coreset_num_cces(coreset2->frequencyDomainResources.buf, coreset2->duration); - verify_agg_levels(num_cces, num_agg_level_candidates, coreset2->controlResourceSetId, rrc_num_agg_level_candidates); + verify_agg_levels(num_cces, configuration->num_agg_level_candidates, coreset2->controlResourceSetId, rrc_num_agg_level_candidates); searchspaceid = 10 + bwp->bwp_Id; NR_SearchSpace_t *ss2 = rrc_searchspace_config(true, searchspaceid, is_SA ? 0 : coreset2->controlResourceSetId, agg_level_candidates); @@ -1785,7 +1766,7 @@ static void config_downlinkBWP(NR_BWP_Downlink_t *bwp, asn1cSeqAdd(&bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list, ss3); bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToReleaseList = NULL; - bwp->bwp_Dedicated->pdsch_Config = config_pdsch(ssb_bitmap, bwp->bwp_Id, dl_antenna_ports, ptrs); + bwp->bwp_Dedicated->pdsch_Config = config_pdsch(ssb_bitmap, bwp->bwp_Id, dl_antenna_ports, configuration->ptrs); set_dl_mcs_table(bwp->bwp_Common->genericParameters.subcarrierSpacing, force_256qam_off ? NULL : uecap, @@ -1797,18 +1778,17 @@ static void config_uplinkBWP(NR_BWP_Uplink_t *ubwp, long bwp_loop, bool is_SA, int uid, + int maxMIMO_Layers, const nr_mac_config_t *configuration, - const NR_ServingCellConfig_t *servingcellconfigdedicated, const NR_ServingCellConfigCommon_t *scc, const NR_UE_NR_Capability_t *uecap) { - ubwp->bwp_Common = calloc(1,sizeof(*ubwp->bwp_Common)); - if(servingcellconfigdedicated->uplinkConfig->uplinkBWP_ToAddModList && - bwp_loop < servingcellconfigdedicated->uplinkConfig->uplinkBWP_ToAddModList->list.count) { - ubwp->bwp_Id = servingcellconfigdedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[bwp_loop]->bwp_Id; - ubwp->bwp_Common->genericParameters.locationAndBandwidth = servingcellconfigdedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[bwp_loop]->bwp_Common->genericParameters.locationAndBandwidth; - ubwp->bwp_Common->genericParameters.subcarrierSpacing = servingcellconfigdedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[bwp_loop]->bwp_Common->genericParameters.subcarrierSpacing; - ubwp->bwp_Common->genericParameters.cyclicPrefix = servingcellconfigdedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[bwp_loop]->bwp_Common->genericParameters.cyclicPrefix; + ubwp->bwp_Common = calloc(1, sizeof(*ubwp->bwp_Common)); + if(configuration->num_additional_bwps > 0) { + ubwp->bwp_Id = configuration->bwp_config[bwp_loop].id; + ubwp->bwp_Common->genericParameters.locationAndBandwidth = configuration->bwp_config[bwp_loop].location_and_bw; + ubwp->bwp_Common->genericParameters.subcarrierSpacing = configuration->bwp_config[bwp_loop].scs; + ubwp->bwp_Common->genericParameters.cyclicPrefix = NULL; } else { ubwp->bwp_Id=bwp_loop+1; ubwp->bwp_Common->genericParameters.locationAndBandwidth = PRBalloc_to_locationandbandwidth(scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth,0); @@ -1847,25 +1827,11 @@ static void config_uplinkBWP(NR_BWP_Uplink_t *ubwp, scheduling_request_config(scc, pucch_Config, ubwp->bwp_Common->genericParameters.subcarrierSpacing); set_dl_DataToUL_ACK(pucch_Config, configuration->minRXTXTIME, ubwp->bwp_Common->genericParameters.subcarrierSpacing); - NR_PUSCH_Config_t *pusch_Config = NULL; - if(servingcellconfigdedicated->uplinkConfig->uplinkBWP_ToAddModList && - bwp_loop < servingcellconfigdedicated->uplinkConfig->uplinkBWP_ToAddModList->list.count) { - pusch_Config = clone_pusch_config(servingcellconfigdedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[bwp_loop] - ->bwp_Dedicated->pusch_Config->choice.setup); - } - ubwp->bwp_Dedicated->pusch_Config = config_pusch(pusch_Config, - configuration->use_deltaMCS, + ubwp->bwp_Dedicated->pusch_Config = config_pusch(configuration->use_deltaMCS, scc, configuration->force_UL256qam_off ? NULL : uecap, configuration->ptrs); - long maxMIMO_Layers = servingcellconfigdedicated && - servingcellconfigdedicated->uplinkConfig - && servingcellconfigdedicated->uplinkConfig->pusch_ServingCellConfig - && servingcellconfigdedicated->uplinkConfig->pusch_ServingCellConfig->choice.setup->ext1 - && servingcellconfigdedicated->uplinkConfig->pusch_ServingCellConfig->choice.setup->ext1->maxMIMO_Layers ? - *servingcellconfigdedicated->uplinkConfig->pusch_ServingCellConfig->choice.setup->ext1->maxMIMO_Layers : 1; - ubwp->bwp_Dedicated->srs_Config = get_config_srs(scc, NULL, curr_bwp, @@ -3241,7 +3207,6 @@ static void fill_harq_IEs(NR_ServingCellConfig_t *scc, int num_dlharq, int num_u static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid, const NR_ServingCellConfigCommon_t *scc, - const NR_ServingCellConfig_t *servingcellconfigdedicated, const nr_mac_config_t *configuration) { const int pdsch_AntennaPorts = @@ -3272,7 +3237,7 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid, config_pucch_resset1(pucch_Config, uid, num_pucch2, NULL); set_pucch_power_config(pucch_Config, configuration->do_CSIRS); - initialUplinkBWP->pusch_Config = config_pusch(NULL, configuration->use_deltaMCS, scc, NULL, configuration->ptrs); + initialUplinkBWP->pusch_Config = config_pusch(configuration->use_deltaMCS, scc, NULL, configuration->ptrs); long maxMIMO_Layers = uplinkConfig && uplinkConfig->pusch_ServingCellConfig && uplinkConfig->pusch_ServingCellConfig->choice.setup->ext1 @@ -3353,12 +3318,7 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid, } // Downlink BWPs - int n_dl_bwp = 0; - if (servingcellconfigdedicated && servingcellconfigdedicated->downlinkBWP_ToAddModList - && servingcellconfigdedicated->downlinkBWP_ToAddModList->list.count > 0) { - n_dl_bwp = servingcellconfigdedicated->downlinkBWP_ToAddModList->list.count; - } - int default_dl_bwp = 0; + int n_dl_bwp = configuration->num_additional_bwps; int first_active_dl_bwp = 0; if (n_dl_bwp > 0) { configDedicated->downlinkBWP_ToAddModList = calloc(1, sizeof(*configDedicated->downlinkBWP_ToAddModList)); @@ -3366,41 +3326,29 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid, NR_BWP_Downlink_t *bwp = calloc(1, sizeof(*bwp)); config_downlinkBWP(bwp, scc, - servingcellconfigdedicated, NULL, 0, false, bwp_loop, true, - configuration->ptrs, - configuration->num_agg_level_candidates); + configuration); asn1cSeqAdd(&configDedicated->downlinkBWP_ToAddModList->list, bwp); } - const NR_BWP_Id_t *firstActiveDownlinkBWP_Id = servingcellconfigdedicated->firstActiveDownlinkBWP_Id; - first_active_dl_bwp = firstActiveDownlinkBWP_Id ? *firstActiveDownlinkBWP_Id : 1; - const NR_BWP_Id_t *defaultDownlinkBWP_Id = servingcellconfigdedicated->defaultDownlinkBWP_Id; - default_dl_bwp = defaultDownlinkBWP_Id ? *defaultDownlinkBWP_Id : 1; + first_active_dl_bwp = configuration->first_active_bwp; } asn1cCallocOne(configDedicated->firstActiveDownlinkBWP_Id, first_active_dl_bwp); - asn1cCallocOne(configDedicated->defaultDownlinkBWP_Id, default_dl_bwp); // Uplink BWPs - int n_ul_bwp = 0; - if (servingcellconfigdedicated && servingcellconfigdedicated->uplinkConfig - && servingcellconfigdedicated->uplinkConfig->uplinkBWP_ToAddModList - && servingcellconfigdedicated->uplinkConfig->uplinkBWP_ToAddModList->list.count > 0) { - n_ul_bwp = servingcellconfigdedicated->uplinkConfig->uplinkBWP_ToAddModList->list.count; - } + int n_ul_bwp = configuration->num_additional_bwps; int first_active_ul_bwp = 0; if (n_ul_bwp > 0) { uplinkConfig->uplinkBWP_ToAddModList = calloc(1, sizeof(*uplinkConfig->uplinkBWP_ToAddModList)); for (int bwp_loop = 0; bwp_loop < n_ul_bwp; bwp_loop++) { NR_BWP_Uplink_t *ubwp = calloc(1, sizeof(*ubwp)); - config_uplinkBWP(ubwp, bwp_loop, true, uid, configuration, servingcellconfigdedicated, scc, NULL); + config_uplinkBWP(ubwp, bwp_loop, true, uid, maxMIMO_Layers, configuration, scc, NULL); asn1cSeqAdd(&uplinkConfig->uplinkBWP_ToAddModList->list, ubwp); } - const NR_BWP_Id_t *firstActiveUplinkBWP_Id = servingcellconfigdedicated->uplinkConfig->firstActiveUplinkBWP_Id; - first_active_ul_bwp = firstActiveUplinkBWP_Id ? *firstActiveUplinkBWP_Id : 1; + first_active_ul_bwp = configuration->first_active_bwp; } asn1cCallocOne(uplinkConfig->firstActiveUplinkBWP_Id, first_active_ul_bwp); @@ -3647,7 +3595,7 @@ NR_RLC_BearerConfig_t *get_DRB_RLC_BearerConfig(long lcChannelId, return rlc_BearerConfig; } -static bool verify_radio_configuration(int uid, const NR_ServingCellConfigCommon_t *scc, const NR_ServingCellConfig_t *scd) +static bool verify_radio_configuration(int uid, const NR_ServingCellConfigCommon_t *scc, const nr_mac_config_t *configuration) { frame_structure_t *fs = &RC.nrmac[0]->frame_structure; int srs_offset = get_ul_slot_offset(fs, uid, false); @@ -3657,8 +3605,7 @@ static bool verify_radio_configuration(int uid, const NR_ServingCellConfigCommon return false; } - /* for RedCap, scd is NULL */ - int n_dl_bwp = scd && scd->downlinkBWP_ToAddModList ? scd->downlinkBWP_ToAddModList->list.count : 1; + int n_dl_bwp = 1 + configuration->num_additional_bwps; // initial + additional bwps int csi_offset = fs->numb_slots_period * n_dl_bwp; // see set_csirs_periodicity if (csi_offset / 320 >= get_full_dl_slots_per_period(fs)) { @@ -3692,14 +3639,13 @@ static bool verify_radio_configuration(int uid, const NR_ServingCellConfigCommon NR_CellGroupConfig_t *get_initial_cellGroupConfig(int uid, const NR_ServingCellConfigCommon_t *scc, - const NR_ServingCellConfig_t *servingcellconfigdedicated, const nr_mac_config_t *configuration, const nr_rlc_configuration_t *default_rlc_config) { - if (!verify_radio_configuration(uid, scc, servingcellconfigdedicated)) + if (!verify_radio_configuration(uid, scc, configuration)) return NULL; - NR_SpCellConfig_t *spCellConfig = get_initial_SpCellConfig(uid, scc, servingcellconfigdedicated, configuration); + NR_SpCellConfig_t *spCellConfig = get_initial_SpCellConfig(uid, scc, configuration); NR_CellGroupConfig_t *cellGroupConfig = calloc(1, sizeof(*cellGroupConfig)); cellGroupConfig->cellGroupId = 0; @@ -3793,7 +3739,6 @@ void update_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig, calloc(1, sizeof(*uplinkConfig->pusch_ServingCellConfig->choice.setup->ext1)); asn1cCallocOne(uplinkConfig->pusch_ServingCellConfig->choice.setup->ext1->maxMIMO_Layers, maxMIMO_Layers); - // UL and SRS configuration if (configuration->do_SRS && uplinkConfig && uplinkConfig->initialUplinkBWP) { ASN_STRUCT_FREE(asn_DEF_NR_SetupRelease_SRS_Config, uplinkConfig->initialUplinkBWP->srs_Config); @@ -3892,7 +3837,6 @@ static NR_ServingCellConfigCommon_t *clone_ServingCellConfigCommon(const NR_Serv } NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigCommon_t *servingcellconfigcommon, - const NR_ServingCellConfig_t *servingcellconfigdedicated, const NR_UE_NR_Capability_t *uecap, int scg_id, int servCellIndex, @@ -3904,7 +3848,6 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC const int do_csirs = configuration->do_CSIRS; AssertFatal(servingcellconfigcommon, "servingcellconfigcommon is null\n"); - AssertFatal(servingcellconfigdedicated, "servingcellconfigdedicated is null\n"); if (uecap == NULL) LOG_E(RRC, "No UE Capabilities available when programming default CellGroup in NSA\n"); @@ -3959,13 +3902,7 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC ulConfig->initialUplinkBWP = initialUplinkBWP; initialUplinkBWP->pucch_Config = NULL; - NR_PUSCH_Config_t *pusch_Config = NULL; - if (servingcellconfigdedicated->uplinkConfig->uplinkBWP_ToAddModList) { - pusch_Config = clone_pusch_config( - servingcellconfigdedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup); - } - initialUplinkBWP->pusch_Config = config_pusch(pusch_Config, - configuration->use_deltaMCS, + initialUplinkBWP->pusch_Config = config_pusch(configuration->use_deltaMCS, servingcellconfigcommon, uecap, configuration->ptrs); @@ -3984,50 +3921,45 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC // Downlink BWPs int n_dl_bwp = 1; - if (servingcellconfigdedicated->downlinkBWP_ToAddModList) { - n_dl_bwp = servingcellconfigdedicated->downlinkBWP_ToAddModList->list.count; + int firstActiveDownlinkBWP_Id = 1; + if (configuration->num_additional_bwps > 0) { + n_dl_bwp = configuration->num_additional_bwps; + firstActiveDownlinkBWP_Id = configuration->first_active_bwp; } - if (n_dl_bwp > 0) { - configDedicated->downlinkBWP_ToAddModList = calloc(1, sizeof(*configDedicated->downlinkBWP_ToAddModList)); - for (int bwp_loop = 0; bwp_loop < n_dl_bwp; bwp_loop++) { - NR_BWP_Downlink_t *bwp = calloc(1, sizeof(*bwp)); - config_downlinkBWP(bwp, - servingcellconfigcommon, - servingcellconfigdedicated, - uecap, - dl_antenna_ports, - configuration->force_256qam_off, - bwp_loop, - false, - configuration->ptrs, - configuration->num_agg_level_candidates); - asn1cSeqAdd(&configDedicated->downlinkBWP_ToAddModList->list, bwp); - } + configDedicated->downlinkBWP_ToAddModList = calloc(1, sizeof(*configDedicated->downlinkBWP_ToAddModList)); + for (int bwp_loop = 0; bwp_loop < n_dl_bwp; bwp_loop++) { + NR_BWP_Downlink_t *bwp = calloc(1, sizeof(*bwp)); + config_downlinkBWP(bwp, + servingcellconfigcommon, + uecap, + dl_antenna_ports, + configuration->force_256qam_off, + bwp_loop, + false, + configuration); + asn1cSeqAdd(&configDedicated->downlinkBWP_ToAddModList->list, bwp); configDedicated->firstActiveDownlinkBWP_Id = calloc(1, sizeof(*configDedicated->firstActiveDownlinkBWP_Id)); - *configDedicated->firstActiveDownlinkBWP_Id = - servingcellconfigdedicated->firstActiveDownlinkBWP_Id ? *servingcellconfigdedicated->firstActiveDownlinkBWP_Id : 1; + *configDedicated->firstActiveDownlinkBWP_Id = firstActiveDownlinkBWP_Id; configDedicated->defaultDownlinkBWP_Id = calloc(1, sizeof(*configDedicated->defaultDownlinkBWP_Id)); - *configDedicated->defaultDownlinkBWP_Id = - servingcellconfigdedicated->defaultDownlinkBWP_Id ? *servingcellconfigdedicated->defaultDownlinkBWP_Id : 1; + *configDedicated->defaultDownlinkBWP_Id = 1; } // Uplink BWPs int n_ul_bwp = 1; - if (servingcellconfigdedicated->uplinkConfig && servingcellconfigdedicated->uplinkConfig->uplinkBWP_ToAddModList) { - n_ul_bwp = servingcellconfigdedicated->uplinkConfig->uplinkBWP_ToAddModList->list.count; + int firstActiveUplinkBWP_Id = 1; + if (configuration->num_additional_bwps > 0) { + n_ul_bwp = configuration->num_additional_bwps; + firstActiveUplinkBWP_Id = configuration->first_active_bwp; } if (n_ul_bwp > 0) { ulConfig->uplinkBWP_ToAddModList = calloc(1, sizeof(*ulConfig->uplinkBWP_ToAddModList)); for (int bwp_loop = 0; bwp_loop < n_ul_bwp; bwp_loop++) { NR_BWP_Uplink_t *ubwp = calloc(1, sizeof(*ubwp)); - config_uplinkBWP(ubwp, bwp_loop, false, uid, configuration, servingcellconfigdedicated, servingcellconfigcommon, uecap); + config_uplinkBWP(ubwp, bwp_loop, false, uid, maxMIMO_Layers, configuration, servingcellconfigcommon, uecap); asn1cSeqAdd(&ulConfig->uplinkBWP_ToAddModList->list, ubwp); } ulConfig->firstActiveUplinkBWP_Id = calloc(1, sizeof(*ulConfig->firstActiveUplinkBWP_Id)); - *ulConfig->firstActiveUplinkBWP_Id = - servingcellconfigdedicated->uplinkConfig->firstActiveUplinkBWP_Id - ? *servingcellconfigdedicated->uplinkConfig->firstActiveUplinkBWP_Id - : 1; + *ulConfig->firstActiveUplinkBWP_Id = firstActiveUplinkBWP_Id; } configDedicated->bwp_InactivityTimer = NULL; diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h index 28993e13cf..865d1b040e 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h @@ -89,7 +89,6 @@ NR_SIB19_r17_t *get_SIB19_NR(const NR_ServingCellConfigCommon_t *scc); NR_CellGroupConfig_t *get_initial_cellGroupConfig(int uid, const NR_ServingCellConfigCommon_t *scc, - const NR_ServingCellConfig_t *servingcellconfigdedicated, const nr_mac_config_t *configuration, const nr_rlc_configuration_t *default_rlc_config); void update_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig, @@ -105,7 +104,6 @@ NR_CellGroupConfig_t *decode_cellGroupConfig(const uint8_t *buffer, int max_buff * configuration, but it will also overwrite the ServingCellConfig passed in * parameter servingcellconfigdedicated! */ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigCommon_t *servingcellconfigcommon, - const NR_ServingCellConfig_t *servingcellconfigdedicated, const NR_UE_NR_Capability_t *uecap, int scg_id, int servCellIndex, diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.redcap.yaml b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.redcap.yaml index 605b56be93..725b85a31e 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.redcap.yaml +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.redcap.yaml @@ -19,6 +19,12 @@ gNBs: # Physical parameters: do_CSIRS: 1 do_SRS: 1 + first_active_bwp: 1; + bwp_list: + - + scs: 1 + bwpStart: 0 + bwpSize: 106 #uess_agg_levels: [0,1,1,1,1] servingCellConfigCommon: #spCellConfigCommon @@ -132,17 +138,6 @@ gNBs: ssPBCH_BlockPower: -25 - servingCellConfigDedicated: - - dl_bwp-Id_1: 1 - dl_bwp1_locationAndBandwidth: 28875 - dl_bwp1_subcarrierSpacing: 1 - firstActiveDownlinkBWP-Id: 1 - defaultDownlinkBWP-Id: 1 - ul_bwp-Id_1: 1 - ul_bwp1_locationAndBandwidth: 28875 - ul_bwp1_subcarrierSpacing: 1 - firstActiveUplinkBWP-Id: 1 - RedCap: cellBarredRedCap1Rx_r17: 1 cellBarredRedCap2Rx_r17: 1 From db93bc022f07b532a899a2872fd108e3ab8ca485 Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 22 Aug 2025 09:37:38 +0200 Subject: [PATCH 606/964] separate functions to configure initial BWPs --- openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c | 105 ++++++++++--------- 1 file changed, 56 insertions(+), 49 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c index 8798a364d1..8d1e195e02 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c @@ -3205,25 +3205,14 @@ static void fill_harq_IEs(NR_ServingCellConfig_t *scc, int num_dlharq, int num_u } } -static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid, - const NR_ServingCellConfigCommon_t *scc, - const nr_mac_config_t *configuration) +static NR_BWP_UplinkDedicated_t *configure_initial_ul_bwp(const NR_ServingCellConfigCommon_t *scc, + const nr_mac_config_t *configuration, + int maxMIMO_Layers, + int id) { - const int pdsch_AntennaPorts = - configuration->pdsch_AntennaPorts.N1 * configuration->pdsch_AntennaPorts.N2 * configuration->pdsch_AntennaPorts.XP; - int curr_bwp = NRRIV2BW(scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); - NR_SpCellConfig_t *SpCellConfig = calloc(1, sizeof(*SpCellConfig)); - SpCellConfig->servCellIndex = NULL; - SpCellConfig->reconfigurationWithSync = NULL; - SpCellConfig->rlmInSyncOutOfSyncThreshold = NULL; - SpCellConfig->rlf_TimersAndConstants = NULL; - - NR_ServingCellConfig_t *configDedicated = calloc(1, sizeof(*configDedicated)); - configDedicated->uplinkConfig = calloc(1, sizeof(*configDedicated->uplinkConfig)); - NR_UplinkConfig_t *uplinkConfig = configDedicated->uplinkConfig; - NR_BWP_UplinkDedicated_t *initialUplinkBWP = calloc(1, sizeof(*initialUplinkBWP)); - uplinkConfig->initialUplinkBWP = initialUplinkBWP; + NR_BWP_t *genericParameters = &scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters; + int curr_bwp = NRRIV2BW(genericParameters->locationAndBandwidth, MAX_BWP_SIZE); initialUplinkBWP->pucch_Config = calloc(1, sizeof(*initialUplinkBWP->pucch_Config)); initialUplinkBWP->pucch_Config->present = NR_SetupRelease_PUCCH_Config_PR_setup; NR_PUCCH_Config_t *pucch_Config = calloc(1, sizeof(*pucch_Config)); @@ -3233,43 +3222,35 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid, pucch_Config->resourceToAddModList = calloc(1, sizeof(*pucch_Config->resourceToAddModList)); pucch_Config->resourceToReleaseList = NULL; int num_pucch2 = get_nb_pucch2_per_slot(scc, curr_bwp); - config_pucch_resset0(pucch_Config, uid, curr_bwp, num_pucch2, NULL); - config_pucch_resset1(pucch_Config, uid, num_pucch2, NULL); + config_pucch_resset0(pucch_Config, id, curr_bwp, num_pucch2, NULL); + config_pucch_resset1(pucch_Config, id, num_pucch2, NULL); set_pucch_power_config(pucch_Config, configuration->do_CSIRS); initialUplinkBWP->pusch_Config = config_pusch(configuration->use_deltaMCS, scc, NULL, configuration->ptrs); - long maxMIMO_Layers = uplinkConfig && uplinkConfig->pusch_ServingCellConfig - && uplinkConfig->pusch_ServingCellConfig->choice.setup->ext1 - && uplinkConfig->pusch_ServingCellConfig->choice.setup->ext1->maxMIMO_Layers - ? *uplinkConfig->pusch_ServingCellConfig->choice.setup->ext1->maxMIMO_Layers - : 1; - // We are using do_srs = 0 here because the periodic SRS will only be enabled in update_cellGroupConfig() if do_srs == 1 - initialUplinkBWP->srs_Config = get_config_srs(scc, NULL, curr_bwp, uid, 0, maxMIMO_Layers, configuration->minRXTXTIME, 0); + initialUplinkBWP->srs_Config = get_config_srs(scc, NULL, curr_bwp, id, 0, maxMIMO_Layers, configuration->minRXTXTIME, 0); scheduling_request_config(scc, pucch_Config, scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing); + set_dl_DataToUL_ACK(pucch_Config, configuration->minRXTXTIME, genericParameters->subcarrierSpacing); + return initialUplinkBWP; +} - set_dl_DataToUL_ACK(pucch_Config, - configuration->minRXTXTIME, - scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing); - - configDedicated->initialDownlinkBWP = calloc(1, sizeof(*configDedicated->initialDownlinkBWP)); - NR_BWP_DownlinkDedicated_t *bwp_Dedicated = configDedicated->initialDownlinkBWP; +static NR_BWP_DownlinkDedicated_t *configure_initial_dl_bwp(const NR_ServingCellConfigCommon_t *scc, + const int pdsch_AntennaPorts, + uint64_t bitmap, + const nr_mac_config_t *configuration) +{ + NR_BWP_DownlinkDedicated_t *bwp_Dedicated = calloc(1, sizeof(*bwp_Dedicated)); bwp_Dedicated->pdcch_Config = calloc(1, sizeof(*bwp_Dedicated->pdcch_Config)); bwp_Dedicated->pdcch_Config->present = NR_SetupRelease_PDCCH_Config_PR_setup; - bwp_Dedicated->pdcch_Config->choice.setup = calloc(1, sizeof(*bwp_Dedicated->pdcch_Config->choice.setup)); - - bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList = - calloc(1, sizeof(*bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList)); - - bwp_Dedicated->pdcch_Config->choice.setup->controlResourceSetToAddModList = - calloc(1, sizeof(*bwp_Dedicated->pdcch_Config->choice.setup->controlResourceSetToAddModList)); - - uint64_t bitmap = get_ssb_bitmap(scc); + NR_PDCCH_Config_t *pdcch_Config = calloc(1, sizeof(*pdcch_Config)); + pdcch_Config->searchSpacesToAddModList = calloc(1, sizeof(*pdcch_Config->searchSpacesToAddModList)); + pdcch_Config->controlResourceSetToAddModList = calloc(1, sizeof(*pdcch_Config->controlResourceSetToAddModList)); + NR_BWP_t *genericParameters = &scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters; + int curr_bwp = NRRIV2BW(genericParameters->locationAndBandwidth, MAX_BWP_SIZE); NR_ControlResourceSet_t *coreset = get_coreset_config(0, curr_bwp, bitmap); - - asn1cSeqAdd(&bwp_Dedicated->pdcch_Config->choice.setup->controlResourceSetToAddModList->list, coreset); + asn1cSeqAdd(&pdcch_Config->controlResourceSetToAddModList->list, coreset); int css_num_agg_level_candidates[NUM_PDCCH_AGG_LEVELS]; css_num_agg_level_candidates[PDCCH_AGG_LEVEL1] = NR_SearchSpace__nrofCandidates__aggregationLevel1_n0; @@ -3282,15 +3263,37 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid, searchspaceid = 5; int rrc_num_agg_level_candidates[NUM_PDCCH_AGG_LEVELS]; int num_cces = get_coreset_num_cces(coreset->frequencyDomainResources.buf, coreset->duration); - verify_agg_levels(num_cces, - configuration->num_agg_level_candidates, - coreset->controlResourceSetId, - rrc_num_agg_level_candidates); + verify_agg_levels(num_cces, configuration->num_agg_level_candidates, coreset->controlResourceSetId, rrc_num_agg_level_candidates); NR_SearchSpace_t *ss2 = rrc_searchspace_config(false, searchspaceid, coreset->controlResourceSetId, rrc_num_agg_level_candidates); - asn1cSeqAdd(&bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list, ss); - asn1cSeqAdd(&bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list, ss2); + asn1cSeqAdd(&pdcch_Config->searchSpacesToAddModList->list, ss); + asn1cSeqAdd(&pdcch_Config->searchSpacesToAddModList->list, ss2); + bwp_Dedicated->pdcch_Config->choice.setup = pdcch_Config; bwp_Dedicated->pdsch_Config = config_pdsch(bitmap, 0, pdsch_AntennaPorts, configuration->ptrs); + return bwp_Dedicated; +} + +static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid, + const NR_ServingCellConfigCommon_t *scc, + const nr_mac_config_t *configuration) +{ + const int pdsch_AntennaPorts = + configuration->pdsch_AntennaPorts.N1 * configuration->pdsch_AntennaPorts.N2 * configuration->pdsch_AntennaPorts.XP; + NR_SpCellConfig_t *SpCellConfig = calloc(1, sizeof(*SpCellConfig)); + SpCellConfig->servCellIndex = NULL; + SpCellConfig->reconfigurationWithSync = NULL; + SpCellConfig->rlmInSyncOutOfSyncThreshold = NULL; + SpCellConfig->rlf_TimersAndConstants = NULL; + + NR_ServingCellConfig_t *configDedicated = calloc(1, sizeof(*configDedicated)); + configDedicated->uplinkConfig = calloc(1, sizeof(*configDedicated->uplinkConfig)); + NR_UplinkConfig_t *uplinkConfig = configDedicated->uplinkConfig; + long maxMIMO_Layers = uplinkConfig + && uplinkConfig->pusch_ServingCellConfig + && uplinkConfig->pusch_ServingCellConfig->choice.setup->ext1 + && uplinkConfig->pusch_ServingCellConfig->choice.setup->ext1->maxMIMO_Layers + ? *uplinkConfig->pusch_ServingCellConfig->choice.setup->ext1->maxMIMO_Layers + : 1; configDedicated->tag_Id = 0; configDedicated->pdsch_ServingCellConfig = calloc(1, sizeof(*configDedicated->pdsch_ServingCellConfig)); @@ -3317,6 +3320,10 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid, pdsch_servingcellconfig->ext3->downlinkHARQ_FeedbackDisabled_r17->choice.setup.buf[3] = 0xFF; } + uint64_t bitmap = get_ssb_bitmap(scc); + uplinkConfig->initialUplinkBWP = configure_initial_ul_bwp(scc, configuration, maxMIMO_Layers, uid); + configDedicated->initialDownlinkBWP = configure_initial_dl_bwp(scc, pdsch_AntennaPorts, bitmap, configuration); + // Downlink BWPs int n_dl_bwp = configuration->num_additional_bwps; int first_active_dl_bwp = 0; From 22cd4e931263a1f1e431f97d64b94378bf38dfec Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 22 Aug 2025 10:48:29 +0200 Subject: [PATCH 607/964] configure only 1 BWP at a given time (1st active BWP) --- openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c | 489 +++++++++---------- 1 file changed, 226 insertions(+), 263 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c index 8d1e195e02..145d5b2057 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c @@ -1665,15 +1665,15 @@ static NR_SetupRelease_PDSCH_Config_t *config_pdsch(uint64_t ssb_bitmap, int bwp return setup_pdsch_Config; } -static void config_downlinkBWP(NR_BWP_Downlink_t *bwp, - const NR_ServingCellConfigCommon_t *scc, - const NR_UE_NR_Capability_t *uecap, - int dl_antenna_ports, - bool force_256qam_off, - int bwp_loop, - bool is_SA, - const nr_mac_config_t *configuration) +static NR_BWP_Downlink_t *config_downlinkBWP(const NR_ServingCellConfigCommon_t *scc, + const NR_UE_NR_Capability_t *uecap, + int dl_antenna_ports, + bool force_256qam_off, + int bwp_loop, + bool is_SA, + const nr_mac_config_t *configuration) { + NR_BWP_Downlink_t *bwp = calloc_or_fail(1, sizeof(*bwp)); bwp->bwp_Common = calloc(1,sizeof(*bwp->bwp_Common)); if(configuration->num_additional_bwps > 0) { const nr_bwp_config_t *bwp_config = &configuration->bwp_config[bwp_loop]; @@ -1772,17 +1772,18 @@ static void config_downlinkBWP(NR_BWP_Downlink_t *bwp, force_256qam_off ? NULL : uecap, bwp->bwp_Dedicated, scc); + return bwp; } -static void config_uplinkBWP(NR_BWP_Uplink_t *ubwp, - long bwp_loop, - bool is_SA, - int uid, - int maxMIMO_Layers, - const nr_mac_config_t *configuration, - const NR_ServingCellConfigCommon_t *scc, - const NR_UE_NR_Capability_t *uecap) +static NR_BWP_Uplink_t *config_uplinkBWP(long bwp_loop, + bool is_SA, + int uid, + int maxMIMO_Layers, + const nr_mac_config_t *configuration, + const NR_ServingCellConfigCommon_t *scc, + const NR_UE_NR_Capability_t *uecap) { + NR_BWP_Uplink_t *ubwp = calloc_or_fail(1, sizeof(*ubwp)); ubwp->bwp_Common = calloc(1, sizeof(*ubwp->bwp_Common)); if(configuration->num_additional_bwps > 0) { ubwp->bwp_Id = configuration->bwp_config[bwp_loop].id; @@ -1843,6 +1844,7 @@ static void config_uplinkBWP(NR_BWP_Uplink_t *ubwp, ubwp->bwp_Dedicated->configuredGrantConfig = NULL; ubwp->bwp_Dedicated->beamFailureRecoveryConfig = NULL; + return ubwp; } static void set_phr_config(NR_MAC_CellGroupConfig_t *mac_CellGroupConfig) @@ -3103,16 +3105,28 @@ static NR_MAC_CellGroupConfig_t *configure_mac_cellgroup(const nr_mac_timers_t * return mac_CellGroupConfig; } -// Set HARQ related IEs according to the number of DL, UL harqprocesses configured -static void fill_harq_IEs(NR_ServingCellConfig_t *scc, int num_dlharq, int num_ulharq) +static void allocate_32_harq(NR_PDSCH_Config_t *pdsch_Config) { + if (!pdsch_Config->ext3) + pdsch_Config->ext3 = calloc(1, sizeof(*pdsch_Config->ext3)); + asn1cCallocOne(pdsch_Config->ext3->harq_ProcessNumberSizeDCI_1_1_r17, 5); +} - AssertFatal(scc && scc->pdsch_ServingCellConfig && - scc->pdsch_ServingCellConfig->present == NR_SetupRelease_PDSCH_ServingCellConfig_PR_setup, +static void allocate_32_ul_harq(NR_PUSCH_Config_t *pusch_Config) +{ + if (!pusch_Config->ext2) + pusch_Config->ext2 = calloc(1, sizeof(*pusch_Config->ext2)); + asn1cCallocOne(pusch_Config->ext2->harq_ProcessNumberSizeDCI_0_1_r17, 5); +} + +// Set HARQ related IEs according to the number of DL, UL harqprocesses configured +static void fill_harq_IEs(NR_ServingCellConfig_t *scc, int num_dlharq, int num_ulharq, int bwp_id) +{ + AssertFatal(scc + && scc->pdsch_ServingCellConfig + && scc->pdsch_ServingCellConfig->present == NR_SetupRelease_PDSCH_ServingCellConfig_PR_setup, "PDSCH_Servingcellconfig IEs NOT present\n"); - NR_PDSCH_ServingCellConfig_t *pdsch_scc = scc->pdsch_ServingCellConfig->choice.setup; - switch (num_dlharq) { case 2: *pdsch_scc->nrofHARQ_ProcessesForPDSCH = NR_PDSCH_ServingCellConfig__nrofHARQ_ProcessesForPDSCH_n2; @@ -3141,34 +3155,27 @@ static void fill_harq_IEs(NR_ServingCellConfig_t *scc, int num_dlharq, int num_u pdsch_scc->ext3 = calloc(1, sizeof(*pdsch_scc->ext3)); asn1cCallocOne(pdsch_scc->ext3->nrofHARQ_ProcessesForPDSCH_v1700, NR_PDSCH_ServingCellConfig__ext3__nrofHARQ_ProcessesForPDSCH_v1700_n32); - NR_BWP_DownlinkDedicated_t *dlbwp = scc->initialDownlinkBWP; - if (dlbwp && dlbwp->pdsch_Config && - dlbwp->pdsch_Config->present == NR_SetupRelease_PDSCH_Config_PR_setup) { - NR_PDSCH_Config_t *dlcfg = scc->initialDownlinkBWP->pdsch_Config->choice.setup; - if (!dlcfg->ext3) - dlcfg->ext3 = calloc(1, sizeof(*dlcfg->ext3)); - asn1cCallocOne(dlcfg->ext3->harq_ProcessNumberSizeDCI_1_1_r17, 5); - } - int num_dl_bwp = 0; - if (scc->downlinkBWP_ToAddModList) - num_dl_bwp = scc->downlinkBWP_ToAddModList->list.count; - for (int i = 0;i < num_dl_bwp; i++) { - dlbwp = scc->downlinkBWP_ToAddModList->list.array[i]->bwp_Dedicated; - if (dlbwp && dlbwp->pdsch_Config && - dlbwp->pdsch_Config->present == NR_SetupRelease_PDSCH_Config_PR_setup) { - NR_PDSCH_Config_t *dlcfg = dlbwp->pdsch_Config->choice.setup; - if (!dlcfg->ext3) - dlcfg->ext3 = calloc(1, sizeof(*dlcfg->ext3)); - asn1cCallocOne(dlcfg->ext3->harq_ProcessNumberSizeDCI_1_1_r17, 5); + NR_BWP_DownlinkDedicated_t *dlbwp = NULL; + if (bwp_id == 0) { + dlbwp = scc->initialDownlinkBWP; + if (dlbwp && dlbwp->pdsch_Config && dlbwp->pdsch_Config->present == NR_SetupRelease_PDSCH_Config_PR_setup) + allocate_32_harq(scc->initialDownlinkBWP->pdsch_Config->choice.setup); + } else { + for (int i = 0; i < scc->downlinkBWP_ToAddModList->list.count; i++) { + if (scc->downlinkBWP_ToAddModList->list.array[i]->bwp_Id != bwp_id) + continue; + dlbwp = scc->downlinkBWP_ToAddModList->list.array[i]->bwp_Dedicated; + if (dlbwp && dlbwp->pdsch_Config && dlbwp->pdsch_Config->present == NR_SetupRelease_PDSCH_Config_PR_setup) + allocate_32_harq(dlbwp->pdsch_Config->choice.setup); } } break; default: // Already IE should have been set to 16 harq processes + AssertFatal(false, "Invalid number of HARQ processes\n"); break; } - - AssertFatal(scc->uplinkConfig,"uplinkConfig IE NOT present\n"); + AssertFatal(scc->uplinkConfig, "uplinkConfig IE NOT present\n"); if (num_ulharq == 32) { if (!scc->uplinkConfig->pusch_ServingCellConfig) @@ -3181,25 +3188,18 @@ static void fill_harq_IEs(NR_ServingCellConfig_t *scc, int num_dlharq, int num_u pusch_scc->ext3 = calloc(1, sizeof(*pusch_scc->ext3)); asn1cCallocOne(pusch_scc->ext3->nrofHARQ_ProcessesForPUSCH_r17, NR_PUSCH_ServingCellConfig__ext3__nrofHARQ_ProcessesForPUSCH_r17_n32); - NR_BWP_UplinkDedicated_t *ulbwp = scc->uplinkConfig->initialUplinkBWP; - if (ulbwp && ulbwp->pusch_Config && - ulbwp->pusch_Config->present == NR_SetupRelease_PUSCH_Config_PR_setup) { - NR_PUSCH_Config_t *ulcfg = ulbwp->pusch_Config->choice.setup; - if (!ulcfg->ext2) - ulcfg->ext2 = calloc(1, sizeof(*ulcfg->ext2)); - asn1cCallocOne(ulcfg->ext2->harq_ProcessNumberSizeDCI_0_1_r17, 5); - } - int num_ul_bwp = 0; - if (scc->uplinkConfig->uplinkBWP_ToAddModList) - num_ul_bwp = scc->uplinkConfig->uplinkBWP_ToAddModList->list.count; - for (int i = 0;i < num_ul_bwp; i++) { - ulbwp = scc->uplinkConfig->uplinkBWP_ToAddModList->list.array[i]->bwp_Dedicated; - if (ulbwp && ulbwp->pusch_Config && - ulbwp->pusch_Config->present == NR_SetupRelease_PUSCH_Config_PR_setup) { - NR_PUSCH_Config_t *ulcfg = ulbwp->pusch_Config->choice.setup; - if (!ulcfg->ext2) - ulcfg->ext2 = calloc(1, sizeof(*ulcfg->ext2)); - asn1cCallocOne(ulcfg->ext2->harq_ProcessNumberSizeDCI_0_1_r17, 5); + NR_BWP_UplinkDedicated_t *ulbwp = NULL; + if (bwp_id == 0) { + ulbwp = scc->uplinkConfig->initialUplinkBWP; + if (ulbwp && ulbwp->pusch_Config && ulbwp->pusch_Config->present == NR_SetupRelease_PUSCH_Config_PR_setup) + allocate_32_ul_harq(ulbwp->pusch_Config->choice.setup); + } else { + for (int i = 0; i < scc->uplinkConfig->uplinkBWP_ToAddModList->list.count; i++) { + if (bwp_id != scc->uplinkConfig->uplinkBWP_ToAddModList->list.array[i]->bwp_Id) + continue; + ulbwp = scc->uplinkConfig->uplinkBWP_ToAddModList->list.array[i]->bwp_Dedicated; + if (ulbwp && ulbwp->pusch_Config && ulbwp->pusch_Config->present == NR_SetupRelease_PUSCH_Config_PR_setup) + allocate_32_ul_harq(ulbwp->pusch_Config->choice.setup); } } } @@ -3321,43 +3321,29 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid, } uint64_t bitmap = get_ssb_bitmap(scc); - uplinkConfig->initialUplinkBWP = configure_initial_ul_bwp(scc, configuration, maxMIMO_Layers, uid); - configDedicated->initialDownlinkBWP = configure_initial_dl_bwp(scc, pdsch_AntennaPorts, bitmap, configuration); + int first_active_bwp = 0; + if (configuration->num_additional_bwps > 0) + first_active_bwp = configuration->first_active_bwp; - // Downlink BWPs - int n_dl_bwp = configuration->num_additional_bwps; - int first_active_dl_bwp = 0; - if (n_dl_bwp > 0) { + asn1cCallocOne(configDedicated->firstActiveDownlinkBWP_Id, first_active_bwp); + asn1cCallocOne(uplinkConfig->firstActiveUplinkBWP_Id, first_active_bwp); + if (first_active_bwp == 0) { + uplinkConfig->initialUplinkBWP = configure_initial_ul_bwp(scc, configuration, maxMIMO_Layers, uid); + configDedicated->initialDownlinkBWP = configure_initial_dl_bwp(scc, pdsch_AntennaPorts, bitmap, configuration); + } else { configDedicated->downlinkBWP_ToAddModList = calloc(1, sizeof(*configDedicated->downlinkBWP_ToAddModList)); - for (int bwp_loop = 0; bwp_loop < n_dl_bwp; bwp_loop++) { - NR_BWP_Downlink_t *bwp = calloc(1, sizeof(*bwp)); - config_downlinkBWP(bwp, - scc, - NULL, - 0, - false, - bwp_loop, - true, - configuration); - asn1cSeqAdd(&configDedicated->downlinkBWP_ToAddModList->list, bwp); - } - first_active_dl_bwp = configuration->first_active_bwp; - } - asn1cCallocOne(configDedicated->firstActiveDownlinkBWP_Id, first_active_dl_bwp); - - // Uplink BWPs - int n_ul_bwp = configuration->num_additional_bwps; - int first_active_ul_bwp = 0; - if (n_ul_bwp > 0) { + NR_BWP_Downlink_t *bwp = config_downlinkBWP(scc, + NULL, + 0, + false, + first_active_bwp - 1, + true, + configuration); + asn1cSeqAdd(&configDedicated->downlinkBWP_ToAddModList->list, bwp); uplinkConfig->uplinkBWP_ToAddModList = calloc(1, sizeof(*uplinkConfig->uplinkBWP_ToAddModList)); - for (int bwp_loop = 0; bwp_loop < n_ul_bwp; bwp_loop++) { - NR_BWP_Uplink_t *ubwp = calloc(1, sizeof(*ubwp)); - config_uplinkBWP(ubwp, bwp_loop, true, uid, maxMIMO_Layers, configuration, scc, NULL); - asn1cSeqAdd(&uplinkConfig->uplinkBWP_ToAddModList->list, ubwp); - } - first_active_ul_bwp = configuration->first_active_bwp; + NR_BWP_Uplink_t *ubwp = config_uplinkBWP(first_active_bwp - 1, true, uid, maxMIMO_Layers, configuration, scc, NULL); + asn1cSeqAdd(&uplinkConfig->uplinkBWP_ToAddModList->list, ubwp); } - asn1cCallocOne(uplinkConfig->firstActiveUplinkBWP_Id, first_active_ul_bwp); configDedicated->csi_MeasConfig = calloc(1, sizeof(*configDedicated->csi_MeasConfig)); configDedicated->csi_MeasConfig->present = NR_SetupRelease_CSI_MeasConfig_PR_setup; @@ -3384,97 +3370,93 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid, } asn1cSeqAdd(&csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list, ssbresset0); - int bwp_loop_end = n_dl_bwp + 1; - for (int bwp_loop = 0; bwp_loop < bwp_loop_end; bwp_loop++) { - int curr_bwp, bwp_id; - struct NR_SetupRelease_PDSCH_Config *pdsch_Config; - if (bwp_loop == 0) { - pdsch_Config = configDedicated->initialDownlinkBWP->pdsch_Config; - curr_bwp = NRRIV2BW(scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); - bwp_id = 0; - } else { - NR_BWP_Downlink_t *bwp = configDedicated->downlinkBWP_ToAddModList->list.array[bwp_loop - 1]; - pdsch_Config = bwp->bwp_Dedicated->pdsch_Config; - curr_bwp = NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); - bwp_id = bwp->bwp_Id; - } - - config_csirs(scc, csi_MeasConfig, pdsch_AntennaPorts, curr_bwp, configuration->do_CSIRS, bwp_loop); - config_csiim(configuration->do_CSIRS, pdsch_AntennaPorts, curr_bwp, csi_MeasConfig, bwp_loop); - - NR_CSI_ResourceConfig_t *csires1 = calloc(1, sizeof(*csires1)); - csires1->csi_ResourceConfigId = bwp_id + 20; - csires1->csi_RS_ResourceSetList.present = NR_CSI_ResourceConfig__csi_RS_ResourceSetList_PR_nzp_CSI_RS_SSB; - csires1->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB = - calloc(1, sizeof(*csires1->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB)); - csires1->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList = - calloc(1, sizeof(*csires1->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList)); - NR_CSI_SSB_ResourceSetId_t *ssbres00 = calloc(1, sizeof(*ssbres00)); - *ssbres00 = 0; - asn1cSeqAdd(&csires1->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList->list, ssbres00); - csires1->bwp_Id = bwp_id; - csires1->resourceType = NR_CSI_ResourceConfig__resourceType_periodic; - asn1cSeqAdd(&csi_MeasConfig->csi_ResourceConfigToAddModList->list, csires1); - - int pucch_Resource = 2; - - if (configuration->do_CSIRS) { - NR_CSI_ResourceConfig_t *csires0 = calloc(1, sizeof(*csires0)); - csires0->csi_ResourceConfigId = bwp_id; - csires0->csi_RS_ResourceSetList.present = NR_CSI_ResourceConfig__csi_RS_ResourceSetList_PR_nzp_CSI_RS_SSB; - csires0->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB = - calloc(1, sizeof(*csires0->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB)); - csires0->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList = - calloc(1, sizeof(*csires0->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList)); - NR_NZP_CSI_RS_ResourceSetId_t *nzp0 = calloc(1, sizeof(*nzp0)); - *nzp0 = bwp_loop; - asn1cSeqAdd(&csires0->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList->list, nzp0); - csires0->bwp_Id = bwp_id; - csires0->resourceType = NR_CSI_ResourceConfig__resourceType_periodic; - asn1cSeqAdd(&csi_MeasConfig->csi_ResourceConfigToAddModList->list, csires0); - } - - if (configuration->do_CSIRS && pdsch_AntennaPorts > 1) { - NR_CSI_ResourceConfig_t *csires2 = calloc(1, sizeof(*csires2)); - csires2->csi_ResourceConfigId = bwp_id + 10; - csires2->csi_RS_ResourceSetList.present = NR_CSI_ResourceConfig__csi_RS_ResourceSetList_PR_csi_IM_ResourceSetList; - csires2->csi_RS_ResourceSetList.choice.csi_IM_ResourceSetList = - calloc(1, sizeof(*csires2->csi_RS_ResourceSetList.choice.csi_IM_ResourceSetList)); - NR_CSI_IM_ResourceSetId_t *csiim00 = calloc(1, sizeof(*csiim00)); - *csiim00 = bwp_loop; - asn1cSeqAdd(&csires2->csi_RS_ResourceSetList.choice.csi_IM_ResourceSetList->list, csiim00); - csires2->bwp_Id = bwp_id; - csires2->resourceType = NR_CSI_ResourceConfig__resourceType_periodic; - asn1cSeqAdd(&csi_MeasConfig->csi_ResourceConfigToAddModList->list, csires2); - - NR_PUCCH_CSI_Resource_t *pucchcsi = calloc(1, sizeof(*pucchcsi)); - pucchcsi->uplinkBandwidthPartId = bwp_id; - pucchcsi->pucch_Resource = pucch_Resource; - config_csi_meas_report(csi_MeasConfig, - scc, - pucchcsi, - pdsch_Config, - &configuration->pdsch_AntennaPorts, - *pdsch_servingcellconfig->ext1->maxMIMO_Layers, - bwp_id, - uid, - curr_bwp); - } - NR_PUCCH_CSI_Resource_t *pucchrsrp = calloc(1, sizeof(*pucchrsrp)); - pucchrsrp->uplinkBandwidthPartId = bwp_id; - pucchrsrp->pucch_Resource = pucch_Resource; - config_rsrp_meas_report(csi_MeasConfig, - scc, - pucchrsrp, - configuration->do_CSIRS, - bwp_id + 10, - uid, - curr_bwp, - pdsch_AntennaPorts, - configuration->do_SINR); + int curr_bwp, bwp_id; + NR_SetupRelease_PDSCH_Config_t *pdsch_Config; + if (first_active_bwp == 0) { + pdsch_Config = configDedicated->initialDownlinkBWP->pdsch_Config; + curr_bwp = NRRIV2BW(scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + bwp_id = 0; + } else { + NR_BWP_Downlink_t *bwp = configDedicated->downlinkBWP_ToAddModList->list.array[0]; + pdsch_Config = bwp->bwp_Dedicated->pdsch_Config; + curr_bwp = NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + bwp_id = bwp->bwp_Id; } - fill_harq_IEs(configDedicated, configuration->num_dlharq, configuration->num_ulharq); + config_csirs(scc, csi_MeasConfig, pdsch_AntennaPorts, curr_bwp, configuration->do_CSIRS, first_active_bwp); + config_csiim(configuration->do_CSIRS, pdsch_AntennaPorts, curr_bwp, csi_MeasConfig, first_active_bwp); + + NR_CSI_ResourceConfig_t *csires1 = calloc(1, sizeof(*csires1)); + csires1->csi_ResourceConfigId = bwp_id + 20; + csires1->csi_RS_ResourceSetList.present = NR_CSI_ResourceConfig__csi_RS_ResourceSetList_PR_nzp_CSI_RS_SSB; + csires1->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB = + calloc(1, sizeof(*csires1->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB)); + csires1->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList = + calloc(1, sizeof(*csires1->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList)); + NR_CSI_SSB_ResourceSetId_t *ssbres00 = calloc(1, sizeof(*ssbres00)); + *ssbres00 = 0; + asn1cSeqAdd(&csires1->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList->list, ssbres00); + csires1->bwp_Id = bwp_id; + csires1->resourceType = NR_CSI_ResourceConfig__resourceType_periodic; + asn1cSeqAdd(&csi_MeasConfig->csi_ResourceConfigToAddModList->list, csires1); + + int pucch_Resource = 2; + if (configuration->do_CSIRS) { + NR_CSI_ResourceConfig_t *csires0 = calloc(1, sizeof(*csires0)); + csires0->csi_ResourceConfigId = bwp_id; + csires0->csi_RS_ResourceSetList.present = NR_CSI_ResourceConfig__csi_RS_ResourceSetList_PR_nzp_CSI_RS_SSB; + csires0->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB = + calloc(1, sizeof(*csires0->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB)); + csires0->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList = + calloc(1, sizeof(*csires0->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList)); + NR_NZP_CSI_RS_ResourceSetId_t *nzp0 = calloc(1, sizeof(*nzp0)); + *nzp0 = first_active_bwp; + asn1cSeqAdd(&csires0->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList->list, nzp0); + csires0->bwp_Id = bwp_id; + csires0->resourceType = NR_CSI_ResourceConfig__resourceType_periodic; + asn1cSeqAdd(&csi_MeasConfig->csi_ResourceConfigToAddModList->list, csires0); + } + + if (configuration->do_CSIRS && pdsch_AntennaPorts > 1) { + NR_CSI_ResourceConfig_t *csires2 = calloc(1, sizeof(*csires2)); + csires2->csi_ResourceConfigId = bwp_id + 10; + csires2->csi_RS_ResourceSetList.present = NR_CSI_ResourceConfig__csi_RS_ResourceSetList_PR_csi_IM_ResourceSetList; + csires2->csi_RS_ResourceSetList.choice.csi_IM_ResourceSetList = + calloc(1, sizeof(*csires2->csi_RS_ResourceSetList.choice.csi_IM_ResourceSetList)); + NR_CSI_IM_ResourceSetId_t *csiim00 = calloc(1, sizeof(*csiim00)); + *csiim00 = first_active_bwp; + asn1cSeqAdd(&csires2->csi_RS_ResourceSetList.choice.csi_IM_ResourceSetList->list, csiim00); + csires2->bwp_Id = bwp_id; + csires2->resourceType = NR_CSI_ResourceConfig__resourceType_periodic; + asn1cSeqAdd(&csi_MeasConfig->csi_ResourceConfigToAddModList->list, csires2); + + NR_PUCCH_CSI_Resource_t *pucchcsi = calloc(1, sizeof(*pucchcsi)); + pucchcsi->uplinkBandwidthPartId = bwp_id; + pucchcsi->pucch_Resource = pucch_Resource; + config_csi_meas_report(csi_MeasConfig, + scc, + pucchcsi, + pdsch_Config, + &configuration->pdsch_AntennaPorts, + *pdsch_servingcellconfig->ext1->maxMIMO_Layers, + bwp_id, + uid, + curr_bwp); + } + NR_PUCCH_CSI_Resource_t *pucchrsrp = calloc(1, sizeof(*pucchrsrp)); + pucchrsrp->uplinkBandwidthPartId = bwp_id; + pucchrsrp->pucch_Resource = pucch_Resource; + config_rsrp_meas_report(csi_MeasConfig, + scc, + pucchrsrp, + configuration->do_CSIRS, + bwp_id + 10, + uid, + curr_bwp, + pdsch_AntennaPorts, + configuration->do_SINR); + + fill_harq_IEs(configDedicated, configuration->num_dlharq, configuration->num_ulharq, first_active_bwp); SpCellConfig->spCellConfigDedicated = configDedicated; if (LOG_DEBUGFLAG(DEBUG_ASN1)) { @@ -3709,33 +3691,24 @@ void update_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig, { DevAssert(cellGroupConfig != NULL); DevAssert(cellGroupConfig->spCellConfig != NULL); + DevAssert(cellGroupConfig->spCellConfig->spCellConfigDedicated != NULL); DevAssert(configuration != NULL); DevAssert(scc != NULL); NR_SpCellConfig_t *SpCellConfig = cellGroupConfig->spCellConfig; - - NR_PDSCH_ServingCellConfig_t *pdsch_servingcellconfig = SpCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->choice.setup; + NR_ServingCellConfig_t *spCellConfigDedicated = SpCellConfig->spCellConfigDedicated; + NR_PDSCH_ServingCellConfig_t *pdsch_servingcellconfig = spCellConfigDedicated->pdsch_ServingCellConfig->choice.setup; set_dl_maxmimolayers(pdsch_servingcellconfig, scc, uecap, configuration->maxMIMO_layers); - NR_CSI_MeasConfig_t *csi_MeasConfig = SpCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup; + NR_CSI_MeasConfig_t *csi_MeasConfig = spCellConfigDedicated->csi_MeasConfig->choice.setup; for (int report = 0; report < csi_MeasConfig->csi_ReportConfigToAddModList->list.count; report++) { NR_CSI_ReportConfig_t *csirep = csi_MeasConfig->csi_ReportConfigToAddModList->list.array[report]; if(csirep->codebookConfig) config_csi_codebook(&configuration->pdsch_AntennaPorts, *pdsch_servingcellconfig->ext1->maxMIMO_Layers, csirep->codebookConfig); } - int curr_bwp = NRRIV2BW(scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); - NR_UplinkConfig_t *uplinkConfig = - SpCellConfig && SpCellConfig->spCellConfigDedicated ? SpCellConfig->spCellConfigDedicated->uplinkConfig : NULL; - + NR_UplinkConfig_t *uplinkConfig = spCellConfigDedicated->uplinkConfig; long maxMIMO_Layers = set_ul_max_layers(configuration, uecap); - if (uplinkConfig->initialUplinkBWP->pusch_Config) { - NR_PUSCH_Config_t *pusch_Config = uplinkConfig->initialUplinkBWP->pusch_Config->choice.setup; - if (pusch_Config->maxRank == NULL) { - pusch_Config->maxRank = calloc(1, sizeof(*pusch_Config->maxRank)); - } - *pusch_Config->maxRank = maxMIMO_Layers; - } if (!uplinkConfig->pusch_ServingCellConfig) uplinkConfig->pusch_ServingCellConfig = calloc(1, sizeof(*uplinkConfig->pusch_ServingCellConfig)); uplinkConfig->pusch_ServingCellConfig->present = NR_SetupRelease_PUSCH_ServingCellConfig_PR_setup; @@ -3746,64 +3719,57 @@ void update_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig, calloc(1, sizeof(*uplinkConfig->pusch_ServingCellConfig->choice.setup->ext1)); asn1cCallocOne(uplinkConfig->pusch_ServingCellConfig->choice.setup->ext1->maxMIMO_Layers, maxMIMO_Layers); - // UL and SRS configuration - if (configuration->do_SRS && uplinkConfig && uplinkConfig->initialUplinkBWP) { - ASN_STRUCT_FREE(asn_DEF_NR_SetupRelease_SRS_Config, uplinkConfig->initialUplinkBWP->srs_Config); - uplinkConfig->initialUplinkBWP->srs_Config = get_config_srs(scc, - uecap, - curr_bwp, - uid, - 0, - maxMIMO_Layers, - configuration->minRXTXTIME, - configuration->do_SRS); + // Update UL BWP + NR_BWP_UplinkDedicated_t *ul_bwp_Dedicated = NULL; + int curr_bwp = 0; + int bwp_id = 0; + if (uplinkConfig && uplinkConfig->initialUplinkBWP) { + ul_bwp_Dedicated = uplinkConfig->initialUplinkBWP; + curr_bwp = NRRIV2BW(scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + } else if (uplinkConfig && uplinkConfig->uplinkBWP_ToAddModList) { + struct NR_UplinkConfig__uplinkBWP_ToAddModList *UL_BWP_list = uplinkConfig->uplinkBWP_ToAddModList; + AssertFatal(UL_BWP_list->list.count == 1, "We should only have 1 BWP configured at a given time\n"); + NR_BWP_Uplink_t *ul_bwp = UL_BWP_list->list.array[0]; + curr_bwp = NRRIV2BW(ul_bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + ul_bwp_Dedicated = ul_bwp->bwp_Dedicated; + bwp_id = ul_bwp->bwp_Id; } - - // Set DL MCS table - NR_BWP_DownlinkDedicated_t *bwp_Dedicated = SpCellConfig->spCellConfigDedicated->initialDownlinkBWP; - set_dl_mcs_table(scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.subcarrierSpacing, - configuration->force_256qam_off ? NULL : uecap, - bwp_Dedicated, - scc); - - NR_BWP_UplinkDedicated_t *ul_bwp_Dedicated = SpCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP; - set_ul_mcs_table(configuration->force_UL256qam_off ? NULL : uecap, scc, ul_bwp_Dedicated->pusch_Config->choice.setup); - - struct NR_ServingCellConfig__downlinkBWP_ToAddModList *DL_BWP_list = - SpCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList; - struct NR_UplinkConfig__uplinkBWP_ToAddModList *UL_BWP_list = uplinkConfig ? uplinkConfig->uplinkBWP_ToAddModList : NULL; - if (DL_BWP_list) { - for (int i = 0; i < DL_BWP_list->list.count; i++) { - NR_BWP_Downlink_t *bwp = DL_BWP_list->list.array[i]; - int scs = bwp->bwp_Common->genericParameters.subcarrierSpacing; - set_dl_mcs_table(scs, configuration->force_256qam_off ? NULL : uecap, bwp->bwp_Dedicated, scc); + if (ul_bwp_Dedicated) { + NR_PUSCH_Config_t *pusch_Config = ul_bwp_Dedicated->pusch_Config->choice.setup; + if (!pusch_Config->maxRank) + pusch_Config->maxRank = calloc(1, sizeof(*pusch_Config->maxRank)); + *pusch_Config->maxRank = maxMIMO_Layers; + if (configuration->do_SRS) { + ASN_STRUCT_FREE(asn_DEF_NR_SetupRelease_SRS_Config, ul_bwp_Dedicated->srs_Config); + ul_bwp_Dedicated->srs_Config = get_config_srs(scc, + uecap, + curr_bwp, + uid, + bwp_id, + maxMIMO_Layers, + configuration->minRXTXTIME, + configuration->do_SRS); } + set_ul_mcs_table(configuration->force_UL256qam_off ? NULL : uecap, scc, pusch_Config); } - if (UL_BWP_list) { - for (int i = 0; i < UL_BWP_list->list.count; i++) { - NR_BWP_Uplink_t *ul_bwp = UL_BWP_list->list.array[i]; - int bwp_size = NRRIV2BW(ul_bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); - if (ul_bwp->bwp_Dedicated->pusch_Config) { - NR_PUSCH_Config_t *pusch_Config = ul_bwp->bwp_Dedicated->pusch_Config->choice.setup; - set_ul_mcs_table(configuration->force_UL256qam_off ? NULL : uecap, scc, pusch_Config); - if (pusch_Config->maxRank == NULL) { - pusch_Config->maxRank = calloc(1, sizeof(*pusch_Config->maxRank)); - } - *pusch_Config->maxRank = maxMIMO_Layers; - } - ASN_STRUCT_FREE(asn_DEF_NR_SetupRelease_SRS_Config, ul_bwp->bwp_Dedicated->srs_Config); - ul_bwp->bwp_Dedicated->srs_Config = get_config_srs(scc, - uecap, - bwp_size, - uid, - i + 1, - maxMIMO_Layers, - configuration->minRXTXTIME, - configuration->do_SRS); - } + // Update DL BWP + NR_BWP_DownlinkDedicated_t *bwp_Dedicated = NULL; + int scs = -1; + if (spCellConfigDedicated->initialDownlinkBWP) { + bwp_Dedicated = spCellConfigDedicated->initialDownlinkBWP; + scs = scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.subcarrierSpacing; + } else if (spCellConfigDedicated->downlinkBWP_ToAddModList) { + struct NR_ServingCellConfig__downlinkBWP_ToAddModList *DL_BWP_list = spCellConfigDedicated->downlinkBWP_ToAddModList; + AssertFatal(DL_BWP_list->list.count == 1, "We should only have 1 BWP configured at a given time\n"); + NR_BWP_Downlink_t *bwp = DL_BWP_list->list.array[0]; + bwp_Dedicated = bwp->bwp_Dedicated; + scs = bwp->bwp_Common->genericParameters.subcarrierSpacing; + } + if (bwp_Dedicated) { + set_dl_mcs_table(scs, configuration->force_256qam_off ? NULL : uecap, bwp_Dedicated, scc); + update_cqitables(bwp_Dedicated->pdsch_Config, csi_MeasConfig); } - update_cqitables(bwp_Dedicated->pdsch_Config, csi_MeasConfig); } void free_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig) @@ -3935,15 +3901,13 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC } configDedicated->downlinkBWP_ToAddModList = calloc(1, sizeof(*configDedicated->downlinkBWP_ToAddModList)); for (int bwp_loop = 0; bwp_loop < n_dl_bwp; bwp_loop++) { - NR_BWP_Downlink_t *bwp = calloc(1, sizeof(*bwp)); - config_downlinkBWP(bwp, - servingcellconfigcommon, - uecap, - dl_antenna_ports, - configuration->force_256qam_off, - bwp_loop, - false, - configuration); + NR_BWP_Downlink_t *bwp = config_downlinkBWP(servingcellconfigcommon, + uecap, + dl_antenna_ports, + configuration->force_256qam_off, + bwp_loop, + false, + configuration); asn1cSeqAdd(&configDedicated->downlinkBWP_ToAddModList->list, bwp); configDedicated->firstActiveDownlinkBWP_Id = calloc(1, sizeof(*configDedicated->firstActiveDownlinkBWP_Id)); *configDedicated->firstActiveDownlinkBWP_Id = firstActiveDownlinkBWP_Id; @@ -3961,8 +3925,7 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC if (n_ul_bwp > 0) { ulConfig->uplinkBWP_ToAddModList = calloc(1, sizeof(*ulConfig->uplinkBWP_ToAddModList)); for (int bwp_loop = 0; bwp_loop < n_ul_bwp; bwp_loop++) { - NR_BWP_Uplink_t *ubwp = calloc(1, sizeof(*ubwp)); - config_uplinkBWP(ubwp, bwp_loop, false, uid, maxMIMO_Layers, configuration, servingcellconfigcommon, uecap); + NR_BWP_Uplink_t *ubwp = config_uplinkBWP(bwp_loop, false, uid, maxMIMO_Layers, configuration, servingcellconfigcommon, uecap); asn1cSeqAdd(&ulConfig->uplinkBWP_ToAddModList->list, ubwp); } ulConfig->firstActiveUplinkBWP_Id = calloc(1, sizeof(*ulConfig->firstActiveUplinkBWP_Id)); @@ -4125,7 +4088,7 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC configDedicated->pathlossReferenceLinking = NULL; configDedicated->servingCellMO = NULL; - fill_harq_IEs(configDedicated, configuration->num_dlharq, configuration->num_ulharq); + fill_harq_IEs(configDedicated, configuration->num_dlharq, configuration->num_ulharq, firstActiveDownlinkBWP_Id); secondaryCellGroup->spCellConfig->spCellConfigDedicated = configDedicated; if (LOG_DEBUGFLAG(DEBUG_ASN1)) { From 7300a7daf3698105d0682456454790dc795af4f3 Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 22 Aug 2025 17:58:44 +0200 Subject: [PATCH 608/964] option to trigger reconfiguration with BWP switching --- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 64 +++++++++++++++-- .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 2 +- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 2 +- .../LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c | 2 +- openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c | 70 +++++++++++++++++++ openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h | 8 ++- 6 files changed, 140 insertions(+), 8 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 2d045a59a8..e576445e45 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -3444,10 +3444,11 @@ void nr_measgap_scheduling(gNB_MAC_INST *nr_mac, frame_t frame, sub_frame_t slot void nr_mac_clean_cellgroup(NR_CellGroupConfig_t *cell_group) { DevAssert(cell_group != NULL); + NR_SpCellConfig_t *spCellConfig = cell_group->spCellConfig; /* remove a reconfigurationWithSync, we don't need it anymore */ - if (cell_group->spCellConfig && cell_group->spCellConfig->reconfigurationWithSync != NULL) { - ASN_STRUCT_FREE(asn_DEF_NR_ReconfigurationWithSync, cell_group->spCellConfig->reconfigurationWithSync); - cell_group->spCellConfig->reconfigurationWithSync = NULL; + if (spCellConfig && spCellConfig->reconfigurationWithSync != NULL) { + ASN_STRUCT_FREE(asn_DEF_NR_ReconfigurationWithSync, spCellConfig->reconfigurationWithSync); + spCellConfig->reconfigurationWithSync = NULL; } /* remove the rlc_BearerToReleaseList, we don't need it anymore */ if (cell_group->rlc_BearerToReleaseList != NULL) { @@ -3459,6 +3460,48 @@ void nr_mac_clean_cellgroup(NR_CellGroupConfig_t *cell_group) /* remove reestablishRLC, we don't need it anymore */ for (int i = 0; i < cell_group->rlc_BearerToAddModList->list.count; ++i) free_and_zero(cell_group->rlc_BearerToAddModList->list.array[i]->reestablishRLC); + /* clean BWP structures */ + NR_ServingCellConfig_t *spCellConfigDedicated = spCellConfig->spCellConfigDedicated; + if (spCellConfigDedicated->downlinkBWP_ToReleaseList) { + struct NR_ServingCellConfig__downlinkBWP_ToReleaseList *rel_dl = spCellConfigDedicated->downlinkBWP_ToReleaseList; + struct NR_ServingCellConfig__downlinkBWP_ToAddModList *add_dl = spCellConfigDedicated->downlinkBWP_ToAddModList; + int num_rel = rel_dl->list.count; + int num_add = add_dl->list.count; + for (int i = 0; i < num_rel; i++) { + NR_BWP_Id_t *rel_id = rel_dl->list.array[i]; + for (int j = 0; j < num_add; j++) { + NR_BWP_Downlink_t *dl_bwp = add_dl->list.array[j]; + if (*rel_id == dl_bwp->bwp_Id) { + asn_sequence_del(&add_dl->list, j, 1); + } + } + asn_sequence_del(&rel_dl->list, i, 1); + } + if (rel_dl->list.count == 0) + free_and_zero(rel_dl); + if (add_dl->list.count == 0) + free_and_zero(add_dl); + } + if (spCellConfigDedicated->uplinkConfig->uplinkBWP_ToReleaseList) { + struct NR_UplinkConfig__uplinkBWP_ToReleaseList *rel_ul = spCellConfigDedicated->uplinkConfig->uplinkBWP_ToReleaseList; + struct NR_UplinkConfig__uplinkBWP_ToAddModList *add_ul = spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList; + int num_rel = rel_ul->list.count; + int num_add = add_ul->list.count; + for (int i = 0; i < num_rel; i++) { + NR_BWP_Id_t *rel_id = rel_ul->list.array[i]; + for (int j = 0; j < num_add; j++) { + NR_BWP_Uplink_t *ul_bwp = add_ul->list.array[j]; + if (*rel_id == ul_bwp->bwp_Id) { + asn_sequence_del(&add_ul->list, j, 1); + } + } + asn_sequence_del(&rel_ul->list, i, 1); + } + if (rel_ul->list.count == 0) + free_and_zero(rel_ul); + if (add_ul->list.count == 0) + free_and_zero(add_ul); + } } int nr_mac_get_reconfig_delay_slots(NR_SubcarrierSpacing_t scs) @@ -3840,9 +3883,22 @@ bool nr_mac_check_ul_failure(gNB_MAC_INST *nrmac, int rnti, NR_UE_sched_ctrl_t * return false; } -void nr_mac_trigger_reconfiguration(const gNB_MAC_INST *nrmac, const NR_UE_info_t *UE) +void nr_mac_trigger_reconfiguration(const gNB_MAC_INST *nrmac, const NR_UE_info_t *UE, int new_bwp_id) { DevAssert(UE->CellGroup != NULL); + if (new_bwp_id >= 0) { + AssertFatal(UE->current_DL_BWP.bwp_id == UE->current_UL_BWP.bwp_id, "We only support same BWP for UL and DL\n"); + if (new_bwp_id == UE->current_DL_BWP.bwp_id) + LOG_E(NR_MAC, "Source BWP ID and target BWP ID are the same, can't perform switch\n"); + else + update_cellGroupConfig_for_BWP_switch(UE->CellGroup, + &nrmac->radio_config, + UE->capability, + nrmac->common_channels[0].ServingCellConfigCommon, + UE->uid, + UE->current_DL_BWP.bwp_id, + new_bwp_id); + } uint8_t buf[2048]; asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_CellGroupConfig, NULL, UE->CellGroup, buf, sizeof(buf)); AssertFatal(enc_rval.encoded > 0, "ASN1 encoding of CellGroupConfig failed, failed type %s\n", enc_rval.failed_type->name); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index b08e703076..aafe213eeb 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -880,7 +880,7 @@ static void nr_rx_ra_sdu(const module_id_t mod_id, if (!old_UE->reconfigSpCellConfig) { LOG_I(NR_MAC, "Received UL_SCH_LCID_C_RNTI with C-RNTI 0x%04x, triggering RRC Reconfiguration\n", crnti); // Trigger RRCReconfiguration - nr_mac_trigger_reconfiguration(mac, old_UE); + nr_mac_trigger_reconfiguration(mac, old_UE, -1); // we configure the UE using common search space with DCIX0 while waiting for a reconfiguration configure_UE_BWP(mac, scc, old_UE, false, NR_SearchSpace__searchSpaceType_PR_common, -1, -1); } diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index cdedb244e9..7ea9a831f9 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -481,7 +481,7 @@ void nr_mac_trigger_ul_failure(NR_UE_sched_ctrl_t *sched_ctrl, NR_SubcarrierSpac void nr_mac_reset_ul_failure(NR_UE_sched_ctrl_t *sched_ctrl); bool nr_mac_check_ul_failure(gNB_MAC_INST *nrmac, int rnti, NR_UE_sched_ctrl_t *sched_ctrl); -void nr_mac_trigger_reconfiguration(const gNB_MAC_INST *nrmac, const NR_UE_info_t *UE); +void nr_mac_trigger_reconfiguration(const gNB_MAC_INST *nrmac, const NR_UE_info_t *UE, int new_bwp_id); void process_addmod_bearers_cellGroupConfig(NR_UE_sched_ctrl_t *sched_ctrl, const struct NR_CellGroupConfig__rlc_BearerToAddModList *addmod); diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c index 88083cdbb3..f73f4b8f70 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -785,8 +785,8 @@ void ue_context_modification_request(const f1ap_ue_context_mod_req_t *req) } } // we re-configure the BWP to apply the CellGroup and to use UE specific Search Space with DCIX1 - nr_mac_clean_cellgroup(UE->CellGroup); configure_UE_BWP(mac, scc, UE, false, NR_SearchSpace__searchSpaceType_PR_ue_Specific, -1, -1); + nr_mac_clean_cellgroup(UE->CellGroup); } if (ue_cap != NULL) { diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c index 145d5b2057..a48171aff8 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c @@ -3683,6 +3683,76 @@ static long set_ul_max_layers(const nr_mac_config_t *configuration, const NR_UE_ return ul_max_layers; } +void update_cellGroupConfig_for_BWP_switch(NR_CellGroupConfig_t *cellGroupConfig, + const nr_mac_config_t *configuration, + const NR_UE_NR_Capability_t *uecap, + const NR_ServingCellConfigCommon_t *scc, + int uid, + int old_bwp, + int new_bwp) +{ + NR_SpCellConfig_t *spCellConfig = cellGroupConfig->spCellConfig; + NR_ServingCellConfig_t *configDedicated = spCellConfig->spCellConfigDedicated; + *configDedicated->firstActiveDownlinkBWP_Id = new_bwp; + NR_UplinkConfig_t *uplinkConfig = configDedicated->uplinkConfig; + *uplinkConfig->firstActiveUplinkBWP_Id = new_bwp; + long ul_maxMIMO_Layers = set_ul_max_layers(configuration, uecap); + + // release old BWP + struct NR_ServingCellConfig__downlinkBWP_ToAddModList *dl_BWP_list = configDedicated->downlinkBWP_ToAddModList; + struct NR_UplinkConfig__uplinkBWP_ToAddModList *ul_BWP_list = uplinkConfig->uplinkBWP_ToAddModList; + if (old_bwp > 0) { // we need to remove old BWP only if it is not the initial + AssertFatal(dl_BWP_list, "Source BWP %d should be present in the list\n", old_bwp); + AssertFatal(ul_BWP_list, "Source BWP %d should be present in the list\n", old_bwp); + NR_BWP_Id_t id = dl_BWP_list->list.array[0]->bwp_Id; + if (!configDedicated->downlinkBWP_ToReleaseList) + configDedicated->downlinkBWP_ToReleaseList = calloc_or_fail(1, sizeof(*configDedicated->downlinkBWP_ToReleaseList)); + asn1cSequenceAdd(configDedicated->downlinkBWP_ToReleaseList->list, NR_BWP_Id_t, rel_id); + *rel_id = id; + AssertFatal(configDedicated->downlinkBWP_ToReleaseList->list.count == 1, + "logic error: there shouldn't be more than 1 BWP to release, but downlinkBWP_ToReleaseList has %d\n", + configDedicated->downlinkBWP_ToReleaseList->list.count); + + id = ul_BWP_list->list.array[0]->bwp_Id; + if (!uplinkConfig->uplinkBWP_ToReleaseList) + uplinkConfig->uplinkBWP_ToReleaseList = calloc_or_fail(1, sizeof(*uplinkConfig->uplinkBWP_ToReleaseList)); + asn1cSequenceAdd(uplinkConfig->uplinkBWP_ToReleaseList->list, NR_BWP_Id_t, ul_rel_id); + *ul_rel_id = id; + AssertFatal(uplinkConfig->uplinkBWP_ToReleaseList->list.count == 1, + "logic error: there shouldn't be more than 1 BWP to release, but uplinkBWP_ToReleaseList has %d\n", + uplinkConfig->uplinkBWP_ToReleaseList->list.count); + } + + const int pdsch_AntennaPorts = + configuration->pdsch_AntennaPorts.N1 * configuration->pdsch_AntennaPorts.N2 * configuration->pdsch_AntennaPorts.XP; + // add new BWP + if (new_bwp == 0) { + uint64_t bitmap = get_ssb_bitmap(scc); + if (!configDedicated->initialDownlinkBWP) + configDedicated->initialDownlinkBWP = calloc_or_fail(1, sizeof(*configDedicated->initialDownlinkBWP)); + if (!uplinkConfig->initialUplinkBWP) + uplinkConfig->initialUplinkBWP = calloc_or_fail(1, sizeof(*uplinkConfig->initialUplinkBWP)); + uplinkConfig->initialUplinkBWP = configure_initial_ul_bwp(scc, configuration, ul_maxMIMO_Layers, uid); + configDedicated->initialDownlinkBWP = configure_initial_dl_bwp(scc, pdsch_AntennaPorts, bitmap, configuration); + } else { + if (!configDedicated->downlinkBWP_ToAddModList) + configDedicated->downlinkBWP_ToAddModList = calloc_or_fail(1, sizeof(*configDedicated->downlinkBWP_ToAddModList)); + NR_BWP_Downlink_t *dl_bwp = config_downlinkBWP(scc, + uecap, + pdsch_AntennaPorts, + configuration->force_256qam_off, + new_bwp - 1, + true, + configuration); + asn1cSeqAdd(&configDedicated->downlinkBWP_ToAddModList->list, dl_bwp); + + if (!uplinkConfig->uplinkBWP_ToAddModList) + uplinkConfig->uplinkBWP_ToAddModList = calloc_or_fail(1, sizeof(*uplinkConfig->uplinkBWP_ToAddModList)); + NR_BWP_Uplink_t *ul_bwp = config_uplinkBWP(new_bwp - 1, true, uid, ul_maxMIMO_Layers, configuration, scc, uecap); + asn1cSeqAdd(&uplinkConfig->uplinkBWP_ToAddModList->list, ul_bwp); + } +} + void update_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig, const int uid, const NR_UE_NR_Capability_t *uecap, diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h index 865d1b040e..44715dc66d 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h @@ -121,7 +121,13 @@ NR_RLC_BearerConfig_t *get_DRB_RLC_BearerConfig(long lcChannelId, NR_RLC_Config_PR rlc_conf, long priority, const nr_rlc_configuration_t *default_rlc_config); - +void update_cellGroupConfig_for_BWP_switch(NR_CellGroupConfig_t *cellGroupConfig, + const nr_mac_config_t *configuration, + const NR_UE_NR_Capability_t *uecap, + const NR_ServingCellConfigCommon_t *scc, + int uid, + int old_bwp, + int new_bwp); NR_MeasurementTimingConfiguration_t *get_nr_mtc(uint8_t *buf, uint32_t len); measgap_config_t create_measgap_config(const NR_MeasurementTimingConfiguration_t *mtc, int scs, int min_rxtxtime); int encode_measgap_config(const measgap_config_t *c, uint8_t *buf); From 45792da029d34a7d29cc4bed9bbd7a8a3e212b38 Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 25 Aug 2025 12:25:55 +0200 Subject: [PATCH 609/964] include missing harq information in phy-sim nr_mac_config_t initialization --- openair1/SIMULATION/NR_PHY/dlsim.c | 2 ++ openair1/SIMULATION/NR_PHY/ulsim.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index 828ff176ec..b44c3b3e50 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -701,6 +701,8 @@ printf("%d\n", slot); .minRXTXTIME = 6, .do_CSIRS = 0, .do_SRS = 0, + .num_dlharq = 16, + .num_ulharq = 16, .maxMIMO_layers = g_nrOfLayers, .force_256qam_off = false, .timer_config.sr_ProhibitTimer = 0, diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index 647456d8d6..e94b12408d 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -658,6 +658,8 @@ int main(int argc, char *argv[]) .minRXTXTIME = 0, .do_CSIRS = 0, .do_SRS = 0, + .num_dlharq = 16, + .num_ulharq = 16, .force_256qam_off = false, .timer_config.sr_ProhibitTimer = 0, .timer_config.sr_TransMax = 64, From ce1ddb260be0340ff80120b755c9e41bf3c7d7ef Mon Sep 17 00:00:00 2001 From: francescomani Date: Wed, 27 Aug 2025 15:49:38 +0200 Subject: [PATCH 610/964] bugfix in BWP release at UE --- openair2/LAYER2/NR_MAC_UE/config_ue.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index d764f7cb86..bb37c3d582 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -2680,8 +2680,8 @@ static void configure_BWPs(NR_UE_MAC_INST_t *mac, NR_ServingCellConfig_t *scd) if (scd->downlinkBWP_ToReleaseList) { for (int i = 0; i < scd->downlinkBWP_ToReleaseList->list.count; i++) { for (int j = 0; j < mac->dl_BWPs.count; j++) { - if (*scd->downlinkBWP_ToReleaseList->list.array[i] == mac->dl_BWPs.array[i]->bwp_id) - release_dl_BWP(mac, i); + if (*scd->downlinkBWP_ToReleaseList->list.array[i] == mac->dl_BWPs.array[j]->bwp_id) + release_dl_BWP(mac, j); } } } @@ -2702,8 +2702,8 @@ static void configure_BWPs(NR_UE_MAC_INST_t *mac, NR_ServingCellConfig_t *scd) if (scd->uplinkConfig->uplinkBWP_ToReleaseList) { for (int i = 0; i < scd->uplinkConfig->uplinkBWP_ToReleaseList->list.count; i++) { for (int j = 0; j < mac->ul_BWPs.count; j++) { - if (*scd->uplinkConfig->uplinkBWP_ToReleaseList->list.array[i] == mac->ul_BWPs.array[i]->bwp_id) - release_ul_BWP(mac, i); + if (*scd->uplinkConfig->uplinkBWP_ToReleaseList->list.array[i] == mac->ul_BWPs.array[j]->bwp_id) + release_ul_BWP(mac, j); } } } From 8d872f2f7d46b7aef244aa1356d2175f8820b023 Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 2 Sep 2025 12:12:20 +0200 Subject: [PATCH 611/964] clone cellGroup for BWP switch to avoid removing BWP currently in use from gNB list --- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 66 +++++++++++-------- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 2 +- openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c | 25 +++++-- openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h | 14 ++-- 4 files changed, 65 insertions(+), 42 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index e576445e45..b047cdd4ee 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -3441,26 +3441,8 @@ void nr_measgap_scheduling(gNB_MAC_INST *nr_mac, frame_t frame, sub_frame_t slot } } -void nr_mac_clean_cellgroup(NR_CellGroupConfig_t *cell_group) +void clean_bwp_structures(NR_SpCellConfig_t *spCellConfig) { - DevAssert(cell_group != NULL); - NR_SpCellConfig_t *spCellConfig = cell_group->spCellConfig; - /* remove a reconfigurationWithSync, we don't need it anymore */ - if (spCellConfig && spCellConfig->reconfigurationWithSync != NULL) { - ASN_STRUCT_FREE(asn_DEF_NR_ReconfigurationWithSync, spCellConfig->reconfigurationWithSync); - spCellConfig->reconfigurationWithSync = NULL; - } - /* remove the rlc_BearerToReleaseList, we don't need it anymore */ - if (cell_group->rlc_BearerToReleaseList != NULL) { - struct NR_CellGroupConfig__rlc_BearerToReleaseList *l = cell_group->rlc_BearerToReleaseList; - asn_sequence_del(&l->list, l->list.count, /* free */ 1); - free(cell_group->rlc_BearerToReleaseList); - cell_group->rlc_BearerToReleaseList = NULL; - } - /* remove reestablishRLC, we don't need it anymore */ - for (int i = 0; i < cell_group->rlc_BearerToAddModList->list.count; ++i) - free_and_zero(cell_group->rlc_BearerToAddModList->list.array[i]->reestablishRLC); - /* clean BWP structures */ NR_ServingCellConfig_t *spCellConfigDedicated = spCellConfig->spCellConfigDedicated; if (spCellConfigDedicated->downlinkBWP_ToReleaseList) { struct NR_ServingCellConfig__downlinkBWP_ToReleaseList *rel_dl = spCellConfigDedicated->downlinkBWP_ToReleaseList; @@ -3504,6 +3486,29 @@ void nr_mac_clean_cellgroup(NR_CellGroupConfig_t *cell_group) } } +void nr_mac_clean_cellgroup(NR_CellGroupConfig_t *cell_group) +{ + DevAssert(cell_group != NULL); + NR_SpCellConfig_t *spCellConfig = cell_group->spCellConfig; + /* remove a reconfigurationWithSync, we don't need it anymore */ + if (spCellConfig && spCellConfig->reconfigurationWithSync != NULL) { + ASN_STRUCT_FREE(asn_DEF_NR_ReconfigurationWithSync, spCellConfig->reconfigurationWithSync); + spCellConfig->reconfigurationWithSync = NULL; + } + /* remove the rlc_BearerToReleaseList, we don't need it anymore */ + if (cell_group->rlc_BearerToReleaseList != NULL) { + struct NR_CellGroupConfig__rlc_BearerToReleaseList *l = cell_group->rlc_BearerToReleaseList; + asn_sequence_del(&l->list, l->list.count, /* free */ 1); + free(cell_group->rlc_BearerToReleaseList); + cell_group->rlc_BearerToReleaseList = NULL; + } + /* remove reestablishRLC, we don't need it anymore */ + for (int i = 0; i < cell_group->rlc_BearerToAddModList->list.count; ++i) + free_and_zero(cell_group->rlc_BearerToAddModList->list.array[i]->reestablishRLC); + /* clean BWP structures */ + clean_bwp_structures(spCellConfig); +} + int nr_mac_get_reconfig_delay_slots(NR_SubcarrierSpacing_t scs) { /* we previously assumed a specific "slot ahead" value for the PHY processing @@ -3886,21 +3891,26 @@ bool nr_mac_check_ul_failure(gNB_MAC_INST *nrmac, int rnti, NR_UE_sched_ctrl_t * void nr_mac_trigger_reconfiguration(const gNB_MAC_INST *nrmac, const NR_UE_info_t *UE, int new_bwp_id) { DevAssert(UE->CellGroup != NULL); + NR_CellGroupConfig_t *cellGroup_for_UE = NULL; if (new_bwp_id >= 0) { AssertFatal(UE->current_DL_BWP.bwp_id == UE->current_UL_BWP.bwp_id, "We only support same BWP for UL and DL\n"); if (new_bwp_id == UE->current_DL_BWP.bwp_id) LOG_E(NR_MAC, "Source BWP ID and target BWP ID are the same, can't perform switch\n"); else - update_cellGroupConfig_for_BWP_switch(UE->CellGroup, - &nrmac->radio_config, - UE->capability, - nrmac->common_channels[0].ServingCellConfigCommon, - UE->uid, - UE->current_DL_BWP.bwp_id, - new_bwp_id); + cellGroup_for_UE = update_cellGroupConfig_for_BWP_switch(UE->CellGroup, + &nrmac->radio_config, + UE->capability, + nrmac->common_channels[0].ServingCellConfigCommon, + UE->uid, + UE->current_DL_BWP.bwp_id, + new_bwp_id); } uint8_t buf[2048]; - asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_CellGroupConfig, NULL, UE->CellGroup, buf, sizeof(buf)); + asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_CellGroupConfig, + NULL, + cellGroup_for_UE ? cellGroup_for_UE : UE->CellGroup, + buf, + sizeof(buf)); AssertFatal(enc_rval.encoded > 0, "ASN1 encoding of CellGroupConfig failed, failed type %s\n", enc_rval.failed_type->name); du_to_cu_rrc_information_t du2cu = { .cellGroupConfig = buf, @@ -3915,6 +3925,8 @@ void nr_mac_trigger_reconfiguration(const gNB_MAC_INST *nrmac, const NR_UE_info_ .cause_value = F1AP_CauseRadioNetwork_action_desirable_for_radio_reasons, }; nrmac->mac_rrc.ue_context_modification_required(&required); + if (cellGroup_for_UE) + free_cellGroupConfig(cellGroup_for_UE); } /* \brief add bearers from CellGroupConfig. diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 7ea9a831f9..bed6b8a1ad 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -476,7 +476,7 @@ bool nr_mac_check_release(NR_UE_sched_ctrl_t *sched_ctrl, int rnti); void nr_mac_trigger_release_complete(gNB_MAC_INST *mac, int rnti); void nr_mac_release_ue(gNB_MAC_INST *mac, int rnti); bool nr_mac_request_release_ue(const gNB_MAC_INST *nrmac, int rnti); - +void clean_bwp_structures(NR_SpCellConfig_t *spCellConfig); void nr_mac_trigger_ul_failure(NR_UE_sched_ctrl_t *sched_ctrl, NR_SubcarrierSpacing_t subcarrier_spacing); void nr_mac_reset_ul_failure(NR_UE_sched_ctrl_t *sched_ctrl); bool nr_mac_check_ul_failure(gNB_MAC_INST *nrmac, int rnti, NR_UE_sched_ctrl_t *sched_ctrl); diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c index a48171aff8..c3e9225b4e 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c @@ -3683,13 +3683,13 @@ static long set_ul_max_layers(const nr_mac_config_t *configuration, const NR_UE_ return ul_max_layers; } -void update_cellGroupConfig_for_BWP_switch(NR_CellGroupConfig_t *cellGroupConfig, - const nr_mac_config_t *configuration, - const NR_UE_NR_Capability_t *uecap, - const NR_ServingCellConfigCommon_t *scc, - int uid, - int old_bwp, - int new_bwp) +NR_CellGroupConfig_t * update_cellGroupConfig_for_BWP_switch(NR_CellGroupConfig_t *cellGroupConfig, + const nr_mac_config_t *configuration, + const NR_UE_NR_Capability_t *uecap, + const NR_ServingCellConfigCommon_t *scc, + int uid, + int old_bwp, + int new_bwp) { NR_SpCellConfig_t *spCellConfig = cellGroupConfig->spCellConfig; NR_ServingCellConfig_t *configDedicated = spCellConfig->spCellConfigDedicated; @@ -3751,6 +3751,17 @@ void update_cellGroupConfig_for_BWP_switch(NR_CellGroupConfig_t *cellGroupConfig NR_BWP_Uplink_t *ul_bwp = config_uplinkBWP(new_bwp - 1, true, uid, ul_maxMIMO_Layers, configuration, scc, uecap); asn1cSeqAdd(&uplinkConfig->uplinkBWP_ToAddModList->list, ul_bwp); } + + // we temporarily need to keep both the old and the new BWP in the CG used by the gNB + // while removing the old from the CG sent to the UE + if (old_bwp > 0) { + NR_CellGroupConfig_t *clone_cg = NULL; + const int copy_result = asn_copy(&asn_DEF_NR_CellGroupConfig, (void **)&clone_cg, cellGroupConfig); + AssertFatal(copy_result == 0, "unable to copy NR_CellGroupConfig for cloning\n"); + clean_bwp_structures(clone_cg->spCellConfig); + return clone_cg; + } + return NULL; } void update_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig, diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h index 44715dc66d..d5df69b3c6 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h @@ -121,13 +121,13 @@ NR_RLC_BearerConfig_t *get_DRB_RLC_BearerConfig(long lcChannelId, NR_RLC_Config_PR rlc_conf, long priority, const nr_rlc_configuration_t *default_rlc_config); -void update_cellGroupConfig_for_BWP_switch(NR_CellGroupConfig_t *cellGroupConfig, - const nr_mac_config_t *configuration, - const NR_UE_NR_Capability_t *uecap, - const NR_ServingCellConfigCommon_t *scc, - int uid, - int old_bwp, - int new_bwp); +NR_CellGroupConfig_t * update_cellGroupConfig_for_BWP_switch(NR_CellGroupConfig_t *cellGroupConfig, + const nr_mac_config_t *configuration, + const NR_UE_NR_Capability_t *uecap, + const NR_ServingCellConfigCommon_t *scc, + int uid, + int old_bwp, + int new_bwp); NR_MeasurementTimingConfiguration_t *get_nr_mtc(uint8_t *buf, uint32_t len); measgap_config_t create_measgap_config(const NR_MeasurementTimingConfiguration_t *mtc, int scs, int min_rxtxtime); int encode_measgap_config(const measgap_config_t *c, uint8_t *buf); From 18041e3c41ccc01830fddfa1bc51ee4d0a9a4702 Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 2 Sep 2025 14:50:57 +0200 Subject: [PATCH 612/964] common function to generate csi_MeasConfig (also used to get the correct CSI meas structure in case of BWP switch) --- openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c | 347 ++++++++----------- 1 file changed, 137 insertions(+), 210 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c index c3e9225b4e..015e5f6e02 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c @@ -3273,6 +3273,122 @@ static NR_BWP_DownlinkDedicated_t *configure_initial_dl_bwp(const NR_ServingCell return bwp_Dedicated; } +static NR_CSI_MeasConfig_t *get_csiMeasConfig(const NR_ServingCellConfig_t *configDedicated, + const NR_ServingCellConfigCommon_t *scc, + const nr_mac_config_t *configuration, + int uid, + int bwp_id, + uint64_t bitmap) +{ + NR_CSI_MeasConfig_t *csi_MeasConfig = calloc(1, sizeof(*csi_MeasConfig)); + csi_MeasConfig->csi_SSB_ResourceSetToAddModList = calloc(1, sizeof(*csi_MeasConfig->csi_SSB_ResourceSetToAddModList)); + csi_MeasConfig->csi_SSB_ResourceSetToReleaseList = NULL; + csi_MeasConfig->csi_ResourceConfigToAddModList = calloc(1, sizeof(*csi_MeasConfig->csi_ResourceConfigToAddModList)); + csi_MeasConfig->csi_ResourceConfigToReleaseList = NULL; + csi_MeasConfig->csi_ReportConfigToAddModList = calloc(1, sizeof(*csi_MeasConfig->csi_ReportConfigToAddModList)); + csi_MeasConfig->csi_ReportConfigToReleaseList = NULL; + + NR_CSI_SSB_ResourceSet_t *ssbresset0 = calloc(1, sizeof(*ssbresset0)); + ssbresset0->csi_SSB_ResourceSetId = 0; + + for (int i = 0; i < 64; i++) { + if ((bitmap >> (63 - i)) & 0x01) { + NR_SSB_Index_t *ssbres = NULL; + asn1cCallocOne(ssbres, i); + asn1cSeqAdd(&ssbresset0->csi_SSB_ResourceList.list, ssbres); + } + } + asn1cSeqAdd(&csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list, ssbresset0); + + int curr_bwp; + NR_SetupRelease_PDSCH_Config_t *pdsch_Config; + if (bwp_id == 0) { + pdsch_Config = configDedicated->initialDownlinkBWP->pdsch_Config; + curr_bwp = NRRIV2BW(scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + } else { + NR_BWP_Downlink_t *bwp = configDedicated->downlinkBWP_ToAddModList->list.array[0]; + pdsch_Config = bwp->bwp_Dedicated->pdsch_Config; + curr_bwp = NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + AssertFatal(bwp_id == bwp->bwp_Id, "BWP ID doesn't match\n"); + } + + const int pdsch_AntennaPorts = + configuration->pdsch_AntennaPorts.N1 * configuration->pdsch_AntennaPorts.N2 * configuration->pdsch_AntennaPorts.XP; + config_csirs(scc, csi_MeasConfig, pdsch_AntennaPorts, curr_bwp, configuration->do_CSIRS, bwp_id); + config_csiim(configuration->do_CSIRS, pdsch_AntennaPorts, curr_bwp, csi_MeasConfig, bwp_id); + + NR_CSI_ResourceConfig_t *csires1 = calloc(1, sizeof(*csires1)); + csires1->csi_ResourceConfigId = bwp_id + 20; + csires1->csi_RS_ResourceSetList.present = NR_CSI_ResourceConfig__csi_RS_ResourceSetList_PR_nzp_CSI_RS_SSB; + csires1->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB = + calloc(1, sizeof(*csires1->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB)); + csires1->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList = + calloc(1, sizeof(*csires1->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList)); + NR_CSI_SSB_ResourceSetId_t *ssbres00 = calloc(1, sizeof(*ssbres00)); + *ssbres00 = 0; + asn1cSeqAdd(&csires1->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList->list, ssbres00); + csires1->bwp_Id = bwp_id; + csires1->resourceType = NR_CSI_ResourceConfig__resourceType_periodic; + asn1cSeqAdd(&csi_MeasConfig->csi_ResourceConfigToAddModList->list, csires1); + + int pucch_Resource = 2; + if (configuration->do_CSIRS) { + NR_CSI_ResourceConfig_t *csires0 = calloc(1, sizeof(*csires0)); + csires0->csi_ResourceConfigId = bwp_id; + csires0->csi_RS_ResourceSetList.present = NR_CSI_ResourceConfig__csi_RS_ResourceSetList_PR_nzp_CSI_RS_SSB; + csires0->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB = + calloc(1, sizeof(*csires0->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB)); + csires0->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList = + calloc(1, sizeof(*csires0->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList)); + NR_NZP_CSI_RS_ResourceSetId_t *nzp0 = calloc(1, sizeof(*nzp0)); + *nzp0 = bwp_id; + asn1cSeqAdd(&csires0->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList->list, nzp0); + csires0->bwp_Id = bwp_id; + csires0->resourceType = NR_CSI_ResourceConfig__resourceType_periodic; + asn1cSeqAdd(&csi_MeasConfig->csi_ResourceConfigToAddModList->list, csires0); + } + + if (configuration->do_CSIRS && pdsch_AntennaPorts > 1) { + NR_CSI_ResourceConfig_t *csires2 = calloc(1, sizeof(*csires2)); + csires2->csi_ResourceConfigId = bwp_id + 10; + csires2->csi_RS_ResourceSetList.present = NR_CSI_ResourceConfig__csi_RS_ResourceSetList_PR_csi_IM_ResourceSetList; + csires2->csi_RS_ResourceSetList.choice.csi_IM_ResourceSetList = + calloc(1, sizeof(*csires2->csi_RS_ResourceSetList.choice.csi_IM_ResourceSetList)); + NR_CSI_IM_ResourceSetId_t *csiim00 = calloc(1, sizeof(*csiim00)); + *csiim00 = bwp_id; + asn1cSeqAdd(&csires2->csi_RS_ResourceSetList.choice.csi_IM_ResourceSetList->list, csiim00); + csires2->bwp_Id = bwp_id; + csires2->resourceType = NR_CSI_ResourceConfig__resourceType_periodic; + asn1cSeqAdd(&csi_MeasConfig->csi_ResourceConfigToAddModList->list, csires2); + + NR_PUCCH_CSI_Resource_t *pucchcsi = calloc(1, sizeof(*pucchcsi)); + pucchcsi->uplinkBandwidthPartId = bwp_id; + pucchcsi->pucch_Resource = pucch_Resource; + config_csi_meas_report(csi_MeasConfig, + scc, + pucchcsi, + pdsch_Config, + &configuration->pdsch_AntennaPorts, + *configDedicated->pdsch_ServingCellConfig->choice.setup->ext1->maxMIMO_Layers, + bwp_id, + uid, + curr_bwp); + } + NR_PUCCH_CSI_Resource_t *pucchrsrp = calloc(1, sizeof(*pucchrsrp)); + pucchrsrp->uplinkBandwidthPartId = bwp_id; + pucchrsrp->pucch_Resource = pucch_Resource; + config_rsrp_meas_report(csi_MeasConfig, + scc, + pucchrsrp, + configuration->do_CSIRS, + bwp_id + 10, + uid, + curr_bwp, + pdsch_AntennaPorts, + configuration->do_SINR); + return csi_MeasConfig; +} + static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid, const NR_ServingCellConfigCommon_t *scc, const nr_mac_config_t *configuration) @@ -3347,114 +3463,12 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid, configDedicated->csi_MeasConfig = calloc(1, sizeof(*configDedicated->csi_MeasConfig)); configDedicated->csi_MeasConfig->present = NR_SetupRelease_CSI_MeasConfig_PR_setup; - - NR_CSI_MeasConfig_t *csi_MeasConfig = calloc(1, sizeof(*csi_MeasConfig)); - configDedicated->csi_MeasConfig->choice.setup = csi_MeasConfig; - - csi_MeasConfig->csi_SSB_ResourceSetToAddModList = calloc(1, sizeof(*csi_MeasConfig->csi_SSB_ResourceSetToAddModList)); - csi_MeasConfig->csi_SSB_ResourceSetToReleaseList = NULL; - csi_MeasConfig->csi_ResourceConfigToAddModList = calloc(1, sizeof(*csi_MeasConfig->csi_ResourceConfigToAddModList)); - csi_MeasConfig->csi_ResourceConfigToReleaseList = NULL; - csi_MeasConfig->csi_ReportConfigToAddModList = calloc(1, sizeof(*csi_MeasConfig->csi_ReportConfigToAddModList)); - csi_MeasConfig->csi_ReportConfigToReleaseList = NULL; - - NR_CSI_SSB_ResourceSet_t *ssbresset0 = calloc(1, sizeof(*ssbresset0)); - ssbresset0->csi_SSB_ResourceSetId = 0; - - for (int i = 0; i < 64; i++) { - if ((bitmap >> (63 - i)) & 0x01) { - NR_SSB_Index_t *ssbres = NULL; - asn1cCallocOne(ssbres, i); - asn1cSeqAdd(&ssbresset0->csi_SSB_ResourceList.list, ssbres); - } - } - asn1cSeqAdd(&csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list, ssbresset0); - - int curr_bwp, bwp_id; - NR_SetupRelease_PDSCH_Config_t *pdsch_Config; - if (first_active_bwp == 0) { - pdsch_Config = configDedicated->initialDownlinkBWP->pdsch_Config; - curr_bwp = NRRIV2BW(scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); - bwp_id = 0; - } else { - NR_BWP_Downlink_t *bwp = configDedicated->downlinkBWP_ToAddModList->list.array[0]; - pdsch_Config = bwp->bwp_Dedicated->pdsch_Config; - curr_bwp = NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); - bwp_id = bwp->bwp_Id; - } - - config_csirs(scc, csi_MeasConfig, pdsch_AntennaPorts, curr_bwp, configuration->do_CSIRS, first_active_bwp); - config_csiim(configuration->do_CSIRS, pdsch_AntennaPorts, curr_bwp, csi_MeasConfig, first_active_bwp); - - NR_CSI_ResourceConfig_t *csires1 = calloc(1, sizeof(*csires1)); - csires1->csi_ResourceConfigId = bwp_id + 20; - csires1->csi_RS_ResourceSetList.present = NR_CSI_ResourceConfig__csi_RS_ResourceSetList_PR_nzp_CSI_RS_SSB; - csires1->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB = - calloc(1, sizeof(*csires1->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB)); - csires1->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList = - calloc(1, sizeof(*csires1->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList)); - NR_CSI_SSB_ResourceSetId_t *ssbres00 = calloc(1, sizeof(*ssbres00)); - *ssbres00 = 0; - asn1cSeqAdd(&csires1->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList->list, ssbres00); - csires1->bwp_Id = bwp_id; - csires1->resourceType = NR_CSI_ResourceConfig__resourceType_periodic; - asn1cSeqAdd(&csi_MeasConfig->csi_ResourceConfigToAddModList->list, csires1); - - int pucch_Resource = 2; - if (configuration->do_CSIRS) { - NR_CSI_ResourceConfig_t *csires0 = calloc(1, sizeof(*csires0)); - csires0->csi_ResourceConfigId = bwp_id; - csires0->csi_RS_ResourceSetList.present = NR_CSI_ResourceConfig__csi_RS_ResourceSetList_PR_nzp_CSI_RS_SSB; - csires0->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB = - calloc(1, sizeof(*csires0->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB)); - csires0->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList = - calloc(1, sizeof(*csires0->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList)); - NR_NZP_CSI_RS_ResourceSetId_t *nzp0 = calloc(1, sizeof(*nzp0)); - *nzp0 = first_active_bwp; - asn1cSeqAdd(&csires0->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList->list, nzp0); - csires0->bwp_Id = bwp_id; - csires0->resourceType = NR_CSI_ResourceConfig__resourceType_periodic; - asn1cSeqAdd(&csi_MeasConfig->csi_ResourceConfigToAddModList->list, csires0); - } - - if (configuration->do_CSIRS && pdsch_AntennaPorts > 1) { - NR_CSI_ResourceConfig_t *csires2 = calloc(1, sizeof(*csires2)); - csires2->csi_ResourceConfigId = bwp_id + 10; - csires2->csi_RS_ResourceSetList.present = NR_CSI_ResourceConfig__csi_RS_ResourceSetList_PR_csi_IM_ResourceSetList; - csires2->csi_RS_ResourceSetList.choice.csi_IM_ResourceSetList = - calloc(1, sizeof(*csires2->csi_RS_ResourceSetList.choice.csi_IM_ResourceSetList)); - NR_CSI_IM_ResourceSetId_t *csiim00 = calloc(1, sizeof(*csiim00)); - *csiim00 = first_active_bwp; - asn1cSeqAdd(&csires2->csi_RS_ResourceSetList.choice.csi_IM_ResourceSetList->list, csiim00); - csires2->bwp_Id = bwp_id; - csires2->resourceType = NR_CSI_ResourceConfig__resourceType_periodic; - asn1cSeqAdd(&csi_MeasConfig->csi_ResourceConfigToAddModList->list, csires2); - - NR_PUCCH_CSI_Resource_t *pucchcsi = calloc(1, sizeof(*pucchcsi)); - pucchcsi->uplinkBandwidthPartId = bwp_id; - pucchcsi->pucch_Resource = pucch_Resource; - config_csi_meas_report(csi_MeasConfig, - scc, - pucchcsi, - pdsch_Config, - &configuration->pdsch_AntennaPorts, - *pdsch_servingcellconfig->ext1->maxMIMO_Layers, - bwp_id, - uid, - curr_bwp); - } - NR_PUCCH_CSI_Resource_t *pucchrsrp = calloc(1, sizeof(*pucchrsrp)); - pucchrsrp->uplinkBandwidthPartId = bwp_id; - pucchrsrp->pucch_Resource = pucch_Resource; - config_rsrp_meas_report(csi_MeasConfig, - scc, - pucchrsrp, - configuration->do_CSIRS, - bwp_id + 10, - uid, - curr_bwp, - pdsch_AntennaPorts, - configuration->do_SINR); + configDedicated->csi_MeasConfig->choice.setup = get_csiMeasConfig(configDedicated, + scc, + configuration, + uid, + first_active_bwp, + bitmap); fill_harq_IEs(configDedicated, configuration->num_dlharq, configuration->num_ulharq, first_active_bwp); SpCellConfig->spCellConfigDedicated = configDedicated; @@ -3723,11 +3737,11 @@ NR_CellGroupConfig_t * update_cellGroupConfig_for_BWP_switch(NR_CellGroupConfig_ uplinkConfig->uplinkBWP_ToReleaseList->list.count); } + uint64_t bitmap = get_ssb_bitmap(scc); const int pdsch_AntennaPorts = configuration->pdsch_AntennaPorts.N1 * configuration->pdsch_AntennaPorts.N2 * configuration->pdsch_AntennaPorts.XP; // add new BWP if (new_bwp == 0) { - uint64_t bitmap = get_ssb_bitmap(scc); if (!configDedicated->initialDownlinkBWP) configDedicated->initialDownlinkBWP = calloc_or_fail(1, sizeof(*configDedicated->initialDownlinkBWP)); if (!uplinkConfig->initialUplinkBWP) @@ -3752,6 +3766,14 @@ NR_CellGroupConfig_t * update_cellGroupConfig_for_BWP_switch(NR_CellGroupConfig_ asn1cSeqAdd(&uplinkConfig->uplinkBWP_ToAddModList->list, ul_bwp); } + ASN_STRUCT_FREE(asn_DEF_NR_CSI_MeasConfig, configDedicated->csi_MeasConfig->choice.setup); + configDedicated->csi_MeasConfig->choice.setup = get_csiMeasConfig(configDedicated, + scc, + configuration, + uid, + new_bwp, + bitmap); + // we temporarily need to keep both the old and the new BWP in the CG used by the gNB // while removing the old from the CG sent to the UE if (old_bwp > 0) { @@ -3899,8 +3921,6 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC { const nr_pdsch_AntennaPorts_t *pdschap = &configuration->pdsch_AntennaPorts; const int dl_antenna_ports = pdschap->N1 * pdschap->N2 * pdschap->XP; - const int do_csirs = configuration->do_CSIRS; - AssertFatal(servingcellconfigcommon, "servingcellconfigcommon is null\n"); if (uecap == NULL) @@ -4062,106 +4082,13 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC configDedicated->csi_MeasConfig = NULL; configDedicated->csi_MeasConfig = calloc(1, sizeof(*configDedicated->csi_MeasConfig)); configDedicated->csi_MeasConfig->present = NR_SetupRelease_CSI_MeasConfig_PR_setup; + configDedicated->csi_MeasConfig->choice.setup = get_csiMeasConfig(configDedicated, + servingcellconfigcommon, + configuration, + uid, + firstActiveUplinkBWP_Id, + bitmap); - NR_CSI_MeasConfig_t *csi_MeasConfig = calloc(1, sizeof(*csi_MeasConfig)); - configDedicated->csi_MeasConfig->choice.setup = csi_MeasConfig; - - csi_MeasConfig->csi_ResourceConfigToAddModList = calloc(1, sizeof(*csi_MeasConfig->csi_ResourceConfigToAddModList)); - csi_MeasConfig->csi_ResourceConfigToReleaseList = NULL; - - csi_MeasConfig->csi_SSB_ResourceSetToAddModList = calloc(1, sizeof(*csi_MeasConfig->csi_SSB_ResourceSetToAddModList)); - csi_MeasConfig->csi_SSB_ResourceSetToReleaseList = NULL; - - csi_MeasConfig->csi_ReportConfigToAddModList = calloc(1, sizeof(*csi_MeasConfig->csi_ReportConfigToAddModList)); - csi_MeasConfig->csi_ReportConfigToReleaseList = NULL; - - NR_CSI_SSB_ResourceSet_t *ssbresset0 = calloc(1, sizeof(*ssbresset0)); - ssbresset0->csi_SSB_ResourceSetId = 0; - - for (int i = 0; i < 64; i++) { - if ((bitmap >> (63 - i)) & 0x01) { - NR_SSB_Index_t *ssbres = NULL; - asn1cCallocOne(ssbres, i); - asn1cSeqAdd(&ssbresset0->csi_SSB_ResourceList.list, ssbres); - } - } - asn1cSeqAdd(&csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list, ssbresset0); - - for (int bwp_loop = 0; bwp_loop < n_dl_bwp; bwp_loop++) { - NR_BWP_Downlink_t *bwp = configDedicated->downlinkBWP_ToAddModList->list.array[bwp_loop]; - int curr_bwp = NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); - - config_csirs(servingcellconfigcommon, csi_MeasConfig, dl_antenna_ports, curr_bwp, do_csirs, bwp_loop); - config_csiim(do_csirs, dl_antenna_ports, curr_bwp, csi_MeasConfig, bwp_loop); - - if (do_csirs) { - NR_CSI_ResourceConfig_t *csires = calloc(1, sizeof(*csires)); - csires->csi_ResourceConfigId = bwp->bwp_Id; - csires->csi_RS_ResourceSetList.present = NR_CSI_ResourceConfig__csi_RS_ResourceSetList_PR_nzp_CSI_RS_SSB; - csires->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB = - calloc(1, sizeof(*csires->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB)); - csires->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList = - calloc(1, sizeof(*csires->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList)); - NR_NZP_CSI_RS_ResourceSetId_t *nzp0 = calloc(1, sizeof(*nzp0)); - *nzp0 = bwp_loop; - asn1cSeqAdd(&csires->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList->list, nzp0); - csires->bwp_Id = bwp->bwp_Id; - csires->resourceType = NR_CSI_ResourceConfig__resourceType_periodic; - asn1cSeqAdd(&csi_MeasConfig->csi_ResourceConfigToAddModList->list, csires); - } - if (do_csirs && dl_antenna_ports > 1) { - NR_CSI_ResourceConfig_t *csiresim = calloc(1, sizeof(*csiresim)); - csiresim->csi_ResourceConfigId = bwp->bwp_Id + 10; - csiresim->csi_RS_ResourceSetList.present = NR_CSI_ResourceConfig__csi_RS_ResourceSetList_PR_csi_IM_ResourceSetList; - csiresim->csi_RS_ResourceSetList.choice.csi_IM_ResourceSetList = - calloc(1, sizeof(*csiresim->csi_RS_ResourceSetList.choice.csi_IM_ResourceSetList)); - NR_CSI_IM_ResourceSetId_t *csiim00 = calloc(1, sizeof(*csiim00)); - *csiim00 = bwp_loop; - asn1cSeqAdd(&csiresim->csi_RS_ResourceSetList.choice.csi_IM_ResourceSetList->list, csiim00); - csiresim->bwp_Id = bwp->bwp_Id; - csiresim->resourceType = NR_CSI_ResourceConfig__resourceType_periodic; - asn1cSeqAdd(&csi_MeasConfig->csi_ResourceConfigToAddModList->list, csiresim); - } - NR_CSI_ResourceConfig_t *ssbres = calloc(1, sizeof(*ssbres)); - ssbres->csi_ResourceConfigId = bwp->bwp_Id + 20; - ssbres->csi_RS_ResourceSetList.present = NR_CSI_ResourceConfig__csi_RS_ResourceSetList_PR_nzp_CSI_RS_SSB; - ssbres->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB = calloc(1, sizeof(*ssbres->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB)); - ssbres->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList = - calloc(1, sizeof(*ssbres->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList)); - NR_CSI_SSB_ResourceSetId_t *ssbres00 = calloc(1, sizeof(*ssbres00)); - *ssbres00 = 0; - asn1cSeqAdd(&ssbres->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList->list, ssbres00); - ssbres->bwp_Id = bwp->bwp_Id; - ssbres->resourceType = NR_CSI_ResourceConfig__resourceType_periodic; - asn1cSeqAdd(&csi_MeasConfig->csi_ResourceConfigToAddModList->list, ssbres); - - NR_PUCCH_CSI_Resource_t *pucchcsires1 = calloc(1, sizeof(*pucchcsires1)); - pucchcsires1->uplinkBandwidthPartId = bwp->bwp_Id; - pucchcsires1->pucch_Resource = 2; - config_csi_meas_report(csi_MeasConfig, - servingcellconfigcommon, - pucchcsires1, - bwp->bwp_Dedicated->pdsch_Config, - pdschap, - *pdsch_servingcellconfig->ext1->maxMIMO_Layers, - bwp->bwp_Id, - uid, - curr_bwp); - // this is the same resource as pucchcsires1, but duplicated to avoid - // double free when releasing the CellGroupConfig - NR_PUCCH_CSI_Resource_t *pucchcsires2 = calloc(1, sizeof(*pucchcsires2)); - pucchcsires2->uplinkBandwidthPartId = bwp->bwp_Id; - pucchcsires2->pucch_Resource = 2; - config_rsrp_meas_report(csi_MeasConfig, - servingcellconfigcommon, - pucchcsires2, - do_csirs, - bwp->bwp_Id + 10, - uid, - curr_bwp, - dl_antenna_ports, - configuration->do_SINR); - } configDedicated->sCellDeactivationTimer = NULL; configDedicated->crossCarrierSchedulingConfig = NULL; configDedicated->tag_Id = 0; From 4e4f27c79dcf3e82c0c6a63b5bf1b1af3b35d569 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 22 Aug 2025 15:57:29 +0200 Subject: [PATCH 613/964] Fix: only create mixed slot UL TDU for more than 1 symbol For PUSCH, we need at least 2 symbols, so ensure when creating the TDA. --- openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c index 5fba6dcaaf..eeb317ae57 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c @@ -1115,7 +1115,6 @@ void nr_rrc_config_ul_tda(NR_ServingCellConfigCommon_t *scc, int min_fb_delay, i int N_dl1 = p1->nrofDownlinkSlots; int N_ul1 = p1->nrofUplinkSlots; - int N_dl2 = p2 ? p2->nrofDownlinkSlots : 0; int N_ul2 = p2 ? p2->nrofUplinkSlots : 0; int tdd_period_idx = get_tdd_period_idx(scc->tdd_UL_DL_ConfigurationCommon); int nb_periods_per_frame = get_nb_periods_per_frame(tdd_period_idx); @@ -1123,20 +1122,22 @@ void nr_rrc_config_ul_tda(NR_ServingCellConfigCommon_t *scc, int min_fb_delay, i // make TDA for the mixed slot long mixed_sliv = get_SLIV(NR_NUMBER_OF_SYMBOLS_PER_SLOT - ul_symb, ul_symb - 1); - if (ul_symb > 1 && (k2 <= N_dl1 || (p2 && N_ul2 == 0))) { + int mixed_min_ul_symb = 3; // need at least two symbols PUSCH + PUCCH + bool has_ul_mixed = ul_symb >= mixed_min_ul_symb; + if (has_ul_mixed && (k2 <= N_dl1 || (p2 && N_ul2 == 0))) { // UL TDA index 2 for mixed slot (TDD) (no pattern 2 and enough DL slots, or pattern2 only DL) tda = set_TimeDomainResourceAllocation(k2, mixed_sliv); // to be reached from suitable DL slot asn1cSeqAdd(&tda_list->list, tda); - } else if (ul_symb > 1 && !p2 && k2 > N_dl1) { // k2 > N_Dl1 + } else if (has_ul_mixed && !p2 && k2 > N_dl1) { // k2 > N_Dl1 // UL TDA for mixed slot without pattern 2 and less DL slots than k2 tda = set_TimeDomainResourceAllocation(nb_slots_per_period, mixed_sliv); // to be reached from last DL (mixed) slot, if any asn1cSeqAdd(&tda_list->list, tda); - } else if (ul_symb > 1 && N_ul2 > 0 && k2 > N_dl1) { + } else if (has_ul_mixed && N_ul2 > 0 && k2 > N_dl1) { // we have pattern 2 with UL, and less p1 DL slots than k2 tda = set_TimeDomainResourceAllocation(N_dl1 + N_ul2 + 1, mixed_sliv); asn1cSeqAdd(&tda_list->list, tda); } else { - AssertFatal(ul_symb == 0, "unhandled case of mixed slot: N_dl1 %d N_ul1 %d N_dl2 %d N_ul2 %d\n", N_dl1, N_ul1, N_dl2, N_ul2); + LOG_I(NR_RRC, "mixed slot has %d UL symbols, cannot create mixed slot TDA\n", ul_symb); } // make TDA for UL slots that are not reachable within k2/min_rxtxtime From 454f690272b7be1b038e6cf8ba0ecbb376de3c83 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 3 Sep 2025 17:57:27 +0200 Subject: [PATCH 614/964] UL TDA for SRS: set correct right k2 We need to set the different k2 values according to the number of UL slots, not all to the same k2. --- openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c index eeb317ae57..435ec2b6e8 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c @@ -1150,7 +1150,7 @@ void nr_rrc_config_ul_tda(NR_ServingCellConfigCommon_t *scc, int min_fb_delay, i tda = set_TimeDomainResourceAllocation(i, get_SLIV(0, 13)); asn1cSeqAdd(&tda_list->list, tda); if (do_SRS) { - tda = set_TimeDomainResourceAllocation(k2, get_SLIV(0, 12)); + tda = set_TimeDomainResourceAllocation(i, get_SLIV(0, 12)); asn1cSeqAdd(&tda_list->list, tda); } } From 11a561cb7b686df51107284c4da9484484fcc409 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 22 Aug 2025 15:57:48 +0200 Subject: [PATCH 615/964] Ensure that retransmission uses TDA as indicated Previously, the TDA reuse condition was wrong: for multiple TDAs with different k2, the symbol allocation might be the same, in which the previous logic was using the wrong TDA. Fix the condition, and insert an assert to ensure the allocated TDA is correct. --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index b08e703076..704d2017c7 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -1805,7 +1805,7 @@ static bool allocate_ul_retransmission(gNB_MAC_INST *nrmac, new_sched.bwp_info = bwp_info; DevAssert(new_sched.ul_harq_pid == harq_pid); - bool reuse_old_tda = (retInfo->tda_info.startSymbolIndex == tda_info->startSymbolIndex) && (retInfo->tda_info.nrOfSymbols <= tda_info->nrOfSymbols); + bool reuse_old_tda = retInfo->time_domain_allocation == tda; if (reuse_old_tda && nrOfLayers == retInfo->nrOfLayers) { /* Check the resource is enough for retransmission */ const uint16_t slbitmap = SL_to_bitmap(retInfo->tda_info.startSymbolIndex, retInfo->tda_info.nrOfSymbols); @@ -1887,6 +1887,7 @@ static bool allocate_ul_retransmission(gNB_MAC_INST *nrmac, fill_pdcch_vrb_map(nrmac, CC_id, &sched_ctrl->sched_pdcch, CCEIndex, sched_ctrl->aggregation_level, dci_beam_idx); // signal new allocation + DevAssert(new_sched.time_domain_allocation == tda); post_process_ulsch(nrmac, pp_pusch, UE, &new_sched); LOG_D(NR_MAC, "%4d.%2d Allocate UL retransmission RNTI %04x sched %4d.%2d (%d RBs)\n", From fd4de3c720b0a4cc491ed004d9589d7f6830ca7c Mon Sep 17 00:00:00 2001 From: rmagueta Date: Fri, 11 Apr 2025 18:31:00 +0100 Subject: [PATCH 616/964] Add support for band in neighbourConfiguration --- openair2/GNB_APP/gnb_config.c | 1 + openair2/GNB_APP/gnb_paramdef.h | 5 ++++- openair2/RRC/NR/MESSAGES/asn1_msg.c | 2 +- openair2/RRC/NR/nr_rrc_defs.h | 1 + 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 94e9012855..f04f491344 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -2057,6 +2057,7 @@ static void fill_neighbour_cell_configuration(uint8_t gnb_idx, gNB_RRC_INST *rrc neighbourCell.nrcell_id = (uint64_t) * (NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_NR_CELLID_IDX].u64ptr); neighbourCell.physicalCellId = *NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_PHYSICAL_ID_IDX].uptr; neighbourCell.subcarrierSpacing = *NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_SCS_IDX].uptr; + neighbourCell.band = *NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_BAND_IDX].uptr; neighbourCell.absoluteFrequencySSB = *NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_ABS_FREQ_SSB_IDX].i64ptr; neighbourCell.tac = *NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_TAC_IDX].uptr; diff --git a/openair2/GNB_APP/gnb_paramdef.h b/openair2/GNB_APP/gnb_paramdef.h index b751d78733..33f0d3cac9 100644 --- a/openair2/GNB_APP/gnb_paramdef.h +++ b/openair2/GNB_APP/gnb_paramdef.h @@ -308,6 +308,7 @@ typedef enum { #define GNB_CONFIG_STRING_NEIGHBOUR_CELL_PHYSICAL_ID "physical_cellId" #define GNB_CONFIG_STRING_NEIGHBOUR_CELL_ABS_FREQ_SSB "absoluteFrequencySSB" #define GNB_CONFIG_STRING_NEIGHBOUR_CELL_SCS "subcarrierSpacing" +#define GNB_CONFIG_STRING_NEIGHBOUR_CELL_BAND "band" #define GNB_CONFIG_STRING_NEIGHBOUR_TRACKING_ARE_CODE "tracking_area_code" #define GNB_CONFIG_STRING_NEIGHBOUR_PLMN "plmn" @@ -316,7 +317,8 @@ typedef enum { #define GNB_CONFIG_N_CELL_PHYSICAL_ID_IDX 2 #define GNB_CONFIG_N_CELL_ABS_FREQ_SSB_IDX 3 #define GNB_CONFIG_N_CELL_SCS_IDX 4 -#define GNB_CONFIG_N_CELL_TAC_IDX 5 +#define GNB_CONFIG_N_CELL_BAND_IDX 5 +#define GNB_CONFIG_N_CELL_TAC_IDX 6 // clang-format off #define GNBNEIGHBOURCELLPARAMS_DESC { \ /* optname helpstr paramflags XXXptr def val type numelt */ \ @@ -325,6 +327,7 @@ typedef enum { {GNB_CONFIG_STRING_NEIGHBOUR_CELL_PHYSICAL_ID, "neighbour cell physical id", PARAMFLAG_MANDATORY, .uptr=NULL, .defuintval=0, TYPE_UINT, 0}, \ {GNB_CONFIG_STRING_NEIGHBOUR_CELL_ABS_FREQ_SSB, "neighbour cell abs freq ssb", PARAMFLAG_MANDATORY, .i64ptr=NULL, .defint64val=0, TYPE_INT64, 0}, \ {GNB_CONFIG_STRING_NEIGHBOUR_CELL_SCS, "neighbour cell scs", PARAMFLAG_MANDATORY, .uptr=NULL, .defuintval=0, TYPE_UINT, 0}, \ + {GNB_CONFIG_STRING_NEIGHBOUR_CELL_BAND, "neighbour cell band", PARAMFLAG_MANDATORY, .uptr=NULL, .defuintval=78, TYPE_UINT, 0}, \ {GNB_CONFIG_STRING_NEIGHBOUR_TRACKING_ARE_CODE, "neighbour cell tracking area", PARAMFLAG_MANDATORY, .uptr=NULL, .defuintval=0, TYPE_UINT, 0}, \ } // clang-format on diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.c b/openair2/RRC/NR/MESSAGES/asn1_msg.c index c016e4c899..e6816bfcbd 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.c +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.c @@ -1048,7 +1048,7 @@ NR_MeasConfig_t *get_MeasConfig(const NR_MeasTiming_t *mt, if (neigh_seq) { int mo_id = 2; FOR_EACH_SEQ_ARR(nr_neighbour_cell_t *, neigh_cell, neigh_seq) { - NR_MeasObjectToAddMod_t *mo_neighbour = get_MeasObject(ft, band, neigh_cell->absoluteFrequencySSB, mo_id); + NR_MeasObjectToAddMod_t *mo_neighbour = get_MeasObject(ft, neigh_cell->band, neigh_cell->absoluteFrequencySSB, mo_id); NR_MeasObjectNR_t *monr = mo_neighbour->measObject.choice.measObjectNR; monr->cellsToAddModList = calloc_or_fail(1, sizeof(*monr->cellsToAddModList)); NR_CellsToAddMod_t *cell = calloc_or_fail(1, sizeof(*cell)); diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index 68a83c9545..f1d9acba7b 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -314,6 +314,7 @@ typedef struct { int physicalCellId; int absoluteFrequencySSB; int subcarrierSpacing; + int band; plmn_identity_t plmn; uint32_t tac; bool isIntraFrequencyNeighbour; From 3a734bc5d468fa97824b69c8c23281f329c57f42 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Sat, 6 Sep 2025 12:16:37 +0200 Subject: [PATCH 617/964] Replace ngap_plmn_identity_t with plmn_id_t and use proper size for TAI List for Paging Use platform type plmn_id_t to simplify the code. TAI List for Paging in NGAP PAGING message (9.2.4.1 3GPP TS 38.413) is limited to 16. --- openair2/COMMON/ngap_messages_types.h | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/openair2/COMMON/ngap_messages_types.h b/openair2/COMMON/ngap_messages_types.h index 635fd2345d..3ee858ecca 100644 --- a/openair2/COMMON/ngap_messages_types.h +++ b/openair2/COMMON/ngap_messages_types.h @@ -82,6 +82,8 @@ #define QOSFLOW_MAX_VALUE 64 +#define NGAP_MAX_NO_TAI_PAGING 16 // 9.2.4.1 3GPP TS 38.413 + /* Security key length used within gNB * Even if only 16 bytes will be effectively used, * the key length is 32 bytes (256 bits) @@ -206,12 +208,6 @@ typedef struct fiveg_s_tmsi_s { uint32_t m_tmsi; } fiveg_s_tmsi_t; -typedef struct ngap_tai_plmn_identity_s { - uint16_t mcc; - uint16_t mnc; - uint8_t mnc_digit_length; -} ngap_plmn_identity_t; - typedef struct ngap_ue_paging_identity_s { fiveg_s_tmsi_t s_tmsi; } ngap_ue_paging_identity_t; @@ -228,7 +224,7 @@ typedef struct ngap_ue_identity_s { } ngap_ue_identity_t; typedef struct ngap_mobility_restriction_s{ - ngap_plmn_identity_t serving_plmn; + plmn_id_t serving_plmn; }ngap_mobility_restriction_t; typedef enum pdusession_qosflow_mapping_ind_e{ @@ -600,10 +596,10 @@ typedef struct ngap_paging_ind_s { ngap_cn_domain_t cn_domain; /* PLMN_identity in TAI of Paging*/ - ngap_plmn_identity_t plmn_identity[256]; + plmn_id_t plmn_identity[NGAP_MAX_NO_TAI_PAGING]; /* TAC in TAIList of Paging*/ - int16_t tac[256]; + int16_t tac[NGAP_MAX_NO_TAI_PAGING]; /* size of TAIList*/ int16_t tai_size; From 4d96f4002331d6341f90b1486ebd0afd44289287 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Thu, 4 Sep 2025 17:14:01 +0200 Subject: [PATCH 618/964] Fix PLMN prints in NGAP/RRC Also, replace NGAP_X with LOG_X to avoid false-positive format warnings in clang. Closes #985 --- openair2/RRC/NR/rrc_gNB_NGAP.c | 31 +++++++----- openair3/NGAP/ngap_gNB_handlers.c | 9 +++- openair3/NGAP/ngap_gNB_nas_procedures.c | 65 ++++++++++++++----------- 3 files changed, 62 insertions(+), 43 deletions(-) diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index 240a591846..407a0d03b7 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -209,7 +209,8 @@ void rrc_gNB_send_NGAP_NAS_FIRST_REQ(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, NR_RRC } int selected_plmn_identity = rrcSetupComplete->selectedPLMN_Identity - 1; // Convert 1-based PLMN Identity IE to 0-based index req->plmn = rrc->configuration.plmn[selected_plmn_identity]; // Select from the stored list - LOG_I(NGAP, "Selected PLMN in the NG Initial UE Message: MCC %u, MNC %u\n", req->plmn.mcc, req->plmn.mnc); + plmn_id_t *p = &req->plmn; + LOG_I(NGAP, "Selected PLMN in the NG Initial UE Message: MCC=%03d MNC=%0*d\n", p->mcc, p->mnc_digit_length, p->mnc); /* 5G-S-TMSI */ if (UE->Initialue_identity_5g_s_TMSI.presence) { @@ -1261,25 +1262,29 @@ int rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND(MessageDef *msg_p, instance_ int rrc_gNB_process_PAGING_IND(MessageDef *msg_p, instance_t instance) { - for (uint16_t tai_size = 0; tai_size < NGAP_PAGING_IND(msg_p).tai_size; tai_size++) { - LOG_I(NR_RRC,"[gNB %ld] In NGAP_PAGING_IND: MCC %d, MNC %d, TAC %d\n", instance, NGAP_PAGING_IND(msg_p).plmn_identity[tai_size].mcc, - NGAP_PAGING_IND(msg_p).plmn_identity[tai_size].mnc, NGAP_PAGING_IND(msg_p).tac[tai_size]); + ngap_paging_ind_t *msg = &NGAP_PAGING_IND(msg_p); + for (uint16_t tai_size = 0; tai_size < msg->tai_size; tai_size++) { + plmn_id_t *p = &msg->plmn_identity[tai_size]; + LOG_I(NR_RRC, + "[gNB %ld] TAI List for Paging: MCC=%03d, MNC=%0*d, TAC=%d\n", + instance, + p->mcc, + p->mnc_digit_length, + p->mnc, + msg->tac[tai_size]); gNB_RrcConfigurationReq *req = &RC.nrrrc[instance]->configuration; for (uint8_t j = 0; j < req->num_plmn; j++) { - plmn_id_t *plmn = &req->plmn[j]; - if (plmn->mcc == NGAP_PAGING_IND(msg_p).plmn_identity[tai_size].mcc - && plmn->mnc == NGAP_PAGING_IND(msg_p).plmn_identity[tai_size].mnc && req->tac == NGAP_PAGING_IND(msg_p).tac[tai_size]) { + plmn_id_t *req_plmn = &req->plmn[j]; + if (req_plmn->mcc == p->mcc && req_plmn->mnc == p->mnc && req->tac == msg->tac[tai_size]) { for (uint8_t CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { AssertFatal(false, "to be implemented properly\n"); if (NODE_IS_CU(RC.nrrrc[instance]->node_type)) { MessageDef *m = itti_alloc_new_message(TASK_RRC_GNB, 0, F1AP_PAGING_IND); - F1AP_PAGING_IND(m).plmn.mcc = RC.nrrrc[j]->configuration.plmn[0].mcc; - F1AP_PAGING_IND(m).plmn.mnc = RC.nrrrc[j]->configuration.plmn[0].mnc; - F1AP_PAGING_IND(m).plmn.mnc_digit_length = RC.nrrrc[j]->configuration.plmn[0].mnc_digit_length; + F1AP_PAGING_IND(m).plmn = *req_plmn; F1AP_PAGING_IND (m).nr_cellid = RC.nrrrc[j]->nr_cellid; - F1AP_PAGING_IND (m).ueidentityindexvalue = (uint16_t)(NGAP_PAGING_IND(msg_p).ue_paging_identity.s_tmsi.m_tmsi%1024); - F1AP_PAGING_IND (m).fiveg_s_tmsi = NGAP_PAGING_IND(msg_p).ue_paging_identity.s_tmsi.m_tmsi; - F1AP_PAGING_IND (m).paging_drx = NGAP_PAGING_IND(msg_p).paging_drx; + F1AP_PAGING_IND(m).ueidentityindexvalue = (uint16_t)(msg->ue_paging_identity.s_tmsi.m_tmsi % 1024); + F1AP_PAGING_IND(m).fiveg_s_tmsi = msg->ue_paging_identity.s_tmsi.m_tmsi; + F1AP_PAGING_IND(m).paging_drx = msg->paging_drx; LOG_E(F1AP, "ueidentityindexvalue %u fiveg_s_tmsi %ld paging_drx %u\n", F1AP_PAGING_IND (m).ueidentityindexvalue, F1AP_PAGING_IND (m).fiveg_s_tmsi, F1AP_PAGING_IND (m).paging_drx); itti_send_msg_to_task(TASK_CU_F1, instance, m); } else { diff --git a/openair3/NGAP/ngap_gNB_handlers.c b/openair3/NGAP/ngap_gNB_handlers.c index b80902add9..8aeaedbba9 100644 --- a/openair3/NGAP/ngap_gNB_handlers.c +++ b/openair3/NGAP/ngap_gNB_handlers.c @@ -1127,7 +1127,14 @@ static int ngap_gNB_handle_paging(sctp_assoc_t assoc_id, uint32_t stream, NGAP_N TBCD_TO_MCC_MNC(&(item_p->tAI.pLMNIdentity), msg->plmn_identity[i].mcc, msg->plmn_identity[i].mnc, msg->plmn_identity[i].mnc_digit_length); OCTET_STRING_TO_INT16(&(item_p->tAI.tAC), msg->tac[i]); msg->tai_size++; - NGAP_DEBUG("[SCTP %u] Received Paging: MCC %d, MNC %d, TAC %d\n", assoc_id, msg->plmn_identity[i].mcc, msg->plmn_identity[i].mnc, msg->tac[i]); + plmn_id_t *p = &msg->plmn_identity[i]; + LOG_D(NGAP, + "[SCTP %u] PLMN in TAI list for Paging: MCC=%03d, MNC=%0*d, TAC=%d\n", + assoc_id, + p->mcc, + p->mnc_digit_length, + p->mnc, + msg->tac[i]); } //paging parameter values diff --git a/openair3/NGAP/ngap_gNB_nas_procedures.c b/openair3/NGAP/ngap_gNB_nas_procedures.c index b291f6b96c..03f8c1c10e 100644 --- a/openair3/NGAP/ngap_gNB_nas_procedures.c +++ b/openair3/NGAP/ngap_gNB_nas_procedures.c @@ -74,23 +74,27 @@ static ngap_gNB_amf_data_t *select_amf(ngap_gNB_instance_t *instance_p, const ng // Select the AMF corresponding to the GUAMI from the RegisteredAMF IE if (msg->ue_identity.presenceMask & NGAP_UE_IDENTITIES_guami) { const nr_guami_t *guami = &msg->ue_identity.guami; - NGAP_DEBUG("GUAMI is present: MCC=%03d MNC=%03d RegionID=%d SetID=%d Pointer=%d\n", - guami->mcc, - guami->mnc, - guami->amf_region_id, - guami->amf_set_id, - guami->amf_pointer); + LOG_D(NGAP, + "GUAMI is present: MCC=%03d MNC=%0*d RegionID=%d SetID=%d Pointer=%d\n", + guami->mcc, + guami->mnc_len, + guami->mnc, + guami->amf_region_id, + guami->amf_set_id, + guami->amf_pointer); amf = ngap_gNB_nnsf_select_amf_by_guami(instance_p, msg->establishment_cause, *guami); if (amf) { - NGAP_INFO("UE %d: Chose AMF '%s' (assoc_id %d) through GUAMI MCC %d MNC %d AMFRI %d AMFSI %d AMFPT %d\n", - msg->gNB_ue_ngap_id, - amf->amf_name, - amf->assoc_id, - guami->mcc, - guami->mnc, - guami->amf_region_id, - guami->amf_set_id, - guami->amf_pointer); + LOG_I(NGAP, + "UE %d: Chose AMF '%s' (assoc_id %d) through GUAMI MCC=%03d MNC=%0*d AMFRI %d AMFSI %d AMFPT %d\n", + msg->gNB_ue_ngap_id, + amf->amf_name, + amf->assoc_id, + guami->mcc, + guami->mnc_len, + guami->mnc, + guami->amf_region_id, + guami->amf_set_id, + guami->amf_pointer); return amf; } } @@ -101,13 +105,15 @@ static ngap_gNB_amf_data_t *select_amf(ngap_gNB_instance_t *instance_p, const ng const fiveg_s_tmsi_t *fgs_tmsi = &msg->ue_identity.s_tmsi; amf = ngap_gNB_nnsf_select_amf_by_amf_setid(instance_p, msg->establishment_cause, msg->plmn, fgs_tmsi->amf_set_id); if (amf) { - NGAP_INFO("UE %d: Chose AMF '%s' (assoc_id %d) through S-TMSI AMFSI %d and selected PLMN MCC %d MNC %d\n", - msg->gNB_ue_ngap_id, - amf->amf_name, - amf->assoc_id, - fgs_tmsi->amf_set_id, - msg->plmn.mcc, - msg->plmn.mnc); + LOG_I(NGAP, + "UE %d: Chose AMF '%s' (assoc_id %d) through S-TMSI AMFSI %d and selected PLMN MCC=%03d MNC=%0*d\n", + msg->gNB_ue_ngap_id, + amf->amf_name, + amf->assoc_id, + fgs_tmsi->amf_set_id, + msg->plmn.mcc, + msg->plmn.mnc_digit_length, + msg->plmn.mnc); return amf; } } @@ -117,13 +123,14 @@ static ngap_gNB_amf_data_t *select_amf(ngap_gNB_instance_t *instance_p, const ng // Select the AMF based on the selected PLMN identity received through RRCSetupComplete amf = ngap_gNB_nnsf_select_amf_by_plmn_id(instance_p, msg->establishment_cause, msg->plmn); if (amf) { - NGAP_INFO("UE %d: Chose AMF '%s' (assoc_id %d) through selected PLMN MCC=%03d MNC=%0*d\n", - msg->gNB_ue_ngap_id, - amf->amf_name, - amf->assoc_id, - msg->plmn.mcc, - msg->plmn.mnc_digit_length, - msg->plmn.mnc); + LOG_I(NGAP, + "UE %d: Chose AMF '%s' (assoc_id %d) through selected PLMN MCC=%03d MNC=%0*d\n", + msg->gNB_ue_ngap_id, + amf->amf_name, + amf->assoc_id, + msg->plmn.mcc, + msg->plmn.mnc_digit_length, + msg->plmn.mnc); return amf; } else { // Select the AMF with the highest capacity From afc13c264c65cbb635d9af879fd8024cae2cc7fb Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Thu, 21 Aug 2025 16:47:09 +0200 Subject: [PATCH 619/964] gNB: compute and store SSB-SINR in dB instead of just the SINR-index --- .../LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 31 ++++++++++++++++--- openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 3 +- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index 00201cdd8d..1b317890ae 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -414,6 +414,25 @@ static void handle_dl_harq(NR_UE_info_t * UE, } } +// Referred Table 10.1.16.1-1 in 38.133 V16.7.0. +static int get_measured_sinr(int index) +{ + if (index < 0 || index > 127) + return INT_MAX; + + return -235 + index * 5; +} + +// Referred Table 10.1.16.1-2 in 38.133 V16.7.0. +static int get_diff_sinr(int index, int best_SINRx10) +{ + if (index <= 0) + return best_SINRx10; + if (index >= 15) + return best_SINRx10 - 150; + return best_SINRx10 - index * 10; +} + //returns the measured RSRP value (upper limit) static bool get_measured_rsrp(uint8_t index, int *rsrp) { @@ -498,22 +517,24 @@ static void evaluate_sinr_report(gNB_MAC_INST *nrmac, } curr_payload = pickandreverse_bits(payload, 7, *cumul_bits); - sinr_report->SINR_index[0] = curr_payload & 0x7f; + int sinr_index = curr_payload & 0x7f; *cumul_bits += 7; csi_report->nb_of_csi_ssb_report++; - if (sinr_report->SINR_index[0] < 0 || sinr_report->SINR_index[0] > 127) { - LOG_E(NR_MAC, "UE %04x: reported SINR index %d invalid\n", UE->rnti, sinr_report->SINR_index[0]); + int SINRx10 = get_measured_sinr(sinr_index); + if (SINRx10 == INT_MAX) { + LOG_E(NR_MAC, "UE %04x: reported SINR index %d invalid\n", UE->rnti, sinr_index); return; } + sinr_report->SINRx10[0] = SINRx10; for (int i = 1; i < sinr_report->nr_reports; i++) { curr_payload = pickandreverse_bits(payload, 4, *cumul_bits); - sinr_report->SINR_index[i] = curr_payload & 0x0f; + sinr_report->SINRx10[i] = get_diff_sinr(curr_payload & 0x0f, sinr_report->SINRx10[0]); *cumul_bits += 4; } - LOG_D(MAC, "Reported SSB-SINR index = %d\n", sinr_report->SINR_index[0]); + LOG_D(MAC, "Reported SSB-SINR = %d.%d\n", sinr_report->SINRx10[0] / 10, sinr_report->SINRx10[0] % 10); } static void evaluate_rsrp_report(gNB_MAC_INST *nrmac, diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 2627c9162b..db12640893 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -521,8 +521,7 @@ typedef struct RSRP_report { uint8_t nr_reports; uint8_t resource_id[MAX_NR_OF_REPORTED_RS]; int RSRP[MAX_NR_OF_REPORTED_RS]; - // SINR index according to tables 10.1.16.1-1, 10.1.16.1-2 - int SINR_index[MAX_NR_OF_REPORTED_RS]; + int SINRx10[MAX_NR_OF_REPORTED_RS]; } RSRP_report_t; struct CSI_Report { From 2b2e9563ffc65471e37405819ca540d38515f41f Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Thu, 21 Aug 2025 16:52:14 +0200 Subject: [PATCH 620/964] gNB: add SSB-SINR measurement values to the MAC statistics output --- .../LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 5 ++++ openair2/LAYER2/NR_MAC_gNB/main.c | 25 +++++++++++++++---- openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 2 ++ 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index 1b317890ae..f2a1988459 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -534,6 +534,11 @@ static void evaluate_sinr_report(gNB_MAC_INST *nrmac, *cumul_bits += 4; } + NR_mac_stats_t *stats = &UE->mac_stats; + // including ssb SINR in mac stats + stats->cumul_sinrx10 += sinr_report->SINRx10[0]; + stats->num_sinr_meas++; + LOG_D(MAC, "Reported SSB-SINR = %d.%d\n", sinr_report->SINRx10[0] / 10, sinr_report->SINRx10[0] % 10); } diff --git a/openair2/LAYER2/NR_MAC_gNB/main.c b/openair2/LAYER2/NR_MAC_gNB/main.c index e80f852022..4860483d73 100644 --- a/openair2/LAYER2/NR_MAC_gNB/main.c +++ b/openair2/LAYER2/NR_MAC_gNB/main.c @@ -126,24 +126,37 @@ size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; NR_mac_stats_t *stats = &UE->mac_stats; const int avg_rsrp = stats->num_rsrp_meas > 0 ? stats->cumul_rsrp / stats->num_rsrp_meas : 0; + const int avg_sinrx10 = stats->num_sinr_meas > 0 ? stats->cumul_sinrx10 / stats->num_sinr_meas : 0; output += snprintf(output, end - output, "UE RNTI %04x CU-UE-ID ", UE->rnti); if (du_exists_f1_ue_data(UE->rnti)) { f1_ue_data_t ued = du_get_f1_ue_data(UE->rnti); output += snprintf(output, end - output, "%d", ued.secondary_ue); } else { - output += snprintf(output, end-output, "(none)"); + output += snprintf(output, end - output, "(none)"); } bool in_sync = !sched_ctrl->ul_failure; output += snprintf(output, end - output, - " %s PH %d dB PCMAX %d dBm, average RSRP %d (%d meas)\n", + " %s PH %d dB PCMAX %d dBm", in_sync ? "in-sync" : "out-of-sync", sched_ctrl->ph, - sched_ctrl->pcmax, - avg_rsrp, - stats->num_rsrp_meas); + sched_ctrl->pcmax); + + if (stats->num_rsrp_meas) + output += snprintf(output, end - output, ", average RSRP %d (%d meas)", avg_rsrp, stats->num_rsrp_meas); + + if (stats->num_sinr_meas) { + output += snprintf(output, + end - output, + ", average SINR %d.%d (%d meas)", + avg_sinrx10 / 10, + avg_sinrx10 % 10, + stats->num_sinr_meas); + } + + output += snprintf(output, end - output, "\n"); if(sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.print_report) output += snprintf(output, @@ -178,6 +191,8 @@ size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset if (reset_rsrp) { stats->num_rsrp_meas = 0; stats->cumul_rsrp = 0; + stats->num_sinr_meas = 0; + stats->cumul_sinrx10 = 0; } output += snprintf(output, end - output, diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index db12640893..1e8fef481d 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -693,6 +693,8 @@ typedef struct NR_mac_stats { uint32_t pucch0_DTX; int cumul_rsrp; uint8_t num_rsrp_meas; + int cumul_sinrx10; + uint8_t num_sinr_meas; char srs_stats[50]; // Statistics may differ depending on SRS usage int pusch_snrx10; int deltaMCS; From 7bb9f6006806142c495bc8d45eefae134d90d058 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Tue, 9 Sep 2025 09:12:57 +0200 Subject: [PATCH 621/964] Fix AMF related prints in NGAP --- openair3/NGAP/ngap_gNB_handlers.c | 3 +-- openair3/NGAP/ngap_gNB_nas_procedures.c | 8 ++++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/openair3/NGAP/ngap_gNB_handlers.c b/openair3/NGAP/ngap_gNB_handlers.c index 8aeaedbba9..6a92be9b79 100644 --- a/openair3/NGAP/ngap_gNB_handlers.c +++ b/openair3/NGAP/ngap_gNB_handlers.c @@ -237,7 +237,6 @@ static int ngap_gNB_handle_ng_setup_response(sctp_assoc_t assoc_id, uint32_t str STAILQ_INSERT_TAIL(&amf_desc_p->served_guami, new_guami_p, next); } - ngap_dump_served_guami(amf_desc_p); /* Set the capacity of this AMF */ NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_NGSetupResponseIEs_t, ie, container, @@ -254,7 +253,7 @@ static int ngap_gNB_handle_ng_setup_response(sctp_assoc_t assoc_id, uint32_t str memcpy(amf_desc_p->amf_name, ie->value.choice.AMFName.buf, ie->value.choice.AMFName.size); amf_desc_p->amf_name[ie->value.choice.AMFName.size] = '\0'; } - + ngap_dump_served_guami(amf_desc_p); /* mandatory set the plmn supports */ NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_NGSetupResponseIEs_t, ie, container, diff --git a/openair3/NGAP/ngap_gNB_nas_procedures.c b/openair3/NGAP/ngap_gNB_nas_procedures.c index 03f8c1c10e..b5db821e36 100644 --- a/openair3/NGAP/ngap_gNB_nas_procedures.c +++ b/openair3/NGAP/ngap_gNB_nas_procedures.c @@ -85,7 +85,7 @@ static ngap_gNB_amf_data_t *select_amf(ngap_gNB_instance_t *instance_p, const ng amf = ngap_gNB_nnsf_select_amf_by_guami(instance_p, msg->establishment_cause, *guami); if (amf) { LOG_I(NGAP, - "UE %d: Chose AMF '%s' (assoc_id %d) through GUAMI MCC=%03d MNC=%0*d AMFRI %d AMFSI %d AMFPT %d\n", + "UE %d: Selected AMF '%s' (assoc_id %d) through GUAMI MCC=%03d MNC=%0*d AMFRI %d AMFSI %d AMFPT %d\n", msg->gNB_ue_ngap_id, amf->amf_name, amf->assoc_id, @@ -106,7 +106,7 @@ static ngap_gNB_amf_data_t *select_amf(ngap_gNB_instance_t *instance_p, const ng amf = ngap_gNB_nnsf_select_amf_by_amf_setid(instance_p, msg->establishment_cause, msg->plmn, fgs_tmsi->amf_set_id); if (amf) { LOG_I(NGAP, - "UE %d: Chose AMF '%s' (assoc_id %d) through S-TMSI AMFSI %d and selected PLMN MCC=%03d MNC=%0*d\n", + "UE %d: Selected AMF '%s' (assoc_id %d) through S-TMSI AMFSI %d and selected PLMN MCC=%03d MNC=%0*d\n", msg->gNB_ue_ngap_id, amf->amf_name, amf->assoc_id, @@ -124,7 +124,7 @@ static ngap_gNB_amf_data_t *select_amf(ngap_gNB_instance_t *instance_p, const ng amf = ngap_gNB_nnsf_select_amf_by_plmn_id(instance_p, msg->establishment_cause, msg->plmn); if (amf) { LOG_I(NGAP, - "UE %d: Chose AMF '%s' (assoc_id %d) through selected PLMN MCC=%03d MNC=%0*d\n", + "UE %d: Selected AMF '%s' (assoc_id %d) through selected PLMN MCC=%03d MNC=%0*d\n", msg->gNB_ue_ngap_id, amf->amf_name, amf->assoc_id, @@ -136,7 +136,7 @@ static ngap_gNB_amf_data_t *select_amf(ngap_gNB_instance_t *instance_p, const ng // Select the AMF with the highest capacity amf = ngap_gNB_nnsf_select_amf(instance_p, msg->establishment_cause); if (amf) { - NGAP_INFO("UE %d: Chose AMF '%s' (assoc_id %d) through highest relative capacity\n", + NGAP_INFO("UE %d: Selected AMF '%s' (assoc_id %d) through highest relative capacity\n", msg->gNB_ue_ngap_id, amf->amf_name, amf->assoc_id); From a9a9dfe297642a873f14608289f34ab7bd869db2 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Thu, 21 Aug 2025 16:55:58 +0200 Subject: [PATCH 622/964] gNB: adjust the dl_max_mcs based on the reported SSB-SINR --- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 32 +++++++++++++++++++ .../LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 6 +++- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 1 + 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 3d2d1254bf..2ad1d384a2 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -248,6 +248,38 @@ uint16_t get_pm_index(const gNB_MAC_INST *nrmac, } } +// look-up table for AMC. Based on BLER vs SNR curves from the nr_dlsim simulation +// command line: nr_dlsim -n 10000 -m 0 -R 25 -b 25 -e MCS -s START_SNR -t 99.99 +// SNR Thresholds for MCS=[0,...,28]; START_SNR=chosen values with a resolution of 0.2dB to maintain a BLER of 10^-3 +static const int SINRx10_MCS_mapping[29] = { + -10, -4, 6, 16, 24, 34, 42, 50, 56, 62, // 0..9 + 86, 92, 98, 104, 112, 118, 124, 140, 146, 154, // 10..19 + 162, 170, 178, 186, 194, 202, 212, 220, 245 // 20..28 +}; + +int get_mcs_from_SINRx10(int mcs_table, int SINRx10, int Nl) +{ + if (mcs_table != 0) { + LOG_E(MAC, "mcs_table = %d, but get_mcs_from_SINRx10() only supports MCS table 0 (TS 38.214 - Table 5.1.3.1-1)\n", mcs_table); + return 28; + } + + int MIMO_SNRx10 = 0; + if (Nl == 2) + MIMO_SNRx10 = 40; + else if (Nl == 4) + MIMO_SNRx10 = 70; + + for (int i = 28; i >= 0; i--) { + if (SINRx10 >= SINRx10_MCS_mapping[i] + MIMO_SNRx10) + return i; + } + + LOG_W(MAC, "SINR (%d.%d dB) too low, no MCS possible to achieve BLER of 10^-3\n", SINRx10 / 10, SINRx10 % 10); + + return 0; +} + uint8_t get_mcs_from_cqi(int mcs_table, int cqi_table, int cqi_idx) { if (cqi_idx <= 0) { diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index f2a1988459..9e0cba1cdd 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -539,7 +539,11 @@ static void evaluate_sinr_report(gNB_MAC_INST *nrmac, stats->cumul_sinrx10 += sinr_report->SINRx10[0]; stats->num_sinr_meas++; - LOG_D(MAC, "Reported SSB-SINR = %d.%d\n", sinr_report->SINRx10[0] / 10, sinr_report->SINRx10[0] % 10); + const int mcs_table = UE->current_DL_BWP.mcsTableIdx; + const int nrOfLayers = get_dl_nrOfLayers(sched_ctrl, UE->current_DL_BWP.dci_format); + sched_ctrl->dl_max_mcs = get_mcs_from_SINRx10(mcs_table, sinr_report->SINRx10[0], nrOfLayers); + + LOG_D(MAC, "Reported SSB-SINR = %d.%d, dl_max_mcs %d\n", sinr_report->SINRx10[0] / 10, sinr_report->SINRx10[0] % 10, sched_ctrl->dl_max_mcs); } static void evaluate_rsrp_report(gNB_MAC_INST *nrmac, diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 84a0923e8b..78c6485a3c 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -403,6 +403,7 @@ uint16_t get_pm_index(const gNB_MAC_INST *nrmac, int layers, int xp_pdsch_antenna_ports); +int get_mcs_from_SINRx10(int mcs_table, int SINRx10, int Nl); uint8_t get_mcs_from_cqi(int mcs_table, int cqi_table, int cqi_idx); uint8_t get_dl_nrOfLayers(const NR_UE_sched_ctrl_t *sched_ctrl, const nr_dci_format_t dci_format); From 9346b50eb37d97ccf353b577c762890ac8433eca Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Thu, 21 Aug 2025 16:57:33 +0200 Subject: [PATCH 623/964] gNB: consider also the min_mcs when computing the DL MCS if only one round is used --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index df5c8e1474..c242ed4377 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -683,7 +683,8 @@ static void pf_dl(module_id_t module_id, const int max_mcs_table = current_BWP->mcsTableIdx == 1 ? 27 : 28; const int max_mcs = min(sched_ctrl->dl_max_mcs, max_mcs_table); if (bo->harq_round_max == 1) { - sched_pdsch->mcs = min(bo->max_mcs, max_mcs); + int new_mcs = min(bo->max_mcs, max_mcs); + sched_pdsch->mcs = max(bo->min_mcs, new_mcs); sched_ctrl->dl_bler_stats.mcs = sched_pdsch->mcs; } else sched_pdsch->mcs = get_mcs_from_bler(bo, stats, &sched_ctrl->dl_bler_stats, max_mcs, frame); From e70bb45ebd269b94e22db9e6d4cb27e82ec14880 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Thu, 21 Aug 2025 16:59:29 +0200 Subject: [PATCH 624/964] gNB: consider the measured PUSCH SNR when computing the UL MCS if only one round is used --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index b08e703076..e758a0cab4 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -2061,7 +2061,11 @@ static int pf_ul(gNB_MAC_INST *nrmac, const int max_mcs = min(bo->max_mcs, max_mcs_table); /* no per-user maximum MCS yet */ int selected_mcs; if (bo->harq_round_max == 1) { - selected_mcs = sched_ctrl->ul_bler_stats.mcs = max_mcs; + int nrOfLayers = get_ul_nrOfLayers(sched_ctrl, current_BWP->dci_format); + selected_mcs = get_mcs_from_SINRx10(current_BWP->mcs_table, sched_ctrl->pusch_snrx10, nrOfLayers); + selected_mcs = min(max_mcs, selected_mcs); + selected_mcs = max(bo->min_mcs, selected_mcs); + sched_ctrl->ul_bler_stats.mcs = selected_mcs; } else { selected_mcs = get_mcs_from_bler(bo, stats, &sched_ctrl->ul_bler_stats, max_mcs, frame); LOG_D(NR_MAC, "%d.%d starting mcs %d bler %f\n", frame, slot, selected_mcs, sched_ctrl->ul_bler_stats.bler); From 1c63d44afd844043a56871b5850cab05d3dfb065 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Thu, 21 Aug 2025 17:02:32 +0200 Subject: [PATCH 625/964] NR UE: make the power averaging IIR filter faster Especially high initial noise levels would stay too long and negatively impact the accuracy of later S(I)NR computations. --- openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c b/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c index fcf5484ed7..3c9850bd52 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c @@ -38,9 +38,8 @@ #include "common/utils/LOG/log.h" #include "PHY/sse_intrin.h" -//#define k1 1000 -#define k1 ((long long int) 1000) -#define k2 ((long long int) (1024-k1)) +#define K1 ((long long int) 512) +#define K2 ((long long int) (1024-K1)) //#define DEBUG_MEAS_RRC //#define DEBUG_MEAS_UE @@ -136,11 +135,11 @@ void nr_ue_measurements(PHY_VARS_NR_UE *ue, if (ue->init_averaging == 0) { for (gNB_id = 0; gNB_id < ue->n_connected_gNB; gNB_id++) - ue->measurements.rx_power_avg[gNB_id] = (int)(((k1*((long long int)(ue->measurements.rx_power_avg[gNB_id]))) + (k2*((long long int)(ue->measurements.rx_power_tot[gNB_id])))) >> 10); + ue->measurements.rx_power_avg[gNB_id] = (int)((K1 * ue->measurements.rx_power_avg[gNB_id] + K2 * ue->measurements.rx_power_tot[gNB_id]) >> 10); - ue->measurements.n0_power_avg = (int)(((k1*((long long int) (ue->measurements.n0_power_avg))) + (k2*((long long int) (ue->measurements.n0_power_tot))))>>10); + ue->measurements.n0_power_avg = (int)((K1 * ue->measurements.n0_power_avg + K2 * ue->measurements.n0_power_tot) >> 10); - LOG_D(PHY, "Noise Power Computation: k1 %lld k2 %lld n0 avg %u n0 tot %u\n", k1, k2, ue->measurements.n0_power_avg, ue->measurements.n0_power_tot); + LOG_D(PHY, "Noise Power Computation: K1 %lld K2 %lld n0 avg %u n0 tot %u\n", K1, K2, ue->measurements.n0_power_avg, ue->measurements.n0_power_tot); } else { From 4e87ac46a1ebd8d638292de95f87b86534115143 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Thu, 21 Aug 2025 17:05:48 +0200 Subject: [PATCH 626/964] nr_dlsim: several fixes for low SNR scenarios If the DCI in PDCCH is not correctly received, no PDSCH would be decoded but counted as no error. Also if the DCI was not correctly received, a TBS of 0 would be used in some computations and memory allocations. Fix these not counting if there is no PDSCH decoding, and by using the known TBS instead of the one received from the DCI. --- openair1/SIMULATION/NR_PHY/dlsim.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index 43abb68a12..eb41cad8bc 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -311,9 +311,9 @@ int main(int argc, char **argv) int i,aa;//,l; double sigma2, sigma2_dB=10, SNR, snr0=-2.0, snr1=2.0; uint8_t snr1set=0; - float effRate; + double effRate; //float psnr; - float eff_tp_check = 0.7; + double eff_tp_check = 0.7; uint32_t TBS = 0; c16_t **txdata; double **s_re,**s_im,**r_re,**r_im; @@ -547,7 +547,7 @@ int main(int argc, char **argv) break; case 't': - eff_tp_check = (float)atoi(optarg)/100; + eff_tp_check = atof(optarg) / 100.0; break; case 'w': @@ -1081,8 +1081,6 @@ printf("%d\n", slot); Sched_INFO->sched_response_id = -1; while (round < num_rounds && !UE_harq_process->decodeResult && !stop) { - round_trials[round]++; - clear_nr_nfapi_information(RC.nrmac[0], 0, frame, slot, &Sched_INFO->DL_req, &Sched_INFO->TX_req, &Sched_INFO->UL_dci_req); UE_info->UE_sched_ctrl.harq_processes[harq_pid].ndi = !(trial&1); UE_info->UE_sched_ctrl.harq_processes[harq_pid].round = round; @@ -1235,6 +1233,9 @@ printf("%d\n", slot); if (dlsch0->last_iteration_cnt >= dlsch0->max_ldpc_iterations) n_errors[round]++; + if (dlsch0->active) + round_trials[round]++; + int16_t *UE_llr = (int16_t*)UE->phy_sim_pdsch_llr; TBS = dlsch0->dlsch_config.TBS;//rel15->TBSize[0]; @@ -1266,8 +1267,8 @@ printf("%d\n", slot); } // round if (test_input_bit == NULL) { - test_input_bit = (unsigned char *)malloc16(sizeof(unsigned char) * TBS); - estimated_output_bit = (unsigned char *)malloc16(sizeof(unsigned char) * TBS); + test_input_bit = (unsigned char *)malloc16(8 * rel15->TBSize[0]); + estimated_output_bit = (unsigned char *)malloc16(8 * rel15->TBSize[0]); } for (i = 0; i < TBS; i++) { @@ -1288,12 +1289,12 @@ printf("%d\n", slot); if (n_trials == 1) printf("errors_bit = %u (trial %d)\n", errors_bit, trial); } - roundStats += ((float)round); + roundStats += round; if (UE_harq_process->decodeResult) - effRate += ((float)TBS) / round; + effRate += ((double)TBS) / round; } // noise trials - roundStats /= ((float)n_trials); + roundStats /= n_trials; for (int r = 0; r < num_rounds; r++) { blerStats[r] = (double)n_errors[r] / round_trials[r]; @@ -1316,7 +1317,7 @@ printf("%d\n", slot); printf("), Channel BER (%e", berStats[0]); for (int r = 1; r < num_rounds; r++) printf(",%e", berStats[r]); - printf(") Avg round %.2f, Eff Rate %.4f bits/slot, Eff Throughput %.2f, TBS %u bits/slot\n", roundStats, effRate, effRate / TBS * 100, TBS); + printf(") Avg round %.2f, Eff Rate %.4f bits/slot, Eff Throughput %.2f, TBS %u bits/slot\n", roundStats, effRate, effRate / (8 * rel15->TBSize[0]) * 100, 8 * rel15->TBSize[0]); printf("*****************************************\n"); printf("\n"); // writing to csv file @@ -1324,7 +1325,7 @@ printf("%d\n", slot); fprintf(csv_file,"%f,%d/%d,",SNR,n_false_positive,n_trials); for (int r = 0; r < num_rounds; r++) fprintf(csv_file,"%d/%d,%u/%u,%f,%e,",n_errors[r], round_trials[r], errors_scrambling[r], available_bits * round_trials[r],blerStats[r],berStats[r]); - fprintf(csv_file,"%.2f,%.4f,%.2f,%u\n", roundStats, effRate, effRate / TBS * 100, TBS); + fprintf(csv_file,"%.2f,%.4f,%.2f,%u\n", roundStats, effRate, effRate / (8 * rel15->TBSize[0]) * 100, 8 * rel15->TBSize[0]); } if (print_perf==1) { printf("\ngNB TX function statistics (per %d us slot, NPRB %d, mcs %d, C %d, block %d)\n", @@ -1332,7 +1333,7 @@ printf("%d\n", slot); g_rbSize, g_mcsIndex, UE->dl_harq_processes[0][slot].C, - msgDataTx->dlsch[0][0].harq_process.pdsch_pdu.pdsch_pdu_rel15.TBSize[0] << 3); + 8 * rel15->TBSize[0]); printDistribution(&gNB->phy_proc_tx,table_tx,"PHY proc tx"); printStatIndent2(&gNB->dci_generation_stats, "DCI encoding time"); printStatIndent2(&gNB->dlsch_encoding_stats,"DLSCH encoding time"); @@ -1406,7 +1407,7 @@ printf("%d\n", slot); break; } - if (effRate > (eff_tp_check*TBS)) { + if (effRate >= (eff_tp_check * 8 * rel15->TBSize[0])) { printf("PDSCH test OK\n"); ret = 0; break; From 2944775952995aeee9f9596290799f98c1234d22 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Thu, 21 Aug 2025 17:12:04 +0200 Subject: [PATCH 627/964] nr_ulsim: fix computation of the scrambling errors The array ul_harq_processes[harq_pid].f contains the data as bits, not bytes. --- openair1/SIMULATION/NR_PHY/ulsim.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index 466ffc6822..05cb7d0a80 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -1478,8 +1478,8 @@ int main(int argc, char *argv[]) } for (i = 0; i < available_bits; i++) { - if (((UE->ul_harq_processes[harq_pid].f[i] == 0) && (pusch_vars->llr[i] <= 0)) - || ((UE->ul_harq_processes[harq_pid].f[i] == 1) && (pusch_vars->llr[i] >= 0))) { + const uint8_t current_bit = (UE->ul_harq_processes[harq_pid].f[i / 8] >> (i & 7)) & 1; + if (((current_bit == 0) && (pusch_vars->llr[i] <= 0)) || ((current_bit == 1) && (pusch_vars->llr[i] >= 0))) { /*if(errors_scrambling == 0) printf("\x1B[34m" "[frame %d][trial %d]\t1st bit in error in unscrambling = %d\n" "\x1B[0m", frame, trial, i);*/ errors_scrambling[round]++; From b3242490f11f9c1994f4634b29cdd54e4cdb34a9 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Thu, 21 Aug 2025 17:20:25 +0200 Subject: [PATCH 628/964] enable SSB-SINR reporting for NTN GEO scenario --- ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn.conf | 1 + 1 file changed, 1 insertion(+) 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 03ca88d01b..859c638457 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 @@ -16,6 +16,7 @@ gNBs = ////////// Physical parameters: + do_SINR = 1; min_rxtxtime = 6; disable_harq = 1; cu_sibs = [2]; From 6b80fbf072f5eb2fea10a01b70b501ecb2bde66a Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Mon, 8 Sep 2025 13:51:45 +0200 Subject: [PATCH 629/964] update doc/MAC/mac-usage.md --- doc/MAC/mac-usage.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/MAC/mac-usage.md b/doc/MAC/mac-usage.md index 6104519f82..ebce013036 100644 --- a/doc/MAC/mac-usage.md +++ b/doc/MAC/mac-usage.md @@ -78,7 +78,7 @@ available in the the file `nrMAC-stats.log` in the same directory in which Example: ``` -UE RNTI 2460 CU-UE-ID 2 in-sync PH 28 dB PCMAX 24 dBm, average RSRP -74 (8 meas) +UE RNTI 2460 CU-UE-ID 2 in-sync PH 28 dB PCMAX 24 dBm, average RSRP -74 (8 meas), average SINR 40.0 (32 meas) UE 2460: CQI 15, RI 2, PMI (14,1) UE 2460: UL-RI 2 TPMI 0 UE 2460: dlsch_rounds 32917/5113/1504/560, dlsch_errors 211, pucch0_DTX 1385, BLER 0.19557 MCS (1) 23 CCE fail 3 @@ -103,6 +103,8 @@ In the first line, * `RSRP` (`-74`): measured power of the DL reference signals at the UE. >-80dBm you should have full DL throughput. <-95 dBm, you are very limited in terms of connectivity. +* `SINR` (`40.0`): measured signal to interference and noise ratio of the SSB + received at the UE. Maximum value that can be reported by the UE is 40.0 dB. The second and third line reflect channel state information (CSI) as reported by the UE, and only appear if CSI-RS/SRS are enabled and _received_ From 5a7d2755460119874513c80a842c0d5f6e1ac83a Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 11 Aug 2025 16:39:52 +0200 Subject: [PATCH 630/964] fix bug in computing number of LCG IDs with data at UE --- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 2 +- 1 file changed, 1 insertion(+), 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 b95597a0ba..cf7fda5ccf 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -2375,7 +2375,7 @@ static void nr_ue_get_sdu_mac_ce_post(NR_UE_MAC_INST_t *mac, int short_bsr_sz = sizeof(NR_BSR_SHORT) + sizeof(NR_MAC_SUBHEADER_FIXED); int num_lcg_id_with_data = 0; for (int lcg_id = 0; lcg_id < NR_MAX_NUM_LCGID; lcg_id++) - num_lcg_id_with_data += LCG_bytes > 0; + num_lcg_id_with_data += LCG_bytes[lcg_id] > 0; int long_bsr_sz = num_lcg_id_with_data + sizeof(NR_BSR_LONG) + sizeof(NR_MAC_SUBHEADER_SHORT); if (num_lcg_id_with_data < 2 && padding_len >= short_bsr_sz) { mac_ce_p->bsr.type_bsr = b_short; From 278d2cbca11d120f9d2ea00111188760af120c9b Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Tue, 5 Aug 2025 10:29:47 +0200 Subject: [PATCH 631/964] fix several not tested malloc or calloc return value --- common/config/config_load_configmodule.c | 6 +- common/utils/telnetsrv/telnetsrv.c | 20 +++--- .../telnetsrv/telnetsrv_5Gue_measurements.c | 2 +- .../telnetsrv/telnetsrv_enb_measurements.c | 2 +- executables/lte-ru.c | 5 +- .../oai_integration/wls_integration/wls_pnf.c | 2 +- nfapi/open-nFAPI/pnf/src/pnf.c | 62 ++++++++----------- openair1/PHY/CODING/3gpplte.c | 4 +- .../PHY/CODING/nrPolar_tools/nr_crc_byte.c | 2 +- openair1/PHY/INIT/lte_param_init.c | 6 +- .../linear_preprocessing_rec.c | 50 +++++++-------- openair1/PHY/TOOLS/calibration_scope.c | 6 +- openair1/PHY/TOOLS/nr_phy_scope.c | 10 +-- 13 files changed, 84 insertions(+), 93 deletions(-) diff --git a/common/config/config_load_configmodule.c b/common/config/config_load_configmodule.c index 9bb1b85f7d..cfe05042ce 100644 --- a/common/config/config_load_configmodule.c +++ b/common/config/config_load_configmodule.c @@ -300,12 +300,16 @@ configmodule_interface_t *load_configmodule(int argc, cfgmode = strdup(CONFIG_LIBCONFIGFILE); } } - static configmodule_interface_t *cfgptr; + static configmodule_interface_t *cfgptr = NULL; if (cfgptr) fprintf(stderr, "ERROR: Call load_configmodule more than one time\n"); // The macros are not thread safe print_params and similar cfgptr = calloc(sizeof(configmodule_interface_t), 1); + if (!cfgptr) { + fprintf(stderr, "ERROR: cannot allocate a memory for configuration\n"); + return NULL; + } /* argv_info is used to memorize command line options which have been recognized */ /* and to detect unrecognized command line options which might have been specified */ cfgptr->argv_info = calloc(sizeof(int32_t), argc+10); diff --git a/common/utils/telnetsrv/telnetsrv.c b/common/utils/telnetsrv/telnetsrv.c index 1d1a5be410..03b67506bc 100644 --- a/common/utils/telnetsrv/telnetsrv.c +++ b/common/utils/telnetsrv/telnetsrv.c @@ -375,32 +375,32 @@ char *telnet_getvarvalue(telnetshell_vardef_t *var, int varindex) char *val; switch (var[varindex].vartype) { case TELNET_VARTYPE_INT32: - val = malloc(64); + val = calloc_or_fail(1, 64); snprintf(val, 64, "%i", *(int32_t *)(var[varindex].varvalptr)); break; case TELNET_VARTYPE_INT64: - val = malloc(128); + val = calloc_or_fail(1, 128); snprintf(val, 128, "%lli", (long long)*(int64_t *)(var[varindex].varvalptr)); break; case TELNET_VARTYPE_INT16: - val = malloc(16); + val = calloc_or_fail(1, 16); snprintf(val, 16, "%hi", *(short *)(var[varindex].varvalptr)); break; case TELNET_VARTYPE_INT8: - val = malloc(16); + val = calloc_or_fail(1, 16); snprintf(val, 16, "%i", (int)(*(int8_t *)(var[varindex].varvalptr))); break; case TELNET_VARTYPE_UINT: - val = malloc(64); + val = calloc_or_fail(1, 64); snprintf(val, 64, "%u", *(unsigned int *)(var[varindex].varvalptr)); break; case TELNET_VARTYPE_DOUBLE: - val = malloc(32); + val = calloc_or_fail(1, 32); snprintf(val, 32, "%g\n", *(double *)(var[varindex].varvalptr)); break; @@ -409,7 +409,7 @@ char *telnet_getvarvalue(telnetshell_vardef_t *var, int varindex) break; default: - val = malloc(64); + val = calloc_or_fail(1, 64); snprintf(val, 64, "ERR:var %i unknown type", varindex); break; } @@ -927,7 +927,7 @@ int add_telnetcmd(char *modulename, telnetshell_vardef_t *var, telnetshell_cmdde for (int j = 0; cmd[j].cmdfunc != NULL; j++) { if (cmd[j].cmdflags & TELNETSRV_CMDFLAG_PUSHINTPOOLQ) { if (afifo == NULL) { - afifo = malloc(sizeof(notifiedFIFO_t)); + afifo = calloc_or_fail(1, sizeof(notifiedFIFO_t)); initNotifiedFIFO(afifo); } cmd[j].qptr = afifo; @@ -956,8 +956,8 @@ int telnetsrv_checkbuildver(char *mainexec_buildversion, char **shlib_buildvers } int telnetsrv_getfarray(loader_shlibfunc_t **farray) { - int const num_func_tln_srv = 3; - *farray = malloc(sizeof(loader_shlibfunc_t) * num_func_tln_srv); + int const num_func_tln_srv = 3; + *farray = calloc_or_fail(num_func_tln_srv, sizeof(loader_shlibfunc_t)); (*farray)[0].fname=TELNET_ADDCMD_FNAME; (*farray)[0].fptr=(int (*)(void) )add_telnetcmd; (*farray)[1].fname=TELNET_POLLCMDQ_FNAME; diff --git a/common/utils/telnetsrv/telnetsrv_5Gue_measurements.c b/common/utils/telnetsrv/telnetsrv_5Gue_measurements.c index 82f791cd2a..6f2d1c7516 100644 --- a/common/utils/telnetsrv/telnetsrv_5Gue_measurements.c +++ b/common/utils/telnetsrv/telnetsrv_5Gue_measurements.c @@ -86,7 +86,7 @@ int get_measurgroups(telnet_measurgroupdef_t **measurgroups) { void measurcmd_display_phycpu(telnet_printfunc_t prnt) { PHY_VARS_NR_UE *UE = PHY_vars_UE_g[0][0]; - telnet_cpumeasurdef_t cpumeasur[MAX_CPU_STAT_TYPE]; + telnet_cpumeasurdef_t cpumeasur[MAX_CPU_STAT_TYPE] = {}; for (int i = 0; i < MAX_CPU_STAT_TYPE; i++) { sprintf(cpumeasur[i].statname, "%s", UE->phy_cpu_stats.cpu_time_stats[i].meas_name); cpumeasur[i].astatptr = &UE->phy_cpu_stats.cpu_time_stats[i]; diff --git a/common/utils/telnetsrv/telnetsrv_enb_measurements.c b/common/utils/telnetsrv/telnetsrv_enb_measurements.c index b8898b665e..7bd18c802b 100644 --- a/common/utils/telnetsrv/telnetsrv_enb_measurements.c +++ b/common/utils/telnetsrv/telnetsrv_enb_measurements.c @@ -160,7 +160,7 @@ void measurcmd_display_rlcstats(telnet_printfunc_t prnt) { UE_info_t *UE_info = &(RC.mac[eNB_id]->UE_info); telnet_ltemeasurdef_t statsptr[]=LTE_RLCMEASURE; int num_rlcmeasure = sizeof(statsptr)/sizeof(telnet_ltemeasurdef_t ); - unsigned int *rlcstats = malloc(num_rlcmeasure*sizeof(unsigned int)); + unsigned int *rlcstats = calloc_or_fail(num_rlcmeasure,sizeof(unsigned int)); eNB_MAC_INST *eNB = RC.mac[eNB_id]; for(int i=0; i 0) { - ru = (RU_t **)malloc(nb_RU*sizeof(RU_t *)); + ru = malloc_or_fail(nb_RU * sizeof(RU_t *)); for (int j = 0; j < nb_RU; j++) { - ru[j] = (RU_t *)malloc(sizeof(RU_t)); - memset((void *)ru[j],0,sizeof(RU_t)); + ru[j] = calloc_or_fail(1,sizeof(RU_t)); ru[j]->idx = j; LOG_I(PHY,"Creating ru[%d]:%p\n", j, ru[j]); ru[j]->if_timing = synch_to_ext_device; diff --git a/nfapi/oai_integration/wls_integration/wls_pnf.c b/nfapi/oai_integration/wls_integration/wls_pnf.c index e02cef30a4..bed517ad01 100644 --- a/nfapi/oai_integration/wls_integration/wls_pnf.c +++ b/nfapi/oai_integration/wls_integration/wls_pnf.c @@ -77,7 +77,7 @@ int wls_fapi_nr_pnf_start() _this = (pnf_t *)(cfg); _this->terminate = 0; // Init PNF config - nfapi_pnf_phy_config_t *phy = (nfapi_pnf_phy_config_t *)malloc(sizeof(nfapi_pnf_phy_config_t)); + nfapi_pnf_phy_config_t *phy = malloc_or_fail(sizeof(nfapi_pnf_phy_config_t)); memset(phy, 0, sizeof(nfapi_pnf_phy_config_t)); phy->state = NFAPI_PNF_PHY_IDLE; diff --git a/nfapi/open-nFAPI/pnf/src/pnf.c b/nfapi/open-nFAPI/pnf/src/pnf.c index 1c851ce277..f9009e4a77 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf.c +++ b/nfapi/open-nFAPI/pnf/src/pnf.c @@ -202,20 +202,16 @@ void pnf_handle_pnf_config_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) nfapi_pnf_phy_config_delete_all(&pnf->_public); // create the phy records - if (req.pnf_phy_rf_config.tl.tag == NFAPI_PNF_PHY_RF_TAG) - { - int i = 0; - for(i = 0; i < req.pnf_phy_rf_config.number_phy_rf_config_info; ++i) - { - nfapi_pnf_phy_config_t* phy = (nfapi_pnf_phy_config_t*)malloc(sizeof(nfapi_pnf_phy_config_t)); - memset(phy, 0, sizeof(nfapi_pnf_phy_config_t)); + if (req.pnf_phy_rf_config.tl.tag == NFAPI_PNF_PHY_RF_TAG) { + for(int i = 0; i < req.pnf_phy_rf_config.number_phy_rf_config_info; ++i) { + nfapi_pnf_phy_config_t* phy = calloc_or_fail(1,sizeof(nfapi_pnf_phy_config_t)); - phy->state = NFAPI_PNF_PHY_IDLE; - phy->phy_id = req.pnf_phy_rf_config.phy_rf_config[i].phy_id; + phy->state = NFAPI_PNF_PHY_IDLE; + phy->phy_id = req.pnf_phy_rf_config.phy_rf_config[i].phy_id; - nfapi_pnf_phy_config_add(&(pnf->_public), phy); - } - } + nfapi_pnf_phy_config_add(&(pnf->_public), phy); + } + } if(pnf->_public.pnf_config_req) { @@ -269,19 +265,13 @@ void pnf_nr_handle_pnf_config_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen nfapi_pnf_phy_config_delete_all(&pnf->_public); // create the phy records - if (req.pnf_phy_rf_config.tl.tag == NFAPI_PNF_PHY_RF_TAG) - { - int i = 0; - for(i = 0; i < req.pnf_phy_rf_config.number_phy_rf_config_info; ++i) - { - nfapi_pnf_phy_config_t* phy = (nfapi_pnf_phy_config_t*)malloc(sizeof(nfapi_pnf_phy_config_t)); - memset(phy, 0, sizeof(nfapi_pnf_phy_config_t)); - - phy->state = NFAPI_PNF_PHY_IDLE; - phy->phy_id = req.pnf_phy_rf_config.phy_rf_config[i].phy_id; - - nfapi_pnf_phy_config_add(&(pnf->_public), phy); - } + if (req.pnf_phy_rf_config.tl.tag == NFAPI_PNF_PHY_RF_TAG) { + for(int i = 0; i < req.pnf_phy_rf_config.number_phy_rf_config_info; ++i) { + nfapi_pnf_phy_config_t* phy = calloc_or_fail(1,sizeof(nfapi_pnf_phy_config_t)); + phy->state = NFAPI_PNF_PHY_IDLE; + phy->phy_id = req.pnf_phy_rf_config.phy_rf_config[i].phy_id; + nfapi_pnf_phy_config_add(&(pnf->_public), phy); + } } if(pnf->_public.pnf_nr_config_req) @@ -2024,21 +2014,19 @@ int pnf_read_dispatch_message(pnf_t* pnf) // now have the size of the mesage } - if(message_size > stack_buffer_size) - { - dynamic_buffer = (uint8_t*)malloc(message_size); + if(message_size > stack_buffer_size) { + dynamic_buffer = malloc_or_fail(message_size); - if(dynamic_buffer == NULL) - { - // todo : add error mesage - NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF Failed to allocate dynamic buffer for sctp_recvmsg size:%d\n", message_size); - return -1; - } + if (dynamic_buffer == NULL) { + // todo : add error mesage + NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF Failed to allocate dynamic buffer for sctp_recvmsg size:%d\n", message_size); + return -1; + } - read_buffer = dynamic_buffer; - } + read_buffer = dynamic_buffer; + } - { + { int flags = 0; (void)memset(&sndrcvinfo, 0, sizeof(struct sctp_sndrcvinfo)); diff --git a/openair1/PHY/CODING/3gpplte.c b/openair1/PHY/CODING/3gpplte.c index 49740487ac..3502a1ad56 100644 --- a/openair1/PHY/CODING/3gpplte.c +++ b/openair1/PHY/CODING/3gpplte.c @@ -450,7 +450,7 @@ t_interleaver_codebook *f1f2mat; short *il_tb; __attribute__((constructor)) static void init_interleaver(void) { int totSize=0; - f1f2mat=(t_interleaver_codebook*) malloc(sizeof(*f1f2mat) * sizeof(f1f2) / sizeof(*f1f2)); + f1f2mat = malloc_or_fail(sizeof(*f1f2mat) * sizeof(f1f2) / sizeof(*f1f2)); for (int i=0; i < sizeof(f1f2)/sizeof(*f1f2) ; i++) { f1f2mat[i].nb_bits=f1f2[i].nb_bits; f1f2mat[i].f1=f1f2[i].f1; @@ -458,7 +458,7 @@ __attribute__((constructor)) static void init_interleaver(void) { f1f2mat[i].beg_index=totSize; totSize+=f1f2mat[i].nb_bits; } - il_tb=(short*)malloc(sizeof(*il_tb)*totSize); + il_tb = malloc_or_fail(sizeof(*il_tb) * totSize); int idx=0; for (int i=0; i < sizeof(f1f2)/sizeof(*f1f2) ; i++) for (uint64_t j=0; j #include //#define DEBUG_PREPROC - +#include "common/utils/utils.h" void transpose (int N, float complex *A, float complex *Result) { @@ -43,14 +43,14 @@ void transpose (int N, float complex *A, float complex *Result) int ldb = col_opB; if (transb == CblasNoTrans) { - B = (float complex*)calloc(ldb*col_opB,sizeof(float complex)); + B = calloc_or_fail(ldb * col_opB, sizeof(float complex)); col_B= col_opB; } else { - B = (float complex*)calloc(ldb*col_opA, sizeof(float complex)); + B = calloc_or_fail(ldb * col_opA, sizeof(float complex)); col_B = col_opA; } - float complex* C = (float complex*)malloc(ldc*col_opB*sizeof(float complex)); + float complex* C = malloc_or_fail(ldc * col_opB * sizeof(float complex)); for (i=0; i>2)*sizeof(float complex)); - float complex *H1_re = malloc(n_rx*(n_tx>>2)*sizeof(float complex)); - float complex *R_corr_col_n_0_re = malloc(n_rx*n_tx*sizeof(float complex)); - float complex *R_corr_col_n_1_re = malloc(n_rx*n_tx*sizeof(float complex)); - float complex *U_0_re = malloc(n_rx*n_tx*sizeof(float complex)); - float complex *U_1_re = malloc(n_rx*n_tx*sizeof(float complex)); - float complex *U_0_herm_re = malloc(n_rx*n_tx*sizeof(float complex)); - float complex *U_1_herm_re = malloc(n_rx*n_tx*sizeof(float complex)); - float complex *D_0_re = malloc(n_rx*n_tx*sizeof(float complex)); - float complex *D_1_re = malloc(n_rx*n_tx*sizeof(float complex)); - float complex *W_Wh_0_re = malloc(n_rx*n_tx*sizeof(float complex)); - float complex *W_Wh_1_re = malloc(n_rx*n_tx*sizeof(float complex)); + float complex *H0_re = malloc_or_fail(n_rx*(n_tx>>2)*sizeof(float complex)); + float complex *H1_re = malloc_or_fail(n_rx*(n_tx>>2)*sizeof(float complex)); + float complex *R_corr_col_n_0_re = malloc_or_fail(n_rx*n_tx*sizeof(float complex)); + float complex *R_corr_col_n_1_re = malloc_or_fail(n_rx*n_tx*sizeof(float complex)); + float complex *U_0_re = malloc_or_fail(n_rx*n_tx*sizeof(float complex)); + float complex *U_1_re = malloc_or_fail(n_rx*n_tx*sizeof(float complex)); + float complex *U_0_herm_re = malloc_or_fail(n_rx*n_tx*sizeof(float complex)); + float complex *U_1_herm_re = malloc_or_fail(n_rx*n_tx*sizeof(float complex)); + float complex *D_0_re = malloc_or_fail(n_rx*n_tx*sizeof(float complex)); + float complex *D_1_re = malloc_or_fail(n_rx*n_tx*sizeof(float complex)); + float complex *W_Wh_0_re = malloc_or_fail(n_rx*n_tx*sizeof(float complex)); + float complex *W_Wh_1_re = malloc_or_fail(n_rx*n_tx*sizeof(float complex)); for (aatx=0; aatxwaterFallh=h-15; - graph->waterFallAvg=malloc(sizeof(*graph->waterFallAvg) * graph->waterFallh); + graph->waterFallAvg = malloc_or_fail(sizeof(*graph->waterFallAvg) * graph->waterFallh); for (int i=0; i< graph->waterFallh; i++) graph->waterFallAvg[i]=0; @@ -309,7 +309,7 @@ static void puschIQ (OAIgraph_t *graph, calibData_t *context) { static OAI_phy_scope_t *createScopeCalibration(calibData_t * context) { FL_OBJECT *obj; - OAI_phy_scope_t *fdui = calloc(( sizeof *fdui ),1); + OAI_phy_scope_t *fdui = calloc_or_fail((sizeof *fdui), 1); fdui->context=context; // Define form fdui->phy_scope = fl_bgn_form( FL_NO_BOX, 800, 800 ); @@ -380,7 +380,7 @@ static void *scopeThread(void *arg) { void CalibrationInitScope(void ** samplesRx,openair0_device *rfdevice) { pthread_t forms_thread; - calibData_t * tmp=(calibData_t *) malloc(sizeof(*tmp)); + calibData_t *tmp = (calibData_t *)malloc_or_fail(sizeof(*tmp)); tmp->samplesRx=samplesRx; tmp->rfdevice=rfdevice; threadCreate(&forms_thread, scopeThread, (void*) tmp, "scope", -1, OAI_PRIORITY_RT_LOW); diff --git a/openair1/PHY/TOOLS/nr_phy_scope.c b/openair1/PHY/TOOLS/nr_phy_scope.c index ac754eb432..8f86bfedc4 100644 --- a/openair1/PHY/TOOLS/nr_phy_scope.c +++ b/openair1/PHY/TOOLS/nr_phy_scope.c @@ -614,7 +614,7 @@ static void puschThroughtput (OAIgraph_t *graph, scopeData_t *p, int nb_UEs) { STATICFORXSCOPE OAI_phy_scope_t *create_phy_scope_gnb(void) { FL_OBJECT *obj; - OAI_phy_scope_t *fdui = calloc(( sizeof *fdui ),1); + OAI_phy_scope_t *fdui = calloc_or_fail((sizeof *fdui), 1); // Define form fdui->phy_scope = fl_bgn_form( FL_NO_BOX, 800, 800 ); fl_set_form_dblbuffer(fdui->phy_scope, 1); @@ -739,7 +739,7 @@ static void scopeUpdaterGnb(enum PlotTypeGnbIf plotType, int numElt) STATICFORXSCOPE void gNBinitScope(scopeParms_t *p) { - AssertFatal(p->gNB->scopeData = calloc(sizeof(scopeData_t), 1), ""); + AssertFatal(p->gNB->scopeData = calloc_or_fail(sizeof(scopeData_t), 1), ""); scopeData_t *scope=(scopeData_t *) p->gNB->scopeData; scope->argc=p->argc; scope->argv=p->argv; @@ -998,7 +998,7 @@ static void uePdschThroughput (scopeGraphData_t **data, OAIgraph_t *graph, PHY_ STATICFORXSCOPE OAI_phy_scope_t *create_phy_scope_nrue(int ID) { FL_OBJECT *obj; - OAI_phy_scope_t *fdui = calloc(( sizeof *fdui ),1); + OAI_phy_scope_t *fdui = calloc_or_fail((sizeof *fdui), 1); // Define form fdui->phy_scope = fl_bgn_form( FL_NO_BOX, 800, 900 ); fl_set_form_dblbuffer(fdui->phy_scope, 1); @@ -1139,7 +1139,7 @@ static void *nrUEscopeThread(void *arg) { STATICFORXSCOPE void nrUEinitScope(PHY_VARS_NR_UE *ue) { - AssertFatal(ue->scopeData = calloc(sizeof(scopeData_t), 1), ""); + AssertFatal(ue->scopeData = calloc_or_fail(sizeof(scopeData_t), 1), ""); scopeData_t *scope=(scopeData_t *) ue->scopeData; scope->copyData = copyData; #ifndef WEBSRVSCOPE @@ -1185,7 +1185,7 @@ static void reset_stats_gNB(FL_OBJECT *button, } static FD_stats_form *create_form_stats_form(int ID) { FL_OBJECT *obj; - FD_stats_form *fdui = calloc(( sizeof *fdui ),1); + FD_stats_form *fdui = calloc_or_fail(( sizeof *fdui ),1); fdui->vdata = fdui->cdata = NULL; fdui->ldata = 0; fdui->stats_form = fl_bgn_form( FL_NO_BOX, 1115, 900 ); From 82931c8f01cb20fa603763f8e822d35df8874863 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Tue, 5 Aug 2025 10:38:47 +0200 Subject: [PATCH 632/964] fix printf() format errors --- .../PHY/CODING/3gpplte_turbo_decoder_sse.c | 16 ++++++++-------- openair1/PHY/INIT/nr_init_ue.c | 11 ----------- openair1/PHY/LTE_TRANSPORT/dci.c | 5 ++++- openair1/PHY/LTE_TRANSPORT/dlsch_scrambling.c | 2 +- openair1/PHY/LTE_TRANSPORT/phich_common.c | 6 +++++- openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c | 3 ++- openair1/PHY/MODULATION/nr_modulation.c | 2 +- openair1/PHY/NR_TRANSPORT/nr_dci.c | 9 --------- openair1/PHY/NR_TRANSPORT/nr_pbch.c | 19 ------------------- .../PHY/NR_UE_TRANSPORT/nr_initial_sync_sl.c | 17 ----------------- openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c | 6 +----- openair1/PHY/NR_UE_TRANSPORT/nr_psbch_tx.c | 9 --------- openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c | 7 ++++++- 13 files changed, 28 insertions(+), 84 deletions(-) diff --git a/openair1/PHY/CODING/3gpplte_turbo_decoder_sse.c b/openair1/PHY/CODING/3gpplte_turbo_decoder_sse.c index e6d1f87b4e..3a35dde491 100644 --- a/openair1/PHY/CODING/3gpplte_turbo_decoder_sse.c +++ b/openair1/PHY/CODING/3gpplte_turbo_decoder_sse.c @@ -1385,7 +1385,7 @@ void compute_beta(llr_t *alpha,llr_t *beta,llr_t *m_11,llr_t *m_10,unsigned shor #else #ifdef DEBUG_LOGMAP - printf("beta0 %u: %03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d\n", + printf("beta0 %d: %03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d\n", (frame_length >> 4), simde_mm_extract_epi8(beta_ptr[0], 0), simde_mm_extract_epi8(beta_ptr[0], 1), @@ -1403,7 +1403,7 @@ void compute_beta(llr_t *alpha,llr_t *beta,llr_t *m_11,llr_t *m_10,unsigned shor simde_mm_extract_epi8(beta_ptr[0], 13), simde_mm_extract_epi8(beta_ptr[0], 14), simde_mm_extract_epi8(beta_ptr[0], 15)); - printf("beta1 %u: %03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d\n", + printf("beta1 %d: %03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d\n", (frame_length >> 4), simde_mm_extract_epi8(beta_ptr[1], 0), simde_mm_extract_epi8(beta_ptr[1], 1), @@ -1421,7 +1421,7 @@ void compute_beta(llr_t *alpha,llr_t *beta,llr_t *m_11,llr_t *m_10,unsigned shor simde_mm_extract_epi8(beta_ptr[1], 13), simde_mm_extract_epi8(beta_ptr[1], 14), simde_mm_extract_epi8(beta_ptr[1], 15)); - printf("beta2 %u: %03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d\n", + printf("beta2 %d: %03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d\n", (frame_length >> 4), simde_mm_extract_epi8(beta_ptr[2], 0), simde_mm_extract_epi8(beta_ptr[2], 1), @@ -1439,7 +1439,7 @@ void compute_beta(llr_t *alpha,llr_t *beta,llr_t *m_11,llr_t *m_10,unsigned shor simde_mm_extract_epi8(beta_ptr[2], 13), simde_mm_extract_epi8(beta_ptr[2], 14), simde_mm_extract_epi8(beta_ptr[2], 15)); - printf("beta3 %u: %03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d\n", + printf("beta3 %d: %03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d\n", (frame_length >> 4), simde_mm_extract_epi8(beta_ptr[3], 0), simde_mm_extract_epi8(beta_ptr[3], 1), @@ -1457,7 +1457,7 @@ void compute_beta(llr_t *alpha,llr_t *beta,llr_t *m_11,llr_t *m_10,unsigned shor simde_mm_extract_epi8(beta_ptr[3], 13), simde_mm_extract_epi8(beta_ptr[3], 14), simde_mm_extract_epi8(beta_ptr[3], 15)); - printf("beta4 %u: %03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d\n", + printf("beta4 %d: %03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d\n", (frame_length >> 4), simde_mm_extract_epi8(beta_ptr[4], 0), simde_mm_extract_epi8(beta_ptr[4], 1), @@ -1475,7 +1475,7 @@ void compute_beta(llr_t *alpha,llr_t *beta,llr_t *m_11,llr_t *m_10,unsigned shor simde_mm_extract_epi8(beta_ptr[4], 13), simde_mm_extract_epi8(beta_ptr[4], 14), simde_mm_extract_epi8(beta_ptr[4], 15)); - printf("beta5 %u: %03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d\n", + printf("beta5 %d: %03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d\n", (frame_length >> 4), simde_mm_extract_epi8(beta_ptr[5], 0), simde_mm_extract_epi8(beta_ptr[5], 1), @@ -1493,7 +1493,7 @@ void compute_beta(llr_t *alpha,llr_t *beta,llr_t *m_11,llr_t *m_10,unsigned shor simde_mm_extract_epi8(beta_ptr[5], 13), simde_mm_extract_epi8(beta_ptr[5], 14), simde_mm_extract_epi8(beta_ptr[5], 15)); - printf("beta6 %u: %03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d\n", + printf("beta6 %d: %03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d\n", (frame_length >> 4), simde_mm_extract_epi8(beta_ptr[6], 0), simde_mm_extract_epi8(beta_ptr[6], 1), @@ -1511,7 +1511,7 @@ void compute_beta(llr_t *alpha,llr_t *beta,llr_t *m_11,llr_t *m_10,unsigned shor simde_mm_extract_epi8(beta_ptr[6], 13), simde_mm_extract_epi8(beta_ptr[6], 14), simde_mm_extract_epi8(beta_ptr[6], 15)); - printf("beta7 %u: %03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d\n", + printf("beta7 %d: %03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d\n", (frame_length >> 4), simde_mm_extract_epi8(beta_ptr[7], 0), simde_mm_extract_epi8(beta_ptr[7], 1), diff --git a/openair1/PHY/INIT/nr_init_ue.c b/openair1/PHY/INIT/nr_init_ue.c index b167cebc26..54a80124f3 100644 --- a/openair1/PHY/INIT/nr_init_ue.c +++ b/openair1/PHY/INIT/nr_init_ue.c @@ -519,17 +519,6 @@ static void sl_generate_psbch_dmrs_qpsk_sequences(PHY_VARS_NR_UE *UE, struct com idx = (((sl_dmrs_sequence[(m << 1) >> 5]) >> ((m << 1) & 0x1f)) & 3); modulated_dmrs_sym[m].r = mod_table[idx].r; modulated_dmrs_sym[m].i = mod_table[idx].i; - -#ifdef SL_DEBUG_INIT_DATA - printf("m:%d gold seq: %d b0-b1: %d-%d DMRS Symbols: %d %d\n", - m, - sl_dmrs_sequence[(m << 1) >> 5], - (((sl_dmrs_sequence[(m << 1) >> 5]) >> ((m << 1) & 0x1f)) & 1), - (((sl_dmrs_sequence[((m << 1) + 1) >> 5]) >> (((m << 1) + 1) & 0x1f)) & 1), - modulated_dmrs_sym[m].r, - modulated_dmrs_sym[m].i); - printf("idx:%d, qpsk_table.r:%d, qpsk_table.i:%d\n", idx, mod_table[idx].r, mod_table[idx].i); -#endif } #ifdef SL_DUMP_INIT_SAMPLES diff --git a/openair1/PHY/LTE_TRANSPORT/dci.c b/openair1/PHY/LTE_TRANSPORT/dci.c index d2ad87f717..c1f54fa9c3 100644 --- a/openair1/PHY/LTE_TRANSPORT/dci.c +++ b/openair1/PHY/LTE_TRANSPORT/dci.c @@ -418,7 +418,10 @@ uint8_t generate_dci_top(uint8_t num_pdcch_symbols, // if REG is allocated to PHICH, skip it if (check_phich_reg(frame_parms,kprime,lprime,mi) == 1) { #ifdef DEBUG_DCI_ENCODING - printf("generate_dci: skipping REG %d (kprime %u, lprime %u)\n",(lprime==0)?(kprime/6) : (kprime>>2),kprime,lprime); + printf("generate_dci: skipping REG %u (kprime %u, lprime %u)\n", + (lprime == 0) ? (kprime / 6) : (kprime >> 2), + kprime, + lprime); #endif } else { // Copy REG to TX buffer diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_scrambling.c b/openair1/PHY/LTE_TRANSPORT/dlsch_scrambling.c index 8bdceceed8..5626f0a9df 100644 --- a/openair1/PHY/LTE_TRANSPORT/dlsch_scrambling.c +++ b/openair1/PHY/LTE_TRANSPORT/dlsch_scrambling.c @@ -202,7 +202,7 @@ void dlsch_unscrambling(LTE_DL_FRAME_PARMS *frame_parms, for (i=0; i<(1+(G>>5)); i++) { for (j=0; j<32; j++,k++) { #ifdef DEBUG_SCRAMBLING - printf("unscrambling %d : %d xor %d =",k,llr[k],(s>>j)&1); + printf("unscrambling %d : %d xor %u =", k, llr[k], (s >> j) & 1); #endif llr[k] = ((2*((s>>j)&1))-1)*llr[k]; #ifdef DEBUG_SCRAMBLING diff --git a/openair1/PHY/LTE_TRANSPORT/phich_common.c b/openair1/PHY/LTE_TRANSPORT/phich_common.c index 302229b88d..48209274fc 100644 --- a/openair1/PHY/LTE_TRANSPORT/phich_common.c +++ b/openair1/PHY/LTE_TRANSPORT/phich_common.c @@ -390,7 +390,11 @@ void generate_phich_reg_mapping(LTE_DL_FRAME_PARMS *frame_parms) { frame_parms->phich_reg[1+(mprime<<1)][1] = ((frame_parms->Nid_cell*n1/n0) + mprime + (n1/3))%n1; frame_parms->phich_reg[1+(mprime<<1)][2] = ((frame_parms->Nid_cell*n2/n0) + mprime + (2*n2/3))%n2; //#ifdef DEBUG_PHICH - printf("phich_reg :%u => %d,%d,%d\n",mprime<<1,frame_parms->phich_reg[mprime<<1][0],frame_parms->phich_reg[mprime][1],frame_parms->phich_reg[mprime][2]); + printf("phich_reg :%d => %d,%d,%d\n", + mprime << 1, + frame_parms->phich_reg[mprime << 1][0], + frame_parms->phich_reg[mprime][1], + frame_parms->phich_reg[mprime][2]); printf("phich_reg :%d => %d,%d,%d\n",1+(mprime<<1),frame_parms->phich_reg[1+(mprime<<1)][0],frame_parms->phich_reg[1+(mprime<<1)][1],frame_parms->phich_reg[1+(mprime<<1)][2]); //#endif } diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c index e613efd6ca..a226e29225 100644 --- a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c +++ b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c @@ -665,7 +665,7 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB, } #ifdef DEBUG_ULSCH_DECODING - printf("ulsch_decoding.c: ACK i %u, r %d, j %u, ColumnSet[j] %d\n",i,r,j,columnset[j]); + printf("ulsch_decoding.c: ACK i %d, r %d, j %d, ColumnSet[j] %d\n", i, r, j, columnset[j]); #endif j=(j+3)&3; } @@ -1040,6 +1040,7 @@ void dump_ulsch_stats(FILE *fd,PHY_VARS_eNB *eNB,int frame) { char output[16384]; char *str = output; + *str = 0; for (eNB_SCH_STATS_t *st = eNB->ulsch_stats; st < eNB->ulsch_stats + sizeofArray(eNB->ulsch_stats); st++) if (st->rnti > 0 && st->round_trials[0] > 100) { for (int aa = 0; aa < eNB->frame_parms.nb_antennas_rx; aa++) diff --git a/openair1/PHY/MODULATION/nr_modulation.c b/openair1/PHY/MODULATION/nr_modulation.c index 4df83cedf9..40de9351d6 100644 --- a/openair1/PHY/MODULATION/nr_modulation.c +++ b/openair1/PHY/MODULATION/nr_modulation.c @@ -414,7 +414,7 @@ void nr_layer_mapping(int nbCodes, } #ifdef DEBUG_LAYER_MAPPING - printf("\nsymb %d/%d\n", i << 3, n_symbs); + printf("\nsymb %d/%u\n", i << 3, n_symbs); printf(" layer 0:\t"); for (int j = 0; j < 8 * 6; j += 6) { printf("%d %d ", ((int16_t *)&mod[i << 3])[j], ((int16_t *)&mod[i << 3])[j + 1]); diff --git a/openair1/PHY/NR_TRANSPORT/nr_dci.c b/openair1/PHY/NR_TRANSPORT/nr_dci.c index bea9cb63c5..0548c8fc10 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dci.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dci.c @@ -220,15 +220,6 @@ static void nr_generate_dci(PHY_VARS_gNB *gNB, } else { // DCI payload txdataF[l * frame_parms->ofdm_symbol_size + k] = c16mulRealShift(mod_dci[dci_idx], amp, 15); -#ifdef DEBUG_DCI - LOG_I(NR_PHY_DCI, - "PDCCH: l %d position %d => (%d,%d)\n", - l, - k, - txdataF[l * frame_parms->ofdm_symbol_size + k].r, - txdataF[l * frame_parms->ofdm_symbol_size + k].i; -#endif - dci_idx++; } diff --git a/openair1/PHY/NR_TRANSPORT/nr_pbch.c b/openair1/PHY/NR_TRANSPORT/nr_pbch.c index 64d07723bd..c5edd4cfde 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_pbch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_pbch.c @@ -65,16 +65,6 @@ void nr_generate_pbch_dmrs(uint32_t *gold_pbch_dmrs, for (int m=0; m>5])>>((m<<1)&0x1f))&3); mod_dmrs[m] = nr_qpsk_mod_table[idx]; -#ifdef DEBUG_PBCH_DMRS - printf("m %d idx %d gold seq %u b0-b1 %d-%d mod_dmrs %d %d\n", - m, - idx, - gold_pbch_dmrs[(m << 1) >> 5], - (((gold_pbch_dmrs[(m << 1) >> 5]) >> ((m << 1) & 0x1f)) & 1), - (((gold_pbch_dmrs[((m << 1) + 1) >> 5]) >> (((m << 1) + 1) & 0x1f)) & 1), - mod_dmrs[m].r, - mod_dmrs[m].i); -#endif } /// Resource mapping @@ -165,9 +155,6 @@ static void nr_pbch_encoded_scrambling(uint32_t *pbch_e, #ifdef DEBUG_PBCH_ENCODING printf("Scrambling params: nushift %d M %d length %d offset %d\n", nushift, M, length, info.offset); #endif -#ifdef DEBUG_PBCH_ENCODING - printf("s: %04x\t", s); -#endif for (int i = 0; i < length; ++i) { if (((i + info.offset) & 0x1f) == 0) @@ -189,9 +176,6 @@ static uint32_t nr_pbch_scrambling(uint32_t pbch_a_interleaved, uint32_t *s = gold_cache(Nid, info.len); #ifdef DEBUG_PBCH_ENCODING printf("Scrambling params: nushift %d M %d length %d offset %d\n", nushift, M, length, info.offset); -#endif -#ifdef DEBUG_PBCH_ENCODING - printf("s: %04x\t", s); #endif int goldIdx = info.goldIdx; for (int i = 0; i < length; ++i) { @@ -280,9 +264,6 @@ void nr_generate_pbch(PHY_VARS_gNB *gNB, uint8_t *interleaver = gNB->nr_pbch_interleaver; for (int i = 0; i < NR_POLAR_PBCH_PAYLOAD_BITS; i++) { pbch_a_interleaved |= ((pbch_a >> i) & 1) << (*(interleaver + i)); -#ifdef DEBUG_PBCH_ENCODING - printf("i %d out 0x%08x ilv %d (in>>i)&1) %d\n", i, pbch_a_interleaved, *(interleaver+i), (pbch_a >> i) & 1); -#endif } #ifdef DEBUG_PBCH_ENCODING diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync_sl.c b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync_sl.c index 2a2200557e..f9047aedd0 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync_sl.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync_sl.c @@ -78,19 +78,6 @@ static int sl_nr_pss_correlation(PHY_VARS_NR_UE *UE, int frame_index) const c64_t r64 = {.r = result.r, .i = result.i}; psss_corr_value += squaredMod(r64); - -#ifdef SL_DEBUG - pss_corr_debug_values[pss_index][n] = psss_corr_value; - printf("frame:%d n:%d, pss_index:%d, pss_for_correlation[pss_index][0]:%x, rxdata[n]:%x\n", - frame_index, - n, - pss_index, - pss_for_correlation[pss_index][0], - rxdata[ar][n + frame_index * sl_fp->samples_per_frame]); - printf("result %lld, pss_corr_values[%d][%d]:%ld\n", result, pss_index, n, pss_corr_debug_values[pss_index][n]); - printf("pss_index %d: n %6u peak_value %15llu\n", pss_index, n, (unsigned long long)pss_corr_debug_values[pss_index][n]); - printf("peak_value:%ld, peak_position:%d, pss_source:%d\n", peak_value, peak_position, pss_source); -#endif } // calculate the absolute value of sync_corr[n] @@ -99,10 +86,6 @@ static int sl_nr_pss_correlation(PHY_VARS_NR_UE *UE, int frame_index) peak_value = psss_corr_value; peak_position = n; pss_source = pss_index; - -#ifdef SL_DEBUG - printf("pss_index %d: n %6u peak_value %15llu\n", pss_index, n, (unsigned long long)psss_corr_value); -#endif } } } diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c b/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c index 8065da24b2..00130b3642 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c @@ -263,11 +263,7 @@ void nr_pbch_unscrambling(int16_t *demod_pbch_e, *pbch_a_interleaved ^= ((unscrambling_mask >> i) & 1) ? ((pbch_a_prime >> i) & 1) << i : (((pbch_a_prime >> i) & 1) ^ ((seq[idxGold] >> ((k + offset) & 0x1f)) & 1)) << i; - k += (!((unscrambling_mask>>i)&1)); -#ifdef DEBUG_PBCH_ENCODING - printf("i %d k %d offset %d (unscrambling_mask>>i)&1) %d s: %08x\t pbch_a_interleaved 0x%08x (!((unscrambling_mask>>i)&1)) %d\n", i, k, offset, (unscrambling_mask>>i)&1, s, *pbch_a_interleaved, - (!((unscrambling_mask>>i)&1))); -#endif + k += (!((unscrambling_mask >> i) & 1)); } else { if (((i + offset) & 0x1f) == 0) idxGold++; diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_psbch_tx.c b/openair1/PHY/NR_UE_TRANSPORT/nr_psbch_tx.c index cc8993bc6d..5a80ca272b 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_psbch_tx.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_psbch_tx.c @@ -40,11 +40,6 @@ void sl_psbch_scrambling(uint32_t *output, uint32_t id, uint16_t length) // x1 is set in lte_gold_generic x2 = id; // C_INIT -#ifdef SL_DEBUG - printf("SIDELINK: Function %s\n", __func__); - printf("Scrambling params: length %d id %d \n", length, id); -#endif - #ifdef SL_DEBUG for (int i = 0; i < 56; i++) { printf("\nBEFORE SCRAMBLING output[%d]:0x%x\n", i, output[i]); @@ -334,10 +329,6 @@ void nr_tx_psbch(PHY_VARS_NR_UE *UE, uint32_t frame_tx, uint32_t slot_tx, sl_nr_ psbch_payload |= (slot_tx << 10) & 0x10000; psbch_payload |= (slot_tx << 26) & 0xFC000000; -#ifdef SL_DEBUG - printf("DEBUG PSBCH TX: DFN, SLOT included. psbch_a :0x%08x, frame:%d, slot:%d\n", psbch_payload, frame_tx, slot_tx); -#endif - LOG_D(PHY, "PSBCH TX: Frame.Slot %d.%d. Payload::0x%08x, slssid:%d\n", frame_tx, slot_tx, psbch_payload, slss_id); // GENERATE Sidelink PSS,SSS Sequences, PSBCH DMRS Symbols, PSBCH Symbols diff --git a/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c b/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c index 3fcbe2a2f3..611572a0a3 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c @@ -506,7 +506,12 @@ static inline void nr_pucch2_3_4_scrambling(uint16_t M_bit, uint16_t rnti, uint1 uint8_t c = (uint8_t)((s >> i) & 1); btildep[i] = (((B>>i)&1) ^ c); #ifdef DEBUG_NR_PUCCH_TX - printf("\t\t\t btilde[%d]=%x from unscrambled bit %d and scrambling %d (%x)\n",i+(iprime<<5),btilde[i],((B>>i)&1),c,s>>i); + printf("\t\t\t btilde[%d]=%x from unscrambled bit %u and scrambling %d (%x)\n", + i + (iprime << 5), + btilde[i], + ((B >> i) & 1), + c, + s >> i); #endif } } From 5d118cf170ecb83c5b77ccb7db9f3a2c4f04b853 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Tue, 5 Aug 2025 10:42:36 +0200 Subject: [PATCH 633/964] fix lack of test for fopen() return value --- openair1/PHY/LTE_TRANSPORT/prach_common.c | 5 +++-- openair1/PHY/TOOLS/smbv.c | 16 ++++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/prach_common.c b/openair1/PHY/LTE_TRANSPORT/prach_common.c index 0939398c60..6dfa1cdec6 100644 --- a/openair1/PHY/LTE_TRANSPORT/prach_common.c +++ b/openair1/PHY/LTE_TRANSPORT/prach_common.c @@ -304,8 +304,9 @@ const uint16_t prach_root_sequence_map4[138] = { 57, 82, 58, 81, 59, 80, 60, 79, 61, 78, 62, 77, 63, 76, 64, 75, 65, 74, 66, 73, 67, 72, 68, 71, 69, 70}; void dump_prach_config(LTE_DL_FRAME_PARMS *frame_parms,uint8_t subframe) { - FILE *fd; - fd = fopen("prach_config.txt","w"); + FILE *fd = fopen("prach_config.txt", "w"); + if (!fd) + return; fprintf(fd,"prach_config: subframe = %d\n",subframe); fprintf(fd,"prach_config: N_RB_UL = %d\n",frame_parms->N_RB_UL); fprintf(fd,"prach_config: frame_type = %s\n",(frame_parms->frame_type==1) ? "TDD":"FDD"); diff --git a/openair1/PHY/TOOLS/smbv.c b/openair1/PHY/TOOLS/smbv.c index a1088cc705..337fcbe13f 100644 --- a/openair1/PHY/TOOLS/smbv.c +++ b/openair1/PHY/TOOLS/smbv.c @@ -61,6 +61,8 @@ int smbv_init_config(const char* fname, uint16_t sequence_length) int k; f_ptr = fopen(fname,"w"); + if (!f_ptr) + return -1; if (sequence_length>4) { msg("ERROR invalid sequence length: %d, maximum is 4\n", sequence_length); @@ -101,6 +103,8 @@ int smbv_write_config_from_frame_parms(const char* fname, LTE_DL_FRAME_PARMS *fr FILE *f_ptr; f_ptr = fopen(fname,"a"); + if (!f_ptr) + return -1; fprintf(f_ptr, "BB:EUTR:SLEN %d\n",slen); @@ -188,6 +192,8 @@ int smbv_configure_datalist_for_alloc(const char* fname, uint8_t alloc, uint8_t { FILE *f_ptr; f_ptr = fopen(fname,"a"); + if (!f_ptr) + return -1; char strbuf[(8<<1)+1]; int i,k; strbuf[0] = '\0'; @@ -245,6 +251,8 @@ int smbv_configure_datalist_for_user(const char* fname, uint8_t user, uint8_t *b { FILE *f_ptr; f_ptr = fopen(fname,"a"); + if (!f_ptr) + return -1; char strbuf[(8<<1)+1]; int i,k; @@ -284,6 +292,8 @@ int smbv_configure_user(const char* fname, uint8_t user, uint8_t transmission_mo { FILE *f_ptr; f_ptr = fopen(fname,"a"); + if (!f_ptr) + return -1; fprintf(f_ptr, "BB:EUTR:DL:USER%d:TXM M1\n",user); fprintf(f_ptr, "BB:EUTR:DL:USER%d:UEC USER\n",user); @@ -302,6 +312,8 @@ int smbv_configure_pdcch(const char* fname,uint8_t subframe,uint8_t num_pdcch_sy FILE *f_ptr; f_ptr = fopen(fname,"a"); + if (!f_ptr) + return -1; fprintf(f_ptr, "BB:EUTR:DL:SUBF%d:ENCC:PCF:CREG %d\n",subframe,num_pdcch_symbols); fprintf(f_ptr, "BB:EUTR:DL:SUBF%d:ENCC:PDCC:FORM VAR\n",subframe); @@ -325,6 +337,8 @@ int smbv_configure_common_dci(const char* fname, uint8_t subframe, const char* t void *dci_pdu = &dci_alloc->dci_pdu[0]; f_ptr = fopen(fname,"a"); + if (!f_ptr) + return -1; fprintf(f_ptr, "BB:EUTR:DL:SUBF%d:ENCC:STAT ON\n",subframe); @@ -383,6 +397,8 @@ int smbv_configure_ue_spec_dci(const char* fname, uint8_t subframe, uint8_t user void *dci_pdu = &dci_alloc->dci_pdu[0]; f_ptr = fopen(fname,"a"); + if (!f_ptr) + return -1; fprintf(f_ptr, "BB:EUTR:DL:SUBF%d:ENCC:STAT ON\n",subframe); fprintf(f_ptr, "BB:EUTR:DL:SUBF%d:ENCC:PDCC:EXTC:ITEM%d:USER USER%d\n",subframe,item,user); From 3190ad47b1df1a6757746303442ee434f5c1a083 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Tue, 5 Aug 2025 10:43:59 +0200 Subject: [PATCH 634/964] avoid a cppcheck warning --- executables/lte-enb.c | 3 ++- openair1/PHY/LTE_TRANSPORT/dci_tools.c | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/executables/lte-enb.c b/executables/lte-enb.c index 39f72db86c..c86a916c7a 100644 --- a/executables/lte-enb.c +++ b/executables/lte-enb.c @@ -1229,7 +1229,8 @@ void init_eNB() LOG_I(PHY,"Initializing eNB %d CC_id %d\n",inst,CC_id); LOG_I(PHY,"Initializing eNB %d CC_id %d\n",inst,CC_id); LOG_I(PHY,"Registering with MAC interface module\n"); - AssertFatal((eNB->if_inst = IF_Module_init(inst))!=NULL,"Cannot register interface"); + eNB->if_inst = IF_Module_init(inst); + AssertFatal(eNB->if_inst, "Cannot register interface"); eNB->if_inst->schedule_response = schedule_response; eNB->if_inst->PHY_config_req = phy_config_request; eNB->if_inst->PHY_config_update_sib2_req = phy_config_update_sib2_request; diff --git a/openair1/PHY/LTE_TRANSPORT/dci_tools.c b/openair1/PHY/LTE_TRANSPORT/dci_tools.c index 9c92503186..4e0a2163e3 100644 --- a/openair1/PHY/LTE_TRANSPORT/dci_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/dci_tools.c @@ -1993,6 +1993,7 @@ int get_narrowband_index(int N_RB_UL,int rb) { default: AssertFatal(1==0,"Impossible N_RB_UL %d\n",N_RB_UL); + return 0; break; } } @@ -2128,6 +2129,7 @@ int get_first_rb_in_narrowband(int N_RB_UL, default: AssertFatal(1==0,"Impossible N_RB_UL %d\n",N_RB_UL); + return 0; break; } } From bc238f9b2f44c279728799a0794c6330bf1e71a9 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Tue, 5 Aug 2025 10:46:29 +0200 Subject: [PATCH 635/964] fix as i can a error detected by cppcheck, w[lprime] is only 0, 1 or -1 --- openair1/PHY/LTE_TRANSPORT/edci.c | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/edci.c b/openair1/PHY/LTE_TRANSPORT/edci.c index 8370b35b49..977dbd9ca7 100644 --- a/openair1/PHY/LTE_TRANSPORT/edci.c +++ b/openair1/PHY/LTE_TRANSPORT/edci.c @@ -262,7 +262,6 @@ void generate_mdci_top(PHY_VARS_eNB *eNB, int frame, int subframe, int16_t amp, mDCI_ALLOC_t *mdci; int coded_bits; LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; - int i; int gain_lin_QPSK; uint16_t *mpdcchtab; uint32_t x1 = 0, x2 = 0, s = 0; @@ -277,7 +276,7 @@ void generate_mdci_top(PHY_VARS_eNB *eNB, int frame, int subframe, int16_t amp, int *w; LOG_D(PHY, "generate_mdci_top: num_dci %d\n", mpdcch->num_dci); - for (i = 0; i < mpdcch->num_dci; i++) { + for (int i = 0; i < mpdcch->num_dci; i++) { mdci = &mpdcch->mdci_alloc[i]; AssertFatal(fp->frame_type == FDD, "TDD is not yet supported for MPDCCH\n"); AssertFatal(fp->Ncp == NORMAL, "Extended Prefix not yet supported for MPDCCH\n"); @@ -358,14 +357,14 @@ void generate_mdci_top(PHY_VARS_eNB *eNB, int frame, int subframe, int16_t amp, if (re_offset > fp->ofdm_symbol_size) re_offset -= (fp->ofdm_symbol_size - 1); - int32_t *txF = &txdataF[0][symbol_offset+re_offset]; - int32_t yIQ; + c16_t *txF = (c16_t *)&txdataF[0][symbol_offset + re_offset]; + c16_t yIQ; - for (i = 0; i < (coded_bits >> 1); i++) { + for (int i = 0; i < (coded_bits >> 1); i++) { // QPSK modulation to yIQ - ((int16_t *) & yIQ)[0] = (*e_ptr == 1) ? -gain_lin_QPSK : gain_lin_QPSK; + yIQ.r = *e_ptr == 1 ? -gain_lin_QPSK : gain_lin_QPSK; e_ptr++; - ((int16_t *) & yIQ)[1] = (*e_ptr == 1) ? -gain_lin_QPSK : gain_lin_QPSK; + yIQ.i = *e_ptr == 1 ? -gain_lin_QPSK : gain_lin_QPSK; e_ptr++; txF[mpdcchtab[i]] = yIQ; /* @@ -406,7 +405,7 @@ void generate_mdci_top(PHY_VARS_eNB *eNB, int frame, int subframe, int16_t amp, int last_prb = (mdci->narrowband*6) + nb_i0 + 5; int soffset[4] = {5,6,12,13}; - for (int lprime=0,i=0; lprime<4; lprime++) { + for (int lprime=0,ii=0; lprime<4; lprime++) { for (int nprb=0; nprb<110; nprb++) { if (nprbN_RB_DL) { re_offset = fp->first_carrier_offset + (12 * nprb); @@ -414,11 +413,11 @@ void generate_mdci_top(PHY_VARS_eNB *eNB, int frame, int subframe, int16_t amp, if (re_offset > fp->ofdm_symbol_size) re_offset -= (fp->ofdm_symbol_size - 1); - txF = &txdataF[0][symbol_offset + re_offset + fp->ofdm_symbol_size*soffset[lprime]]; + txF = (c16_t *)&txdataF[0][symbol_offset + re_offset + fp->ofdm_symbol_size * soffset[lprime]]; } - for (int mprime=0; mprime<3; mprime++,i+=2) { - if ((i & 0x1f) == 0) { + for (int mprime=0; mprime<3; mprime++,ii+=2) { + if ((ii & 0x1f) == 0) { s = lte_gold_generic(&x1, &x2, reset); reset = 0; } @@ -426,8 +425,8 @@ void generate_mdci_top(PHY_VARS_eNB *eNB, int frame, int subframe, int16_t amp, // select PRBs corresponding to narrowband if ((nprb>= first_prb) && (nprb<= last_prb)) { - ((int16_t *) & yIQ)[0] = (((s >> (i & 0x1f)) & 1) == 1) ? -gain_lin_QPSK : gain_lin_QPSK; - ((int16_t *) & yIQ)[1] = (((s >> ((i + 1) & 0x1f)) & 1) == 1) ? -gain_lin_QPSK : gain_lin_QPSK; + yIQ.r = (s >> (ii & 0x1f)) & 1 ? -gain_lin_QPSK : gain_lin_QPSK; + yIQ.i = (s >> ((ii + 1) & 0x1f)) & 1 ? -gain_lin_QPSK : gain_lin_QPSK; AssertFatal(mdci->transmission_type==1,"transmission_type %d!=1, handle this ...\n",mdci->transmission_type); if (mdci->transmission_type==1) { // same thing on both 107 and 109 @@ -435,9 +434,9 @@ void generate_mdci_top(PHY_VARS_eNB *eNB, int frame, int subframe, int16_t amp, txF[1+(5*mprime)] = yIQ; } else { // put on selected antenna port with w sequence if (((mprime+nprb)&1) == 0) - txF[off+(5*mprime)] = yIQ*w[lprime]; + txF[off + (5 * mprime)] = (c16_t){yIQ.r * w[lprime], yIQ.i * w[lprime]}; else - txF[off+(5*mprime)] = yIQ*w[3-lprime]; + txF[off + (5 * mprime)] = (c16_t){yIQ.r * w[3 - lprime], yIQ.i * w[3 - lprime]}; } /* From 10f304d9dac585265e2f71c2ad7776405d422f80 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Tue, 5 Aug 2025 10:47:14 +0200 Subject: [PATCH 636/964] return a error case before a SEGV if the pointer is null --- openair1/PHY/LTE_TRANSPORT/prach.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/openair1/PHY/LTE_TRANSPORT/prach.c b/openair1/PHY/LTE_TRANSPORT/prach.c index 90c9d63925..979a145497 100644 --- a/openair1/PHY/LTE_TRANSPORT/prach.c +++ b/openair1/PHY/LTE_TRANSPORT/prach.c @@ -368,6 +368,11 @@ void rx_prach0(PHY_VARS_eNB *eNB, uint8_t update_TA = 4; uint8_t update_TA2 = 1; + if (!eNB) { + LOG_E(PHY, "inconsistent case\n"); + return; + } + switch (eNB->frame_parms.N_RB_DL) { case 6: update_TA = 16; From af125c39dfab820bc5890b569bc85b848bd64f19 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Tue, 5 Aug 2025 10:48:14 +0200 Subject: [PATCH 637/964] array test overflow and possible divide by 0 fixes --- openair1/PHY/LTE_UE_TRANSPORT/dci_tools_ue.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/openair1/PHY/LTE_UE_TRANSPORT/dci_tools_ue.c b/openair1/PHY/LTE_UE_TRANSPORT/dci_tools_ue.c index d8d3008be7..e567dc3d9b 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/dci_tools_ue.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/dci_tools_ue.c @@ -124,7 +124,7 @@ static int errorRB(int rb, char * table, int line) { return 0; } -#define rbAllocCheck(RBalL, TabLe) (RBalL) > sizeof(TabLe)/sizeof(*TabLe) ? errorRB(RBalL, #TabLe, __LINE__) : TabLe[RBalL] +#define rbAllocCheck(RBalL, TabLe) (RBalL) >= sizeof(TabLe) / sizeof(*TabLe) ? errorRB(RBalL, #TabLe, __LINE__) : TabLe[RBalL] void extract_dci1A_info(uint8_t N_RB_DL, frame_type_t frame_type, void *dci_pdu, DCI_INFO_EXTRACTED_t *pdci_info_extarcted) { uint8_t harq_pid=0; @@ -4965,7 +4965,8 @@ double sinr_eff_cqi_calc(PHY_VARS_UE *ue, uint8_t eNB_id, uint8_t subframe) } } - s_dB[count] = 10*log10(abs_channel/2) - meas->n0_power_avg_dB; + if (abs_channel > 0) + s_dB[count] = 10 * log10(abs_channel / 2.0) - meas->n0_power_avg_dB; } break; From c833aee524d4f1d124c2f6580f3cfa9b1720e131 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Tue, 9 Sep 2025 15:50:36 +0200 Subject: [PATCH 638/964] refine the LTE prach fix from cppcheck error detection --- openair1/PHY/LTE_TRANSPORT/prach.c | 42 +++++++++++++++++------------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/prach.c b/openair1/PHY/LTE_TRANSPORT/prach.c index 979a145497..6cb2de68d2 100644 --- a/openair1/PHY/LTE_TRANSPORT/prach.c +++ b/openair1/PHY/LTE_TRANSPORT/prach.c @@ -346,20 +346,31 @@ void rx_prach0(PHY_VARS_eNB *eNB, } } - if ((eNB==NULL) && ru->function == NGFI_RRU_IF4p5) { - /// **** send_IF4 of rxsigF to RAU **** /// - if (br_flag == 1) - send_IF4p5(ru, frame_prach, subframe, IF4p5_PRACH+1+ce_level); - else - send_IF4p5(ru, frame_prach, subframe, IF4p5_PRACH); - - return; - } else if (eNB!=NULL) { - if (LOG_DEBUGFLAG(DEBUG_PRACH)) { - int en = dB_fixed(signal_energy((int32_t *)&rxsigF[0][0],840)); - - if ((en > 10)&&(br_flag==1)) LOG_I(PHY,"PRACH (br_flag %d,ce_level %d, n_ra_prb %d, k %d): Frame %d, Subframe %d => %d dB\n",br_flag,ce_level,n_ra_prb,k,frame_prach,subframe,en); + if (!eNB) { + if (ru->function == NGFI_RRU_IF4p5) { + /// **** send_IF4 of rxsigF to RAU **** /// + if (br_flag == 1) + send_IF4p5(ru, frame_prach, subframe, IF4p5_PRACH + 1 + ce_level); + else + send_IF4p5(ru, frame_prach, subframe, IF4p5_PRACH); + } else { + LOG_E(PHY, "inconsistent case\n"); } + return; + } + + if (LOG_DEBUGFLAG(DEBUG_PRACH)) { + int en = dB_fixed(signal_energy((int32_t *)&rxsigF[0][0], 840)); + if ((en > 10) && (br_flag == 1)) + LOG_I(PHY, + "PRACH (br_flag %d,ce_level %d, n_ra_prb %d, k %d): Frame %d, Subframe %d => %d dB\n", + br_flag, + ce_level, + n_ra_prb, + k, + frame_prach, + subframe, + en); } // in case of RAU and prach received rx_thread wakes up prach @@ -368,11 +379,6 @@ void rx_prach0(PHY_VARS_eNB *eNB, uint8_t update_TA = 4; uint8_t update_TA2 = 1; - if (!eNB) { - LOG_E(PHY, "inconsistent case\n"); - return; - } - switch (eNB->frame_parms.N_RB_DL) { case 6: update_TA = 16; From bd6180e362e5c0d89c6790f04123a8dc274d22d7 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 22 Aug 2025 17:13:50 +0200 Subject: [PATCH 639/964] UL TDA: ensure we reach Msg3 in all cases In at least the case of mu=1, min_rxtxtime=2 and DDDSU with no UL symbols (for ULSCH) in the mixed slot, the current state of code does not allow a UE to attach. This is because at mu=1, Msg3 is k2+delta, where k2=min_rxtxtime and delta(mu)=3. Prior, this special case was handled because we had a dedicated Msg3 TDA, which in most cases is not necessary (because the mixed slot allocates the DCI, and the following mixed slot has the UL grant). Add code that tries to ensure that we only add the Msg3 TDA in cases when we need it. Fixes: 961a646dc756 ("Remove dedicated Msg3 TDA") --- openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c index 435ec2b6e8..6b808eebfa 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c @@ -1115,6 +1115,7 @@ void nr_rrc_config_ul_tda(NR_ServingCellConfigCommon_t *scc, int min_fb_delay, i int N_dl1 = p1->nrofDownlinkSlots; int N_ul1 = p1->nrofUplinkSlots; + int N_dl2 = p2 ? p2->nrofDownlinkSlots : 0; int N_ul2 = p2 ? p2->nrofUplinkSlots : 0; int tdd_period_idx = get_tdd_period_idx(scc->tdd_UL_DL_ConfigurationCommon); int nb_periods_per_frame = get_nb_periods_per_frame(tdd_period_idx); @@ -1155,6 +1156,22 @@ void nr_rrc_config_ul_tda(NR_ServingCellConfigCommon_t *scc, int min_fb_delay, i } } } + + // for Msg3, an additional get_delta_for_k2(mu) is added to k2. + // check that any UL slot is reachable under this condition + // the below is designed to only hit specific (known) cases + // examples: DDDSU (no TDA in S), + int N_dl = max(N_dl1, N_dl2); + int delta = get_delta_for_k2(mu); + int k2_msg3 = k2 + delta; + if (nb_slots_per_period % k2_msg3 == 0 /* see example above */ + && k2_msg3 > N_dl /* otherwise, can always have a D that reaches U */ + && k2_msg3 > N_ul /* otherwise, can always have a D that reaches U */ + && !has_ul_mixed /* if mixed slot, even for DDDSU would reach */) { + /* reach next UL from mixed slot in previous period */ + tda = set_TimeDomainResourceAllocation(k2_msg3, get_SLIV(0, 13)); + asn1cSeqAdd(&tda_list->list, tda); + } } AssertFatal(tda_list->list.count <= 16, "cannot reach all UL slots with current TDD configuration\n"); From 67cb3f026dc5cada517c674304487243d72a8531 Mon Sep 17 00:00:00 2001 From: Francesco Mani Date: Fri, 5 Sep 2025 09:27:46 +0200 Subject: [PATCH 640/964] Save PUSCH information for each (re-)transmission Instead of only saving this information in the first transmission, also store it on each retransmission. This should ensure that if some information changes, we always relate to the last transmission. For instance, power control information might have changed, and should be considered in subsequent rounds, if necessary. It also simplifies code. Fixes: 6294ce715e4d ("Reorder pf_ul to process retransmission") --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 704d2017c7..eaec37b159 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -2421,16 +2421,11 @@ void post_process_ulsch(gNB_MAC_INST *nr_mac, post_process_pusch_t *pusch, NR_UE /* Statistics */ AssertFatal(cur_harq->round < nr_mac->ul_bler.harq_round_max, "Indexing ulsch_rounds[%d] is out of bounds\n", cur_harq->round); UE->mac_stats.ul.rounds[cur_harq->round]++; + /* Save information on MCS, TBS etc for the current initial transmission + * so we have access to it when retransmitting */ + cur_harq->sched_pusch = *sched_pusch; if (cur_harq->round == 0) { UE->mac_stats.ulsch_total_bytes_scheduled += sched_pusch->tb_size; - /* Save information on MCS, TBS etc for the current initial transmission - * so we have access to it when retransmitting */ - cur_harq->sched_pusch = *sched_pusch; - /* save which time allocation and nrOfLayers have been used, to be used on - * retransmissions */ - cur_harq->sched_pusch.time_domain_allocation = sched_pusch->time_domain_allocation; - cur_harq->sched_pusch.nrOfLayers = sched_pusch->nrOfLayers; - cur_harq->sched_pusch.tpmi = sched_pusch->tpmi; sched_ctrl->sched_ul_bytes += sched_pusch->tb_size; UE->mac_stats.ul.total_rbs += sched_pusch->rbSize; From 9ba2e7ca5b0b0fbaab2e02bb82e363a88a5e60e6 Mon Sep 17 00:00:00 2001 From: Florian Kaltenberger Date: Thu, 4 Sep 2025 09:46:49 +0200 Subject: [PATCH 641/964] Revert "Removed TRP-scheme byte from UL BF PDU to Interop with Aerial 25-1 (FAPI 10.02)" This commit broke compatibility with Aerial when compiled with -DSCF_FAPI_10_04_SRS=ON. It was decided that this should become the default. This reverts commit 8beb382277a55ca00498317e6a5cdeb9f26bea00. --- nfapi/open-nFAPI/fapi/src/nr_fapi_p7.c | 4 ++-- nfapi/open-nFAPI/fapi/src/nr_fapi_p7_utils.c | 6 +++--- nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h | 2 +- nfapi/tests/p7/nr_fapi_ul_tti_request_test.c | 2 +- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/nfapi/open-nFAPI/fapi/src/nr_fapi_p7.c b/nfapi/open-nFAPI/fapi/src/nr_fapi_p7.c index befd2c9dd3..aa90d3b4b9 100644 --- a/nfapi/open-nFAPI/fapi/src/nr_fapi_p7.c +++ b/nfapi/open-nFAPI/fapi/src/nr_fapi_p7.c @@ -708,7 +708,7 @@ static uint8_t pack_nr_rx_beamforming_pdu(const nfapi_nr_ul_beamforming_t *beamf uint8_t **ppWritePackedMsg, uint8_t *end) { // Pack RX Beamforming PDU - if (!(push16(beamforming_pdu->num_prgs, ppWritePackedMsg, end) + if (!(push8(beamforming_pdu->trp_scheme, ppWritePackedMsg, end) && push16(beamforming_pdu->num_prgs, ppWritePackedMsg, end) && push16(beamforming_pdu->prg_size, ppWritePackedMsg, end) && push8(beamforming_pdu->dig_bf_interface, ppWritePackedMsg, end))) { return 0; @@ -1033,7 +1033,7 @@ uint8_t pack_ul_tti_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, static uint8_t unpack_nr_rx_beamforming_pdu(nfapi_nr_ul_beamforming_t *beamforming_pdu, uint8_t **ppReadPackedMsg, uint8_t *end) { // Unpack RX Beamforming PDU - if (!(pull16(ppReadPackedMsg, &beamforming_pdu->num_prgs, end) + if (!(pull8(ppReadPackedMsg, &beamforming_pdu->trp_scheme, end) && pull16(ppReadPackedMsg, &beamforming_pdu->num_prgs, end) && pull16(ppReadPackedMsg, &beamforming_pdu->prg_size, end) && pull8(ppReadPackedMsg, &beamforming_pdu->dig_bf_interface, end))) { return 0; 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 0a858e0be9..fb645707ad 100644 --- a/nfapi/open-nFAPI/fapi/src/nr_fapi_p7_utils.c +++ b/nfapi/open-nFAPI/fapi/src/nr_fapi_p7_utils.c @@ -214,7 +214,7 @@ bool eq_dl_tti_request(const nfapi_nr_dl_tti_request_t *a, const nfapi_nr_dl_tti static bool eq_ul_tti_beamforming(const nfapi_nr_ul_beamforming_t *a, const nfapi_nr_ul_beamforming_t *b) { - // EQ(a->trp_scheme, b->trp_scheme); + EQ(a->trp_scheme, b->trp_scheme); EQ(a->num_prgs, b->num_prgs); EQ(a->prg_size, b->prg_size); EQ(a->dig_bf_interface, b->dig_bf_interface); @@ -1174,7 +1174,7 @@ void copy_dl_tti_request(const nfapi_nr_dl_tti_request_t *src, nfapi_nr_dl_tti_r static void copy_ul_tti_beamforming(const nfapi_nr_ul_beamforming_t *src, nfapi_nr_ul_beamforming_t *dst) { - // dst->trp_scheme = src->trp_scheme; + dst->trp_scheme = src->trp_scheme; dst->num_prgs = src->num_prgs; dst->prg_size = src->prg_size; dst->dig_bf_interface = src->dig_bf_interface; @@ -2201,7 +2201,7 @@ void dump_dl_tti_request(const nfapi_nr_dl_tti_request_t *msg) static void dump_ul_tti_beamforming(const nfapi_nr_ul_beamforming_t *pdu, int depth) { - // INDENTED_PRINTF("TRP Scheme = %d\n", pdu->trp_scheme); + INDENTED_PRINTF("TRP Scheme = %d\n", pdu->trp_scheme); INDENTED_PRINTF("numPRGs = %d\n", pdu->num_prgs); INDENTED_PRINTF("prgSize = %d\n", pdu->prg_size); INDENTED_PRINTF("digBFInterface = %d\n", pdu->dig_bf_interface); 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 f186352b6d..a7e6b43af6 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 @@ -1219,7 +1219,7 @@ typedef struct typedef struct { - // uint8_t trp_scheme; // This field shall be set to 0, to identify that this table is used. Not part of FAPI 10.02, thus removed + uint8_t trp_scheme; // This field shall be set to 0, to identify that this table is used. uint16_t num_prgs; // Number of PRGs spanning this allocation. Value : 1->275 uint16_t prg_size; // Size in RBs of a precoding resource block group (PRG) – to which the same digital beamforming gets applied. Value: 1->275 uint8_t dig_bf_interface; // Number of logical antenna ports (parallel streams) resulting from the Rx combining. Value: 0->255 diff --git a/nfapi/tests/p7/nr_fapi_ul_tti_request_test.c b/nfapi/tests/p7/nr_fapi_ul_tti_request_test.c index 90b1625a7e..f7087c92ef 100644 --- a/nfapi/tests/p7/nr_fapi_ul_tti_request_test.c +++ b/nfapi/tests/p7/nr_fapi_ul_tti_request_test.c @@ -24,7 +24,7 @@ static void fill_ul_tti_request_beamforming(nfapi_nr_ul_beamforming_t *beamforming_pdu) { - // beamforming_pdu->trp_scheme = rand8(); // not part of 10.02 + beamforming_pdu->trp_scheme = rand8(); beamforming_pdu->num_prgs = rand16_range(1, NFAPI_MAX_NUM_PRGS); beamforming_pdu->prg_size = rand16_range(1, 275); beamforming_pdu->dig_bf_interface = rand8_range(1,NFAPI_MAX_NUM_BG_IF); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c index 45bb68fa5c..69458daf21 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c @@ -463,7 +463,7 @@ static void nr_configure_srs(gNB_MAC_INST *nrmac, srs_pdu->srs_parameters_v4.prg_size = 1; srs_pdu->srs_parameters_v4.num_total_ue_antennas = 1 << srs_pdu->num_ant_ports; if (srs_resource_set->usage == NR_SRS_ResourceSet__usage_beamManagement) { - // srs_pdu->beamforming.trp_scheme = 0; + srs_pdu->beamforming.trp_scheme = 0; srs_pdu->beamforming.num_prgs = m_SRS[srs_pdu->config_index]; srs_pdu->beamforming.prg_size = srs_pdu->srs_parameters_v4.srs_bandwidth_size; } From f977b6affd7b2d5bc8196937e2ae45ac6c9f589a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Soares=20Silva?= Date: Thu, 4 Sep 2025 14:57:58 +0100 Subject: [PATCH 642/964] Alter Aerial documentation to mention mandatory L1 compilation flag --- doc/Aerial_FAPI_Split_Tutorial.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/Aerial_FAPI_Split_Tutorial.md b/doc/Aerial_FAPI_Split_Tutorial.md index 942b706d37..08e66bdbba 100644 --- a/doc/Aerial_FAPI_Split_Tutorial.md +++ b/doc/Aerial_FAPI_Split_Tutorial.md @@ -66,6 +66,8 @@ The UEs that have been tested and confirmed working with Aerial are the followin To set up the L1 and install the components manually refer to this [instructions page](https://docs.nvidia.com/aerial/cuda-accelerated-ran/index.html). **Note**: +- As of wk36, the L1 must be compiled with the following CMake flag: `-DSCF_FAPI_10_04_SRS=ON` , this is due to the usage +of the FAPI 10.04 version of the SRS PDU, and RX_Beamforming PDU. - To configure the Gigabyte server please refer to these [instructions](https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/2025.w13/doc/Aerial_FAPI_Split_Tutorial.md) - The last release to support the Gigabyte server is **Aerial CUDA-Accelerated RAN 24-1**. From a9da4dba353cdb88418a361f60f515cfc2c2eabf Mon Sep 17 00:00:00 2001 From: Reem Bahsoun Date: Wed, 10 Sep 2025 13:10:52 +0200 Subject: [PATCH 643/964] New cuBB image compiled with -DSCF_FAPI_10_04_SRS=ON flag This flag will be used to compile the cuBB regardless of the use of SRS This is due to the RX_Beamforming PDU that's used following 222.10.04 --- ci-scripts/yaml_files/sa_gnb_aerial/docker-compose.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci-scripts/yaml_files/sa_gnb_aerial/docker-compose.yaml b/ci-scripts/yaml_files/sa_gnb_aerial/docker-compose.yaml index efc4d15b72..a5cf02cc40 100644 --- a/ci-scripts/yaml_files/sa_gnb_aerial/docker-compose.yaml +++ b/ci-scripts/yaml_files/sa_gnb_aerial/docker-compose.yaml @@ -23,7 +23,7 @@ services: - ../../../cmake_targets/share:/opt/cuBB/share userns_mode: host ipc: "shareable" - image: cubb-build:25-2 + image: cubb-build:25-2-srs environment: - cuBB_SDK=/opt/nvidia/cuBB command: bash -c "sudo rm -rf /tmp/phy.log && sudo chmod +x /opt/nvidia/cuBB/aerial_l1_entrypoint.sh && /opt/nvidia/cuBB/aerial_l1_entrypoint.sh" From 66f0d960d3161de4c103544fa51b86022cf54d0a Mon Sep 17 00:00:00 2001 From: Calvin Peyron Date: Mon, 8 Sep 2025 11:47:16 +0200 Subject: [PATCH 644/964] Physim doc: mention unmaintained simulators --- doc/physical-simulators.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/doc/physical-simulators.md b/doc/physical-simulators.md index 662daa2a95..600f46191e 100644 --- a/doc/physical-simulators.md +++ b/doc/physical-simulators.md @@ -159,3 +159,11 @@ For legacy support or archival purposes, you can still find this implementation ```bash git checkout 2025.w18 ``` + +# Unmaintained tests + +A few tests dedicated to 4G are unmaintained: + +- `mbmssim` +- `scansim` +- all simulators of format `www-tmyyyy` (for instance, `dlsim_tm4`) From cfe9bfecce18ddc7d65095e60b240805d501c9b1 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 22 Aug 2025 08:07:55 +0200 Subject: [PATCH 645/964] HTML report: Update to 2025 --- ci-scripts/cls_oai_html.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci-scripts/cls_oai_html.py b/ci-scripts/cls_oai_html.py index c4e13b2e62..7daa3e9321 100644 --- a/ci-scripts/cls_oai_html.py +++ b/ci-scripts/cls_oai_html.py @@ -247,7 +247,7 @@ class HTMLManagement(): self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write('

\n') - self.htmlFile.write('
End of Test Report -- Copyright 2018 OpenAirInterface. All Rights Reserved.
\n') + self.htmlFile.write('
End of Test Report -- Copyright 2025 OpenAirInterface. All Rights Reserved.
\n') self.htmlFile.write('\n') self.htmlFile.write('\n') self.htmlFile.close() From 582aeac49640a6513ac34ca1731aa1579e704859 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 22 Aug 2025 08:12:28 +0200 Subject: [PATCH 646/964] Remove superfluous HTML.CreateHtmlTabFooter() CreateHtmlTabFooter() is already called in main.py, at the end of an XML. This is enough, the others are "duplicates" that are not necessary. --- ci-scripts/cls_containerize.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index 7ee8dc4746..33dc39e3a4 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -362,7 +362,6 @@ class Containerize(): cmd.close() logging.error('\u001B[1m Building OAI Images Failed\u001B[0m') HTML.CreateHtmlTestRow(self.imageKind, 'KO', CONST.ALL_PROCESSES_OK) - HTML.CreateHtmlTabFooter(False) return False else: result = re.search(r'Size *= *(?P[0-9\-]+) *bytes', cmd.getBefore()) @@ -486,7 +485,6 @@ class Containerize(): logging.error('\u001B[1m Build of L2sim proxy failed\u001B[0m') ssh.close() HTML.CreateHtmlTestRow('commit ' + tag, 'KO', CONST.ALL_PROCESSES_OK) - HTML.CreateHtmlTabFooter(False) return False else: logging.debug('L2sim proxy image for tag ' + tag + ' already exists, skipping build') @@ -555,7 +553,6 @@ class Containerize(): if ret.returncode != 0: logging.error(f'No {baseImage} image present, cannot build tests') HTML.CreateHtmlTestRow(self.imageKind, 'KO', CONST.ALL_PROCESSES_OK) - HTML.CreateHtmlTabFooter(False) return False # build ran-unittests image @@ -566,7 +563,6 @@ class Containerize(): if ret.returncode != 0: logging.error(f'Cannot build unit tests') HTML.CreateHtmlTestRow("Unit test build failed", 'KO', [dockerfile]) - HTML.CreateHtmlTabFooter(False) return False HTML.CreateHtmlTestRowQueue("Build unit tests", 'OK', [dockerfile]) @@ -585,11 +581,9 @@ class Containerize(): if ret.returncode == 0: HTML.CreateHtmlTestRowQueue('Unit tests succeeded', 'OK', [ret.stdout]) - HTML.CreateHtmlTabFooter(True) return True else: HTML.CreateHtmlTestRowQueue('Unit tests failed (see also doc/UnitTests.md)', 'KO', [ret.stdout]) - HTML.CreateHtmlTabFooter(False) return False def Push_Image_to_Local_Registry(self, node, HTML, tag_prefix=""): From dd3ecbcf38a8a75b934fc507c65673f261ada8ca Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 26 Aug 2025 16:30:55 +0200 Subject: [PATCH 647/964] CI: Harmonize exec_script() API Instead of making the function a class member, make it an instance member because (1) it is more aligned with other functions, notably, run(), and (2) especially for RemoteCmd() it can be faster, as successive exec_script() calls do not require a new SSH connection. --- ci-scripts/cls_cluster.py | 3 ++- ci-scripts/cls_cmd.py | 20 +++++--------------- ci-scripts/cls_containerize.py | 3 ++- ci-scripts/cls_corenetwork.py | 3 ++- ci-scripts/cls_oaicitest.py | 3 ++- ci-scripts/tests/cmd.py | 18 ++++++++++++------ 6 files changed, 25 insertions(+), 25 deletions(-) diff --git a/ci-scripts/cls_cluster.py b/ci-scripts/cls_cluster.py index ae4e718ecf..2ffd94802e 100644 --- a/ci-scripts/cls_cluster.py +++ b/ci-scripts/cls_cluster.py @@ -426,7 +426,8 @@ class Cluster: logging.debug(f'Running physims from server: {node}') script = "scripts/oc-deploy-physims.sh" options = f"oaicicd-core-for-ci-ran {oc_release} {image_tag} {self.eNBSourceCodePath}" - ret = cls_cmd.runScript(node, script, 600, options) + with cls_cmd.getConnection(node) as c: + ret = c.exec_script(script, 600, options) logging.debug(f'"{script}" finished with code {ret.returncode}, output:\n{ret.stdout}') with cls_cmd.getConnection(node) as ssh: details_json = archiveArtifact(ssh, ctx, f'{self.eNBSourceCodePath}/ci-scripts/{oc_release}-tests.json') diff --git a/ci-scripts/cls_cmd.py b/ci-scripts/cls_cmd.py index fb074bdfce..9916049c11 100644 --- a/ci-scripts/cls_cmd.py +++ b/ci-scripts/cls_cmd.py @@ -45,12 +45,6 @@ def getConnection(host, d=None): else: return RemoteCmd(host, d=d) -def runScript(host, path, timeout, parameters=None, redirect=None, silent=False): - if is_local(host): - return LocalCmd.exec_script(path, timeout, parameters, redirect, silent) - else: - return RemoteCmd.exec_script(host, path, timeout, parameters, redirect, silent) - # provides a partial interface for the legacy SSHconnection class (getBefore(), command()) class Cmd(metaclass=abc.ABCMeta): def cd(self, d, silent=False): @@ -111,12 +105,12 @@ class LocalCmd(Cmd): logging.debug(f'Working dir is {self.cwd}') self.cp = sp.CompletedProcess(args='', returncode=0, stdout='') - def exec_script(path, timeout, parameters=None, redirect=None, silent=False): + def exec_script(self, path, timeout, parameters=None, redirect=None, silent=False): if redirect and not redirect.startswith("/"): raise ValueError(f"redirect must be absolute, but is {redirect}") c = f"{path} {parameters}" if parameters else path if not redirect: - ret = sp.run(c, shell=True, timeout=timeout, stdout=sp.PIPE, stderr=sp.STDOUT) + ret = sp.run(c, shell=True, cwd=self.cwd, timeout=timeout, stdout=sp.PIPE, stderr=sp.STDOUT) ret.stdout = ret.stdout.decode('utf-8').strip() else: with open(redirect, "w") as f: @@ -238,18 +232,15 @@ class RemoteCmd(Cmd): cfg['sock'] = paramiko.ProxyCommand(ucfg['proxycommand']) return cfg - def exec_script(host, path, timeout, parameters=None, redirect=None, silent=False): + def exec_script(self, path, timeout, parameters=None, redirect=None, silent=False): if redirect and not redirect.startswith("/"): raise ValueError(f"redirect must be absolute, but is {redirect}") p = parameters if parameters else "" r = f"> {redirect}" if redirect else "" if not silent: - logging.debug(f"local> ssh {host} bash -s {p} < {path} {r} # {path} from localhost") - client = RemoteCmd._ssh_init() - cfg = RemoteCmd._lookup_ssh_config(host) - client.connect(**cfg) + logging.debug(f"local> ssh {self.hostname} bash -s {p} < {path} {r}") bash_opt = 'BASH_XTRACEFD=1' # write bash set -x output to stdout, see bash(1) - stdin, stdout, stderr = client.exec_command(f"{bash_opt} bash -s {p} {r}", timeout=timeout) + stdin, stdout, stderr = self.client.exec_command(f"{bash_opt} bash -s {p} {r}", timeout=timeout) # open() the file f at path, read() it and write() it into the stdin of the bash -s cmd with open(path) as f: stdin.write(f.read()) @@ -259,7 +250,6 @@ class RemoteCmd(Cmd): if redirect: cmd += f" &> {redirect}" ret = sp.CompletedProcess(args=cmd, returncode=stdout.channel.recv_exit_status(), stdout=stdout.read(size=None) + stderr.read(size=None)) ret.stdout = ret.stdout.decode('utf-8').strip() - client.close() return ret def run(self, line, timeout=300, silent=False, reportNonZero=True): diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index 33dc39e3a4..8b5a817ac6 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -66,7 +66,8 @@ def CreateWorkspace(host, sourcePath, ranRepository, ranCommitID, ranTargetBranc ranTargetBranch = 'develop' options += f" {ranTargetBranch}" logging.info(f'execute "{script}" with options "{options}" on node {host}') - ret = cls_cmd.runScript(host, script, 90, options) + with cls_cmd.getConnection(host) as c: + ret = c.exec_script(script, 90, options) logging.debug(f'"{script}" finished with code {ret.returncode}, output:\n{ret.stdout}') return ret.returncode == 0 diff --git a/ci-scripts/cls_corenetwork.py b/ci-scripts/cls_corenetwork.py index ad83eae622..bfdaa77481 100644 --- a/ci-scripts/cls_corenetwork.py +++ b/ci-scripts/cls_corenetwork.py @@ -77,7 +77,8 @@ class CoreNetwork: words = line[1:].strip().split(" ") script_name = words[0] options = " ".join(words[1:]) - ret = cls_cmd.runScript(host, script_name, 300, parameters=options, silent=silent) + with cls_cmd.getConnection(host) as c: + ret = c.exec_script(script_name, 300, parameters=options, silent=silent) return ret def _command(self, cmd_list, must_succeed=False, silent=False): diff --git a/ci-scripts/cls_oaicitest.py b/ci-scripts/cls_oaicitest.py index 18631134c0..623bf3e5bf 100644 --- a/ci-scripts/cls_oaicitest.py +++ b/ci-scripts/cls_oaicitest.py @@ -234,7 +234,8 @@ def Custom_Command(HTML, node, command): def Custom_Script(HTML, node, script): logging.info(f"Executing custom script on {node}") - ret = cls_cmd.runScript(node, script, 90) + with cls_cmd.getConnection(node) as c: + ret = c.exec_script(script, 90) logging.debug(f"Custom_Script: {script} on node: {node} - return code {ret.returncode}, output:\n{ret.stdout}") status = 'OK' message = [ret.stdout] diff --git a/ci-scripts/tests/cmd.py b/ci-scripts/tests/cmd.py index 4d7aedfa0e..b9cbb6f51e 100644 --- a/ci-scripts/tests/cmd.py +++ b/ci-scripts/tests/cmd.py @@ -36,17 +36,20 @@ class TestCmd(unittest.TestCase): self.assertEqual(ret.stdout, "test") def test_local_script(self): - ret = cls_cmd.runScript("localhost", "tests/scripts/hello-world.sh", 1) + with cls_cmd.getConnection("localhost") as ssh: + ret = ssh.exec_script("tests/scripts/hello-world.sh", 1) self.assertEqual(ret.args, "tests/scripts/hello-world.sh") self.assertEqual(ret.returncode, 0) self.assertEqual(ret.stdout, "+ echo hello, world\nhello, world") - ret = cls_cmd.runScript("localhost", "tests/scripts/hello-fail.sh", 1, "TESTFAIL") + with cls_cmd.getConnection("localhost") as ssh: + ret = ssh.exec_script("tests/scripts/hello-fail.sh", 1, "TESTFAIL") self.assertEqual(ret.args, "tests/scripts/hello-fail.sh TESTFAIL") self.assertEqual(ret.returncode, 1) self.assertEqual(ret.stdout, "TESTFAIL") - ret = cls_cmd.runScript("localhost", "tests/scripts/hello-fail.sh", 1, "TESTFAIL2", "/tmp/result") + with cls_cmd.getConnection("localhost") as ssh: + ret = ssh.exec_script("tests/scripts/hello-fail.sh", 1, "TESTFAIL2", "/tmp/result") self.assertEqual(ret.args, "tests/scripts/hello-fail.sh TESTFAIL2 &> /tmp/result") self.assertEqual(ret.returncode, 1) self.assertEqual(ret.stdout, "") @@ -75,17 +78,20 @@ class TestCmd(unittest.TestCase): @unittest.skip("need to be able to passwordlessly SSH to localhost, also disable stty -ixon") def test_remote_script(self): - ret = cls_cmd.runScript("127.0.0.1", "tests/scripts/hello-world.sh", 1) + with cls_cmd.getConnection("127.0.0.1") as ssh: + ret = ssh.exec_script("tests/scripts/hello-world.sh", 1) self.assertEqual(ret.args, "tests/scripts/hello-world.sh") self.assertEqual(ret.returncode, 0) self.assertEqual(ret.stdout, "+ echo hello, world\nhello, world") - ret = cls_cmd.runScript("127.0.0.1", "tests/scripts/hello-fail.sh", 1, "TESTFAIL") + with cls_cmd.getConnection("127.0.0.1") as ssh: + ret = ssh.exec_script("tests/scripts/hello-fail.sh", 1, "TESTFAIL") self.assertEqual(ret.args, "tests/scripts/hello-fail.sh TESTFAIL") self.assertEqual(ret.returncode, 1) self.assertEqual(ret.stdout, "TESTFAIL") - ret = cls_cmd.runScript("127.0.0.1", "tests/scripts/hello-fail.sh", 1, "TESTFAIL2", "/tmp/result") + with cls_cmd.getConnection("127.0.0.1") as ssh: + ret = ssh.exec_script("tests/scripts/hello-fail.sh", 1, "TESTFAIL2", "/tmp/result") self.assertEqual(ret.args, "tests/scripts/hello-fail.sh TESTFAIL2 &> /tmp/result") self.assertEqual(ret.returncode, 1) self.assertEqual(ret.stdout, "") From 876d2b1b697a0c90a2e8bdd3254dc40918c2322a Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 22 Aug 2025 14:25:42 +0200 Subject: [PATCH 648/964] CI PhySims: archive LastTest.log LastTest.log has logs of all tests. It is a raw file from which we generate per-test logs, but it is useful to also archive this in case we need it. --- ci-scripts/cls_cluster.py | 1 + ci-scripts/scripts/oc-deploy-physims.sh | 1 + 2 files changed, 2 insertions(+) diff --git a/ci-scripts/cls_cluster.py b/ci-scripts/cls_cluster.py index 2ffd94802e..def8b1272f 100644 --- a/ci-scripts/cls_cluster.py +++ b/ci-scripts/cls_cluster.py @@ -435,6 +435,7 @@ class Cluster: archiveArtifact(ssh, ctx, f'{self.eNBSourceCodePath}/ci-scripts/physim_log.txt') archiveArtifact(ssh, ctx, f'{self.eNBSourceCodePath}/ci-scripts/physim_pods_summary.txt') archiveArtifact(ssh, ctx, f'{self.eNBSourceCodePath}/ci-scripts/LastTestsFailed.log') + archiveArtifact(ssh, ctx, f'{self.eNBSourceCodePath}/ci-scripts/LastTest.log') test_status, test_summary, test_result = cls_analysis.Analysis.analyze_oc_physim(result_junit, details_json, ctx.logPath) if test_summary: if test_status: diff --git a/ci-scripts/scripts/oc-deploy-physims.sh b/ci-scripts/scripts/oc-deploy-physims.sh index ddb2e964ef..c46b900bdc 100755 --- a/ci-scripts/scripts/oc-deploy-physims.sh +++ b/ci-scripts/scripts/oc-deploy-physims.sh @@ -23,6 +23,7 @@ oc logs -f -n ${OC_NS} "$POD_ID" | while read -r line; do oc logs -n ${OC_NS} "$POD_ID" >> ${OAI_DIR}/ci-scripts/physim_log.txt oc describe pod $POD_ID >> ${OAI_DIR}/ci-scripts/physim_pods_summary.txt oc cp "$POD_ID":/opt/oai-physim/Testing/Temporary/LastTestsFailed.log ${OAI_DIR}/ci-scripts/LastTestsFailed.log + oc cp "$POD_ID":/opt/oai-physim/Testing/Temporary/LastTest.log ${OAI_DIR}/ci-scripts/LastTest.log oc cp "$POD_ID":/opt/oai-physim/${OC_RELEASE}-tests.json ${OAI_DIR}/ci-scripts/${OC_RELEASE}-tests.json oc cp "$POD_ID":/opt/oai-physim/${OC_RELEASE}-run.xml ${OAI_DIR}/ci-scripts/${OC_RELEASE}-run.xml break From deadd5414df68eca747eaeb822c6738657283409 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 22 Aug 2025 14:39:24 +0200 Subject: [PATCH 649/964] CI: Generalizce deploy_oc_physim() A future commit will enable to deploy physical simulators via docker. Hence: - Move the script to run out of deploy_oc_physim(), to make it more generic (later commits will introduce other scripts) - pass the working directory (the function will be moved into cls_oaicitest, as it fits neither cls_containerize nor cls_cluster when deploying the tests from source) - not using ci-scripts: don't hardcode a specific path, just use the working directory - avoid helm-specific pods summary, and put it into the general "physim logs" - remove helm-specific "release", and use a generic name for results - always log pod logs and status to debug, even if deployment was not successful or tests did not finish. --- ci-scripts/cls_cluster.py | 19 ++++++------------- ci-scripts/main.py | 6 +++++- ci-scripts/scripts/oc-deploy-physims.sh | 12 ++++++------ 3 files changed, 17 insertions(+), 20 deletions(-) diff --git a/ci-scripts/cls_cluster.py b/ci-scripts/cls_cluster.py index def8b1272f..0db451b63c 100644 --- a/ci-scripts/cls_cluster.py +++ b/ci-scripts/cls_cluster.py @@ -418,24 +418,17 @@ class Cluster: return status - def deploy_oc_physim(self, ctx, HTML, oc_release, node): - if self.ranRepository == '' or self.ranBranch == '' or self.ranCommitID == '': - HELP.GenericHelp(CONST.Version) - raise ValueError(f'Insufficient Parameter: ranRepository {self.ranRepository} ranBranch {self.ranBranch} ranCommitID {self.ranCommitID}') - image_tag = cls_containerize.CreateTag(self.ranCommitID, self.ranBranch, self.ranAllowMerge) + def deploy_oc_physim(self, ctx, HTML, node, workdir, script, options): logging.debug(f'Running physims from server: {node}') - script = "scripts/oc-deploy-physims.sh" - options = f"oaicicd-core-for-ci-ran {oc_release} {image_tag} {self.eNBSourceCodePath}" with cls_cmd.getConnection(node) as c: ret = c.exec_script(script, 600, options) logging.debug(f'"{script}" finished with code {ret.returncode}, output:\n{ret.stdout}') with cls_cmd.getConnection(node) as ssh: - details_json = archiveArtifact(ssh, ctx, f'{self.eNBSourceCodePath}/ci-scripts/{oc_release}-tests.json') - result_junit = archiveArtifact(ssh, ctx, f'{self.eNBSourceCodePath}/ci-scripts/{oc_release}-run.xml') - archiveArtifact(ssh, ctx, f'{self.eNBSourceCodePath}/ci-scripts/physim_log.txt') - archiveArtifact(ssh, ctx, f'{self.eNBSourceCodePath}/ci-scripts/physim_pods_summary.txt') - archiveArtifact(ssh, ctx, f'{self.eNBSourceCodePath}/ci-scripts/LastTestsFailed.log') - archiveArtifact(ssh, ctx, f'{self.eNBSourceCodePath}/ci-scripts/LastTest.log') + details_json = archiveArtifact(ssh, ctx, f'{workdir}/desc-tests.json') + result_junit = archiveArtifact(ssh, ctx, f'{workdir}/results-run.xml') + archiveArtifact(ssh, ctx, f'{workdir}/physim_log.txt') + archiveArtifact(ssh, ctx, f'{workdir}/LastTestsFailed.log') + archiveArtifact(ssh, ctx, f'{workdir}/LastTest.log') test_status, test_summary, test_result = cls_analysis.Analysis.analyze_oc_physim(result_junit, details_json, ctx.logPath) if test_summary: if test_status: diff --git a/ci-scripts/main.py b/ci-scripts/main.py index cbc03a47d5..36608a4fec 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -245,7 +245,11 @@ def ExecuteActionWithParam(action, ctx): elif action == 'Deploy_Run_PhySim': oc_release = test.findtext('oc_release') node = test.findtext('node') or None - success = CLUSTER.deploy_oc_physim(ctx, HTML, oc_release, node) + script = "scripts/oc-deploy-physims.sh" + image_tag = cls_containerize.CreateTag(CLUSTER.ranCommitID, CLUSTER.ranBranch, CLUSTER.ranAllowMerge) + options = f"oaicicd-core-for-ci-ran {oc_release} {image_tag} {CLUSTER.eNBSourceCodePath}" + workdir = CLUSTER.eNBSourceCodePath + success = CLUSTER.deploy_oc_physim(ctx, HTML, node, workdir, script, options) elif action == 'DeployCoreNetwork' or action == 'UndeployCoreNetwork': cn_id = test.findtext('cn_id') diff --git a/ci-scripts/scripts/oc-deploy-physims.sh b/ci-scripts/scripts/oc-deploy-physims.sh index c46b900bdc..953e541770 100755 --- a/ci-scripts/scripts/oc-deploy-physims.sh +++ b/ci-scripts/scripts/oc-deploy-physims.sh @@ -20,15 +20,15 @@ echo "Monitoring logs for 'FINISHED' in pod '$POD_ID'" oc logs -f -n ${OC_NS} "$POD_ID" | while read -r line; do if [[ "$line" == *"FINISHED"* ]]; then echo "'FINISHED' detected in logs. Copying logs..." - oc logs -n ${OC_NS} "$POD_ID" >> ${OAI_DIR}/ci-scripts/physim_log.txt - oc describe pod $POD_ID >> ${OAI_DIR}/ci-scripts/physim_pods_summary.txt - oc cp "$POD_ID":/opt/oai-physim/Testing/Temporary/LastTestsFailed.log ${OAI_DIR}/ci-scripts/LastTestsFailed.log - oc cp "$POD_ID":/opt/oai-physim/Testing/Temporary/LastTest.log ${OAI_DIR}/ci-scripts/LastTest.log - oc cp "$POD_ID":/opt/oai-physim/${OC_RELEASE}-tests.json ${OAI_DIR}/ci-scripts/${OC_RELEASE}-tests.json - oc cp "$POD_ID":/opt/oai-physim/${OC_RELEASE}-run.xml ${OAI_DIR}/ci-scripts/${OC_RELEASE}-run.xml + oc cp "$POD_ID":/opt/oai-physim/Testing/Temporary/LastTestsFailed.log ${OAI_DIR}/LastTestsFailed.log + oc cp "$POD_ID":/opt/oai-physim/Testing/Temporary/LastTest.log ${OAI_DIR}/LastTest.log + oc cp "$POD_ID":/opt/oai-physim/${OC_RELEASE}-tests.json ${OAI_DIR}/desc-tests.json + oc cp "$POD_ID":/opt/oai-physim/${OC_RELEASE}-run.xml ${OAI_DIR}/results-run.xml break fi done +oc logs -n ${OC_NS} "$POD_ID" >> ${OAI_DIR}/physim_log.txt +oc describe pod $POD_ID >> ${OAI_DIR}/physim_log.txt helm uninstall ${OC_RELEASE} --wait oc delete istag oai-physim:${IMG_TAG} -n ${OC_NS} oc logout > /dev/null From 0ff85ff2c06f3e6a1e1ebcea6e447c38cbd9e2ee Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 22 Aug 2025 14:40:52 +0200 Subject: [PATCH 650/964] Rename PhySim deployment task to Deploy_Run_OC_PhySim A future commit will introduce the possibility to deploy physims using docker, so rename the current step to reflect that it works via OpenShift. --- ci-scripts/main.py | 2 +- ci-scripts/xml_class_list.yml | 2 +- ci-scripts/xml_files/physim_4g_deploy_run.xml | 2 +- ci-scripts/xml_files/physim_5g_deploy_run.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 36608a4fec..cdbf6c64d9 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -242,7 +242,7 @@ def ExecuteActionWithParam(action, ctx): st = test.findtext('idle_sleep_time_in_sec') or "5" success = cls_oaicitest.IdleSleep(HTML, int(st)) - elif action == 'Deploy_Run_PhySim': + elif action == 'Deploy_Run_OC_PhySim': oc_release = test.findtext('oc_release') node = test.findtext('node') or None script = "scripts/oc-deploy-physims.sh" diff --git a/ci-scripts/xml_class_list.yml b/ci-scripts/xml_class_list.yml index 211e02d4c1..88d782cd5b 100755 --- a/ci-scripts/xml_class_list.yml +++ b/ci-scripts/xml_class_list.yml @@ -23,7 +23,7 @@ - Deploy_Object - Undeploy_Object - Cppcheck_Analysis - - Deploy_Run_PhySim + - Deploy_Run_OC_PhySim - LicenceAndFormattingCheck - Push_Local_Registry - Pull_Local_Registry diff --git a/ci-scripts/xml_files/physim_4g_deploy_run.xml b/ci-scripts/xml_files/physim_4g_deploy_run.xml index bdad3e412f..cd34037760 100644 --- a/ci-scripts/xml_files/physim_4g_deploy_run.xml +++ b/ci-scripts/xml_files/physim_4g_deploy_run.xml @@ -37,7 +37,7 @@
- Deploy_Run_PhySim + Deploy_Run_OC_PhySim Deploy and run physical simulator on openshift physims-4g avra diff --git a/ci-scripts/xml_files/physim_5g_deploy_run.xml b/ci-scripts/xml_files/physim_5g_deploy_run.xml index 08de47aaac..1967003124 100644 --- a/ci-scripts/xml_files/physim_5g_deploy_run.xml +++ b/ci-scripts/xml_files/physim_5g_deploy_run.xml @@ -37,7 +37,7 @@ - Deploy_Run_PhySim + Deploy_Run_OC_PhySim Deploy and run physical simulator on openshift physims-5g avra From c4a0c3b05e345adc1a654722356b66e0ca94a2ef Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 22 Aug 2025 14:45:28 +0200 Subject: [PATCH 651/964] Rename to deploy_physim() deploy_oc_physim() is not specific to OpenShift anymore, so rename to a neutral name. --- ci-scripts/cls_cluster.py | 27 --------------------------- ci-scripts/cls_oaicitest.py | 27 +++++++++++++++++++++++++++ ci-scripts/main.py | 2 +- 3 files changed, 28 insertions(+), 28 deletions(-) diff --git a/ci-scripts/cls_cluster.py b/ci-scripts/cls_cluster.py index 0db451b63c..4e13cdf7b3 100644 --- a/ci-scripts/cls_cluster.py +++ b/ci-scripts/cls_cluster.py @@ -34,7 +34,6 @@ import time import os import cls_oai_html -import cls_analysis import constants as CONST import helpreadme as HELP import cls_containerize @@ -417,29 +416,3 @@ class Cluster: c.run(f'cp -r {ctx.logPath} {os.getcwd()}/test_log_{ctx.test_id}/') return status - - def deploy_oc_physim(self, ctx, HTML, node, workdir, script, options): - logging.debug(f'Running physims from server: {node}') - with cls_cmd.getConnection(node) as c: - ret = c.exec_script(script, 600, options) - logging.debug(f'"{script}" finished with code {ret.returncode}, output:\n{ret.stdout}') - with cls_cmd.getConnection(node) as ssh: - details_json = archiveArtifact(ssh, ctx, f'{workdir}/desc-tests.json') - result_junit = archiveArtifact(ssh, ctx, f'{workdir}/results-run.xml') - archiveArtifact(ssh, ctx, f'{workdir}/physim_log.txt') - archiveArtifact(ssh, ctx, f'{workdir}/LastTestsFailed.log') - archiveArtifact(ssh, ctx, f'{workdir}/LastTest.log') - test_status, test_summary, test_result = cls_analysis.Analysis.analyze_oc_physim(result_junit, details_json, ctx.logPath) - if test_summary: - if test_status: - HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) - HTML.CreateHtmlTestRowPhySimTestResult(test_summary, test_result) - logging.info('\u001B[1m Physical Simulator Pass\u001B[0m') - else: - HTML.CreateHtmlTestRowQueue('At least one physical simulator test failed!', 'KO', ["See below for details"]) - HTML.CreateHtmlTestRowPhySimTestResult(test_summary, test_result) - logging.error('\u001B[1m Physical Simulator Fail\u001B[0m') - else: - HTML.CreateHtmlTestRowQueue('Physical simulator failed', 'KO', [test_result]) - logging.error('\u001B[1m Physical Simulator Fail\u001B[0m') - return test_status diff --git a/ci-scripts/cls_oaicitest.py b/ci-scripts/cls_oaicitest.py index 623bf3e5bf..69a06f906b 100644 --- a/ci-scripts/cls_oaicitest.py +++ b/ci-scripts/cls_oaicitest.py @@ -46,6 +46,7 @@ import constants as CONST import cls_module import cls_corenetwork +import cls_analysis import cls_cmd from cls_ci_helper import archiveArtifact @@ -250,6 +251,32 @@ def IdleSleep(HTML, idle_sleep_time): HTML.CreateHtmlTestRow(f"{idle_sleep_time} sec", 'OK', CONST.ALL_PROCESSES_OK) return True +def Deploy_Physim(ctx, HTML, node, workdir, script, options): + logging.debug(f'Running physims on server {node} workdir {workdir}') + with cls_cmd.getConnection(node) as c: + ret = c.exec_script(script, 600, options) + logging.debug(f'"{script}" finished with code {ret.returncode}, output:\n{ret.stdout}') + with cls_cmd.getConnection(node) as ssh: + details_json = archiveArtifact(ssh, ctx, f'{workdir}/desc-tests.json') + result_junit = archiveArtifact(ssh, ctx, f'{workdir}/results-run.xml') + archiveArtifact(ssh, ctx, f'{workdir}/physim_log.txt') + archiveArtifact(ssh, ctx, f'{workdir}/LastTestsFailed.log') + archiveArtifact(ssh, ctx, f'{workdir}/LastTest.log') + test_status, test_summary, test_result = cls_analysis.Analysis.analyze_oc_physim(result_junit, details_json, ctx.logPath) + if test_summary: + if test_status: + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) + HTML.CreateHtmlTestRowPhySimTestResult(test_summary, test_result) + logging.info('\u001B[1m Physical Simulator Pass\u001B[0m') + else: + HTML.CreateHtmlTestRowQueue('At least one physical simulator test failed!', 'KO', ["See below for details"]) + HTML.CreateHtmlTestRowPhySimTestResult(test_summary, test_result) + logging.error('\u001B[1m Physical Simulator Fail\u001B[0m') + else: + HTML.CreateHtmlTestRowQueue('Physical simulator failed', 'KO', [test_result]) + logging.error('\u001B[1m Physical Simulator Fail\u001B[0m') + return test_status + #----------------------------------------------------------- # OaiCiTest Class Definition #----------------------------------------------------------- diff --git a/ci-scripts/main.py b/ci-scripts/main.py index cdbf6c64d9..e6b8c68cc1 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -249,7 +249,7 @@ def ExecuteActionWithParam(action, ctx): image_tag = cls_containerize.CreateTag(CLUSTER.ranCommitID, CLUSTER.ranBranch, CLUSTER.ranAllowMerge) options = f"oaicicd-core-for-ci-ran {oc_release} {image_tag} {CLUSTER.eNBSourceCodePath}" workdir = CLUSTER.eNBSourceCodePath - success = CLUSTER.deploy_oc_physim(ctx, HTML, node, workdir, script, options) + success = cls_oaicitest.Deploy_Physim(ctx, HTML, node, workdir, script, options) elif action == 'DeployCoreNetwork' or action == 'UndeployCoreNetwork': cn_id = test.findtext('cn_id') From 1120d41dd625b8676704f9d25c1c28ecefa2442b Mon Sep 17 00:00:00 2001 From: Nick Hedberg Date: Fri, 29 Aug 2025 15:30:41 +0000 Subject: [PATCH 652/964] Populate sampled_ue_antennas --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c index 45bb68fa5c..86e9f9fcd3 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c @@ -462,6 +462,12 @@ static void nr_configure_srs(gNB_MAC_INST *nrmac, srs_pdu->srs_parameters_v4.iq_representation = 1; srs_pdu->srs_parameters_v4.prg_size = 1; srs_pdu->srs_parameters_v4.num_total_ue_antennas = 1 << srs_pdu->num_ant_ports; + /* For srs usage: codebook, this is a bitmask of the antenna ports that should be used for data. + * num_ant_ports num_total_ue_antennas sampled_ue_antennas + * 0 1 1 + * 1 2 3 + * 2 4 15 */ + srs_pdu->srs_parameters_v4.sampled_ue_antennas = (2 << srs_pdu->num_ant_ports) - 1; if (srs_resource_set->usage == NR_SRS_ResourceSet__usage_beamManagement) { // srs_pdu->beamforming.trp_scheme = 0; srs_pdu->beamforming.num_prgs = m_SRS[srs_pdu->config_index]; From 7e6826ec036cf1efa4a233f8479951048151b685 Mon Sep 17 00:00:00 2001 From: rmagueta Date: Fri, 11 Apr 2025 18:33:29 +0100 Subject: [PATCH 653/964] Refactor and minor improvements in get_MeasConfig function --- openair2/RRC/NR/MESSAGES/asn1_msg.c | 79 ++++++++++++++++++++--------- openair2/RRC/NR/MESSAGES/asn1_msg.h | 1 + openair2/RRC/NR/rrc_gNB.c | 27 ++++++---- 3 files changed, 72 insertions(+), 35 deletions(-) diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.c b/openair2/RRC/NR/MESSAGES/asn1_msg.c index e6816bfcbd..3ff6aecea9 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.c +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.c @@ -995,22 +995,32 @@ static NR_MeasIdToAddMod_t *get_MeasId(NR_MeasId_t measId, NR_ReportConfigId_t r NR_MeasConfig_t *get_MeasConfig(const NR_MeasTiming_t *mt, int band, int scs, + int nr_pci, NR_ReportConfigToAddMod_t *rc_PER, NR_ReportConfigToAddMod_t *rc_A2, seq_arr_t *rc_A3_seq, seq_arr_t *neigh_seq) { + DevAssert(mt != NULL && mt->frequencyAndTiming != NULL); + const struct NR_MeasTiming__frequencyAndTiming *ft = mt->frequencyAndTiming; + NR_MeasConfig_t *mc = calloc_or_fail(1, sizeof(*mc)); mc->measObjectToAddModList = calloc_or_fail(1, sizeof(*mc->measObjectToAddModList)); mc->reportConfigToAddModList = calloc_or_fail(1, sizeof(*mc->reportConfigToAddModList)); mc->measIdToAddModList = calloc_or_fail(1, sizeof(*mc->measIdToAddModList)); + // Report Configuration: A reporting configuration defines the reporting criteria. The reporting criteria are classified as event + // triggered reporting, periodic reporting, CGI reporting or SFTD reporting. + + // Periodic report if (rc_PER) asn1cSeqAdd(&mc->reportConfigToAddModList->list, rc_PER); + // Event A2 if (rc_A2) asn1cSeqAdd(&mc->reportConfigToAddModList->list, rc_A2); + // Event A3 if (rc_A3_seq) { for (int i = 0; i < rc_A3_seq->size; i++) { NR_ReportConfigToAddMod_t *rc_A3 = (NR_ReportConfigToAddMod_t *)seq_arr_at(rc_A3_seq, i); @@ -1018,33 +1028,19 @@ NR_MeasConfig_t *get_MeasConfig(const NR_MeasTiming_t *mt, } } - DevAssert(mt != NULL && mt->frequencyAndTiming != NULL); - const struct NR_MeasTiming__frequencyAndTiming *ft = mt->frequencyAndTiming; - // Measurement Objects: Specifies what is to be measured. For NR and inter-RAT E-UTRA measurements, this may include // cell-specific offsets, blacklisted cells to be ignored and whitelisted cells to consider for measurements. + + // Serving cell NR_MeasObjectToAddMod_t *mo1 = get_MeasObject(ft, band, ft->carrierFreq, 1); - if (neigh_seq) { - NR_MeasObjectNR_t *monr1 = mo1->measObject.choice.measObjectNR; - if (monr1->cellsToAddModList == NULL) - monr1->cellsToAddModList = calloc_or_fail(1, sizeof(*monr1->cellsToAddModList)); - FOR_EACH_SEQ_ARR(nr_neighbour_cell_t *, n, neigh_seq) { - NR_CellsToAddMod_t *cell = calloc_or_fail(1, sizeof(*cell)); - cell->physCellId = n->physicalCellId; - ASN_SEQUENCE_ADD(&monr1->cellsToAddModList->list, cell); - } - } + NR_MeasObjectNR_t *monr1 = mo1->measObject.choice.measObjectNR; + monr1->cellsToAddModList = calloc_or_fail(1, sizeof(*monr1->cellsToAddModList)); + NR_CellsToAddMod_t *cell = calloc_or_fail(1, sizeof(*cell)); + cell->physCellId = nr_pci; + ASN_SEQUENCE_ADD(&monr1->cellsToAddModList->list, cell); asn1cSeqAdd(&mc->measObjectToAddModList->list, mo1); - // Preparation of measId - uint8_t reportIdx = 0; - for (; reportIdx < mc->reportConfigToAddModList->list.count; reportIdx++) { - const NR_ReportConfigId_t reportId = mc->reportConfigToAddModList->list.array[reportIdx]->reportConfigId; - NR_MeasIdToAddMod_t *measid = get_MeasId(reportIdx + 1, reportId, 1); - asn1cSeqAdd(&mc->measIdToAddModList->list, measid); - } - - // Preparation of measId for neighbour cells for periodic report + // Neighbour cells if (neigh_seq) { int mo_id = 2; FOR_EACH_SEQ_ARR(nr_neighbour_cell_t *, neigh_cell, neigh_seq) { @@ -1055,13 +1051,46 @@ NR_MeasConfig_t *get_MeasConfig(const NR_MeasTiming_t *mt, cell->physCellId = neigh_cell->physicalCellId; ASN_SEQUENCE_ADD(&monr->cellsToAddModList->list, cell); asn1cSeqAdd(&mc->measObjectToAddModList->list, mo_neighbour); - NR_MeasIdToAddMod_t *measid = get_MeasId(reportIdx + 1, rc_PER->reportConfigId, mo_id); - asn1cSeqAdd(&mc->measIdToAddModList->list, measid); - reportIdx++; mo_id++; } } + // Measurement identities: A list of measurement identities where each measurement identity links one measurement object with one + // reporting configuration. By configuring multiple measurement identities, it is possible to link more than one measurement + // object to the same reporting configuration, as well as to link more than one reporting configuration to the same measurement + // object. + + // MeasId for Periodic report + int meas_idx = 0; + if (rc_PER) { + for (; meas_idx < mc->measObjectToAddModList->list.count; meas_idx++) { + const NR_MeasObjectId_t measObjectId = mc->measObjectToAddModList->list.array[meas_idx]->measObjectId; + NR_MeasIdToAddMod_t *measid = get_MeasId(meas_idx + 1, rc_PER->reportConfigId, measObjectId); + asn1cSeqAdd(&mc->measIdToAddModList->list, measid); + } + } + + // MeasId for Event A2 + if (rc_A2) { + NR_MeasIdToAddMod_t *measid_A2 = get_MeasId(meas_idx + 1, rc_A2->reportConfigId, 1); + meas_idx++; + asn1cSeqAdd(&mc->measIdToAddModList->list, measid_A2); + } + + // MeasId for Event A3 + if (neigh_seq) { + int i = 0; + FOR_EACH_SEQ_ARR(nr_neighbour_cell_t *, neigh_cell, neigh_seq) { + NR_ReportConfigId_t reportConfigId = neigh_cell->physicalCellId == -1 ? 3 : i + 4; + NR_MeasIdToAddMod_t *measid_A3 = get_MeasId(meas_idx + 1, reportConfigId, i + 2); + meas_idx++; + asn1cSeqAdd(&mc->measIdToAddModList->list, measid_A3); + i++; + } + } + + // Quantity configurations: The quantity configuration defines the measurement filtering configuration used for measurement event + // evaluation and related reporting, and for periodical reporting of that measurement. mc->quantityConfig = calloc_or_fail(1, sizeof(*mc->quantityConfig)); mc->quantityConfig->quantityConfigNR_List = calloc_or_fail(1, sizeof(*mc->quantityConfig->quantityConfigNR_List)); NR_QuantityConfigNR_t *qcnr = calloc_or_fail(1, sizeof(*qcnr)); diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.h b/openair2/RRC/NR/MESSAGES/asn1_msg.h index 432db0e5cd..dde62d142f 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.h +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.h @@ -153,6 +153,7 @@ int do_RRCReestablishmentComplete(uint8_t *buffer, size_t buffer_size, int64_t r NR_MeasConfig_t *get_MeasConfig(const NR_MeasTiming_t *mt, int band, int scs, + int nr_pci, NR_ReportConfigToAddMod_t *rc_PER, NR_ReportConfigToAddMod_t *rc_A2, seq_arr_t *rc_A3_seq, diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 000c4f46cb..0e5912aafe 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -544,12 +544,12 @@ static NR_ReportConfigToAddMod_t *prepare_a2_event_report(const nr_a2_event_t *a return rc_A2; } -static NR_ReportConfigToAddMod_t *prepare_a3_event_report(const nr_a3_event_t *a3_event) +static NR_ReportConfigToAddMod_t *prepare_a3_event_report(const nr_a3_event_t *a3_event, NR_ReportConfigId_t reportConfigId) { NR_ReportConfigToAddMod_t *rc_A3 = calloc(1, sizeof(*rc_A3)); // 3 is default A3 Report Config ID. So cellId(0) specific Report Config ID // starts from 4 - rc_A3->reportConfigId = a3_event->pci == -1 ? 3 : a3_event->pci + 4; + rc_A3->reportConfigId = reportConfigId; rc_A3->reportConfig.present = NR_ReportConfigToAddMod__reportConfig_PR_reportConfigNR; NR_EventTriggerConfig_t *etrc_A3 = calloc(1, sizeof(*etrc_A3)); etrc_A3->eventId.present = NR_EventTriggerConfig__eventId_PR_eventA3; @@ -593,6 +593,7 @@ NR_MeasConfig_t *nr_rrc_get_measconfig(const gNB_RRC_INST *rrc, uint64_t nr_cell NR_ReportConfigToAddMod_t *rc_PER = NULL; NR_ReportConfigToAddMod_t *rc_A2 = NULL; seq_arr_t *rc_A3_seq = NULL; + seq_arr_t *neigh_seq = NULL; if (du->mtc != NULL) { int scs = get_ssb_scs(cell_info); int band = get_dl_band(cell_info); @@ -609,24 +610,30 @@ NR_MeasConfig_t *nr_rrc_get_measconfig(const gNB_RRC_INST *rrc, uint64_t nr_cell If default one added once as a report, no need to add it again && duplication. */ rc_A3_seq = malloc(sizeof(seq_arr_t)); + neigh_seq = malloc(sizeof(seq_arr_t)); seq_arr_init(rc_A3_seq, sizeof(NR_ReportConfigToAddMod_t)); - LOG_D(NR_RRC, "HO LOG: Preparing A3 Event Measurement Configuration!\n"); - bool is_default_a3_added = false; + seq_arr_init(neigh_seq, sizeof(nr_neighbour_cell_t)); + LOG_D(NR_RRC, "Preparing A3 Event Measurement Configuration!\n"); + bool default_a3_added = false; // To ensure that the default configuration is only added once for (int i = 0; i < neighbour_cells->size; i++) { nr_neighbour_cell_t *neighbourCell = (nr_neighbour_cell_t *)seq_arr_at(neighbour_cells, i); - const nr_a3_event_t *a3Event = get_a3_configuration((gNB_RRC_INST *)rrc, neighbourCell->physicalCellId); - if (!a3Event || is_default_a3_added) + if (default_a3_added && neighbourCell->physicalCellId == -1) continue; - if (a3Event->pci == -1) - is_default_a3_added = true; - seq_arr_push_back(rc_A3_seq, prepare_a3_event_report(a3Event), sizeof(NR_ReportConfigToAddMod_t)); + seq_arr_push_back(neigh_seq, neighbourCell, sizeof(nr_neighbour_cell_t)); + const nr_a3_event_t *a3Event = get_a3_configuration((gNB_RRC_INST *)rrc, neighbourCell->physicalCellId); + if (a3Event) { + NR_ReportConfigId_t reportConfigId = neighbourCell->physicalCellId == -1 ? 3 : i + 4; + seq_arr_push_back(rc_A3_seq, prepare_a3_event_report(a3Event, reportConfigId), sizeof(NR_ReportConfigToAddMod_t)); + if (neighbourCell->physicalCellId == -1) + default_a3_added = true; + } } } if (rrc->measurementConfiguration.per_event) rc_PER = prepare_periodic_event_report(rrc->measurementConfiguration.per_event); if (rrc->measurementConfiguration.a2_event) rc_A2 = prepare_a2_event_report(rrc->measurementConfiguration.a2_event); - return get_MeasConfig(mt, band, scs, rc_PER, rc_A2, rc_A3_seq, neighbour_cells); + return get_MeasConfig(mt, band, scs, cell_info->nr_pci, rc_PER, rc_A2, rc_A3_seq, neigh_seq); } return NULL; } From 1dac64fa428ba75bc2e1ca5edef769c32e04a36d Mon Sep 17 00:00:00 2001 From: Reem Bahsoun Date: Wed, 13 Aug 2025 10:48:43 +0200 Subject: [PATCH 654/964] Add UE host (raspix) and OC CN for HO CI setup --- ci-scripts/ci_infra.yaml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/ci-scripts/ci_infra.yaml b/ci-scripts/ci_infra.yaml index 7a6999f503..85dbd10180 100644 --- a/ci-scripts/ci_infra.yaml +++ b/ci-scripts/ci_infra.yaml @@ -12,6 +12,14 @@ idefix: IF: wwan0 MTU: 1500 +raspix: + Host: raspix + AttachScript: sudo /opt/mbim_scripts/start_quectel_mbim.sh + DetachScript: sudo /opt/mbim_scripts/stop_quectel_mbim.sh + NetworkScript: ip a show dev wwan0 + IF: wwan0 + MTU: 1500 + up2: Host: up2 AttachScript: sudo /opt/mbim/start_quectel_mbim.sh @@ -77,6 +85,14 @@ oc-cn5g-20897: Undeploy: "! scripts/oc-cn5g-undeploy.sh /opt/oai-cn5g-fed-develop-2025-jan oaicicd-core-for-fhi72" LogCollect: "! scripts/oc-cn5g-logcollect.sh /opt/oai-cn5g-fed-develop-2025-jan oaicicd-core-for-fhi72 %%log_dir%%" +oc-cn5g-00102-ho: + Host: groot + NetworkScript: echo "inet 172.21.6.111" + RunIperf3Server: False + Deploy: "! scripts/oc-cn5g-deploy.sh /opt/oai-cn5g-fed-develop-2025-jan oaicicd-core-for-ho" + Undeploy: "! scripts/oc-cn5g-undeploy.sh /opt/oai-cn5g-fed-develop-2025-jan oaicicd-core-for-ho" + LogCollect: "! scripts/oc-cn5g-logcollect.sh /opt/oai-cn5g-fed-develop-2025-jan oaicicd-core-for-ho %%log_dir%%" + oc-cn5g-20897-aerial: Host: gracehopper1-oai NetworkScript: echo "inet 172.21.6.105" From bb383359e2f1744b5253c0e10782ad8373f7e8b9 Mon Sep 17 00:00:00 2001 From: Reem Bahsoun Date: Wed, 13 Aug 2025 11:42:52 +0200 Subject: [PATCH 655/964] Add the required files for Handover CI setup (.conf, .yml, .xml) --- ci-scripts/conf_files/gnb-cu.sa.f1.ho.conf | 76 ++++++ ...b-du.sa.band78.51prb.usrpb210.ho-pci0.conf | 217 +++++++++++++++ ...b-du.sa.band78.51prb.usrpb210.ho-pci1.conf | 217 +++++++++++++++ .../conf_files/neighbour-config-ho.conf | 52 ++++ .../container_sa_f1_ho_b210_quectel.xml | 251 ++++++++++++++++++ .../5g_sa_f1_b210_ho/docker-compose.yml | 90 +++++++ 6 files changed, 903 insertions(+) create mode 100644 ci-scripts/conf_files/gnb-cu.sa.f1.ho.conf create mode 100644 ci-scripts/conf_files/gnb-du.sa.band78.51prb.usrpb210.ho-pci0.conf create mode 100644 ci-scripts/conf_files/gnb-du.sa.band78.51prb.usrpb210.ho-pci1.conf create mode 100644 ci-scripts/conf_files/neighbour-config-ho.conf create mode 100644 ci-scripts/xml_files/container_sa_f1_ho_b210_quectel.xml create mode 100644 ci-scripts/yaml_files/5g_sa_f1_b210_ho/docker-compose.yml diff --git a/ci-scripts/conf_files/gnb-cu.sa.f1.ho.conf b/ci-scripts/conf_files/gnb-cu.sa.f1.ho.conf new file mode 100644 index 0000000000..8159eff571 --- /dev/null +++ b/ci-scripts/conf_files/gnb-cu.sa.f1.ho.conf @@ -0,0 +1,76 @@ +Active_gNBs = ( "oai-cu"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe88; + +# cell_type = "CELL_MACRO_GNB"; + + gNB_name = "oai-cu"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + plmn_list = ({ mcc = 001; mnc = 03; mnc_length = 2; snssaiList = ({ sst = 1 }) }); + + @include "neighbour-config-ho.conf" + + nr_cellid = 12345678L; + + tr_s_preference = "f1"; + + local_s_address = "172.21.19.98"; + remote_s_address = "0.0.0.0"; + local_s_portd = 2153; + remote_s_portd = 2154; + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// AMF parameters: + amf_ip_address = ({ ipv4 = "172.21.6.109"; }); + + NETWORK_INTERFACES : + { + + GNB_IPV4_ADDRESS_FOR_NG_AMF = "172.21.19.98/22"; + GNB_IPV4_ADDRESS_FOR_NGU = "172.21.19.98/22"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + } +); + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + +log_config : +{ + global_log_level ="info"; + pdcp_log_level ="info"; + rrc_log_level ="info"; + f1ap_log_level ="info"; + ngap_log_level ="info"; +}; diff --git a/ci-scripts/conf_files/gnb-du.sa.band78.51prb.usrpb210.ho-pci0.conf b/ci-scripts/conf_files/gnb-du.sa.band78.51prb.usrpb210.ho-pci0.conf new file mode 100644 index 0000000000..6360d79124 --- /dev/null +++ b/ci-scripts/conf_files/gnb-du.sa.band78.51prb.usrpb210.ho-pci0.conf @@ -0,0 +1,217 @@ +Active_gNBs = ( "oai-du0"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe88; + gNB_DU_ID = 0xe00; + gNB_name = "oai-du0"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1 ; + plmn_list = ({ mcc = 001; mnc = 03; mnc_length = 2; snssaiList = ({ sst = 1; }) }); + + nr_cellid = 12345678L; + + ////////// Physical parameters: + + do_CSIRS = 0; + do_SRS = 0; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # 4.01 GHz + absoluteFrequencySSB = 629376; + dl_frequencyBand = 78; + # 4 GHz + dl_absoluteFrequencyPointA = 628720; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 51; + #initialDownlinkBWP + #genericParameters + # this is RBstart=27,L=48 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 13750; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 12; + initialDLBWPsearchSpaceZero = 0; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 51; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 13750; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -96; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 14; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = -25; + } + + ); + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + } +); + +MACRLCs = ( +{ + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "f1"; + local_n_address = "172.21.19.98"; + remote_n_address = "172.21.19.98"; + local_n_portc = 500; + local_n_portd = 2154; + remote_n_portc = 501; + remote_n_portd = 2153; + pusch_TargetSNRx10 = 200; + pucch_TargetSNRx10 = 230; +# ul_prbblack_SNR_threshold = 10; +} +); + +L1s = ( +{ + num_cc = 1; + tr_n_preference = "local_mac"; + prach_dtx_threshold = 100; + pucch0_dtx_threshold = 10; + max_ldpc_iterations = 20; + sl_ahead = 3; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 +} +); + +RUs = ( +{ + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 0; + att_rx = 0; + bands = [78]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 114; + eNB_instances = [0]; +# USRP is connected to an Octoclock in order to establish synchroniation with other USRPs + clock_src = "external"; + time_src = "external"; +} +); + +log_config : +{ + global_log_level ="info"; + hw_log_level ="info"; + phy_log_level ="info"; + mac_log_level ="info"; + rlc_log_level ="info"; + pdcp_log_level ="info"; + rrc_log_level ="info"; + ngap_log_level ="debug"; + f1ap_log_level ="info"; +}; diff --git a/ci-scripts/conf_files/gnb-du.sa.band78.51prb.usrpb210.ho-pci1.conf b/ci-scripts/conf_files/gnb-du.sa.band78.51prb.usrpb210.ho-pci1.conf new file mode 100644 index 0000000000..d432d7323a --- /dev/null +++ b/ci-scripts/conf_files/gnb-du.sa.band78.51prb.usrpb210.ho-pci1.conf @@ -0,0 +1,217 @@ +Active_gNBs = ( "oai-du1"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe88; + gNB_DU_ID = 0xe01; + gNB_name = "oai-du1"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1 ; + plmn_list = ({ mcc = 001; mnc = 03; mnc_length = 2; snssaiList = ({ sst = 1; }) }); + + nr_cellid = 11111111L; + + ////////// Physical parameters: + + do_CSIRS = 0; + do_SRS = 0; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 1; + +# downlinkConfigCommon + #frequencyInfoDL + # 4.01 GHz + absoluteFrequencySSB = 629376; + dl_frequencyBand = 78; + # 4 GHz + dl_absoluteFrequencyPointA = 628720; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 51; + #initialDownlinkBWP + #genericParameters + # this is RBstart=27,L=48 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 13750; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 12; + initialDLBWPsearchSpaceZero = 0; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 51; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 13750; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -96; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 14; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = -25; + } + + ); + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + } +); + +MACRLCs = ( +{ + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "f1"; + local_n_address = "172.21.19.99"; + remote_n_address = "172.21.19.98"; + local_n_portc = 500; + local_n_portd = 2154; + remote_n_portc = 501; + remote_n_portd = 2153; + pusch_TargetSNRx10 = 200; + pucch_TargetSNRx10 = 230; +# ul_prbblack_SNR_threshold = 10; +} +); + +L1s = ( +{ + num_cc = 1; + tr_n_preference = "local_mac"; + prach_dtx_threshold = 100; + pucch0_dtx_threshold = 10; + max_ldpc_iterations = 20; + sl_ahead = 3; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 +} +); + +RUs = ( +{ + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 0; + att_rx = 0; + bands = [78]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 114; + eNB_instances = [0]; +# USRP is connected to an Octoclock in order to establish synchroniation with other USRPs + clock_src = "external"; + time_src = "external"; +} +); + +log_config : +{ + global_log_level ="info"; + hw_log_level ="info"; + phy_log_level ="info"; + mac_log_level ="info"; + rlc_log_level ="info"; + pdcp_log_level ="info"; + rrc_log_level ="info"; + ngap_log_level ="debug"; + f1ap_log_level ="info"; +}; diff --git a/ci-scripts/conf_files/neighbour-config-ho.conf b/ci-scripts/conf_files/neighbour-config-ho.conf new file mode 100644 index 0000000000..82d4a8472c --- /dev/null +++ b/ci-scripts/conf_files/neighbour-config-ho.conf @@ -0,0 +1,52 @@ +neighbour_list = ( + { + nr_cellid = 12345678; + neighbour_cell_configuration = ( + { + gNB_ID = 0xe01; + nr_cellid = 11111111; + physical_cellId = 1; + absoluteFrequencySSB = 629376; + subcarrierSpacing = 1; #30 KHz + plmn = { mcc = 001; mnc = 03; mnc_length = 2}; + tracking_area_code = 1; + } + ) + }, + { + nr_cellid = 11111111; + neighbour_cell_configuration = ( + { + gNB_ID = 0xe00; + nr_cellid = 12345678; + physical_cellId = 0; + absoluteFrequencySSB = 629376; + subcarrierSpacing = 1; #30 KHz + plmn = { mcc = 001; mnc = 03; mnc_length = 2}; + tracking_area_code = 1; + } + ) + } + ); + + +nr_measurement_configuration = { + Periodical = { + enable = 1; + includeBeamMeasurements = 1; + maxNrofRS_IndexesToReport = 4; + }; + + A2 = { + enable = 1; + threshold = 110; + timeToTrigger = 1; + }; + + A3 = ({ + cell_id = -1; #Default + offset = 10; + hysteresis = 0; + timeToTrigger = 1 + }) +}; diff --git a/ci-scripts/xml_files/container_sa_f1_ho_b210_quectel.xml b/ci-scripts/xml_files/container_sa_f1_ho_b210_quectel.xml new file mode 100644 index 0000000000..814346b5f3 --- /dev/null +++ b/ci-scripts/xml_files/container_sa_f1_ho_b210_quectel.xml @@ -0,0 +1,251 @@ + + + TEST-F1-HO-B210 + F1 Handover 20 MHz TDD SA + tasks + + 000001 + 000002 + 000003 + 000004 + 000005 + 000006 + 000007 + 000008 + 000009 + 000010 + 000011 + 000012 + 000013 + 000014 + 000015 + 000016 + 000017 + 000018 + 000019 + 000020 + 000021 + 000022 + 000023 + 000024 + 000025 + 000026 + + + + + + DeployCoreNetwork + Initialize 5G Core + oc-cn5g-00102-ho + + + + Pull_Local_Registry + Pull Images from Local Registry + oai-gnb + groot + + + + Pull_Local_Registry + Pull Images from Local Registry + oai-gnb + rocket + + + + Create_Workspace + Create new Workspace for groot + groot + + + + Create_Workspace + Create new Workspace on rocket + rocket + + + + Deploy_Object + Deploy gNB-CU in a container + ci-scripts/yaml_files/5g_sa_f1_b210_ho + groot + oai_cu + + + + Deploy_Object + Deploy gNB-DU0 (TDD/Band77/20MHz/B210) in a container + ci-scripts/yaml_files/5g_sa_f1_b210_ho + oai_du0 + groot + + + + Attach_UE + Attach Quectel + raspix + + + + Ping + Ping: 100pings in 20sec + raspix + oc-cn5g-00102-ho + -c 100 -i 0.2 + 5 + + + + Deploy_Object + Deploy gNB-DU1 (TDD/Band77/20MHz/B210) in a container + ci-scripts/yaml_files/5g_sa_f1_b210_ho + rocket + oai_du1 + + + + IdleSleep + Sleep + 5 + + + + Custom_Command + Trigger Handover + groot + echo ci trigger_f1_ho | ncat 127.0.0.1 9090 + + + + Ping + Ping: 50pings in 10sec + raspix + oc-cn5g-00102-ho + -c 50 -i 0.2 + 5 + + + + Custom_Command + UE connected to DU1? + groot + echo ci fetch_du_by_ue_id 1 | ncat 127.0.0.1 9090 | grep "3585" + + + + Custom_Command + Trigger Handover + groot + echo ci trigger_f1_ho | ncat 127.0.0.1 9090 + + + + Ping + Ping: 50pings in 10sec + raspix + oc-cn5g-00102-ho + -c 50 -i 0.2 + 5 + + + + Custom_Command + UE connected to DU0? + groot + echo ci fetch_du_by_ue_id 1 | ncat 127.0.0.1 9090 | grep "3584" + + + + Custom_Command + Trigger Handover + groot + echo ci trigger_f1_ho | ncat 127.0.0.1 9090 + + + + Ping + Ping: 50pings in 10sec + raspix + oc-cn5g-00102-ho + -c 50 -i 0.2 + 5 + + + + Custom_Command + UE connected to DU1? + groot + echo ci fetch_du_by_ue_id 1 | ncat 127.0.0.1 9090 | grep "3585" + + + + Detach_UE + true + Detach Quectel + raspix + + + + Undeploy_Object + true + Undeploy CU-DU0 + groot + ci-scripts/yaml_files/5g_sa_f1_b210_ho + + + + Undeploy_Object + true + Undeploy DU1 + rocket + ci-scripts/yaml_files/5g_sa_f1_b210_ho + + + + Clean_Test_Server_Images + true + Clean Test Images on Test Server + groot + oai-gnb + + + + Clean_Test_Server_Images + true + Clean Test Images on Test Server + rocket + oai-gnb + + + + UndeployCoreNetwork + true + Terminate 5G Core + oc-cn5g-00102-ho + + + + diff --git a/ci-scripts/yaml_files/5g_sa_f1_b210_ho/docker-compose.yml b/ci-scripts/yaml_files/5g_sa_f1_b210_ho/docker-compose.yml new file mode 100644 index 0000000000..aaf058a9f7 --- /dev/null +++ b/ci-scripts/yaml_files/5g_sa_f1_b210_ho/docker-compose.yml @@ -0,0 +1,90 @@ +services: + oai_cu: + image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop} + container_name: oai-cu + cap_drop: + - ALL + ulimits: + core: -1 # for core dumps + environment: + USE_ADDITIONAL_OPTIONS: --telnetsrv --telnetsrv.listenport 9090 --telnetsrv.shrmod ci --sa + --log_config.global_log_options level,nocolor,utc_time,line_num,function + volumes: + - ../../conf_files/gnb-cu.sa.f1.ho.conf:/opt/oai-gnb/etc/gnb.conf + - ../../conf_files/neighbour-config-ho.conf:/opt/oai-gnb/etc/neighbour-config-ho.conf + # for performance reasons, we use host mode: in bridge mode, we have + # unacceptable DL TCP performance. However, the whole point of + # containerization is to not be in host mode, so update this to macvlan + # later. + network_mode: "host" + #entrypoint: /bin/bash -c "sleep infinity" + healthcheck: + # pgrep does NOT work + test: /bin/bash -c "ps aux | grep -v grep | grep -c softmodem" + interval: 10s + timeout: 5s + retries: 5 + + oai_du0: + image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop} + container_name: oai-du0 + cap_drop: + - ALL + cap_add: + - SYS_NICE + - IPC_LOCK + ulimits: + core: -1 # for core dumps + environment: + USE_B2XX: 'yes' + USE_ADDITIONAL_OPTIONS: --RUs.[0].sdr_addrs serial=30AD30F --sa + --telnetsrv --telnetsrv.listenport 9091 --telnetsrv.shrmod ci + --log_config.global_log_options level,nocolor,utc_time,line_num,function + devices: + - /dev/bus/usb/:/dev/bus/usb/ + volumes: + - ../../conf_files/gnb-du.sa.band78.51prb.usrpb210.ho-pci0.conf:/opt/oai-gnb/etc/gnb.conf + # for performance reasons, we use host mode: in bridge mode, we have + # unacceptable DL TCP performance. However, the whole point of + # containerization is to not be in host mode, so update this to macvlan + # later. + network_mode: "host" + #entrypoint: /bin/bash -c "sleep infinity" + healthcheck: + # pgrep does NOT work + test: /bin/bash -c "ps aux | grep -v grep | grep -c softmodem" + interval: 10s + timeout: 5s + retries: 5 + + oai_du1: + image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop} + container_name: oai-du1 + cap_drop: + - ALL + cap_add: + - SYS_NICE + - IPC_LOCK + ulimits: + core: -1 # for core dumps + environment: + USE_B2XX: 'yes' + USE_ADDITIONAL_OPTIONS: --RUs.[0].sdr_addrs serial=31F8010 --sa + --telnetsrv --telnetsrv.listenport 9091 --telnetsrv.shrmod ci + --log_config.global_log_options level,nocolor,utc_time,line_num,function + devices: + - /dev/bus/usb/:/dev/bus/usb/ + volumes: + - ../../conf_files/gnb-du.sa.band78.51prb.usrpb210.ho-pci1.conf:/opt/oai-gnb/etc/gnb.conf + # for performance reasons, we use host mode: in bridge mode, we have + # unacceptable DL TCP performance. However, the whole point of + # containerization is to not be in host mode, so update this to macvlan + # later. + network_mode: "host" + #entrypoint: /bin/bash -c "sleep infinity" + healthcheck: + # pgrep does NOT work + test: /bin/bash -c "ps aux | grep -v grep | grep -c softmodem" + interval: 10s + timeout: 5s + retries: 5 From 20a2ff1e49a68f7f6ac4c44460cd32537140689a Mon Sep 17 00:00:00 2001 From: Reem Bahsoun Date: Thu, 4 Sep 2025 16:00:00 +0200 Subject: [PATCH 656/964] Add the Handover pipeline to the RAN-Container-Parent --- ci-scripts/Jenkinsfile-GitLab-Container | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/ci-scripts/Jenkinsfile-GitLab-Container b/ci-scripts/Jenkinsfile-GitLab-Container index f2a84fbd91..fcb87cc014 100644 --- a/ci-scripts/Jenkinsfile-GitLab-Container +++ b/ci-scripts/Jenkinsfile-GitLab-Container @@ -661,6 +661,29 @@ pipeline { } } } + stage ("SA-Handover-CN5G") { + when { expression {do5Gtest} } + steps { + script { + triggerSlaveJob ('RAN-SA-Handover-CN5G', 'SA-Handover-CN5G') + } + } + post { + always { + script { + // Using a unique variable name for each test stage to avoid overwriting on a global variable + // due to parallel-time concurrency + saHandoverStatus = finalizeSlaveJob('RAN-SA-Handover-CN5G') + } + } + failure { + script { + currentBuild.result = 'FAILURE' + failingStages += saHandoverStatus + } + } + } + } stage ("SA-OAIUE-CN5G") { when { expression {do5Gtest || do5GUeTest} } steps { From 197492ae89ec858d874d11902af607a846e86ad6 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 5 Sep 2025 11:07:22 +0200 Subject: [PATCH 657/964] Add documentation on UL-heavy TDD patterns --- doc/MAC/mac-usage.md | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/doc/MAC/mac-usage.md b/doc/MAC/mac-usage.md index 6104519f82..13f633eb1a 100644 --- a/doc/MAC/mac-usage.md +++ b/doc/MAC/mac-usage.md @@ -38,7 +38,7 @@ The actual scheduler implementation can be found in functions `pf_dl()` and [`gNB_scheduler_ulsch.c`](../../openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c) (for UL), respectively. -## PDDCH aggregation level +## PDCCH aggregation level PDCCH aggregation level is selected using closed loop controller, where DL HARQ feedback is the controller feedback signal. It is used to increment `pdcch_cl_adjust` @@ -60,7 +60,7 @@ in aggregation level 2 which translates to `uess_agg_levels` set to `[0, 2, 0, Say we have 90% PDCCH success rate at aggregation level 1, `pdcch_cl_adjust` will stay at 0 for most of the time. 2 consecutive PDCCH failures will not result in increasing the aggregation level (because (0.05 + 0.05) * 4 = 0.4 which is closer to 0 than to 1). If PDCCH fails 3 times -in a row the aggregation level will change to 2 and hopefully back to 1 once more PDDCH successes +in a row the aggregation level will change to 2 and hopefully back to 1 once more PDCCH successes happen. ### Example 2 @@ -402,3 +402,13 @@ pattern2: { nrofUplinkSymbols2 = 0; }; ``` + +#### UL-heavy TDD patterns + +"UL-heavy TDD patterns", i.e., TDD patterns that have many UL slots are +supported. Examples for such patterns would be DSUUU or DDDSUUUUUU. + +Note that you should increase the aggregation level candidates as described in +[the corresponding section above](#pdcch-aggregation-level). This is because the +scheduler has to schedule multiple DCIs in a single DL slots for multiple UL +slots. As a suggestion, you could try `uess_agg_levels = [4, 2, 2, 0, 0]`. From 89ebbb41927664c4749bfc44a20fde316ec63d82 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 9 Sep 2025 11:29:33 +0100 Subject: [PATCH 658/964] Do not trigger ul failure in measgap scheduling and standardize the verification if MAC is active in other scheduling functions --- .../LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 4 ++-- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 21 ++++++++++++------- .../LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c | 3 +-- .../LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 4 ++-- .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 2 +- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 2 ++ 6 files changed, 21 insertions(+), 15 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index df5c8e1474..2d0e3d946d 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -628,7 +628,7 @@ static void pf_dl(module_id_t module_id, NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; NR_UE_DL_BWP_t *current_BWP = &UE->current_DL_BWP; - if (sched_ctrl->ul_failure) + if (!nr_mac_ue_is_active(UE)) continue; const NR_mac_dir_stats_t *stats = &UE->mac_stats.dl; @@ -1037,7 +1037,7 @@ void nr_schedule_ue_spec(module_id_t module_id, NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; NR_UE_DL_BWP_t *current_BWP = &UE->current_DL_BWP; - if (sched_ctrl->ul_failure && !get_softmodem_params()->phy_test) + if (!nr_mac_ue_is_active(UE) && !get_softmodem_params()->phy_test) continue; NR_sched_pdsch_t *sched_pdsch = &sched_ctrl->sched_pdsch; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 3d2d1254bf..ee0f57d082 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -3432,10 +3432,7 @@ void nr_measgap_scheduling(gNB_MAC_INST *nr_mac, frame_t frame, sub_frame_t slot interrupt_followup_action_t a = nr_timer_is_active(t) ? UE->interrupt_action : FOLLOW_INSYNC; // start a timer to stop scheduling UE during MeasGap, or extend timer for // duration of measGap with existing follow-up action - // TODO: if the timer is running, it might be to stop scheduling of the UE afterwards, but then it does not make sense to stop - // scheduling the UE now, we should maybe just skip it? if (!nr_timer_is_active(t) || nr_timer_remaining_time(t) < mgc->mgl_slots) { - nr_mac_trigger_ul_failure(&UE->UE_sched_ctrl, UE->current_DL_BWP.scs); /* set the UE to "not active" */ nr_mac_interrupt_ue_transmission(nr_mac, UE, a, mgc->mgl_slots); } } @@ -3564,12 +3561,9 @@ void nr_mac_update_timers(module_id_t module_id, frame_t frame, slot_t slot) if (nr_timer_tick(&sched_ctrl->transm_interrupt)) { /* expired */ nr_timer_stop(&sched_ctrl->transm_interrupt); - if (UE->interrupt_action == FOLLOW_OUTOFSYNC) { + if (UE->interrupt_action == FOLLOW_OUTOFSYNC) nr_mac_trigger_ul_failure(sched_ctrl, UE->current_DL_BWP.scs); - } else { - DevAssert(UE->interrupt_action == FOLLOW_INSYNC); - nr_mac_reset_ul_failure(sched_ctrl); - } + /* else: default FOLLOW_INSYNC: nothing to do (UE is now active again) */ } } } @@ -3777,6 +3771,17 @@ bool nr_mac_check_release(NR_UE_sched_ctrl_t *sched_ctrl, int rnti) return sched_ctrl->release_timer == 0; } +bool nr_mac_ue_is_active(const NR_UE_info_t *ue) +{ + /* pass NR_UE_info_t, so that later we could adapt, e.g., for DRX */ + const NR_UE_sched_ctrl_t *sched_ctrl = &ue->UE_sched_ctrl; + if (sched_ctrl->ul_failure) + return false; + if (nr_timer_is_active(&sched_ctrl->transm_interrupt)) + return false; + return true; +} + #define UL_FAILURE_REQ_GRACE 10000 #define UL_FAILURE_TIMEOUT 30000 void nr_mac_trigger_ul_failure(NR_UE_sched_ctrl_t *sched_ctrl, NR_SubcarrierSpacing_t subcarrier_spacing) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c index 45bb68fa5c..03417b52e5 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c @@ -527,10 +527,9 @@ void nr_schedule_srs(int module_id, frame_t frame, int slot) UE_iterator(UE_info->connected_ue_list, UE) { const int CC_id = 0; - NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; NR_UE_UL_BWP_t *current_BWP = &UE->current_UL_BWP; - if ((sched_ctrl->ul_failure && !get_softmodem_params()->phy_test) || nr_timer_is_active(&sched_ctrl->transm_interrupt)) { + if (!nr_mac_ue_is_active(UE) && !get_softmodem_params()->phy_test) { continue; } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index 00201cdd8d..e35945f6da 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -236,7 +236,7 @@ void nr_csi_meas_reporting(int Mod_idP,frame_t frame, slot_t slot) NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP; const int n_slots_frame = nrmac->frame_structure.numb_slots_frame; - if (nr_timer_is_active(&sched_ctrl->transm_interrupt) || (sched_ctrl->ul_failure && !get_softmodem_params()->phy_test)) { + if (!nr_mac_ue_is_active(UE) && !get_softmodem_params()->phy_test) { continue; } const NR_CSI_MeasConfig_t *csi_measconfig = UE->sc_info.csi_MeasConfig; @@ -1250,7 +1250,7 @@ void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t SFN, slot_t slot) NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP; const int n_slots_frame = nrmac->frame_structure.numb_slots_frame; - if (sched_ctrl->ul_failure || nr_timer_is_active(&sched_ctrl->transm_interrupt)) + if (!nr_mac_ue_is_active(UE)) continue; NR_PUCCH_Config_t *pucch_Config = ul_bwp->pucch_Config; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index b08e703076..68114688f7 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -1963,7 +1963,7 @@ static int pf_ul(gNB_MAC_INST *nrmac, UE_iterator(UE_list, UE) { NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; - if (sched_ctrl->ul_failure) + if (!nr_mac_ue_is_active(UE)) continue; LOG_D(NR_MAC,"pf_ul: preparing UL scheduling for UE %04x\n",UE->rnti); diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 84a0923e8b..f82263d928 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -478,6 +478,8 @@ void nr_mac_trigger_release_complete(gNB_MAC_INST *mac, int rnti); void nr_mac_release_ue(gNB_MAC_INST *mac, int rnti); bool nr_mac_request_release_ue(const gNB_MAC_INST *nrmac, int rnti); +bool nr_mac_ue_is_active(const NR_UE_info_t *ue); + void nr_mac_trigger_ul_failure(NR_UE_sched_ctrl_t *sched_ctrl, NR_SubcarrierSpacing_t subcarrier_spacing); void nr_mac_reset_ul_failure(NR_UE_sched_ctrl_t *sched_ctrl); bool nr_mac_check_ul_failure(gNB_MAC_INST *nrmac, int rnti, NR_UE_sched_ctrl_t *sched_ctrl); From 7c9a7ab3749e4af11a1728b7201c05db5a6873d7 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 10 Sep 2025 07:51:30 +0200 Subject: [PATCH 659/964] Reset sched_ul_bytes on BSR to tend to overestimation On BSR reception, reset sched_ul_bytes. This change means that we assume that no data is "in flight" for this UE at time of BSR reception, or, put differently, that we overestimate the buffer size at UE (in the worst case). To illustrate this, consider the following traces before/after this change. Before this change: Upon BSR reception, the estimated BSR of the UE is reset, but the gNB still accounts for data "in flight". It is visible that the calculated buffer size (estimated - scheduled) quickly goes to zero, and we don't use all resources, despite the buffer still being full. The maximum application throughput in this run was ~220Mbps. [NR_MAC] SHORT BSR at 773.19, est buf 300000 [NR_MAC] ULSCH/PUSCH: 774. 6 RNTI af8e UL sched 774. 9 PRB start 0:162 TDA 2 TBS 32797 est 300000 sched 152704 est BSR 147296 TPC 1 [NR_MAC] ULSCH/PUSCH: 774. 6 RNTI af8e UL sched 774.11 PRB start 0:162 TDA 4 TBS 7172 est 300000 sched 159876 est BSR 140124 TPC 1 [NR_MAC] ULSCH/PUSCH: 774.10 RNTI af8e UL sched 774.12 PRB start 0:162 TDA 0 TBS 32797 est 292845 sched 185501 est BSR 107344 TPC 1 [NR_MAC] ULSCH/PUSCH: 774.10 RNTI af8e UL sched 774.13 PRB start 0:162 TDA 2 TBS 32797 est 292845 sched 218298 est BSR 74547 TPC 1 [NR_MAC] ULSCH/PUSCH: 774.11 RNTI af8e UL sched 774.14 PRB start 0:162 TDA 2 TBS 32797 est 260117 sched 218298 est BSR 41819 TPC 1 [NR_MAC] ULSCH/PUSCH: 774.11 RNTI af8e UL sched 774.16 PRB start 0:162 TDA 4 TBS 7172 est 260117 sched 225470 est BSR 34647 TPC 1 [NR_MAC] ULSCH/PUSCH: 774.15 RNTI af8e UL sched 774.17 PRB start 0: 35 TDA 0 TBS 7172 est 220236 sched 185501 est BSR 34735 TPC 1 [NR_MAC] ULSCH/PUSCH: 774.15 RNTI af8e UL sched 774.18 PRB start 0:162 TDA 2 TBS 32797 est 220236 sched 218298 est BSR 1938 TPC 1 [NR_MAC] ULSCH/PUSCH: 774.16 RNTI af8e UL sched 774.19 PRB start 0: 10 TDA 2 TBS 2017 est 187508 sched 187518 est BSR -10 TPC 1 [NR_MAC] SHORT BSR at 774. 9, est buf 300000 [NR_MAC] ULSCH/PUSCH: 775. 0 RNTI af8e UL sched 775. 2 PRB start 0:162 TDA 0 TBS 32797 est 260117 sched 147549 est BSR 112568 TPC 1 [NR_MAC] ULSCH/PUSCH: 775. 0 RNTI af8e UL sched 775. 3 PRB start 0:162 TDA 2 TBS 32797 est 260117 sched 180346 est BSR 79771 TPC 1 [NR_MAC] ULSCH/PUSCH: 775. 1 RNTI af8e UL sched 775. 4 PRB start 0:162 TDA 2 TBS 32797 est 227389 sched 180346 est BSR 47043 TPC 1 [NR_MAC] ULSCH/PUSCH: 775. 1 RNTI af8e UL sched 775. 6 PRB start 0:162 TDA 4 TBS 7172 est 227389 sched 187518 est BSR 39871 TPC 1 [NR_MAC] ULSCH/PUSCH: 775. 5 RNTI af8e UL sched 775. 7 PRB start 0:162 TDA 0 TBS 32797 est 180353 sched 173174 est BSR 7179 TPC 1 [NR_MAC] ULSCH/PUSCH: 775. 5 RNTI af8e UL sched 775. 8 PRB start 0: 36 TDA 2 TBS 7298 est 180353 sched 180472 est BSR -119 TPC 1 After this change: The gNB resets the number of bytes "in flight" (sched). Thus, the calculated buffer is larger, and does not "run out" before a new BSR arrives (which still indicates the maximum). The UE is thus allocated all resources, but we might overestimate some resources. The maximum application throughput in this run was ~300Mbps, limited by MCS and not by estimated buffer size as in the previous case. [NR_MAC] SHORT BSR at 43. 3, est buf 300000 [NR_MAC] ULSCH/PUSCH: 43.15 RNTI d3ea UL sched 43.17 PRB start 0:162 TDA 0 TBS 36897 est 263180 sched 36897 est BSR 226283 TPC 1 [NR_MAC] ULSCH/PUSCH: 43.15 RNTI d3ea UL sched 43.18 PRB start 0:162 TDA 2 TBS 36897 est 263180 sched 73794 est BSR 189386 TPC 1 [NR_MAC] ULSCH/PUSCH: 43.16 RNTI d3ea UL sched 43.19 PRB start 12:150 TDA 2 TBS 33822 est 263180 sched 107616 est BSR 155564 TPC 1 [NR_MAC] ULSCH/PUSCH: 43.16 RNTI d3ea UL sched 44. 1 PRB start 0:162 TDA 4 TBS 7941 est 263180 sched 115557 est BSR 147623 TPC 1 [NR_MAC] ULSCH/PUSCH: 44. 1 RNTI d3ea UL sched 44. 3 PRB start 0:162 TDA 0 TBS 36897 est 173698 sched 25881 est BSR 147817 TPC 1 [NR_MAC] ULSCH/PUSCH: 44. 1 RNTI d3ea UL sched 44. 4 PRB start 0:162 TDA 2 TBS 36897 est 173698 sched 62778 est BSR 110920 TPC 1 [NR_MAC] ULSCH/PUSCH: 44. 1 RNTI d3ea UL sched 44. 6 PRB start 0:162 TDA 4 TBS 7941 est 173698 sched 70719 est BSR 102979 TPC 1 [NR_MAC] SHORT BSR at 43.13, est buf 300000 [NR_MAC] ULSCH/PUSCH: 44. 5 RNTI d3ea UL sched 44. 7 PRB start 0:162 TDA 0 TBS 36897 est 292079 sched 36897 est BSR 255182 TPC 1 [NR_MAC] ULSCH/PUSCH: 44. 5 RNTI d3ea UL sched 44. 8 PRB start 0:162 TDA 2 TBS 36897 est 292079 sched 73794 est BSR 218285 TPC 1 [NR_MAC] ULSCH/PUSCH: 44. 6 RNTI d3ea UL sched 44. 9 PRB start 0:162 TDA 2 TBS 36897 est 292079 sched 110691 est BSR 181388 TPC 1 [NR_MAC] ULSCH/PUSCH: 44. 6 RNTI d3ea UL sched 44.11 PRB start 0:162 TDA 4 TBS 7941 est 292079 sched 118632 est BSR 173447 TPC 1 [NR_MAC] ULSCH/PUSCH: 44.10 RNTI d3ea UL sched 44.12 PRB start 0:162 TDA 0 TBS 36897 est 213587 sched 39972 est BSR 173615 TPC 1 [NR_MAC] ULSCH/PUSCH: 44.10 RNTI d3ea UL sched 44.13 PRB start 0:162 TDA 2 TBS 36897 est 213587 sched 76869 est BSR 136718 TPC 1 --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index eaec37b159..ad685dba68 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -595,6 +595,7 @@ static int nr_process_mac_pdu(instance_t module_idP, /* Extract short BSR value */ ce_ptr = &pduP[mac_subheader_len]; sched_ctrl->estimated_ul_buffer = estimate_ul_buffer_short_bsr((NR_BSR_SHORT *)ce_ptr); + sched_ctrl->sched_ul_bytes = 0; LOG_D(NR_MAC, "SHORT BSR at %4d.%2d, est buf %d\n", frameP, slot, sched_ctrl->estimated_ul_buffer); break; @@ -603,6 +604,7 @@ static int nr_process_mac_pdu(instance_t module_idP, /* Extract long BSR value */ ce_ptr = &pduP[mac_subheader_len]; sched_ctrl->estimated_ul_buffer = estimate_ul_buffer_long_bsr((NR_BSR_LONG *)ce_ptr); + sched_ctrl->sched_ul_bytes = 0; LOG_D(NR_MAC, "LONG BSR at %4d.%2d, estim buf %d\n", frameP, slot, sched_ctrl->estimated_ul_buffer); break; From b283960637c6f598bc3a50651ac8ac6d353abae7 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 9 Sep 2025 10:40:01 +0200 Subject: [PATCH 660/964] Increase periodic BSR to 5ms: increase UL throughput In high throughput UL scenarios, at least with our configuration, the UE only sends Short BSR. The maximum is 300000 bytes, which is completely "scheduled away" after a couple of UL grants. Increase the periodic BSR to 5ms to get more BSR, which results in higher UL throughput. --- openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c index 6b808eebfa..2f020fbf4e 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c @@ -3006,7 +3006,7 @@ static NR_MAC_CellGroupConfig_t *configure_mac_cellgroup(const nr_mac_timers_t * NR_MAC_CellGroupConfig_t * mac_CellGroupConfig = calloc(1, sizeof(*mac_CellGroupConfig)); AssertFatal(mac_CellGroupConfig != NULL, "Couldn't allocate mac-CellGroupConfig. Out of memory!\n"); mac_CellGroupConfig->bsr_Config = calloc(1, sizeof(*mac_CellGroupConfig->bsr_Config)); - mac_CellGroupConfig->bsr_Config->periodicBSR_Timer = NR_BSR_Config__periodicBSR_Timer_sf10; + mac_CellGroupConfig->bsr_Config->periodicBSR_Timer = NR_BSR_Config__periodicBSR_Timer_sf5; mac_CellGroupConfig->bsr_Config->retxBSR_Timer = NR_BSR_Config__retxBSR_Timer_sf80; mac_CellGroupConfig->tag_Config = calloc(1, sizeof(*mac_CellGroupConfig->tag_Config)); mac_CellGroupConfig->tag_Config->tag_ToReleaseList = NULL; From bb378620e9f8d3bf7cabd3ad02ebf4ccec93670d Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 5 Sep 2025 11:23:25 +0200 Subject: [PATCH 661/964] Remove ulsch_max_frame_inactivity from CI configs The parameter is either set to 10 (the default, so not necessary), or to 0 forcing the gNB to schedule the UE all the time, which is only necessary in specific scenario, and here simply wrong. --- ci-scripts/conf_files/gnb-vnf.sa.band78.273prb.aerial.conf | 1 - ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn-leo.conf | 1 - ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn.conf | 1 - ci-scripts/conf_files/gnb.sa.band77.162prb.usrpn310.2x2.conf | 1 - ci-scripts/conf_files/gnb.sa.band77.273prb.usrpn310.2x2.conf | 1 - ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.neighbour.conf | 1 - 6 files changed, 6 deletions(-) diff --git a/ci-scripts/conf_files/gnb-vnf.sa.band78.273prb.aerial.conf b/ci-scripts/conf_files/gnb-vnf.sa.band78.273prb.aerial.conf index 585d639f9f..f26891d8f2 100644 --- a/ci-scripts/conf_files/gnb-vnf.sa.band78.273prb.aerial.conf +++ b/ci-scripts/conf_files/gnb-vnf.sa.band78.273prb.aerial.conf @@ -197,7 +197,6 @@ MACRLCs = ( tr_n_preference = "local_RRC"; pusch_TargetSNRx10 = 200; # 150; pucch_TargetSNRx10 = 200; #200; - ulsch_max_frame_inactivity = 10; dl_max_mcs = 28; ul_max_mcs = 28; } diff --git a/ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn-leo.conf b/ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn-leo.conf index 6b1ce70b01..8d71434f66 100644 --- a/ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn-leo.conf +++ b/ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn-leo.conf @@ -198,7 +198,6 @@ MACRLCs = ( num_cc = 1; tr_s_preference = "local_L1"; tr_n_preference = "local_RRC"; -# ulsch_max_frame_inactivity = 0; pusch_TargetSNRx10 = 150; pucch_TargetSNRx10 = 200; dl_max_mcs = 9; 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 03ca88d01b..ceb689bf31 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 @@ -205,7 +205,6 @@ MACRLCs = ( num_cc = 1; tr_s_preference = "local_L1"; tr_n_preference = "local_RRC"; -# ulsch_max_frame_inactivity = 0; pusch_TargetSNRx10 = 150; pucch_TargetSNRx10 = 200; dl_max_mcs = 9; diff --git a/ci-scripts/conf_files/gnb.sa.band77.162prb.usrpn310.2x2.conf b/ci-scripts/conf_files/gnb.sa.band77.162prb.usrpn310.2x2.conf index 23a8b34c3a..b0b060362d 100644 --- a/ci-scripts/conf_files/gnb.sa.band77.162prb.usrpn310.2x2.conf +++ b/ci-scripts/conf_files/gnb.sa.band77.162prb.usrpn310.2x2.conf @@ -180,7 +180,6 @@ MACRLCs = ( tr_n_preference = "local_RRC"; pusch_TargetSNRx10 = 300; pucch_TargetSNRx10 = 300; - ulsch_max_frame_inactivity = 0; pusch_FailureThres = 100; ul_max_mcs = 28; } diff --git a/ci-scripts/conf_files/gnb.sa.band77.273prb.usrpn310.2x2.conf b/ci-scripts/conf_files/gnb.sa.band77.273prb.usrpn310.2x2.conf index 3c51a977d8..5928ea4452 100644 --- a/ci-scripts/conf_files/gnb.sa.band77.273prb.usrpn310.2x2.conf +++ b/ci-scripts/conf_files/gnb.sa.band77.273prb.usrpn310.2x2.conf @@ -175,7 +175,6 @@ MACRLCs = ( pusch_TargetSNRx10 = 270; pucch_TargetSNRx10 = 270; pusch_FailureThres = 1000; - ulsch_max_frame_inactivity = 0; ul_max_mcs = 25; } ); diff --git a/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.neighbour.conf b/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.neighbour.conf index 0808c4b43d..eebf6e644f 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.neighbour.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.neighbour.conf @@ -233,7 +233,6 @@ MACRLCs = ( tr_n_preference = "local_RRC"; pusch_TargetSNRx10 = 250; pucch_TargetSNRx10 = 200; - ulsch_max_frame_inactivity = 0; } ); From 13e9910e4e09e65ae5da53817047174804b27389 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 9 Sep 2025 10:46:00 +0200 Subject: [PATCH 662/964] Modify CI SA 60MHz 2x2 test to be DSUUU Update configuration and tweak iperf thresholds accordingly. Tune some parameters for good UL reception. --- .../gnb.sa.band77.162prb.usrpn310.2x2.conf | 13 ++++++++----- .../container_sa_n310_2X2_60MHz_quectel.xml | 14 +++++++------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/ci-scripts/conf_files/gnb.sa.band77.162prb.usrpn310.2x2.conf b/ci-scripts/conf_files/gnb.sa.band77.162prb.usrpn310.2x2.conf index b0b060362d..932699a83f 100644 --- a/ci-scripts/conf_files/gnb.sa.band77.162prb.usrpn310.2x2.conf +++ b/ci-scripts/conf_files/gnb.sa.band77.162prb.usrpn310.2x2.conf @@ -24,6 +24,7 @@ gNBs = pusch_AntennaPorts = 2; do_CSIRS = 1; do_SRS = 1; + uess_agg_levels = [4,2,0,0,0]; servingCellConfigCommon = ( { @@ -139,9 +140,9 @@ gNBs = # dl_UL_TransmissionPeriodicity # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 dl_UL_TransmissionPeriodicity = 5; - nrofDownlinkSlots = 2; + nrofDownlinkSlots = 1; nrofDownlinkSymbols = 6; - nrofUplinkSlots = 2; + nrofUplinkSlots = 3; nrofUplinkSymbols = 4; ssPBCH_BlockPower = -20; @@ -178,10 +179,12 @@ MACRLCs = ( num_cc = 1; tr_s_preference = "local_L1"; tr_n_preference = "local_RRC"; - pusch_TargetSNRx10 = 300; - pucch_TargetSNRx10 = 300; + pusch_TargetSNRx10 = 320; + pucch_TargetSNRx10 = 320; pusch_FailureThres = 100; - ul_max_mcs = 28; + ul_max_mcs = 28; + ul_bler_target_upper = 0.20; + ul_bler_target_lower = 0.10; } ); diff --git a/ci-scripts/xml_files/container_sa_n310_2X2_60MHz_quectel.xml b/ci-scripts/xml_files/container_sa_n310_2X2_60MHz_quectel.xml index b153952252..ab7188c023 100644 --- a/ci-scripts/xml_files/container_sa_n310_2X2_60MHz_quectel.xml +++ b/ci-scripts/xml_files/container_sa_n310_2X2_60MHz_quectel.xml @@ -22,7 +22,7 @@ --> TEST-SA-FR1-N310-2x2-60MHz - 60 MHz 2x2 TDD SA + 60 MHz 2x2 TDD SA DSUUU tasks 100000 @@ -114,8 +114,8 @@ Iperf - iperf (DL/200Mbps/UDP)(30 sec)(single-ue profile) - -u -b 200M -t 30 -R + iperf (DL/150Mbps/UDP)(30 sec)(single-ue profile) + -u -b 150M -t 30 -R matix-cn5g up2 25 @@ -124,8 +124,8 @@ Iperf - iperf (UL/180Mbps/UDP)(30 sec)(single-ue profile) - -u -b 180M -t 30 + iperf (UL/250Mbps/UDP)(30 sec)(single-ue profile) + -u -b 250M -t 30 matix-cn5g up2 10 @@ -147,8 +147,8 @@ matix ci-scripts/yaml_files/5g_sa_n310_2x2_60MHz oai-gnb - 10,100,100,100 - 10,100,100,100 + 15,100,100,100 + 20,100,100,100 From e2b3c1546e6b85535f260d2a3ef5df7b51fdbfb5 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 5 Sep 2025 11:29:08 +0200 Subject: [PATCH 663/964] Add TDD pattern config asserts Check that the number of slots in period/symbols in mixed slot conforms to what is prescribed by the spec. --- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common_tdd.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common_tdd.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common_tdd.c index b9f41a64a3..922a0153d9 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common_tdd.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common_tdd.c @@ -138,6 +138,10 @@ static uint8_t set_tdd_bmap_period(const NR_TDD_UL_DL_Pattern_t *pattern, tdd_pe n_ul_slot, n_dl_symbols, n_ul_symbols); + AssertFatal(n_dl_symbols + n_ul_symbols < 14, + "number of mixed slot symbols must be smaller than 14: DL %d, UL %d\n", + n_dl_symbols, + n_ul_symbols); return total_slot; } @@ -174,6 +178,11 @@ static void config_tdd_patterns(const NR_TDD_UL_DL_ConfigCommon_t *tdd, frame_st num_of_patterns, nb_slots_p1, nb_slots_p2); + AssertFatal(nb_slots_p1 + nb_slots_p2 == fs->numb_slots_period, + "total number of slots must equal to %d: p1 %d + p2 %d\n", + fs->numb_slots_period, + nb_slots_p1, + nb_slots_p2); } /** From 91069fffd17c074d917a00275c3c72e2fb89a807 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 27 Aug 2025 16:14:18 +0200 Subject: [PATCH 664/964] Query system info --- ci-scripts/cls_oaicitest.py | 2 ++ ci-scripts/scripts/sys-info.sh | 17 +++++++++++++++++ 2 files changed, 19 insertions(+) create mode 100755 ci-scripts/scripts/sys-info.sh diff --git a/ci-scripts/cls_oaicitest.py b/ci-scripts/cls_oaicitest.py index 69a06f906b..ba0ce0d9e8 100644 --- a/ci-scripts/cls_oaicitest.py +++ b/ci-scripts/cls_oaicitest.py @@ -254,8 +254,10 @@ def IdleSleep(HTML, idle_sleep_time): def Deploy_Physim(ctx, HTML, node, workdir, script, options): logging.debug(f'Running physims on server {node} workdir {workdir}') with cls_cmd.getConnection(node) as c: + sys_info = c.exec_script("scripts/sys-info.sh", 5) ret = c.exec_script(script, 600, options) logging.debug(f'"{script}" finished with code {ret.returncode}, output:\n{ret.stdout}') + HTML.CreateHtmlTestRowQueue('Query system info', 'OK', [sys_info.stdout]) with cls_cmd.getConnection(node) as ssh: details_json = archiveArtifact(ssh, ctx, f'{workdir}/desc-tests.json') result_junit = archiveArtifact(ssh, ctx, f'{workdir}/results-run.xml') diff --git a/ci-scripts/scripts/sys-info.sh b/ci-scripts/scripts/sys-info.sh new file mode 100755 index 0000000000..01dd4b0d6c --- /dev/null +++ b/ci-scripts/scripts/sys-info.sh @@ -0,0 +1,17 @@ +CORES=$(nproc) +MODEL=$(lscpu | awk -F: '/Model name/ {print $2; exit}' | xargs) +MAX_FREQ=$(lscpu | awk -F: '/CPU max MHz/ {printf "%.2f MHz", $2; exit}') +CURRENT_FREQ=$(awk -F: '/cpu MHz/ {printf " %.2f MHz", $2; exit}' /proc/cpuinfo) +RAM=$(free -h --si | awk '/Mem:/ {print $2}') +# sudo -n: non-interactive, will silently fail in case we don't have privileges +DMID=$(sudo -n dmidecode -t memory 2>/dev/null) +if [ $? -eq 0 ]; then + RAM_TYPE=$(echo "$DMID" | awk -F: '/Type:/ {print $2}' | grep -Ev 'Unknown|Other|None' | head -1 | xargs) +else + RAM_TYPE="can't query" +fi + + +echo "CPU: model ${MODEL}" +echo "${CORES} cores, max CPU freq ${MAX_FREQ}, current ${CURRENT_FREQ}" +echo "RAM ${RAM} type ${RAM_TYPE}" From 1cfca6ce47f2bf1e397abe6697a6d4edf5010e6e Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 8 Sep 2025 14:59:16 +0200 Subject: [PATCH 665/964] Move PhySim definition to openair1/SIMULATION/tests Most (but not all) physical simulators are defined under openair1/SIMULATION/. Defining physical simulators below there seems to be the more "obvious" directory anyway, as the physical simulators are openair1/SIMULATION/tests Phy(L1) Sim tests => PhySim (tests) --- doc/physical-simulators.md | 2 +- docker/Dockerfile.phySim.rhel9 | 2 +- openair1/CMakeLists.txt | 1 + openair1/PHY/CODING/CMakeLists.txt | 4 ---- openair1/SIMULATION/CMakeLists.txt | 3 +++ openair1/{PHY/CODING => SIMULATION}/tests/CMakeLists.txt | 0 6 files changed, 6 insertions(+), 6 deletions(-) create mode 100644 openair1/SIMULATION/CMakeLists.txt rename openair1/{PHY/CODING => SIMULATION}/tests/CMakeLists.txt (100%) diff --git a/doc/physical-simulators.md b/doc/physical-simulators.md index 600f46191e..bf537b1fbd 100644 --- a/doc/physical-simulators.md +++ b/doc/physical-simulators.md @@ -100,7 +100,7 @@ ctest -L nr_ulsch -j 4 To define a new test or modify existing ones, update the following file: ``` -openair1/PHY/CODING/tests/CMakeLists.txt +openair1/SIMULATION/tests/CMakeLists.txt ``` Use the `add_physim_test` macro with the following arguments: diff --git a/docker/Dockerfile.phySim.rhel9 b/docker/Dockerfile.phySim.rhel9 index e9ccf68b00..c5faab2ec7 100644 --- a/docker/Dockerfile.phySim.rhel9 +++ b/docker/Dockerfile.phySim.rhel9 @@ -98,7 +98,7 @@ RUN ldconfig && \ WORKDIR /opt/oai-physim/ COPY --from=phy-sim-build \ - /oai-ran/cmake_targets/ran_build/build/openair1/PHY/CODING/tests/CTestTestfile.cmake \ + /oai-ran/cmake_targets/ran_build/build/openair1/SIMULATION/tests/CTestTestfile.cmake \ /opt/oai-physim/ #CMD ["sleep", "infinity"] diff --git a/openair1/CMakeLists.txt b/openair1/CMakeLists.txt index 1ce6debaf1..123d723342 100644 --- a/openair1/CMakeLists.txt +++ b/openair1/CMakeLists.txt @@ -1 +1,2 @@ add_subdirectory(PHY) +add_subdirectory(SIMULATION) diff --git a/openair1/PHY/CODING/CMakeLists.txt b/openair1/PHY/CODING/CMakeLists.txt index 5b7508fc29..7e07f8f2dc 100644 --- a/openair1/PHY/CODING/CMakeLists.txt +++ b/openair1/PHY/CODING/CMakeLists.txt @@ -68,7 +68,3 @@ if (ENABLE_LDPC_CUDA) endif() add_subdirectory(nrLDPC_coding) - -if(ENABLE_PHYSIM_TESTS) - add_subdirectory(tests) -endif() diff --git a/openair1/SIMULATION/CMakeLists.txt b/openair1/SIMULATION/CMakeLists.txt new file mode 100644 index 0000000000..b93118ccb7 --- /dev/null +++ b/openair1/SIMULATION/CMakeLists.txt @@ -0,0 +1,3 @@ +if(ENABLE_PHYSIM_TESTS) + add_subdirectory(tests) +endif() diff --git a/openair1/PHY/CODING/tests/CMakeLists.txt b/openair1/SIMULATION/tests/CMakeLists.txt similarity index 100% rename from openair1/PHY/CODING/tests/CMakeLists.txt rename to openair1/SIMULATION/tests/CMakeLists.txt From 89321fe824a8bb634513606a9cfa723c24afef2b Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 22 Aug 2025 11:44:36 +0000 Subject: [PATCH 666/964] Add Dockerfile for physim build in CI --- ci-scripts/docker/Dockerfile.physim.ubuntu | 46 ++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 ci-scripts/docker/Dockerfile.physim.ubuntu diff --git a/ci-scripts/docker/Dockerfile.physim.ubuntu b/ci-scripts/docker/Dockerfile.physim.ubuntu new file mode 100644 index 0000000000..c3adfba966 --- /dev/null +++ b/ci-scripts/docker/Dockerfile.physim.ubuntu @@ -0,0 +1,46 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (the "License"); you may not use this file +# * except in compliance with the License. +# * You may obtain a copy of the License at +# * +# * http://www.openairinterface.org/?page_id=698 +# * +# * Unless required by applicable law or agreed to in writing, software +# * distributed under the License is distributed on an "AS IS" BASIS, +# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# * See the License for the specific language governing permissions and +# * limitations under the License. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# +# Dockerfile for the Open-Air-Interface BUILD service +# Valid for Ubuntu 24.04 +# +#--------------------------------------------------------------------- + +FROM ran-base:develop AS ran-tests + +#RUN apt-get update && \ +# DEBIAN_FRONTEND=noninteractive apt-get upgrade --yes && \ +# DEBIAN_FRONTEND=noninteractive apt-get install --yes \ +# libgtest-dev \ +# libyaml-cpp-dev + +RUN rm -Rf /oai-ran +WORKDIR /oai-ran +COPY . . + +WORKDIR /oai-ran/build +# TODO should SANITIZE be ON? it makes it compile much longer +RUN cmake -GNinja -DENABLE_PHYSIM_TESTS=ON \ + -DSANITIZE_UNDEFINED=OFF -DSANITIZE_ADDRESS=OFF \ + -DCMAKE_C_FLAGS=-Werror -DCMAKE_CXX_FLAGS=-Werror \ + .. && \ + ninja ldpctest polartest smallblocktest nr_pbchsim nr_dlschsim nr_ulschsim nr_dlsim nr_ulsim nr_pucchsim nr_prachsim nr_psbchsim From e6a0a1cac42a7754c8fa8c1c006937c7bb74fb9f Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 22 Aug 2025 12:33:36 +0000 Subject: [PATCH 667/964] Deployment script of physims via docker --- .../docker-build-and-deploy-physims.sh | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100755 ci-scripts/scripts/docker-build-and-deploy-physims.sh diff --git a/ci-scripts/scripts/docker-build-and-deploy-physims.sh b/ci-scripts/scripts/docker-build-and-deploy-physims.sh new file mode 100755 index 0000000000..c49ebefc1d --- /dev/null +++ b/ci-scripts/scripts/docker-build-and-deploy-physims.sh @@ -0,0 +1,46 @@ +#!/bin/bash + +function die() { echo $@; exit 1; } +[ $# -ge 1 ] || die "usage: $0 [ctest-options]" + +IMAGE=ran-physimtests:ci-temp +CONTAINER=ran-physimtests +function cleanup-docker() { + docker stop ${CONTAINER} + docker rm ${CONTAINER} + docker rmi ${IMAGE} + docker volume prune --force +} +trap cleanup-docker EXIT + +set -x +DIR=$1 +RESULT_DIR=${DIR}/ +shift +CTEST_OPT=$@ + +# build physims +docker build --progress=plain --tag ${IMAGE} --file ${DIR}/ci-scripts/docker/Dockerfile.physim.ubuntu ${DIR} &>> ${RESULT_DIR}/physim_log.txt +if [ $? -ne 0 ]; then + echo "build of physims failed" + exit 1 +fi + +# get a JSON description of all tests to run +docker run -a STDOUT --workdir /oai-ran/build/ --env LD_LIBRARY_PATH=/oai-ran/build/ --rm --name ${CONTAINER} ${IMAGE} ctest ${CTEST_OPT} --show-only=json-v1 &> ${RESULT_DIR}/desc-tests.json +JSON_RES=$? + +# run the actual tests: we don't suppy --rm as we have to copy the files +# similar to unit tests, we can't mount the file where we write physims-5g-run.xml to +# as it would write a file as root, but this script is run as a normal user +docker run -a STDOUT --workdir /oai-ran/build/ --env LD_LIBRARY_PATH=/oai-ran/build/ --name ${CONTAINER} ${IMAGE} ctest ${CTEST_OPT} --output-junit results-run.xml --test-output-size-passed 100000 --test-output-size-failed 100000 &>> ${RESULT_DIR}/physim_log.txt +RUN_RES=$? +docker cp ${CONTAINER}:/oai-ran/build/results-run.xml ${RESULT_DIR}/ +docker cp ${CONTAINER}:/oai-ran/build/Testing/Temporary/LastTestsFailed.log ${RESULT_DIR}/ +docker cp ${CONTAINER}:/oai-ran/build/Testing/Temporary/LastTest.log ${RESULT_DIR}/ + +# if both were successful, return 0 +# TODO not sure +#[[ $JSON_RES -eq 0 && $RUN_RES -eq 0 ]] && exit 0 + +exit 0 From 4809ffc92a7a1bee9519aa16feea547bdc24260a Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 22 Aug 2025 15:01:09 +0200 Subject: [PATCH 668/964] Add new Physim test for gracehopper --- ci-scripts/main.py | 8 ++++ ci-scripts/xml_class_list.yml | 1 + ci-scripts/xml_files/physim_gracehopper.xml | 46 +++++++++++++++++++++ 3 files changed, 55 insertions(+) create mode 100644 ci-scripts/xml_files/physim_gracehopper.xml diff --git a/ci-scripts/main.py b/ci-scripts/main.py index e6b8c68cc1..ee855d7102 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -251,6 +251,14 @@ def ExecuteActionWithParam(action, ctx): workdir = CLUSTER.eNBSourceCodePath success = cls_oaicitest.Deploy_Physim(ctx, HTML, node, workdir, script, options) + elif action == 'Build_Deploy_Docker_PhySim': + node = test.findtext('node') or None + ctest_opt = test.findtext('ctest-opt') or '' + script = "scripts/docker-build-and-deploy-physims.sh" + options = f"{CONTAINERS.eNBSourceCodePath} {ctest_opt}" + workdir = CONTAINERS.eNBSourceCodePath + success = cls_oaicitest.Deploy_Physim(ctx, HTML, node, workdir, script, options) + elif action == 'DeployCoreNetwork' or action == 'UndeployCoreNetwork': cn_id = test.findtext('cn_id') core_op = getattr(cls_oaicitest.OaiCiTest, action) diff --git a/ci-scripts/xml_class_list.yml b/ci-scripts/xml_class_list.yml index 88d782cd5b..4ab7bd1714 100755 --- a/ci-scripts/xml_class_list.yml +++ b/ci-scripts/xml_class_list.yml @@ -24,6 +24,7 @@ - Undeploy_Object - Cppcheck_Analysis - Deploy_Run_OC_PhySim + - Build_Deploy_Docker_PhySim - LicenceAndFormattingCheck - Push_Local_Registry - Pull_Local_Registry diff --git a/ci-scripts/xml_files/physim_gracehopper.xml b/ci-scripts/xml_files/physim_gracehopper.xml new file mode 100644 index 0000000000..a2abc628d0 --- /dev/null +++ b/ci-scripts/xml_files/physim_gracehopper.xml @@ -0,0 +1,46 @@ + + + build-tab + PhySim + wrench + + 800813 + 010201 + + + + + Create_Workspace + Create new Workspace + localhost + + + + Build_Deploy_Docker_PhySim + Deploy and Deploy PhySim + localhost + -R 5g -E physim.5g.nr_dlsim.mcs.mimo.test9 -j16 + + + From b7cb74699ded057fe2b884ec6d1cbe91b5f49fb5 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 8 Sep 2025 09:32:47 +0200 Subject: [PATCH 669/964] add_physim_test(): change signature for full test name Change signature of the macro to take the full test name, a separate description (previously called a label?), and the executable and test invocation. The overall signature becomes easier. The rational for the full test name is that a later commit will introduce the possibility to define physim tests that are checked for specific times, in which case we need to reuse the test name. Thus, using the full name from the beginning leads to more clarity, even though they are a bit longer. Add an additional safety check that the given simulator is actually a target defined within the project (in other words, it actually exists). Update the documentation correspondingly. --- doc/physical-simulators.md | 26 +- openair1/SIMULATION/tests/CMakeLists.txt | 376 ++++++++++++----------- 2 files changed, 200 insertions(+), 202 deletions(-) diff --git a/doc/physical-simulators.md b/doc/physical-simulators.md index bf537b1fbd..dab457d38f 100644 --- a/doc/physical-simulators.md +++ b/doc/physical-simulators.md @@ -103,26 +103,22 @@ To define a new test or modify existing ones, update the following file: openair1/SIMULATION/tests/CMakeLists.txt ``` -Use the `add_physim_test` macro with the following arguments: -```cmake -add_physim_test( ) -``` +Use the `add_physim_test()` macro with the following arguments: -### Arguments: + add_physim_test( ) -* ``: Test generation (e.g., `4g` or `5g`) -* ``: Name of the test executable (e.g., `nr_prachsim`) -* ``: Description shown in `ctest` output, useful for categorization and indexing. -* ``: Label used for filtering tests (via `-L`), shown in the ctest output summary as a descriptive tag. -* ``: Command line options passed to the test +where: +- `` can be any name, but the canonical, historical format is to put + it `physim...test` where `` is 4g/5g, and `` + is an increasing number +- `` is a human-readable description of the test +- ` ` is the test invocation, where `` must + be a target built by OAI cmake (e.g., `nr_prachsim`), followed by any options. -### Example: +For instance, a PRACHsim looks like this: -```cmake -# add_physim_test( ) -add_physim_test(5g nr_prachsim test8 "15kHz SCS, 25 PRBs" -a -s -30 -n 300 -p 99 -R 25 -m 0) -``` + add_physim_test(physim.5g.nr_prachsim.test8 "15kHz SCS, 25 PRBs" nr_prachsim -a -s -30 -n 300 -p 99 -R 25 -m 0) These tests are run automatically as part of the following pipelines: [RAN-PhySim-Cluster-4G](https://jenkins-oai.eurecom.fr/job/RAN-PhySim-Cluster-4G/) and [RAN-PhySim-Cluster-5G](https://jenkins-oai.eurecom.fr/job/RAN-PhySim-Cluster-5G/) diff --git a/openair1/SIMULATION/tests/CMakeLists.txt b/openair1/SIMULATION/tests/CMakeLists.txt index 2f8f88d547..4d57ada955 100644 --- a/openair1/SIMULATION/tests/CMakeLists.txt +++ b/openair1/SIMULATION/tests/CMakeLists.txt @@ -1,15 +1,17 @@ # Define a macro to add tests for different physical simulators -macro(add_physim_test test_gen test_exec test_description test_label) +macro(add_physim_test test_name test_description test_exec) # catch all the arguments past the last expected arqument and store them in the options_list + if (NOT TARGET ${test_exec}) + message(FATAL_ERROR "test executable ${test_exec} is not an executable") + endif() set(options_list ${ARGN}) - set(test_name physim.${test_gen}.${test_exec}.${test_description}) add_test( NAME ${test_name} COMMAND ${test_exec} ${options_list} COMMAND_EXPAND_LISTS ) set_tests_properties(${test_name} PROPERTIES - LABELS "${test_exec}: ${test_label};${test_exec}" + LABELS "${test_exec}: ${test_description};${test_exec}" ENVIRONMENT "LD_LIBRARY_PATH=." ) add_dependencies(tests ${test_exec}) @@ -19,247 +21,247 @@ endmacro() ###### dlsim unit test ###### #################################################################################### -add_physim_test(4g dlsim basic.test1 "10 MHz, R2.FDD (MCS 5), EVA5, -1dB" -m=5 -g=F -s=-1 -w=1.0 -f=.2 -n=1500 -B=50 -c=2 -z=2 -Tperf=60) -add_physim_test(4g dlsim basic.test2 "1.4 MHz, R4.FDD (MCS 4), EVA5, 0dB (70%)" -m=4 -g=F -s=0 -w=1.0 -f=.2 -n=1500 -B=6 -c=4 -z=2 -Tperf=60) -add_physim_test(4g dlsim basic.test3 "10 MHz, R3.FDD (MCS 15), EVA5, 6.7dB (70%)" -m=15 -g=F -s=6.7 -w=1.0 -f=.2 -n=1500 -B=50 -c=2 -z=2 -Tperf=60) -add_physim_test(4g dlsim basic.test4 "5 MHz, R3-1.FDD (MCS 15), EVA5, 6.7dB (70%)" -m=15 -g=F -s=6.7 -w=1.0 -f=.2 -n=1500 -B=25 -c=2 -z=2 -Tperf=60) -add_physim_test(4g dlsim basic.test5 "10 MHz, R3-1.FDD (MCS 15), EVA5, 6.7dB (30%)" -m=15 -g=G -s=1.4 -w=1.0 -f=.2 -n=1500 -B=50 -c=2 -z=2 -Tperf=25) -add_physim_test(4g dlsim basic.test6 "5 MHz, R3-1.FDD (MCS 15), ETU70, 1.4 dB (30%)" -m=15 -g=G -s=1.4 -w=1.0 -f=.2 -n=1500 -B=25 -c=2 -z=2 -Tperf=25) -add_physim_test(4g dlsim basic.test7 "5 MHz, R6.FDD (MCS 25), EVA5, 17.4 dB (70%)" -m=25 -g=F -s=17.4 -w=1.0 -f=.2 -n=1500 -B=25 -c=3 -z=2 -Tperf=60) -add_physim_test(4g dlsim basic.test8 "5 MHz, R6-1.FDD (MCS 24,18 PRB), EVA5, 17.5dB (70%)" -m=25 -g=F -s=17.5 -w=1.0 -f=.2 -n=1500 -B=25 -c=3 -z=2 -r=1022 -Tperf=60) -add_physim_test(4g dlsim basic.test9 "10 MHz, R7.FDD (MCS 25), EVA5, 17.7dB (70%)" -m=26 -g=F -s=17.7 -w=1.0 -f=.2 -n=1500 -B=50 -c=2 -z=2 -Tperf=60) -add_physim_test(4g dlsim 100rb.tm2.test1 "20 MHz, R.9 FDD (MCS 26), EVA5, 17.6dB (70%)" -m=26 -g=F -s=17.6 -w=1.0 -f=.2 -n=1500 -B=100 -c=2 -z=2 -Tperf=60) -add_physim_test(4g dlsim 100rb.tm2.test2 "20 MHz, R.9-2 FDD (MCS 26, 17PRB), EVA5, 17.3dB (70%)" -m=26 -g=F -s=17.3 -w=1.0 -f=.2 -n=1500 -B=100 -c=2 -z=2 -r=1600 -Tperf=60) -add_physim_test(4g dlsim 100rb.tm2.test3 "20 MHz, R.9-1 FDD (MCS 26, 83 PRB), EVA5, 16.6dB (70%)" -m=26 -g=F -s=16.6 -w=1.0 -f=.2 -n=1500 -B=100 -c=2 -z=2 -r=1899 -Tperf=60) -add_physim_test(4g dlsim 100rb.tm2.test4 "10 MHz, R.11 FDD (MCS 14), EVA5, 6.8 dB (70%)" -m=14 -g=F -s=6.8 -w=1.0 -f=.2 -n=1500 -B=50 -c=2 -x=2 -y=2 -z=2 -Tperf=60) -add_physim_test(4g dlsim 100rb.tm2.test5 "5 MHz, R.11-2 FDD (MCS 13), EVA5, 5.9 dB (70%)" -m=13 -g=F -s=5.9 -w=1.0 -f=.2 -n=1500 -B=25 -c=3 -x=2 -y=2 -z=2 -Tperf=60) +add_physim_test(physim.4g.dlsim.basic.test1 "10 MHz, R2.FDD (MCS 5), EVA5, -1dB" dlsim -m=5 -g=F -s=-1 -w=1.0 -f=.2 -n=1500 -B=50 -c=2 -z=2 -Tperf=60) +add_physim_test(physim.4g.dlsim.basic.test2 "1.4 MHz, R4.FDD (MCS 4), EVA5, 0dB (70%)" dlsim -m=4 -g=F -s=0 -w=1.0 -f=.2 -n=1500 -B=6 -c=4 -z=2 -Tperf=60) +add_physim_test(physim.4g.dlsim.basic.test3 "10 MHz, R3.FDD (MCS 15), EVA5, 6.7dB (70%)" dlsim -m=15 -g=F -s=6.7 -w=1.0 -f=.2 -n=1500 -B=50 -c=2 -z=2 -Tperf=60) +add_physim_test(physim.4g.dlsim.basic.test4 "5 MHz, R3-1.FDD (MCS 15), EVA5, 6.7dB (70%)" dlsim -m=15 -g=F -s=6.7 -w=1.0 -f=.2 -n=1500 -B=25 -c=2 -z=2 -Tperf=60) +add_physim_test(physim.4g.dlsim.basic.test5 "10 MHz, R3-1.FDD (MCS 15), EVA5, 6.7dB (30%)" dlsim -m=15 -g=G -s=1.4 -w=1.0 -f=.2 -n=1500 -B=50 -c=2 -z=2 -Tperf=25) +add_physim_test(physim.4g.dlsim.basic.test6 "5 MHz, R3-1.FDD (MCS 15), ETU70, 1.4 dB (30%)" dlsim -m=15 -g=G -s=1.4 -w=1.0 -f=.2 -n=1500 -B=25 -c=2 -z=2 -Tperf=25) +add_physim_test(physim.4g.dlsim.basic.test7 "5 MHz, R6.FDD (MCS 25), EVA5, 17.4 dB (70%)" dlsim -m=25 -g=F -s=17.4 -w=1.0 -f=.2 -n=1500 -B=25 -c=3 -z=2 -Tperf=60) +add_physim_test(physim.4g.dlsim.basic.test8 "5 MHz, R6-1.FDD (MCS 24,18 PRB), EVA5, 17.5dB (70%)" dlsim -m=25 -g=F -s=17.5 -w=1.0 -f=.2 -n=1500 -B=25 -c=3 -z=2 -r=1022 -Tperf=60) +add_physim_test(physim.4g.dlsim.basic.test9 "10 MHz, R7.FDD (MCS 25), EVA5, 17.7dB (70%)" dlsim -m=26 -g=F -s=17.7 -w=1.0 -f=.2 -n=1500 -B=50 -c=2 -z=2 -Tperf=60) +add_physim_test(physim.4g.dlsim.100rb.tm2.test1 "20 MHz, R.9 FDD (MCS 26), EVA5, 17.6dB (70%)" dlsim -m=26 -g=F -s=17.6 -w=1.0 -f=.2 -n=1500 -B=100 -c=2 -z=2 -Tperf=60) +add_physim_test(physim.4g.dlsim.100rb.tm2.test2 "20 MHz, R.9-2 FDD (MCS 26, 17PRB), EVA5, 17.3dB (70%)" dlsim -m=26 -g=F -s=17.3 -w=1.0 -f=.2 -n=1500 -B=100 -c=2 -z=2 -r=1600 -Tperf=60) +add_physim_test(physim.4g.dlsim.100rb.tm2.test3 "20 MHz, R.9-1 FDD (MCS 26, 83 PRB), EVA5, 16.6dB (70%)" dlsim -m=26 -g=F -s=16.6 -w=1.0 -f=.2 -n=1500 -B=100 -c=2 -z=2 -r=1899 -Tperf=60) +add_physim_test(physim.4g.dlsim.100rb.tm2.test4 "10 MHz, R.11 FDD (MCS 14), EVA5, 6.8 dB (70%)" dlsim -m=14 -g=F -s=6.8 -w=1.0 -f=.2 -n=1500 -B=50 -c=2 -x=2 -y=2 -z=2 -Tperf=60) +add_physim_test(physim.4g.dlsim.100rb.tm2.test5 "5 MHz, R.11-2 FDD (MCS 13), EVA5, 5.9 dB (70%)" dlsim -m=13 -g=F -s=5.9 -w=1.0 -f=.2 -n=1500 -B=25 -c=3 -x=2 -y=2 -z=2 -Tperf=60) #################################################################################### ###### ulsim unit test ###### #################################################################################### -add_physim_test(4g ulsim test1 "5 MHz, FDD (MCS 5), AWGN, 6dB" -BnbRBs=25 -mcs=5 -yN_rx=1 -gchannel=N -xTransmission=1 -snr=6 -wsnrInterrupt=1.0 -e_snr_step=.1 -P -nb_frame=1500 -Tperf=70) -add_physim_test(4g ulsim test2 "5 MHz, FDD (MCS 16), AWGN , 12dB (70%)" -BnbRBs=25 -mcs=16 -yN_rx=1 -gchannel=N -xTransmission=1 -snr=12 -wsnrInterrupt=1.0 -e_snr_step=.1 -P -nb_frame=1500 -Tperf=70) -add_physim_test(4g ulsim test3 "10 MHz, R3.FDD (MCS 5), AWGN, 6dB (70%)" -BnbRBs=50 -mcs=5 -yN_rx=1 -gchannel=N -xTransmission=1 -snr=6 -wsnrInterrupt=1.0 -e_snr_step=.1 -P -nb_frame=1500 -Tperf=70) -add_physim_test(4g ulsim test4 "10 MHz, R3-1.FDD (MCS 16), AWGN, 12dB (70%)" -BnbRBs=50 -mcs=16 -yN_rx=1 -gchannel=N -xTransmission=1 -snr=12 -wsnrInterrupt=1.0 -e_snr_step=.1 -P -nb_frame=1500 -Tperf=70) -add_physim_test(4g ulsim test5 "20 MHz, FDD (MCS 5), AWGN, 6dB (70%)" -BnbRBs=100 -mcs=5 -yN_rx=1 -gchannel=N -xTransmission=1 -snr=6 -wsnrInterrupt=1.0 -e_snr_step=.1 -P -nb_frame=1500 -Tperf=70) -add_physim_test(4g ulsim test6 "20 MHz, FDD (MCS 16), AWGN, 12 dB (70%)" -BnbRBs=100 -mcs=16 -yN_rx=1 -gchannel=N -xTransmission=1 -snr=12 -wsnrInterrupt=1.0 -e_snr_step=.1 -P -nb_frame=1500 -Tperf=70) +add_physim_test(physim.4g.ulsim.test1 "5 MHz, FDD (MCS 5), AWGN, 6dB" ulsim -BnbRBs=25 -mcs=5 -yN_rx=1 -gchannel=N -xTransmission=1 -snr=6 -wsnrInterrupt=1.0 -e_snr_step=.1 -P -nb_frame=1500 -Tperf=70) +add_physim_test(physim.4g.ulsim.test2 "5 MHz, FDD (MCS 16), AWGN , 12dB (70%)" ulsim -BnbRBs=25 -mcs=16 -yN_rx=1 -gchannel=N -xTransmission=1 -snr=12 -wsnrInterrupt=1.0 -e_snr_step=.1 -P -nb_frame=1500 -Tperf=70) +add_physim_test(physim.4g.ulsim.test3 "10 MHz, R3.FDD (MCS 5), AWGN, 6dB (70%)" ulsim -BnbRBs=50 -mcs=5 -yN_rx=1 -gchannel=N -xTransmission=1 -snr=6 -wsnrInterrupt=1.0 -e_snr_step=.1 -P -nb_frame=1500 -Tperf=70) +add_physim_test(physim.4g.ulsim.test4 "10 MHz, R3-1.FDD (MCS 16), AWGN, 12dB (70%)" ulsim -BnbRBs=50 -mcs=16 -yN_rx=1 -gchannel=N -xTransmission=1 -snr=12 -wsnrInterrupt=1.0 -e_snr_step=.1 -P -nb_frame=1500 -Tperf=70) +add_physim_test(physim.4g.ulsim.test5 "20 MHz, FDD (MCS 5), AWGN, 6dB (70%)" ulsim -BnbRBs=100 -mcs=5 -yN_rx=1 -gchannel=N -xTransmission=1 -snr=6 -wsnrInterrupt=1.0 -e_snr_step=.1 -P -nb_frame=1500 -Tperf=70) +add_physim_test(physim.4g.ulsim.test6 "20 MHz, FDD (MCS 16), AWGN, 12 dB (70%)" ulsim -BnbRBs=100 -mcs=16 -yN_rx=1 -gchannel=N -xTransmission=1 -snr=12 -wsnrInterrupt=1.0 -e_snr_step=.1 -P -nb_frame=1500 -Tperf=70) #################################################################################### ###### ldpctest unit test ###### #################################################################################### -add_physim_test(5g ldpctest test1 "block length = 3872, BG1" -l3872 -s10 -n300) -add_physim_test(5g ldpctest test2 "block length = 4224, BG1" -l4224 -s10 -n300) -add_physim_test(5g ldpctest test3 "block length = 4576, BG1" -l4576 -s10 -n300) -add_physim_test(5g ldpctest test4 "block length = 4928, BG1" -l4928 -s10 -n300) -add_physim_test(5g ldpctest test5 "block length = 5280, BG1" -l5280 -s10 -n300) -add_physim_test(5g ldpctest test6 "block length = 5632, BG1" -l5632 -s10 -n300) -add_physim_test(5g ldpctest test7 "block length = 6336, BG1" -l6336 -s10 -n300) -add_physim_test(5g ldpctest test8 "block length = 7040, BG1" -l7040 -s10 -n300) -add_physim_test(5g ldpctest test9 "block length = 7744, BG1" -l7744 -s10 -n300) -add_physim_test(5g ldpctest test10 "block length = 8448, BG1" -l8448 -s10 -n300) -add_physim_test(5g ldpctest test11 "block length = 1, BG2" -l1 -s10 -n300) -add_physim_test(5g ldpctest test12 "block length = 100, BG2" -l100 -s10 -n300) -add_physim_test(5g ldpctest test13 "block length = 193, BG2" -l193 -s10 -n300) -add_physim_test(5g ldpctest test14 "block length = 500, BG2" -l500 -s10 -n300) -add_physim_test(5g ldpctest test15 "block length = 561, BG2" -l561 -s10 -n300) -add_physim_test(5g ldpctest test16 "block length = 600, BG2" -l600 -s10 -n300) -add_physim_test(5g ldpctest test17 "block length = 641, BG2" -l641 -s10 -n300) -add_physim_test(5g ldpctest test18 "block length = 2000, BG1" -l2000 -s10 -n300) -add_physim_test(5g ldpctest test19 "block length = 3000, BG1" -l3000 -s10 -n300) -add_physim_test(5g ldpctest test20 "block length = 3840, BG1" -l3840 -s10 -n300) +add_physim_test(physim.5g.ldpctest.test1 "block length = 3872, BG1" ldpctest -l3872 -s10 -n300) +add_physim_test(physim.5g.ldpctest.test2 "block length = 4224, BG1" ldpctest -l4224 -s10 -n300) +add_physim_test(physim.5g.ldpctest.test3 "block length = 4576, BG1" ldpctest -l4576 -s10 -n300) +add_physim_test(physim.5g.ldpctest.test4 "block length = 4928, BG1" ldpctest -l4928 -s10 -n300) +add_physim_test(physim.5g.ldpctest.test5 "block length = 5280, BG1" ldpctest -l5280 -s10 -n300) +add_physim_test(physim.5g.ldpctest.test6 "block length = 5632, BG1" ldpctest -l5632 -s10 -n300) +add_physim_test(physim.5g.ldpctest.test7 "block length = 6336, BG1" ldpctest -l6336 -s10 -n300) +add_physim_test(physim.5g.ldpctest.test8 "block length = 7040, BG1" ldpctest -l7040 -s10 -n300) +add_physim_test(physim.5g.ldpctest.test9 "block length = 7744, BG1" ldpctest -l7744 -s10 -n300) +add_physim_test(physim.5g.ldpctest.test10 "block length = 8448, BG1" ldpctest -l8448 -s10 -n300) +add_physim_test(physim.5g.ldpctest.test11 "block length = 1, BG2" ldpctest -l1 -s10 -n300) +add_physim_test(physim.5g.ldpctest.test12 "block length = 100, BG2" ldpctest -l100 -s10 -n300) +add_physim_test(physim.5g.ldpctest.test13 "block length = 193, BG2" ldpctest -l193 -s10 -n300) +add_physim_test(physim.5g.ldpctest.test14 "block length = 500, BG2" ldpctest -l500 -s10 -n300) +add_physim_test(physim.5g.ldpctest.test15 "block length = 561, BG2" ldpctest -l561 -s10 -n300) +add_physim_test(physim.5g.ldpctest.test16 "block length = 600, BG2" ldpctest -l600 -s10 -n300) +add_physim_test(physim.5g.ldpctest.test17 "block length = 641, BG2" ldpctest -l641 -s10 -n300) +add_physim_test(physim.5g.ldpctest.test18 "block length = 2000, BG1" ldpctest -l2000 -s10 -n300) +add_physim_test(physim.5g.ldpctest.test19 "block length = 3000, BG1" ldpctest -l3000 -s10 -n300) +add_physim_test(physim.5g.ldpctest.test20 "block length = 3840, BG1" ldpctest -l3840 -s10 -n300) #################################################################################### ###### polartest unit test ###### #################################################################################### -add_physim_test(5g polartest test1 "PBCH polar test" -q -s-10 -f0) -add_physim_test(5g polartest test2 "DCI polar test" -q -s-10 -f0 -m1) -add_physim_test(5g polartest test3 "UCI polar test,6-bit CRC" -q -s-2 -f2 -m2 -k12) -add_physim_test(5g polartest test4 "UCI polar test,11-bit CRC" -q -s-2 -f2 -m2 -k20) +add_physim_test(physim.5g.polartest.test1 "PBCH polar test" polartest -q -s-10 -f0) +add_physim_test(physim.5g.polartest.test2 "DCI polar test" polartest -q -s-10 -f0 -m1) +add_physim_test(physim.5g.polartest.test3 "UCI polar test,6-bit CRC" polartest -q -s-2 -f2 -m2 -k12) +add_physim_test(physim.5g.polartest.test4 "UCI polar test,11-bit CRC" polartest -q -s-2 -f2 -m2 -k20) #################################################################################### ###### nr_pbchsim unit test ###### #################################################################################### -add_physim_test(5g nr_pbchsim 106rb.test1 "PBCH-only, 106 PRB, NID 2" -s-11 -S-8 -n30 -R106 -N2) -add_physim_test(5g nr_pbchsim 106rb.test2 "PBCH and synchronization, 106PBR" -s-11 -S-8 -n30 -o8000 -I -R106) -add_physim_test(5g nr_pbchsim 106rb.test3 "PBCH and synchronization, 106PBR, SSB SC OFFSET 6" -s-11 -S-8 -n30 -R106 -c6) -add_physim_test(5g nr_pbchsim 217rb.test1 "PBCH-only, 217 PRB" -s-10 -S-8 -n30 -R217) -add_physim_test(5g nr_pbchsim 217rb.test2 "PBCH and synchronization, 217 RPB" -s-10 -S-8 -n30 -o8000 -I -R217) -add_physim_test(5g nr_pbchsim 273rb.test1 "PBCH-only, 273 PRB" -s-10 -S-8 -n30 -R273) -add_physim_test(5g nr_pbchsim 273rb.test2 "PBCH and synchronization, 273 PRB" -s-10 -S-8 -n30 -o8000 -I -R273) -add_physim_test(5g nr_pbchsim otherSCS.test1 "PBCH-only, 15Khz, 5Mhz" -s-10 -S-8 -n30 -m0 -R25) -add_physim_test(5g nr_pbchsim otherSCS.test2 "PBCH-only, 120Khz, 50Mhz" -s-10 -S-8 -n30 -m3 -R32) +add_physim_test(physim.5g.nr_pbchsim.106rb.test1 "PBCH-only, 106 PRB, NID 2" nr_pbchsim -s-11 -S-8 -n30 -R106 -N2) +add_physim_test(physim.5g.nr_pbchsim.106rb.test2 "PBCH and synchronization, 106PBR" nr_pbchsim -s-11 -S-8 -n30 -o8000 -I -R106) +add_physim_test(physim.5g.nr_pbchsim.106rb.test3 "PBCH and synchronization, 106PBR, SSB SC OFFSET 6" nr_pbchsim -s-11 -S-8 -n30 -R106 -c6) +add_physim_test(physim.5g.nr_pbchsim.217rb.test1 "PBCH-only, 217 PRB" nr_pbchsim -s-10 -S-8 -n30 -R217) +add_physim_test(physim.5g.nr_pbchsim.217rb.test2 "PBCH and synchronization, 217 RPB" nr_pbchsim -s-10 -S-8 -n30 -o8000 -I -R217) +add_physim_test(physim.5g.nr_pbchsim.273rb.test1 "PBCH-only, 273 PRB" nr_pbchsim -s-10 -S-8 -n30 -R273) +add_physim_test(physim.5g.nr_pbchsim.273rb.test2 "PBCH and synchronization, 273 PRB" nr_pbchsim -s-10 -S-8 -n30 -o8000 -I -R273) +add_physim_test(physim.5g.nr_pbchsim.otherSCS.test1 "PBCH-only, 15Khz, 5Mhz" nr_pbchsim -s-10 -S-8 -n30 -m0 -R25) +add_physim_test(physim.5g.nr_pbchsim.otherSCS.test2 "PBCH-only, 120Khz, 50Mhz" nr_pbchsim -s-10 -S-8 -n30 -m3 -R32) #################################################################################### ###### nr_dlsim unit test ###### #################################################################################### -add_physim_test(5g nr_dlsim basic.test1 "106 PRB" -n300 -R106 -b106 -s5) -add_physim_test(5g nr_dlsim basic.test2 "217 PRB" -n300 -R217 -b217 -s5) -add_physim_test(5g nr_dlsim basic.test3 "273 PRB" -n300 -R273 -b273 -s5) -add_physim_test(5g nr_dlsim basic.test4 "HARQ test 25% TP 4 rounds" -n300 -s1 -S2 -t25) -add_physim_test(5g nr_dlsim basic.test5 "HARQ test 33% TP 3 rounds" -n300 -s1 -S2 -t33) -add_physim_test(5g nr_dlsim basic.test6 "HARQ test 50% TP 2 rounds" -n300 -s5 -S7 -t50) -add_physim_test(5g nr_dlsim basic.test7 "25 PRBs, 15 kHz SCS" -n300 -m0 -e0 -R25 -b25 -i 2 1 0) -add_physim_test(5g nr_dlsim basic.test8 "32 PRBs, 120 kHz SCS" -n300 -s5 -m3 -R32 -b32) -add_physim_test(5g nr_dlsim offset.test1 "106 PRB 25 PDSCH-Offset" -n300 -R106 -a25 -s5) -add_physim_test(5g nr_dlsim offset.test2 "106 PRB 51 PDSCH-Offset" -n300 -R106 -a51 -s5) -add_physim_test(5g nr_dlsim offset.test3 "217 PRB 100 PDSCH-PRBs" -n300 -R217 -b100 -s5) -add_physim_test(5g nr_dlsim offset.test4 "217 PRB 80 PDSCH-Offset" -n300 -R217 -a80 -s5) -add_physim_test(5g nr_dlsim offset.test5 "217 PRB 100 PDSCH-PRBs 110 PDSCH-Offset" -n300 -R217 -a110 -s5 -b100) -add_physim_test(5g nr_dlsim mcs.mimo.test1 "106 PRBs 50 PDSCH-PRBs MCS Index 27" -n300 -e27 -s30) -add_physim_test(5g nr_dlsim mcs.mimo.test2 "106 PRBs 50 PDSCH-PRBs MCS Index 16" -n300 -e16 -s11 -S13) -add_physim_test(5g nr_dlsim mcs.mimo.test3 "106 MCS-TABLE 256 QAM MCS Index 26" -n300 -q1 -e26 -s30) -add_physim_test(5g nr_dlsim mcs.mimo.test4 "106 MCS-TABLE 256 QAM Fading Channel" -n300 -q1 -e24 -s30 -gA) -add_physim_test(5g nr_dlsim mcs.mimo.test5 "MCS 0, low SNR performance" -n300 -e0 -t95 -S-1.0 -i 2 1 0) -add_physim_test(5g nr_dlsim mcs.mimo.test6 "4x4 MIMO, 1 Layer" -n30 -s20 -U 3 0 0 2 -gA -x1 -y4 -z4) -add_physim_test(5g nr_dlsim mcs.mimo.test7 "4x4 MIMO, 2 Layers" -n30 -s20 -U 3 0 0 2 -gA -x2 -y4 -z4) -add_physim_test(5g nr_dlsim mcs.mimo.test8 "4x4 MIMO, 2 Layers 256 QAM" -n30 -s25 -e22 -q1 -U 3 0 0 2 -gA -x2 -y4 -z4) -add_physim_test(5g nr_dlsim mcs.mimo.test9 "4x4 MIMO, 4 Layers" -n30 -s20 -U 3 0 0 2 -x4 -y4 -z4) -add_physim_test(5g nr_dlsim dmrs.ptrs.test1 "3 PTRS, 8 Interpolated Symbols" -n300 -s5 -T 2 2 2) -add_physim_test(5g nr_dlsim dmrs.ptrs.test2 "6 PTRS, 5 Interpolated Symbols" -n300 -s5 -T 2 1 2) -add_physim_test(5g nr_dlsim dmrs.ptrs.test3 "11 PTRS, 0 Interpolated Symbols" -n300 -s5 -T 2 0 4) -add_physim_test(5g nr_dlsim dmrs.ptrs.test4 "Mapping type A, 2 DMRS Symbols" -n300 -s5 -S7 -U 2 0 1) -add_physim_test(5g nr_dlsim dmrs.ptrs.test5 "Mapping type A, 3 DMRS Symbols" -n300 -s5 -S7 -U 2 0 2) -add_physim_test(5g nr_dlsim dmrs.ptrs.test6 "Mapping type B, 4 DMRS Symbols" -n300 -s5 -S7 -U 2 1 3) +add_physim_test(physim.5g.nr_dlsim.basic.test1 "106 PRB" nr_dlsim -n300 -R106 -b106 -s5) +add_physim_test(physim.5g.nr_dlsim.basic.test2 "217 PRB" nr_dlsim -n300 -R217 -b217 -s5) +add_physim_test(physim.5g.nr_dlsim.basic.test3 "273 PRB" nr_dlsim -n300 -R273 -b273 -s5) +add_physim_test(physim.5g.nr_dlsim.basic.test4 "HARQ test 25% TP 4 rounds" nr_dlsim -n300 -s1 -S2 -t25) +add_physim_test(physim.5g.nr_dlsim.basic.test5 "HARQ test 33% TP 3 rounds" nr_dlsim -n300 -s1 -S2 -t33) +add_physim_test(physim.5g.nr_dlsim.basic.test6 "HARQ test 50% TP 2 rounds" nr_dlsim -n300 -s5 -S7 -t50) +add_physim_test(physim.5g.nr_dlsim.basic.test7 "25 PRBs, 15 kHz SCS" nr_dlsim -n300 -m0 -e0 -R25 -b25 -i 2 1 0) +add_physim_test(physim.5g.nr_dlsim.basic.test8 "32 PRBs, 120 kHz SCS" nr_dlsim -n300 -s5 -m3 -R32 -b32) +add_physim_test(physim.5g.nr_dlsim.offset.test1 "106 PRB 25 PDSCH-Offset" nr_dlsim -n300 -R106 -a25 -s5) +add_physim_test(physim.5g.nr_dlsim.offset.test2 "106 PRB 51 PDSCH-Offset" nr_dlsim -n300 -R106 -a51 -s5) +add_physim_test(physim.5g.nr_dlsim.offset.test3 "217 PRB 100 PDSCH-PRBs" nr_dlsim -n300 -R217 -b100 -s5) +add_physim_test(physim.5g.nr_dlsim.offset.test4 "217 PRB 80 PDSCH-Offset" nr_dlsim -n300 -R217 -a80 -s5) +add_physim_test(physim.5g.nr_dlsim.offset.test5 "217 PRB 100 PDSCH-PRBs 110 PDSCH-Offset" nr_dlsim -n300 -R217 -a110 -s5 -b100) +add_physim_test(physim.5g.nr_dlsim.mcs.mimo.test1 "106 PRBs 50 PDSCH-PRBs MCS Index 27" nr_dlsim -n300 -e27 -s30) +add_physim_test(physim.5g.nr_dlsim.mcs.mimo.test2 "106 PRBs 50 PDSCH-PRBs MCS Index 16" nr_dlsim -n300 -e16 -s11 -S13) +add_physim_test(physim.5g.nr_dlsim.mcs.mimo.test3 "106 MCS-TABLE 256 QAM MCS Index 26" nr_dlsim -n300 -q1 -e26 -s30) +add_physim_test(physim.5g.nr_dlsim.mcs.mimo.test4 "106 MCS-TABLE 256 QAM Fading Channel" nr_dlsim -n300 -q1 -e24 -s30 -gA) +add_physim_test(physim.5g.nr_dlsim.mcs.mimo.test5 "MCS 0, low SNR performance" nr_dlsim -n300 -e0 -t95 -S-1.0 -i 2 1 0) +add_physim_test(physim.5g.nr_dlsim.mcs.mimo.test6 "4x4 MIMO, 1 Layer" nr_dlsim -n30 -s20 -U 3 0 0 2 -gA -x1 -y4 -z4) +add_physim_test(physim.5g.nr_dlsim.mcs.mimo.test7 "4x4 MIMO, 2 Layers" nr_dlsim -n30 -s20 -U 3 0 0 2 -gA -x2 -y4 -z4) +add_physim_test(physim.5g.nr_dlsim.mcs.mimo.test8 "4x4 MIMO, 2 Layers 256 QAM" nr_dlsim -n30 -s25 -e22 -q1 -U 3 0 0 2 -gA -x2 -y4 -z4) +add_physim_test(physim.5g.nr_dlsim.mcs.mimo.test9 "4x4 MIMO, 4 Layers" nr_dlsim -n30 -s20 -U 3 0 0 2 -x4 -y4 -z4) +add_physim_test(physim.5g.nr_dlsim.dmrs.ptrs.test1 "3 PTRS, 8 Interpolated Symbols" nr_dlsim -n300 -s5 -T 2 2 2) +add_physim_test(physim.5g.nr_dlsim.dmrs.ptrs.test2 "6 PTRS, 5 Interpolated Symbols" nr_dlsim -n300 -s5 -T 2 1 2) +add_physim_test(physim.5g.nr_dlsim.dmrs.ptrs.test3 "11 PTRS, 0 Interpolated Symbols" nr_dlsim -n300 -s5 -T 2 0 4) +add_physim_test(physim.5g.nr_dlsim.dmrs.ptrs.test4 "Mapping type A, 2 DMRS Symbols" nr_dlsim -n300 -s5 -S7 -U 2 0 1) +add_physim_test(physim.5g.nr_dlsim.dmrs.ptrs.test5 "Mapping type A, 3 DMRS Symbols" nr_dlsim -n300 -s5 -S7 -U 2 0 2) +add_physim_test(physim.5g.nr_dlsim.dmrs.ptrs.test6 "Mapping type B, 4 DMRS Symbols" nr_dlsim -n300 -s5 -S7 -U 2 1 3) #################################################################################### ###### nr_dlschsim unit test ###### #################################################################################### -add_physim_test(5g nr_dlschsim test1 "106 PRBs" -R 106 -m9 -s13 -n300) -add_physim_test(5g nr_dlschsim test2 "217 PRBs" -R 217 -m15 -s15 -n300) -add_physim_test(5g nr_dlschsim test3 "273 PRBs" -R 273 -m19 -s20 -n300) +add_physim_test(physim.5g.nr_dlschsim.test1 "106 PRBs" nr_dlschsim -R 106 -m9 -s13 -n300) +add_physim_test(physim.5g.nr_dlschsim.test2 "217 PRBs" nr_dlschsim -R 217 -m15 -s15 -n300) +add_physim_test(physim.5g.nr_dlschsim.test3 "273 PRBs" nr_dlschsim -R 273 -m19 -s20 -n300) #################################################################################### ###### smallblocktest unit test ###### #################################################################################### -add_physim_test(5g smallblocktest test1 "3 bits" -l 3 -s -4 -d 1 -i 10000) -add_physim_test(5g smallblocktest test2 "6 bits" -l 6 -s -4 -d 1 -i 10000) -add_physim_test(5g smallblocktest test3 "7 bits" -l 7 -s -4 -d 1 -i 10000) -add_physim_test(5g smallblocktest test4 "11 bits" -l 11 -s -4 -d 1 -i 10000) +add_physim_test(physim.5g.smallblocktest.test1 "3 bits" smallblocktest -l 3 -s -4 -d 1 -i 10000) +add_physim_test(physim.5g.smallblocktest.test2 "6 bits" smallblocktest -l 6 -s -4 -d 1 -i 10000) +add_physim_test(physim.5g.smallblocktest.test3 "7 bits" smallblocktest -l 7 -s -4 -d 1 -i 10000) +add_physim_test(physim.5g.smallblocktest.test4 "11 bits" smallblocktest -l 11 -s -4 -d 1 -i 10000) #################################################################################### ###### nr_ulschsim unit test ###### #################################################################################### -add_physim_test(5g nr_ulschsim test1 "106 PRBs" -R 106 -m9 -s13 -n300) -add_physim_test(5g nr_ulschsim test2 "217 PRBs" -R 217 -m15 -s15 -n300) -add_physim_test(5g nr_ulschsim test3 "273 PRBs" -R 273 -m19 -s20 -n300) -add_physim_test(5g nr_ulschsim test4 "106 PRBs 4-layer MIMO" -R 106 -m9 -s13 -n300 -y4 -z4 -W4) +add_physim_test(physim.5g.nr_ulschsim.test1 "106 PRBs" nr_ulschsim -R 106 -m9 -s13 -n300) +add_physim_test(physim.5g.nr_ulschsim.test2 "217 PRBs" nr_ulschsim -R 217 -m15 -s15 -n300) +add_physim_test(physim.5g.nr_ulschsim.test3 "273 PRBs" nr_ulschsim -R 273 -m19 -s20 -n300) +add_physim_test(physim.5g.nr_ulschsim.test4 "106 PRBs 4-layer MIMO" nr_ulschsim -R 106 -m9 -s13 -n300 -y4 -z4 -W4) #################################################################################### ###### nr_pucchsim unit test ###### #################################################################################### -add_physim_test(5g nr_pucchsim test1 "Format 0 1-bit ACK miss 106 PRB" -R 106 -i 1 -P 0 -b 1 -s-2 -n3000) -add_physim_test(5g nr_pucchsim test2 "Format 0 2-bit ACK miss 106 PRB" -R 106 -i 1 -P 0 -b 2 -s-2 -n3000) -add_physim_test(5g nr_pucchsim test3 "Format 0 2-bit ACK miss, 1-bit SR 106 PRB" -R 106 -i 1 -P 0 -b 2 -s-2 -c -n3000) -add_physim_test(5g nr_pucchsim test4 "Format 2 3-bit 2/106 PRB" -R 106 -i 1 -P 2 -b 3 -s0 -n3000) -add_physim_test(5g nr_pucchsim test5 "Format 2 4-bit 2/106 PRB" -R 106 -i 1 -P 2 -b 4 -s0 -n3000) -add_physim_test(5g nr_pucchsim test6 "Format 2 5-bit 2/106 PRB" -R 106 -i 1 -P 2 -b 5 -s1 -n3000) -add_physim_test(5g nr_pucchsim test7 "Format 2 6-bit 2/106 PRB" -R 106 -i 1 -P 2 -b 6 -s2 -n3000) -add_physim_test(5g nr_pucchsim test8 "Format 2 7-bit 2/106 PRB" -R 106 -i 1 -P 2 -b 7 -s3 -n3000) -add_physim_test(5g nr_pucchsim test9 "Format 2 8-bit 2/106 PRB" -R 106 -i 1 -P 2 -b 8 -s4 -n3000) -add_physim_test(5g nr_pucchsim test10 "Format 2 9-bit 2/106 PRB" -R 106 -i 1 -P 2 -b 9 -s5 -n3000) -add_physim_test(5g nr_pucchsim test11 "Format 2 10-bit 2/106 PRB" -R 106 -i 1 -P 2 -b 10 -s6 -n3000) -add_physim_test(5g nr_pucchsim test12 "Format 2 11-bit 2/106 PRB" -R 106 -i 1 -P 2 -b 11 -s6 -n3000) -add_physim_test(5g nr_pucchsim test13 "Format 2 12-bit 4/106 PRB" -R 106 -i 1 -P 2 -q4 -b 12 -s-3 -n3000) -add_physim_test(5g nr_pucchsim test14 "Format 2 19-bit 4/106 PRB" -R 106 -i 1 -P 2 -q4 -b 19 -s-3 -n3000) -add_physim_test(5g nr_pucchsim test15 "Format 2 12-bit 8/106 PRB" -R 106 -i 1 -P 2 -q8 -b 12 -s-3 -n3000) -add_physim_test(5g nr_pucchsim test16 "Format 2 19-bit 8/106 PRB" -R 106 -i 1 -P 2 -q8 -b 19 -s-3 -n3000) -add_physim_test(5g nr_pucchsim test17 "Format 2 32-bit 8/106 PRB" -R 106 -i 1 -P 2 -q8 -b 32 -s-3 -n3000) -add_physim_test(5g nr_pucchsim test18 "Format 2 32-bit 16/106 PRB" -R 106 -i 1 -P 2 -q16 -b 32 -s-3 -n3000) -add_physim_test(5g nr_pucchsim test19 "Format 2 64-bit 16/106 PRB" -R 106 -i 1 -P 2 -q16 -b 64 -s-3 -n3000) -add_physim_test(5g nr_pucchsim test20 "Format 0 1-bit Ack miss 273 PRB" -R 273 -z8 -i 1 -P 0 -b 1 -s-2 -n3000) -add_physim_test(5g nr_pucchsim test21 "Format 0 2-bit Ack miss 273 PRB" -R 273 -z8 -i 1 -P 0 -b 2 -s-2 -n3000) -add_physim_test(5g nr_pucchsim test22 "Format 0 2-bit Ack miss+SR 273 PRB" -R 273 -z8 -i 1 -P 0 -b 2 -s-2 -c -n3000) -add_physim_test(5g nr_pucchsim test23 "Format 2 4-bit 2/273 PRB" -R 273 -z8 -i 1 -P 2 -b 4 -s-8 -S0 -n3000) -add_physim_test(5g nr_pucchsim test24 "Format 2 7-bit 2/273 PRB" -R 273 -z8 -i 1 -P 2 -b 7 -s3 -n3000) -add_physim_test(5g nr_pucchsim test25 "Format 2 11-bit 2/273 PRB" -R 273 -z8 -i 1 -P 2 -b 11 -s6 -n3000) -add_physim_test(5g nr_pucchsim test26 "Format 2 12-bit 8/273 PRB" -R 273 -z8 -i 1 -P 2 -q8 -b 12 -s-3 -n3000) -add_physim_test(5g nr_pucchsim test27 "Format 2 19-bit 8/273 PRB" -R 273 -z8 -i 1 -P 2 -q8 -b 19 -s-3 -n3000) -add_physim_test(5g nr_pucchsim test28 "Format 2 64-bit 16/273 PRB" -R 273 -z8 -i 1 -P 2 -q16 -b 64 -s-3 -n3000) -add_physim_test(5g nr_pucchsim test29 "Format 2 64-bit 16/273 PRB Delay 2us" -R 273 -z8 -i 1 -P 2 -q16 -b 64 -s0 -S7 -d 2 -n3000) +add_physim_test(physim.5g.nr_pucchsim.test1 "Format 0 1-bit ACK miss 106 PRB" nr_pucchsim -R 106 -i 1 -P 0 -b 1 -s-2 -n3000) +add_physim_test(physim.5g.nr_pucchsim.test2 "Format 0 2-bit ACK miss 106 PRB" nr_pucchsim -R 106 -i 1 -P 0 -b 2 -s-2 -n3000) +add_physim_test(physim.5g.nr_pucchsim.test3 "Format 0 2-bit ACK miss, 1-bit SR 106 PRB" nr_pucchsim -R 106 -i 1 -P 0 -b 2 -s-2 -c -n3000) +add_physim_test(physim.5g.nr_pucchsim.test4 "Format 2 3-bit 2/106 PRB" nr_pucchsim -R 106 -i 1 -P 2 -b 3 -s0 -n3000) +add_physim_test(physim.5g.nr_pucchsim.test5 "Format 2 4-bit 2/106 PRB" nr_pucchsim -R 106 -i 1 -P 2 -b 4 -s0 -n3000) +add_physim_test(physim.5g.nr_pucchsim.test6 "Format 2 5-bit 2/106 PRB" nr_pucchsim -R 106 -i 1 -P 2 -b 5 -s1 -n3000) +add_physim_test(physim.5g.nr_pucchsim.test7 "Format 2 6-bit 2/106 PRB" nr_pucchsim -R 106 -i 1 -P 2 -b 6 -s2 -n3000) +add_physim_test(physim.5g.nr_pucchsim.test8 "Format 2 7-bit 2/106 PRB" nr_pucchsim -R 106 -i 1 -P 2 -b 7 -s3 -n3000) +add_physim_test(physim.5g.nr_pucchsim.test9 "Format 2 8-bit 2/106 PRB" nr_pucchsim -R 106 -i 1 -P 2 -b 8 -s4 -n3000) +add_physim_test(physim.5g.nr_pucchsim.test10 "Format 2 9-bit 2/106 PRB" nr_pucchsim -R 106 -i 1 -P 2 -b 9 -s5 -n3000) +add_physim_test(physim.5g.nr_pucchsim.test11 "Format 2 10-bit 2/106 PRB" nr_pucchsim -R 106 -i 1 -P 2 -b 10 -s6 -n3000) +add_physim_test(physim.5g.nr_pucchsim.test12 "Format 2 11-bit 2/106 PRB" nr_pucchsim -R 106 -i 1 -P 2 -b 11 -s6 -n3000) +add_physim_test(physim.5g.nr_pucchsim.test13 "Format 2 12-bit 4/106 PRB" nr_pucchsim -R 106 -i 1 -P 2 -q4 -b 12 -s-3 -n3000) +add_physim_test(physim.5g.nr_pucchsim.test14 "Format 2 19-bit 4/106 PRB" nr_pucchsim -R 106 -i 1 -P 2 -q4 -b 19 -s-3 -n3000) +add_physim_test(physim.5g.nr_pucchsim.test15 "Format 2 12-bit 8/106 PRB" nr_pucchsim -R 106 -i 1 -P 2 -q8 -b 12 -s-3 -n3000) +add_physim_test(physim.5g.nr_pucchsim.test16 "Format 2 19-bit 8/106 PRB" nr_pucchsim -R 106 -i 1 -P 2 -q8 -b 19 -s-3 -n3000) +add_physim_test(physim.5g.nr_pucchsim.test17 "Format 2 32-bit 8/106 PRB" nr_pucchsim -R 106 -i 1 -P 2 -q8 -b 32 -s-3 -n3000) +add_physim_test(physim.5g.nr_pucchsim.test18 "Format 2 32-bit 16/106 PRB" nr_pucchsim -R 106 -i 1 -P 2 -q16 -b 32 -s-3 -n3000) +add_physim_test(physim.5g.nr_pucchsim.test19 "Format 2 64-bit 16/106 PRB" nr_pucchsim -R 106 -i 1 -P 2 -q16 -b 64 -s-3 -n3000) +add_physim_test(physim.5g.nr_pucchsim.test20 "Format 0 1-bit Ack miss 273 PRB" nr_pucchsim -R 273 -z8 -i 1 -P 0 -b 1 -s-2 -n3000) +add_physim_test(physim.5g.nr_pucchsim.test21 "Format 0 2-bit Ack miss 273 PRB" nr_pucchsim -R 273 -z8 -i 1 -P 0 -b 2 -s-2 -n3000) +add_physim_test(physim.5g.nr_pucchsim.test22 "Format 0 2-bit Ack miss+SR 273 PRB" nr_pucchsim -R 273 -z8 -i 1 -P 0 -b 2 -s-2 -c -n3000) +add_physim_test(physim.5g.nr_pucchsim.test23 "Format 2 4-bit 2/273 PRB" nr_pucchsim -R 273 -z8 -i 1 -P 2 -b 4 -s-8 -S0 -n3000) +add_physim_test(physim.5g.nr_pucchsim.test24 "Format 2 7-bit 2/273 PRB" nr_pucchsim -R 273 -z8 -i 1 -P 2 -b 7 -s3 -n3000) +add_physim_test(physim.5g.nr_pucchsim.test25 "Format 2 11-bit 2/273 PRB" nr_pucchsim -R 273 -z8 -i 1 -P 2 -b 11 -s6 -n3000) +add_physim_test(physim.5g.nr_pucchsim.test26 "Format 2 12-bit 8/273 PRB" nr_pucchsim -R 273 -z8 -i 1 -P 2 -q8 -b 12 -s-3 -n3000) +add_physim_test(physim.5g.nr_pucchsim.test27 "Format 2 19-bit 8/273 PRB" nr_pucchsim -R 273 -z8 -i 1 -P 2 -q8 -b 19 -s-3 -n3000) +add_physim_test(physim.5g.nr_pucchsim.test28 "Format 2 64-bit 16/273 PRB" nr_pucchsim -R 273 -z8 -i 1 -P 2 -q16 -b 64 -s-3 -n3000) +add_physim_test(physim.5g.nr_pucchsim.test29 "Format 2 64-bit 16/273 PRB Delay 2us" nr_pucchsim -R 273 -z8 -i 1 -P 2 -q16 -b 64 -s0 -S7 -d 2 -n3000) #################################################################################### ###### nr_ulsim unit test ###### #################################################################################### -add_physim_test(5g nr_ulsim misc.test1 "MCS 9 106 PRBs" -n300 -m9 -r106 -s5) -add_physim_test(5g nr_ulsim misc.test2 "MCS 16 50 PRBs" -n300 -m16 -s10) -add_physim_test(5g nr_ulsim misc.test3 "MCS 28 50 PRBs" -n300 -m28 -s20) -add_physim_test(5g nr_ulsim misc.test4 "MCS 27 50 PRBs 256QAM" -n300 -m27 -s25 -q1) -add_physim_test(5g nr_ulsim misc.test5 "MCS 9 217 PRBs" -n300 -m9 -R217 -r217 -s5) -add_physim_test(5g nr_ulsim misc.test6 "MCS 9 273 PRBs" -n300 -m9 -R273 -r273 -s5) -add_physim_test(5g nr_ulsim misc.test7 "PUSCH Type A, 2 DMRS Symbols" -n300 -s5 -U 0,1,1,1) -add_physim_test(5g nr_ulsim misc.test8 "PUSCH Type A, 3 DMRS, 4 PTRS, 5 Interpolated Symbols" -n300 -s5 -T 1,2 -U 0,2,1,1) -add_physim_test(5g nr_ulsim misc.test9 "PUSCH Type B, 3 DMRS, 2 PTRS, 7 Interpolated Symbols" -n300 -s5 -T 2,2 -U 1,2,1,1) -add_physim_test(5g nr_ulsim misc.test10 "PUSCH Type B, 3 DMRS, 2 PTRS, 3 Interpolated Symbols" -n300 -s5 -a4 -b8 -T 1,2 -U 1,3,1,1) -add_physim_test(5g nr_ulsim misc.test11 "25 PRBs, 15 kHz SCS" -n300 -u0 -m0 -R25 -r25 -i 1,0) -add_physim_test(5g nr_ulsim misc.test12 "32 PRBs, 120 kHz SCS" -n300 -s5 -r32 -R32 -u3) -add_physim_test(5g nr_ulsim misc.test13 "MCS 0, low SNR performance" -n300 -m0 -S -0.6 -i 1,0) -add_physim_test(5g nr_ulsim misc.test14 "MCS 28, 106 PRBs, Time shift 8" -n300 -m28 -R106 -r106 -t90 -s24 -S24 -d 8) -add_physim_test(5g nr_ulsim misc.test15 "SRS, SNR 40 dB" -n300 -s40 -E 1) -add_physim_test(5g nr_ulsim sc-fdma.test1 "SC-FDMA, 50 PRBs" -n300 -s5 -Z) -add_physim_test(5g nr_ulsim sc-fdma.test2 "SC-FDMA, 75 PRBs" -n300 -s5 -Z -r75) -add_physim_test(5g nr_ulsim sc-fdma.test3 "SC-FDMA, 216 PRBs" -n150 -s5 -Z -r216 -R217) -add_physim_test(5g nr_ulsim sc-fdma.test4 "SC-FDMA, 273 PRBs" -n150 -s5 -Z -r270 -R273) -add_physim_test(5g nr_ulsim sc-fdma.test5 "SC-FDMA, 3 DMRS" -n300 -s5 -Z -U 0,2,1,2) -add_physim_test(5g nr_ulsim mimo.test1 "MCS 19 50 PRBs 2 RX_Antenna" -n300 -m19 -s10 -S15 -z2) -add_physim_test(5g nr_ulsim mimo.test2 "MCS 9 106 PRBs MIMO 2 layers" -n300 -m9 -r106 -s8 -W2 -y2 -z2) -add_physim_test(5g nr_ulsim mimo.test3 "MCS 10 106 PRBs MIMO 2 layers" -n300 -m10 -r106 -s12 -W2 -y2 -z2) -add_physim_test(5g nr_ulsim mimo.test4 "MCS 19 106 PRBs MIMO 2 layers" -n300 -m19 -r106 -s22 -W2 -y2 -z2) -add_physim_test(5g nr_ulsim mimo.test5 "MCS 9 106 PRBs MIMO 4 layers" -n300 -m9 -r106 -s10 -W4 -y4 -z4) -add_physim_test(5g nr_ulsim 3gpp.test1 "3GPP G-FR1-A5-13, PUSCH Type A, 40 MHz BW, 30 kHz SCS, 2 RX Antennas Requirements Test" -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R106 -r106 -U 0,1,1,2 -z2 -s12.4 -S12.4) -add_physim_test(5g nr_ulsim 3gpp.test2 "3GPP G-FR1-A5-13, PUSCH Type A, 40 MHz BW, 30 kHz SCS, 4 RX Antennas Requirements Test" -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R106 -r106 -U 0,1,1,2 -z4 -s8.5 -S8.5) -add_physim_test(5g nr_ulsim 3gpp.test3 "3GPP G-FR1-A5-13, PUSCH Type A, 40 MHz BW, 30 kHz SCS, 8 RX Antennas Requirements Test" -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R106 -r106 -U 0,1,1,2 -z8 -s5.4 -S5.4) -add_physim_test(5g nr_ulsim 3gpp.test4 "3GPP G-FR1-A5-8, PUSCH Type B, 5 MHz BW, 15 kHz SCS, 2 RX Antennas Requirements Test" -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 0 -m20 -R25 -r25 -U 1,1,1,2 -z2 -s12.5 -S12.5) -add_physim_test(5g nr_ulsim 3gpp.test5 "3GPP G-FR1-A5-8, PUSCH Type B, 5 MHz BW, 15 kHz SCS, 4 RX Antennas Requirements Test" -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 0 -m20 -R25 -r25 -U 1,1,1,2 -z4 -s8.9 -S8.9) -add_physim_test(5g nr_ulsim 3gpp.test6 "3GPP G-FR1-A5-8, PUSCH Type B, 5 MHz BW, 15 kHz SCS, 8 RX Antennas Requirements Test" -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 0 -m20 -R25 -r25 -U 1,1,1,2 -z8 -s5.7 -S5.7) -add_physim_test(5g nr_ulsim 3gpp.test7 "3GPP G-FR1-A5-9, PUSCH Type B, 10 MHz BW, 15 kHz SCS, 2 RX Antennas Requirements Test" -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 0 -m20 -R52 -r52 -U 1,1,1,2 -z2 -s12.6 -S12.6) -add_physim_test(5g nr_ulsim 3gpp.test8 "3GPP G-FR1-A5-9, PUSCH Type B, 10 MHz BW, 15 kHz SCS, 4 RX Antennas Requirements Test" -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 0 -m20 -R52 -r52 -U 1,1,1,2 -z4 -s8.9 -S8.9) -add_physim_test(5g nr_ulsim 3gpp.test9 "3GPP G-FR1-A5-9, PUSCH Type B, 10 MHz BW, 15 kHz SCS, 8 RX Antennas Requirements Test" -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 0 -m20 -R52 -r52 -U 1,1,1,2 -z8 -s5.8 -S5.8) -add_physim_test(5g nr_ulsim 3gpp.test10 "3GPP G-FR1-A5-10, PUSCH Type B, 20 MHz BW, 15 kHz SCS, 2 RX Antennas Requirements Test" -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 0 -m20 -R106 -r106 -U 1,1,1,2 -z2 -s12.3 -S12.3) -add_physim_test(5g nr_ulsim 3gpp.test11 "3GPP G-FR1-A5-10, PUSCH Type B, 20 MHz BW, 15 kHz SCS, 4 RX Antennas Requirements Test" -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 0 -m20 -R106 -r106 -U 1,1,1,2 -z4 -s8.8 -S8.8) -add_physim_test(5g nr_ulsim 3gpp.test12 "3GPP G-FR1-A5-10, PUSCH Type B, 20 MHz BW, 15 kHz SCS, 8 RX Antennas Requirements Test" -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 0 -m20 -R106 -r106 -U 1,1,1,2 -z8 -s5.7 -S5.7) -add_physim_test(5g nr_ulsim 3gpp.test13 "3GPP G-FR1-A5-11, PUSCH Type B, 10 MHz BW, 30 kHz SCS, 2 RX Antennas Requirements Test" -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R24 -r24 -U 1,1,1,2 -z2 -s12.5 -S12.5) -add_physim_test(5g nr_ulsim 3gpp.test14 "3GPP G-FR1-A5-11, PUSCH Type B, 10 MHz BW, 30 kHz SCS, 4 RX Antennas Requirements Test" -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R24 -r24 -U 1,1,1,2 -z4 -s8.6 -S8.6) -add_physim_test(5g nr_ulsim 3gpp.test15 "3GPP G-FR1-A5-11, PUSCH Type B, 10 MHz BW, 30 kHz SCS, 8 RX Antennas Requirements Test" -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R24 -r24 -U 1,1,1,2 -z8 -s5.6 -S5.6) -add_physim_test(5g nr_ulsim 3gpp.test16 "3GPP G-FR1-A5-12, PUSCH Type B, 20 MHz BW, 30 kHz SCS, 2 RX Antennas Requirements Test" -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R51 -r51 -U 1,1,1,2 -z2 -s12.5 -S12.5) -add_physim_test(5g nr_ulsim 3gpp.test17 "3GPP G-FR1-A5-12, PUSCH Type B, 20 MHz BW, 30 kHz SCS, 4 RX Antennas Requirements Test" -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R51 -r51 -U 1,1,1,2 -z4 -s8.6 -S8.6) -add_physim_test(5g nr_ulsim 3gpp.test18 "3GPP G-FR1-A5-12, PUSCH Type B, 20 MHz BW, 30 kHz SCS, 8 RX Antennas Requirements Test" -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R51 -r51 -U 1,1,1,2 -z8 -s5.6 -S5.6) -add_physim_test(5g nr_ulsim 3gpp.test19 "3GPP G-FR1-A5-13, PUSCH Type B, 40 MHz BW, 30 kHz SCS, 2 RX Antennas Requirements Test" -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R106 -r106 -U 1,1,1,2 -z2 -s12.5 -S12.5) -add_physim_test(5g nr_ulsim 3gpp.test20 "3GPP G-FR1-A5-13, PUSCH Type B, 40 MHz BW, 30 kHz SCS, 4 RX Antennas Requirements Test" -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R106 -r106 -U 1,1,1,2 -z4 -s8.7 -S8.7) -add_physim_test(5g nr_ulsim 3gpp.test21 "3GPP G-FR1-A5-13, PUSCH Type B, 40 MHz BW, 30 kHz SCS, 8 RX Antennas Requirements Test" -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R106 -r106 -U 1,1,1,2 -z8 -s5.5 -S5.5) -add_physim_test(5g nr_ulsim 3gpp.test22 "3GPP G-FR1-A5-14, PUSCH Type B, 100 MHz BW, 30 kHz SCS, 2 RX Antennas Requirements Test" -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R273 -r273 -U 1,1,1,2 -z2 -s13.1 -S13.1) -add_physim_test(5g nr_ulsim 3gpp.test23 "3GPP G-FR1-A5-14, PUSCH Type B, 100 MHz BW, 30 kHz SCS, 4 RX Antennas Requirements Test" -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R273 -r273 -U 1,1,1,2 -z4 -s9.2 -S9.2) -add_physim_test(5g nr_ulsim 3gpp.test24 "3GPP G-FR1-A5-14, PUSCH Type B, 100 MHz BW, 30 kHz SCS, 8 RX Antennas Requirements Test" -n300 -b14 -I8 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R273 -r273 -U 1,1,1,2 -z8 -s5.9 -S5.9) -add_physim_test(5g nr_ulsim 3gpp.test25 "3GPP G-FR1-A3-27, PUSCH Type B, 40 MHz BW, 30 kHz SCS, 2 RX Antennas Requirements Test, 2 layers" -n300 -b14 -I15 -i 0,1 -g B,l -t70 -u 1 -m2 -R106 -r106 -U 1,1,1,2 -W2 -y2 -z2 -s1.7 -S1.7) -add_physim_test(5g nr_ulsim 3gpp.test26 "3GPP G-FR1-A3-27, PUSCH Type B, 40 MHz BW, 30 kHz SCS, 4 RX Antennas Requirements Test, 2 layers" -n300 -b14 -I15 -i 0,1 -g B,l -t70 -u 1 -m2 -R106 -r106 -U 1,1,1,2 -W2 -y2 -z4 -s-2.1 -S-2.1) -add_physim_test(5g nr_ulsim 3gpp.test27 "3GPP G-FR1-A4-27, PUSCH Type B, 40 MHz BW, 30 kHz SCS, 2 RX Antennas Requirements Test, 2 layers" -n300 -b14 -I15 -i 0,1 -g C,l -t70 -u 1 -m16 -R106 -r106 -U 1,1,1,2 -W2 -y2 -z2 -s18.7 -S18.7) -add_physim_test(5g nr_ulsim 3gpp.test28 "3GPP G-FR1-A4-27, PUSCH Type B, 40 MHz BW, 30 kHz SCS, 4 RX Antennas Requirements Test, 2 layers" -n300 -b14 -I15 -i 0,1 -g C,l -t70 -u 1 -m16 -R106 -r106 -U 1,1,1,2 -W2 -y2 -z4 -s11.2 -S11.2) +add_physim_test(physim.5g.nr_ulsim.misc.test1 "MCS 9 106 PRBs" nr_ulsim -n300 -m9 -r106 -s5) +add_physim_test(physim.5g.nr_ulsim.misc.test2 "MCS 16 50 PRBs" nr_ulsim -n300 -m16 -s10) +add_physim_test(physim.5g.nr_ulsim.misc.test3 "MCS 28 50 PRBs" nr_ulsim -n300 -m28 -s20) +add_physim_test(physim.5g.nr_ulsim.misc.test4 "MCS 27 50 PRBs 256QAM" nr_ulsim -n300 -m27 -s25 -q1) +add_physim_test(physim.5g.nr_ulsim.misc.test5 "MCS 9 217 PRBs" nr_ulsim -n300 -m9 -R217 -r217 -s5) +add_physim_test(physim.5g.nr_ulsim.misc.test6 "MCS 9 273 PRBs" nr_ulsim -n300 -m9 -R273 -r273 -s5) +add_physim_test(physim.5g.nr_ulsim.misc.test7 "PUSCH Type A, 2 DMRS Symbols" nr_ulsim -n300 -s5 -U 0,1,1,1) +add_physim_test(physim.5g.nr_ulsim.misc.test8 "PUSCH Type A, 3 DMRS, 4 PTRS, 5 Interpolated Symbols" nr_ulsim -n300 -s5 -T 1,2 -U 0,2,1,1) +add_physim_test(physim.5g.nr_ulsim.misc.test9 "PUSCH Type B, 3 DMRS, 2 PTRS, 7 Interpolated Symbols" nr_ulsim -n300 -s5 -T 2,2 -U 1,2,1,1) +add_physim_test(physim.5g.nr_ulsim.misc.test10 "PUSCH Type B, 3 DMRS, 2 PTRS, 3 Interpolated Symbols" nr_ulsim -n300 -s5 -a4 -b8 -T 1,2 -U 1,3,1,1) +add_physim_test(physim.5g.nr_ulsim.misc.test11 "25 PRBs, 15 kHz SCS" nr_ulsim -n300 -u0 -m0 -R25 -r25 -i 1,0) +add_physim_test(physim.5g.nr_ulsim.misc.test12 "32 PRBs, 120 kHz SCS" nr_ulsim -n300 -s5 -r32 -R32 -u3) +add_physim_test(physim.5g.nr_ulsim.misc.test13 "MCS 0, low SNR performance" nr_ulsim -n300 -m0 -S -0.6 -i 1,0) +add_physim_test(physim.5g.nr_ulsim.misc.test14 "MCS 28, 106 PRBs, Time shift 8" nr_ulsim -n300 -m28 -R106 -r106 -t90 -s24 -S24 -d 8) +add_physim_test(physim.5g.nr_ulsim.misc.test15 "SRS, SNR 40 dB" nr_ulsim -n300 -s40 -E 1) +add_physim_test(physim.5g.nr_ulsim.sc-fdma.test1 "SC-FDMA, 50 PRBs" nr_ulsim -n300 -s5 -Z) +add_physim_test(physim.5g.nr_ulsim.sc-fdma.test2 "SC-FDMA, 75 PRBs" nr_ulsim -n300 -s5 -Z -r75) +add_physim_test(physim.5g.nr_ulsim.sc-fdma.test3 "SC-FDMA, 216 PRBs" nr_ulsim -n150 -s5 -Z -r216 -R217) +add_physim_test(physim.5g.nr_ulsim.sc-fdma.test4 "SC-FDMA, 273 PRBs" nr_ulsim -n150 -s5 -Z -r270 -R273) +add_physim_test(physim.5g.nr_ulsim.sc-fdma.test5 "SC-FDMA, 3 DMRS" nr_ulsim -n300 -s5 -Z -U 0,2,1,2) +add_physim_test(physim.5g.nr_ulsim.mimo.test1 "MCS 19 50 PRBs 2 RX_Antenna" nr_ulsim -n300 -m19 -s10 -S15 -z2) +add_physim_test(physim.5g.nr_ulsim.mimo.test2 "MCS 9 106 PRBs MIMO 2 layers" nr_ulsim -n300 -m9 -r106 -s8 -W2 -y2 -z2) +add_physim_test(physim.5g.nr_ulsim.mimo.test3 "MCS 10 106 PRBs MIMO 2 layers" nr_ulsim -n300 -m10 -r106 -s12 -W2 -y2 -z2) +add_physim_test(physim.5g.nr_ulsim.mimo.test4 "MCS 19 106 PRBs MIMO 2 layers" nr_ulsim -n300 -m19 -r106 -s22 -W2 -y2 -z2) +add_physim_test(physim.5g.nr_ulsim.mimo.test5 "MCS 9 106 PRBs MIMO 4 layers" nr_ulsim -n300 -m9 -r106 -s10 -W4 -y4 -z4) +add_physim_test(physim.5g.nr_ulsim.3gpp.test1 "3GPP G-FR1-A5-13, PUSCH Type A, 40 MHz BW, 30 kHz SCS, 2 RX Antennas Requirements Test" nr_ulsim -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R106 -r106 -U 0,1,1,2 -z2 -s12.4 -S12.4) +add_physim_test(physim.5g.nr_ulsim.3gpp.test2 "3GPP G-FR1-A5-13, PUSCH Type A, 40 MHz BW, 30 kHz SCS, 4 RX Antennas Requirements Test" nr_ulsim -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R106 -r106 -U 0,1,1,2 -z4 -s8.5 -S8.5) +add_physim_test(physim.5g.nr_ulsim.3gpp.test3 "3GPP G-FR1-A5-13, PUSCH Type A, 40 MHz BW, 30 kHz SCS, 8 RX Antennas Requirements Test" nr_ulsim -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R106 -r106 -U 0,1,1,2 -z8 -s5.4 -S5.4) +add_physim_test(physim.5g.nr_ulsim.3gpp.test4 "3GPP G-FR1-A5-8, PUSCH Type B, 5 MHz BW, 15 kHz SCS, 2 RX Antennas Requirements Test" nr_ulsim -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 0 -m20 -R25 -r25 -U 1,1,1,2 -z2 -s12.5 -S12.5) +add_physim_test(physim.5g.nr_ulsim.3gpp.test5 "3GPP G-FR1-A5-8, PUSCH Type B, 5 MHz BW, 15 kHz SCS, 4 RX Antennas Requirements Test" nr_ulsim -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 0 -m20 -R25 -r25 -U 1,1,1,2 -z4 -s8.9 -S8.9) +add_physim_test(physim.5g.nr_ulsim.3gpp.test6 "3GPP G-FR1-A5-8, PUSCH Type B, 5 MHz BW, 15 kHz SCS, 8 RX Antennas Requirements Test" nr_ulsim -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 0 -m20 -R25 -r25 -U 1,1,1,2 -z8 -s5.7 -S5.7) +add_physim_test(physim.5g.nr_ulsim.3gpp.test7 "3GPP G-FR1-A5-9, PUSCH Type B, 10 MHz BW, 15 kHz SCS, 2 RX Antennas Requirements Test" nr_ulsim -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 0 -m20 -R52 -r52 -U 1,1,1,2 -z2 -s12.6 -S12.6) +add_physim_test(physim.5g.nr_ulsim.3gpp.test8 "3GPP G-FR1-A5-9, PUSCH Type B, 10 MHz BW, 15 kHz SCS, 4 RX Antennas Requirements Test" nr_ulsim -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 0 -m20 -R52 -r52 -U 1,1,1,2 -z4 -s8.9 -S8.9) +add_physim_test(physim.5g.nr_ulsim.3gpp.test9 "3GPP G-FR1-A5-9, PUSCH Type B, 10 MHz BW, 15 kHz SCS, 8 RX Antennas Requirements Test" nr_ulsim -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 0 -m20 -R52 -r52 -U 1,1,1,2 -z8 -s5.8 -S5.8) +add_physim_test(physim.5g.nr_ulsim.3gpp.test10 "3GPP G-FR1-A5-10, PUSCH Type B, 20 MHz BW, 15 kHz SCS, 2 RX Antennas Requirements Test" nr_ulsim -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 0 -m20 -R106 -r106 -U 1,1,1,2 -z2 -s12.3 -S12.3) +add_physim_test(physim.5g.nr_ulsim.3gpp.test11 "3GPP G-FR1-A5-10, PUSCH Type B, 20 MHz BW, 15 kHz SCS, 4 RX Antennas Requirements Test" nr_ulsim -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 0 -m20 -R106 -r106 -U 1,1,1,2 -z4 -s8.8 -S8.8) +add_physim_test(physim.5g.nr_ulsim.3gpp.test12 "3GPP G-FR1-A5-10, PUSCH Type B, 20 MHz BW, 15 kHz SCS, 8 RX Antennas Requirements Test" nr_ulsim -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 0 -m20 -R106 -r106 -U 1,1,1,2 -z8 -s5.7 -S5.7) +add_physim_test(physim.5g.nr_ulsim.3gpp.test13 "3GPP G-FR1-A5-11, PUSCH Type B, 10 MHz BW, 30 kHz SCS, 2 RX Antennas Requirements Test" nr_ulsim -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R24 -r24 -U 1,1,1,2 -z2 -s12.5 -S12.5) +add_physim_test(physim.5g.nr_ulsim.3gpp.test14 "3GPP G-FR1-A5-11, PUSCH Type B, 10 MHz BW, 30 kHz SCS, 4 RX Antennas Requirements Test" nr_ulsim -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R24 -r24 -U 1,1,1,2 -z4 -s8.6 -S8.6) +add_physim_test(physim.5g.nr_ulsim.3gpp.test15 "3GPP G-FR1-A5-11, PUSCH Type B, 10 MHz BW, 30 kHz SCS, 8 RX Antennas Requirements Test" nr_ulsim -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R24 -r24 -U 1,1,1,2 -z8 -s5.6 -S5.6) +add_physim_test(physim.5g.nr_ulsim.3gpp.test16 "3GPP G-FR1-A5-12, PUSCH Type B, 20 MHz BW, 30 kHz SCS, 2 RX Antennas Requirements Test" nr_ulsim -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R51 -r51 -U 1,1,1,2 -z2 -s12.5 -S12.5) +add_physim_test(physim.5g.nr_ulsim.3gpp.test17 "3GPP G-FR1-A5-12, PUSCH Type B, 20 MHz BW, 30 kHz SCS, 4 RX Antennas Requirements Test" nr_ulsim -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R51 -r51 -U 1,1,1,2 -z4 -s8.6 -S8.6) +add_physim_test(physim.5g.nr_ulsim.3gpp.test18 "3GPP G-FR1-A5-12, PUSCH Type B, 20 MHz BW, 30 kHz SCS, 8 RX Antennas Requirements Test" nr_ulsim -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R51 -r51 -U 1,1,1,2 -z8 -s5.6 -S5.6) +add_physim_test(physim.5g.nr_ulsim.3gpp.test19 "3GPP G-FR1-A5-13, PUSCH Type B, 40 MHz BW, 30 kHz SCS, 2 RX Antennas Requirements Test" nr_ulsim -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R106 -r106 -U 1,1,1,2 -z2 -s12.5 -S12.5) +add_physim_test(physim.5g.nr_ulsim.3gpp.test20 "3GPP G-FR1-A5-13, PUSCH Type B, 40 MHz BW, 30 kHz SCS, 4 RX Antennas Requirements Test" nr_ulsim -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R106 -r106 -U 1,1,1,2 -z4 -s8.7 -S8.7) +add_physim_test(physim.5g.nr_ulsim.3gpp.test21 "3GPP G-FR1-A5-13, PUSCH Type B, 40 MHz BW, 30 kHz SCS, 8 RX Antennas Requirements Test" nr_ulsim -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R106 -r106 -U 1,1,1,2 -z8 -s5.5 -S5.5) +add_physim_test(physim.5g.nr_ulsim.3gpp.test22 "3GPP G-FR1-A5-14, PUSCH Type B, 100 MHz BW, 30 kHz SCS, 2 RX Antennas Requirements Test" nr_ulsim -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R273 -r273 -U 1,1,1,2 -z2 -s13.1 -S13.1) +add_physim_test(physim.5g.nr_ulsim.3gpp.test23 "3GPP G-FR1-A5-14, PUSCH Type B, 100 MHz BW, 30 kHz SCS, 4 RX Antennas Requirements Test" nr_ulsim -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R273 -r273 -U 1,1,1,2 -z4 -s9.2 -S9.2) +add_physim_test(physim.5g.nr_ulsim.3gpp.test24 "3GPP G-FR1-A5-14, PUSCH Type B, 100 MHz BW, 30 kHz SCS, 8 RX Antennas Requirements Test" nr_ulsim -n300 -b14 -I8 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R273 -r273 -U 1,1,1,2 -z8 -s5.9 -S5.9) +add_physim_test(physim.5g.nr_ulsim.3gpp.test25 "3GPP G-FR1-A3-27, PUSCH Type B, 40 MHz BW, 30 kHz SCS, 2 RX Antennas Requirements Test, 2 layers" nr_ulsim -n300 -b14 -I15 -i 0,1 -g B,l -t70 -u 1 -m2 -R106 -r106 -U 1,1,1,2 -W2 -y2 -z2 -s1.7 -S1.7) +add_physim_test(physim.5g.nr_ulsim.3gpp.test26 "3GPP G-FR1-A3-27, PUSCH Type B, 40 MHz BW, 30 kHz SCS, 4 RX Antennas Requirements Test, 2 layers" nr_ulsim -n300 -b14 -I15 -i 0,1 -g B,l -t70 -u 1 -m2 -R106 -r106 -U 1,1,1,2 -W2 -y2 -z4 -s-2.1 -S-2.1) +add_physim_test(physim.5g.nr_ulsim.3gpp.test27 "3GPP G-FR1-A4-27, PUSCH Type B, 40 MHz BW, 30 kHz SCS, 2 RX Antennas Requirements Test, 2 layers" nr_ulsim -n300 -b14 -I15 -i 0,1 -g C,l -t70 -u 1 -m16 -R106 -r106 -U 1,1,1,2 -W2 -y2 -z2 -s18.7 -S18.7) +add_physim_test(physim.5g.nr_ulsim.3gpp.test28 "3GPP G-FR1-A4-27, PUSCH Type B, 40 MHz BW, 30 kHz SCS, 4 RX Antennas Requirements Test, 2 layers" nr_ulsim -n300 -b14 -I15 -i 0,1 -g C,l -t70 -u 1 -m16 -R106 -r106 -U 1,1,1,2 -W2 -y2 -z4 -s11.2 -S11.2) #################################################################################### ###### nr_prachsim unit test ###### #################################################################################### -add_physim_test(5g nr_prachsim test1 "30kHz SCS, 106 PRBs, Prach format A2" -a -s -30 -n 300 -p 63 -R 106) -add_physim_test(5g nr_prachsim test2 "30kHz SCS, 217 PRBs, Prach format A2" -a -s -30 -n 300 -p 63 -R 217) -add_physim_test(5g nr_prachsim test3 "30kHz SCS, 273 PRBs, Prach format A2" -a -s -30 -n 300 -p 63 -R 273) -add_physim_test(5g nr_prachsim test4 "30kHz SCS, 106 PRBs, Prach format 0" -a -s -30 -n 300 -p 63 -R 106 -c 4) -add_physim_test(5g nr_prachsim test5 "120kHz SCS, 32 PRBs, Prach format A2" -a -s -30 -n 300 -p 32 -R 32 -m 3 -c52) -add_physim_test(5g nr_prachsim test6 "120kHz SCS, 66 PRBs, Prach format A2" -a -s -30 -n 300 -p 32 -R 66 -m 3 -c52) -add_physim_test(5g nr_prachsim test7 "120kHz SCS, 66 PRBs, High Speed Enabled" -a -s -30 -n 300 -R 66 -m 3 -c52 -H) -add_physim_test(5g nr_prachsim test8 "15kHz SCS, 25 PRBs" -a -s -30 -n 300 -p 99 -R 25 -m 0) +add_physim_test(physim.5g.nr_prachsim.test1 "30kHz SCS, 106 PRBs, Prach format A2" nr_prachsim -a -s -30 -n 300 -p 63 -R 106) +add_physim_test(physim.5g.nr_prachsim.test2 "30kHz SCS, 217 PRBs, Prach format A2" nr_prachsim -a -s -30 -n 300 -p 63 -R 217) +add_physim_test(physim.5g.nr_prachsim.test3 "30kHz SCS, 273 PRBs, Prach format A2" nr_prachsim -a -s -30 -n 300 -p 63 -R 273) +add_physim_test(physim.5g.nr_prachsim.test4 "30kHz SCS, 106 PRBs, Prach format 0" nr_prachsim -a -s -30 -n 300 -p 63 -R 106 -c 4) +add_physim_test(physim.5g.nr_prachsim.test5 "120kHz SCS, 32 PRBs, Prach format A2" nr_prachsim -a -s -30 -n 300 -p 32 -R 32 -m 3 -c52) +add_physim_test(physim.5g.nr_prachsim.test6 "120kHz SCS, 66 PRBs, Prach format A2" nr_prachsim -a -s -30 -n 300 -p 32 -R 66 -m 3 -c52) +add_physim_test(physim.5g.nr_prachsim.test7 "120kHz SCS, 66 PRBs, High Speed Enabled" nr_prachsim -a -s -30 -n 300 -R 66 -m 3 -c52 -H) +add_physim_test(physim.5g.nr_prachsim.test8 "15kHz SCS, 25 PRBs" nr_prachsim -a -s -30 -n 300 -p 99 -R 25 -m 0) #################################################################################### ###### nr_psbchsim unit test ###### #################################################################################### -add_physim_test(5g nr_psbchsim test1 "SLSS Search" -I) -add_physim_test(5g nr_psbchsim test2 "PSBCH TxRx" -n 30) +add_physim_test(physim.5g.nr_psbchsim.test1 "SLSS Search" nr_psbchsim -I) +add_physim_test(physim.5g.nr_psbchsim.test2 "PSBCH TxRx" nr_psbchsim -n 30) From 48be94a8c1f8ce9ac8d7597a74f3586f9edd6fb1 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 26 Aug 2025 09:17:50 +0200 Subject: [PATCH 670/964] Remove LDPC GPU physim tests Many of these tests do not pass (ldpctest returns non-zero output). Moving to ctest would make all these tests and hence the pipeline fail. --- ci-scripts/xml_files/ldpc_gpu_test.xml | 396 ------------------------- 1 file changed, 396 deletions(-) delete mode 100644 ci-scripts/xml_files/ldpc_gpu_test.xml diff --git a/ci-scripts/xml_files/ldpc_gpu_test.xml b/ci-scripts/xml_files/ldpc_gpu_test.xml deleted file mode 100644 index 00ccbe3da1..0000000000 --- a/ci-scripts/xml_files/ldpc_gpu_test.xml +++ /dev/null @@ -1,396 +0,0 @@ - - - test-ldpc-gpu - Test-ldpc-GPU - tasks - - 000002 000003 000004 000005 000006 000007 000008 000009 000010 000011 000012 000013 000014 000015 000016 000017 000018 000019 000020 000021 - 000022 000023 000024 000025 000026 000027 000028 000029 000030 000031 000032 000033 000034 000035 000036 000037 000038 000039 000040 000041 - - - - - Run_Physim - Run LDPC Test with CPU - true - caracal - ldpctest - -l 3872 -s10 -n100 - - - - Run_Physim - Run LDPC Test with GPU - true - caracal - ldpctest - -l 3872 -s10 -n100 -G 1 - - - - Run_Physim - Run LDPC Test with CPU - true - caracal - ldpctest - -l 4224 -s10 -n100 - - - - Run_Physim - Run LDPC Test with GPU - true - caracal - ldpctest - -l 4224 -s10 -n100 -G 1 - - - - Run_Physim - Run LDPC Test with CPU - true - caracal - ldpctest - -l 4576 -s10 -n100 - - - - Run_Physim - Run LDPC Test with GPU - true - caracal - ldpctest - -l 4576 -s10 -n100 -G 1 - - - - Run_Physim - Run LDPC Test with CPU - true - caracal - ldpctest - -l 4928 -s10 -n100 - - - - Run_Physim - Run LDPC Test with GPU - true - caracal - ldpctest - -l 4928 -s10 -n100 -G 1 - - - - Run_Physim - Run LDPC Test with CPU - true - caracal - ldpctest - -l 5280 -s10 -n100 - - - - Run_Physim - Run LDPC Test with GPU - true - caracal - ldpctest - -l 5280 -s10 -n100 -G 1 - - - - Run_Physim - Run LDPC Test with CPU - true - caracal - ldpctest - -l 5632 -s10 -n100 - - - - Run_Physim - Run LDPC Test with GPU - true - caracal - ldpctest - -l 5632 -s10 -n100 -G 1 - - - - Run_Physim - Run LDPC Test with CPU - true - caracal - ldpctest - -l 6336 -s10 -n100 - - - - Run_Physim - Run LDPC Test with GPU - true - caracal - ldpctest - -l 6336 -s10 -n100 -G 1 - - - - Run_Physim - Run LDPC Test with CPU - true - caracal - ldpctest - -l 7040 -s10 -n100 - - - - Run_Physim - Run LDPC Test with GPU - true - caracal - ldpctest - -l 7040 -s10 -n100 -G 1 - - - - Run_Physim - Run LDPC Test with CPU - true - caracal - ldpctest - -l 7744 -s10 -n100 - - - - Run_Physim - Run LDPC Test with GPU - true - caracal - ldpctest - -l 7744 -s10 -n100 -G 1 - - - - Run_Physim - Run LDPC Test with CPU - true - caracal - ldpctest - -l 8448 -s10 -n100 - - - - Run_Physim - Run LDPC Test with GPU - true - caracal - ldpctest - -l 8448 -s10 -n100 -G 1 - - - - Run_Physim - Run LDPC Test with CPU - true - caracal - ldpctest - -l 1 -s10 -n100 - - - - Run_Physim - Run LDPC Test with GPU - true - caracal - ldpctest - -l 1 -s10 -n100 -G 1 - - - - Run_Physim - Run LDPC Test with CPU - true - caracal - ldpctest - -l 100 -s10 -n100 - - - - Run_Physim - Run LDPC Test with GPU - true - caracal - ldpctest - -l 100 -s10 -n100 -G 1 - - - - Run_Physim - Run LDPC Test with CPU - true - caracal - ldpctest - -l 193 -s10 -n100 - - - - Run_Physim - Run LDPC Test with GPU - true - caracal - ldpctest - -l 193 -s10 -n100 -G 1 - - - - Run_Physim - Run LDPC Test with CPU - true - caracal - ldpctest - -l 500 -s10 -n100 - - - - Run_Physim - Run LDPC Test with GPU - true - caracal - ldpctest - -l 500 -s10 -n100 -G 1 - - - - Run_Physim - Run LDPC Test with CPU - true - caracal - ldpctest - -l 561 -s10 -n100 - - - - Run_Physim - Run LDPC Test with GPU - true - caracal - ldpctest - -l 561 -s10 -n100 -G 1 - - - - Run_Physim - Run LDPC Test with CPU - true - caracal - ldpctest - -l 600 -s10 -n100 - - - - Run_Physim - Run LDPC Test with GPU - true - caracal - ldpctest - -l 600 -s10 -n100 -G 1 - - - - Run_Physim - Run LDPC Test with CPU - true - caracal - ldpctest - -l 641 -s10 -n100 - - - - Run_Physim - Run LDPC Test with GPU - true - caracal - ldpctest - -l 641 -s10 -n100 -G 1 - - - - Run_Physim - Run LDPC Test with CPU - true - caracal - ldpctest - -l 2000 -s10 -n100 - - - - Run_Physim - Run LDPC Test with GPU - true - caracal - ldpctest - -l 2000 -s10 -n100 -G 1 - - - - Run_Physim - Run LDPC Test with CPU - true - caracal - ldpctest - -l 3000 -s10 -n100 - - - - Run_Physim - Run LDPC Test with GPU - true - caracal - ldpctest - -l 3000 -s10 -n100 -G 1 - - - - Run_Physim - Run LDPC Test with CPU - true - caracal - ldpctest - -l 3840 -s10 -n100 - - - - Run_Physim - Run LDPC Test with GPU - true - caracal - ldpctest - -l 3840 -s10 -n100 -G 1 - - - - - From 55cebe6edf6d566cf335982730348400df6dbaa3 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sat, 6 Sep 2025 15:07:23 +0200 Subject: [PATCH 671/964] Provide add_timed_physim_test() in cmake Add two new macros that allow to register physim tests for ctest, including timing thresholds that should be fulfilled. First, add_timed_physim_test() registers a new test using a helper script RunTimedTest.cmake. This is because after test execution, we need to analyze logs, and the recommended way to do multiple steps in one test is via a helper cmake script: https://cmake.org/pipermail/cmake-developers/2016-February/027816.html Second, check_physim_threshold() adds new thresholds. It takes a text to be parsed, and a condition (e.g., "< 20") to check for the number following the threshold (which is assumed to be present right after the threshold). It uses a test property to count the total number of checks (limiting them to 10), and sets environment variables for the script. I initially planned to use a test property for checks, but those are only valid in the same directory, and RunTimedTest.cmake seems to be assumed by cmake to be "elsewhere", hence I needed to resort to environment variables. RunTimedTest.cmake is called through cmake with the test parameters and checks. It re-constructs a list of checks [1], runs the test, and pipes the log into a separate script that is passed all checks (see below). Afterwards, it verifies that both the test and script passed. A script analyze-timing.sh builds an awk script from the checks passed. The script analyzes each line of the test output for the threshold, and compares against the threshold. analyze-timing.sh returns success if all checks passed. [1] I did not manage to pass a "list" of checks in a single environment variable through the check_physim_threshold(), which would be simpler. --- doc/physical-simulators.md | 38 ++++++++++ openair1/SIMULATION/tests/CMakeLists.txt | 72 ++++++++++++++++++ openair1/SIMULATION/tests/RunTimedTest.cmake | 41 ++++++++++ openair1/SIMULATION/tests/analyze-timing.sh | 78 ++++++++++++++++++++ 4 files changed, 229 insertions(+) create mode 100644 openair1/SIMULATION/tests/RunTimedTest.cmake create mode 100755 openair1/SIMULATION/tests/analyze-timing.sh diff --git a/doc/physical-simulators.md b/doc/physical-simulators.md index dab457d38f..cd573a8686 100644 --- a/doc/physical-simulators.md +++ b/doc/physical-simulators.md @@ -103,6 +103,7 @@ To define a new test or modify existing ones, update the following file: openair1/SIMULATION/tests/CMakeLists.txt ``` +## `add_physim_test()` Use the `add_physim_test()` macro with the following arguments: @@ -123,6 +124,43 @@ For instance, a PRACHsim looks like this: These tests are run automatically as part of the following pipelines: [RAN-PhySim-Cluster-4G](https://jenkins-oai.eurecom.fr/job/RAN-PhySim-Cluster-4G/) and [RAN-PhySim-Cluster-5G](https://jenkins-oai.eurecom.fr/job/RAN-PhySim-Cluster-5G/) +## `add_timed_physim_test()` + +Use the `add_timed_physim_test()` macro to add a test the same way as with +`add_physim_test()` above. Additionally, it allows to check for thresholds with +`check_threshold()`: + + check_threshold( ) + +where: +- `` is any test that must have been added with + `add_timed_physim_test()` +- `` is a threshold to check for, e.g., `PHY tx proc`, and +- `` a condition to check, e.g. `< 200` + +There are two convenience functions to simplify the use of `check_threshold()`: + + check_threshold_range( LOWER UPPER ) + check_threshold_variance( AVG ABS_VAR ) + +where +- `` and `` are a lower and upper threshold, respectively, where + either one or both variables can be provided, and +- `` and `` are average and the variation in absolute numbers + (not a percentage!) can be provided. + +Both functions internally use `check_threshold()`. + +Thus upon execution of the test, the test will be run, but additionally ctest +will check for a match of `PHY tx proc ` (where ` is of format +`[0-9]+(\.[0-9]+)?`), and a matching number will be checked against condition +`< 200`. + +For instance, this could look like this: + + add_timed_physim_test(physim.5g.nr_dlsim.test3 "Some description" nr_dlsim -P) + check_physim_threshold(physim.5g.nr_dlsim.test3 "DLSCH encoding time" "< 50") + ### How to rerun failed CI tests using `ctest` Ctest automatically logs the failed tests in LastTestsFailed.log. This log is archived in diff --git a/openair1/SIMULATION/tests/CMakeLists.txt b/openair1/SIMULATION/tests/CMakeLists.txt index 4d57ada955..a7532e142d 100644 --- a/openair1/SIMULATION/tests/CMakeLists.txt +++ b/openair1/SIMULATION/tests/CMakeLists.txt @@ -17,6 +17,78 @@ macro(add_physim_test test_name test_description test_exec) add_dependencies(tests ${test_exec}) endmacro() +define_property(TEST PROPERTY CHECK_COUNT BRIEF_DOCS "helper property to enumerate checks in environment") +function(add_timed_physim_test test_name test_description test_exec) + # catch all the arguments past the last expected arqument and store them in the options_list + if (NOT TARGET ${test_exec}) + message(FATAL_ERROR "test executable ${test_exec} is not an executable") + endif() + set(test_invocation $ ${ARGN}) + add_test( + NAME ${test_name} + COMMAND ${CMAKE_COMMAND} "-DTEST_CMD=${test_invocation}" "-DCHECK_SCRIPT=${CMAKE_CURRENT_SOURCE_DIR}/analyze-timing.sh" -P ${CMAKE_CURRENT_SOURCE_DIR}/RunTimedTest.cmake + ) + set_tests_properties(${test_name} PROPERTIES + LABELS "${test_exec}" + TEST_DESCRIPTION "${test_description}" + # pass test description also through environment variable: for cmake < 3.30, + # in JSON export, we cannot recover the description otherwise + # see also https://gitlab.kitware.com/cmake/cmake/-/issues/21490 + ENVIRONMENT "LD_LIBRARY_PATH=.;TEST_DESCRIPTION=${test_description}" + ) + set_tests_properties(${test_name} PROPERTIES CHECK_COUNT 0) +endfunction() + +function(check_threshold testname threshold condition) + # check that threshold and condition don't have a colon (;), because that + # would interfere with cmake's list management + string(FIND "${threshold}" ";" pos) + if (pos GREATER -1) + message(FATAL_ERROR "colon not allowed in threshold, but have \"${threshold}\"") + endif() + string(FIND "${condition}" ";" pos) + if (pos GREATER -1) + message(FATAL_ERROR "colon not allowed in condition, but have \"${condition}\"") + endif() + set(THRCOND "${threshold}\;${condition}") + + get_test_property(${testname} CHECK_COUNT count) + #message(STATUS "add check ${count} ${THRCOND}") + if (${count} GREATER 10) + message(FATAL_ERROR "only maximum of 10 checks per test allowed") + endif() + + # add a new environment variable CHECK_X with this threshold+condition, then + # increase test property regarding check count + set_property(TEST ${testname} APPEND PROPERTY ENVIRONMENT "CHECK_${count}=${THRCOND}") + MATH(EXPR count "${count}+1") + set_tests_properties(${testname} PROPERTIES CHECK_COUNT ${count}) +endfunction() + +function(check_threshold_range testname threshold) + cmake_parse_arguments(RANGE "" "LOWER;UPPER" "" ${ARGN}) + if (NOT RANGE_LOWER AND NOT RANGE_UPPER) + message(FATAL_ERROR "need at least one LOWER or one UPPER threshold") + endif() + if (RANGE_LOWER) + check_threshold(${testname} ${threshold} "> ${RANGE_LOWER}") + endif() + if (RANGE_UPPER) + check_threshold(${testname} ${threshold} "< ${RANGE_UPPER}") + endif() +endfunction() + +function(check_threshold_variance testname threshold) + cmake_parse_arguments(VARIANCE "" "AVG;ABS_VAR" "" ${ARGN}) + if (NOT VARIANCE_AVG AND NOT VARIANCE_ABS_VAR) + message(FATAL_ERROR "need both AVG and ABS_VAR") + endif() + MATH(EXPR upper "${VARIANCE_AVG}+${VARIANCE_ABS_VAR}") + MATH(EXPR lower "${VARIANCE_AVG}-${VARIANCE_ABS_VAR}") + check_threshold_range(${testname} ${threshold} LOWER ${lower} UPPER ${upper}) +endfunction() + + #################################################################################### ###### dlsim unit test ###### #################################################################################### diff --git a/openair1/SIMULATION/tests/RunTimedTest.cmake b/openair1/SIMULATION/tests/RunTimedTest.cmake new file mode 100644 index 0000000000..779d781bec --- /dev/null +++ b/openair1/SIMULATION/tests/RunTimedTest.cmake @@ -0,0 +1,41 @@ +# this script expects +# - TEST_CMD (program + options) +# - CHECK_SCRIPT (path to analyze-timing.sh) +# further, it analyzes the (test-specific) environment for CHECK_0, CHECK_1, +# etc. to construct the input to the check script. + +# the calling process writes env vars CHECK_0, CHECK_1, ... +# each has "condition;threshold" as it's content +# combine all necessary CHECK0, CHECK1, ... into a single array CHECKS +# to be passed to the check script +foreach(count RANGE 9) + set(CHECK "CHECK_${count}") + if (NOT DEFINED ENV{${CHECK}}) + break() + endif() + list(APPEND CHECKS "$ENV{${CHECK}}") +endforeach() + +# execute the actual test command TEST_CMD and pipe its output into the +# check script. Afterwards, check both commands return codes. +execute_process(COMMAND ${TEST_CMD} + COMMAND ${CHECK_SCRIPT} ${CHECKS} + COMMAND_ECHO STDOUT + RESULTS_VARIABLE RET_CODES +) +list(LENGTH RET_CODES LEN_RET_CODES) +if(NOT LEN_RET_CODES EQUAL 2) + message(SEND_ERROR "execute_process() did not run both commands!") +endif() + +list(GET RET_CODES 0 TEST_RET_CODE) +message(STATUS "test command finished with ${TEST_RET_CODE}") +if(NOT ${TEST_RET_CODE} MATCHES "0") + message(SEND_ERROR " => test failed!") +endif() + +list(GET RET_CODES 1 CHECK_RET_CODE) +message(STATUS "check command finished with ${CHECK_RET_CODE}") +if(NOT ${CHECK_RET_CODE} MATCHES "0") + message(SEND_ERROR " => check failed!") +endif() diff --git a/openair1/SIMULATION/tests/analyze-timing.sh b/openair1/SIMULATION/tests/analyze-timing.sh new file mode 100755 index 0000000000..2ca45f346f --- /dev/null +++ b/openair1/SIMULATION/tests/analyze-timing.sh @@ -0,0 +1,78 @@ +#!/bin/bash + +# This bash script builds an awk script. The awk script tries to match +# (provided) patterns and compares them against given thresholds condition +# (e.g., threshold is "< 10"). + +function die() { echo $@ 1>&2; exit 1; } + +# RC will be the return code. If any rule fails, it will set RC=1, which will +# make the script fail. Print also every line, because the logs are piped into +# this script, but a user is typically also interested into the raw logs. +SCRIPT=' + BEGIN { RC = 0; } + + { print $0 } +' + +NUM=0 +# for each pair of /, add corresponding rules. +while [ $# -gt 0 ]; do + [ $# -ne 1 ] || die "unmatched /" + PATTERN=${1} + COND=${2} + shift 2 + + # Add a rule that searches for a PATTERN + number, and checks against + # CONDition. If the condition does not hold, it is counted as a failure (sets + # RC to signal error). In both cases, the result is logged in an array to + # output at the end of the script. + # + # Example: pattern "PHY proc tx", condition "< 200" + # The awk script tries to match every line for "PHY proc tx _NUMBER_" (where + # number is a decimal), and compares _NUMBER_ against condition "< 200", + # i.e., "_NUMBER_ < 200". + # If the condition holds, will set "CHECK PHY proc tx _NUMBER_ < 200 SUCCESS". + # If the condition fails, will set "CHECK PHY proc tx _NUMBER_ < 200 FAIL". + SCRIPT+=' + match($0, /'${PATTERN}' +([0-9]+(\.[0-9]+)?)/, n) { + if (n[1] '${COND}') { + r = "SUCCESS"; + } else { + r = "FAIL"; + RC = 1; + } + RESULTS['${NUM}']=sprintf("CHECK %-35s %7.2f %-8s %s", "'${PATTERN}'", n[1], " '${COND}'", r); + } +' + + # Generate an additional rule for the end of the logs: if the pattern is not + # found, it is counted as a failure and logged appropriately. + # Following the above example "PHY proc tx" and "< 200": if such log is not + # found, will set "CHECK PHY proc tx < 200 NOTFOUND" + SCRIPT+=' + END { + if (!RESULTS['${NUM}']) { + RESULTS['${NUM}']=sprintf("CHECK %-35s %-7s NOTFOUND", "'${PATTERN}'", "'${COND}'"); + RC = 1; + } + } +' + + let NUM=${NUM}+1 +done + +# After passing through all logs, print all results, and exit with return code +# (0 on success, i.e..all conditions checked, otherwise 1 on failure). +SCRIPT+=' + END { + for (i = 0; i < '${NUM}'; ++i) { + print RESULTS[i] + } + exit RC + } +' + +# Read from separate file descriptor 3: this allows us to pipe the actual log +# to analyze into awk (by using the script like so: analyze-timing.sh < log) +awk -f /dev/fd/3 3<<< ${SCRIPT} From a7f0a1a20c98121192ea0ae446070a3d257efba8 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 26 Aug 2025 09:07:41 +0200 Subject: [PATCH 672/964] Import Offload unit tests into CTest The unit tests have been imported with this command: xmlstarlet sel -t -m '//testCaseList/testCase[class="Run_Physim"]' \ -v "concat('add_timed_physim_test(physim.5g-offload.',physim_test,'.testX.Y \"',desc,'\" ',physim_test,' ',physim_run_args,')')" \ -n t2_offload_enc_nr_dlsim.xml t2_offload_dec_nr_ulsim.xml >> ../../openair1/SIMULATION/tests/CMakeLists.txt The next commit will further cleanup this output. I commit it like this for verification purposes. --- openair1/SIMULATION/tests/CMakeLists.txt | 51 ++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/openair1/SIMULATION/tests/CMakeLists.txt b/openair1/SIMULATION/tests/CMakeLists.txt index a7532e142d..3f940313bb 100644 --- a/openair1/SIMULATION/tests/CMakeLists.txt +++ b/openair1/SIMULATION/tests/CMakeLists.txt @@ -337,3 +337,54 @@ add_physim_test(physim.5g.nr_prachsim.test8 "15kHz SCS, 25 PRBs" nr_prachsim -a add_physim_test(physim.5g.nr_psbchsim.test1 "SLSS Search" nr_psbchsim -I) add_physim_test(physim.5g.nr_psbchsim.test2 "PSBCH TxRx" nr_psbchsim -n 30) + +#################################################################################### +###### offload-specific tests ###### +#################################################################################### + +if (ENABLE_LDPC_AAL) + +add_timed_physim_test(physim.5g-offload.nr_dlsim.testX.Y "Run nr_dlsim with CPU: SNR = 30, MCS = 5, 106 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e5 -b106 -R106 -X 8,9,10,11,12 -P) +add_timed_physim_test(physim.5g-offload.nr_dlsim.testX.Y "Run nr_dlsim with T2 LDPC offload: SNR = 30, MCS = 5, 106 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e5 -b106 -R106 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_timed_physim_test(physim.5g-offload.nr_dlsim.testX.Y "Run nr_dlsim with CPU: SNR = 30, MCS = 15, 106 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e15 -b106 -R106 -X 8,9,10,11,12 -P) +add_timed_physim_test(physim.5g-offload.nr_dlsim.testX.Y "Run nr_dlsim with T2 LDPC offload: SNR = 30, MCS = 15, 106 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e15 -b106 -R106 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_timed_physim_test(physim.5g-offload.nr_dlsim.testX.Y "Run nr_dlsim with CPU: SNR = 30, MCS = 25, 106 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e25 -b106 -R106 -X 8,9,10,11,12 -P) +add_timed_physim_test(physim.5g-offload.nr_dlsim.testX.Y "Run nr_dlsim with T2 LDPC offload: SNR = 30, MCS = 25, 106 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e25 -b106 -R106 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_timed_physim_test(physim.5g-offload.nr_dlsim.testX.Y "Run nr_dlsim with CPU: SNR = 30, MCS = 5, 273 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e5 -b273 -R273 -X 8,9,10,11,12 -P) +add_timed_physim_test(physim.5g-offload.nr_dlsim.testX.Y "Run nr_dlsim with T2 LDPC offload: SNR = 30, MCS = 5, 273 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e5 -b273 -R273 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_timed_physim_test(physim.5g-offload.nr_dlsim.testX.Y "Run nr_dlsim with CPU: SNR = 30, MCS = 15, 273 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e15 -b273 -R273 -X 8,9,10,11,12 -P) +add_timed_physim_test(physim.5g-offload.nr_dlsim.testX.Y "Run nr_dlsim with T2 LDPC offload: SNR = 30, MCS = 15, 273 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e15 -b273 -R273 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_timed_physim_test(physim.5g-offload.nr_dlsim.testX.Y "Run nr_dlsim with CPU: SNR = 30, MCS = 25, 273 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e25 -b273 -R273 -X 8,9,10,11,12 -P) +add_timed_physim_test(physim.5g-offload.nr_dlsim.testX.Y "Run nr_dlsim with T2 LDPC offload: SNR = 30, MCS = 25, 273 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e25 -b273 -R273 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_timed_physim_test(physim.5g-offload.nr_dlsim.testX.Y "Run nr_dlsim with CPU: SNR = 30, MCS = 5, 273 PRBs, 2 layers" nr_dlsim -n1000 -s30 -S30.2 -e5 -b273 -R273 -X 8,9,10,11,12 -x2 -z2 -y2 -P) +add_timed_physim_test(physim.5g-offload.nr_dlsim.testX.Y "Run nr_dlsim with T2 LDPC offload: SNR = 30, MCS = 5, 273 PRBs, 2 layers" nr_dlsim -n1000 -s30 -S30.2 -e5 -b273 -R273 -X4,5,6,7,8,9 -x2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_timed_physim_test(physim.5g-offload.nr_dlsim.testX.Y "Run nr_dlsim with CPU: SNR = 30, MCS = 15, 273 PRBs, 2 layers" nr_dlsim -n1000 -s30 -S30.2 -e15 -b273 -R273 -X 8,9,10,11,12 -x2 -z2 -y2 -P) +add_timed_physim_test(physim.5g-offload.nr_dlsim.testX.Y "Run nr_dlsim with T2 LDPC offload: SNR = 30, MCS = 15, 273 PRBs, 2 layers" nr_dlsim -n1000 -s30 -S30.2 -e15 -b273 -R273 -X4,5,6,7,8,9 -x2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_timed_physim_test(physim.5g-offload.nr_dlsim.testX.Y "Run nr_dlsim with CPU: SNR = 30, MCS = 25, 273 PRBs, 2 layers" nr_dlsim -n1000 -s30 -S30.2 -e25 -b273 -R273 -X 8,9,10,11,12 -x2 -z2 -y2 -P) +add_timed_physim_test(physim.5g-offload.nr_dlsim.testX.Y "Run nr_dlsim with T2 LDPC offload: SNR = 30, MCS = 25, 273 PRBs, 2 layers" nr_dlsim -n1000 -s30 -S30.2 -e25 -b273 -R273 -X4,5,6,7,8,9 -x2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_timed_physim_test(physim.5g-offload.nr_dlsim.testX.Y "Run nr_dlsim with CPU: SNR = 30, MCS = 5, 273 PRBs, 2 layers, 4 antennas" nr_dlsim -n1000 -s30 -S30.2 -e5 -b273 -R273 -X8,9,10,11,12 -x2 -z4 -y4 -P) +add_timed_physim_test(physim.5g-offload.nr_dlsim.testX.Y "Run nr_dlsim with T2 LDPC offload: SNR = 30, MCS = 5, 273 PRBs, 2 layers, 4 antennas" nr_dlsim -n1000 -s30 -S30.2 -e5 -b273 -R273 -X4,5,6,7,8,9 -x2 -z4 -y4 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_timed_physim_test(physim.5g-offload.nr_dlsim.testX.Y "Run nr_dlsim with CPU: SNR = 30, MCS = 20, 273 PRBs, 2 layers, 4 antennas" nr_dlsim -n1000 -s30 -S30.2 -e15 -b273 -R273 -X8,9,10,11,12 -x2 -z4 -y4 -P) +add_timed_physim_test(physim.5g-offload.nr_dlsim.testX.Y "Run nr_dlsim with T2 LDPC offload: SNR = 30, MCS = 20, 273 PRBs, 2 layers, 4 antennas" nr_dlsim -n1000 -s30 -S30.2 -e15 -b273 -R273 -X4,5,6,7,8,9 -x2 -z4 -y4 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_timed_physim_test(physim.5g-offload.nr_dlsim.testX.Y "Run nr_dlsim with CPU: SNR = 30, MCS = 27, 273 PRBs, 2 layers, 4 antennas" nr_dlsim -n1000 -s30 -S30.2 -e25 -b273 -R273 -X8,9,10,11,12 -x2 -z4 -y4 -P) +add_timed_physim_test(physim.5g-offload.nr_dlsim.testX.Y "Run nr_dlsim with T2 LDPC offload: SNR = 30, MCS = 27, 273 PRBs, 2 layers, 4 antennas" nr_dlsim -n1000 -s30 -S30.2 -e25 -b273 -R273 -X4,5,6,7,8,9 -x2 -z4 -y4 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_timed_physim_test(physim.5g-offload.nr_ulsim.testX.Y "Run nr_ulsim with CPU: SNR = 30, MCS = 5, 106 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m5 -r106 -R106 -C10 -P) +add_timed_physim_test(physim.5g-offload.nr_ulsim.testX.Y "Run nr_ulsim with T2 LDPC offload: SNR = 30, MCS = 5, 106 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m5 -r106 -R106 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_timed_physim_test(physim.5g-offload.nr_ulsim.testX.Y "Run nr_ulsim with CPU: SNR = 30, MCS = 15, 106 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m15 -r106 -R106 -C10 -P) +add_timed_physim_test(physim.5g-offload.nr_ulsim.testX.Y "Run nr_ulsim with T2 LDPC offload: SNR = 30, MCS = 15, 106 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m15 -r106 -R106 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_timed_physim_test(physim.5g-offload.nr_ulsim.testX.Y "Run nr_ulsim with CPU: SNR = 30, MCS = 25, 106 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m25 -r106 -R106 -C10 -P) +add_timed_physim_test(physim.5g-offload.nr_ulsim.testX.Y "Run nr_ulsim with T2 LDPC offload: SNR = 30, MCS = 25, 106 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m25 -r106 -R106 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_timed_physim_test(physim.5g-offload.nr_ulsim.testX.Y "Run nr_ulsim with CPU: SNR = 30, MCS = 5, 273 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m5 -r273 -R273 -C10 -P) +add_timed_physim_test(physim.5g-offload.nr_ulsim.testX.Y "Run nr_ulsim with T2 LDPC offload: SNR = 30, MCS = 5, 273 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m5 -r273 -R273 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_timed_physim_test(physim.5g-offload.nr_ulsim.testX.Y "Run nr_ulsim with CPU: SNR = 30, MCS = 15, 273 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m15 -r273 -R273 -C10 -P) +add_timed_physim_test(physim.5g-offload.nr_ulsim.testX.Y "Run nr_ulsim with T2 LDPC offload: SNR = 30, MCS = 15, 273 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m15 -r273 -R273 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_timed_physim_test(physim.5g-offload.nr_ulsim.testX.Y "Run nr_ulsim with CPU: SNR = 30, MCS = 25, 273 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m25 -r273 -R273 -C10 -P) +add_timed_physim_test(physim.5g-offload.nr_ulsim.testX.Y "Run nr_ulsim with T2 LDPC offload: SNR = 30, MCS = 25, 273 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m25 -r273 -R273 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_timed_physim_test(physim.5g-offload.nr_ulsim.testX.Y "Run nr_ulsim with CPU: SNR = 30, MCS = 5, 273 PRBs, 2 layers" nr_ulsim -n1000 -s30 -S30.2 -m5 -r273 -R273 -C10 -W2 -z2 -y2 -P) +add_timed_physim_test(physim.5g-offload.nr_ulsim.testX.Y "Run nr_ulsim with T2 LDPC offload: SNR = 30, MCS = 5, 273 PRBs, 2 layers" nr_ulsim -n1000 -s30 -S30.2 -m5 -r273 -R273 -C10 -W2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_timed_physim_test(physim.5g-offload.nr_ulsim.testX.Y "Run nr_ulsim with CPU: SNR = 30, MCS = 15, 273 PRBs, 2 layers" nr_ulsim -n1000 -s30 -S30.2 -m15 -r273 -R273 -C10 -W2 -z2 -y2 -P) +add_timed_physim_test(physim.5g-offload.nr_ulsim.testX.Y "Run nr_ulsim with T2 LDPC offload: SNR = 30, MCS = 15, 273 PRBs, 2 layers" nr_ulsim -n1000 -s30 -S30.2 -m15 -r273 -R273 -C10 -W2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_timed_physim_test(physim.5g-offload.nr_ulsim.testX.Y "Run nr_ulsim with CPU: SNR = 30, MCS = 25, 273 PRBs, 2 layers" nr_ulsim -n1000 -s30 -S30.2 -m25 -r273 -R273 -C10 -W2 -z2 -y2 -P) +add_timed_physim_test(physim.5g-offload.nr_ulsim.testX.Y "Run nr_ulsim with T2 LDPC offload: SNR = 30, MCS = 25, 273 PRBs, 2 layers" nr_ulsim -n1000 -s30 -S30.2 -m25 -r273 -R273 -C10 -W2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) + +endif() From 9528ccceb908a981594af001d89214c434c72edf Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 8 Sep 2025 15:23:59 +0200 Subject: [PATCH 673/964] Clean up output of xmlstarlet command --- openair1/SIMULATION/tests/CMakeLists.txt | 85 ++++++++++++------------ 1 file changed, 43 insertions(+), 42 deletions(-) diff --git a/openair1/SIMULATION/tests/CMakeLists.txt b/openair1/SIMULATION/tests/CMakeLists.txt index 3f940313bb..13c678c78a 100644 --- a/openair1/SIMULATION/tests/CMakeLists.txt +++ b/openair1/SIMULATION/tests/CMakeLists.txt @@ -344,47 +344,48 @@ add_physim_test(physim.5g.nr_psbchsim.test2 "PSBCH TxRx" nr_psbchsim -n 30) if (ENABLE_LDPC_AAL) -add_timed_physim_test(physim.5g-offload.nr_dlsim.testX.Y "Run nr_dlsim with CPU: SNR = 30, MCS = 5, 106 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e5 -b106 -R106 -X 8,9,10,11,12 -P) -add_timed_physim_test(physim.5g-offload.nr_dlsim.testX.Y "Run nr_dlsim with T2 LDPC offload: SNR = 30, MCS = 5, 106 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e5 -b106 -R106 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) -add_timed_physim_test(physim.5g-offload.nr_dlsim.testX.Y "Run nr_dlsim with CPU: SNR = 30, MCS = 15, 106 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e15 -b106 -R106 -X 8,9,10,11,12 -P) -add_timed_physim_test(physim.5g-offload.nr_dlsim.testX.Y "Run nr_dlsim with T2 LDPC offload: SNR = 30, MCS = 15, 106 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e15 -b106 -R106 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) -add_timed_physim_test(physim.5g-offload.nr_dlsim.testX.Y "Run nr_dlsim with CPU: SNR = 30, MCS = 25, 106 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e25 -b106 -R106 -X 8,9,10,11,12 -P) -add_timed_physim_test(physim.5g-offload.nr_dlsim.testX.Y "Run nr_dlsim with T2 LDPC offload: SNR = 30, MCS = 25, 106 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e25 -b106 -R106 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) -add_timed_physim_test(physim.5g-offload.nr_dlsim.testX.Y "Run nr_dlsim with CPU: SNR = 30, MCS = 5, 273 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e5 -b273 -R273 -X 8,9,10,11,12 -P) -add_timed_physim_test(physim.5g-offload.nr_dlsim.testX.Y "Run nr_dlsim with T2 LDPC offload: SNR = 30, MCS = 5, 273 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e5 -b273 -R273 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) -add_timed_physim_test(physim.5g-offload.nr_dlsim.testX.Y "Run nr_dlsim with CPU: SNR = 30, MCS = 15, 273 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e15 -b273 -R273 -X 8,9,10,11,12 -P) -add_timed_physim_test(physim.5g-offload.nr_dlsim.testX.Y "Run nr_dlsim with T2 LDPC offload: SNR = 30, MCS = 15, 273 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e15 -b273 -R273 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) -add_timed_physim_test(physim.5g-offload.nr_dlsim.testX.Y "Run nr_dlsim with CPU: SNR = 30, MCS = 25, 273 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e25 -b273 -R273 -X 8,9,10,11,12 -P) -add_timed_physim_test(physim.5g-offload.nr_dlsim.testX.Y "Run nr_dlsim with T2 LDPC offload: SNR = 30, MCS = 25, 273 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e25 -b273 -R273 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) -add_timed_physim_test(physim.5g-offload.nr_dlsim.testX.Y "Run nr_dlsim with CPU: SNR = 30, MCS = 5, 273 PRBs, 2 layers" nr_dlsim -n1000 -s30 -S30.2 -e5 -b273 -R273 -X 8,9,10,11,12 -x2 -z2 -y2 -P) -add_timed_physim_test(physim.5g-offload.nr_dlsim.testX.Y "Run nr_dlsim with T2 LDPC offload: SNR = 30, MCS = 5, 273 PRBs, 2 layers" nr_dlsim -n1000 -s30 -S30.2 -e5 -b273 -R273 -X4,5,6,7,8,9 -x2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) -add_timed_physim_test(physim.5g-offload.nr_dlsim.testX.Y "Run nr_dlsim with CPU: SNR = 30, MCS = 15, 273 PRBs, 2 layers" nr_dlsim -n1000 -s30 -S30.2 -e15 -b273 -R273 -X 8,9,10,11,12 -x2 -z2 -y2 -P) -add_timed_physim_test(physim.5g-offload.nr_dlsim.testX.Y "Run nr_dlsim with T2 LDPC offload: SNR = 30, MCS = 15, 273 PRBs, 2 layers" nr_dlsim -n1000 -s30 -S30.2 -e15 -b273 -R273 -X4,5,6,7,8,9 -x2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) -add_timed_physim_test(physim.5g-offload.nr_dlsim.testX.Y "Run nr_dlsim with CPU: SNR = 30, MCS = 25, 273 PRBs, 2 layers" nr_dlsim -n1000 -s30 -S30.2 -e25 -b273 -R273 -X 8,9,10,11,12 -x2 -z2 -y2 -P) -add_timed_physim_test(physim.5g-offload.nr_dlsim.testX.Y "Run nr_dlsim with T2 LDPC offload: SNR = 30, MCS = 25, 273 PRBs, 2 layers" nr_dlsim -n1000 -s30 -S30.2 -e25 -b273 -R273 -X4,5,6,7,8,9 -x2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) -add_timed_physim_test(physim.5g-offload.nr_dlsim.testX.Y "Run nr_dlsim with CPU: SNR = 30, MCS = 5, 273 PRBs, 2 layers, 4 antennas" nr_dlsim -n1000 -s30 -S30.2 -e5 -b273 -R273 -X8,9,10,11,12 -x2 -z4 -y4 -P) -add_timed_physim_test(physim.5g-offload.nr_dlsim.testX.Y "Run nr_dlsim with T2 LDPC offload: SNR = 30, MCS = 5, 273 PRBs, 2 layers, 4 antennas" nr_dlsim -n1000 -s30 -S30.2 -e5 -b273 -R273 -X4,5,6,7,8,9 -x2 -z4 -y4 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) -add_timed_physim_test(physim.5g-offload.nr_dlsim.testX.Y "Run nr_dlsim with CPU: SNR = 30, MCS = 20, 273 PRBs, 2 layers, 4 antennas" nr_dlsim -n1000 -s30 -S30.2 -e15 -b273 -R273 -X8,9,10,11,12 -x2 -z4 -y4 -P) -add_timed_physim_test(physim.5g-offload.nr_dlsim.testX.Y "Run nr_dlsim with T2 LDPC offload: SNR = 30, MCS = 20, 273 PRBs, 2 layers, 4 antennas" nr_dlsim -n1000 -s30 -S30.2 -e15 -b273 -R273 -X4,5,6,7,8,9 -x2 -z4 -y4 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) -add_timed_physim_test(physim.5g-offload.nr_dlsim.testX.Y "Run nr_dlsim with CPU: SNR = 30, MCS = 27, 273 PRBs, 2 layers, 4 antennas" nr_dlsim -n1000 -s30 -S30.2 -e25 -b273 -R273 -X8,9,10,11,12 -x2 -z4 -y4 -P) -add_timed_physim_test(physim.5g-offload.nr_dlsim.testX.Y "Run nr_dlsim with T2 LDPC offload: SNR = 30, MCS = 27, 273 PRBs, 2 layers, 4 antennas" nr_dlsim -n1000 -s30 -S30.2 -e25 -b273 -R273 -X4,5,6,7,8,9 -x2 -z4 -y4 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) -add_timed_physim_test(physim.5g-offload.nr_ulsim.testX.Y "Run nr_ulsim with CPU: SNR = 30, MCS = 5, 106 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m5 -r106 -R106 -C10 -P) -add_timed_physim_test(physim.5g-offload.nr_ulsim.testX.Y "Run nr_ulsim with T2 LDPC offload: SNR = 30, MCS = 5, 106 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m5 -r106 -R106 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) -add_timed_physim_test(physim.5g-offload.nr_ulsim.testX.Y "Run nr_ulsim with CPU: SNR = 30, MCS = 15, 106 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m15 -r106 -R106 -C10 -P) -add_timed_physim_test(physim.5g-offload.nr_ulsim.testX.Y "Run nr_ulsim with T2 LDPC offload: SNR = 30, MCS = 15, 106 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m15 -r106 -R106 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) -add_timed_physim_test(physim.5g-offload.nr_ulsim.testX.Y "Run nr_ulsim with CPU: SNR = 30, MCS = 25, 106 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m25 -r106 -R106 -C10 -P) -add_timed_physim_test(physim.5g-offload.nr_ulsim.testX.Y "Run nr_ulsim with T2 LDPC offload: SNR = 30, MCS = 25, 106 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m25 -r106 -R106 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) -add_timed_physim_test(physim.5g-offload.nr_ulsim.testX.Y "Run nr_ulsim with CPU: SNR = 30, MCS = 5, 273 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m5 -r273 -R273 -C10 -P) -add_timed_physim_test(physim.5g-offload.nr_ulsim.testX.Y "Run nr_ulsim with T2 LDPC offload: SNR = 30, MCS = 5, 273 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m5 -r273 -R273 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) -add_timed_physim_test(physim.5g-offload.nr_ulsim.testX.Y "Run nr_ulsim with CPU: SNR = 30, MCS = 15, 273 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m15 -r273 -R273 -C10 -P) -add_timed_physim_test(physim.5g-offload.nr_ulsim.testX.Y "Run nr_ulsim with T2 LDPC offload: SNR = 30, MCS = 15, 273 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m15 -r273 -R273 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) -add_timed_physim_test(physim.5g-offload.nr_ulsim.testX.Y "Run nr_ulsim with CPU: SNR = 30, MCS = 25, 273 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m25 -r273 -R273 -C10 -P) -add_timed_physim_test(physim.5g-offload.nr_ulsim.testX.Y "Run nr_ulsim with T2 LDPC offload: SNR = 30, MCS = 25, 273 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m25 -r273 -R273 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) -add_timed_physim_test(physim.5g-offload.nr_ulsim.testX.Y "Run nr_ulsim with CPU: SNR = 30, MCS = 5, 273 PRBs, 2 layers" nr_ulsim -n1000 -s30 -S30.2 -m5 -r273 -R273 -C10 -W2 -z2 -y2 -P) -add_timed_physim_test(physim.5g-offload.nr_ulsim.testX.Y "Run nr_ulsim with T2 LDPC offload: SNR = 30, MCS = 5, 273 PRBs, 2 layers" nr_ulsim -n1000 -s30 -S30.2 -m5 -r273 -R273 -C10 -W2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) -add_timed_physim_test(physim.5g-offload.nr_ulsim.testX.Y "Run nr_ulsim with CPU: SNR = 30, MCS = 15, 273 PRBs, 2 layers" nr_ulsim -n1000 -s30 -S30.2 -m15 -r273 -R273 -C10 -W2 -z2 -y2 -P) -add_timed_physim_test(physim.5g-offload.nr_ulsim.testX.Y "Run nr_ulsim with T2 LDPC offload: SNR = 30, MCS = 15, 273 PRBs, 2 layers" nr_ulsim -n1000 -s30 -S30.2 -m15 -r273 -R273 -C10 -W2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) -add_timed_physim_test(physim.5g-offload.nr_ulsim.testX.Y "Run nr_ulsim with CPU: SNR = 30, MCS = 25, 273 PRBs, 2 layers" nr_ulsim -n1000 -s30 -S30.2 -m25 -r273 -R273 -C10 -W2 -z2 -y2 -P) -add_timed_physim_test(physim.5g-offload.nr_ulsim.testX.Y "Run nr_ulsim with T2 LDPC offload: SNR = 30, MCS = 25, 273 PRBs, 2 layers" nr_ulsim -n1000 -s30 -S30.2 -m25 -r273 -R273 -C10 -W2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_timed_physim_test(physim.5g-offload.nr_dlsim.testCPU.1 "CPU: SNR = 30, MCS = 5, 106 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e5 -b106 -R106 -X 8,9,10,11,12 -P) +add_timed_physim_test(physim.5g-offload.nr_dlsim.testT2.1 "T2 LDPC offload: SNR = 30, MCS = 5, 106 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e5 -b106 -R106 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_timed_physim_test(physim.5g-offload.nr_dlsim.testCPU.2 "CPU: SNR = 30, MCS = 15, 106 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e15 -b106 -R106 -X 8,9,10,11,12 -P) +add_timed_physim_test(physim.5g-offload.nr_dlsim.testT2.2 "T2 LDPC offload: SNR = 30, MCS = 15, 106 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e15 -b106 -R106 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_timed_physim_test(physim.5g-offload.nr_dlsim.testCPU.3 "CPU: SNR = 30, MCS = 25, 106 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e25 -b106 -R106 -X 8,9,10,11,12 -P) +add_timed_physim_test(physim.5g-offload.nr_dlsim.testT2.3 "T2 LDPC offload: SNR = 30, MCS = 25, 106 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e25 -b106 -R106 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_timed_physim_test(physim.5g-offload.nr_dlsim.testCPU.4 "CPU: SNR = 30, MCS = 5, 273 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e5 -b273 -R273 -X 8,9,10,11,12 -P) +add_timed_physim_test(physim.5g-offload.nr_dlsim.testT2.4 "T2 LDPC offload: SNR = 30, MCS = 5, 273 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e5 -b273 -R273 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_timed_physim_test(physim.5g-offload.nr_dlsim.testCPU.5 "CPU: SNR = 30, MCS = 15, 273 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e15 -b273 -R273 -X 8,9,10,11,12 -P) +add_timed_physim_test(physim.5g-offload.nr_dlsim.testT2.5 "T2 LDPC offload: SNR = 30, MCS = 15, 273 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e15 -b273 -R273 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_timed_physim_test(physim.5g-offload.nr_dlsim.testCPU.6 "CPU: SNR = 30, MCS = 25, 273 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e25 -b273 -R273 -X 8,9,10,11,12 -P) +add_timed_physim_test(physim.5g-offload.nr_dlsim.testT2.6 "T2 LDPC offload: SNR = 30, MCS = 25, 273 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e25 -b273 -R273 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_timed_physim_test(physim.5g-offload.nr_dlsim.testCPU.7 "CPU: SNR = 30, MCS = 5, 273 PRBs, 2 layers" nr_dlsim -n1000 -s30 -S30.2 -e5 -b273 -R273 -X 8,9,10,11,12 -x2 -z2 -y2 -P) +add_timed_physim_test(physim.5g-offload.nr_dlsim.testT2.7 "T2 LDPC offload: SNR = 30, MCS = 5, 273 PRBs, 2 layers" nr_dlsim -n1000 -s30 -S30.2 -e5 -b273 -R273 -X4,5,6,7,8,9 -x2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_timed_physim_test(physim.5g-offload.nr_dlsim.testCPU.8 "CPU: SNR = 30, MCS = 15, 273 PRBs, 2 layers" nr_dlsim -n1000 -s30 -S30.2 -e15 -b273 -R273 -X 8,9,10,11,12 -x2 -z2 -y2 -P) +add_timed_physim_test(physim.5g-offload.nr_dlsim.testT2.8 "T2 LDPC offload: SNR = 30, MCS = 15, 273 PRBs, 2 layers" nr_dlsim -n1000 -s30 -S30.2 -e15 -b273 -R273 -X4,5,6,7,8,9 -x2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_timed_physim_test(physim.5g-offload.nr_dlsim.testCPU.9 "CPU: SNR = 30, MCS = 25, 273 PRBs, 2 layers" nr_dlsim -n1000 -s30 -S30.2 -e25 -b273 -R273 -X 8,9,10,11,12 -x2 -z2 -y2 -P) +add_timed_physim_test(physim.5g-offload.nr_dlsim.testT2.9 "T2 LDPC offload: SNR = 30, MCS = 25, 273 PRBs, 2 layers" nr_dlsim -n1000 -s30 -S30.2 -e25 -b273 -R273 -X4,5,6,7,8,9 -x2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_timed_physim_test(physim.5g-offload.nr_dlsim.testCPU.10 "CPU: SNR = 30, MCS = 5, 273 PRBs, 2 layers, 4 antennas" nr_dlsim -n1000 -s30 -S30.2 -e5 -b273 -R273 -X8,9,10,11,12 -x2 -z4 -y4 -P) +add_timed_physim_test(physim.5g-offload.nr_dlsim.testT2.10 "T2 LDPC offload: SNR = 30, MCS = 5, 273 PRBs, 2 layers, 4 antennas" nr_dlsim -n1000 -s30 -S30.2 -e5 -b273 -R273 -X4,5,6,7,8,9 -x2 -z4 -y4 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_timed_physim_test(physim.5g-offload.nr_dlsim.testCPU.11 "CPU: SNR = 30, MCS = 20, 273 PRBs, 2 layers, 4 antennas" nr_dlsim -n1000 -s30 -S30.2 -e15 -b273 -R273 -X8,9,10,11,12 -x2 -z4 -y4 -P) +add_timed_physim_test(physim.5g-offload.nr_dlsim.testT2.11 "T2 LDPC offload: SNR = 30, MCS = 20, 273 PRBs, 2 layers, 4 antennas" nr_dlsim -n1000 -s30 -S30.2 -e15 -b273 -R273 -X4,5,6,7,8,9 -x2 -z4 -y4 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_timed_physim_test(physim.5g-offload.nr_dlsim.testCPU.12 "CPU: SNR = 30, MCS = 27, 273 PRBs, 2 layers, 4 antennas" nr_dlsim -n1000 -s30 -S30.2 -e25 -b273 -R273 -X8,9,10,11,12 -x2 -z4 -y4 -P) +add_timed_physim_test(physim.5g-offload.nr_dlsim.testT2.12 "T2 LDPC offload: SNR = 30, MCS = 27, 273 PRBs, 2 layers, 4 antennas" nr_dlsim -n1000 -s30 -S30.2 -e25 -b273 -R273 -X4,5,6,7,8,9 -x2 -z4 -y4 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) + +add_timed_physim_test(physim.5g-offload.nr_ulsim.testCPU.1 "CPU: SNR = 30, MCS = 5, 106 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m5 -r106 -R106 -C10 -P) +add_timed_physim_test(physim.5g-offload.nr_ulsim.testT2.1 "T2 LDPC offload: SNR = 30, MCS = 5, 106 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m5 -r106 -R106 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_timed_physim_test(physim.5g-offload.nr_ulsim.testCPU.2 "CPU: SNR = 30, MCS = 15, 106 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m15 -r106 -R106 -C10 -P) +add_timed_physim_test(physim.5g-offload.nr_ulsim.testT2.2 "T2 LDPC offload: SNR = 30, MCS = 15, 106 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m15 -r106 -R106 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_timed_physim_test(physim.5g-offload.nr_ulsim.testCPU.3 "CPU: SNR = 30, MCS = 25, 106 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m25 -r106 -R106 -C10 -P) +add_timed_physim_test(physim.5g-offload.nr_ulsim.testT2.3 "T2 LDPC offload: SNR = 30, MCS = 25, 106 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m25 -r106 -R106 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_timed_physim_test(physim.5g-offload.nr_ulsim.testCPU.4 "CPU: SNR = 30, MCS = 5, 273 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m5 -r273 -R273 -C10 -P) +add_timed_physim_test(physim.5g-offload.nr_ulsim.testT2.4 "T2 LDPC offload: SNR = 30, MCS = 5, 273 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m5 -r273 -R273 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_timed_physim_test(physim.5g-offload.nr_ulsim.testCPU.5 "CPU: SNR = 30, MCS = 15, 273 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m15 -r273 -R273 -C10 -P) +add_timed_physim_test(physim.5g-offload.nr_ulsim.testT2.5 "T2 LDPC offload: SNR = 30, MCS = 15, 273 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m15 -r273 -R273 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_timed_physim_test(physim.5g-offload.nr_ulsim.testCPU.6 "CPU: SNR = 30, MCS = 25, 273 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m25 -r273 -R273 -C10 -P) +add_timed_physim_test(physim.5g-offload.nr_ulsim.testT2.6 "T2 LDPC offload: SNR = 30, MCS = 25, 273 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m25 -r273 -R273 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_timed_physim_test(physim.5g-offload.nr_ulsim.testCPU.7 "CPU: SNR = 30, MCS = 5, 273 PRBs, 2 layers" nr_ulsim -n1000 -s30 -S30.2 -m5 -r273 -R273 -C10 -W2 -z2 -y2 -P) +add_timed_physim_test(physim.5g-offload.nr_ulsim.testT2.7 "T2 LDPC offload: SNR = 30, MCS = 5, 273 PRBs, 2 layers" nr_ulsim -n1000 -s30 -S30.2 -m5 -r273 -R273 -C10 -W2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_timed_physim_test(physim.5g-offload.nr_ulsim.testCPU.8 "CPU: SNR = 30, MCS = 15, 273 PRBs, 2 layers" nr_ulsim -n1000 -s30 -S30.2 -m15 -r273 -R273 -C10 -W2 -z2 -y2 -P) +add_timed_physim_test(physim.5g-offload.nr_ulsim.testT2.8 "T2 LDPC offload: SNR = 30, MCS = 15, 273 PRBs, 2 layers" nr_ulsim -n1000 -s30 -S30.2 -m15 -r273 -R273 -C10 -W2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_timed_physim_test(physim.5g-offload.nr_ulsim.testCPU.9 "CPU: SNR = 30, MCS = 25, 273 PRBs, 2 layers" nr_ulsim -n1000 -s30 -S30.2 -m25 -r273 -R273 -C10 -W2 -z2 -y2 -P) +add_timed_physim_test(physim.5g-offload.nr_ulsim.testT2.9 "T2 LDPC offload: SNR = 30, MCS = 25, 273 PRBs, 2 layers" nr_ulsim -n1000 -s30 -S30.2 -m25 -r273 -R273 -C10 -W2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) endif() From da644bc91d7c62105ddeb70d74ef4ec717cbde50 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 8 Sep 2025 17:02:31 +0200 Subject: [PATCH 674/964] Import existing timing thresholds for offload tests Imported using commands: xmlstarlet sel -t \ -m '//testCaseList/testCase[class="Run_Physim"]' \ -v "concat('check_physim_threshold(physim.5g-offload.',physim_test,'.testX.Y \"DLSCH encoding time\" \"< ', physim_time_threshold, '\")')" \ -n t2_offload_enc_nr_dlsim.xml >> ../../openair1/SIMULATION/tests/ThresholdsOffload.cmake xmlstarlet sel -t \ -m '//testCaseList/testCase[class="Run_Physim"]' \ -v "concat('check_physim_threshold(physim.5g-offload.',physim_test,'.testX.Y \"ULSCH total decoding time\" \"< ', physim_time_threshold, '\")')" \ -n t2_offload_dec_nr_ulsim.xml >> ../../openair1/SIMULATION/tests/ThresholdsOffload.cmake --- openair1/SIMULATION/tests/CMakeLists.txt | 2 + .../SIMULATION/tests/ThresholdsOffload.cmake | 43 +++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 openair1/SIMULATION/tests/ThresholdsOffload.cmake diff --git a/openair1/SIMULATION/tests/CMakeLists.txt b/openair1/SIMULATION/tests/CMakeLists.txt index 13c678c78a..d71df315bb 100644 --- a/openair1/SIMULATION/tests/CMakeLists.txt +++ b/openair1/SIMULATION/tests/CMakeLists.txt @@ -388,4 +388,6 @@ add_timed_physim_test(physim.5g-offload.nr_ulsim.testT2.8 "T2 LDPC offload: SNR add_timed_physim_test(physim.5g-offload.nr_ulsim.testCPU.9 "CPU: SNR = 30, MCS = 25, 273 PRBs, 2 layers" nr_ulsim -n1000 -s30 -S30.2 -m25 -r273 -R273 -C10 -W2 -z2 -y2 -P) add_timed_physim_test(physim.5g-offload.nr_ulsim.testT2.9 "T2 LDPC offload: SNR = 30, MCS = 25, 273 PRBs, 2 layers" nr_ulsim -n1000 -s30 -S30.2 -m25 -r273 -R273 -C10 -W2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +include(ThresholdsOffload.cmake) + endif() diff --git a/openair1/SIMULATION/tests/ThresholdsOffload.cmake b/openair1/SIMULATION/tests/ThresholdsOffload.cmake new file mode 100644 index 0000000000..72b2ee2569 --- /dev/null +++ b/openair1/SIMULATION/tests/ThresholdsOffload.cmake @@ -0,0 +1,43 @@ +check_threshold(physim.5g-offload.nr_dlsim.testCPU.1 "DLSCH encoding time" "< 230") +check_threshold(physim.5g-offload.nr_dlsim.testT2.1 "DLSCH encoding time" "< 100") +check_threshold(physim.5g-offload.nr_dlsim.testCPU.2 "DLSCH encoding time" "< 300") +check_threshold(physim.5g-offload.nr_dlsim.testT2.2 "DLSCH encoding time" "< 100") +check_threshold(physim.5g-offload.nr_dlsim.testCPU.3 "DLSCH encoding time" "< 350") +check_threshold(physim.5g-offload.nr_dlsim.testT2.3 "DLSCH encoding time" "< 200") +check_threshold(physim.5g-offload.nr_dlsim.testCPU.4 "DLSCH encoding time" "< 300") +check_threshold(physim.5g-offload.nr_dlsim.testT2.4 "DLSCH encoding time" "< 150") +check_threshold(physim.5g-offload.nr_dlsim.testCPU.5 "DLSCH encoding time" "< 350") +check_threshold(physim.5g-offload.nr_dlsim.testT2.5 "DLSCH encoding time" "< 250") +check_threshold(physim.5g-offload.nr_dlsim.testCPU.6 "DLSCH encoding time" "< 400") +check_threshold(physim.5g-offload.nr_dlsim.testT2.6 "DLSCH encoding time" "< 400") +check_threshold(physim.5g-offload.nr_dlsim.testCPU.7 "DLSCH encoding time" "< 400") +check_threshold(physim.5g-offload.nr_dlsim.testT2.7 "DLSCH encoding time" "< 200") +check_threshold(physim.5g-offload.nr_dlsim.testCPU.8 "DLSCH encoding time" "< 450") +check_threshold(physim.5g-offload.nr_dlsim.testT2.8 "DLSCH encoding time" "< 500") +check_threshold(physim.5g-offload.nr_dlsim.testCPU.9 "DLSCH encoding time" "< 500") +check_threshold(physim.5g-offload.nr_dlsim.testT2.9 "DLSCH encoding time" "< 500") +check_threshold(physim.5g-offload.nr_dlsim.testCPU.10 "DLSCH encoding time" "< 400") +check_threshold(physim.5g-offload.nr_dlsim.testT2.10 "DLSCH encoding time" "< 200") +check_threshold(physim.5g-offload.nr_dlsim.testCPU.11 "DLSCH encoding time" "< 400") +check_threshold(physim.5g-offload.nr_dlsim.testT2.11 "DLSCH encoding time" "< 300") +check_threshold(physim.5g-offload.nr_dlsim.testCPU.12 "DLSCH encoding time" "< 450") +check_threshold(physim.5g-offload.nr_dlsim.testT2.12 "DLSCH encoding time" "< 450") + +check_threshold(physim.5g-offload.nr_ulsim.testCPU.1 "ULSCH total decoding time" "< 300") +check_threshold(physim.5g-offload.nr_ulsim.testT2.1 "ULSCH total decoding time" "< 100") +check_threshold(physim.5g-offload.nr_ulsim.testCPU.2 "ULSCH total decoding time" "< 300") +check_threshold(physim.5g-offload.nr_ulsim.testT2.2 "ULSCH total decoding time" "< 150") +check_threshold(physim.5g-offload.nr_ulsim.testCPU.3 "ULSCH total decoding time" "< 250") +check_threshold(physim.5g-offload.nr_ulsim.testT2.3 "ULSCH total decoding time" "< 250") +check_threshold(physim.5g-offload.nr_ulsim.testCPU.4 "ULSCH total decoding time" "< 300") +check_threshold(physim.5g-offload.nr_ulsim.testT2.4 "ULSCH total decoding time" "< 150") +check_threshold(physim.5g-offload.nr_ulsim.testCPU.5 "ULSCH total decoding time" "< 400") +check_threshold(physim.5g-offload.nr_ulsim.testT2.5 "ULSCH total decoding time" "< 350") +check_threshold(physim.5g-offload.nr_ulsim.testCPU.6 "ULSCH total decoding time" "< 400") +check_threshold(physim.5g-offload.nr_ulsim.testT2.6 "ULSCH total decoding time" "< 550") +check_threshold(physim.5g-offload.nr_ulsim.testCPU.7 "ULSCH total decoding time" "< 300") +check_threshold(physim.5g-offload.nr_ulsim.testT2.7 "ULSCH total decoding time" "< 250") +check_threshold(physim.5g-offload.nr_ulsim.testCPU.8 "ULSCH total decoding time" "< 600") +check_threshold(physim.5g-offload.nr_ulsim.testT2.8 "ULSCH total decoding time" "< 650") +check_threshold(physim.5g-offload.nr_ulsim.testCPU.9 "ULSCH total decoding time" "< 650") +check_threshold(physim.5g-offload.nr_ulsim.testT2.9 "ULSCH total decoding time" "< 1100") From adabb6a96728baff799a6414868ea2eb11193c66 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 26 Aug 2025 13:27:29 +0200 Subject: [PATCH 675/964] Add script to run PhySims from source physim script more --- ci-scripts/scripts/source-deploy-physims.sh | 30 +++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 ci-scripts/scripts/source-deploy-physims.sh diff --git a/ci-scripts/scripts/source-deploy-physims.sh b/ci-scripts/scripts/source-deploy-physims.sh new file mode 100644 index 0000000000..6054453301 --- /dev/null +++ b/ci-scripts/scripts/source-deploy-physims.sh @@ -0,0 +1,30 @@ + +function die() { echo $@; exit 1; } +[ $# -ge 1 ] || die "usage: $0 [ctest-options]" + +set -x +DIR=$1 +shift +CTEST_OPT=$@ + +cd ${DIR}/cmake_targets/ran_build/build +ninja ldpctest polartest smallblocktest nr_pbchsim nr_dlschsim nr_ulschsim nr_dlsim nr_ulsim nr_pucchsim nr_prachsim nr_psbchsim + +# get a JSON description of all tests to run +ctest ${CTEST_OPT} --show-only=json-v1 &> ${DIR}/desc-tests.json +JSON_RES=$? + +# we run the T2 offload tests, so provide some additional permissions +# to be able to initialize DPDK +sudo setcap cap_dac_override,cap_sys_admin+ep nr_ulsim +sudo setcap cap_dac_override,cap_sys_admin+ep nr_dlsim +ctest ${CTEST_OPT} --output-junit ${DIR}/results-run.xml --test-output-size-passed 100000 --test-output-size-failed 100000 &>> ${DIR}/physim_log.txt +RUN_RES=$? +cp Testing/Temporary/LastTestsFailed.log ${DIR}/ +cp Testing/Temporary/LastTest.log ${DIR}/ + +# if both were successful, return 0 +# TODO not sure +#[[ $JSON_RES -eq 0 && $RUN_RES -eq 0 ]] && exit 0 + +exit 0 From 42dbaaf75cb7d681c8116d3bb5b034064d7525f4 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 26 Aug 2025 11:12:22 +0200 Subject: [PATCH 676/964] Add new T2 Offload test --- ci-scripts/main.py | 4 +- ci-scripts/xml_class_list.yml | 1 + .../xml_files/t2_offload_physim_enc_dec.xml | 54 +++++++++++++++++++ 3 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 ci-scripts/xml_files/t2_offload_physim_enc_dec.xml diff --git a/ci-scripts/main.py b/ci-scripts/main.py index ee855d7102..63472bc098 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -251,10 +251,10 @@ def ExecuteActionWithParam(action, ctx): workdir = CLUSTER.eNBSourceCodePath success = cls_oaicitest.Deploy_Physim(ctx, HTML, node, workdir, script, options) - elif action == 'Build_Deploy_Docker_PhySim': + elif action == 'Build_Deploy_Docker_PhySim' or action == 'Build_Deploy_Source_PhySim': node = test.findtext('node') or None ctest_opt = test.findtext('ctest-opt') or '' - script = "scripts/docker-build-and-deploy-physims.sh" + script = "scripts/docker-build-and-deploy-physims.sh" if action == 'Build_Deploy_Docker_PhySim' else 'scripts/source-deploy-physims.sh' options = f"{CONTAINERS.eNBSourceCodePath} {ctest_opt}" workdir = CONTAINERS.eNBSourceCodePath success = cls_oaicitest.Deploy_Physim(ctx, HTML, node, workdir, script, options) diff --git a/ci-scripts/xml_class_list.yml b/ci-scripts/xml_class_list.yml index 4ab7bd1714..daca7b2595 100755 --- a/ci-scripts/xml_class_list.yml +++ b/ci-scripts/xml_class_list.yml @@ -25,6 +25,7 @@ - Cppcheck_Analysis - Deploy_Run_OC_PhySim - Build_Deploy_Docker_PhySim + - Build_Deploy_Source_PhySim - LicenceAndFormattingCheck - Push_Local_Registry - Pull_Local_Registry diff --git a/ci-scripts/xml_files/t2_offload_physim_enc_dec.xml b/ci-scripts/xml_files/t2_offload_physim_enc_dec.xml new file mode 100644 index 0000000000..73631a7a3c --- /dev/null +++ b/ci-scripts/xml_files/t2_offload_physim_enc_dec.xml @@ -0,0 +1,54 @@ + + + + test-t2-offload-enc-dec + Test T2 Offload + tasks + + 010204 + 111111 + 402010 + + + + + Custom_Command + Disable Sleep States + caracal + sudo cpupower idle-set -D 0 + + + + Custom_Command + true + Enable Sleep States + caracal + sudo cpupower idle-set -E + + + + Build_Deploy_Source_PhySim + Build and Deploy PhySim T2 Offload tests + caracal + -R 5g-offload -j1 + + From b00dd803d1ee22652db319edcbc683d640fb1b2c Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 26 Aug 2025 11:14:03 +0200 Subject: [PATCH 677/964] Remove existing physim offload tests After the parent commit, there is no need for these XML files anymore. The tests are driven by ctest instead. --- ci-scripts/cls_analysis.py | 56 ---- ci-scripts/cls_native.py | 15 - ci-scripts/main.py | 7 - ci-scripts/xml_class_list.yml | 1 - .../xml_files/t2_offload_dec_nr_ulsim.xml | 230 -------------- .../xml_files/t2_offload_enc_nr_dlsim.xml | 290 ------------------ 6 files changed, 599 deletions(-) delete mode 100644 ci-scripts/xml_files/t2_offload_dec_nr_ulsim.xml delete mode 100644 ci-scripts/xml_files/t2_offload_enc_nr_dlsim.xml diff --git a/ci-scripts/cls_analysis.py b/ci-scripts/cls_analysis.py index 236a4743a1..09848a6972 100644 --- a/ci-scripts/cls_analysis.py +++ b/ci-scripts/cls_analysis.py @@ -26,64 +26,8 @@ import os import xml.etree.ElementTree as ET import json -# Define the mapping of physim_test values to search patterns -PHYSIM_PATTERN_MAPPING = { - 'nr_ulsim': [ - r'(Total PHY proc rx)\s+(\d+\.\d+)\s+us', # Pattern for RX PHY processing time - r'(ULSCH total decoding time)\s+(\d+\.\d+)\s+us', # Pattern for ULSCH decoding time - ], - 'nr_dlsim': [ - r'(PHY proc tx)\s+(\d+\.\d+)\s+us', # Pattern for TX PHY processing time - r'(DLSCH encoding time)\s+(\d+\.\d+)\s+us', # Pattern for DLSCH encoding time - ], - 'ldpctest': [ - r'(Encoding time mean):\s+(\d+\.\d+)\s+us', # Pattern for encoding time mean - r'(Decoding time mean):\s+(\d+\.\d+)\s+us', # Pattern for decoding time mean - ], -} -# Define test conditions based on the simulation type -PHYSIM_TEST_CONDITION = { - 'nr_ulsim': 'test OK', # For nr_ulsim, check if 'test OK' is present - 'nr_dlsim': 'test OK', # For nr_dlsim, check if 'test OK' is present - 'ldpctest': None, # No condition for ldpctest, just process the patterns -} - class Analysis(): - def analyze_physim(log, physim_test, options, threshold): - search_patterns = PHYSIM_PATTERN_MAPPING.get(physim_test) - test_condition = PHYSIM_TEST_CONDITION.get(physim_test) - success = False - msg = '' - - try: - with open(log, 'r') as f: - log_content = f.read() - except FileNotFoundError as e: - msg = f'{log} file not found, exception: {e}' - return False, msg - except Exception as e: - msg = f'Error while parsing log file {log}: exception: {e}' - return False, msg - - if test_condition and test_condition not in log_content: - msg = f"Test did not succeed, '{test_condition}' not found in log file {log}." - return False, msg - - time1_match = re.search(search_patterns[0], log_content) - time2_match = re.search(search_patterns[1], log_content) - if not(time1_match and time2_match): - msg = f"Processing time not found in log file {log}." - return False, msg - - success = float(time2_match.group(2)) < float(threshold) - if success: - msg = f'{time1_match.group(1)}: {time1_match.group(2)} us\n{time2_match.group(1)}: {time2_match.group(2)} us' - else: - msg = f'{time1_match.group(1)}: {time1_match.group(2)} us\n{time2_match.group(1)}: {time2_match.group(2)} us exceeds a limit of {threshold} us' - - return success,msg - def analyze_oc_physim(result_junit, details_json, logPath): try: tree = ET.parse(result_junit) diff --git a/ci-scripts/cls_native.py b/ci-scripts/cls_native.py index 1736cc144d..d96f60bdca 100644 --- a/ci-scripts/cls_native.py +++ b/ci-scripts/cls_native.py @@ -64,18 +64,3 @@ class Native(): logging.error('\u001B[1m Building OAI Failed\u001B[0m') HTML.CreateHtmlTestRow(options, 'KO', CONST.ALL_PROCESSES_OK) return success - - def Run_Physim(ctx, HTML, host, directory, options, physim_test, threshold): - logging.debug(f'Runnin {physim_test} on server: {host}') - workSpacePath = f'{directory}/cmake_targets' - runLogFile=f'{workSpacePath}/physim.log' - with cls_cmd.getConnection(host) as cmd: - cmd.run(f'sudo LD_LIBRARY_PATH=.:{DPDK_PATH}/lib64/ {workSpacePath}/ran_build/build/{physim_test} {options} > {runLogFile} 2>&1') - physim_file = archiveArtifact(cmd, ctx, runLogFile) - success, msg = cls_analysis.Analysis.analyze_physim(physim_file, physim_test, options, threshold) - if success: - HTML.CreateHtmlTestRowQueue(options, 'OK', [msg]) - else: - logging.error(msg) - HTML.CreateHtmlTestRowQueue(options, 'KO', [msg]) - return success diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 63472bc098..3e7be396cc 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -286,13 +286,6 @@ def ExecuteActionWithParam(action, ctx): return True success = CONTAINERS.Create_Workspace(node, HTML) - elif action == 'Run_Physim': - physim_options = test.findtext('physim_run_args') - physim_test = test.findtext('physim_test') - physim_threshold = test.findtext('physim_time_threshold') or 'inf' - node = test.findtext('node') - success = cls_native.Native.Run_Physim(ctx, HTML, node, RAN.eNBSourceCodePath, physim_options, physim_test, physim_threshold) - elif action == 'LicenceAndFormattingCheck': node = test.findtext('node') success = SCA.LicenceAndFormattingCheck(ctx, node, HTML) diff --git a/ci-scripts/xml_class_list.yml b/ci-scripts/xml_class_list.yml index daca7b2595..615454bbea 100755 --- a/ci-scripts/xml_class_list.yml +++ b/ci-scripts/xml_class_list.yml @@ -1,7 +1,6 @@ - Build_Proxy - Build_Cluster_Image - Pull_Cluster_Image - - Run_Physim - Build_eNB - Initialize_eNB - Terminate_eNB diff --git a/ci-scripts/xml_files/t2_offload_dec_nr_ulsim.xml b/ci-scripts/xml_files/t2_offload_dec_nr_ulsim.xml deleted file mode 100644 index 4a2daf0b97..0000000000 --- a/ci-scripts/xml_files/t2_offload_dec_nr_ulsim.xml +++ /dev/null @@ -1,230 +0,0 @@ - - - - test-t2-offload-dec - Test T2 Offload Decoder - tasks - - 010204 - 010111 010112 010121 010122 010131 010132 - 010211 010212 010221 010222 010231 010232 - 010311 010312 010321 010322 010331 010332 - 402010 - - - - - Custom_Command - Disable Sleep States - caracal - sudo cpupower idle-set -D 0 - - - - Custom_Command - true - Enable Sleep States - caracal - sudo cpupower idle-set -E - - - - Run_Physim - Run nr_ulsim with CPU: SNR = 30, MCS = 5, 106 PRBs, 1 layer - true - caracal - nr_ulsim - 300 - -n1000 -s30 -S30.2 -m5 -r106 -R106 -C10 -P - - - - Run_Physim - Run nr_ulsim with T2 LDPC offload: SNR = 30, MCS = 5, 106 PRBs, 1 layer - true - caracal - nr_ulsim - 100 - -n1000 -s30 -S30.2 -m5 -r106 -R106 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 - - - - Run_Physim - Run nr_ulsim with CPU: SNR = 30, MCS = 15, 106 PRBs, 1 layer - true - caracal - nr_ulsim - 300 - -n1000 -s30 -S30.2 -m15 -r106 -R106 -C10 -P - - - - Run_Physim - Run nr_ulsim with T2 LDPC offload: SNR = 30, MCS = 15, 106 PRBs, 1 layer - true - caracal - nr_ulsim - 150 - -n1000 -s30 -S30.2 -m15 -r106 -R106 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 - - - - Run_Physim - Run nr_ulsim with CPU: SNR = 30, MCS = 25, 106 PRBs, 1 layer - true - caracal - nr_ulsim - 250 - -n1000 -s30 -S30.2 -m25 -r106 -R106 -C10 -P - - - - Run_Physim - Run nr_ulsim with T2 LDPC offload: SNR = 30, MCS = 25, 106 PRBs, 1 layer - true - caracal - nr_ulsim - 250 - -n1000 -s30 -S30.2 -m25 -r106 -R106 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 - - - - Run_Physim - Run nr_ulsim with CPU: SNR = 30, MCS = 5, 273 PRBs, 1 layer - true - caracal - nr_ulsim - 300 - -n1000 -s30 -S30.2 -m5 -r273 -R273 -C10 -P - - - - Run_Physim - Run nr_ulsim with T2 LDPC offload: SNR = 30, MCS = 5, 273 PRBs, 1 layer - true - caracal - nr_ulsim - 150 - -n1000 -s30 -S30.2 -m5 -r273 -R273 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 - - - - Run_Physim - Run nr_ulsim with CPU: SNR = 30, MCS = 15, 273 PRBs, 1 layer - true - caracal - nr_ulsim - 400 - -n1000 -s30 -S30.2 -m15 -r273 -R273 -C10 -P - - - - Run_Physim - Run nr_ulsim with T2 LDPC offload: SNR = 30, MCS = 15, 273 PRBs, 1 layer - true - caracal - nr_ulsim - 350 - -n1000 -s30 -S30.2 -m15 -r273 -R273 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 - - - - Run_Physim - Run nr_ulsim with CPU: SNR = 30, MCS = 25, 273 PRBs, 1 layer - true - caracal - nr_ulsim - 400 - -n1000 -s30 -S30.2 -m25 -r273 -R273 -C10 -P - - - - Run_Physim - Run nr_ulsim with T2 LDPC offload: SNR = 30, MCS = 25, 273 PRBs, 1 layer - true - caracal - nr_ulsim - 550 - -n1000 -s30 -S30.2 -m25 -r273 -R273 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 - - - - Run_Physim - Run nr_ulsim with CPU: SNR = 30, MCS = 5, 273 PRBs, 2 layers - true - caracal - nr_ulsim - 300 - -n1000 -s30 -S30.2 -m5 -r273 -R273 -C10 -W2 -z2 -y2 -P - - - - Run_Physim - Run nr_ulsim with T2 LDPC offload: SNR = 30, MCS = 5, 273 PRBs, 2 layers - true - caracal - nr_ulsim - 250 - -n1000 -s30 -S30.2 -m5 -r273 -R273 -C10 -W2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 - - - - Run_Physim - Run nr_ulsim with CPU: SNR = 30, MCS = 15, 273 PRBs, 2 layers - true - caracal - nr_ulsim - 600 - -n1000 -s30 -S30.2 -m15 -r273 -R273 -C10 -W2 -z2 -y2 -P - - - - Run_Physim - Run nr_ulsim with T2 LDPC offload: SNR = 30, MCS = 15, 273 PRBs, 2 layers - true - caracal - nr_ulsim - 650 - -n1000 -s30 -S30.2 -m15 -r273 -R273 -C10 -W2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 - - - - Run_Physim - Run nr_ulsim with CPU: SNR = 30, MCS = 25, 273 PRBs, 2 layers - true - caracal - nr_ulsim - 650 - -n1000 -s30 -S30.2 -m25 -r273 -R273 -C10 -W2 -z2 -y2 -P - - - - Run_Physim - Run nr_ulsim with T2 LDPC offload: SNR = 30, MCS = 25, 273 PRBs, 2 layers - true - caracal - nr_ulsim - 1100 - -n1000 -s30 -S30.2 -m25 -r273 -R273 -C10 -W2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 - - - diff --git a/ci-scripts/xml_files/t2_offload_enc_nr_dlsim.xml b/ci-scripts/xml_files/t2_offload_enc_nr_dlsim.xml deleted file mode 100644 index 69dc27943c..0000000000 --- a/ci-scripts/xml_files/t2_offload_enc_nr_dlsim.xml +++ /dev/null @@ -1,290 +0,0 @@ - - - - test-t2-offload-enc - Test T2 Offload Encoder - tasks - - 102040 - 000111 000112 000121 000122 000131 000132 - 000211 000212 000221 000222 000231 000232 - 000311 000312 000321 000322 000331 000332 - 000411 000412 000421 000422 000431 000432 - 040201 - - - - - Custom_Command - Disable Sleep States - caracal - sudo cpupower idle-set -D 0 - - - - Custom_Command - true - Enable Sleep States - caracal - sudo cpupower idle-set -E - - - - Run_Physim - Run nr_dlsim with CPU: SNR = 30, MCS = 5, 106 PRBs, 1 layer - true - caracal - nr_dlsim - 230 - -n1000 -s30 -S30.2 -e5 -b106 -R106 -X 8,9,10,11,12 -P - - - - Run_Physim - Run nr_dlsim with T2 LDPC offload: SNR = 30, MCS = 5, 106 PRBs, 1 layer - true - caracal - nr_dlsim - 100 - -n1000 -s30 -S30.2 -e5 -b106 -R106 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 - - - - Run_Physim - Run nr_dlsim with CPU: SNR = 30, MCS = 15, 106 PRBs, 1 layer - true - caracal - nr_dlsim - 300 - -n1000 -s30 -S30.2 -e15 -b106 -R106 -X 8,9,10,11,12 -P - - - - Run_Physim - Run nr_dlsim with T2 LDPC offload: SNR = 30, MCS = 15, 106 PRBs, 1 layer - true - caracal - nr_dlsim - 100 - -n1000 -s30 -S30.2 -e15 -b106 -R106 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 - - - - Run_Physim - Run nr_dlsim with CPU: SNR = 30, MCS = 25, 106 PRBs, 1 layer - true - caracal - nr_dlsim - 350 - -n1000 -s30 -S30.2 -e25 -b106 -R106 -X 8,9,10,11,12 -P - - - - Run_Physim - Run nr_dlsim with T2 LDPC offload: SNR = 30, MCS = 25, 106 PRBs, 1 layer - true - caracal - nr_dlsim - 200 - -n1000 -s30 -S30.2 -e25 -b106 -R106 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 - - - - Run_Physim - Run nr_dlsim with CPU: SNR = 30, MCS = 5, 273 PRBs, 1 layer - true - caracal - nr_dlsim - 300 - -n1000 -s30 -S30.2 -e5 -b273 -R273 -X 8,9,10,11,12 -P - - - - Run_Physim - Run nr_dlsim with T2 LDPC offload: SNR = 30, MCS = 5, 273 PRBs, 1 layer - true - caracal - nr_dlsim - 150 - -n1000 -s30 -S30.2 -e5 -b273 -R273 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 - - - - Run_Physim - Run nr_dlsim with CPU: SNR = 30, MCS = 15, 273 PRBs, 1 layer - true - caracal - nr_dlsim - 350 - -n1000 -s30 -S30.2 -e15 -b273 -R273 -X 8,9,10,11,12 -P - - - - Run_Physim - Run nr_dlsim with T2 LDPC offload: SNR = 30, MCS = 15, 273 PRBs, 1 layer - true - caracal - nr_dlsim - 250 - -n1000 -s30 -S30.2 -e15 -b273 -R273 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 - - - - Run_Physim - Run nr_dlsim with CPU: SNR = 30, MCS = 25, 273 PRBs, 1 layer - true - caracal - nr_dlsim - 400 - -n1000 -s30 -S30.2 -e25 -b273 -R273 -X 8,9,10,11,12 -P - - - - Run_Physim - Run nr_dlsim with T2 LDPC offload: SNR = 30, MCS = 25, 273 PRBs, 1 layer - true - caracal - nr_dlsim - 400 - -n1000 -s30 -S30.2 -e25 -b273 -R273 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 - - - - Run_Physim - Run nr_dlsim with CPU: SNR = 30, MCS = 5, 273 PRBs, 2 layers - true - caracal - nr_dlsim - 400 - -n1000 -s30 -S30.2 -e5 -b273 -R273 -X 8,9,10,11,12 -x2 -z2 -y2 -P - - - - Run_Physim - Run nr_dlsim with T2 LDPC offload: SNR = 30, MCS = 5, 273 PRBs, 2 layers - true - caracal - nr_dlsim - 200 - -n1000 -s30 -S30.2 -e5 -b273 -R273 -X4,5,6,7,8,9 -x2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 - - - - Run_Physim - Run nr_dlsim with CPU: SNR = 30, MCS = 15, 273 PRBs, 2 layers - true - caracal - nr_dlsim - 450 - -n1000 -s30 -S30.2 -e15 -b273 -R273 -X 8,9,10,11,12 -x2 -z2 -y2 -P - - - - Run_Physim - Run nr_dlsim with T2 LDPC offload: SNR = 30, MCS = 15, 273 PRBs, 2 layers - true - caracal - nr_dlsim - 500 - -n1000 -s30 -S30.2 -e15 -b273 -R273 -X4,5,6,7,8,9 -x2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 - - - - Run_Physim - Run nr_dlsim with CPU: SNR = 30, MCS = 25, 273 PRBs, 2 layers - true - caracal - nr_dlsim - 500 - -n1000 -s30 -S30.2 -e25 -b273 -R273 -X 8,9,10,11,12 -x2 -z2 -y2 -P - - - - Run_Physim - Run nr_dlsim with T2 LDPC offload: SNR = 30, MCS = 25, 273 PRBs, 2 layers - true - caracal - nr_dlsim - 500 - -n1000 -s30 -S30.2 -e25 -b273 -R273 -X4,5,6,7,8,9 -x2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 - - - - Run_Physim - Run nr_dlsim with CPU: SNR = 30, MCS = 5, 273 PRBs, 2 layers, 4 antennas - true - caracal - nr_dlsim - 400 - -n1000 -s30 -S30.2 -e5 -b273 -R273 -X8,9,10,11,12 -x2 -z4 -y4 -P - - - - Run_Physim - Run nr_dlsim with T2 LDPC offload: SNR = 30, MCS = 5, 273 PRBs, 2 layers, 4 antennas - true - caracal - nr_dlsim - 200 - -n1000 -s30 -S30.2 -e5 -b273 -R273 -X4,5,6,7,8,9 -x2 -z4 -y4 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 - - - - Run_Physim - Run nr_dlsim with CPU: SNR = 30, MCS = 20, 273 PRBs, 2 layers, 4 antennas - true - caracal - nr_dlsim - 400 - -n1000 -s30 -S30.2 -e15 -b273 -R273 -X8,9,10,11,12 -x2 -z4 -y4 -P - - - - Run_Physim - Run nr_dlsim with T2 LDPC offload: SNR = 30, MCS = 20, 273 PRBs, 2 layers, 4 antennas - true - caracal - nr_dlsim - 300 - -n1000 -s30 -S30.2 -e15 -b273 -R273 -X4,5,6,7,8,9 -x2 -z4 -y4 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 - - - - Run_Physim - Run nr_dlsim with CPU: SNR = 30, MCS = 27, 273 PRBs, 2 layers, 4 antennas - true - caracal - nr_dlsim - 450 - -n1000 -s30 -S30.2 -e25 -b273 -R273 -X8,9,10,11,12 -x2 -z4 -y4 -P - - - - Run_Physim - Run nr_dlsim with T2 LDPC offload: SNR = 30, MCS = 27, 273 PRBs, 2 layers, 4 antennas - true - caracal - nr_dlsim - 450 - -n1000 -s30 -S30.2 -e25 -b273 -R273 -X4,5,6,7,8,9 -x2 -z4 -y4 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1 - - From e824a6373de205a706b638dacd4ff729f55f0608 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sat, 6 Sep 2025 16:33:04 +0200 Subject: [PATCH 678/964] Rename to analyze_physim() --- ci-scripts/cls_analysis.py | 2 +- ci-scripts/cls_oaicitest.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ci-scripts/cls_analysis.py b/ci-scripts/cls_analysis.py index 09848a6972..240a89dc16 100644 --- a/ci-scripts/cls_analysis.py +++ b/ci-scripts/cls_analysis.py @@ -28,7 +28,7 @@ import json class Analysis(): - def analyze_oc_physim(result_junit, details_json, logPath): + def analyze_physim(result_junit, details_json, logPath): try: tree = ET.parse(result_junit) root = tree.getroot() diff --git a/ci-scripts/cls_oaicitest.py b/ci-scripts/cls_oaicitest.py index ba0ce0d9e8..8dc4ae3a6f 100644 --- a/ci-scripts/cls_oaicitest.py +++ b/ci-scripts/cls_oaicitest.py @@ -264,7 +264,7 @@ def Deploy_Physim(ctx, HTML, node, workdir, script, options): archiveArtifact(ssh, ctx, f'{workdir}/physim_log.txt') archiveArtifact(ssh, ctx, f'{workdir}/LastTestsFailed.log') archiveArtifact(ssh, ctx, f'{workdir}/LastTest.log') - test_status, test_summary, test_result = cls_analysis.Analysis.analyze_oc_physim(result_junit, details_json, ctx.logPath) + test_status, test_summary, test_result = cls_analysis.Analysis.analyze_physim(result_junit, details_json, ctx.logPath) if test_summary: if test_status: HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) From 15befb41e666f808c9b39722f34ddd69a7c4bcd1 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 8 Sep 2025 11:44:55 +0200 Subject: [PATCH 679/964] Physim deploy(): add deployment timeout --- ci-scripts/scripts/oc-deploy-physims.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci-scripts/scripts/oc-deploy-physims.sh b/ci-scripts/scripts/oc-deploy-physims.sh index 953e541770..c209be485b 100755 --- a/ci-scripts/scripts/oc-deploy-physims.sh +++ b/ci-scripts/scripts/oc-deploy-physims.sh @@ -13,7 +13,7 @@ OAI_DIR=${4} cat /opt/oc-password | oc login -u oaicicd --server https://api.oai.cs.eurecom.fr:6443 > /dev/null oc project ${OC_NS} > /dev/null oc tag oaicicd-ran/oai-physim:${IMG_TAG} ${OC_NS}/oai-physim:${IMG_TAG} -helm install ${OC_RELEASE} ${OAI_DIR}/charts/${OC_RELEASE} --set global.image.version=${IMG_TAG} --wait +helm install ${OC_RELEASE} ${OAI_DIR}/charts/${OC_RELEASE} --set global.image.version=${IMG_TAG} --wait --timeout 120s POD_ID=$(oc get pods | grep oai-${OC_RELEASE} | awk '{print $1}') sleep 10 echo "Monitoring logs for 'FINISHED' in pod '$POD_ID'" From e5139b6f0fbc2a3bea76461bdd07bd7824b82e2c Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 8 Sep 2025 14:40:30 +0200 Subject: [PATCH 680/964] Put physim status info in separate box A follow-up commit will introduce a change to print timing logs in the HTML (if present in the test). Prepare for this with separate box. --- ci-scripts/cls_oai_html.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci-scripts/cls_oai_html.py b/ci-scripts/cls_oai_html.py index 7daa3e9321..cb1ca56542 100644 --- a/ci-scripts/cls_oai_html.py +++ b/ci-scripts/cls_oai_html.py @@ -533,6 +533,6 @@ class HTMLManagement(): self.htmlFile.write(' ' + value[2] + '\n') else: self.htmlFile.write(' ' + value[2] + '\n') - self.htmlFile.write(' ' + value[1] + '\n') + self.htmlFile.write(f'
{value[1]}
\n') self.htmlFile.close() From eb9e4ef9ba1b92f4ad71e56970652e8270b61b2a Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 8 Sep 2025 14:42:07 +0200 Subject: [PATCH 681/964] Pass CTest test description in custom property or environment Prior to this change, each test would have, as label, it's description. This leads to many labels, which are normally reserved for grouping tests. Move the description into a custom property instead. Since we rely on the JSON output for the generation of HTML reports, we need to also extract the description from the generated JSON. However, custom properties are only logged starting from cmake 3.30. For back-wards compatibility, write an additional, separate environment variable TEST_DESCRIPTION from which the description can be read as a fallback. For the add_timed_physim_test(), this has been already done in a parent commit. --- ci-scripts/cls_analysis.py | 19 ++++++++++++++++++- openair1/SIMULATION/tests/CMakeLists.txt | 10 ++++++++-- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/ci-scripts/cls_analysis.py b/ci-scripts/cls_analysis.py index 240a89dc16..46b32bf449 100644 --- a/ci-scripts/cls_analysis.py +++ b/ci-scripts/cls_analysis.py @@ -28,6 +28,23 @@ import json class Analysis(): + def _get_test_description(properties): + env_vars = None + for p in properties: + if p["name"] == "ENVIRONMENT": + env_vars = p["value"] # save for later if no custom property + if p["name"] == "TEST_DESCRIPTION": + return p["value"] + # if we came till here, it means there is no custom test property + # saved in JSON. See if we have a description in environment variables + if not env_vars: + return "" + for ev in env_vars: + name, value = ev.split("=", 1) + if name == "TEST_DESCRIPTION": + return value + return "" + def analyze_physim(result_junit, details_json, logPath): try: tree = ET.parse(result_junit) @@ -60,7 +77,7 @@ class Analysis(): for test in root: # for each test test_name = test.attrib["name"] test_exec = json_test_desc[test_name]["properties"][1]["value"][0] - desc = json_test_desc[test_name]["properties"][1]["value"][1] + desc = Analysis._get_test_description(json_test_desc[test_name]["properties"]) # get runtime and checks test_check = test.attrib["status"] == "run" time = round(float(test.attrib["time"]), 1) diff --git a/openair1/SIMULATION/tests/CMakeLists.txt b/openair1/SIMULATION/tests/CMakeLists.txt index d71df315bb..273142a1d7 100644 --- a/openair1/SIMULATION/tests/CMakeLists.txt +++ b/openair1/SIMULATION/tests/CMakeLists.txt @@ -1,3 +1,5 @@ +define_property(TEST PROPERTY TEST_DESCRIPTION BRIEF_DOCS "A human-readable description of this test") + # Define a macro to add tests for different physical simulators macro(add_physim_test test_name test_description test_exec) # catch all the arguments past the last expected arqument and store them in the options_list @@ -11,8 +13,12 @@ macro(add_physim_test test_name test_description test_exec) COMMAND_EXPAND_LISTS ) set_tests_properties(${test_name} PROPERTIES - LABELS "${test_exec}: ${test_description};${test_exec}" - ENVIRONMENT "LD_LIBRARY_PATH=." + LABELS "${test_exec}" + TEST_DESCRIPTION "${test_description}" + # pass test description also through environment variable: for cmake < 3.30, + # in JSON export, we cannot recover the description otherwise + # see also https://gitlab.kitware.com/cmake/cmake/-/issues/21490 + ENVIRONMENT "LD_LIBRARY_PATH=.;TEST_DESCRIPTION=${test_description}" ) add_dependencies(tests ${test_exec}) endmacro() From 5beb8bf3143ac4897ebc337897f655eadfa99b29 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 8 Sep 2025 12:09:08 +0200 Subject: [PATCH 682/964] Print results of physims Remove the runtime, which is not interesting, and add instead - test name and if the test failed - the threshold checks, if any, and - possible additional information about test failures. --- ci-scripts/cls_analysis.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/ci-scripts/cls_analysis.py b/ci-scripts/cls_analysis.py index 46b32bf449..588490da62 100644 --- a/ci-scripts/cls_analysis.py +++ b/ci-scripts/cls_analysis.py @@ -90,13 +90,16 @@ class Analysis(): with open(f'{log_dir}/{test_name}.log', 'w') as f: f.write(output) # prepare result and info - info = f"Runtime: {f'{time:.3f}'[:5]} s" resultstr = 'PASS' if (test_check and time_check and output_check) else 'FAIL' + info = f"{test_name}.log: test {resultstr}" + for l in output.splitlines(): + if l.startswith("CHECK "): + info += f"\n{l}" if test_check: if not output_check: - info += " Test log exceeds maximal allowed length 100 kB" + info += "\nTest log exceeds maximal allowed length 100 kB" if not time_check: - info += " Test exceeds 150s" + info += "\nTest exceeds 150s" if not (time_check and output_check): nb_failed += 1 # time threshold/output length error, not counted for by ctest as of now test_result[test_name] = [desc, info, resultstr] From 998018db5003ca848e3dda9578b918b224cf4122 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 8 Sep 2025 19:06:10 +0200 Subject: [PATCH 683/964] Slight restructuring of the physim doc Move info about pipelines to the introduction instead of somewhere in the middle. Add some filler text, and fix indentation headings. --- doc/physical-simulators.md | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/doc/physical-simulators.md b/doc/physical-simulators.md index cd573a8686..32b4979798 100644 --- a/doc/physical-simulators.md +++ b/doc/physical-simulators.md @@ -18,6 +18,12 @@ Physims are essential for: * Regression testing * Ensuring correctness before merging new contributions into the repository +These tests are run automatically as part of the following +pipelines: + +- [RAN-PhySim-Cluster-4G](https://jenkins-oai.eurecom.fr/job/RAN-PhySim-Cluster-4G/) +- [RAN-PhySim-Cluster-5G](https://jenkins-oai.eurecom.fr/job/RAN-PhySim-Cluster-5G/) + ## Examples of Simulators | Technology | Simulators | Description | @@ -31,7 +37,7 @@ Physims are essential for: | | `nr_psbchsim` | Sidelink simulation | | Coding | `ldpctest`, `polartest`, `smallblocktest` | LDPC, Polar, and other FEC tests | -### Source Locations +## Source Locations * 4G PHY simulators: `openair1/SIMULATION/LTE_PHY/` * 5G PHY simulators: `openair1/SIMULATION/NR_PHY/` @@ -48,6 +54,9 @@ openair1/SIMULATION/NR_PHY/dlsim.c ## Option 1: Using CMake +Build the simulators and tests using the dedicated cmake option, then run +`ctest` which will run all registered tests. + ```bash cd openairinterface5g mkdir build && cd build @@ -67,9 +76,7 @@ cd ran_build/build ctest ``` -# `ctest` Usage Tips - -## Useful Options +## `ctest` Usage Tips Use the following options to customize test execution: @@ -84,16 +91,12 @@ Use the following options to customize test execution: For the complete list of `ctest` options, refer to the manual: -```bash -man ctest -``` + man ctest -## Example +For instance, to run only all run NR ULSCH simulator tests, with 4 jobs in +parallel, type -```bash -# Run only NR ULSCH simulator tests, in parallel -ctest -L nr_ulsch -j 4 -``` + ctest -L nr_ulschsim -j 4 # Adding a New Physim Test @@ -121,9 +124,6 @@ For instance, a PRACHsim looks like this: add_physim_test(physim.5g.nr_prachsim.test8 "15kHz SCS, 25 PRBs" nr_prachsim -a -s -30 -n 300 -p 99 -R 25 -m 0) -These tests are run automatically as part of the following -pipelines: [RAN-PhySim-Cluster-4G](https://jenkins-oai.eurecom.fr/job/RAN-PhySim-Cluster-4G/) and [RAN-PhySim-Cluster-5G](https://jenkins-oai.eurecom.fr/job/RAN-PhySim-Cluster-5G/) - ## `add_timed_physim_test()` Use the `add_timed_physim_test()` macro to add a test the same way as with @@ -161,7 +161,7 @@ For instance, this could look like this: add_timed_physim_test(physim.5g.nr_dlsim.test3 "Some description" nr_dlsim -P) check_physim_threshold(physim.5g.nr_dlsim.test3 "DLSCH encoding time" "< 50") -### How to rerun failed CI tests using `ctest` +# How to rerun failed CI tests using `ctest` Ctest automatically logs the failed tests in LastTestsFailed.log. This log is archived in the CI artifacts and can be reused locally to rerun only those failed tests. From 31aaa4ed3ff788e8af09c9cc2df0f02acecfbec5 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 12 Sep 2025 09:57:10 +0200 Subject: [PATCH 684/964] Add PhySim-GraceHopper-5G to test pipelines --- ci-scripts/Jenkinsfile-GitLab-Container | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/ci-scripts/Jenkinsfile-GitLab-Container b/ci-scripts/Jenkinsfile-GitLab-Container index f2a84fbd91..03dedbd339 100644 --- a/ci-scripts/Jenkinsfile-GitLab-Container +++ b/ci-scripts/Jenkinsfile-GitLab-Container @@ -269,6 +269,29 @@ pipeline { } } } + stage ("PhySim-GraceHopper-5G") { + when { expression {do5Gtest || do5GUeTest} } + steps { + script { + triggerSlaveJob ('RAN-PhySim-GraceHopper-5G', 'PhySim-GraceHopper-5G') + } + } + post { + always { + script { + // Using a unique variable name for each test stage to avoid overwriting on a global variable + // due to parallel-time concurrency + physimGH5GStatus = finalizeSlaveJob('RAN-PhySim-GraceHopper-5G') + } + } + failure { + script { + currentBuild.result = 'FAILURE' + failingStages += physimGH5GStatus + } + } + } + } stage ("PhySim-Cluster-4G") { when { expression {do4Gtest} } steps { From 8ca1d0d38db73a9467e43b5fdbe880d9a4df8db0 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 12 Sep 2025 15:00:15 +0200 Subject: [PATCH 685/964] Doc: Add PhySim-Gracehopper and update existing PhySim-Cluster --- doc/TESTBenches.md | 15 +++++++++++---- doc/physical-simulators.md | 1 + 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/doc/TESTBenches.md b/doc/TESTBenches.md index f6a77c2d09..d7881fb993 100644 --- a/doc/TESTBenches.md +++ b/doc/TESTBenches.md @@ -172,10 +172,17 @@ information on how the images are built. ~4G-LTE ~5G-NR - nepes + B200 (eNB), ofqot + B200 (gNB), idefix + Quectel, nepes w/ ltebox - basic NSA test -- [RAN-PhySim-Cluster](https://jenkins-oai.eurecom.fr/job/RAN-PhySim-Cluster/) - ~4G-LTE ~5G-NR ~nrUE - - cluster (`RAN_OC` resource), tests in OpenShift Cluster - - unitary simulators (`nr_dlsim`, etc.) +- [RAN-PhySim-Cluster-4G](https://jenkins-oai.eurecom.fr/job/RAN-PhySim-Cluster-4G/) + ~4G-LTE + - tests 4G physical simulators (`nr_dlsim`, etc.) in OpenShift Cluster (x86) + - see [`./physical-simulators.md`](./physical-simulators.md) for an overview +- [RAN-PhySim-Cluster-5G](https://jenkins-oai.eurecom.fr/job/RAN-PhySim-Cluster-5G/) + ~5G-NR ~nrUE + - tests 5G physical simulators (`nr_dlsim`, etc.) in OpenShift Cluster (x86) + - see [`./physical-simulators.md`](./physical-simulators.md) for an overview +- [RAN-PhySim-GraceHopper-5G](https://jenkins-oai.eurecom.fr/job/RAN-PhySim-GraceHopper-5G/) + ~5G-NR ~nrUE + - tests 5G physical simulators (`nr_dlsim`, etc.) on Nvidia GraceHopper (ARMv9) - see [`./physical-simulators.md`](./physical-simulators.md) for an overview - [RAN-RF-Sim-Test-4G](https://jenkins-oai.eurecom.fr/job/RAN-RF-Sim-Test-4G/) ~4G-LTE diff --git a/doc/physical-simulators.md b/doc/physical-simulators.md index 32b4979798..b74531fd20 100644 --- a/doc/physical-simulators.md +++ b/doc/physical-simulators.md @@ -23,6 +23,7 @@ pipelines: - [RAN-PhySim-Cluster-4G](https://jenkins-oai.eurecom.fr/job/RAN-PhySim-Cluster-4G/) - [RAN-PhySim-Cluster-5G](https://jenkins-oai.eurecom.fr/job/RAN-PhySim-Cluster-5G/) +- [RAN-PhySim-GraceHopper-5G](https://jenkins-oai.eurecom.fr/job/RAN-PhySim-GraceHopper-5G/) ## Examples of Simulators From 40fd22e26a09ba37176bc95955634ff19c7cd4d9 Mon Sep 17 00:00:00 2001 From: Leonardo Bonati Date: Fri, 12 Sep 2025 08:24:25 -0400 Subject: [PATCH 686/964] Fix memory allocation issue in KPM RAN function sd parameter handling --- openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c index fd6578b3b2..aa68ba7d9d 100644 --- a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c +++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c @@ -170,7 +170,7 @@ static void capture_sst_sd(test_cond_value_t* test_cond_value, uint8_t *sst, uin DevAssert(test_cond_value->octet_string_value->len == 4); uint8_t *buf = test_cond_value->octet_string_value->buf; *sst = buf[0]; - *sd = malloc(**sd); + *sd = malloc(sizeof(uint32_t)); **sd = buf[1] << 16 | buf[2] << 8 | buf[3]; } printf("[E2 AGENT][E2SM-KPM] Condition NSSAI (%d, %x).\n", *sst, (*sd) ? **sd : 0xffffff); From 166589c2ef867a37104cdd0a7c82e599bb0683fb Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 12 Sep 2025 18:47:02 +0200 Subject: [PATCH 687/964] Add bands for neighbour configuration in HO CI pipeline Since !3531, the band is mandatory in a neighbour configuration. See also: fd4de3c720b0 ("Add support for band in neighbourConfiguration") --- ci-scripts/conf_files/neighbour-config-ho.conf | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ci-scripts/conf_files/neighbour-config-ho.conf b/ci-scripts/conf_files/neighbour-config-ho.conf index 82d4a8472c..f9d1e38ee0 100644 --- a/ci-scripts/conf_files/neighbour-config-ho.conf +++ b/ci-scripts/conf_files/neighbour-config-ho.conf @@ -8,6 +8,7 @@ neighbour_list = ( physical_cellId = 1; absoluteFrequencySSB = 629376; subcarrierSpacing = 1; #30 KHz + band = 78; plmn = { mcc = 001; mnc = 03; mnc_length = 2}; tracking_area_code = 1; } @@ -22,6 +23,7 @@ neighbour_list = ( physical_cellId = 0; absoluteFrequencySSB = 629376; subcarrierSpacing = 1; #30 KHz + band = 78; plmn = { mcc = 001; mnc = 03; mnc_length = 2}; tracking_area_code = 1; } From 9f97320cbe9a26bff23fa24781715e74c0e74082 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 20 Aug 2025 19:07:06 +0200 Subject: [PATCH 688/964] HO Preparation: calloc pdcp_config in DRB to Modify Item decoding The malloced struct is initialized to garbage and when the IE is absent, the output "PDCP reestablishment" member (allocated in the stack) is set to a random value. --- openair2/E1AP/lib/e1ap_bearer_context_management.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair2/E1AP/lib/e1ap_bearer_context_management.c b/openair2/E1AP/lib/e1ap_bearer_context_management.c index 2c4f938a24..f9afa06f69 100644 --- a/openair2/E1AP/lib/e1ap_bearer_context_management.c +++ b/openair2/E1AP/lib/e1ap_bearer_context_management.c @@ -1658,7 +1658,7 @@ static bool e1_decode_pdu_session_to_mod_item(pdu_session_to_mod_t *out, const E drb->id = drb2Mod->dRB_ID; // PDCP Config (O) if (drb2Mod->pDCP_Configuration) { - drb->pdcp_config = malloc_or_fail(sizeof(*drb->pdcp_config)); + drb->pdcp_config = calloc_or_fail(1, sizeof(*drb->pdcp_config)); CHECK_E1AP_DEC(e1_decode_pdcp_config(drb->pdcp_config, drb2Mod->pDCP_Configuration)); } // SDAP Config (O) From 956d30f4e139be730d4cab09d59f69cd82381dda Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Thu, 12 Jun 2025 22:46:08 +0200 Subject: [PATCH 689/964] HO preparation: fix PLMN type in nr_neighbour_cell_t During the review of the N2 HO MR it has been found that the wrong type plmn_identity_t (S1AP) was used in RRC. Now updated to the platform type plmn_id_t. --- openair2/RRC/NR/nr_rrc_defs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index f1d9acba7b..f670dc4f86 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -315,7 +315,7 @@ typedef struct { int absoluteFrequencySSB; int subcarrierSpacing; int band; - plmn_identity_t plmn; + plmn_id_t plmn; uint32_t tac; bool isIntraFrequencyNeighbour; } nr_neighbour_cell_t; From 0a796ebb6cbd55d18dbc57f96860ad43706e67d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Soares=20Silva?= Date: Thu, 11 Sep 2025 09:40:46 +0100 Subject: [PATCH 690/964] Fix ERROR.indication unpack function Fix an issue in which the unpacking is erroneously deemed unsuccessful even though it succeed in pulling all the bytes, this was due to not properly handling the return value of pull16 which is either 0 or 2, not 0 or 1. Check the results of push and pull operation with correct boolean operator. --- nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c | 27 +++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c index a7cb729f6c..4bcc9b2a44 100644 --- a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c +++ b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c @@ -1866,22 +1866,23 @@ uint8_t unpack_nr_stop_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void uint8_t pack_nr_error_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { nfapi_nr_error_indication_scf_t *pNfapiMsg = (nfapi_nr_error_indication_scf_t *)msg; - uint8_t retval = push16(pNfapiMsg->sfn, ppWritePackedMsg, end) != 0; - retval &= push16(pNfapiMsg->slot, ppWritePackedMsg, end) != 0; - retval &= push8(pNfapiMsg->message_id, ppWritePackedMsg, end); - retval &= push8(pNfapiMsg->error_code, ppWritePackedMsg, end); - - retval &= pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config); - return retval; + if (push16(pNfapiMsg->sfn, ppWritePackedMsg, end) && push16(pNfapiMsg->slot, ppWritePackedMsg, end) + && push8(pNfapiMsg->message_id, ppWritePackedMsg, end) && push8(pNfapiMsg->error_code, ppWritePackedMsg, end) + && pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)) { + return 1; + } else { + return 0; + } } uint8_t unpack_nr_error_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { nfapi_nr_error_indication_scf_t *pNfapiMsg = (nfapi_nr_error_indication_scf_t *)msg; - uint8_t retval = pull16(ppReadPackedMsg, &pNfapiMsg->sfn, end); - retval &= pull16(ppReadPackedMsg, &pNfapiMsg->slot, end); - retval &= pull8(ppReadPackedMsg, &pNfapiMsg->message_id, end); - retval &= pull8(ppReadPackedMsg, &pNfapiMsg->error_code, end); - retval &= unpack_nr_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)); - return retval; + if (pull16(ppReadPackedMsg, &pNfapiMsg->sfn, end) && pull16(ppReadPackedMsg, &pNfapiMsg->slot, end) + && pull8(ppReadPackedMsg, &pNfapiMsg->message_id, end) && pull8(ppReadPackedMsg, &pNfapiMsg->error_code, end) + && unpack_nr_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension))) { + return 1; + } else { + return 0; + } } From 6ff098e0bd56653759df060c81e812eb9fa341c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Soares=20Silva?= Date: Wed, 10 Sep 2025 16:20:12 +0100 Subject: [PATCH 691/964] Add Aerial-specific ERROR.indication codes This adds the expectable error codes from Aerial L1, as described in https://docs.nvidia.com/aerial/archive/aerial-sdk/23-3/text/cubb_release_notes/scf_fapi_support.html#additional-aerial-specific-error-codes-reported-in-error-indication-from-l1-to-l2 The errors are added in such a way that they're only visible when compiled with Aerial --- .../nfapi/public_inc/nfapi_nr_interface_scf.h | 43 ++++++++++++++----- 1 file changed, 33 insertions(+), 10 deletions(-) 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 f186352b6d..fc45a620d2 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 @@ -707,18 +707,41 @@ typedef enum { NFAPI_NR_STOP_MSG_INVALID_STATE } nfapi_nr_stop_errors_e; -//3.3.5 PHY Notifications +// 3.3.5 PHY Notifications + +#define SCF_ERROR_LIST \ + X(NFAPI_NR_PHY_API_MSG_OK, 0x0) \ + X(NFAPI_NR_PHY_API_MSG_INVALID_STATE, 0x1) \ + X(NFAPI_NR_PHY_API_MSG_INVALID_CONFIG, 0x2) \ + X(NFAPI_NR_PHY_API_SFN_OUT_OF_SYNC, 0X3) \ + X(NFAPI_NR_PHY_API_MSG_SLOR_ERR, 0X4) \ + X(NFAPI_NR_PHY_API_MSG_BCH_MISSING, 0X5) \ + X(NFAPI_NR_PHY_API_MSG_INVALID_SFN, 0X6) \ + X(NFAPI_NR_PHY_API_MSG_UL_DCI_ERR, 0X7) \ + X(NFAPI_NR_PHY_API_MSG_TX_ERR, 0X8) + +#ifdef ENABLE_AERIAL +#define AERIAL_ERROR_LIST \ + X(AERIAL_ERROR_CODE_FAPI_END, 0x32) \ + X(AERIAL_ERROR_CODE_L1_PROC_OBJ_UNAVAILABLE_ERR, 0x33) \ + X(AERIAL_ERROR_CODE_MSG_LATE_SLOT_ERR, 0x34) \ + X(AERIAL_ERROR_CODE_PARTIAL_SRS_IND_ERR, 0x35) \ + X(AERIAL_ERROR_CODE_L1_DL_CPLANE_TX_ERROR, 0x36) \ + X(AERIAL_ERROR_CODE_L1_UL_CPLANE_TX_ERROR, 0x37) \ + X(AERIAL_ERROR_CODE_L1_DL_GPU_ERROR, 0x38) \ + X(AERIAL_ERROR_CODE_L1_DL_CPU_TASK_ERROR, 0x39) \ + X(AERIAL_ERROR_CODE_L1_UL_CPU_TASK_ERROR, 0x3A) \ + X(AERIAL_ERROR_CODE_L1_P1_EXIT_ERROR, 0x3B) \ + X(AERIAL_ERROR_CODE_L1_P2_EXIT_ERROR, 0x3C) \ + X(AERIAL_ERROR_CODE_L1_DL_CH_ERROR, 0x3D) \ + X(AERIAL_ERROR_CODE_L1_UL_CH_ERROR, 0x3E) +#else +#define AERIAL_ERROR_LIST +#endif #define NFAPI_PHY_ERROR_LIST \ -X(NFAPI_NR_PHY_API_MSG_OK ,0x0)\ -X(NFAPI_NR_PHY_API_MSG_INVALID_STATE ,0x1)\ -X(NFAPI_NR_PHY_API_MSG_INVALID_CONFIG ,0x2)\ -X(NFAPI_NR_PHY_API_SFN_OUT_OF_SYNC ,0X3)\ -X(NFAPI_NR_PHY_API_MSG_SLOR_ERR ,0X4)\ -X(NFAPI_NR_PHY_API_MSG_BCH_MISSING ,0X5)\ -X(NFAPI_NR_PHY_API_MSG_INVALID_SFN ,0X6)\ -X(NFAPI_NR_PHY_API_MSG_UL_DCI_ERR ,0X7)\ -X(NFAPI_NR_PHY_API_MSG_TX_ERR ,0X8) + SCF_ERROR_LIST \ + AERIAL_ERROR_LIST typedef enum { #define X(name, value) name = value, From 524aa84e966f98f6eb6ed915683a68b5d5a645b8 Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Mon, 4 Aug 2025 19:26:02 -0400 Subject: [PATCH 692/964] fix: issue 954 - DCI monitoring after RRC setup After the UE is configured with pdcch-Config, it continues to monitor fallback search spaces in pdcch-ConfigCommon for DCI with C-RNTI. The rational is that after sending RRC Setup the network won't know if the UE has received and successfully applied it. Hence the network would still continue to use the fallback DCI till it receives RRC setup complete. --- .../NR_MAC_UE/nr_ue_dci_configuration.c | 41 +++++++++++++++---- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c index 7a2e9c6ed9..d45cfe8dc1 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c @@ -502,19 +502,42 @@ void ue_dci_configuration(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_request_t *dl config_dci_pdu(mac, dl_config, rnti_type, slot, ra_SS); } } else if (mac->state == UE_CONNECTED) { + /* + In RRC Connected state, the UE monitors for fallback DCI with C-RNTI in common and UE-specific SS. + First the UE check all UE specific SS. If no fallback DCI is configured, it configures one of following + common SS with the shown priority + 1. RA SS + 2. Other SI SS + 3. Paging SS + 4. SIB1 SS + + There is a possibility that gNB could configure multiple UE-specific SS for fallback DCI or/and common SS, + and in a given slot more than one SS become active. For the moment, we assume such configuration wouldn't happen + and hence don't handle it for the sake of implementation simplicity. + */ + bool configured_fallback_dci = false; for (int i = 0; i < pdcch_config->list_SS.count; i++) { NR_SearchSpace_t *ss = pdcch_config->list_SS.array[i]; - if (is_ss_monitor_occasion(frame, slot, slots_per_frame, ss)) + if (is_ss_monitor_occasion(frame, slot, slots_per_frame, ss)) { config_dci_pdu(mac, dl_config, TYPE_C_RNTI_, slot, ss); + configured_fallback_dci |= (ss->searchSpaceType->present == NR_SearchSpace__searchSpaceType_PR_common); + } } - const NR_SearchSpace_t *ra_SS = get_common_search_space(mac, pdcch_config->ra_SS_id); - if (pdcch_config->list_SS.count == 0 && ra_SS) { - // If the UE has not been provided a Type3-PDCCH CSS set or a USS set and - // the UE has received a C-RNTI and has been provided a Type1-PDCCH CSS set, - // the UE monitors PDCCH candidates for DCI format 0_0 and DCI format 1_0 - // with CRC scrambled by the C-RNTI in the Type1-PDCCH CSS set - if (is_ss_monitor_occasion(frame, slot, slots_per_frame, ra_SS)) - config_dci_pdu(mac, dl_config, TYPE_C_RNTI_, slot, ra_SS); + const NR_SearchSpace_t *css = NULL; + if (!configured_fallback_dci) { +#define CSS_VALID_CUR_SLOT(CSS) \ + ((CSS > -1) && is_ss_monitor_occasion(frame, slot, slots_per_frame, get_common_search_space(mac, CSS))) + if (CSS_VALID_CUR_SLOT(pdcch_config->ra_SS_id)) + css = get_common_search_space(mac, pdcch_config->ra_SS_id); + else if (CSS_VALID_CUR_SLOT(pdcch_config->otherSI_SS_id)) + css = get_common_search_space(mac, pdcch_config->otherSI_SS_id); + else if (CSS_VALID_CUR_SLOT(pdcch_config->paging_SS_id)) + css = get_common_search_space(mac, pdcch_config->paging_SS_id); +#undef CSS_VALID_CUR_SLOT + else + css = mac->search_space_zero; + AssertFatal(css, "Atleast one CSS should be present in connected state\n"); + config_dci_pdu(mac, dl_config, TYPE_C_RNTI_, slot, css); } } } From e0b5880db7406ef4af08fac242e588db98d0de26 Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 9 Sep 2025 18:54:33 +0200 Subject: [PATCH 693/964] cleanup NR_UL_UE_HARQ_t --- openair1/PHY/INIT/nr_init_ue.c | 1 - openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h | 17 ----------------- 2 files changed, 18 deletions(-) diff --git a/openair1/PHY/INIT/nr_init_ue.c b/openair1/PHY/INIT/nr_init_ue.c index 54a80124f3..e617b08172 100644 --- a/openair1/PHY/INIT/nr_init_ue.c +++ b/openair1/PHY/INIT/nr_init_ue.c @@ -484,7 +484,6 @@ void clean_UE_harq(PHY_VARS_NR_UE *UE) } for (int harq_pid = 0; harq_pid < NR_MAX_ULSCH_HARQ_PROCESSES; harq_pid++) { NR_UL_UE_HARQ_t *ul_harq_process = &UE->ul_harq_processes[harq_pid]; - ul_harq_process->tx_status = NEW_TRANSMISSION_HARQ; ul_harq_process->round = 0; } } diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h index ce7f41d2b9..c63754b583 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h @@ -38,18 +38,7 @@ #include "nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h" #include "../NR_TRANSPORT/nr_transport_common_proto.h" -typedef enum { - NEW_TRANSMISSION_HARQ, - RETRANSMISSION_HARQ -} harq_result_t; - typedef struct { - /// HARQ tx status - harq_result_t tx_status; - /// Last TPC command - uint8_t TPC; - /// Length of ACK information (bits) - uint8_t O_ACK; /// Index of current HARQ round for this ULSCH uint8_t round; /// pointer to pdu from MAC interface (TS 36.212 V15.4.0, Sec 5.1 p. 8) @@ -66,14 +55,8 @@ typedef struct { uint32_t C; /// Number of bits in code segments uint32_t K; - /// Total number of bits across all segments - uint32_t sumKr; /// Number of "Filler" bits uint32_t F; - /// n_DMRS for cyclic shift of DMRS - uint8_t n_DMRS; - /// n_DMRS2 for cyclic shift of DMRS - uint8_t n_DMRS2; /// Number of soft channel bits uint32_t G; // Number of modulated symbols carrying data From 93f5f6580640447599145b88b777babc04981731 Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 11 Sep 2025 17:57:20 +0200 Subject: [PATCH 694/964] remove --sa command line option from sa_fhi_7.2_metanoia_2x2_gnb docker compose --- .../yaml_files/sa_fhi_7.2_metanoia_2x2_gnb/docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci-scripts/yaml_files/sa_fhi_7.2_metanoia_2x2_gnb/docker-compose.yml b/ci-scripts/yaml_files/sa_fhi_7.2_metanoia_2x2_gnb/docker-compose.yml index 06273747bf..f08859a516 100644 --- a/ci-scripts/yaml_files/sa_fhi_7.2_metanoia_2x2_gnb/docker-compose.yml +++ b/ci-scripts/yaml_files/sa_fhi_7.2_metanoia_2x2_gnb/docker-compose.yml @@ -9,7 +9,7 @@ services: container_name: oai-gnb environment: TZ: Europe/Paris - USE_ADDITIONAL_OPTIONS: --sa --thread-pool 7,8,9,10,11,12 + USE_ADDITIONAL_OPTIONS: --thread-pool 7,8,9,10,11,12 devices: - /dev/vfio:/dev/vfio/ volumes: From b8683dd351d0c87f42b73c1a2e39bb2d47ad9395 Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 11 Sep 2025 18:47:25 +0200 Subject: [PATCH 695/964] check command line for unknown options at gNB --- executables/nr-softmodem.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c index d8df770cb8..0bd583662b 100644 --- a/executables/nr-softmodem.c +++ b/executables/nr-softmodem.c @@ -713,6 +713,11 @@ int main( int argc, char **argv ) { // wait for end of program printf("TYPE TO TERMINATE\n"); + // Sleep a while before checking all parameters have been used + // Some are used directly in external threads, asynchronously + sleep(2); + config_check_unknown_cmdlineopt(uniqCfg, CONFIG_CHECKALLSECTIONS); + itti_wait_tasks_end(NULL); printf("Returned from ITTI signal handler\n"); From fd791568ffc072927c84fa94611526b57dc15a4c Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 11 Sep 2025 18:50:00 +0200 Subject: [PATCH 696/964] change RUNMODEM documentation to reflect --sa not being optional anymore --- doc/RUNMODEM.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/doc/RUNMODEM.md b/doc/RUNMODEM.md index ba2d48be28..6e46a361fe 100644 --- a/doc/RUNMODEM.md +++ b/doc/RUNMODEM.md @@ -85,10 +85,8 @@ The standalone mode is the default mode. Before tag `2024.w45`, the default mode was NSA. Thus, in the past, to run either the gNB or the UE in standalone mode, it was necessary to provide the -`--sa` flag in the command line. This is not necessary anymore; if in doubt, -you can provide `--sa` on the command line. The gNB will ignore this option if -not relevant; the UE might complain that it does not know this option, which -means that standalone is already active. +`--sa` flag in the command line. This is not the case anymore. If provided +the softmodem exits reporting that it does not know this option. The default (SA) mode does the following: - At the gNB: From e99cf956e75e5b56a09696e17ff6ed73130e4eeb Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 16 Sep 2025 10:25:04 +0200 Subject: [PATCH 697/964] remove --sa option from newly created handover test --- ci-scripts/yaml_files/5g_sa_f1_b210_ho/docker-compose.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ci-scripts/yaml_files/5g_sa_f1_b210_ho/docker-compose.yml b/ci-scripts/yaml_files/5g_sa_f1_b210_ho/docker-compose.yml index aaf058a9f7..24a3055701 100644 --- a/ci-scripts/yaml_files/5g_sa_f1_b210_ho/docker-compose.yml +++ b/ci-scripts/yaml_files/5g_sa_f1_b210_ho/docker-compose.yml @@ -7,7 +7,7 @@ services: ulimits: core: -1 # for core dumps environment: - USE_ADDITIONAL_OPTIONS: --telnetsrv --telnetsrv.listenport 9090 --telnetsrv.shrmod ci --sa + USE_ADDITIONAL_OPTIONS: --telnetsrv --telnetsrv.listenport 9090 --telnetsrv.shrmod ci --log_config.global_log_options level,nocolor,utc_time,line_num,function volumes: - ../../conf_files/gnb-cu.sa.f1.ho.conf:/opt/oai-gnb/etc/gnb.conf @@ -37,7 +37,7 @@ services: core: -1 # for core dumps environment: USE_B2XX: 'yes' - USE_ADDITIONAL_OPTIONS: --RUs.[0].sdr_addrs serial=30AD30F --sa + USE_ADDITIONAL_OPTIONS: --RUs.[0].sdr_addrs serial=30AD30F --telnetsrv --telnetsrv.listenport 9091 --telnetsrv.shrmod ci --log_config.global_log_options level,nocolor,utc_time,line_num,function devices: @@ -69,7 +69,7 @@ services: core: -1 # for core dumps environment: USE_B2XX: 'yes' - USE_ADDITIONAL_OPTIONS: --RUs.[0].sdr_addrs serial=31F8010 --sa + USE_ADDITIONAL_OPTIONS: --RUs.[0].sdr_addrs serial=31F8010 --telnetsrv --telnetsrv.listenport 9091 --telnetsrv.shrmod ci --log_config.global_log_options level,nocolor,utc_time,line_num,function devices: From a76f7a8c62cc98a1b14059c73f6563a6877ffd0f Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 16 Sep 2025 11:21:04 +0200 Subject: [PATCH 698/964] remove rfsim option from CU in F1 docker --- ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml b/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml index 18313d0559..94ef3e7868 100644 --- a/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml @@ -100,7 +100,6 @@ services: - SYS_NICE environment: USE_ADDITIONAL_OPTIONS: --log_config.global_log_options level,nocolor,time - --rfsimulator.options chanmod --gNBs.[0].remote_s_address 0.0.0.0 --telnetsrv --telnetsrv.listenaddr 192.168.71.150 --telnetsrv.shrmod ci From 8d6bb6bf2007ca795a1992ab27df6e606944ba32 Mon Sep 17 00:00:00 2001 From: rmagueta Date: Fri, 15 Nov 2024 18:25:07 +0000 Subject: [PATCH 699/964] Definition of L1 and implementation of L3 measurements for serving cell --- common/utils/nr/nr_common.h | 13 +++++ .../nfapi/public_inc/fapi_nr_ue_constants.h | 2 +- .../nfapi/public_inc/fapi_nr_ue_interface.h | 15 +++-- .../PHY/NR_UE_ESTIMATION/nr_ue_measurements.c | 19 ++++++ openair1/PHY/NR_UE_TRANSPORT/csi_rx.c | 28 +++++---- openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 4 +- .../SIMULATION/NR_PHY/nr_unitary_common.c | 9 +++ openair2/COMMON/mac_messages_def.h | 4 ++ openair2/COMMON/mac_messages_types.h | 10 ++++ openair2/LAYER2/NR_MAC_UE/mac_defs.h | 4 +- openair2/LAYER2/NR_MAC_UE/mac_proto.h | 6 +- openair2/LAYER2/NR_MAC_UE/main_ue_nr.c | 2 +- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 58 +++++++++---------- openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c | 20 +++---- openair2/RRC/NR_UE/L2_interface_ue.c | 11 ++++ openair2/RRC/NR_UE/L2_interface_ue.h | 6 ++ openair2/RRC/NR_UE/rrc_UE.c | 53 +++++++++++++++++ openair2/RRC/NR_UE/rrc_defs.h | 10 ++++ 18 files changed, 206 insertions(+), 68 deletions(-) diff --git a/common/utils/nr/nr_common.h b/common/utils/nr/nr_common.h index 6ab3f58dab..67f0913dc4 100644 --- a/common/utils/nr/nr_common.h +++ b/common/utils/nr/nr_common.h @@ -88,6 +88,8 @@ static inline const char *rnti_types(nr_rnti_type_t rr) #define NR_NUMBER_OF_SYMBOLS_PER_SLOT_EXTENDED_CP 12 #define NR_MAX_NB_LAYERS 4 // 8 +#define BOUNDED_EVAL(a, b, c) (min(c, max(a, b))) + // Since the IQ samples are represented by SQ15 R+I (see https://en.wikipedia.org/wiki/Q_(number_format)) we need to compensate when // calcualting signal energy. Instead of shifting each sample right by 15, we can normalize the result in dB scale once its // calcualted. Signal energy is calculated using RMS^2, where each sample is squared before taking the average of the sum, therefore @@ -175,6 +177,17 @@ typedef struct { uint32_t step; } NR_timer_t; +typedef struct val_init { + int val; + bool init; +} val_init_t; + +typedef struct meas_s { + uint16_t Nid_cell; + val_init_t ss_rsrp_dBm; + val_init_t csi_rsrp_dBm; +} meas_t; + /** * @brief To start a timer * @param timer Timer to be started diff --git a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_constants.h b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_constants.h index 37b661afb9..57292ecee5 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_constants.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_constants.h @@ -20,7 +20,7 @@ #define FAPI_NR_RX_PDU_TYPE_DLSCH 0x03 #define FAPI_NR_DCI_IND 0x04 #define FAPI_NR_RX_PDU_TYPE_RAR 0x05 -#define FAPI_NR_CSIRS_IND 0x06 +#define FAPI_NR_MEAS_IND 0x06 #define FAPI_NR_SIBS_MASK_SIB1 0x1 diff --git a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h index 64c8dab07e..a9e83758f6 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h @@ -49,16 +49,23 @@ typedef enum { NFAPI_NR_FORMAT_0_1_AND_1_1, } nfapi_nr_dci_formats_e; +typedef enum { + NFAPI_NR_CSI_MEAS, + NFAPI_NR_SS_MEAS +} nfapi_nr_meas_type_e; typedef struct { - uint32_t rsrp; - int rsrp_dBm; + uint32_t gNB_index; + uint16_t Nid_cell; + nfapi_nr_meas_type_e meas_type; + bool is_neighboring_cell; + uint8_t rsrp_dBm; uint8_t rank_indicator; uint16_t i1; uint8_t i2; uint8_t cqi; rlm_t radiolink_monitoring; -} fapi_nr_csirs_measurements_t; +} fapi_nr_l1_measurements_t; typedef struct { /// frequency_domain_resource; @@ -145,7 +152,7 @@ typedef struct { fapi_nr_pdsch_pdu_t pdsch_pdu; fapi_nr_ssb_pdu_t ssb_pdu; fapi_nr_sib_pdu_t sib_pdu; - fapi_nr_csirs_measurements_t csirs_measurements; + fapi_nr_l1_measurements_t l1_measurements; }; } fapi_nr_rx_indication_body_t; diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c b/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c index 3c9850bd52..825e025308 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c @@ -37,6 +37,7 @@ #include "PHY/phy_extern_nr_ue.h" #include "common/utils/LOG/log.h" #include "PHY/sse_intrin.h" +#include "SCHED_NR_UE/defs.h" #define K1 ((long long int) 512) #define K2 ((long long int) (1024-K1)) @@ -254,6 +255,24 @@ void nr_ue_ssb_rsrp_measurements(PHY_VARS_NR_UE *ue, ue->measurements.ssb_rsrp_dBm[ssb_index], rsrp_db_per_re, ue->measurements.ssb_sinr_dB[ssb_index]); + + // Send SS measurements to MAC + if (!ue->if_inst || !ue->if_inst->dl_indication) + return; + + fapi_nr_l1_measurements_t l1_measurements = { + .gNB_index = proc->gNB_id, + .meas_type = NFAPI_NR_SS_MEAS, + .Nid_cell = ue->frame_parms.Nid_cell, + .is_neighboring_cell = false, + }; + int ssb_rsrp_dBm = ue->measurements.ssb_rsrp_dBm[ssb_index]; + l1_measurements.rsrp_dBm = BOUNDED_EVAL(16, ssb_rsrp_dBm + 157, 113); // TS 38.133 - Table 10.1.6.1-1 + nr_downlink_indication_t dl_indication = {0}; + fapi_nr_rx_indication_t rx_ind = {0}; + nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, NULL); + nr_fill_rx_indication(&rx_ind, FAPI_NR_MEAS_IND, ue, NULL, NULL, 1, proc, &l1_measurements, NULL); + ue->if_inst->dl_indication(&dl_indication); } // This function computes the received noise power diff --git a/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c b/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c index 295718e22c..4ab72a13f0 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c +++ b/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c @@ -979,18 +979,24 @@ void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue, } // Send CSI measurements to MAC - fapi_nr_csirs_measurements_t csirs_measurements; - csirs_measurements.rsrp = rsrp; - csirs_measurements.rsrp_dBm = rsrp_dBm; - csirs_measurements.rank_indicator = rank_indicator; - csirs_measurements.i1 = *i1; - csirs_measurements.i2 = *i2; - csirs_measurements.cqi = cqi; - csirs_measurements.radiolink_monitoring = RLM_no_monitoring; // TODO do be activated in case of RLM based on CSI-RS + if (!ue->if_inst || !ue->if_inst->dl_indication) + return; + + fapi_nr_l1_measurements_t l1_measurements = { + .gNB_index = proc->gNB_id, + .meas_type = NFAPI_NR_CSI_MEAS, + .Nid_cell = frame_parms->Nid_cell, + .is_neighboring_cell = false, + .rsrp_dBm = BOUNDED_EVAL(16, rsrp_dBm + 157, 113), // TS 38.133 - Table 10.1.6.1-1 + .rank_indicator = rank_indicator, + .i1 = *i1, + .i2 = *i2, + .cqi = cqi, + .radiolink_monitoring = RLM_no_monitoring, // TODO do be activated in case of RLM based on CSI-RS + }; nr_downlink_indication_t dl_indication; fapi_nr_rx_indication_t rx_ind = {0}; nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, NULL); - nr_fill_rx_indication(&rx_ind, FAPI_NR_CSIRS_IND, ue, NULL, NULL, 1, proc, (void *)&csirs_measurements, NULL); - if (ue->if_inst && ue->if_inst->dl_indication) - ue->if_inst->dl_indication(&dl_indication); + nr_fill_rx_indication(&rx_ind, FAPI_NR_MEAS_IND, ue, NULL, NULL, 1, proc, (void *)&l1_measurements, NULL); + ue->if_inst->dl_indication(&dl_indication); } diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index f683a2098d..25447e4bb4 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -186,8 +186,8 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind, rx->ssb_pdu.decoded_pdu = false; } } break; - case FAPI_NR_CSIRS_IND: - memcpy(&rx->csirs_measurements, typeSpecific, sizeof(fapi_nr_csirs_measurements_t)); + case FAPI_NR_MEAS_IND: + memcpy(&rx->l1_measurements, typeSpecific, sizeof(fapi_nr_l1_measurements_t)); break; default: break; diff --git a/openair1/SIMULATION/NR_PHY/nr_unitary_common.c b/openair1/SIMULATION/NR_PHY/nr_unitary_common.c index 7aca911b7f..585c5388e4 100644 --- a/openair1/SIMULATION/NR_PHY/nr_unitary_common.c +++ b/openair1/SIMULATION/NR_PHY/nr_unitary_common.c @@ -178,3 +178,12 @@ void *rrc_nrue(void *notUsed) { return NULL; } + +void nr_mac_rrc_meas_ind_ue(module_id_t module_id, + uint32_t gNB_index, + uint16_t Nid_cell, + bool csi_meas, + bool is_neighboring_cell, + uint8_t rsrp_dBm) +{ +} diff --git a/openair2/COMMON/mac_messages_def.h b/openair2/COMMON/mac_messages_def.h index f342444c65..11e8ab6f5e 100644 --- a/openair2/COMMON/mac_messages_def.h +++ b/openair2/COMMON/mac_messages_def.h @@ -62,3 +62,7 @@ MESSAGE_DEF(NR_RRC_MAC_SBCCH_DATA_IND, MESSAGE_PRIORITY_MED_PLUS, NRRrcMacSBc // Message to GNB_APP to update SIB19 satellite position information MESSAGE_DEF(GNB_SAT_POSITION_UPDATE, MESSAGE_PRIORITY_MED, gnb_sat_position_update_t, gnb_sat_position_update) + +// nrUE +MESSAGE_DEF(NR_RRC_MAC_MEAS_DATA_IND, MESSAGE_PRIORITY_MED_PLUS, NRRrcMacMeasDataInd, nr_rrc_mac_meas_data_ind) + diff --git a/openair2/COMMON/mac_messages_types.h b/openair2/COMMON/mac_messages_types.h index f5712b115a..677e1e90b1 100644 --- a/openair2/COMMON/mac_messages_types.h +++ b/openair2/COMMON/mac_messages_types.h @@ -44,6 +44,8 @@ #define NR_RRC_MAC_BCCH_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.nr_rrc_mac_bcch_data_ind #define NR_RRC_MAC_SBCCH_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.nr_rrc_mac_sbcch_data_ind +#define NR_RRC_MAC_MEAS_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.nr_rrc_mac_meas_data_ind + #define RRC_MAC_BCCH_MBMS_DATA_REQ(mSGpTR) (mSGpTR)->ittiMsg.rrc_mac_bcch_mbms_data_req #define RRC_MAC_BCCH_MBMS_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.rrc_mac_bcch_mbms_data_ind @@ -142,6 +144,14 @@ typedef struct NRRrcMacSBcchDataInd_s { uint8_t rsrp; } NRRrcMacSBcchDataInd; +typedef struct NRRrcMacMeasDataInd_s { + uint8_t gnb_index; + uint8_t rsrp_dBm; + uint16_t Nid_cell; + bool is_csi_meas; + bool is_neighboring_cell; +} NRRrcMacMeasDataInd; + typedef struct RrcMacBcchMbmsDataReq_s { uint32_t frame; uint32_t sdu_size; diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index d734870f52..680b5138df 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -594,8 +594,8 @@ typedef struct NR_UE_MAC_INST_s { nr_csi_report_t csi_report_template[MAX_CSI_REPORTCONFIG]; - /// measurements from CSI-RS - fapi_nr_csirs_measurements_t csirs_measurements; + /// measurements from SS or CSI-RS + fapi_nr_l1_measurements_t l1_measurements; //// FAPI-like interface message fapi_nr_ul_config_request_t *ul_config_request; diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index 6d4f025a30..035e59c09c 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -117,10 +117,8 @@ csi_payload_t nr_ue_aperiodic_csi_reporting(NR_UE_MAC_INST_t *mac, dci_field_t c nr_dci_format_t nr_ue_process_dci_indication_pdu(NR_UE_MAC_INST_t *mac, frame_t frame, int slot, fapi_nr_dci_indication_pdu_t *dci); -int8_t nr_ue_process_csirs_measurements(NR_UE_MAC_INST_t *mac, - frame_t frame, - int slot, - fapi_nr_csirs_measurements_t *csirs_measurements); +void nr_ue_process_l1_measurements(NR_UE_MAC_INST_t *mac, frame_t frame, int slot, fapi_nr_l1_measurements_t *l1_measurements); + void nr_ue_aperiodic_srs_scheduling(NR_UE_MAC_INST_t *mac, long resource_trigger, int frame, int slot); bool trigger_periodic_scheduling_request(NR_UE_MAC_INST_t *mac, diff --git a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c index 3348c6b278..78bfb1021c 100644 --- a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c +++ b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c @@ -302,7 +302,7 @@ void release_mac_configuration(NR_UE_MAC_INST_t *mac, NR_UE_MAC_reset_cause_t ca release_ul_BWP(mac, i); memset(&mac->ssb_measurements, 0, sizeof(mac->ssb_measurements)); - memset(&mac->csirs_measurements, 0, sizeof(mac->csirs_measurements)); + memset(&mac->l1_measurements, 0, sizeof(mac->l1_measurements)); memset(&mac->ul_time_alignment, 0, sizeof(mac->ul_time_alignment)); for (int i = mac->TAG_list.count; i > 0 ; i--) asn_sequence_del(&mac->TAG_list, i - 1, 1); diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index a4362a346e..ab13c9dd07 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -1504,13 +1504,17 @@ nr_dci_format_t nr_ue_process_dci_indication_pdu(NR_UE_MAC_INST_t *mac, frame_t return format; } -int8_t nr_ue_process_csirs_measurements(NR_UE_MAC_INST_t *mac, - frame_t frame, - int slot, - fapi_nr_csirs_measurements_t *csirs_measurements) { - LOG_D(NR_MAC,"(%d.%d) Received CSI-RS measurements\n", frame, slot); - memcpy(&mac->csirs_measurements, csirs_measurements, sizeof(*csirs_measurements)); - return 0; +void nr_ue_process_l1_measurements(NR_UE_MAC_INST_t *mac, frame_t frame, int slot, fapi_nr_l1_measurements_t *l1_measurements) +{ + LOG_D(NR_MAC, "(%d.%d) Received CSI-RS measurements\n", frame, slot); + memcpy(&mac->l1_measurements, l1_measurements, sizeof(*l1_measurements)); + bool csi_meas = l1_measurements->meas_type == NFAPI_NR_CSI_MEAS; + nr_mac_rrc_meas_ind_ue(mac->ue_id, + l1_measurements->gNB_index, + l1_measurements->Nid_cell, + csi_meas, + l1_measurements->is_neighboring_cell, + l1_measurements->rsrp_dBm); } static void set_harq_status(NR_UE_MAC_INST_t *mac, @@ -2993,9 +2997,9 @@ static csi_payload_t get_csirs_RI_PMI_CQI_payload(NR_UE_MAC_INST_t *mac, AssertFatal(csi_report, "Couldn't find CSI report with ID %ld\n", csi_reportconfig->reportConfigId); int cri_bitlen = csi_report->csi_meas_bitlen.cri_bitlen; int ri_bitlen = csi_report->csi_meas_bitlen.ri_bitlen; - int pmi_x1_bitlen = csi_report->csi_meas_bitlen.pmi_x1_bitlen[mac->csirs_measurements.rank_indicator]; - int pmi_x2_bitlen = csi_report->csi_meas_bitlen.pmi_x2_bitlen[mac->csirs_measurements.rank_indicator]; - int cqi_bitlen = csi_report->csi_meas_bitlen.cqi_bitlen[mac->csirs_measurements.rank_indicator]; + int pmi_x1_bitlen = csi_report->csi_meas_bitlen.pmi_x1_bitlen[mac->l1_measurements.rank_indicator]; + int pmi_x2_bitlen = csi_report->csi_meas_bitlen.pmi_x2_bitlen[mac->l1_measurements.rank_indicator]; + int cqi_bitlen = csi_report->csi_meas_bitlen.cqi_bitlen[mac->l1_measurements.rank_indicator]; if (get_softmodem_params()->emulate_l1) { static const uint8_t mcs_to_cqi[] = {0, 1, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, @@ -3003,9 +3007,9 @@ static csi_payload_t get_csirs_RI_PMI_CQI_payload(NR_UE_MAC_INST_t *mac, CHECK_INDEX(nr_bler_data, NR_NUM_MCS - 1); int mcs = get_mcs_from_sinr(nr_bler_data, (mac->nr_ue_emul_l1.cqi - 640) * 0.1); CHECK_INDEX(mcs_to_cqi, mcs); - mac->csirs_measurements.rank_indicator = mac->nr_ue_emul_l1.ri; - mac->csirs_measurements.i1 = mac->nr_ue_emul_l1.pmi; - mac->csirs_measurements.cqi = mcs_to_cqi[mcs]; + mac->l1_measurements.rank_indicator = mac->nr_ue_emul_l1.ri; + mac->l1_measurements.i1 = mac->nr_ue_emul_l1.pmi; + mac->l1_measurements.cqi = mcs_to_cqi[mcs]; } int padding_bitlen = 0; @@ -3014,19 +3018,19 @@ static csi_payload_t get_csirs_RI_PMI_CQI_payload(NR_UE_MAC_INST_t *mac, p1_bits = cri_bitlen + ri_bitlen + cqi_bitlen; p2_bits = pmi_x1_bitlen + pmi_x2_bitlen; temp_payload_1 = (0/*mac->csi_measurements.cri*/ << (cqi_bitlen + ri_bitlen)) | - (mac->csirs_measurements.rank_indicator << cqi_bitlen) | - (mac->csirs_measurements.cqi); - temp_payload_2 = (mac->csirs_measurements.i1 << pmi_x2_bitlen) | - mac->csirs_measurements.i2; + (mac->l1_measurements.rank_indicator << cqi_bitlen) | + (mac->l1_measurements.cqi); + temp_payload_2 = (mac->l1_measurements.i1 << pmi_x2_bitlen) | + mac->l1_measurements.i2; } else { p1_bits = nr_get_csi_bitlen(csi_report); padding_bitlen = p1_bits - (cri_bitlen + ri_bitlen + pmi_x1_bitlen + pmi_x2_bitlen + cqi_bitlen); temp_payload_1 = (0/*mac->csi_measurements.cri*/ << (cqi_bitlen + pmi_x2_bitlen + pmi_x1_bitlen + padding_bitlen + ri_bitlen)) | - (mac->csirs_measurements.rank_indicator << (cqi_bitlen + pmi_x2_bitlen + pmi_x1_bitlen + padding_bitlen)) | - (mac->csirs_measurements.i1 << (cqi_bitlen + pmi_x2_bitlen)) | - (mac->csirs_measurements.i2 << (cqi_bitlen)) | - (mac->csirs_measurements.cqi); + (mac->l1_measurements.rank_indicator << (cqi_bitlen + pmi_x2_bitlen + pmi_x1_bitlen + padding_bitlen)) | + (mac->l1_measurements.i1 << (cqi_bitlen + pmi_x2_bitlen)) | + (mac->l1_measurements.i2 << (cqi_bitlen)) | + (mac->l1_measurements.cqi); } temp_payload_1 = reverse_bits(temp_payload_1, p1_bits); @@ -3085,17 +3089,7 @@ static csi_payload_t get_csirs_RSRP_payload(NR_UE_MAC_INST_t *mac, } // TODO: Improvements will be needed to cri_ssbri_bitlen>0 - // TS 38.133 - Table 10.1.6.1-1 - int rsrp_dBm = mac->csirs_measurements.rsrp_dBm; - if (rsrp_dBm < -140) { - temp_payload = 16; - } else if (rsrp_dBm > -44) { - temp_payload = 113; - } else { - temp_payload = mac->csirs_measurements.rsrp_dBm + 157; - } - - temp_payload = reverse_bits(temp_payload, n_bits); + temp_payload = reverse_bits(mac->l1_measurements.rsrp_dBm, n_bits); // rsrp_dBm as in TS 38.133 - Table 10.1.6.1-1 LOG_D(NR_MAC, "cri_ssbri_bitlen = %d\n", cri_ssbri_bitlen); LOG_D(NR_MAC, "rsrp_bitlen = %d\n", rsrp_bitlen); diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c index 21818c68c3..3f765bf6c9 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c @@ -1174,13 +1174,11 @@ static void handle_rlm(rlm_t rlm_result, int frame, NR_UE_MAC_INST_t *mac) nr_mac_rrc_sync_ind(mac->ue_id, frame, is_sync); } -static int8_t handle_csirs_measurements(NR_UE_MAC_INST_t *mac, - frame_t frame, - int slot, - fapi_nr_csirs_measurements_t *csirs_measurements) +static int8_t handle_l1_measurements(NR_UE_MAC_INST_t *mac, frame_t frame, int slot, fapi_nr_l1_measurements_t *l1_measurements) { - handle_rlm(csirs_measurements->radiolink_monitoring, frame, mac); - return nr_ue_process_csirs_measurements(mac, frame, slot, csirs_measurements); + handle_rlm(l1_measurements->radiolink_monitoring, frame, mac); + nr_ue_process_l1_measurements(mac, frame, slot, l1_measurements); + return 0; } void update_harq_status(NR_UE_MAC_INST_t *mac, uint8_t harq_pid, uint8_t ack_nack) @@ -1316,11 +1314,11 @@ static uint32_t nr_ue_dl_processing(NR_UE_MAC_INST_t *mac, nr_downlink_indicatio } ret_mask |= (handle_dlsch(mac, dl_info, i)) << FAPI_NR_RX_PDU_TYPE_RAR; break; - case FAPI_NR_CSIRS_IND: - ret_mask |= (handle_csirs_measurements(mac, - dl_info->frame, - dl_info->slot, - &rx_indication_body.csirs_measurements)) << FAPI_NR_CSIRS_IND; + case FAPI_NR_MEAS_IND: + ret_mask |= (handle_l1_measurements(mac, + dl_info->frame, + dl_info->slot, + &rx_indication_body.l1_measurements)) << FAPI_NR_MEAS_IND; break; default: break; diff --git a/openair2/RRC/NR_UE/L2_interface_ue.c b/openair2/RRC/NR_UE/L2_interface_ue.c index b751f31670..d6bee2ab10 100644 --- a/openair2/RRC/NR_UE/L2_interface_ue.c +++ b/openair2/RRC/NR_UE/L2_interface_ue.c @@ -37,6 +37,17 @@ typedef uint32_t channel_t; +void nr_mac_rrc_meas_ind_ue(module_id_t module_id, uint32_t gNB_index, uint16_t Nid_cell, bool csi_meas, bool is_neighboring_cell, uint8_t rsrp_dBm) +{ + MessageDef *message_p = itti_alloc_new_message(TASK_MAC_UE, 0, NR_RRC_MAC_MEAS_DATA_IND); + NR_RRC_MAC_MEAS_DATA_IND(message_p).gnb_index = gNB_index; + NR_RRC_MAC_MEAS_DATA_IND(message_p).Nid_cell = Nid_cell; + NR_RRC_MAC_MEAS_DATA_IND(message_p).is_csi_meas = csi_meas; + NR_RRC_MAC_MEAS_DATA_IND(message_p).is_neighboring_cell = is_neighboring_cell; + NR_RRC_MAC_MEAS_DATA_IND(message_p).rsrp_dBm = rsrp_dBm; + itti_send_msg_to_task(TASK_RRC_NRUE, GNB_MODULE_ID_TO_INSTANCE(module_id), message_p); +} + void nr_mac_rrc_sync_ind(const module_id_t module_id, const frame_t frame, const bool in_sync) { MessageDef *message_p = itti_alloc_new_message(TASK_MAC_UE, 0, NR_RRC_MAC_SYNC_IND); diff --git a/openair2/RRC/NR_UE/L2_interface_ue.h b/openair2/RRC/NR_UE/L2_interface_ue.h index daaed50e65..857c110d9e 100644 --- a/openair2/RRC/NR_UE/L2_interface_ue.h +++ b/openair2/RRC/NR_UE/L2_interface_ue.h @@ -37,6 +37,12 @@ void nr_mac_rrc_data_ind_ue(const module_id_t module_id, const channel_t channel, const uint8_t* pduP, const sdu_size_t pdu_len); +void nr_mac_rrc_meas_ind_ue(module_id_t module_id, + uint32_t gNB_index, + uint16_t Nid_cell, + bool csi_meas, + bool is_neighboring_cell, + uint8_t rsrp_dBm); void nr_mac_rrc_inactivity_timer_ind(const module_id_t mod_id); void nr_mac_rrc_msg3_ind(const module_id_t mod_id, const int rnti, bool prepare_payload); void nr_ue_rrc_timer_trigger(int instance, int frame, int gnb_id); diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 52d9ecb50a..8683269054 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -807,6 +807,9 @@ NR_UE_RRC_INST_t* nr_rrc_init_ue(char* uecap_file, int instance_id, int num_ant_ for (int i = 0; i < NB_CNX_UE; i++) { rrcPerNB_t *ptr = &rrc->perNB[i]; ptr->SInfo = (NR_UE_RRC_SI_INFO){0}; + ptr->l3_measurements = (l3_measurements_t){0}; + ptr->l3_measurements.ssb_filter_coeff_rsrp = 1.0f; + ptr->l3_measurements.csi_RS_filter_coeff_rsrp = 1.0f; init_SI_timers(&ptr->SInfo); } @@ -1814,6 +1817,14 @@ static void handle_quantityconfig(rrcPerNB_t *rrc, NR_QuantityConfig_t *quantity if (!rrc->QuantityConfig[i]) rrc->QuantityConfig[i] = calloc(1, sizeof(*rrc->QuantityConfig[i])); rrc->QuantityConfig[i]->quantityConfigCell = quantityNR->quantityConfigCell; + // TODO: It remains to compute ssb_filter_coeff_rsrp and csi_RS_filter_coeff_rsrp for multiple quantityConfig + // TS 38.331 - 5.5.3.2 Layer 3 filtering + NR_QuantityConfigRS_t *qcc = &quantityNR->quantityConfigCell; + l3_measurements_t *l3_measurements = &rrc->l3_measurements; + if (qcc->ssb_FilterConfig.filterCoefficientRSRP) + l3_measurements->ssb_filter_coeff_rsrp = 1. / pow(2, (*qcc->ssb_FilterConfig.filterCoefficientRSRP) / 4); + if (qcc->csi_RS_FilterConfig.filterCoefficientRSRP) + l3_measurements->csi_RS_filter_coeff_rsrp = 1. / pow(2, (*qcc->csi_RS_FilterConfig.filterCoefficientRSRP) / 4); if (quantityNR->quantityConfigRS_Index) UPDATE_IE(rrc->QuantityConfig[i]->quantityConfigRS_Index, quantityNR->quantityConfigRS_Index, struct NR_QuantityConfigRS); } @@ -2238,6 +2249,34 @@ static int nr_rrc_ue_decode_dcch(NR_UE_RRC_INST_t *rrc, return 0; } +static void apply_ema(val_init_t *vi_rsrp_dBm, float filter_coeff_rsrp, int rsrp_dBm) +{ + int *quant = &vi_rsrp_dBm->val; + bool *meas_init = &vi_rsrp_dBm->init; + float coef = *meas_init ? filter_coeff_rsrp : 1.0f; // if not init, first measurement gets full weight + *quant = (1.0f - coef) * (*quant) + coef * rsrp_dBm; + *meas_init = true; +} + +void nr_ue_meas_filtering(rrcPerNB_t *rrc, bool is_neighboring_cell, uint16_t Nid_cell, bool csi_meas, int rsrp_dBm) +{ + if (is_neighboring_cell) + return; + + l3_measurements_t *l3_measurements = &rrc->l3_measurements; + meas_t *meas_cell = &l3_measurements->serving_cell; + if (meas_cell->Nid_cell != Nid_cell) { + meas_cell->ss_rsrp_dBm.init = false; + meas_cell->csi_rsrp_dBm.init = false; + } + meas_cell->Nid_cell = Nid_cell; + + if (csi_meas) + apply_ema(&meas_cell->csi_rsrp_dBm, l3_measurements->csi_RS_filter_coeff_rsrp, rsrp_dBm); + else + apply_ema(&meas_cell->ss_rsrp_dBm, l3_measurements->ssb_filter_coeff_rsrp, rsrp_dBm); +} + void nr_rrc_handle_ra_indication(NR_UE_RRC_INST_t *rrc, bool ra_succeeded) { NR_UE_Timers_Constants_t *timers = &rrc->timers_and_constants; @@ -2354,6 +2393,20 @@ void *rrc_nrue(void *notUsed) nr_rrc_ue_decode_NR_SBCCH_SL_BCH_Message(rrc, sbcch->gnb_index,sbcch->frame, sbcch->slot, sbcch->sdu, sbcch->sdu_size, sbcch->rx_slss_id); + case NR_RRC_MAC_MEAS_DATA_IND: + + LOG_D(NR_RRC, "[%s][Nid_cell %i] Received %s measurements: RSRP = %i (dBm)\n", + NR_RRC_MAC_MEAS_DATA_IND(msg_p).is_neighboring_cell? "Neighboring cell" : "Active cell", + NR_RRC_MAC_MEAS_DATA_IND(msg_p).Nid_cell, + NR_RRC_MAC_MEAS_DATA_IND(msg_p).is_csi_meas ? "CSI meas" : "SSB meas", + NR_RRC_MAC_MEAS_DATA_IND(msg_p).rsrp_dBm - 157); + + rrcPerNB_t *rrcNB = rrc->perNB + NR_RRC_MAC_MEAS_DATA_IND(msg_p).gnb_index; + nr_ue_meas_filtering(rrcNB, + NR_RRC_MAC_MEAS_DATA_IND(msg_p).is_neighboring_cell, + NR_RRC_MAC_MEAS_DATA_IND(msg_p).Nid_cell, + NR_RRC_MAC_MEAS_DATA_IND(msg_p).is_csi_meas, + NR_RRC_MAC_MEAS_DATA_IND(msg_p).rsrp_dBm - 157); break; case NR_RRC_MAC_CCCH_DATA_IND: { diff --git a/openair2/RRC/NR_UE/rrc_defs.h b/openair2/RRC/NR_UE/rrc_defs.h index bc645f7cc1..31e7305b96 100644 --- a/openair2/RRC/NR_UE/rrc_defs.h +++ b/openair2/RRC/NR_UE/rrc_defs.h @@ -192,6 +192,15 @@ typedef enum { typedef enum { RB_NOT_PRESENT, RB_ESTABLISHED, RB_SUSPENDED } NR_RB_status_t; +typedef struct l3_measurements_s { + float ssb_filter_coeff_rsrp; + float csi_RS_filter_coeff_rsrp; + meas_t serving_cell; + long trigger_to_measid; + long trigger_quantity; + long rs_type; +} l3_measurements_t; + typedef struct rrcPerNB { NR_MeasObjectToAddMod_t *MeasObj[MAX_MEAS_OBJ]; NR_ReportConfigToAddMod_t *ReportConfig[MAX_MEAS_CONFIG]; @@ -201,6 +210,7 @@ typedef struct rrcPerNB { NR_MeasGapConfig_t *measGapConfig; NR_UE_RRC_SI_INFO SInfo; NR_RSRP_Range_t s_measure; + l3_measurements_t l3_measurements; } rrcPerNB_t; typedef struct NR_UE_RRC_INST_s { From 3e65d75f833e7abebae37a093162405678fb7bd7 Mon Sep 17 00:00:00 2001 From: rmagueta Date: Mon, 18 Nov 2024 17:29:20 +0000 Subject: [PATCH 700/964] UE sends the measurement report for event A2 --- openair2/RRC/NR/MESSAGES/asn1_msg.c | 57 ++++++++++++ openair2/RRC/NR/MESSAGES/asn1_msg.h | 11 +++ openair2/RRC/NR_UE/rrc_UE.c | 93 +++++++++++++++++++ openair2/RRC/NR_UE/rrc_defs.h | 1 + openair2/RRC/NR_UE/rrc_proto.h | 3 + openair2/RRC/NR_UE/rrc_timers_and_constants.c | 55 +++++++++++ 6 files changed, 220 insertions(+) diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.c b/openair2/RRC/NR/MESSAGES/asn1_msg.c index 3ff6aecea9..21ccb1e40f 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.c +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.c @@ -785,6 +785,63 @@ int do_RRCSetupComplete(uint8_t *buffer, return((enc_rval.encoded+7)/8); } +// TODO: This function is only implemented for event A2 +int do_nrMeasurementReport_SA(NR_MeasurementReport_t *measurementReport, + long trigger_to_measid, + long trigger_quantity, + long rs_type, + uint16_t Nid_cell, + int rsrp_dBm, + uint8_t *buffer, + size_t buffer_size) +{ + asn_enc_rval_t enc_rval; + NR_UL_DCCH_Message_t ul_dcch_msg; + memset((void *)&ul_dcch_msg, 0, sizeof(NR_UL_DCCH_Message_t)); + + ul_dcch_msg.message.present = NR_UL_DCCH_MessageType_PR_c1; + ul_dcch_msg.message.choice.c1 = CALLOC(1, sizeof(struct NR_UL_DCCH_MessageType__c1)); + ul_dcch_msg.message.choice.c1->present = NR_UL_DCCH_MessageType__c1_PR_measurementReport; + + memset(measurementReport, 0, sizeof(struct NR_MeasurementReport)); + ul_dcch_msg.message.choice.c1->choice.measurementReport = measurementReport; + measurementReport->criticalExtensions.present = NR_MeasurementReport__criticalExtensions_PR_measurementReport; + + NR_MeasurementReport_IEs_t *measurementReport_ie = CALLOC(1, sizeof(struct NR_MeasurementReport_IEs)); + measurementReport->criticalExtensions.choice.measurementReport = measurementReport_ie; + measurementReport_ie->measResults.measId = trigger_to_measid; + + NR_MeasResultServMO_t *measResultServMo = CALLOC(1, sizeof(struct NR_MeasResultServMO)); + + NR_MeasResultNR_t *measResultServingCell = &measResultServMo->measResultServingCell; + measResultServingCell->physCellId = CALLOC(1, sizeof(NR_PhysCellId_t)); + *measResultServingCell->physCellId = Nid_cell; + + struct NR_MeasQuantityResults *active_mq_res = CALLOC(1, sizeof(struct NR_MeasQuantityResults)); + + if (trigger_quantity == NR_MeasTriggerQuantityOffset_PR_rsrp) { + active_mq_res->rsrp = CALLOC(1, sizeof(NR_RSRP_Range_t)); + + *active_mq_res->rsrp = rsrp_dBm + 157; + if (rs_type == NR_NR_RS_Type_ssb) + measResultServingCell->measResult.cellResults.resultsSSB_Cell = active_mq_res; + else + measResultServingCell->measResult.cellResults.resultsCSI_RS_Cell = active_mq_res; + } + + ASN_SEQUENCE_ADD(&measurementReport_ie->measResults.measResultServingMOList.list, measResultServMo); + enc_rval = uper_encode_to_buffer(&asn_DEF_NR_UL_DCCH_Message, NULL, (void *)&ul_dcch_msg, buffer, buffer_size); + AssertFatal(enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", enc_rval.failed_type->name, enc_rval.encoded); + + if (LOG_DEBUGFLAG(DEBUG_ASN1)) { + xer_fprint(stdout, &asn_DEF_NR_UL_DCCH_Message, (void *)&ul_dcch_msg); + } + + LOG_I(NR_RRC, "MeasurementReport Encoded %zd bits (%zd bytes)\n", enc_rval.encoded, (enc_rval.encoded + 7) / 8); + + return ((enc_rval.encoded + 7) / 8); +} + int do_NR_DLInformationTransfer(uint8_t *buffer, size_t buffer_len, uint8_t transaction_id, diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.h b/openair2/RRC/NR/MESSAGES/asn1_msg.h index dde62d142f..4f13ca2fad 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.h +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.h @@ -50,11 +50,13 @@ #include "NR_ReestablishmentCause.h" #include "NR_SRB-ToAddModList.h" #include "NR_SecurityConfig.h" +#include "NR_MeasurementReport.h" #include "NR_MeasurementTimingConfiguration.h" #include "ds/seq_arr.h" #include "ds/byte_array.h" #include "rrc_messages_types.h" #include "openair2/LAYER2/nr_pdcp/nr_pdcp_configuration.h" +#include "common/utils/nr/nr_common.h" struct asn_TYPE_descriptor_s; typedef struct { @@ -127,6 +129,15 @@ int do_NR_MeasurementTimingConfiguration(const NR_MeasurementTimingConfiguration int do_RRCSetupRequest(uint8_t *buffer, size_t buffer_size, uint8_t *rv, uint64_t fiveG_S_TMSI_part1); +int do_nrMeasurementReport_SA(NR_MeasurementReport_t *measurementReport, + long trigger_to_measid, + long trigger_quantity, + long rs_type, + uint16_t Nid_cell, + int rsrp_dBm, + uint8_t *buffer, + size_t buffer_size); + int do_NR_RRCReconfigurationComplete_for_nsa(uint8_t *buffer, size_t buffer_size, NR_RRC_TransactionIdentifier_t Transaction_id); int do_NR_RRCReconfigurationComplete(uint8_t *buffer, size_t buffer_size, const uint8_t Transaction_id); diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 8683269054..d0b551f67a 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -2277,6 +2277,79 @@ void nr_ue_meas_filtering(rrcPerNB_t *rrc, bool is_neighboring_cell, uint16_t Ni apply_ema(&meas_cell->ss_rsrp_dBm, l3_measurements->ssb_filter_coeff_rsrp, rsrp_dBm); } +static void nr_ue_check_meas_report(NR_UE_RRC_INST_t *rrc, const uint8_t gnb_index) +{ + rrcPerNB_t *rrcNB = rrc->perNB + gnb_index; + l3_measurements_t *l3_measurements = &rrcNB->l3_measurements; + + for (int i = 0; i < MAX_MEAS_CONFIG; i++) { + NR_ReportConfigToAddMod_t *report_config = rrcNB->ReportConfig[i]; + if (report_config == NULL) + continue; + + if (report_config->reportConfig.present != NR_ReportConfigToAddMod__reportConfig_PR_reportConfigNR) + continue; + + NR_ReportConfigNR_t *report_config_nr = report_config->reportConfig.choice.reportConfigNR; + if (report_config_nr->reportType.present != NR_ReportConfigNR__reportType_PR_eventTriggered) + continue; + + NR_EventTriggerConfig_t *event_trigger_config = report_config_nr->reportType.choice.eventTriggered; + if (event_trigger_config->eventId.present != NR_EventTriggerConfig__eventId_PR_eventA2) + continue; + + struct NR_EventTriggerConfig__eventId__eventA2 *event_A2 = event_trigger_config->eventId.choice.eventA2; + if (event_A2->a2_Threshold.present != NR_MeasTriggerQuantity_PR_rsrp) + continue; + + meas_t *serving_cell = &l3_measurements->serving_cell; + int serving_cell_rsrp = INT_MAX; + if (serving_cell->ss_rsrp_dBm.init == true) { + serving_cell_rsrp = serving_cell->ss_rsrp_dBm.val; + } else if (serving_cell->csi_rsrp_dBm.init == true) { + serving_cell_rsrp = serving_cell->csi_rsrp_dBm.val; + } else { + LOG_E(NR_RRC, "There are no RSRP measurements taken for the active cell\n"); + } + + // TS 38.133 - Table 10.1.6.1-1: SS-RSRP and CSI-RSRP measurement report mapping + int rsrp_threshold = event_A2->a2_Threshold.choice.rsrp - 157; + int rsrp_hysteresis = event_A2->hysteresis >> 1; + + // TS 38.331 - 5.5.4.3 Event A2 (Serving becomes worse than threshold) + if (serving_cell_rsrp + rsrp_hysteresis < rsrp_threshold) { + if (!nr_timer_is_active(&l3_measurements->TA2)) { + nr_timer_setup(&l3_measurements->TA2, get_A2_event_time_to_trigger(event_A2->timeToTrigger), 10); + nr_timer_start(&l3_measurements->TA2); + int report_config_id = report_config->reportConfigId; + int meas_id = -1; + for (int j = 0; j < MAX_MEAS_ID; j++) { + NR_MeasIdToAddMod_t *meas_id_toAddMod = rrcNB->MeasId[j]; + if (meas_id_toAddMod == NULL) { + continue; + } + if (meas_id_toAddMod->reportConfigId == report_config_id) { + meas_id = meas_id_toAddMod->measId; + } + } + AssertFatal(meas_id > 0, "meas_id did not found for report_config_id %i\n", report_config_id); + + l3_measurements->trigger_to_measid = meas_id; + l3_measurements->trigger_quantity = event_A2->a2_Threshold.present; + l3_measurements->rs_type = event_trigger_config->rsType; + + LOG_W(NR_RRC, + "(active_cell_rsrp) %i + (rsrp_hysteresis) %i < (rsrp_threshold) %i\n", + serving_cell_rsrp, + rsrp_hysteresis, + rsrp_threshold); + } + } else if (nr_timer_is_active(&l3_measurements->TA2) && (serving_cell_rsrp - rsrp_hysteresis > rsrp_threshold)) { + nr_timer_stop(&l3_measurements->TA2); + } + } +} + void nr_rrc_handle_ra_indication(NR_UE_RRC_INST_t *rrc, bool ra_succeeded) { NR_UE_Timers_Constants_t *timers = &rrc->timers_and_constants; @@ -2407,6 +2480,7 @@ void *rrc_nrue(void *notUsed) NR_RRC_MAC_MEAS_DATA_IND(msg_p).Nid_cell, NR_RRC_MAC_MEAS_DATA_IND(msg_p).is_csi_meas, NR_RRC_MAC_MEAS_DATA_IND(msg_p).rsrp_dBm - 157); + nr_ue_check_meas_report(rrc, NR_RRC_MAC_MEAS_DATA_IND(msg_p).gnb_index); break; case NR_RRC_MAC_CCCH_DATA_IND: { @@ -3045,3 +3119,22 @@ void nr_rrc_set_mac_queue(instance_t instance, notifiedFIFO_t *mac_input_nf) NR_UE_RRC_INST_t *rrc = get_NR_UE_rrc_inst(instance); rrc->mac_input_nf = mac_input_nf; } + +void rrc_ue_generate_measurementReport(rrcPerNB_t *rrc, instance_t ue_id) +{ + uint8_t buffer[NR_RRC_BUF_SIZE]; + NR_MeasurementReport_t measurementReport = {0}; + l3_measurements_t *l3m = &rrc->l3_measurements; + int rsrp_dBm = l3m->rs_type == NR_NR_RS_Type_ssb ? l3m->serving_cell.ss_rsrp_dBm.val : l3m->serving_cell.csi_rsrp_dBm.val; + uint8_t size = do_nrMeasurementReport_SA(&measurementReport, + l3m->trigger_to_measid, + l3m->trigger_quantity, + l3m->rs_type, + l3m->serving_cell.Nid_cell, + rsrp_dBm, + buffer, + sizeof(buffer)); + + int srb_id = 1; // possibly TODO in SRB3 in some cases + nr_pdcp_data_req_srb(ue_id, srb_id, 0, size, buffer, deliver_pdu_srb_rlc, NULL); +} diff --git a/openair2/RRC/NR_UE/rrc_defs.h b/openair2/RRC/NR_UE/rrc_defs.h index 31e7305b96..dfcd01a09a 100644 --- a/openair2/RRC/NR_UE/rrc_defs.h +++ b/openair2/RRC/NR_UE/rrc_defs.h @@ -199,6 +199,7 @@ typedef struct l3_measurements_s { long trigger_to_measid; long trigger_quantity; long rs_type; + NR_timer_t TA2; } l3_measurements_t; typedef struct rrcPerNB { diff --git a/openair2/RRC/NR_UE/rrc_proto.h b/openair2/RRC/NR_UE/rrc_proto.h index ba853f546d..d332ca5175 100644 --- a/openair2/RRC/NR_UE/rrc_proto.h +++ b/openair2/RRC/NR_UE/rrc_proto.h @@ -55,6 +55,8 @@ void nr_rrc_going_to_IDLE(NR_UE_RRC_INST_t *rrc, void handle_RRCRelease(NR_UE_RRC_INST_t *rrc); +void rrc_ue_generate_measurementReport(rrcPerNB_t *rrc, instance_t ue_id); + void set_rlf_sib1_timers_and_constants(NR_UE_Timers_Constants_t *tac, NR_UE_TimersAndConstants_t *ue_TimersAndConstants); /**\brief RRC UE task. @@ -83,6 +85,7 @@ 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); +int get_A2_event_time_to_trigger(long time_to_trigger); void reset_rlf_timers_and_constants(NR_UE_Timers_Constants_t *tac); void set_default_timers_and_constants(NR_UE_Timers_Constants_t *tac); void nr_rrc_set_sib1_timers_and_constants(NR_UE_Timers_Constants_t *tac, NR_SIB1_t *sib1); diff --git a/openair2/RRC/NR_UE/rrc_timers_and_constants.c b/openair2/RRC/NR_UE/rrc_timers_and_constants.c index 57f6be2eb6..b0bc4661bc 100644 --- a/openair2/RRC/NR_UE/rrc_timers_and_constants.c +++ b/openair2/RRC/NR_UE/rrc_timers_and_constants.c @@ -122,6 +122,19 @@ void nr_rrc_SI_timers(NR_UE_RRC_SI_INFO *SInfo) } } +void handle_meas_timers(NR_UE_RRC_INST_t *rrc) +{ + for (int i = 0; i < NB_CNX_UE; i++) { + rrcPerNB_t *nb = &rrc->perNB[i]; + l3_measurements_t *l3_measurements = &nb->l3_measurements; + + bool ta2_expired = nr_timer_tick(&l3_measurements->TA2); + if (ta2_expired && l3_measurements->trigger_quantity > 0) { + rrc_ue_generate_measurementReport(nb, rrc->ue_id); + } + } +} + void nr_rrc_handle_timers(NR_UE_RRC_INST_t *rrc) { NR_UE_Timers_Constants_t *timers = &rrc->timers_and_constants; @@ -185,6 +198,8 @@ void nr_rrc_handle_timers(NR_UE_RRC_INST_t *rrc) // Spec 38.331 Section 5.2.2.6 handle_t430_expiry(rrc); } + + handle_meas_timers(rrc); } int nr_rrc_get_T304(long t304) @@ -630,3 +645,43 @@ void reset_rlf_timers_and_constants(NR_UE_Timers_Constants_t *tac) tac->N310_cnt = 0; tac->N311_cnt = 0; } + +int get_A2_event_time_to_trigger(long time_to_trigger) +{ + switch (time_to_trigger) { + case NR_TimeToTrigger_ms0: + return 0; + case NR_TimeToTrigger_ms40: + return 40; + case NR_TimeToTrigger_ms64: + return 64; + case NR_TimeToTrigger_ms80: + return 80; + case NR_TimeToTrigger_ms100: + return 100; + case NR_TimeToTrigger_ms128: + return 128; + case NR_TimeToTrigger_ms160: + return 160; + case NR_TimeToTrigger_ms256: + return 256; + case NR_TimeToTrigger_ms320: + return 320; + case NR_TimeToTrigger_ms480: + return 480; + case NR_TimeToTrigger_ms512: + return 512; + case NR_TimeToTrigger_ms640: + return 640; + case NR_TimeToTrigger_ms1024: + return 1024; + case NR_TimeToTrigger_ms1280: + return 1280; + case NR_TimeToTrigger_ms2560: + return 2560; + case NR_TimeToTrigger_ms5120: + return 5120; + default: + AssertFatal(false, "Invalid TimeToTrigger %ld\n", time_to_trigger); + } +} From 2c369a8299620f1d2f9371ebdd5d1bfb905777c8 Mon Sep 17 00:00:00 2001 From: alexjiao Date: Tue, 26 Aug 2025 14:57:25 +0100 Subject: [PATCH 701/964] Handle reportAmount and reportInterval in reportConfigNR --- openair2/RRC/NR_UE/rrc_UE.c | 49 ++++++++++++++++++- openair2/RRC/NR_UE/rrc_defs.h | 4 ++ openair2/RRC/NR_UE/rrc_timers_and_constants.c | 17 +++++++ 3 files changed, 69 insertions(+), 1 deletion(-) diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index d0b551f67a..7ace2c7a91 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -1666,6 +1666,14 @@ static void handle_meas_reporting_remove(rrcPerNB_t *rrc, int id, NR_UE_Timers_C // TODO stop the periodical reporting timer or timer T321, whichever is running, // and reset the associated information (e.g. timeToTrigger) for this measId nr_timer_stop(&timers->T321); + + l3_measurements_t *l3_measurements = &rrc->l3_measurements; + nr_timer_stop(&l3_measurements->TA2); + nr_timer_stop(&l3_measurements->periodic_report_timer); + + l3_measurements->reports_sent = 0; + l3_measurements->max_reports = 0; + l3_measurements->report_interval_ms = 0; } static void handle_measobj_remove(rrcPerNB_t *rrc, struct NR_MeasObjectToRemoveList *remove_list, NR_UE_Timers_Constants_t *timers) @@ -2277,6 +2285,38 @@ void nr_ue_meas_filtering(rrcPerNB_t *rrc, bool is_neighboring_cell, uint16_t Ni apply_ema(&meas_cell->ss_rsrp_dBm, l3_measurements->ssb_filter_coeff_rsrp, rsrp_dBm); } +static long get_measurement_report_interval_ms(NR_ReportInterval_t interval) +{ + switch (interval) { + case NR_ReportInterval_ms120: + return 120; + case NR_ReportInterval_ms240: + return 240; + case NR_ReportInterval_ms480: + return 480; + case NR_ReportInterval_ms640: + return 640; + case NR_ReportInterval_ms1024: + return 1024; + case NR_ReportInterval_ms2048: + return 2048; + case NR_ReportInterval_ms5120: + return 5120; + case NR_ReportInterval_ms10240: + return 10240; + case NR_ReportInterval_min1: + return 60000; + case NR_ReportInterval_min6: + return 360000; + case NR_ReportInterval_min12: + return 720000; + case NR_ReportInterval_min30: + return 1800000; + default: + return 1024; + } +} + static void nr_ue_check_meas_report(NR_UE_RRC_INST_t *rrc, const uint8_t gnb_index) { rrcPerNB_t *rrcNB = rrc->perNB + gnb_index; @@ -2318,7 +2358,7 @@ static void nr_ue_check_meas_report(NR_UE_RRC_INST_t *rrc, const uint8_t gnb_ind // TS 38.331 - 5.5.4.3 Event A2 (Serving becomes worse than threshold) if (serving_cell_rsrp + rsrp_hysteresis < rsrp_threshold) { - if (!nr_timer_is_active(&l3_measurements->TA2)) { + if (!nr_timer_is_active(&l3_measurements->TA2) && (l3_measurements->reports_sent == 0)) { nr_timer_setup(&l3_measurements->TA2, get_A2_event_time_to_trigger(event_A2->timeToTrigger), 10); nr_timer_start(&l3_measurements->TA2); int report_config_id = report_config->reportConfigId; @@ -2337,6 +2377,11 @@ static void nr_ue_check_meas_report(NR_UE_RRC_INST_t *rrc, const uint8_t gnb_ind l3_measurements->trigger_to_measid = meas_id; l3_measurements->trigger_quantity = event_A2->a2_Threshold.present; l3_measurements->rs_type = event_trigger_config->rsType; + l3_measurements->reports_sent = 0; + l3_measurements->max_reports = (event_trigger_config->reportAmount == NR_EventTriggerConfig__reportAmount_infinity) + ? INT_MAX + : (1 << event_trigger_config->reportAmount); + l3_measurements->report_interval_ms = get_measurement_report_interval_ms(event_trigger_config->reportInterval); LOG_W(NR_RRC, "(active_cell_rsrp) %i + (rsrp_hysteresis) %i < (rsrp_threshold) %i\n", @@ -2346,6 +2391,8 @@ static void nr_ue_check_meas_report(NR_UE_RRC_INST_t *rrc, const uint8_t gnb_ind } } else if (nr_timer_is_active(&l3_measurements->TA2) && (serving_cell_rsrp - rsrp_hysteresis > rsrp_threshold)) { nr_timer_stop(&l3_measurements->TA2); + nr_timer_stop(&l3_measurements->periodic_report_timer); + l3_measurements->reports_sent = 0; } } } diff --git a/openair2/RRC/NR_UE/rrc_defs.h b/openair2/RRC/NR_UE/rrc_defs.h index dfcd01a09a..d1435526b3 100644 --- a/openair2/RRC/NR_UE/rrc_defs.h +++ b/openair2/RRC/NR_UE/rrc_defs.h @@ -199,7 +199,11 @@ typedef struct l3_measurements_s { long trigger_to_measid; long trigger_quantity; long rs_type; + int reports_sent; + int max_reports; + long report_interval_ms; NR_timer_t TA2; + NR_timer_t periodic_report_timer; } l3_measurements_t; typedef struct rrcPerNB { diff --git a/openair2/RRC/NR_UE/rrc_timers_and_constants.c b/openair2/RRC/NR_UE/rrc_timers_and_constants.c index b0bc4661bc..694656736a 100644 --- a/openair2/RRC/NR_UE/rrc_timers_and_constants.c +++ b/openair2/RRC/NR_UE/rrc_timers_and_constants.c @@ -131,6 +131,23 @@ void handle_meas_timers(NR_UE_RRC_INST_t *rrc) bool ta2_expired = nr_timer_tick(&l3_measurements->TA2); if (ta2_expired && l3_measurements->trigger_quantity > 0) { rrc_ue_generate_measurementReport(nb, rrc->ue_id); + l3_measurements->reports_sent = 1; + + if (l3_measurements->reports_sent < l3_measurements->max_reports) { + nr_timer_setup(&l3_measurements->periodic_report_timer, l3_measurements->report_interval_ms, 10); + nr_timer_start(&l3_measurements->periodic_report_timer); + } + } + + bool periodic_expired = nr_timer_tick(&l3_measurements->periodic_report_timer); + if (periodic_expired && l3_measurements->reports_sent < l3_measurements->max_reports) { + rrc_ue_generate_measurementReport(nb, rrc->ue_id); + l3_measurements->reports_sent++; + + if (l3_measurements->reports_sent < l3_measurements->max_reports) { + nr_timer_setup(&l3_measurements->periodic_report_timer, l3_measurements->report_interval_ms, 10); + nr_timer_start(&l3_measurements->periodic_report_timer); + } } } } From 2aa496bae717cec0a7e0499a528780597b32b72e Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Tue, 16 Sep 2025 15:24:25 +0200 Subject: [PATCH 702/964] Add nr-cuup to run_locally.sh --- ci-scripts/run_locally.sh | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/ci-scripts/run_locally.sh b/ci-scripts/run_locally.sh index 1d4a73e919..6423378e9c 100755 --- a/ci-scripts/run_locally.sh +++ b/ci-scripts/run_locally.sh @@ -15,16 +15,18 @@ fi # The script assumes you've build the following images: # -# docker build . -f docker/Dockerfile.gNB.ubuntu22 -t oai-gnb -# docker build . -f docker/Dockerfile.nrUE.ubuntu22 -t oai-nr-ue +# docker build . -f docker/Dockerfile.gNB.ubuntu -t oai-gnb +# docker build . -f docker/Dockerfile.nr-cuup.ubuntu -t oai-nr-cuup +# docker build . -f docker/Dockerfile.nrUE.ubuntu -t oai-nr-ue # # The images above depend on the following images: # -# docker build . -f docker/Dockerfile.build.ubuntu22 -t ran-build -# dokcer build . -f docker/Dockerfile.base.ubuntu22 -t ran-base +# docker build . -f docker/Dockerfile.build.ubuntu -t ran-build +# docker build . -f docker/Dockerfile.base.ubuntu -t ran-base docker tag oai-nr-ue oai-ci/oai-nr-ue:develop-${SHORT_COMMIT_SHA} docker tag oai-gnb oai-ci/oai-gnb:develop-${SHORT_COMMIT_SHA} +docker tag oai-nr-cuup oai-ci/oai-nr-cuup:develop-${SHORT_COMMIT_SHA} python3 main.py --mode=InitiateHtml --ranRepository=NONE --ranBranch=${CURRENT_BRANCH} \ --ranCommitID=${COMMIT_SHA} --ranAllowMerge=false \ From 1ea90fc9870bfdeabde786c4f23034d0a31bbafd Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 17 Sep 2025 15:24:10 +0200 Subject: [PATCH 703/964] Rename to native_armv9 image build type For clarity, rename to native_armv9 for clarity. The check inside Python checked for native_arm, and if we introduce native_armv8 (for jetson), it would also match that. --- ci-scripts/cls_containerize.py | 2 +- ci-scripts/xml_files/container_image_build_arm.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index 8b5a817ac6..744614e95a 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -304,7 +304,7 @@ class Containerize(): result = re.search('build_cross_arm64', self.imageKind) if result is not None: self.dockerfileprefix = '.ubuntu.cross-arm64' - result = re.search('native_arm', self.imageKind) + result = re.search('native_armv9', self.imageKind) if result is not None: imageNames.append(('oai-gnb', 'gNB', 'oai-gnb', '')) imageNames.append(('ran-build-fhi72', 'build.fhi72.native_arm', 'ran-build-fhi72', '')) diff --git a/ci-scripts/xml_files/container_image_build_arm.xml b/ci-scripts/xml_files/container_image_build_arm.xml index 7c731fd3a1..f5daa348aa 100644 --- a/ci-scripts/xml_files/container_image_build_arm.xml +++ b/ci-scripts/xml_files/container_image_build_arm.xml @@ -40,7 +40,7 @@ Build_Image Build all Images gracehopper3-oai - native_arm + native_armv9
From 8045dc71e0643ae547a65b867d549f05af01d485 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 17 Sep 2025 15:26:34 +0200 Subject: [PATCH 704/964] XML description for build on Jetson (ARMv8) --- ci-scripts/cls_containerize.py | 5 ++ .../container_image_build_jetson.xml | 53 +++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 ci-scripts/xml_files/container_image_build_jetson.xml diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index 744614e95a..965ff6a6db 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -311,6 +311,11 @@ class Containerize(): imageNames.append(('oai-nr-cuup', 'nr-cuup', 'oai-nr-cuup', '')) imageNames.append(('oai-nr-ue', 'nrUE', 'oai-nr-ue', '')) imageNames.append(('oai-gnb-aerial', 'gNB.aerial', 'oai-gnb-aerial', '')) + result = re.search('native_armv8', self.imageKind) + if result is not None: + imageNames.append(('oai-gnb', 'gNB', 'oai-gnb', '')) + imageNames.append(('oai-nr-cuup', 'nr-cuup', 'oai-nr-cuup', '')) + imageNames.append(('oai-nr-ue', 'nrUE', 'oai-nr-ue', '')) cmd.cd(lSourcePath) # if asterix, copy the entitlement and subscription manager configurations diff --git a/ci-scripts/xml_files/container_image_build_jetson.xml b/ci-scripts/xml_files/container_image_build_jetson.xml new file mode 100644 index 0000000000..3cdac5efcb --- /dev/null +++ b/ci-scripts/xml_files/container_image_build_jetson.xml @@ -0,0 +1,53 @@ + + + build-tab + Build Container Images for ARM + wrench + + 800813 + 000001 + 000010 + + + + + Create_Workspace + Create new Workspace for server 0 + jetson3-oai + + + Build_Image + Build all Images + jetson3-oai + native_armv8 + + + + Push_Local_Registry + Push Images to Local Registry + jetson3-oai + armv8_ + + + From 44729d57656af72ff7fe10278b0a6357d1759fb6 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 17 Sep 2025 17:24:41 +0200 Subject: [PATCH 705/964] Add Jetson build pipeline to RAN-Container-Parent --- ci-scripts/Jenkinsfile-GitLab-Container | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/ci-scripts/Jenkinsfile-GitLab-Container b/ci-scripts/Jenkinsfile-GitLab-Container index 57d6b1651e..4bdb20d371 100644 --- a/ci-scripts/Jenkinsfile-GitLab-Container +++ b/ci-scripts/Jenkinsfile-GitLab-Container @@ -175,6 +175,28 @@ pipeline { } } } + stage ("Ubuntu-Jetson-Image-Builder") { + steps { + script { + triggerSlaveJob ('RAN-Ubuntu-Jetson-Image-Builder', 'Ubuntu-Jetson-Image-Builder') + } + } + post { + always { + script { + // Using a unique variable name for each test stage to avoid overwriting on a global variable + // due to parallel-time concurrency + ubuntuJetsonBuildStatus = finalizeSlaveJob('RAN-Ubuntu-Jetson-Image-Builder') + } + } + failure { + script { + currentBuild.result = 'FAILURE' + failingStages += ubuntuJetsonBuildStatus + } + } + } + } stage ("RHEL-Cluster-Image-Builder") { steps { script { From 95dfb67e512e434a93d38e421cf84e760db4fbaa Mon Sep 17 00:00:00 2001 From: francescomani Date: Wed, 17 Sep 2025 16:55:38 +0200 Subject: [PATCH 706/964] fix MSG3 with C-RNTI failure --- openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index 58269f769a..bc29f7a9b9 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -1193,7 +1193,9 @@ void nr_ra_contention_resolution_failed(NR_UE_MAC_INST_t *mac) ra->t_crnti = 0; // flush MSG3 buffer free_and_zero(ra->Msg3_buffer); - nr_mac_rrc_msg3_ind(mac->ue_id, 0, true); + // MSG3 with C-RNTI is a L2 procedure, we shouldn't send any indication to RRC + if (!mac->msg3_C_RNTI) + nr_mac_rrc_msg3_ind(mac->ue_id, 0, true); NR_PRACH_RESOURCES_t *prach_resources = &ra->prach_resources; prach_resources->preamble_tx_counter++; if (prach_resources->preamble_tx_counter == ra->preambleTransMax + 1) { From a1175f7f613c6d94602ef1d0433cdca2d09272bc Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 17 Sep 2025 18:38:14 +0200 Subject: [PATCH 707/964] Add documentation for Jetson build pipeline --- doc/TESTBenches.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/doc/TESTBenches.md b/doc/TESTBenches.md index d7881fb993..70a31d7391 100644 --- a/doc/TESTBenches.md +++ b/doc/TESTBenches.md @@ -135,6 +135,14 @@ information on how the images are built. - target image from `Dockerfile.nr-cuup.ubuntu` - target image from `Dockerfile.nrUE.ubuntu` - target image from `Dockerfile.gNB.aerial.ubuntu` +- [RAN-Ubuntu-Jetson-Image-Builder](https://jenkins-oai.eurecom.fr/job/RAN-Ubuntu-Jetson-Image-Builder/) + ~BUILD-ONLY ~4G-LTE ~5G-NR + - jetson3-oai: ARMv8 Ubuntu image build using docker + - base image from `Dockerfile.base.ubuntu` + - build image from `Dockerfile.build.ubuntu`, followed by + - target image from `Dockerfile.gNB.ubuntu` + - target image from `Dockerfile.nr-cuup.ubuntu` + - target image from `Dockerfile.nrUE.ubuntu` #### Image Test pipelines From 8c78ef5b946f53ec6f8c584f7f9710a44ce91c33 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 17 Sep 2025 18:39:10 +0200 Subject: [PATCH 708/964] Correct Ubuntu version (to generic "Ubuntu") --- doc/TESTBenches.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/TESTBenches.md b/doc/TESTBenches.md index 70a31d7391..e7564b8678 100644 --- a/doc/TESTBenches.md +++ b/doc/TESTBenches.md @@ -113,7 +113,7 @@ information on how the images are built. - [RAN-Ubuntu18-Image-Builder](https://jenkins-oai.eurecom.fr/job/RAN-Ubuntu18-Image-Builder/) ~BUILD-ONLY ~4G-LTE ~5G-NR ~nrUE - run formatting check from `ci-scripts/docker/Dockerfile.formatting.ubuntu` - - obelix: Ubuntu 22 image build using docker (Note: builds U22 images while pipeline is named U18!) + - obelix: Ubuntu image build using docker (Note: builds Ubuntu images of newer version while pipeline is named U18!) - base image from `Dockerfile.base.ubuntu` - build image from `Dockerfile.build.ubuntu`, followed by - target image from `Dockerfile.eNB.ubuntu` @@ -128,7 +128,7 @@ information on how the images are built. - build unit tests from `ci-scripts/docker/Dockerfile.unittest.ubuntu`, and run them - [RAN-Ubuntu-ARM-Image-Builder](https://jenkins-oai.eurecom.fr/job/RAN-Ubuntu-ARM-Image-Builder/) ~BUILD-ONLY ~4G-LTE ~5G-NR - - gracehopper3-oai: ARM Ubuntu 22 image build using docker + - gracehopper3-oai: ARM Ubuntu image build using docker - base image from `Dockerfile.base.ubuntu` - build image from `Dockerfile.build.ubuntu`, followed by - target image from `Dockerfile.gNB.ubuntu` From 98462c20ba80433ec853395e2ccabedf2c4bfc26 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 17 Sep 2025 14:58:50 +0200 Subject: [PATCH 709/964] Remove interrupt_action Remove this flag, as it is not used as of this commit, and introduces confusion (see next commit: we reused the trans_interrupt timer for the transmission action indicator stop action, where the UE should stay active, while it is *not* when transm_interrupt is active). --- .../LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c | 13 ++++--------- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 2 +- openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 3 --- 3 files changed, 5 insertions(+), 13 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index ae5305d77c..e914a71af3 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -3461,11 +3461,10 @@ void nr_measgap_scheduling(gNB_MAC_INST *nr_mac, frame_t frame, sub_frame_t slot continue; NR_timer_t *t = &UE->UE_sched_ctrl.transm_interrupt; - interrupt_followup_action_t a = nr_timer_is_active(t) ? UE->interrupt_action : FOLLOW_INSYNC; // start a timer to stop scheduling UE during MeasGap, or extend timer for // duration of measGap with existing follow-up action if (!nr_timer_is_active(t) || nr_timer_remaining_time(t) < mgc->mgl_slots) { - nr_mac_interrupt_ue_transmission(nr_mac, UE, a, mgc->mgl_slots); + nr_mac_interrupt_ue_transmission(nr_mac, UE, mgc->mgl_slots); } } } @@ -3549,7 +3548,7 @@ int nr_mac_get_reconfig_delay_slots(NR_SubcarrierSpacing_t scs) return (delay_ms << scs) + sl_ahead; } -int nr_mac_interrupt_ue_transmission(gNB_MAC_INST *mac, NR_UE_info_t *UE, interrupt_followup_action_t action, int slots) +int nr_mac_interrupt_ue_transmission(gNB_MAC_INST *mac, NR_UE_info_t *UE, int slots) { DevAssert(mac != NULL); DevAssert(UE != NULL); @@ -3557,7 +3556,6 @@ int nr_mac_interrupt_ue_transmission(gNB_MAC_INST *mac, NR_UE_info_t *UE, interr nr_timer_setup(&UE->UE_sched_ctrl.transm_interrupt, slots, 1); nr_timer_start(&UE->UE_sched_ctrl.transm_interrupt); - UE->interrupt_action = action; // it might happen that timing advance command should be sent during the UE // inactivity time. To prevent this, set a variable as if we would have just @@ -3565,14 +3563,14 @@ int nr_mac_interrupt_ue_transmission(gNB_MAC_INST *mac, NR_UE_info_t *UE, interr // frames, after the inactivity of the UE. UE->UE_sched_ctrl.ta_frame = (mac->frame - 1 + 1024) % 1024; - LOG_D(NR_MAC, "UE %04x: Interrupt UE transmission (%d slots) action %d\n", UE->rnti, slots, UE->interrupt_action); + LOG_D(NR_MAC, "UE %04x: Interrupt UE transmission (%d slots)\n", UE->rnti, slots); return 0; } int nr_transmission_action_indicator_stop(gNB_MAC_INST *mac, NR_UE_info_t *UE_info) { int delay = nr_mac_get_reconfig_delay_slots(UE_info->current_DL_BWP.scs); - nr_mac_interrupt_ue_transmission(mac, UE_info, FOLLOW_OUTOFSYNC, delay); + nr_mac_interrupt_ue_transmission(mac, UE_info, delay); LOG_I(NR_MAC, "gNB-DU received the TransmissionActionIndicator with Stop value for UE %04x\n", UE_info->rnti); return 0; } @@ -3641,9 +3639,6 @@ void nr_mac_update_timers(module_id_t module_id, frame_t frame, slot_t slot) if (nr_timer_tick(&sched_ctrl->transm_interrupt)) { /* expired */ nr_timer_stop(&sched_ctrl->transm_interrupt); - if (UE->interrupt_action == FOLLOW_OUTOFSYNC) - nr_mac_trigger_ul_failure(sched_ctrl, UE->current_DL_BWP.scs); - /* else: default FOLLOW_INSYNC: nothing to do (UE is now active again) */ } } } diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index be5d9d37b9..f04b28b8da 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -65,7 +65,7 @@ void nr_mac_prepare_ra_ue(gNB_MAC_INST *nrmac, NR_UE_info_t *UE); bool add_new_UE_RA(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE); int nr_mac_get_reconfig_delay_slots(NR_SubcarrierSpacing_t scs); -int nr_mac_interrupt_ue_transmission(gNB_MAC_INST *mac, NR_UE_info_t *UE, interrupt_followup_action_t action, int slots); +int nr_mac_interrupt_ue_transmission(gNB_MAC_INST *mac, NR_UE_info_t *UE, int slots); int nr_transmission_action_indicator_stop(gNB_MAC_INST *mac, NR_UE_info_t *UE_info); void clear_nr_nfapi_information(gNB_MAC_INST *gNB, diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index af62663de7..3abc547454 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -762,8 +762,6 @@ typedef struct measgap_config { int mgl_slots; } measgap_config_t; -typedef enum interrupt_followup_action { FOLLOW_INSYNC, FOLLOW_OUTOFSYNC } interrupt_followup_action_t; - /*! \brief UE list used by gNB to order UEs/CC for scheduling*/ typedef struct { rnti_t rnti; @@ -780,7 +778,6 @@ typedef struct { /// in case of reestablishment, old spCellConfig to apply after /// reconfiguration NR_SpCellConfig_t *reconfigSpCellConfig; - interrupt_followup_action_t interrupt_action; NR_UE_NR_Capability_t *capability; measgap_config_t measgap_config; // UE selected beam index From 25380e807507e87c58c1cd82289bcf9e43497131 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 17 Sep 2025 15:09:25 +0200 Subject: [PATCH 710/964] Add transm_timout timer to set UE to UL failure after timeout Introduce a new timer for the use case where a UE should not be scheduled anymore after a certain time. This is the case, for instance, during handover, where the "source DU" forwards the RRCReconfiguration and should stop scheduling this UE after some time. Originally, transm_interrupt was introduced in 5c6d90aaff41 ("Use NR_timer_t for UE transmission interrupt, e.g., RRC processing") to stop scheduling a UE. Commit 004403c84d57 ("Implement F1 UE Ctxt Modif Transmission Action Indicator") reused this timer in an attempt to save code with an "interrupt follow action". In commit 89ebbb419276 ("Do not trigger ul failure in measgap scheduling and standardize the verification if MAC is active in other scheduling functions"), the transm_interrupt timer is used to not schedule a UE through function nr_mac_ue_is_active(). This led to the UE not being forwarded the RRCReconfiguration, effectively breaking handover, as the message never reaches the UE. By using a new timer, the intended functionality is restored. Fixes: 89ebbb419276 ("Do not trigger ul failure in measgap scheduling and standardize the verification if MAC is active in other scheduling functions") --- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 20 ++++++++++++++++++- openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 4 ++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index e914a71af3..7d8367ff6b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -3567,10 +3567,23 @@ int nr_mac_interrupt_ue_transmission(gNB_MAC_INST *mac, NR_UE_info_t *UE, int sl return 0; } +static void nr_mac_ue_transmission_timeout(gNB_MAC_INST *mac, NR_UE_info_t *UE, int slots) +{ + DevAssert(mac != NULL); + DevAssert(UE != NULL); + NR_SCHED_ENSURE_LOCKED(&mac->sched_lock); + + nr_timer_setup(&UE->UE_sched_ctrl.transm_timeout, slots, 1); + nr_timer_start(&UE->UE_sched_ctrl.transm_timeout); + + LOG_I(NR_MAC, "UE %04x: Timeout for UE transmission (%d slots)\n", UE->rnti, slots); + return; +} + int nr_transmission_action_indicator_stop(gNB_MAC_INST *mac, NR_UE_info_t *UE_info) { int delay = nr_mac_get_reconfig_delay_slots(UE_info->current_DL_BWP.scs); - nr_mac_interrupt_ue_transmission(mac, UE_info, delay); + nr_mac_ue_transmission_timeout(mac, UE_info, delay); LOG_I(NR_MAC, "gNB-DU received the TransmissionActionIndicator with Stop value for UE %04x\n", UE_info->rnti); return 0; } @@ -3640,6 +3653,11 @@ void nr_mac_update_timers(module_id_t module_id, frame_t frame, slot_t slot) /* expired */ nr_timer_stop(&sched_ctrl->transm_interrupt); } + if (nr_timer_tick(&sched_ctrl->transm_timeout)) { + nr_timer_stop(&sched_ctrl->transm_timeout); + LOG_W(NR_MAC, "UE %04x UL failure after transmission timeout\n", UE->rnti); + nr_mac_trigger_ul_failure(sched_ctrl, UE->current_DL_BWP.scs); + } } } diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 3abc547454..50f77b681c 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -688,6 +688,10 @@ typedef struct { /// Timer for RRC processing procedures and transmission activity NR_timer_t transm_interrupt; + /// Timer for timeout before UE is set to UL failure (e.g., + /// "TransmissionActionIndicator" handling + NR_timer_t transm_timeout; + /// sri, ul_ri and tpmi based on SRS nr_srs_feedback_t srs_feedback; From 26698d4f07144f3af729f41498a51e78280a64ff Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Mon, 14 Jul 2025 17:09:21 +0200 Subject: [PATCH 711/964] HO Preparation: do verify_section_notset of neighbour and measurement config for DU During the review of N2 HO MR it has been found that there was no check on the absence of the neighbour and measurement section in the DU config file. --- openair2/GNB_APP/gnb_config.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index dcd17efe22..a3f9f0169b 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -722,6 +722,8 @@ void RCconfig_verify(configmodule_interface_t *cfg, ngran_node_t node_type) verify_section_notset(cfg, GNB_CONFIG_STRING_GNB_LIST ".[0]", GNB_CONFIG_STRING_AMF_IP_ADDRESS); verify_section_notset(cfg, NULL, CONFIG_STRING_SECURITY); verify_section_notset(cfg, NULL, CONFIG_STRING_NR_PDCP_LIST); + verify_section_notset(cfg, NULL, GNB_CONFIG_STRING_NEIGHBOUR_LIST); + verify_section_notset(cfg, NULL, GNB_CONFIG_STRING_MEASUREMENT_CONFIGURATION); } // else nothing to be checked /* other possible verifications: PNF, VNF, CU-CP, CU-UP, ...? */ From 2f4f1770509a52b59e7e4836b6d173b08d012229 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 20 Aug 2025 22:21:31 +0200 Subject: [PATCH 712/964] HO Preparation: allocate HO Context in the F1 trigger rather than nr_initiate_handover During the N2 HO review has been found that the HO context was not allocated at trigger time but later in the flow. This might lead to issues in some scenarios (e.g. in N2 HO) and it was fixed in this commit. --- openair2/RRC/NR/rrc_gNB_mobility.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/openair2/RRC/NR/rrc_gNB_mobility.c b/openair2/RRC/NR/rrc_gNB_mobility.c index fe3214da2d..7324399d0c 100644 --- a/openair2/RRC/NR/rrc_gNB_mobility.c +++ b/openair2/RRC/NR/rrc_gNB_mobility.c @@ -128,11 +128,8 @@ static void nr_initiate_handover(const gNB_RRC_INST *rrc, DevAssert(target_du != NULL); // source_du might be NULL -> inter-CU handover DevAssert(ho_prep_info->buf != NULL && ho_prep_info->len > 0); + DevAssert(ue->ho_context); - if (ue->ho_context != NULL) { - LOG_E(NR_RRC, "handover for UE %u ongoing, cannot trigger new\n", ue->rrc_ue_id); - return; - } // if any reconfiguration is ongoing, abort handover request for (int i = 0; i < NR_RRC_TRANSACTION_IDENTIFIER_NUMBER; ++i) { if (ue->xids[i] != RRC_ACTION_NONE) { @@ -141,10 +138,7 @@ static void nr_initiate_handover(const gNB_RRC_INST *rrc, } } - // if we know the source DU (F1 handover), allocate the context for it, - // otherwise only for the target DU (N2, Xn) - ho_ctx_type_t ctx_type = source_du != NULL ? HO_CTX_BOTH : HO_CTX_TARGET; - nr_handover_context_t *ho_ctx = alloc_ho_ctx(ctx_type); + nr_handover_context_t *ho_ctx = ue->ho_context; ho_ctx->target->du = target_du; // we will know target->{du_ue_id,new_rnti} once we have UE ctxt setup // response @@ -164,7 +158,7 @@ static void nr_initiate_handover(const gNB_RRC_INST *rrc, int result = asn_copy(&asn_DEF_NR_CellGroupConfig, (void **)&ho_ctx->source->old_cellGroupConfig, ue->masterCellGroup); AssertFatal(result == 0, "error during asn_copy() of CellGroupConfig\n"); } - ue->ho_context = ho_ctx; + LOG_A(NR_RRC, "Handover triggered for UE %u/RNTI %04x towards DU %ld/assoc_id %d/PCI %d\n", ue->rrc_ue_id, @@ -355,6 +349,13 @@ void nr_rrc_trigger_f1_ho(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue, nr_rrc_du_contain uint8_t buf[NR_RRC_BUF_SIZE]; int size = do_NR_HandoverPreparationInformation(ue->ue_cap_buffer.buf, ue->ue_cap_buffer.len, buf, sizeof buf); + // Allocate handover context (both CU and DU) + if (ue->ho_context != NULL) { + LOG_E(NR_RRC, "Ongoing handover for UE %d, cannot trigger new\n", ue->rrc_ue_id); + return; + } + ue->ho_context = alloc_ho_ctx(HO_CTX_BOTH); + // corresponds to a "handover request", 38.300 Sec 9.3.2.3 // see also 38.413 Sec 9.3.1.29 for information on source-CU to target-CU // information (Source NG-RAN Node to Target NG-RAN Node Transparent Container) From ff5b2bc8b27a05acb27a12bf63c3693ca6b22787 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Thu, 21 Aug 2025 00:11:18 +0200 Subject: [PATCH 713/964] HO Preparation: print neighbour cell configuration --- openair2/GNB_APP/gnb_config.c | 38 +++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index a3f9f0169b..55110fc449 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -1860,21 +1860,21 @@ static void fill_neighbour_cell_configuration(uint8_t gnb_idx, gNB_RRC_INST *rrc GNBNEIGHBOURCELLPARAMS_DESC, GNB_CONFIG_STRING_NEIGHBOUR_CELL_LIST, neighbourpath); - LOG_D(GNB_APP, "HO LOG: For the Cell: %ld Neighbour Cell ELM NUM: %d\n", cell.nr_cell_id, NeighbourCellParamList.numelt); + LOG_I(GNB_APP, "Cell %ld has %d neighbours\n", cell.nr_cell_id, NeighbourCellParamList.numelt); if (NeighbourCellParamList.numelt < 1) continue; cell.neighbour_cells = malloc_or_fail(sizeof(seq_arr_t)); seq_arr_init(cell.neighbour_cells, sizeof(nr_neighbour_cell_t)); for (int l = 0; l < NeighbourCellParamList.numelt; ++l) { - nr_neighbour_cell_t neighbourCell = {0}; - neighbourCell.gNB_ID = *(NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_GNB_ID_IDX].uptr); - neighbourCell.nrcell_id = (uint64_t) * (NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_NR_CELLID_IDX].u64ptr); - neighbourCell.physicalCellId = *NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_PHYSICAL_ID_IDX].uptr; - neighbourCell.subcarrierSpacing = *NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_SCS_IDX].uptr; - neighbourCell.band = *NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_BAND_IDX].uptr; - neighbourCell.absoluteFrequencySSB = *NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_ABS_FREQ_SSB_IDX].i64ptr; - neighbourCell.tac = *NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_TAC_IDX].uptr; + nr_neighbour_cell_t n = {0}; + n.gNB_ID = *(NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_GNB_ID_IDX].uptr); + n.nrcell_id = (uint64_t) * (NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_NR_CELLID_IDX].u64ptr); + n.physicalCellId = *NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_PHYSICAL_ID_IDX].uptr; + n.subcarrierSpacing = *NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_SCS_IDX].uptr; + n.band = *NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_BAND_IDX].uptr; + n.absoluteFrequencySSB = *NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_ABS_FREQ_SSB_IDX].i64ptr; + n.tac = *NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_TAC_IDX].uptr; char neighbour_plmn_path[CONFIG_MAXOPTLENGTH]; snprintf(neighbour_plmn_path, @@ -1886,10 +1886,22 @@ static void fill_neighbour_cell_configuration(uint8_t gnb_idx, gNB_RRC_INST *rrc GNB_CONFIG_STRING_NEIGHBOUR_PLMN); GET_PARAMS(NeighbourPlmn, GNBPLMNPARAMS_DESC, neighbour_plmn_path); - neighbourCell.plmn.mcc = *NeighbourPlmn[GNB_MOBILE_COUNTRY_CODE_IDX].uptr; - neighbourCell.plmn.mnc = *NeighbourPlmn[GNB_MOBILE_NETWORK_CODE_IDX].uptr; - neighbourCell.plmn.mnc_digit_length = *NeighbourPlmn[GNB_MNC_DIGIT_LENGTH].uptr; - seq_arr_push_back(cell.neighbour_cells, &neighbourCell, sizeof(neighbourCell)); + n.plmn.mcc = *NeighbourPlmn[GNB_MOBILE_COUNTRY_CODE_IDX].uptr; + n.plmn.mnc = *NeighbourPlmn[GNB_MOBILE_NETWORK_CODE_IDX].uptr; + n.plmn.mnc_digit_length = *NeighbourPlmn[GNB_MNC_DIGIT_LENGTH].uptr; + seq_arr_push_back(cell.neighbour_cells, &n, sizeof(n)); + LOG_I(GNB_APP, + " [%d] neighbor ID %d cellId %ld PCI %d SCS %d SSB ARFCN %u TAC %u PLMN %03u.%0*u\n", + l, + n.gNB_ID, + n.nrcell_id, + n.physicalCellId, + n.subcarrierSpacing, + n.absoluteFrequencySSB, + n.tac, + n.plmn.mcc, + n.plmn.mnc_digit_length, + n.plmn.mnc); } seq_arr_push_back(rrc->neighbour_cell_configuration, &cell, sizeof(cell)); } From cfb654e77f7f4b8176f0e9f3a0042d39ece53e5a Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Mon, 1 Sep 2025 14:00:35 +0200 Subject: [PATCH 714/964] HO Preparation: add alloc_ho_ctx to rrc_gNB_mobility lib --- openair2/RRC/NR/rrc_gNB_mobility.c | 3 +-- openair2/RRC/NR/rrc_gNB_mobility.h | 3 +++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/openair2/RRC/NR/rrc_gNB_mobility.c b/openair2/RRC/NR/rrc_gNB_mobility.c index 7324399d0c..fbccc637a7 100644 --- a/openair2/RRC/NR/rrc_gNB_mobility.c +++ b/openair2/RRC/NR/rrc_gNB_mobility.c @@ -42,8 +42,7 @@ #include "openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc_extern.h" #endif -typedef enum { HO_CTX_BOTH, HO_CTX_SOURCE, HO_CTX_TARGET } ho_ctx_type_t; -static nr_handover_context_t *alloc_ho_ctx(ho_ctx_type_t type) +nr_handover_context_t *alloc_ho_ctx(ho_ctx_type_t type) { nr_handover_context_t *ho_ctx = calloc_or_fail(1, sizeof(*ho_ctx)); if (type == HO_CTX_SOURCE || type == HO_CTX_BOTH) { diff --git a/openair2/RRC/NR/rrc_gNB_mobility.h b/openair2/RRC/NR/rrc_gNB_mobility.h index 6e9bcbcfe6..a907b3c472 100644 --- a/openair2/RRC/NR/rrc_gNB_mobility.h +++ b/openair2/RRC/NR/rrc_gNB_mobility.h @@ -72,6 +72,9 @@ typedef struct nr_handover_context_s { nr_ho_target_cu_t *target; } nr_handover_context_t; +typedef enum { HO_CTX_BOTH, HO_CTX_SOURCE, HO_CTX_TARGET } ho_ctx_type_t; +nr_handover_context_t *alloc_ho_ctx(ho_ctx_type_t type); + void nr_rrc_trigger_f1_ho(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue, nr_rrc_du_container_t *source_du, nr_rrc_du_container_t *target_du); void nr_rrc_finalize_ho(gNB_RRC_UE_t *ue); From 20e534d483e5dbbb8e2cacc030d8dd74a5104966 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Tue, 25 Mar 2025 10:04:10 +0100 Subject: [PATCH 715/964] Add NGAP Handover Required message NGAP encoder and RRC callback on source NG-RAN This commit introduces the NG Mobility Management Procedure known as Handover Preparation. The outbound message is sent by the source NG-RAN and is known as Handover Required. * introduce NGAP library for Mobility Management * introduce NGAP IEs encoder functions for Handover Required and relevant common IEs * handle RRC trigger in NGAP and Send NGAP Handover Required to the AMF Co-authored-by: batuhan duyuler --- CMakeLists.txt | 1 + openair2/COMMON/ngap_messages_def.h | 1 + openair2/COMMON/ngap_messages_types.h | 87 ++++++++- openair2/RRC/NR/rrc_gNB_NGAP.c | 78 ++++++++ openair2/RRC/NR/rrc_gNB_NGAP.h | 5 + openair3/NGAP/ngap_common.c | 29 +++ openair3/NGAP/ngap_common.h | 3 + openair3/NGAP/ngap_gNB.c | 59 ++++++ openair3/NGAP/ngap_gNB_decoder.c | 10 + openair3/NGAP/ngap_gNB_encoder.c | 3 +- openair3/NGAP/ngap_gNB_mobility_management.c | 193 +++++++++++++++++++ openair3/NGAP/ngap_gNB_mobility_management.h | 31 +++ openair3/NGAP/ngap_msg_includes.h | 8 + 13 files changed, 506 insertions(+), 2 deletions(-) create mode 100644 openair3/NGAP/ngap_gNB_mobility_management.c create mode 100644 openair3/NGAP/ngap_gNB_mobility_management.h diff --git a/CMakeLists.txt b/CMakeLists.txt index fa2d497589..058bfd7a39 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -363,6 +363,7 @@ add_library(ngap ${NGAP_DIR}/ngap_gNB.c ${NGAP_DIR}/ngap_common.c ${NGAP_DIR}/ngap_gNB_context_management_procedures.c + ${NGAP_DIR}/ngap_gNB_mobility_management.c ${NGAP_DIR}/ngap_gNB_decoder.c ${NGAP_DIR}/ngap_gNB_encoder.c ${NGAP_DIR}/ngap_gNB_handlers.c diff --git a/openair2/COMMON/ngap_messages_def.h b/openair2/COMMON/ngap_messages_def.h index 4f05a564c4..eea62d6c00 100644 --- a/openair2/COMMON/ngap_messages_def.h +++ b/openair2/COMMON/ngap_messages_def.h @@ -71,6 +71,7 @@ MESSAGE_DEF(NGAP_UE_CTXT_MODIFICATION_FAIL , MESSAGE_PRIORITY_MED, ngap_ue_ctxt_ MESSAGE_DEF(NGAP_PDUSESSION_SETUP_RESP , MESSAGE_PRIORITY_MED, ngap_pdusession_setup_resp_t , ngap_pdusession_setup_resp) MESSAGE_DEF(NGAP_PDUSESSION_MODIFY_RESP , MESSAGE_PRIORITY_MED, ngap_pdusession_modify_resp_t , ngap_pdusession_modify_resp) MESSAGE_DEF(NGAP_PDUSESSION_RELEASE_RESPONSE , MESSAGE_PRIORITY_MED, ngap_pdusession_release_resp_t , ngap_pdusession_release_resp) +MESSAGE_DEF(NGAP_HANDOVER_REQUIRED, MESSAGE_PRIORITY_MED, ngap_handover_required_t, ngap_handover_required) /* NGAP -> RRC messages */ MESSAGE_DEF(NGAP_DOWNLINK_NAS , MESSAGE_PRIORITY_MED, ngap_downlink_nas_t , ngap_downlink_nas ) diff --git a/openair2/COMMON/ngap_messages_types.h b/openair2/COMMON/ngap_messages_types.h index 3ee858ecca..57ecc51e79 100644 --- a/openair2/COMMON/ngap_messages_types.h +++ b/openair2/COMMON/ngap_messages_types.h @@ -65,7 +65,7 @@ #define NGAP_PDUSESSION_SETUP_REQ(mSGpTR) (mSGpTR)->ittiMsg.ngap_pdusession_setup_req #define NGAP_PDUSESSION_MODIFY_REQ(mSGpTR) (mSGpTR)->ittiMsg.ngap_pdusession_modify_req #define NGAP_PAGING_IND(mSGpTR) (mSGpTR)->ittiMsg.ngap_paging_ind - +#define NGAP_HANDOVER_REQUIRED(mSGpTR) (mSGpTR)->ittiMsg.ngap_handover_required #define NGAP_UE_CONTEXT_RELEASE_REQ(mSGpTR) (mSGpTR)->ittiMsg.ngap_ue_release_req #define NGAP_PDUSESSION_RELEASE_COMMAND(mSGpTR) (mSGpTR)->ittiMsg.ngap_pdusession_release_command #define NGAP_PDUSESSION_RELEASE_RESPONSE(mSGpTR) (mSGpTR)->ittiMsg.ngap_pdusession_release_resp @@ -463,6 +463,91 @@ typedef struct ngap_uplink_nas_s { byte_array_t nas_pdu; } ngap_uplink_nas_t; +typedef struct target_cell_id_s { + plmn_id_t plmn_identity; + uint32_t nrCellIdentity; +} cell_id_t; + +typedef struct target_ran_node_id_s { + uint32_t targetgNBId; + plmn_id_t plmn_identity; + uint32_t tac; +} target_ran_node_id_t; + +/* 3GPP TS 38.413 9.3.1.29 */ +typedef struct { + // QoS Flow Identifier + uint8_t qfi; +} qosflow_info_t; + +/* 3GPP TS 38.413 9.3.1.29 */ +typedef struct { + // PDU Session ID + uint8_t pdusession_id; + // QoS Flow Information List + uint8_t nb_of_qos_flow; + qosflow_info_t qos_flow_info[QOSFLOW_MAX_VALUE]; +} pdusession_resource_info_t; + +/* 3GPP TS 38.413 9.3.1.97 */ +typedef struct { + // Global Cell ID + cell_id_t id; + // Cell type + uint8_t type; + // Time UE Stayed in Cell + long time_in_cell; + // Cause + ngap_cause_t *cause; +} last_visited_ngran_cell_info_t; + +/* 3GPP TS 38.413 9.3.1.29 */ +typedef struct { + // RRC Container: HandoverPreparationInformation message + byte_array_t handoverInfo; + // Target Cell ID + cell_id_t targetCellId; + // PDU Session Resource Information List + uint16_t nb_pdu_session_resource; + pdusession_resource_info_t pdu_session_resource[NGAP_MAX_PDU_SESSION]; + // UE History Information + last_visited_ngran_cell_info_t ue_history_info; +} source_to_target_transparent_container_t; + +typedef enum { + HANDOVER_TYPE_INTRA5GS, // Intra5GS: NG-RAN node to NG-RAN node + HANDOVER_TYPE_5GSTOEPS, // 5GStoEPS: NG-RAN node to eNB + HANDOVER_TYPE_EPSTO5GS, // EPSto5GS: eNB to NG-RAN node + HANDOVER_TYPE_5GSTOUTRA, // 5GStoUTRA: NG-RAN node to UTRA +} ho_type_t; + +/* 3GPP TS 38.413 9.2.3.1 */ +typedef struct { + // PDU Session ID + uint8_t pdusession_id; + // Handover Required Transfer + byte_array_t ho_required_transfer; +} pdusession_resource_t; + +/* 3GPP TS 38.413 9.2.3.1 */ +typedef struct { + // RAN UE NGAP ID + uint32_t gNB_ue_ngap_id; + // AMF UE NGAP ID + uint64_t amf_ue_ngap_id; + // Handover Type + ho_type_t handoverType; + // Cause + ngap_cause_t cause; + // Target ID + target_ran_node_id_t target_gnb_id; + // PDU Session Resource List + uint8_t nb_of_pdusessions; + pdusession_resource_t pdusessions[NGAP_MAX_PDU_SESSION]; + // Source to Target Transparent Container + source_to_target_transparent_container_t *source2target; +} ngap_handover_required_t; + typedef struct ngap_ue_cap_info_ind_s { uint32_t gNB_ue_ngap_id; byte_array_t ue_radio_cap; diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index 407a0d03b7..5632e5932b 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -49,6 +49,7 @@ #include "NGAP_QosFlowSetupRequestItem.h" #include "NGAP_asn_constant.h" #include "NGAP_ProtocolIE-Field.h" +#include "NGAP_CellSize.h" #include "NR_UE-NR-Capability.h" #include "NR_UERadioAccessCapabilityInformation.h" #include "MAC/mac.h" @@ -1297,3 +1298,80 @@ int rrc_gNB_process_PAGING_IND(MessageDef *msg_p, instance_t instance) return 0; } + +/** @brief Callback for NGAP Handover Required message (3GPP TS 38.413 9.2.3.1) + * Direction: source gNB -> AMF */ +void rrc_gNB_send_NGAP_HANDOVER_REQUIRED(gNB_RRC_INST *rrc, + gNB_RRC_UE_t *UE, + const nr_neighbour_cell_t *neighbour, + const byte_array_t hoPrepInfo) +{ + LOG_I(NR_RRC, "Handover Preparation: send Handover Required (target gNB ID=%d, PCI=%d)\n", neighbour->gNB_ID, neighbour->physicalCellId); + + const plmn_id_t plmn = {.mcc = neighbour->plmn.mnc, + .mnc = neighbour->plmn.mnc, + .mnc_digit_length = neighbour->plmn.mnc_digit_length}; + + const target_ran_node_id_t target = { + .plmn_identity = plmn, + .tac = neighbour->tac, + .targetgNBId = neighbour->gNB_ID, + }; + + ngap_handover_required_t msg = { + .amf_ue_ngap_id = UE->amf_ue_ngap_id, + .gNB_ue_ngap_id = UE->rrc_ue_id, + .nb_of_pdusessions = UE->nb_of_pdusessions, + .cause.type = NGAP_CAUSE_RADIO_NETWORK, + .cause.value = NGAP_CAUSE_RADIO_NETWORK_HANDOVER_DESIRABLE_FOR_RADIO_REASON, + .handoverType = HANDOVER_TYPE_INTRA5GS, + .target_gnb_id = target, + }; + + cell_id_t target_cell = { + .nrCellIdentity = neighbour->nrcell_id, + .plmn_identity = plmn, + }; + + // Source to Target Transparent Container (M) + msg.source2target = calloc_or_fail(1, sizeof(*msg.source2target)); + // Target Cell ID (M) + msg.source2target->targetCellId = target_cell; + // RRC Container (M) + msg.source2target->handoverInfo = copy_byte_array(hoPrepInfo); + // UE History Info (M) + msg.source2target->ue_history_info.cause = malloc_or_fail(sizeof(*msg.source2target->ue_history_info.cause)); + msg.source2target->ue_history_info.cause->type = NGAP_CAUSE_RADIO_NETWORK; + msg.source2target->ue_history_info.cause->value = NGAP_CAUSE_RADIO_NETWORK_HANDOVER_DESIRABLE_FOR_RADIO_REASON; + msg.source2target->ue_history_info.type = NGAP_CellSize_small; + msg.source2target->ue_history_info.time_in_cell = 500; // dummy number for now + msg.source2target->ue_history_info.id = target_cell; + + /* Fill both PDU Session Resource List IE (M) in Handover Required + and PDU Session Resource Information List IE (O) in the Source NG-RAN + Node to Target NG-RAN Node Transparent Container */ + for (int i = 0; i < UE->nb_of_pdusessions; ++i) { + if (UE->pduSession[i].status == PDU_SESSION_STATUS_DONE || UE->pduSession[i].status == PDU_SESSION_STATUS_ESTABLISHED) { + rrc_pdu_session_param_t *pduSession = find_pduSession(UE, UE->pduSession[i].param.pdusession_id, false); + if (!pduSession) + continue; + // Handover Required Transfer (M) + uint8_t ho_required_transfer[128] = {0}; + msg.pdusessions[i].ho_required_transfer.buf = ho_required_transfer; + msg.pdusessions[i].ho_required_transfer.len = sizeof(ho_required_transfer); + // PDU Session ID + msg.pdusessions[i].pdusession_id = pduSession->param.pdusession_id; + + // PDU Session Resource Information List (O) + msg.source2target->pdu_session_resource[i].nb_of_qos_flow = pduSession->param.nb_qos; + for (int j = 0; j < pduSession->param.nb_qos; ++j) { + msg.source2target->pdu_session_resource[i].qos_flow_info[j].qfi = pduSession->param.qos[j].qfi; + } + msg.source2target->nb_pdu_session_resource++; + } + } + + MessageDef *msg_p = itti_alloc_new_message(TASK_RRC_GNB, 0, NGAP_HANDOVER_REQUIRED); + NGAP_HANDOVER_REQUIRED(msg_p) = msg; + itti_send_msg_to_task(TASK_NGAP, rrc->module_id, msg_p); +} diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.h b/openair2/RRC/NR/rrc_gNB_NGAP.h index 22fff8705f..fd8cb31ff1 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.h +++ b/openair2/RRC/NR/rrc_gNB_NGAP.h @@ -89,4 +89,9 @@ void nr_rrc_pdcp_config_security(gNB_RRC_UE_t *UE, bool enable_ciphering); int rrc_gNB_process_PAGING_IND(MessageDef *msg_p, instance_t instance); +void rrc_gNB_send_NGAP_HANDOVER_REQUIRED(gNB_RRC_INST *rrc, + gNB_RRC_UE_t *UE, + const nr_neighbour_cell_t *neighbourCellConfiguration, + const byte_array_t hoPrepInfo); + #endif diff --git a/openair3/NGAP/ngap_common.c b/openair3/NGAP/ngap_common.c index 82c2ccaf2a..b51c8e80de 100644 --- a/openair3/NGAP/ngap_common.c +++ b/openair3/NGAP/ngap_common.c @@ -112,3 +112,32 @@ ngap_mobility_restriction_t decode_ngap_mobility_restriction(const NGAP_Mobility TBCD_TO_MCC_MNC(&in->servingPLMN, out.serving_plmn.mcc, out.serving_plmn.mnc, out.serving_plmn.mnc_digit_length); return out; } + +void encode_ngap_target_id(NGAP_HandoverRequiredIEs_t *out, const target_ran_node_id_t *in) +{ + out->id = NGAP_ProtocolIE_ID_id_TargetID; + out->criticality = NGAP_Criticality_reject; + out->value.present = NGAP_HandoverRequiredIEs__value_PR_TargetID; + // CHOICE Target ID: NG-RAN (M) + out->value.choice.TargetID.present = NGAP_TargetID_PR_targetRANNodeID; + asn1cCalloc(out->value.choice.TargetID.choice.targetRANNodeID, targetRan); + // Global RAN Node ID (M) + targetRan->globalRANNodeID.present = NGAP_GlobalRANNodeID_PR_globalGNB_ID; + asn1cCalloc(targetRan->globalRANNodeID.choice.globalGNB_ID, globalGnbId); + globalGnbId->gNB_ID.present = NGAP_GNB_ID_PR_gNB_ID; + MACRO_GNB_ID_TO_BIT_STRING(in->targetgNBId, &globalGnbId->gNB_ID.choice.gNB_ID); + MCC_MNC_TO_PLMNID(in->plmn_identity.mcc, in->plmn_identity.mnc, in->plmn_identity.mnc_digit_length, &globalGnbId->pLMNIdentity); + // Selected TAI (M) + INT24_TO_OCTET_STRING(in->tac, &targetRan->selectedTAI.tAC); + MCC_MNC_TO_PLMNID(in->plmn_identity.mcc, + in->plmn_identity.mnc, + in->plmn_identity.mnc_digit_length, + &targetRan->selectedTAI.pLMNIdentity); +} + +void encode_ngap_nr_cgi(NGAP_NR_CGI_t *out, const plmn_id_t *plmn, const uint32_t cell_id) +{ + out->iE_Extensions = NULL; + MCC_MNC_TO_PLMNID(plmn->mcc, plmn->mnc, plmn->mnc_digit_length, &out->pLMNIdentity); + NR_CELL_ID_TO_BIT_STRING(cell_id, &out->nRCellIdentity); +} diff --git a/openair3/NGAP/ngap_common.h b/openair3/NGAP/ngap_common.h index dd7fdebc54..1e53d9dd1a 100644 --- a/openair3/NGAP/ngap_common.h +++ b/openair3/NGAP/ngap_common.h @@ -87,6 +87,9 @@ ngap_ambr_t decode_ngap_UEAggregateMaximumBitRate(const NGAP_UEAggregateMaximumB nssai_t decode_ngap_nssai(const NGAP_S_NSSAI_t *in); ngap_security_capabilities_t decode_ngap_security_capabilities(const NGAP_UESecurityCapabilities_t *in); ngap_mobility_restriction_t decode_ngap_mobility_restriction(const NGAP_MobilityRestrictionList_t *in); +void encode_ngap_target_id(NGAP_HandoverRequiredIEs_t *out, const target_ran_node_id_t *in); +void encode_ngap_nr_cgi(NGAP_NR_CGI_t *out, const plmn_id_t *plmn, const uint32_t cell_id); +pdusession_level_qos_parameter_t fill_qos(uint8_t qfi, const NGAP_QosFlowLevelQosParameters_t *params); /** @}*/ diff --git a/openair3/NGAP/ngap_gNB.c b/openair3/NGAP/ngap_gNB.c index 8edb5c3aa3..4b4fc2f850 100644 --- a/openair3/NGAP/ngap_gNB.c +++ b/openair3/NGAP/ngap_gNB.c @@ -55,6 +55,8 @@ #include "ngap_gNB_management_procedures.h" #include "ngap_gNB_nas_procedures.h" #include "ngap_messages_types.h" +#include "ngap_gNB_mobility_management.h" +#include "ngap_gNB_ue_context.h" #include "oai_asn1.h" #include "openair3/SECU/kdf.h" #include "queue.h" @@ -275,6 +277,57 @@ void ngap_gNB_handle_sctp_data_ind(sctp_data_ind_t *sctp_data_ind) { AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); } + /** @brief UE Mobility Management: callback for Handover Required */ +int ngap_handover_required(instance_t instance, ngap_handover_required_t *msg) +{ + DevAssert(msg != NULL); + NGAP_DEBUG("Triggered Handover Required\n"); + /* Retrieve the NGAP gNB instance associated with Mod_id */ + ngap_gNB_instance_t *ngap_gNB_instance_p = ngap_gNB_get_instance(instance); + DevAssert(ngap_gNB_instance_p != NULL); + + ngap_gNB_ue_context_t *ue_context_p = NULL; + if ((ue_context_p = ngap_get_ue_context(msg->gNB_ue_ngap_id)) == NULL) { + /* The context for this gNB ue ngap id doesn't exist in the map of gNB UEs */ + NGAP_WARN("Failed to find ue context associated with gNB ue ngap id: 0x%08x\n", msg->gNB_ue_ngap_id); + return -1; + } + + if ((ue_context_p->gNB_ue_ngap_id != msg->gNB_ue_ngap_id)) { + NGAP_ERROR("ue_context_p->gNB_ue_ngap_id %d does not match msg->gNB_ue_ngap_id %d\n", + ue_context_p->gNB_ue_ngap_id, + msg->gNB_ue_ngap_id); + return -1; + } + + NGAP_NGAP_PDU_t *pdu = encode_ng_handover_required(msg); + if (!pdu) { + NGAP_ERROR("Failed to encode Handover Required\n"); + ASN_STRUCT_FREE(asn_DEF_NGAP_NGAP_PDU, pdu); + return -1; + } + + if (LOG_DEBUGFLAG(DEBUG_ASN1)) + xer_fprint(stdout, &asn_DEF_NGAP_NGAP_PDU, &pdu); + + byte_array_t out = { .buf = NULL, .len = 0 }; + if (ngap_gNB_encode_pdu(pdu, &out.buf, (uint32_t *)&out.len) < 0) { + ASN_STRUCT_FREE(asn_DEF_NGAP_NGAP_PDU, pdu); + NGAP_ERROR("Failed to encode Handover Required message\n"); + return -1; + } + free(pdu); + + /* UE associated signalling -> use the allocated stream */ + ngap_gNB_itti_send_sctp_data_req(ngap_gNB_instance_p->instance, + ue_context_p->amf_ref->assoc_id, + out.buf, + out.len, + ue_context_p->tx_stream); + + return 0; +} + void ngap_gNB_init(void) { NGAP_DEBUG("Starting NGAP layer\n"); ngap_gNB_prepare_internal_data(); @@ -356,6 +409,12 @@ void *ngap_gNB_process_itti_msg(void *notUsed) { ngap_gNB_pdusession_release_resp(instance, &NGAP_PDUSESSION_RELEASE_RESPONSE(received_msg)); break; + case NGAP_HANDOVER_REQUIRED: + if (ngap_handover_required(instance, &NGAP_HANDOVER_REQUIRED(received_msg)) < 0) { + NGAP_ERROR("Handover Required failure: indication to RRC is not sent!\n"); + } + break; + default: NGAP_ERROR("Received unhandled message: %d:%s\n", ITTI_MSG_ID(received_msg), ITTI_MSG_NAME(received_msg)); break; diff --git a/openair3/NGAP/ngap_gNB_decoder.c b/openair3/NGAP/ngap_gNB_decoder.c index 4b76abecbb..58c70011cf 100644 --- a/openair3/NGAP/ngap_gNB_decoder.c +++ b/openair3/NGAP/ngap_gNB_decoder.c @@ -70,6 +70,12 @@ static int ngap_gNB_decode_initiating_message(NGAP_NGAP_PDU_t *pdu) { NGAP_INFO("PDUSESSIONSetup initiating message\n"); break; + case NGAP_ProcedureCode_id_HandoverPreparation: + res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu); + free(res.buffer); + NGAP_INFO("Handover Preparation initiating message\n"); + break; + case NGAP_ProcedureCode_id_PDUSessionResourceModify: res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu); free(res.buffer); @@ -119,6 +125,10 @@ static int ngap_gNB_decode_successful_outcome(NGAP_NGAP_PDU_t *pdu) { free(res.buffer); break; + case NGAP_ProcedureCode_id_HandoverPreparation: + res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu); + free(res.buffer); + break; default: NGAP_ERROR("Unknown procedure ID (%d) for successfull outcome message\n", diff --git a/openair3/NGAP/ngap_gNB_encoder.c b/openair3/NGAP/ngap_gNB_encoder.c index c3c095541d..a6e91ba9c8 100644 --- a/openair3/NGAP/ngap_gNB_encoder.c +++ b/openair3/NGAP/ngap_gNB_encoder.c @@ -52,7 +52,8 @@ static inline int ngap_gNB_encode_initiating(NGAP_NGAP_PDU_t *pdu, uint8_t **buf NGAP_ProcedureCode_id_NASNonDeliveryIndication, NGAP_ProcedureCode_id_UEContextReleaseRequest, NGAP_ProcedureCode_id_PathSwitchRequest, - NGAP_ProcedureCode_id_PDUSessionResourceModifyIndication}; + NGAP_ProcedureCode_id_PDUSessionResourceModifyIndication, + NGAP_ProcedureCode_id_HandoverPreparation}; int i; for (i = 0; i < sizeofArray(tmp); i++) if (pdu->choice.initiatingMessage->procedureCode == tmp[i]) diff --git a/openair3/NGAP/ngap_gNB_mobility_management.c b/openair3/NGAP/ngap_gNB_mobility_management.c new file mode 100644 index 0000000000..4f116c8f34 --- /dev/null +++ b/openair3/NGAP/ngap_gNB_mobility_management.c @@ -0,0 +1,193 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include +#include +#include +#include "ngap_common.h" +#include "ngap_msg_includes.h" +#include "ngap_gNB_defs.h" +#include "ngap_gNB_ue_context.h" +#include "oai_asn1.h" +#include "ngap_gNB_management_procedures.h" +#include "ngap_gNB_encoder.h" +#include "ngap_gNB_itti_messaging.h" + +/** @brief UE Mobility Management: encode Handover Required + * (9.2.3.1 of 3GPP TS 38.413) NG-RAN node → AMF */ +NGAP_NGAP_PDU_t *encode_ng_handover_required(const ngap_handover_required_t *msg) +{ + NGAP_NGAP_PDU_t *pdu = malloc_or_fail(sizeof(*pdu)); + + /* Prepare the NGAP message to encode */ + pdu->present = NGAP_NGAP_PDU_PR_initiatingMessage; + asn1cCalloc(pdu->choice.initiatingMessage, head); + head->procedureCode = NGAP_ProcedureCode_id_HandoverPreparation; + head->criticality = NGAP_Criticality_reject; + head->value.present = NGAP_InitiatingMessage__value_PR_HandoverRequired; + NGAP_HandoverRequired_t *out = &head->value.choice.HandoverRequired; + + // AMF UE NGAP ID (M) + asn1cSequenceAdd(out->protocolIEs.list, NGAP_HandoverRequiredIEs_t, ie1); + ie1->id = NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID; + ie1->criticality = NGAP_Criticality_reject; + ie1->value.present = NGAP_HandoverRequiredIEs__value_PR_AMF_UE_NGAP_ID; + asn_uint642INTEGER(&ie1->value.choice.AMF_UE_NGAP_ID, msg->amf_ue_ngap_id); + + // RAN UE NGAP ID (M) + asn1cSequenceAdd(out->protocolIEs.list, NGAP_HandoverRequiredIEs_t, ie2); + ie2->id = NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID; + ie2->criticality = NGAP_Criticality_reject; + ie2->value.present = NGAP_HandoverRequiredIEs__value_PR_RAN_UE_NGAP_ID; + ie2->value.choice.RAN_UE_NGAP_ID = msg->gNB_ue_ngap_id; + + // Handover Type (M) + asn1cSequenceAdd(out->protocolIEs.list, NGAP_HandoverRequiredIEs_t, ie3); + ie3->id = NGAP_ProtocolIE_ID_id_HandoverType; + ie3->criticality = NGAP_Criticality_reject; + ie3->value.present = NGAP_HandoverRequiredIEs__value_PR_HandoverType; + ie3->value.choice.HandoverType = msg->handoverType; + + // Cause (M) + asn1cSequenceAdd(out->protocolIEs.list, NGAP_HandoverRequiredIEs_t, ie4); + ie4->id = NGAP_ProtocolIE_ID_id_Cause; + ie4->criticality = NGAP_Criticality_ignore; + ie4->value.present = NGAP_HandoverRequiredIEs__value_PR_Cause; + encode_ngap_cause(&ie4->value.choice.Cause, &msg->cause); + + // Target ID (M) + asn1cSequenceAdd(out->protocolIEs.list, NGAP_HandoverRequiredIEs_t, ie5); + encode_ngap_target_id(ie5, &msg->target_gnb_id); + + // PDU Session Resource List (M) + asn1cSequenceAdd(out->protocolIEs.list, NGAP_HandoverRequiredIEs_t, ie6); + ie6->id = NGAP_ProtocolIE_ID_id_PDUSessionResourceListHORqd; + ie6->criticality = NGAP_Criticality_reject; + ie6->value.present = NGAP_HandoverRequiredIEs__value_PR_PDUSessionResourceListHORqd; + for (int i = 0; i < msg->nb_of_pdusessions; ++i) { + asn1cSequenceAdd(ie6->value.choice.PDUSessionResourceListHORqd.list, NGAP_PDUSessionResourceItemHORqd_t, hoRequiredPduSession); + // PDU Session ID (M) + hoRequiredPduSession->pDUSessionID = msg->pdusessions[i].pdusession_id; + // Handover Required Transfer (M) + NGAP_HandoverRequiredTransfer_t hoRequiredTransfer = {0}; + uint8_t ho_req_transfer_transparent_container_buffer[128] = {0}; + if (LOG_DEBUGFLAG(DEBUG_ASN1)) + xer_fprint(stdout, &asn_DEF_NGAP_HandoverRequiredTransfer, &hoRequiredTransfer); + asn_enc_rval_t enc_rval = aper_encode_to_buffer(&asn_DEF_NGAP_HandoverRequiredTransfer, + NULL, + &hoRequiredTransfer, + ho_req_transfer_transparent_container_buffer, + 128); + AssertFatal(enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", enc_rval.failed_type->name, enc_rval.encoded); + hoRequiredPduSession->handoverRequiredTransfer.buf = CALLOC(1, (enc_rval.encoded + 7) / 8); + memcpy(hoRequiredPduSession->handoverRequiredTransfer.buf, + ho_req_transfer_transparent_container_buffer, + (enc_rval.encoded + 7) / 8); + hoRequiredPduSession->handoverRequiredTransfer.size = (enc_rval.encoded + 7) / 8; + + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_HandoverRequiredTransfer, &hoRequiredTransfer); + } + + // Source NG-RAN Node to Target NG-RAN Node Transparent Container (M) + asn1cSequenceAdd(out->protocolIEs.list, NGAP_HandoverRequiredIEs_t, ie); + ie->id = NGAP_ProtocolIE_ID_id_SourceToTarget_TransparentContainer; + ie->criticality = NGAP_Criticality_reject; + ie->value.present = NGAP_HandoverRequiredIEs__value_PR_SourceToTarget_TransparentContainer; + + NGAP_SourceNGRANNode_ToTargetNGRANNode_TransparentContainer_t *source2target = calloc_or_fail(1, sizeof(*source2target)); + + // RRC Container (M) (HandoverPreparationInformation) + source2target->rRCContainer.size = msg->source2target->handoverInfo.len; + source2target->rRCContainer.buf = malloc_or_fail(msg->source2target->handoverInfo.len); + memcpy(source2target->rRCContainer.buf, msg->source2target->handoverInfo.buf, source2target->rRCContainer.size); + + // PDU Session Resource Information List (O) + asn1cCalloc(source2target->pDUSessionResourceInformationList, pduSessionList); + for (uint8_t i = 0; i < msg->nb_of_pdusessions; ++i) { + const pdusession_resource_t *pduSession = &msg->pdusessions[i]; + NGAP_DEBUG("Handover Required: preparing PDU Session Resource Information List for PDU Session ID %d\n", + pduSession->pdusession_id); + asn1cSequenceAdd(pduSessionList->list, NGAP_PDUSessionResourceInformationItem_t, item); + // PDU Session ID (M) + item->pDUSessionID = msg->source2target->pdu_session_resource[i].pdusession_id; + // QoS Flow Information List (M) + for (int q = 0; q < msg->source2target->pdu_session_resource[i].nb_of_qos_flow; ++q) { + asn1cSequenceAdd(item->qosFlowInformationList.list, NGAP_QosFlowInformationItem_t, qosFlowInfo); + qosFlowInfo->qosFlowIdentifier = msg->source2target->pdu_session_resource[i].qos_flow_info[q].qfi; + } + } + + // Target Cell ID (NG-RAN CGI) (M) + source2target->targetCell_ID.present = NGAP_NGRAN_CGI_PR_nR_CGI; + asn1cCalloc(source2target->targetCell_ID.choice.nR_CGI, tNrCGI); + encode_ngap_nr_cgi(tNrCGI, &msg->target_gnb_id.plmn_identity, msg->source2target->targetCellId.nrCellIdentity); + + // UE history Information (M) + asn1cSequenceAdd(source2target->uEHistoryInformation.list, NGAP_LastVisitedCellItem_t, lastVisitedCell); + lastVisitedCell->iE_Extensions = NULL; + // Last Visited Cell Information (M) + lastVisitedCell->lastVisitedCellInformation.present = NGAP_LastVisitedCellInformation_PR_nGRANCell; + // CHOICE (M): NG-RAN Cell + asn1cCalloc(lastVisitedCell->lastVisitedCellInformation.choice.nGRANCell, lastVisitedNR); + // Cell Type (M) + lastVisitedNR->cellType.cellSize = msg->source2target->ue_history_info.type; + // Global Cell ID (M) + lastVisitedNR->globalCellID.present = NGAP_NGRAN_CGI_PR_nR_CGI; + asn1cCalloc(lastVisitedNR->globalCellID.choice.nR_CGI, lastVisitedNrCGI); + cell_id_t *cell = &msg->source2target->ue_history_info.id; + encode_ngap_nr_cgi(lastVisitedNrCGI, &cell->plmn_identity, cell->nrCellIdentity); + // HO Cause Value (O) + if (msg->source2target->ue_history_info.cause) { + asn1cCalloc(lastVisitedNR->hOCauseValue, lastVisitedCause); + encode_ngap_cause(lastVisitedCause, msg->source2target->ue_history_info.cause); + } + // Time UE Stayed in Cell (M) + lastVisitedNR->timeUEStayedInCell = msg->source2target->ue_history_info.time_in_cell; + + if (LOG_DEBUGFLAG(DEBUG_ASN1)) + xer_fprint(stdout, &asn_DEF_NGAP_SourceNGRANNode_ToTargetNGRANNode_TransparentContainer, source2target); + + uint8_t source_to_target_transparent_container_buf[16384] = {0}; + asn_enc_rval_t enc_rval = aper_encode_to_buffer(&asn_DEF_NGAP_SourceNGRANNode_ToTargetNGRANNode_TransparentContainer, + NULL, + (void *)source2target, + (void *)&source_to_target_transparent_container_buf, + 16384); + ASN_STRUCT_FREE(asn_DEF_NGAP_SourceNGRANNode_ToTargetNGRANNode_TransparentContainer, source2target); + if (enc_rval.encoded < 0) { + AssertFatal(enc_rval.encoded > 0, + "HO LOG: Source to Transparent ASN1 message encoding failed (%s, %lu)!\n", + enc_rval.failed_type->name, + enc_rval.encoded); + return NULL; + } + + int total_bytes = (enc_rval.encoded + 7) / 8; + int ret = OCTET_STRING_fromBuf(&ie->value.choice.SourceToTarget_TransparentContainer, + (const char *)&source_to_target_transparent_container_buf, + total_bytes); + if (ret != 0) { + LOG_E(NR_RRC, "HO LOG: Can not perform OCTET_STRING_fromBuf for the SourceToTarget_TransparentContainer"); + return NULL; + } + + return pdu; +} diff --git a/openair3/NGAP/ngap_gNB_mobility_management.h b/openair3/NGAP/ngap_gNB_mobility_management.h new file mode 100644 index 0000000000..b3926877eb --- /dev/null +++ b/openair3/NGAP/ngap_gNB_mobility_management.h @@ -0,0 +1,31 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef NGAP_GNB_MOBILITY_MANAGEMENT_H_ +#define NGAP_GNB_MOBILITY_MANAGEMENT_H_ + +#include +#include "common/platform_types.h" +#include "ngap_messages_types.h" + +NGAP_NGAP_PDU_t *encode_ng_handover_required(const ngap_handover_required_t *msg); + +#endif /* NGAP_GNB_MOBILITY_MANAGEMENT_H_ */ diff --git a/openair3/NGAP/ngap_msg_includes.h b/openair3/NGAP/ngap_msg_includes.h index 1debc2e9f1..cf7d0d9f49 100644 --- a/openair3/NGAP/ngap_msg_includes.h +++ b/openair3/NGAP/ngap_msg_includes.h @@ -78,5 +78,13 @@ #include "NGAP_Dynamic5QIDescriptor.h" #include "NGAP_PDUSessionResourceModifyRequestTransfer.h" #include "NGAP_QosFlowAddOrModifyRequestItem.h" +#include "NGAP_PDUSessionResourceItemHORqd.h" +#include "NGAP_PDUSessionResourceInformationItem.h" +#include "NGAP_QosFlowInformationItem.h" +#include "NGAP_LastVisitedCellItem.h" +#include "NGAP_LastVisitedNGRANCellInformation.h" +#include "NGAP_PDUSessionResourceInformationList.h" +#include "NGAP_HandoverRequiredTransfer.h" +#include "NGAP_SourceNGRANNode-ToTargetNGRANNode-TransparentContainer.h" #endif // NGAP_MSG_INCLUDES_H From 6e4f1b7b31a74505e412bfa243ac9daa992d1250 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Tue, 25 Mar 2025 10:09:49 +0100 Subject: [PATCH 716/964] Add N2 Handover decision and trigger preparation on source CU (1) add N2 ho decision based on measurements (2) add trigger for N2 HO on source CU (3) generate NG Handover Preparation Information message, including RRCReconfiguration, to be passed to the NG Handover Required message (4) call RRC callback for Handover Required message Co-authored-by: batuhan duyuler --- openair2/RRC/NR/MESSAGES/asn1_msg.c | 81 +++++++++++++++++++++++++++++ openair2/RRC/NR/MESSAGES/asn1_msg.h | 3 ++ openair2/RRC/NR/nr_rrc_proto.h | 3 ++ openair2/RRC/NR/rrc_gNB.c | 18 ++++--- openair2/RRC/NR/rrc_gNB_mobility.c | 66 +++++++++++++++++------ openair2/RRC/NR/rrc_gNB_mobility.h | 6 +++ 6 files changed, 155 insertions(+), 22 deletions(-) diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.c b/openair2/RRC/NR/MESSAGES/asn1_msg.c index 3ff6aecea9..8bd9716107 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.c +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.c @@ -564,6 +564,43 @@ static NR_RRCReconfiguration_IEs_t *build_RRCReconfiguration_IEs(const nr_rrc_re return ie; } +static byte_array_t do_HO_RRCReconfiguration(nr_rrc_reconfig_param_t *params) +{ + NR_RRCReconfiguration_IEs_t *ie = build_RRCReconfiguration_IEs(params); + byte_array_t msg = {.buf = NULL, .len = 0}; + + // Create the standalone RRCReconfiguration message + NR_RRCReconfiguration_t rrcReconf = {0}; + rrcReconf.rrc_TransactionIdentifier = params->transaction_id; + rrcReconf.criticalExtensions.present = NR_RRCReconfiguration__criticalExtensions_PR_rrcReconfiguration; + rrcReconf.criticalExtensions.choice.rrcReconfiguration = ie; + + // Encode the message + int val = uper_encode_to_new_buffer(&asn_DEF_NR_RRCReconfiguration, NULL, &rrcReconf, (void **)&msg.buf); + if (val <= 0) { + LOG_E(NR_RRC, "ASN1 RRCReconfiguration message encoding failed\n"); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NR_RRCReconfiguration, &rrcReconf); + return msg; + } + msg.len = val; + LOG_D(NR_RRC, "RRCReconfiguration: Encoded (%ld bytes)\n", msg.len); + + // don't free what we did not allocate, so set fields with pointers to NULL + // if memory comes from outside + ie->measConfig = NULL; + if (ie->radioBearerConfig) { + ie->radioBearerConfig->srb3_ToRelease = NULL; + ie->radioBearerConfig->drb_ToReleaseList = NULL; + ie->radioBearerConfig->drb_ToAddModList = NULL; + ie->radioBearerConfig->srb_ToAddModList = NULL; + ie->radioBearerConfig->securityConfig = NULL; + } + + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NR_RRCReconfiguration, &rrcReconf); + + return msg; +} + byte_array_t do_RRCReconfiguration(const nr_rrc_reconfig_param_t *params) { byte_array_t msg = {.buf = NULL, .len = 0}; @@ -1101,6 +1138,50 @@ NR_MeasConfig_t *get_MeasConfig(const NR_MeasTiming_t *mt, return mc; } +/** @brief HandoverPreparationInformation message (11.2.2 of TS 38.331) + * 1) generate RRCReconfiguration to be transferred + * 2) encodes UE Capabilities from UE Context + * 3) encodes AS context + * 4) generates HO Preparation Info */ +byte_array_t get_HandoverPreparationInformation(nr_rrc_reconfig_param_t *params, int scell_pci) +{ + // Buffer to return + byte_array_t buffer = {.buf = NULL, .len = 0}; + + /* Prepare handoverPreparationInformation IEs */ + NR_HandoverPreparationInformation_t hoPrepInfo = {0}; + hoPrepInfo.criticalExtensions.present = NR_HandoverPreparationInformation__criticalExtensions_PR_c1; + asn1cCalloc(hoPrepInfo.criticalExtensions.choice.c1, c1); + c1->present = NR_HandoverPreparationInformation__criticalExtensions__c1_PR_handoverPreparationInformation; + asn1cCalloc(c1->choice.handoverPreparationInformation, hpi); + + /* Decode stored NR_UE_CapabilityRAT_ContainerList and add to IEs */ + NR_UE_CapabilityRAT_ContainerList_t *clist = NULL; + asn_dec_rval_t dec_rval = + uper_decode(NULL, &asn_DEF_NR_UE_CapabilityRAT_ContainerList, (void **)&clist, params->ue_cap.buf, params->ue_cap.len, 0, 0); + if (dec_rval.code != RC_OK) { + LOG_W(NR_RRC, "Failed to decode UE capability container list for HandoverPreparationInformation, ignoring capabilities\n"); + return buffer; + } + hpi->ue_CapabilityRAT_List = *clist; + free(clist); + + /* sourceConfig: Encode RRCReconfiguration as used in the source cell */ + byte_array_t msg = do_HO_RRCReconfiguration(params); + asn1cCalloc(hpi->sourceConfig, sourceConfig); + OCTET_STRING_fromBuf(&sourceConfig->rrcReconfiguration, (const char *)msg.buf, msg.len); + free_byte_array(msg); + + if (LOG_DEBUGFLAG(DEBUG_ASN1)) + xer_fprint(stdout, &asn_DEF_NR_HandoverPreparationInformation, (void **)&hoPrepInfo); + + /* encode */ + buffer.len = uper_encode_to_new_buffer(&asn_DEF_NR_HandoverPreparationInformation, NULL, (void *)&hoPrepInfo, (void *)&buffer.buf); + AssertFatal(buffer.len > 0, "ASN1 message encoding failed (%ld)!\n", buffer.len); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NR_HandoverPreparationInformation, &hoPrepInfo); + return buffer; +} + void free_MeasConfig(NR_MeasConfig_t *mc) { ASN_STRUCT_FREE(asn_DEF_NR_MeasConfig, mc); diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.h b/openair2/RRC/NR/MESSAGES/asn1_msg.h index dde62d142f..aab65f6685 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.h +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.h @@ -69,6 +69,7 @@ typedef struct { NR_CellGroupConfig_t *cell_group_config; bool masterKeyUpdate; int nextHopChainingCount; + byte_array_t ue_cap; } nr_rrc_reconfig_param_t; /* @@ -161,4 +162,6 @@ NR_MeasConfig_t *get_MeasConfig(const NR_MeasTiming_t *mt, void free_MeasConfig(NR_MeasConfig_t *mc); int do_NR_Paging(uint8_t Mod_id, uint8_t *buffer, uint32_t tmsi); +byte_array_t get_HandoverPreparationInformation(nr_rrc_reconfig_param_t *params, int scell_pci); + #endif /* __RRC_NR_MESSAGES_ASN1_MSG__H__ */ diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h index 0d675ff525..a1918bdd34 100644 --- a/openair2/RRC/NR/nr_rrc_proto.h +++ b/openair2/RRC/NR/nr_rrc_proto.h @@ -125,4 +125,7 @@ nr_rrc_reconfig_param_t get_RRCReconfiguration_params(gNB_RRC_INST *rrc, gNB_RRC pdusession_level_qos_parameter_t *get_qos_characteristics(const int qfi, rrc_pdu_session_param_t *pduSession); f1ap_qos_flow_param_t get_qos_char_from_qos_flow_param(const pdusession_level_qos_parameter_t *qos_param); void openair_rrc_gNB_configuration(gNB_RRC_INST *rrc, gNB_RrcConfigurationReq *configuration); +NR_SRB_ToAddModList_t *createSRBlist(gNB_RRC_UE_t *ue, uint8_t reestablish); +NR_DRB_ToAddModList_t *createDRBlist(gNB_RRC_UE_t *ue, bool reestablish); + #endif diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 0e5912aafe..ad36b9c10d 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -307,7 +307,7 @@ unsigned int rrc_gNB_get_next_transaction_identifier(module_id_t gnb_mod_idP) * for the radio bearer changes, with some expections for SRB1 (i.e. when resuming * an RRC connection, or at the first reconfiguration after RRC connection * reestablishment in NR, do not re-establish PDCP) */ -static NR_SRB_ToAddModList_t *createSRBlist(gNB_RRC_UE_t *ue, uint8_t reestablish) +NR_SRB_ToAddModList_t *createSRBlist(gNB_RRC_UE_t *ue, uint8_t reestablish) { if (!ue->Srb[SRB1].Active) { LOG_E(NR_RRC, "Call SRB list while SRB1 doesn't exist\n"); @@ -328,7 +328,7 @@ static NR_SRB_ToAddModList_t *createSRBlist(gNB_RRC_UE_t *ue, uint8_t reestablis return list; } -static NR_DRB_ToAddModList_t *createDRBlist(gNB_RRC_UE_t *ue, bool reestablish) +NR_DRB_ToAddModList_t *createDRBlist(gNB_RRC_UE_t *ue, bool reestablish) { NR_DRB_ToAddMod_t *DRB_config = NULL; NR_DRB_ToAddModList_t *DRB_configList = CALLOC(sizeof(*DRB_configList), 1); @@ -349,7 +349,7 @@ static NR_DRB_ToAddModList_t *createDRBlist(gNB_RRC_UE_t *ue, bool reestablish) return DRB_configList; } -static void freeSRBlist(NR_SRB_ToAddModList_t *l) +void freeSRBlist(NR_SRB_ToAddModList_t *l) { ASN_STRUCT_FREE(asn_DEF_NR_SRB_ToAddModList, l); } @@ -1383,6 +1383,7 @@ static void process_Event_Based_Measurement_Report(gNB_RRC_INST *rrc, int servingCellRSRP = 0; int neighbourCellRSRP = 0; int scell_pci = -1; + int best_rsrp = -10000; switch (event_triggered->eventId.present) { case NR_EventTriggerConfig__eventId_PR_eventA2: @@ -1443,14 +1444,20 @@ static void process_Event_Based_Measurement_Report(gNB_RRC_INST *rrc, // No F1 connection but static neighbour configuration is available const nr_a3_event_t *a3_event_configuration = get_a3_configuration(rrc, neighbour->physicalCellId); // Additional check - This part can be modified according to additional cell specific Handover Margin + // a3-Offset: The actual value is field value * 0.5 dB. if (a3_event_configuration - && ((a3_event_configuration->a3_offset + a3_event_configuration->hysteresis) + && ((a3_event_configuration->a3_offset * 0.5 + a3_event_configuration->hysteresis) < (neighbourCellRSRP - servingCellRSRP))) { + if (neighbourCellRSRP > best_rsrp) { + // UE can send multiple neighbour cells A3 event report in 1 Meas Report. So, we need to find the best neighbour + best_rsrp = neighbourCellRSRP; + LOG_I(NR_RRC, "HO LOG: Serving Cell RSRP: %d - Best Neighbor RSRP: %d ! Trigger N2 HO\n", servingCellRSRP, best_rsrp); + nr_rrc_trigger_n2_ho(rrc, ue, scell_pci, neighbour); + } LOG_D(NR_RRC, "HO LOG: Trigger N2 HO for the neighbour gnb: %u cell: %lu\n", neighbour->gNB_ID, neighbour->nrcell_id); } } else if (neigh_cell && neighbour) { /* we know the cell and are connected to the DU! */ - gNB_RRC_INST *rrc = RC.nrrrc[0]; nr_rrc_du_container_t *source_du = get_du_by_cell_id(rrc, serving_cell->nr_cellid); DevAssert(source_du); nr_rrc_du_container_t *target_du = get_du_by_cell_id(rrc, neigh_cell->nr_cellid); @@ -1459,7 +1466,6 @@ static void process_Event_Based_Measurement_Report(gNB_RRC_INST *rrc, LOG_W(NR_RRC, "UE %d: received A3 event for stronger neighbor PCI %d, but no such neighbour in configuration\n", ue->rrc_ue_id, neighbour_pci); } } - } break; default: LOG_D(NR_RRC, "NR_EventTriggerConfig__eventId_PR_NOTHING or Other event report\n"); diff --git a/openair2/RRC/NR/rrc_gNB_mobility.c b/openair2/RRC/NR/rrc_gNB_mobility.c index fbccc637a7..fa2eead5ca 100644 --- a/openair2/RRC/NR/rrc_gNB_mobility.c +++ b/openair2/RRC/NR/rrc_gNB_mobility.c @@ -215,27 +215,12 @@ static void nr_initiate_handover(const gNB_RRC_INST *rrc, free_ue_context_setup_req(&ue_context_setup_req); } -/* -void nr_rrc_trigger_n2_ho(gNB_RRC_INST *rrc, int nr_cgi, uint8_t *ho_prep_info, uint32_t *ho_prep_len, void *pdu_session) -{ - // call from outside (via NGAP message), with the request for handover for a - // (any) UE. This handler should, in order: - // - // 1. look up the target DU =du= via get_du_by_cell_id(nr_cgi) - // (and reject the request if it can't find the DU) - // 2. create a context for a new UE =UE=, based on pdu_session information - // 3. call nr_initiate_handover(rrc, UE, NULL, du, ho_prep_info, ho_prep_len); - // - // after success of the DU, send the result via =success_ptr= to the source - // CU. -} -*/ - typedef struct deliver_ue_ctxt_modification_data_t { gNB_RRC_INST *rrc; f1ap_ue_context_mod_req_t *modification_req; sctp_assoc_t assoc_id; } deliver_ue_ctxt_modification_data_t; + static void rrc_deliver_ue_ctxt_modif_req(void *deliver_pdu_data, ue_id_t ue_id, int srb_id, char *buf, int size, int sdu_id) { DevAssert(deliver_pdu_data != NULL); @@ -399,3 +384,52 @@ void nr_HO_F1_trigger_telnet(gNB_RRC_INST *rrc, uint32_t rrc_ue_id) nr_rrc_trigger_f1_ho(rrc, ue, source_du, target_du); } + +/** @brief Generate the HandoverPreparationInformation to be carried + * in the RRC Container (9.3.1.29 of 3GPP TS 38.413) of the Source + * NG-RAN Node to Target NG-RAN Node Transparent Container IE */ +static byte_array_t rrc_gNB_generate_HandoverPreparationInformation(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue, int serving_pci) +{ + nr_rrc_reconfig_param_t params = get_RRCReconfiguration_params(rrc, ue, 0, false); + params.ue_cap = ue->ue_cap_buffer; + + byte_array_t hoPrepInfo = get_HandoverPreparationInformation(¶ms, serving_pci); + free_RRCReconfiguration_params(params); + + if (hoPrepInfo.len < 0) { + LOG_E(NR_RRC, "HandoverPreparationInformation generation failed for UE %d\n", ue->rrc_ue_id); + return hoPrepInfo; + } + + LOG_D(NR_RRC, "HO LOG: Handover Preparation for UE %lu Encoded (%zd bytes)\n", ue->amf_ue_ngap_id, hoPrepInfo.len); + + return hoPrepInfo; +} + +/** @brief Trigger N2 handover on source gNB: + * 1) Prepare RRC Container with HandoverPreparationInformation message + * 2) send NGAP Handover Required message */ +void nr_rrc_trigger_n2_ho(gNB_RRC_INST *rrc, + gNB_RRC_UE_t *ue, + int serving_pci, + const nr_neighbour_cell_t *neighbour_config) +{ + byte_array_t hoPrepInfo = rrc_gNB_generate_HandoverPreparationInformation(rrc, ue, serving_pci); + if (hoPrepInfo.len < 0) { + free_byte_array(hoPrepInfo); + LOG_E(NR_RRC, "Failed to trigger N2 handover on source gNB for UE %x\n", ue->rrc_ue_id); + return; + } + + // allocate context for source + if (ue->ho_context != NULL) { + LOG_E(NR_RRC, "Ongoing handover for UE %d, cannot trigger new\n", ue->rrc_ue_id); + return; + } + + ue->ho_context = alloc_ho_ctx(HO_CTX_SOURCE); + ue->ho_context->source->du = get_du_for_ue(rrc, ue->rrc_ue_id); + + rrc_gNB_send_NGAP_HANDOVER_REQUIRED(rrc, ue, neighbour_config, hoPrepInfo); + free_byte_array(hoPrepInfo); +} diff --git a/openair2/RRC/NR/rrc_gNB_mobility.h b/openair2/RRC/NR/rrc_gNB_mobility.h index a907b3c472..3169ea23c0 100644 --- a/openair2/RRC/NR/rrc_gNB_mobility.h +++ b/openair2/RRC/NR/rrc_gNB_mobility.h @@ -23,6 +23,7 @@ #include #include "common/utils/ds/byte_array.h" +#include "nr_rrc_defs.h" /* forward declarations */ typedef struct gNB_RRC_INST_s gNB_RRC_INST; @@ -78,4 +79,9 @@ nr_handover_context_t *alloc_ho_ctx(ho_ctx_type_t type); void nr_rrc_trigger_f1_ho(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue, nr_rrc_du_container_t *source_du, nr_rrc_du_container_t *target_du); void nr_rrc_finalize_ho(gNB_RRC_UE_t *ue); +void nr_rrc_trigger_n2_ho(gNB_RRC_INST *rrc, + gNB_RRC_UE_t *ue, + int serving_pci, + const nr_neighbour_cell_t *neighbour_config); + #endif /* RRC_GNB_MOBILITY_H_ */ From 92abefb815a4f7067b9f0e93a8e0445fb750724e Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Fri, 7 Mar 2025 12:15:20 +0100 Subject: [PATCH 717/964] Add NGAP Handover Failure message This message is sent from the Target NG-RAN to the AMF. The commit introduces: * NGAP encoding function * N2 callback for the target gNB * handle the failure in RRC, inform NGAP * send NGAP message to AMF via SCTP Note: UE context in NGAP is fetched from the amf_ue_ngap_id Co-authored-by: batuhan duyuler --- openair2/COMMON/ngap_messages_def.h | 1 + openair2/COMMON/ngap_messages_types.h | 10 +++++ openair2/RRC/NR/rrc_gNB_NGAP.c | 10 ++++- openair2/RRC/NR/rrc_gNB_NGAP.h | 2 + openair2/RRC/NR/rrc_gNB_mobility.c | 13 ++++++ openair2/RRC/NR/rrc_gNB_mobility.h | 2 + openair3/NGAP/ngap_gNB.c | 44 ++++++++++++++++++++ openair3/NGAP/ngap_gNB_mobility_management.c | 33 +++++++++++++++ openair3/NGAP/ngap_gNB_mobility_management.h | 1 + openair3/NGAP/ngap_gNB_ue_context.c | 6 +++ openair3/NGAP/ngap_gNB_ue_context.h | 1 + 11 files changed, 122 insertions(+), 1 deletion(-) diff --git a/openair2/COMMON/ngap_messages_def.h b/openair2/COMMON/ngap_messages_def.h index eea62d6c00..9cf975d34a 100644 --- a/openair2/COMMON/ngap_messages_def.h +++ b/openair2/COMMON/ngap_messages_def.h @@ -72,6 +72,7 @@ MESSAGE_DEF(NGAP_PDUSESSION_SETUP_RESP , MESSAGE_PRIORITY_MED, ngap_pdu MESSAGE_DEF(NGAP_PDUSESSION_MODIFY_RESP , MESSAGE_PRIORITY_MED, ngap_pdusession_modify_resp_t , ngap_pdusession_modify_resp) MESSAGE_DEF(NGAP_PDUSESSION_RELEASE_RESPONSE , MESSAGE_PRIORITY_MED, ngap_pdusession_release_resp_t , ngap_pdusession_release_resp) MESSAGE_DEF(NGAP_HANDOVER_REQUIRED, MESSAGE_PRIORITY_MED, ngap_handover_required_t, ngap_handover_required) +MESSAGE_DEF(NGAP_HANDOVER_FAILURE, MESSAGE_PRIORITY_MED, ngap_handover_failure_t, ngap_handover_failure) /* NGAP -> RRC messages */ MESSAGE_DEF(NGAP_DOWNLINK_NAS , MESSAGE_PRIORITY_MED, ngap_downlink_nas_t , ngap_downlink_nas ) diff --git a/openair2/COMMON/ngap_messages_types.h b/openair2/COMMON/ngap_messages_types.h index 57ecc51e79..9a3e7a9a45 100644 --- a/openair2/COMMON/ngap_messages_types.h +++ b/openair2/COMMON/ngap_messages_types.h @@ -66,6 +66,8 @@ #define NGAP_PDUSESSION_MODIFY_REQ(mSGpTR) (mSGpTR)->ittiMsg.ngap_pdusession_modify_req #define NGAP_PAGING_IND(mSGpTR) (mSGpTR)->ittiMsg.ngap_paging_ind #define NGAP_HANDOVER_REQUIRED(mSGpTR) (mSGpTR)->ittiMsg.ngap_handover_required +#define NGAP_HANDOVER_FAILURE(mSGpTR) (mSGpTR)->ittiMsg.ngap_handover_failure + #define NGAP_UE_CONTEXT_RELEASE_REQ(mSGpTR) (mSGpTR)->ittiMsg.ngap_ue_release_req #define NGAP_PDUSESSION_RELEASE_COMMAND(mSGpTR) (mSGpTR)->ittiMsg.ngap_pdusession_release_command #define NGAP_PDUSESSION_RELEASE_RESPONSE(mSGpTR) (mSGpTR)->ittiMsg.ngap_pdusession_release_resp @@ -548,6 +550,14 @@ typedef struct { source_to_target_transparent_container_t *source2target; } ngap_handover_required_t; +/* 3GPP TS 38.413 9.2.3.6 */ +typedef struct { + // AMF UE NGAP ID (M) + uint64_t amf_ue_ngap_id; + // Cause (M) + ngap_cause_t cause; +} ngap_handover_failure_t; + typedef struct ngap_ue_cap_info_ind_s { uint32_t gNB_ue_ngap_id; byte_array_t ue_radio_cap; diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index 5632e5932b..9b4096da4b 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -1063,7 +1063,15 @@ int rrc_gNB_process_NGAP_UE_CONTEXT_RELEASE_REQ(MessageDef *msg_p, instance_t in } } -//----------------------------------------------------------------------------- +/** @brief Sends the NG Handover Failure from the Target NG-RAN to the AMF */ +void rrc_gNB_send_NGAP_HANDOVER_FAILURE(gNB_RRC_INST *rrc, ngap_handover_failure_t *msg) +{ + LOG_I(NR_RRC, "Send NG Handover Failure message (amf_ue_ngap_id %ld) with cause %d \n ", msg->amf_ue_ngap_id, msg->cause.value); + MessageDef *msg_p = itti_alloc_new_message(TASK_RRC_GNB, 0, NGAP_HANDOVER_FAILURE); + NGAP_HANDOVER_FAILURE(msg_p) = *msg; + itti_send_msg_to_task(TASK_NGAP, rrc->module_id, msg_p); +} + /* * Process the NG command NGAP_UE_CONTEXT_RELEASE_COMMAND, sent by AMF. * The gNB should remove all pdu session, NG context, and other context of the UE. diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.h b/openair2/RRC/NR/rrc_gNB_NGAP.h index fd8cb31ff1..7c52843c0f 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.h +++ b/openair2/RRC/NR/rrc_gNB_NGAP.h @@ -94,4 +94,6 @@ void rrc_gNB_send_NGAP_HANDOVER_REQUIRED(gNB_RRC_INST *rrc, const nr_neighbour_cell_t *neighbourCellConfiguration, const byte_array_t hoPrepInfo); +void rrc_gNB_send_NGAP_HANDOVER_FAILURE(gNB_RRC_INST *rrc, ngap_handover_failure_t *msg); + #endif diff --git a/openair2/RRC/NR/rrc_gNB_mobility.c b/openair2/RRC/NR/rrc_gNB_mobility.c index fa2eead5ca..7b1324d6e5 100644 --- a/openair2/RRC/NR/rrc_gNB_mobility.c +++ b/openair2/RRC/NR/rrc_gNB_mobility.c @@ -406,6 +406,19 @@ static byte_array_t rrc_gNB_generate_HandoverPreparationInformation(gNB_RRC_INST return hoPrepInfo; } +/** @brief Callback function to trigger NG Handover Failure on the target gNB, to inform the AMF + * that the preparation of resources has failed (e.g. unsatisfied criteria, gNB is already loaded). + * This message represents an Unsuccessful Outcome of the Handover Resource Allocation */ +void nr_rrc_n2_ho_failure(gNB_RRC_INST *rrc, uint32_t gnb_ue_id, ngap_handover_failure_t *msg) +{ + LOG_I(NR_RRC, "Triggering N2 Handover Failure\n"); + rrc_gNB_send_NGAP_HANDOVER_FAILURE(rrc, msg); + LOG_I(NR_RRC, "Send UE Context Release for gnb_ue_id %d\n", gnb_ue_id); + rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(rrc, gnb_ue_id); + rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_REQ(rrc->module_id, ue_context_p, msg->cause); + return; +} + /** @brief Trigger N2 handover on source gNB: * 1) Prepare RRC Container with HandoverPreparationInformation message * 2) send NGAP Handover Required message */ diff --git a/openair2/RRC/NR/rrc_gNB_mobility.h b/openair2/RRC/NR/rrc_gNB_mobility.h index 3169ea23c0..0bb5faf7fa 100644 --- a/openair2/RRC/NR/rrc_gNB_mobility.h +++ b/openair2/RRC/NR/rrc_gNB_mobility.h @@ -53,6 +53,7 @@ typedef struct nr_ho_source_cu { /* acknowledgement of handover request. buf+len is the RRC Reconfiguration */ typedef void (*ho_req_ack_t)(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue); typedef void (*ho_success_t)(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue); + typedef struct nr_ho_target_cu { /// pointer to the (target) DU structure const nr_rrc_du_container_t *du; @@ -78,6 +79,7 @@ nr_handover_context_t *alloc_ho_ctx(ho_ctx_type_t type); void nr_rrc_trigger_f1_ho(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue, nr_rrc_du_container_t *source_du, nr_rrc_du_container_t *target_du); void nr_rrc_finalize_ho(gNB_RRC_UE_t *ue); +void nr_rrc_n2_ho_failure(gNB_RRC_INST *rrc, uint32_t gnb_ue_id, ngap_handover_failure_t *msg); void nr_rrc_trigger_n2_ho(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue, diff --git a/openair3/NGAP/ngap_gNB.c b/openair3/NGAP/ngap_gNB.c index 4b4fc2f850..58511f307c 100644 --- a/openair3/NGAP/ngap_gNB.c +++ b/openair3/NGAP/ngap_gNB.c @@ -334,6 +334,46 @@ void ngap_gNB_init(void) { itti_mark_task_ready(TASK_NGAP); } +static int ngap_gNB_handover_failure(instance_t instance, const ngap_handover_failure_t *msg) +{ + ngap_gNB_ue_context_t *ue_context_p = NULL; + uint8_t *buffer = NULL; + uint32_t length; + + ngap_gNB_instance_t *ngap_gNB_instance_p = ngap_gNB_get_instance(instance); + DevAssert(msg != NULL); + DevAssert(ngap_gNB_instance_p != NULL); + + NGAP_NGAP_PDU_t *pdu = encode_ng_handover_failure(msg); + if (!pdu) { + NGAP_ERROR("Failed to encode NG Handover Failure\n"); + ASN_STRUCT_FREE(asn_DEF_NGAP_NGAP_PDU, pdu); + return -1; + } + + if (ngap_gNB_encode_pdu(pdu, &buffer, &length) < 0) { + NGAP_ERROR("Failed to encode HANDOVER FAILURE MESSAGE\n"); + ASN_STRUCT_FREE(asn_DEF_NGAP_NGAP_PDU, pdu); + return -1; + } + + ngap_gNB_amf_data_t *amf = ngap_gNB_get_AMF_from_instance(ngap_gNB_instance_p); + if ((ue_context_p = ngap_get_ue_context_from_amf_ue_ngap_id(msg->amf_ue_ngap_id)) == NULL) { + //The context for this gNB ue ngap id doesn't exist in the map of gNB UEs + NGAP_WARN("Failed to find UE context associated with amf_ue_ngap_id=%ld\n", msg->amf_ue_ngap_id); + /*In this case there is no ue context since HO REQ might be failed at preprocessing stage itself. + * so sctp message send to AMF based on its assoc_id */ + ngap_gNB_itti_send_sctp_data_req(ngap_gNB_instance_p->instance, amf->assoc_id, buffer, length, 0); + ASN_STRUCT_FREE(asn_DEF_NGAP_NGAP_PDU, pdu); + return -1; + } + + ngap_gNB_itti_send_sctp_data_req(ngap_gNB_instance_p->instance, amf->assoc_id, buffer, length, amf->nextstream); + ASN_STRUCT_FREE(asn_DEF_NGAP_NGAP_PDU, &pdu); + + return 0; +} + void *ngap_gNB_process_itti_msg(void *notUsed) { MessageDef *received_msg = NULL; int result; @@ -415,6 +455,10 @@ void *ngap_gNB_process_itti_msg(void *notUsed) { } break; + case NGAP_HANDOVER_FAILURE: + ngap_gNB_handover_failure(instance, &NGAP_HANDOVER_FAILURE(received_msg)); + break; + default: NGAP_ERROR("Received unhandled message: %d:%s\n", ITTI_MSG_ID(received_msg), ITTI_MSG_NAME(received_msg)); break; diff --git a/openair3/NGAP/ngap_gNB_mobility_management.c b/openair3/NGAP/ngap_gNB_mobility_management.c index 4f116c8f34..9d84fccd09 100644 --- a/openair3/NGAP/ngap_gNB_mobility_management.c +++ b/openair3/NGAP/ngap_gNB_mobility_management.c @@ -191,3 +191,36 @@ NGAP_NGAP_PDU_t *encode_ng_handover_required(const ngap_handover_required_t *msg return pdu; } + +NGAP_NGAP_PDU_t *encode_ng_handover_failure(const ngap_handover_failure_t *msg) +{ + NGAP_NGAP_PDU_t *pdu = malloc_or_fail(sizeof(*pdu)); + + /* Prepare the NGAP message to encode */ + pdu->present = NGAP_NGAP_PDU_PR_unsuccessfulOutcome; + asn1cCalloc(pdu->choice.unsuccessfulOutcome, head); + head->procedureCode = NGAP_ProcedureCode_id_HandoverResourceAllocation; + head->criticality = NGAP_Criticality_reject; + head->value.present = NGAP_UnsuccessfulOutcome__value_PR_HandoverFailure; + NGAP_HandoverFailure_t *out = &head->value.choice.HandoverFailure; + + // AMF_UE_NGAP_ID (M) + { + asn1cSequenceAdd(out->protocolIEs.list, NGAP_HandoverFailureIEs_t, ie); + ie->id = NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID; + ie->criticality = NGAP_Criticality_reject; + ie->value.present = NGAP_HandoverFailureIEs__value_PR_AMF_UE_NGAP_ID; + asn_uint642INTEGER(&ie->value.choice.AMF_UE_NGAP_ID, msg->amf_ue_ngap_id); + } + + // Cause (M) + { + asn1cSequenceAdd(out->protocolIEs.list, NGAP_HandoverFailureIEs_t, ie); + ie->id = NGAP_ProtocolIE_ID_id_Cause; + ie->criticality = NGAP_Criticality_ignore; + ie->value.present = NGAP_HandoverFailureIEs__value_PR_Cause; + encode_ngap_cause(&ie->value.choice.Cause, &msg->cause); + } + + return pdu; +} diff --git a/openair3/NGAP/ngap_gNB_mobility_management.h b/openair3/NGAP/ngap_gNB_mobility_management.h index b3926877eb..6f5cdde742 100644 --- a/openair3/NGAP/ngap_gNB_mobility_management.h +++ b/openair3/NGAP/ngap_gNB_mobility_management.h @@ -27,5 +27,6 @@ #include "ngap_messages_types.h" NGAP_NGAP_PDU_t *encode_ng_handover_required(const ngap_handover_required_t *msg); +NGAP_NGAP_PDU_t *encode_ng_handover_failure(const ngap_handover_failure_t *msg); #endif /* NGAP_GNB_MOBILITY_MANAGEMENT_H_ */ diff --git a/openair3/NGAP/ngap_gNB_ue_context.c b/openair3/NGAP/ngap_gNB_ue_context.c index d0949b88c2..994271d822 100644 --- a/openair3/NGAP/ngap_gNB_ue_context.c +++ b/openair3/NGAP/ngap_gNB_ue_context.c @@ -76,6 +76,12 @@ struct ngap_gNB_ue_context_s *ngap_get_ue_context(uint32_t gNB_ue_ngap_id) return RB_FIND(ngap_ue_map, &ngap_ue_head, &temp); } +ngap_gNB_ue_context_t *ngap_get_ue_context_from_amf_ue_ngap_id(uint32_t amf_ue_ngap_id) +{ + ngap_gNB_ue_context_t temp = {.amf_ue_ngap_id = amf_ue_ngap_id}; + return RB_FIND(ngap_ue_map, &ngap_ue_head, &temp); +} + struct ngap_gNB_ue_context_s *ngap_detach_ue_context(uint32_t gNB_ue_ngap_id) { struct ngap_gNB_ue_context_s *tmp = ngap_get_ue_context(gNB_ue_ngap_id); diff --git a/openair3/NGAP/ngap_gNB_ue_context.h b/openair3/NGAP/ngap_gNB_ue_context.h index aaf9e83bbc..1022f2f4c3 100644 --- a/openair3/NGAP/ngap_gNB_ue_context.h +++ b/openair3/NGAP/ngap_gNB_ue_context.h @@ -81,6 +81,7 @@ typedef struct ngap_gNB_ue_context_s { void ngap_store_ue_context(const ngap_gNB_ue_context_t *ue_desc_p); ngap_gNB_ue_context_t *ngap_get_ue_context(uint32_t gNB_ue_ngap_id); +ngap_gNB_ue_context_t *ngap_get_ue_context_from_amf_ue_ngap_id(uint32_t amf_ue_ngap_id); ngap_gNB_ue_context_t *ngap_detach_ue_context(uint32_t gNB_ue_ngap_id); #endif /* NGAP_GNB_UE_CONTEXT_H_ */ From 461cfb7911828ce1db9a716a206d428dd9a96200 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Tue, 11 Mar 2025 15:37:07 +0100 Subject: [PATCH 718/964] Add NGAP Handover Request decoding and RRC handler This commit introduces the NG Mobility Management Procedure known as Handover Resource Allocation. The inbound message is sent by the AMF and is known as Handover Request. Major changes: (0) Add Handover Resource Allocation initiating message decoding * add case for NGAP initiating message and unsuccessful message decoding (1) handle Handover Request on the target NG-RAN (2) decode NG Handover Request message (3) process payload, e.g. create UE context, store IDs, set UP security and trigger bearer setup Co-authored-by: batuhan duyuler --- openair2/COMMON/ngap_messages_def.h | 1 + openair2/COMMON/ngap_messages_types.h | 68 ++++++-- openair2/RRC/NR/nr_rrc_proto.h | 1 + openair2/RRC/NR/rrc_gNB.c | 7 +- openair2/RRC/NR/rrc_gNB_NGAP.c | 101 +++++++++++- openair2/RRC/NR/rrc_gNB_NGAP.h | 3 + openair2/RRC/NR/rrc_gNB_mobility.c | 2 + openair2/RRC/NR/rrc_gNB_mobility.h | 2 + openair3/NGAP/ngap_common.c | 130 +++++++++++++++ openair3/NGAP/ngap_common.h | 3 + openair3/NGAP/ngap_gNB_decoder.c | 6 + openair3/NGAP/ngap_gNB_encoder.c | 16 +- openair3/NGAP/ngap_gNB_handlers.c | 115 ++++---------- openair3/NGAP/ngap_gNB_mobility_management.c | 158 +++++++++++++++++++ openair3/NGAP/ngap_gNB_mobility_management.h | 1 + openair3/NGAP/ngap_msg_includes.h | 15 ++ 16 files changed, 525 insertions(+), 104 deletions(-) diff --git a/openair2/COMMON/ngap_messages_def.h b/openair2/COMMON/ngap_messages_def.h index 9cf975d34a..53b16350e1 100644 --- a/openair2/COMMON/ngap_messages_def.h +++ b/openair2/COMMON/ngap_messages_def.h @@ -83,6 +83,7 @@ MESSAGE_DEF(NGAP_PDUSESSION_SETUP_REQ , MESSAGE_PRIORITY_MED, ngap_pd MESSAGE_DEF(NGAP_PDUSESSION_MODIFY_REQ , MESSAGE_PRIORITY_MED, ngap_pdusession_modify_req_t , ngap_pdusession_modify_req ) MESSAGE_DEF(NGAP_PDUSESSION_RELEASE_COMMAND , MESSAGE_PRIORITY_MED, ngap_pdusession_release_command_t , ngap_pdusession_release_command) MESSAGE_DEF(NGAP_UE_CONTEXT_RELEASE_COMMAND, MESSAGE_PRIORITY_MED, ngap_ue_release_command_t , ngap_ue_release_command) +MESSAGE_DEF(NGAP_HANDOVER_REQUEST, MESSAGE_PRIORITY_MED, ngap_handover_request_t, ngap_handover_request) /* NGAP <-> RRC messages (can be initiated either by MME or gNB) */ MESSAGE_DEF(NGAP_UE_CONTEXT_RELEASE_REQ , MESSAGE_PRIORITY_MED, ngap_ue_release_req_t , ngap_ue_release_req) diff --git a/openair2/COMMON/ngap_messages_types.h b/openair2/COMMON/ngap_messages_types.h index 9a3e7a9a45..49212b257c 100644 --- a/openair2/COMMON/ngap_messages_types.h +++ b/openair2/COMMON/ngap_messages_types.h @@ -67,6 +67,7 @@ #define NGAP_PAGING_IND(mSGpTR) (mSGpTR)->ittiMsg.ngap_paging_ind #define NGAP_HANDOVER_REQUIRED(mSGpTR) (mSGpTR)->ittiMsg.ngap_handover_required #define NGAP_HANDOVER_FAILURE(mSGpTR) (mSGpTR)->ittiMsg.ngap_handover_failure +#define NGAP_HANDOVER_REQUEST(mSGpTR) (mSGpTR)->ittiMsg.ngap_handover_request #define NGAP_UE_CONTEXT_RELEASE_REQ(mSGpTR) (mSGpTR)->ittiMsg.ngap_ue_release_req #define NGAP_PDUSESSION_RELEASE_COMMAND(mSGpTR) (mSGpTR)->ittiMsg.ngap_pdusession_release_command @@ -229,6 +230,15 @@ typedef struct ngap_mobility_restriction_s{ plmn_id_t serving_plmn; }ngap_mobility_restriction_t; +/* PDU Session Resource Setup Request Transfer (9.3.4.1 3GPP TS 38.413) */ +typedef struct { + uint8_t nb_qos; + pdusession_level_qos_parameter_t qos[QOSFLOW_MAX_VALUE]; + pdu_session_type_t pdu_session_type; + // UPF endpoint of the NG-U (N3) transport bearer + gtpu_tunnel_t n3_incoming; +} pdusession_transfer_t; + typedef enum pdusession_qosflow_mapping_ind_e{ QOSFLOW_MAPPING_INDICATION_UL = 0, QOSFLOW_MAPPING_INDICATION_DL = 1, @@ -558,6 +568,55 @@ typedef struct { ngap_cause_t cause; } ngap_handover_failure_t; +typedef struct { + // Next-Hop NH + uint8_t next_hop[SECURITY_KEY_LENGTH]; + // Next Hop Chaining Count + uint8_t next_hop_chain_count; +} ngap_security_context_t; + +/* Handover Request (3GPP TS 38.413 9.2.3.4) + PDU Session Resource Setup Item */ +typedef struct { + // PDU Session ID + uint8_t pdusession_id; + pdu_session_type_t pdu_session_type; + // S-NSSAI + nssai_t nssai; + // Handover Required Transfer + pdusession_transfer_t pdusessionTransfer; +} ho_request_pdusession_t; + +/* 3GPP TS 38.413 9.2.3.4 */ +typedef struct { + // AMF UE NGAP ID + uint64_t amf_ue_ngap_id; + // Handover Type + ho_type_t ho_type; + // Cause + ngap_cause_t cause; + // UE Aggregate Maximum Bit Rate + ngap_ambr_t ue_ambr; + // UE Security Capabilities + ngap_security_capabilities_t security_capabilities; + // Security Context + ngap_security_context_t security_context; + // PDU Session Resource Setup List + uint8_t nb_of_pdusessions; + ho_request_pdusession_t pduSessionResourceSetupList[NGAP_MAX_PDU_SESSION]; + // Allowed NSSAI + uint8_t nb_allowed_nssais; + nssai_t allowed_nssai[8]; + // Source to Target Transparent Container contents + uint64_t nr_cell_id; + byte_array_t ue_ho_prep_info; + byte_array_t ue_cap; + // Mobility Restriction List + ngap_mobility_restriction_t *mobility_restriction; + // GUAMI + nr_guami_t guami; +} ngap_handover_request_t; + typedef struct ngap_ue_cap_info_ind_s { uint32_t gNB_ue_ngap_id; byte_array_t ue_radio_cap; @@ -628,15 +687,6 @@ typedef struct ngap_downlink_nas_s { byte_array_t nas_pdu; } ngap_downlink_nas_t; -/* PDU Session Resource Setup Request Transfer (9.3.4.1 3GPP TS 38.413) */ -typedef struct { - uint8_t nb_qos; - pdusession_level_qos_parameter_t qos[QOSFLOW_MAX_VALUE]; - pdu_session_type_t pdu_session_type; - // UPF endpoint of the NG-U (N3) transport bearer - gtpu_tunnel_t n3_incoming; -} pdusession_transfer_t; - /* PDU Session Resource Setup/Modify Request Item */ typedef struct { int pdusession_id; diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h index a1918bdd34..bbaaaf5774 100644 --- a/openair2/RRC/NR/nr_rrc_proto.h +++ b/openair2/RRC/NR/nr_rrc_proto.h @@ -127,5 +127,6 @@ f1ap_qos_flow_param_t get_qos_char_from_qos_flow_param(const pdusession_level_qo void openair_rrc_gNB_configuration(gNB_RRC_INST *rrc, gNB_RrcConfigurationReq *configuration); NR_SRB_ToAddModList_t *createSRBlist(gNB_RRC_UE_t *ue, uint8_t reestablish); NR_DRB_ToAddModList_t *createDRBlist(gNB_RRC_UE_t *ue, bool reestablish); +void activate_srb(gNB_RRC_UE_t *UE, int srb_id); #endif diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index ad36b9c10d..48ea8e760e 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -354,7 +354,7 @@ void freeSRBlist(NR_SRB_ToAddModList_t *l) ASN_STRUCT_FREE(asn_DEF_NR_SRB_ToAddModList, l); } -static void activate_srb(gNB_RRC_UE_t *UE, int srb_id) +void activate_srb(gNB_RRC_UE_t *UE, int srb_id) { AssertFatal(srb_id == 1 || srb_id == 2, "handling only SRB 1 or 2\n"); if (UE->Srb[srb_id].Active == 1) { @@ -2944,6 +2944,11 @@ void *rrc_gnb_task(void *args_p) { rrc_gNB_process_PAGING_IND(msg_p, instance); break; + case NGAP_HANDOVER_REQUEST: + rrc_gNB_process_Handover_Request(RC.nrrrc[instance], instance, &NGAP_HANDOVER_REQUEST(msg_p)); + rrc_gNB_free_Handover_Request(&NGAP_HANDOVER_REQUEST(msg_p)); // Free transfered NG message + break; + default: LOG_E(NR_RRC, "[gNB %ld] Received unexpected message %s\n", instance, msg_name_p); break; diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index 9b4096da4b..68aa502f77 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -83,6 +83,8 @@ #include "rrc_messages_types.h" #include "s1ap_messages_types.h" #include "uper_encoder.h" +#include "rrc_gNB_mobility.h" +#include "rrc_gNB_du.h" #ifdef E2_AGENT #include "openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc_extern.h" @@ -163,18 +165,24 @@ static nr_guami_t get_guami(const uint32_t amf_Id, const plmn_id_t plmn) return guami; } +/** @brief Copy NGAP PDU Session Transfer item to RRC pdusession_t struct */ +static void cp_pdusession_transfer_to_pdusession(pdusession_t *dst, const pdusession_transfer_t *src) +{ + dst->nb_qos = src->nb_qos; + for (uint8_t i = 0; i < src->nb_qos && i < QOSFLOW_MAX_VALUE; ++i) { + dst->qos[i] = src->qos[i]; + } + dst->pdu_session_type = src->pdu_session_type; + dst->n3_incoming = src->n3_incoming; +} + /** @brief Copy NGAP PDU Session Resource item to RRC pdusession_t struct */ static void cp_pdusession_resource_item_to_pdusession(pdusession_t *dst, const pdusession_resource_item_t *src) { dst->pdusession_id = src->pdusession_id; dst->nas_pdu = src->nas_pdu; - dst->nb_qos = src->pdusessionTransfer.nb_qos; - for (uint8_t i = 0; i < src->pdusessionTransfer.nb_qos && i < QOSFLOW_MAX_VALUE; ++i) { - dst->qos[i] = src->pdusessionTransfer.qos[i]; - } - dst->pdu_session_type = src->pdusessionTransfer.pdu_session_type; - dst->n3_incoming = src->pdusessionTransfer.n3_incoming; dst->nssai = src->nssai; + cp_pdusession_transfer_to_pdusession(dst, &src->pdusessionTransfer); } /** @@ -1072,6 +1080,87 @@ void rrc_gNB_send_NGAP_HANDOVER_FAILURE(gNB_RRC_INST *rrc, ngap_handover_failure itti_send_msg_to_task(TASK_NGAP, rrc->module_id, msg_p); } +/** @brief Process NG Handover Request message (8.4.2.2 3GPP TS 38.413) */ +int rrc_gNB_process_Handover_Request(gNB_RRC_INST *rrc, instance_t instance, ngap_handover_request_t *msg) +{ + LOG_I(NR_RRC, "Received Handover Request (on PCI=%lu) \n", msg->nr_cell_id); + struct nr_rrc_du_container_t *du = get_du_by_cell_id(rrc, msg->nr_cell_id); + if (du == NULL) { + /* Cell Not Found! Return HO Request Failure*/ + LOG_E(RRC, "Failed to process Handover Request: no DU found with PCI=%lu \n", msg->nr_cell_id); + ngap_handover_failure_t fail = { + .amf_ue_ngap_id = msg->amf_ue_ngap_id, + .cause.type = NGAP_CAUSE_RADIO_NETWORK, + .cause.value = NGAP_CAUSE_RADIO_NETWORK_RADIO_RESOURCES_NOT_AVAILABLE, + }; + rrc_gNB_send_NGAP_HANDOVER_FAILURE(rrc, &fail); + return -1; + } + + // Create UE context + sctp_assoc_t curr_assoc_id = du->assoc_id; + rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_create_ue_context(curr_assoc_id, UINT16_MAX, rrc, UINT64_MAX, UINT32_MAX); + gNB_RRC_UE_t *UE = &ue_context_p->ue_context; + + // allocate context for target + if (UE->ho_context != NULL) { + LOG_E(NR_RRC, "Ongoing handover for UE %d, cannot trigger new\n", UE->rrc_ue_id); + return -1; + } + UE->ho_context = alloc_ho_ctx(HO_CTX_TARGET); + + // Store IDs in UE context + UE->amf_ue_ngap_id = msg->amf_ue_ngap_id; + UE->ue_guami = msg->guami; + UE->ho_context->target->ue_ho_prep_info = copy_byte_array(msg->ue_ho_prep_info); + // store the received UE Security Capabilities in the UE context + FREE_AND_ZERO_BYTE_ARRAY(UE->ue_cap_buffer); + UE->ue_cap_buffer = copy_byte_array(msg->ue_cap); + + /* store the received Security Context in the UE context + and take it into use as defined in TS 33.501 */ + set_UE_security_algos(rrc, UE, &msg->security_capabilities); + UE->nh_ncc = msg->security_context.next_hop_chain_count; + memcpy(UE->nh, msg->security_context.next_hop, SECURITY_KEY_LENGTH); + // Reset KgNB + memset(UE->kgnb, 0, SECURITY_KEY_LENGTH); + // Derive KgNB* + const f1ap_served_cell_info_t *cell_info = &du->setup_req->cell[0].info; + uint32_t ssb_arfcn = get_ssb_arfcn(du); + nr_derive_key_ng_ran_star(cell_info->nr_pci, ssb_arfcn, UE->nh, UE->kgnb); + UE->as_security_active = true; + // Activate SRBs + activate_srb(UE, SRB1); + activate_srb(UE, SRB2); + nr_rrc_pdcp_config_security(UE, false); + + // Copy PDU Session Resource Setup item to RRC struct and do PDU Session Resource Setup procedure + pdusession_t to_setup = { + .nssai = msg->pduSessionResourceSetupList->nssai, + .pdu_session_type = msg->pduSessionResourceSetupList->pdu_session_type , + .pdusession_id = msg->pduSessionResourceSetupList->pdusession_id, + }; + cp_pdusession_transfer_to_pdusession(&to_setup, &msg->pduSessionResourceSetupList->pdusessionTransfer); + if (!trigger_bearer_setup(rrc, UE, msg->nb_of_pdusessions, &to_setup, msg->ue_ambr.br_dl)) { + LOG_E(NR_RRC, "Failed to establish PDU session: handover failed\n"); + ngap_handover_failure_t fail = { + .amf_ue_ngap_id = msg->amf_ue_ngap_id, + .cause.type = NGAP_CAUSE_RADIO_NETWORK, + .cause.value = NGAP_CAUSE_RADIO_NETWORK_HO_FAILURE_IN_TARGET_5GC_NGRAN_NODE_OR_TARGET_SYSTEM, + }; + rrc_gNB_send_NGAP_HANDOVER_FAILURE(rrc, &fail); + } + + return 0; +} + +void rrc_gNB_free_Handover_Request(ngap_handover_request_t *msg) +{ + free_byte_array(msg->ue_cap); + free_byte_array(msg->ue_ho_prep_info); + free(msg->mobility_restriction); +} + /* * Process the NG command NGAP_UE_CONTEXT_RELEASE_COMMAND, sent by AMF. * The gNB should remove all pdu session, NG context, and other context of the UE. diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.h b/openair2/RRC/NR/rrc_gNB_NGAP.h index 7c52843c0f..53e2b51f8c 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.h +++ b/openair2/RRC/NR/rrc_gNB_NGAP.h @@ -96,4 +96,7 @@ void rrc_gNB_send_NGAP_HANDOVER_REQUIRED(gNB_RRC_INST *rrc, void rrc_gNB_send_NGAP_HANDOVER_FAILURE(gNB_RRC_INST *rrc, ngap_handover_failure_t *msg); +int rrc_gNB_process_Handover_Request(gNB_RRC_INST *rrc, instance_t instance, ngap_handover_request_t *msg); +void rrc_gNB_free_Handover_Request(ngap_handover_request_t *msg); + #endif diff --git a/openair2/RRC/NR/rrc_gNB_mobility.c b/openair2/RRC/NR/rrc_gNB_mobility.c index 7b1324d6e5..c9d60422e8 100644 --- a/openair2/RRC/NR/rrc_gNB_mobility.c +++ b/openair2/RRC/NR/rrc_gNB_mobility.c @@ -57,6 +57,8 @@ nr_handover_context_t *alloc_ho_ctx(ho_ctx_type_t type) static void free_ho_ctx(nr_handover_context_t *ho_ctx) { free(ho_ctx->source); + if (ho_ctx->target) + FREE_AND_ZERO_BYTE_ARRAY(ho_ctx->target->ue_ho_prep_info); free(ho_ctx->target); free(ho_ctx); } diff --git a/openair2/RRC/NR/rrc_gNB_mobility.h b/openair2/RRC/NR/rrc_gNB_mobility.h index 0bb5faf7fa..77b90ac3e0 100644 --- a/openair2/RRC/NR/rrc_gNB_mobility.h +++ b/openair2/RRC/NR/rrc_gNB_mobility.h @@ -63,6 +63,8 @@ typedef struct nr_ho_target_cu { uint32_t du_ue_id; /// new (target) RNTI (as for du_ue_id) rnti_t new_rnti; + /// Handover Preparation Buffer + byte_array_t ue_ho_prep_info; /// function pointer to announce handover request acknowledgment ho_req_ack_t ho_req_ack; /// function pointer to announce handover success diff --git a/openair3/NGAP/ngap_common.c b/openair3/NGAP/ngap_common.c index b51c8e80de..9e3e2e9d13 100644 --- a/openair3/NGAP/ngap_common.c +++ b/openair3/NGAP/ngap_common.c @@ -66,6 +66,43 @@ void encode_ngap_cause(NGAP_Cause_t *out, const ngap_cause_t *in) } } +ngap_cause_t decode_ngap_cause(const NGAP_Cause_t *in) +{ + ngap_cause_t out = {0}; + switch (in->present) { + case NGAP_Cause_PR_radioNetwork: + out.type = NGAP_CAUSE_RADIO_NETWORK; + out.value = in->choice.radioNetwork; + break; + + case NGAP_Cause_PR_transport: + out.type = NGAP_CAUSE_TRANSPORT; + out.value = in->choice.transport; + break; + + case NGAP_Cause_PR_nas: + out.type = NGAP_CAUSE_NAS; + out.value = in->choice.nas; + break; + + case NGAP_Cause_PR_protocol: + out.type = NGAP_CAUSE_PROTOCOL; + out.value = in->choice.protocol; + break; + + case NGAP_Cause_PR_misc: + out.type = NGAP_CAUSE_MISC; + out.value = in->choice.misc; + break; + + default: + out.type = NGAP_CAUSE_NOTHING; + NGAP_ERROR("Unknown failure cause %d\n", in->present); + break; + } + return out; +} + nr_guami_t decode_ngap_guami(const NGAP_GUAMI_t *in) { nr_guami_t out = {0}; @@ -141,3 +178,96 @@ void encode_ngap_nr_cgi(NGAP_NR_CGI_t *out, const plmn_id_t *plmn, const uint32_ MCC_MNC_TO_PLMNID(plmn->mcc, plmn->mnc, plmn->mnc_digit_length, &out->pLMNIdentity); NR_CELL_ID_TO_BIT_STRING(cell_id, &out->nRCellIdentity); } + +pdusession_level_qos_parameter_t fill_qos(uint8_t qfi, const NGAP_QosFlowLevelQosParameters_t *params) +{ + pdusession_level_qos_parameter_t out = {0}; + // QFI + out.qfi = qfi; + AssertFatal(params != NULL, "QoS parameters are NULL\n"); + // QosCharacteristics + const NGAP_QosCharacteristics_t *qosChar = ¶ms->qosCharacteristics; + AssertFatal(qosChar != NULL, "QoS characteristics are NULL\n"); + if (qosChar->present == NGAP_QosCharacteristics_PR_nonDynamic5QI) { + AssertFatal(qosChar->choice.nonDynamic5QI != NULL, "nonDynamic5QI is NULL\n"); + out.fiveQI_type = NON_DYNAMIC; + out.fiveQI = qosChar->choice.nonDynamic5QI->fiveQI; + } else if (qosChar->present == NGAP_QosCharacteristics_PR_dynamic5QI) { + AssertFatal(qosChar->choice.dynamic5QI != NULL, "dynamic5QI is NULL\n"); + out.fiveQI_type = DYNAMIC; + out.fiveQI = *qosChar->choice.dynamic5QI->fiveQI; + } else { + AssertFatal(0, "Unsupported QoS Characteristics present value: %d\n", qosChar->present); + } + // Allocation and Retention Priority + const NGAP_AllocationAndRetentionPriority_t *arp = ¶ms->allocationAndRetentionPriority; + out.allocation_retention_priority.priority_level = arp->priorityLevelARP; + out.allocation_retention_priority.pre_emp_capability = arp->pre_emptionCapability; + out.allocation_retention_priority.pre_emp_vulnerability = arp->pre_emptionVulnerability; + + return out; +} + +static gtpu_tunnel_t decode_TNLInformation(const NGAP_GTPTunnel_t *gTPTunnel_p) +{ + gtpu_tunnel_t out = {0}; + // Transport layer address + memcpy(out.addr.buffer, gTPTunnel_p->transportLayerAddress.buf, gTPTunnel_p->transportLayerAddress.size); + out.addr.length = gTPTunnel_p->transportLayerAddress.size - gTPTunnel_p->transportLayerAddress.bits_unused; + // GTP tunnel endpoint ID + OCTET_STRING_TO_INT32(&gTPTunnel_p->gTP_TEID, out.teid); + return out; +} + +void *decode_pdusession_transfer(const asn_TYPE_descriptor_t *td, const OCTET_STRING_t buf) +{ + void *decoded = NULL; + asn_codec_ctx_t ctx = {.max_stack_size = 100 * 1000}; + asn_dec_rval_t rval = aper_decode(&ctx, td, &decoded, buf.buf, buf.size, 0, 0); + if (rval.code != RC_OK) { + NGAP_ERROR("Decoding failed for %s\n", td->name); + return NULL; + } + return decoded; +} + +/** @brief Decode PDU Session Resource Setup Request Transfer (9.3.4.1 3GPP TS 38.413) */ +bool decodePDUSessionResourceSetup(pdusession_transfer_t *out, const OCTET_STRING_t in) +{ + void *decoded = decode_pdusession_transfer(&asn_DEF_NGAP_PDUSessionResourceSetupRequestTransfer, in); + if (!decoded) { + LOG_E(NR_RRC, "Failed to decode PDUSessionResourceSetupRequestTransfer\n"); + return false; + } + + NGAP_PDUSessionResourceSetupRequestTransfer_t *pdusessionTransfer = (NGAP_PDUSessionResourceSetupRequestTransfer_t *)decoded; + for (int i = 0; i < pdusessionTransfer->protocolIEs.list.count; i++) { + NGAP_PDUSessionResourceSetupRequestTransferIEs_t *pdusessionTransfer_ies = pdusessionTransfer->protocolIEs.list.array[i]; + switch (pdusessionTransfer_ies->id) { + // UL NG-U UP TNL Information (Mandatory) + case NGAP_ProtocolIE_ID_id_UL_NGU_UP_TNLInformation: + out->n3_incoming = decode_TNLInformation(pdusessionTransfer_ies->value.choice.UPTransportLayerInformation.choice.gTPTunnel); + break; + + // PDU Session Type (Mandatory) + case NGAP_ProtocolIE_ID_id_PDUSessionType: + out->pdu_session_type = pdusessionTransfer_ies->value.choice.PDUSessionType; + break; + + // QoS Flow Setup Request List (Mandatory) + case NGAP_ProtocolIE_ID_id_QosFlowSetupRequestList: + out->nb_qos = pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.count; + for (int i = 0; i < out->nb_qos; i++) { + NGAP_QosFlowSetupRequestItem_t *item = pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.array[i]; + out->qos[i] = fill_qos(item->qosFlowIdentifier, &item->qosFlowLevelQosParameters); + } + break; + + default: + LOG_D(NR_RRC, "Unhandled optional IE %ld\n", pdusessionTransfer_ies->id); + } + } + ASN_STRUCT_FREE(asn_DEF_NGAP_PDUSessionResourceSetupRequestTransfer, pdusessionTransfer); + + return true; +} diff --git a/openair3/NGAP/ngap_common.h b/openair3/NGAP/ngap_common.h index 1e53d9dd1a..9afaf47c4b 100644 --- a/openair3/NGAP/ngap_common.h +++ b/openair3/NGAP/ngap_common.h @@ -83,6 +83,7 @@ typedef int (*ngap_message_decoded_callback)(sctp_assoc_t assoc_id, uint32_t str void encode_ngap_cause(NGAP_Cause_t *out, const ngap_cause_t *in); nr_guami_t decode_ngap_guami(const NGAP_GUAMI_t *in); +ngap_cause_t decode_ngap_cause(const NGAP_Cause_t *in); ngap_ambr_t decode_ngap_UEAggregateMaximumBitRate(const NGAP_UEAggregateMaximumBitRate_t *in); nssai_t decode_ngap_nssai(const NGAP_S_NSSAI_t *in); ngap_security_capabilities_t decode_ngap_security_capabilities(const NGAP_UESecurityCapabilities_t *in); @@ -90,6 +91,8 @@ ngap_mobility_restriction_t decode_ngap_mobility_restriction(const NGAP_Mobility void encode_ngap_target_id(NGAP_HandoverRequiredIEs_t *out, const target_ran_node_id_t *in); void encode_ngap_nr_cgi(NGAP_NR_CGI_t *out, const plmn_id_t *plmn, const uint32_t cell_id); pdusession_level_qos_parameter_t fill_qos(uint8_t qfi, const NGAP_QosFlowLevelQosParameters_t *params); +void *decode_pdusession_transfer(const asn_TYPE_descriptor_t *td, const OCTET_STRING_t buf); +bool decodePDUSessionResourceSetup(pdusession_transfer_t *out, const OCTET_STRING_t in); /** @}*/ diff --git a/openair3/NGAP/ngap_gNB_decoder.c b/openair3/NGAP/ngap_gNB_decoder.c index 58c70011cf..a56357b55a 100644 --- a/openair3/NGAP/ngap_gNB_decoder.c +++ b/openair3/NGAP/ngap_gNB_decoder.c @@ -94,6 +94,12 @@ static int ngap_gNB_decode_initiating_message(NGAP_NGAP_PDU_t *pdu) { NGAP_INFO("TODO ErrorIndication initiating message\n"); break; + case NGAP_ProcedureCode_id_HandoverResourceAllocation: + res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu); + free(res.buffer); + NGAP_INFO("Handover Resource Allocation initiating message\n"); + break; + default: NGAP_ERROR("Unknown procedure ID (%d) for initiating message\n", (int)pdu->choice.initiatingMessage->procedureCode); diff --git a/openair3/NGAP/ngap_gNB_encoder.c b/openair3/NGAP/ngap_gNB_encoder.c index a6e91ba9c8..056aea2fe6 100644 --- a/openair3/NGAP/ngap_gNB_encoder.c +++ b/openair3/NGAP/ngap_gNB_encoder.c @@ -77,7 +77,8 @@ static inline int ngap_gNB_encode_successfull_outcome(NGAP_NGAP_PDU_t *pdu, uint NGAP_ProcedureCode_id_UEContextRelease, NGAP_ProcedureCode_id_PDUSessionResourceSetup, NGAP_ProcedureCode_id_PDUSessionResourceModify, - NGAP_ProcedureCode_id_PDUSessionResourceRelease}; + NGAP_ProcedureCode_id_PDUSessionResourceRelease, + NGAP_ProcedureCode_id_HandoverResourceAllocation}; int i; for (i = 0; i < sizeofArray(tmp); i++) if (pdu->choice.successfulOutcome->procedureCode == tmp[i]) @@ -98,8 +99,17 @@ static inline int ngap_gNB_encode_unsuccessfull_outcome(NGAP_NGAP_PDU_t *pdu, ui { DevAssert(pdu != NULL); - if (pdu->choice.unsuccessfulOutcome->procedureCode != NGAP_ProcedureCode_id_InitialContextSetup) { - NGAP_DEBUG("Unknown procedure ID (%d) for unsuccessfull outcome message\n", (int)pdu->choice.unsuccessfulOutcome->procedureCode); + const NGAP_ProcedureCode_t id[] = {NGAP_ProcedureCode_id_InitialContextSetup, NGAP_ProcedureCode_id_HandoverResourceAllocation}; + + int i; + for (i = 0; i < sizeofArray(id); i++) { + if (pdu->choice.unsuccessfulOutcome->procedureCode == id[i]) { + break; + } + } + + if (i == sizeofArray(id)) { + NGAP_WARN("Unknown procedure ID (%ld) for successful outcome message\n", pdu->choice.successfulOutcome->procedureCode); return -1; } diff --git a/openair3/NGAP/ngap_gNB_handlers.c b/openair3/NGAP/ngap_gNB_handlers.c index 6a92be9b79..485d37236a 100644 --- a/openair3/NGAP/ngap_gNB_handlers.c +++ b/openair3/NGAP/ngap_gNB_handlers.c @@ -44,7 +44,9 @@ #include "ngap_common.h" #include "ngap_gNB_decoder.h" #include "ngap_gNB_defs.h" +#include "ngap_gNB_nnsf.h" #include "ngap_gNB_management_procedures.h" +#include "ngap_gNB_mobility_management.h" #include "ngap_gNB_nas_procedures.h" #include "ngap_gNB_trace.h" #include "ngap_gNB_ue_context.h" @@ -693,97 +695,40 @@ static int ngap_gNB_handle_error_indication(sctp_assoc_t assoc_id, uint32_t stre return 0; } -static void *decode_pdusession_transfer(const asn_TYPE_descriptor_t *td, const OCTET_STRING_t buf) +/** @brief Handler for NGAP Handover Request message (AMF -> target NG-RAN) + * Decode the NGAP message and transfer to RRC */ +static int ngap_gNB_handle_handover_request(sctp_assoc_t assoc_id, uint32_t stream, NGAP_NGAP_PDU_t *pdu) { - void *decoded = NULL; - asn_codec_ctx_t ctx = {.max_stack_size = 100 * 1000}; - asn_dec_rval_t rval = aper_decode(&ctx, td, &decoded, buf.buf, buf.size, 0, 0); - if (rval.code != RC_OK) { - NGAP_ERROR("Decoding failed for %s\n", td->name); - return NULL; - } - return decoded; -} + DevAssert(pdu != NULL); -static pdusession_level_qos_parameter_t fill_qos(uint8_t qfi, const NGAP_QosFlowLevelQosParameters_t *params) -{ - pdusession_level_qos_parameter_t out = {0}; - // QFI - out.qfi = qfi; - AssertFatal(params != NULL, "QoS parameters are NULL\n"); - // QosCharacteristics - const NGAP_QosCharacteristics_t *qosChar = ¶ms->qosCharacteristics; - AssertFatal(qosChar != NULL, "QoS characteristics are NULL\n"); - if (qosChar->present == NGAP_QosCharacteristics_PR_nonDynamic5QI) { - AssertFatal(qosChar->choice.nonDynamic5QI != NULL, "nonDynamic5QI is NULL\n"); - out.fiveQI_type = NON_DYNAMIC; - out.fiveQI = qosChar->choice.nonDynamic5QI->fiveQI; - } else if (qosChar->present == NGAP_QosCharacteristics_PR_dynamic5QI) { - AssertFatal(qosChar->choice.dynamic5QI != NULL, "dynamic5QI is NULL\n"); - out.fiveQI_type = DYNAMIC; - out.fiveQI = *qosChar->choice.dynamic5QI->fiveQI; - } else { - AssertFatal(0, "Unsupported QoS Characteristics present value: %d\n", qosChar->present); - } - // Allocation and Retention Priority - const NGAP_AllocationAndRetentionPriority_t *arp = ¶ms->allocationAndRetentionPriority; - out.allocation_retention_priority.priority_level = arp->priorityLevelARP; - out.allocation_retention_priority.pre_emp_capability = arp->pre_emptionCapability; - out.allocation_retention_priority.pre_emp_vulnerability = arp->pre_emptionVulnerability; - - return out; -} - -static gtpu_tunnel_t decode_TNLInformation(const NGAP_GTPTunnel_t *gTPTunnel_p) -{ - gtpu_tunnel_t out = {0}; - // Transport layer address - memcpy(out.addr.buffer, gTPTunnel_p->transportLayerAddress.buf, gTPTunnel_p->transportLayerAddress.size); - out.addr.length = gTPTunnel_p->transportLayerAddress.size - gTPTunnel_p->transportLayerAddress.bits_unused; - // GTP tunnel endpoint ID - OCTET_STRING_TO_INT32(&gTPTunnel_p->gTP_TEID, out.teid); - return out; -} - -/** @brief Decode PDU Session Resource Setup Request Transfer (9.3.4.1 3GPP TS 38.413) */ -static bool decodePDUSessionResourceSetup(pdusession_transfer_t *out, const OCTET_STRING_t in) -{ - void *decoded = decode_pdusession_transfer(&asn_DEF_NGAP_PDUSessionResourceSetupRequestTransfer, in); - if (!decoded) { - LOG_E(NR_RRC, "Failed to decode PDUSessionResourceSetupRequestTransfer\n"); - return false; + ngap_gNB_amf_data_t *amf_desc_p = ngap_gNB_get_AMF(NULL, assoc_id, 0); + if (amf_desc_p == NULL) { + NGAP_ERROR("Received Handover Request for non existing AMF context\n"); + return -1; } - NGAP_PDUSessionResourceSetupRequestTransfer_t *pdusessionTransfer = (NGAP_PDUSessionResourceSetupRequestTransfer_t *)decoded; - for (int i = 0; i < pdusessionTransfer->protocolIEs.list.count; i++) { - NGAP_PDUSessionResourceSetupRequestTransferIEs_t *pdusessionTransfer_ies = pdusessionTransfer->protocolIEs.list.array[i]; - switch (pdusessionTransfer_ies->id) { - // UL NG-U UP TNL Information (Mandatory) - case NGAP_ProtocolIE_ID_id_UL_NGU_UP_TNLInformation: - out->n3_incoming = decode_TNLInformation(pdusessionTransfer_ies->value.choice.UPTransportLayerInformation.choice.gTPTunnel); - break; + MessageDef *message_p = itti_alloc_new_message(TASK_NGAP, 0, NGAP_HANDOVER_REQUEST); + ngap_handover_request_t *msg = &NGAP_HANDOVER_REQUEST(message_p); + memset(msg, 0, sizeof(*msg)); - // PDU Session Type (Mandatory) - case NGAP_ProtocolIE_ID_id_PDUSessionType: - out->pdu_session_type = pdusessionTransfer_ies->value.choice.PDUSessionType; - break; - - // QoS Flow Setup Request List (Mandatory) - case NGAP_ProtocolIE_ID_id_QosFlowSetupRequestList: - out->nb_qos = pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.count; - for (int i = 0; i < out->nb_qos; i++) { - NGAP_QosFlowSetupRequestItem_t *item = pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.array[i]; - out->qos[i] = fill_qos(item->qosFlowIdentifier, &item->qosFlowLevelQosParameters); - } - break; - - default: - LOG_D(NR_RRC, "Unhandled optional IE %ld\n", pdusessionTransfer_ies->id); - } + if (decode_ng_handover_request(msg, pdu) < 0) { + NGAP_ERROR("Failed to decode NG Handover Request\n"); + ngap_handover_failure_t fail = { + .amf_ue_ngap_id = msg->amf_ue_ngap_id, + .cause.type = NGAP_CAUSE_RADIO_NETWORK, + .cause.value = NGAP_CAUSE_RADIO_NETWORK_HO_FAILURE_IN_TARGET_5GC_NGRAN_NODE_OR_TARGET_SYSTEM, + }; + NGAP_INFO("Send NG Handover Failure message (amf_ue_ngap_id %ld) with cause %d \n ", fail.amf_ue_ngap_id, fail.cause.value); + MessageDef *msg_p = itti_alloc_new_message(TASK_NGAP, 0, NGAP_HANDOVER_FAILURE); + NGAP_HANDOVER_FAILURE(msg_p) = fail; + itti_send_msg_to_task(TASK_NGAP, amf_desc_p->ngap_gNB_instance->instance, msg_p); + return -1; } - ASN_STRUCT_FREE(asn_DEF_NGAP_PDUSessionResourceSetupRequestTransfer, pdusessionTransfer); - return true; + NGAP_INFO("Received NG Handover Request from AMF %s (ID=%lu)\n", amf_desc_p->amf_name, msg->amf_ue_ngap_id); + itti_send_msg_to_task(TASK_RRC_GNB, amf_desc_p->ngap_gNB_instance->instance, message_p); + + return 0; } static int ngap_gNB_handle_initial_context_request(sctp_assoc_t assoc_id, uint32_t stream, NGAP_NGAP_PDU_t *pdu) @@ -1394,7 +1339,7 @@ const ngap_message_decoded_callback ngap_messages_callback[][3] = { {0, 0, 0}, /* HandoverCancel */ {0, 0, 0}, /* HandoverNotification */ {0, 0, 0}, /* HandoverPreparation */ - {0, 0, 0}, /* HandoverResourceAllocation */ + {ngap_gNB_handle_handover_request, 0, 0}, /* HandoverResourceAllocation */ {ngap_gNB_handle_initial_context_request, 0, 0}, /* InitialContextSetup */ {0, 0, 0}, /* InitialUEMessage */ {0, 0, 0}, /* LocationReportingControl */ diff --git a/openair3/NGAP/ngap_gNB_mobility_management.c b/openair3/NGAP/ngap_gNB_mobility_management.c index 9d84fccd09..2aa0056dfe 100644 --- a/openair3/NGAP/ngap_gNB_mobility_management.c +++ b/openair3/NGAP/ngap_gNB_mobility_management.c @@ -30,6 +30,7 @@ #include "ngap_gNB_management_procedures.h" #include "ngap_gNB_encoder.h" #include "ngap_gNB_itti_messaging.h" +#include "conversions.h" /** @brief UE Mobility Management: encode Handover Required * (9.2.3.1 of 3GPP TS 38.413) NG-RAN node → AMF */ @@ -224,3 +225,160 @@ NGAP_NGAP_PDU_t *encode_ng_handover_failure(const ngap_handover_failure_t *msg) return pdu; } + +static void free_ng_handover_request(ngap_handover_request_t *msg) +{ + free_byte_array(msg->ue_ho_prep_info); + free_byte_array(msg->ue_cap); + free(msg->mobility_restriction); +} + +int decode_ng_handover_request(ngap_handover_request_t *out, const NGAP_NGAP_PDU_t *pdu) +{ + DevAssert(pdu != NULL); + NGAP_HandoverRequest_t *container = &pdu->choice.initiatingMessage->value.choice.HandoverRequest; + NGAP_HandoverRequestIEs_t *ie; + + // Handover Type (M) + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_HandoverRequestIEs_t, ie, container, NGAP_ProtocolIE_ID_id_HandoverType, true); + out->ho_type = ie->value.choice.HandoverType; + if (out->ho_type != HANDOVER_TYPE_INTRA5GS) { + NGAP_ERROR("Only Intra5GS Handover is supported at the moment!\n"); + return -1; + } + + // AMF UE NGAP ID (M) + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_HandoverRequestIEs_t, ie, container, NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID, true); + asn_INTEGER2ulong(&(ie->value.choice.AMF_UE_NGAP_ID), &out->amf_ue_ngap_id); + + // GUAMI (M) + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_HandoverRequestIEs_t, ie, container, NGAP_ProtocolIE_ID_id_GUAMI, true); + out->guami = decode_ngap_guami(&ie->value.choice.GUAMI); + + // UE Aggregate Maximum Bit Rate (M) + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_HandoverRequestIEs_t, ie, container, NGAP_ProtocolIE_ID_id_UEAggregateMaximumBitRate, true); + out->ue_ambr = decode_ngap_UEAggregateMaximumBitRate(&ie->value.choice.UEAggregateMaximumBitRate); + + // Allowed NSSAI (M) + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_HandoverRequestIEs_t, ie, container, NGAP_ProtocolIE_ID_id_AllowedNSSAI, true); + NGAP_DEBUG("AllowedNSSAI.list.count %d\n", ie->value.choice.AllowedNSSAI.list.count); + out->nb_allowed_nssais = ie->value.choice.AllowedNSSAI.list.count; + for (int i = 0; i < out->nb_allowed_nssais; i++) { + out->allowed_nssai[i] = decode_ngap_nssai(&ie->value.choice.AllowedNSSAI.list.array[i]->s_NSSAI); + } + + // UE Security Capabilities (M) + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_HandoverRequestIEs_t, ie, container, NGAP_ProtocolIE_ID_id_UESecurityCapabilities, true); + out->security_capabilities = decode_ngap_security_capabilities(&ie->value.choice.UESecurityCapabilities); + + // Security Context (M) + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_HandoverRequestIEs_t, ie, container, NGAP_ProtocolIE_ID_id_SecurityContext, true); + NGAP_SecurityContext_t *sc = &ie->value.choice.SecurityContext; + memcpy(&out->security_context.next_hop, sc->nextHopNH.buf, sc->nextHopNH.size); + out->security_context.next_hop_chain_count = sc->nextHopChainingCount; + + // Mobility Restriction List (O) + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_HandoverRequestIEs_t, ie, container, NGAP_ProtocolIE_ID_id_MobilityRestrictionList, false); + if (ie != NULL) { + out->mobility_restriction = malloc_or_fail(sizeof(*out->mobility_restriction)); + *out->mobility_restriction = decode_ngap_mobility_restriction(&ie->value.choice.MobilityRestrictionList); + } + + // Cause (M) + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_HandoverRequestIEs_t, ie, container, NGAP_ProtocolIE_ID_id_Cause, true); + out->cause = decode_ngap_cause(&ie->value.choice.Cause); + + // Source to Target Transparent Container + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_HandoverRequestIEs_t, + ie, + container, + NGAP_ProtocolIE_ID_id_SourceToTarget_TransparentContainer, + true); + NGAP_SourceToTarget_TransparentContainer_t *choice = &ie->value.choice.SourceToTarget_TransparentContainer; + byte_array_t sourceToTargetTransparentContainer = create_byte_array(choice->size, choice->buf); + NGAP_SourceNGRANNode_ToTargetNGRANNode_TransparentContainer_t *source2target = NULL; + asn_dec_rval_t dec_rval = aper_decode_complete(NULL, + &asn_DEF_NGAP_SourceNGRANNode_ToTargetNGRANNode_TransparentContainer, + (void **)&source2target, + sourceToTargetTransparentContainer.buf, + sourceToTargetTransparentContainer.len); + + free_byte_array(sourceToTargetTransparentContainer); + if (dec_rval.code != RC_OK) { + free_ng_handover_request(out); + NGAP_ERROR("Failed to decode sourceToTargetTransparentContainer\n"); + return -1; + } + + if (LOG_DEBUGFLAG(DEBUG_ASN1)) + xer_fprint(stdout, &asn_DEF_NGAP_SourceNGRANNode_ToTargetNGRANNode_TransparentContainer, source2target); + + // Extract Cell Identity + BIT_STRING_TO_NR_CELL_IDENTITY(&source2target->targetCell_ID.choice.nR_CGI->nRCellIdentity, out->nr_cell_id); + + // Handover Preparation Information: store and decode + out->ue_ho_prep_info = create_byte_array(source2target->rRCContainer.size, source2target->rRCContainer.buf); + NR_HandoverPreparationInformation_t *hoPrepInformation = NULL; + asn_dec_rval_t hoPrep_dec_rval = uper_decode_complete(NULL, + &asn_DEF_NR_HandoverPreparationInformation, + (void **)&hoPrepInformation, + source2target->rRCContainer.buf, + source2target->rRCContainer.size); + AssertFatal(hoPrep_dec_rval.code == RC_OK && hoPrep_dec_rval.consumed > 0, "Handover Prep Info decode error\n"); + if (hoPrep_dec_rval.code != RC_OK && !hoPrep_dec_rval.consumed) { + NGAP_ERROR("Failed to decode HandoverPreparationInformation, abort Handover Request decoding\n"); + free_ng_handover_request(out); + ASN_STRUCT_FREE(asn_DEF_NGAP_SourceNGRANNode_ToTargetNGRANNode_TransparentContainer, source2target); + return -1; + } + + ASN_STRUCT_FREE(asn_DEF_NGAP_SourceNGRANNode_ToTargetNGRANNode_TransparentContainer, source2target); + + if (LOG_DEBUGFLAG(DEBUG_ASN1)) + xer_fprint(stdout, &asn_DEF_NR_HandoverPreparationInformation, hoPrepInformation); + + // Decode UE capabilities and store + NR_HandoverPreparationInformation_IEs_t *hpi = + hoPrepInformation->criticalExtensions.choice.c1->choice.handoverPreparationInformation; + const NR_UE_CapabilityRAT_ContainerList_t *ue_CapabilityRAT_ContainerList = &hpi->ue_CapabilityRAT_List; + out->ue_cap.len = uper_encode_to_new_buffer(&asn_DEF_NR_UE_CapabilityRAT_ContainerList, + NULL, + ue_CapabilityRAT_ContainerList, + (void **)&out->ue_cap.buf); + + ASN_STRUCT_FREE(asn_DEF_NR_HandoverPreparationInformation, hoPrepInformation); + + if (out->ue_cap.len <= 0) { + free_ng_handover_request(out); + NGAP_ERROR("could not encode UE-CapabilityRAT-ContainerList\n"); + return -1; + } + + // PDU Session Resource Setup List (M) + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_HandoverRequestIEs_t, + ie, + container, + NGAP_ProtocolIE_ID_id_PDUSessionResourceSetupListHOReq, + true); + out->nb_of_pdusessions = ie->value.choice.PDUSessionResourceSetupListHOReq.list.count; + for (int pduSesIdx = 0; pduSesIdx < out->nb_of_pdusessions; ++pduSesIdx) { + NGAP_PDUSessionResourceSetupItemHOReq_t *item_p = ie->value.choice.PDUSessionResourceSetupListHOReq.list.array[pduSesIdx]; + // PDU Session ID (M) + ho_request_pdusession_t *setup = &out->pduSessionResourceSetupList[pduSesIdx]; + setup->pdusession_id = item_p->pDUSessionID; + setup->pdu_session_type = PDUSessionType_ipv4; + // S-NSSAI (M) + setup->nssai = decode_ngap_nssai(&item_p->s_NSSAI); + // Handover Request Transfer (M) + bool ret = decodePDUSessionResourceSetup(&setup->pdusessionTransfer, item_p->handoverRequestTransfer); + if (!ret) { + free_ng_handover_request(out); + NGAP_ERROR("Failed to decode pDUSessionResourceSetupRequestTransfer in NG Initial Context Setup Request\n"); + return -1; + } + } + + + + return 0; +} diff --git a/openair3/NGAP/ngap_gNB_mobility_management.h b/openair3/NGAP/ngap_gNB_mobility_management.h index 6f5cdde742..66e85e644e 100644 --- a/openair3/NGAP/ngap_gNB_mobility_management.h +++ b/openair3/NGAP/ngap_gNB_mobility_management.h @@ -28,5 +28,6 @@ NGAP_NGAP_PDU_t *encode_ng_handover_required(const ngap_handover_required_t *msg); NGAP_NGAP_PDU_t *encode_ng_handover_failure(const ngap_handover_failure_t *msg); +int decode_ng_handover_request(ngap_handover_request_t *out, const NGAP_NGAP_PDU_t *pdu); #endif /* NGAP_GNB_MOBILITY_MANAGEMENT_H_ */ diff --git a/openair3/NGAP/ngap_msg_includes.h b/openair3/NGAP/ngap_msg_includes.h index cf7d0d9f49..a80df29401 100644 --- a/openair3/NGAP/ngap_msg_includes.h +++ b/openair3/NGAP/ngap_msg_includes.h @@ -86,5 +86,20 @@ #include "NGAP_PDUSessionResourceInformationList.h" #include "NGAP_HandoverRequiredTransfer.h" #include "NGAP_SourceNGRANNode-ToTargetNGRANNode-TransparentContainer.h" +#include "NGAP_PDUSessionResourceSetupItemHOReq.h" +#include "NGAP_HandoverCommand.h" +#include "NGAP_HandoverCommandTransfer.h" +#include "NGAP_TargetNGRANNode-ToSourceNGRANNode-TransparentContainer.h" +#include "NGAP_TargetToSource-TransparentContainer.h" +#include "NGAP_UEHistoryInformation.h" +#include "NGAP_Cause.h" +#include "NGAP_PDUSessionResourceHandoverItem.h" +#include "NGAP_SourceToTarget-TransparentContainer.h" +#include "NGAP_HandoverRequest.h" +#include "NGAP_PDUSessionResourceAdmittedList.h" +#include "NGAP_PDUSessionResourceAdmittedItem.h" +#include "NGAP_HandoverRequestAcknowledgeTransfer.h" +#include "NGAP_QosFlowItemWithDataForwarding.h" +#include "NR_HandoverPreparationInformation.h" #endif // NGAP_MSG_INCLUDES_H From fa75484e135c40e60c57805eb3248de522b2f1d4 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 12 Mar 2025 18:00:19 +0100 Subject: [PATCH 719/964] Add NGAP Handover Request Acknowledge encoder and RRC callback This commit completes the NG Mobility Management Procedure known as Handover Resource Allocation. The outbound message is sent by the target NG-RAN and is known as Handover Request Acknowledge. Major changes: * add RRC callback to trigger the generation of NG Handover Request Acknowledge on the target NG-RAN * add NG Handover Request Acknowledge encoder Co-authored-by: batuhan duyuler --- openair2/COMMON/ngap_messages_def.h | 1 + openair2/COMMON/ngap_messages_types.h | 31 +++++++ openair2/RRC/NR/rrc_gNB_NGAP.c | 36 ++++++++ openair2/RRC/NR/rrc_gNB_NGAP.h | 2 + openair3/NGAP/ngap_gNB.c | 50 ++++++++++ openair3/NGAP/ngap_gNB_mobility_management.c | 96 +++++++++++++++++++- openair3/NGAP/ngap_gNB_mobility_management.h | 2 + 7 files changed, 215 insertions(+), 3 deletions(-) diff --git a/openair2/COMMON/ngap_messages_def.h b/openair2/COMMON/ngap_messages_def.h index 53b16350e1..e9e185e152 100644 --- a/openair2/COMMON/ngap_messages_def.h +++ b/openair2/COMMON/ngap_messages_def.h @@ -73,6 +73,7 @@ MESSAGE_DEF(NGAP_PDUSESSION_MODIFY_RESP , MESSAGE_PRIORITY_MED, ngap_pd MESSAGE_DEF(NGAP_PDUSESSION_RELEASE_RESPONSE , MESSAGE_PRIORITY_MED, ngap_pdusession_release_resp_t , ngap_pdusession_release_resp) MESSAGE_DEF(NGAP_HANDOVER_REQUIRED, MESSAGE_PRIORITY_MED, ngap_handover_required_t, ngap_handover_required) MESSAGE_DEF(NGAP_HANDOVER_FAILURE, MESSAGE_PRIORITY_MED, ngap_handover_failure_t, ngap_handover_failure) +MESSAGE_DEF(NGAP_HANDOVER_REQUEST_ACKNOWLEDGE, MESSAGE_PRIORITY_MED, ngap_handover_request_ack_t, ngap_handover_request_ack) /* NGAP -> RRC messages */ MESSAGE_DEF(NGAP_DOWNLINK_NAS , MESSAGE_PRIORITY_MED, ngap_downlink_nas_t , ngap_downlink_nas ) diff --git a/openair2/COMMON/ngap_messages_types.h b/openair2/COMMON/ngap_messages_types.h index 49212b257c..5a5937500d 100644 --- a/openair2/COMMON/ngap_messages_types.h +++ b/openair2/COMMON/ngap_messages_types.h @@ -68,6 +68,7 @@ #define NGAP_HANDOVER_REQUIRED(mSGpTR) (mSGpTR)->ittiMsg.ngap_handover_required #define NGAP_HANDOVER_FAILURE(mSGpTR) (mSGpTR)->ittiMsg.ngap_handover_failure #define NGAP_HANDOVER_REQUEST(mSGpTR) (mSGpTR)->ittiMsg.ngap_handover_request +#define NGAP_HANDOVER_REQUEST_ACKNOWLEDGE(mSGpTR) (mSGpTR)->ittiMsg.ngap_handover_request_ack #define NGAP_UE_CONTEXT_RELEASE_REQ(mSGpTR) (mSGpTR)->ittiMsg.ngap_ue_release_req #define NGAP_PDUSESSION_RELEASE_COMMAND(mSGpTR) (mSGpTR)->ittiMsg.ngap_pdusession_release_command @@ -617,6 +618,36 @@ typedef struct { nr_guami_t guami; } ngap_handover_request_t; +/* 9.3.4.11 3GPP TS 38.413 */ +typedef struct { + // QoS Flow Setup Response List + uint8_t nb_of_qos_flow; + pdusession_associate_qosflow_t qos_setup_list[QOSFLOW_MAX_VALUE]; + // DL NG-U UP TNL Information + uint32_t gtp_teid; + transport_layer_addr_t gNB_addr; +} ho_request_ack_transfer_t; + +/* 9.2.3.5 3GPP TS 38.413 */ +typedef struct { + // PDU Session ID (M) + uint8_t pdu_session_id; + // Handover Request Acknowledge Transfer (M) + ho_request_ack_transfer_t ack_transfer; +} pdu_session_resource_admitted_t; + +typedef struct { + // AMF UE NGAP ID + uint32_t gNB_ue_ngap_id; + // RAN UE NGAP ID + uint64_t amf_ue_ngap_id; + // PDU Session Resource Admitted List + pdu_session_resource_admitted_t pdusessions[NGAP_MAX_PDU_SESSION]; + uint8_t nb_of_pdusessions; + // Target to Source Transparent Container + byte_array_t target2source; +} ngap_handover_request_ack_t; + typedef struct ngap_ue_cap_info_ind_s { uint32_t gNB_ue_ngap_id; byte_array_t ue_radio_cap; diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index 68aa502f77..19cd12704f 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -1270,6 +1270,42 @@ void rrc_gNB_send_NGAP_UE_CAPABILITIES_IND(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, LOG_I(NR_RRC,"Send message to ngap: NGAP_UE_CAPABILITIES_IND\n"); } +void rrc_gNB_send_NGAP_HANDOVER_REQUEST_ACKNOWLEDGE(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, byte_array_t ho_command) +{ + LOG_D(NR_RRC, "Sending Handover Request Acknowledge\n"); + + MessageDef *msg_p = itti_alloc_new_message(TASK_RRC_GNB, 0, NGAP_HANDOVER_REQUEST_ACKNOWLEDGE); + ngap_handover_request_ack_t *msg = &NGAP_HANDOVER_REQUEST_ACKNOWLEDGE(msg_p); + memset(msg, 0, sizeof(*msg)); + + // RAN UE NGAP ID + msg->gNB_ue_ngap_id = UE->rrc_ue_id; + // AMF UE NGAP ID + msg->amf_ue_ngap_id = UE->amf_ue_ngap_id; + // PDU Session Resource Admitted List + msg->nb_of_pdusessions = UE->nb_of_pdusessions; + for (int i = 0; i < UE->nb_of_pdusessions; i++) { + rrc_pdu_session_param_t *session = &UE->pduSession[i]; + session->status = PDU_SESSION_STATUS_ESTABLISHED; + // PDU Session ID + msg->pdusessions[i].pdu_session_id = session->param.pdusession_id; + // Handover Request Acknowledge Transfer + ho_request_ack_transfer_t *transfer = &msg->pdusessions[i].ack_transfer; + transfer->gtp_teid = session->param.n3_outgoing.teid; + memcpy(transfer->gNB_addr.buffer, session->param.n3_outgoing.addr.buffer, session->param.n3_outgoing.addr.length); + transfer->gNB_addr.length = session->param.n3_outgoing.addr.length; + transfer->nb_of_qos_flow = session->param.nb_qos; + for (int q = 0; q < transfer->nb_of_qos_flow; q++) { + transfer->qos_setup_list[q].qfi = session->param.qos[q].qfi; + transfer->qos_setup_list[q].qos_flow_mapping_ind = QOSFLOW_MAPPING_INDICATION_DL; + } + } + // Target to Source Transparent Container + msg->target2source = copy_byte_array(ho_command); + + itti_send_msg_to_task(TASK_NGAP, rrc->module_id, msg_p); +} + void rrc_gNB_send_NGAP_PDUSESSION_RELEASE_RESPONSE(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, uint8_t xid) { int pdu_sessions_released = 0; diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.h b/openair2/RRC/NR/rrc_gNB_NGAP.h index 53e2b51f8c..9d51db4186 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.h +++ b/openair2/RRC/NR/rrc_gNB_NGAP.h @@ -99,4 +99,6 @@ void rrc_gNB_send_NGAP_HANDOVER_FAILURE(gNB_RRC_INST *rrc, ngap_handover_failure int rrc_gNB_process_Handover_Request(gNB_RRC_INST *rrc, instance_t instance, ngap_handover_request_t *msg); void rrc_gNB_free_Handover_Request(ngap_handover_request_t *msg); +void rrc_gNB_send_NGAP_HANDOVER_REQUEST_ACKNOWLEDGE(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, byte_array_t ho_command); + #endif diff --git a/openair3/NGAP/ngap_gNB.c b/openair3/NGAP/ngap_gNB.c index 58511f307c..e80b914871 100644 --- a/openair3/NGAP/ngap_gNB.c +++ b/openair3/NGAP/ngap_gNB.c @@ -374,6 +374,51 @@ static int ngap_gNB_handover_failure(instance_t instance, const ngap_handover_fa return 0; } +static int ngap_gNB_handover_request_acknowledge(instance_t instance, ngap_handover_request_ack_t *msg) +{ + byte_array_t ba = { .buf = NULL, .len = 0 }; + + /* Retrieve the NGAP gNB instance associated with Mod_id */ + ngap_gNB_instance_t *ngap = ngap_gNB_get_instance(instance); + DevAssert(msg != NULL); + DevAssert(ngap != NULL); + + // First, create and store NGAP UE context + ngap_gNB_ue_context_t ue_context_p = { + .amf_ref = ngap_gNB_get_AMF_from_instance(ngap), + .gNB_ue_ngap_id = msg->gNB_ue_ngap_id, + .amf_ue_ngap_id = msg->amf_ue_ngap_id, + .gNB_instance = ngap, + .ue_state = NGAP_UE_CONNECTED, + }; + if (ue_context_p.amf_ref == NULL) { + NGAP_ERROR("Failed to fetch AMF for current NGAP instance\n"); + return -1; + } + ngap_store_ue_context(&ue_context_p); + + NGAP_NGAP_PDU_t *pdu = encode_ng_handover_request_ack(msg); + if (!pdu) { + NGAP_ERROR("Failed to encode NG Handover Request Acknowledge\n"); + return -1; + } + + if (LOG_DEBUGFLAG(DEBUG_ASN1)) + xer_fprint(stdout, &asn_DEF_NGAP_NGAP_PDU, pdu); + + if (ngap_gNB_encode_pdu(pdu, &ba.buf, (uint32_t *)&ba.len) < 0) { + NGAP_ERROR("Failed to encode Handover Request Acknowledge message\n"); + ASN_STRUCT_FREE(asn_DEF_NGAP_NGAP_PDU, pdu); + return -1; + } + + /* UE associated signalling -> use the allocated stream */ + ngap_gNB_itti_send_sctp_data_req(ngap->instance, ue_context_p.amf_ref->assoc_id, ba.buf, ba.len, ue_context_p.tx_stream); + NGAP_INFO("Sent Handover Request Acknowledge to AMF\n"); + + return 0; +} + void *ngap_gNB_process_itti_msg(void *notUsed) { MessageDef *received_msg = NULL; int result; @@ -459,6 +504,11 @@ void *ngap_gNB_process_itti_msg(void *notUsed) { ngap_gNB_handover_failure(instance, &NGAP_HANDOVER_FAILURE(received_msg)); break; + case NGAP_HANDOVER_REQUEST_ACKNOWLEDGE: + ngap_gNB_handover_request_acknowledge(instance, &NGAP_HANDOVER_REQUEST_ACKNOWLEDGE(received_msg)); + free_ng_handover_req_ack(&NGAP_HANDOVER_REQUEST_ACKNOWLEDGE(received_msg)); + break; + default: NGAP_ERROR("Received unhandled message: %d:%s\n", ITTI_MSG_ID(received_msg), ITTI_MSG_NAME(received_msg)); break; diff --git a/openair3/NGAP/ngap_gNB_mobility_management.c b/openair3/NGAP/ngap_gNB_mobility_management.c index 2aa0056dfe..4c64659e01 100644 --- a/openair3/NGAP/ngap_gNB_mobility_management.c +++ b/openair3/NGAP/ngap_gNB_mobility_management.c @@ -22,6 +22,7 @@ #include #include #include +#include "conversions.h" #include "ngap_common.h" #include "ngap_msg_includes.h" #include "ngap_gNB_defs.h" @@ -377,8 +378,97 @@ int decode_ng_handover_request(ngap_handover_request_t *out, const NGAP_NGAP_PDU return -1; } } - - - return 0; } + +NGAP_NGAP_PDU_t *encode_ng_handover_request_ack(ngap_handover_request_ack_t *msg) +{ + NGAP_NGAP_PDU_t *pdu = malloc_or_fail(sizeof(*pdu)); + + pdu->present = NGAP_NGAP_PDU_PR_successfulOutcome; + asn1cCalloc(pdu->choice.successfulOutcome, head); + head->procedureCode = NGAP_ProcedureCode_id_HandoverResourceAllocation; + head->criticality = NGAP_Criticality_reject; + head->value.present = NGAP_SuccessfulOutcome__value_PR_HandoverRequestAcknowledge; + NGAP_HandoverRequestAcknowledge_t *out = &head->value.choice.HandoverRequestAcknowledge; + + // AMF UE NGAP ID (M) + { + asn1cSequenceAdd(out->protocolIEs.list, NGAP_HandoverRequestAcknowledgeIEs_t, ie); + ie->id = NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID; + ie->criticality = NGAP_Criticality_ignore; + ie->value.present = NGAP_HandoverRequestAcknowledgeIEs__value_PR_AMF_UE_NGAP_ID; + asn_uint642INTEGER(&ie->value.choice.AMF_UE_NGAP_ID, msg->amf_ue_ngap_id); + } + + // RAN UE NGAP ID (M) + { + asn1cSequenceAdd(out->protocolIEs.list, NGAP_HandoverRequestAcknowledgeIEs_t, ie); + ie->id = NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID; + ie->criticality = NGAP_Criticality_ignore; + ie->value.present = NGAP_HandoverRequestAcknowledgeIEs__value_PR_RAN_UE_NGAP_ID; + ie->value.choice.RAN_UE_NGAP_ID = msg->gNB_ue_ngap_id; + } + + // Target to Source Transparent Container (M) + { + asn1cSequenceAdd(out->protocolIEs.list, NGAP_HandoverRequestAcknowledgeIEs_t, ie); + ie->id = NGAP_ProtocolIE_ID_id_TargetToSource_TransparentContainer; + ie->criticality = NGAP_Criticality_reject; + ie->value.present = NGAP_HandoverRequestAcknowledgeIEs__value_PR_TargetToSource_TransparentContainer; + NGAP_TargetNGRANNode_ToSourceNGRANNode_TransparentContainer_t *t2s = calloc_or_fail(1, sizeof(*t2s)); + // RRC Container (M) + { + // Encode Handover Command + t2s->rRCContainer.size = msg->target2source.len; + t2s->rRCContainer.buf = malloc_or_fail(msg->target2source.len); + memcpy(t2s->rRCContainer.buf, msg->target2source.buf, msg->target2source.len); + byte_array_t ba = { .buf = NULL, .len = 0 }; + ba.len = aper_encode_to_new_buffer(&asn_DEF_NGAP_TargetNGRANNode_ToSourceNGRANNode_TransparentContainer, NULL, t2s, (void **)&ba.buf); + OCTET_STRING_fromBuf(&ie->value.choice.TargetToSource_TransparentContainer, (const char *)ba.buf, ba.len); + ASN_STRUCT_FREE(asn_DEF_NGAP_TargetNGRANNode_ToSourceNGRANNode_TransparentContainer, t2s); + free_byte_array(ba); + } + } + + // PDU Session Resource Admitted List (M) + { + asn1cSequenceAdd(out->protocolIEs.list, NGAP_HandoverRequestAcknowledgeIEs_t, ie); + ie->id = NGAP_ProtocolIE_ID_id_PDUSessionResourceAdmittedList; + ie->criticality = NGAP_Criticality_ignore; + ie->value.present = NGAP_HandoverRequestAcknowledgeIEs__value_PR_PDUSessionResourceAdmittedList; + + for (int pduSesIdx = 0; pduSesIdx < msg->nb_of_pdusessions; pduSesIdx++) { + asn1cSequenceAdd(ie->value.choice.PDUSessionResourceAdmittedList.list, NGAP_PDUSessionResourceAdmittedItem_t, item); + item->pDUSessionID = msg->pdusessions[pduSesIdx].pdu_session_id; + /* dLQosFlowPerTNLInformation */ + NGAP_HandoverRequestAcknowledgeTransfer_t transfer = {0}; + transfer.dL_NGU_UP_TNLInformation.present = NGAP_UPTransportLayerInformation_PR_gTPTunnel; + asn1cCalloc(transfer.dL_NGU_UP_TNLInformation.choice.gTPTunnel, tmp); + GTP_TEID_TO_ASN1(msg->pdusessions[pduSesIdx].ack_transfer.gtp_teid, &tmp->gTP_TEID); + tnl_to_bitstring(&tmp->transportLayerAddress, msg->pdusessions[pduSesIdx].ack_transfer.gNB_addr); + + for (int j = 0; j < msg->pdusessions[pduSesIdx].ack_transfer.nb_of_qos_flow; j++) { + asn1cSequenceAdd(transfer.qosFlowSetupResponseList.list, NGAP_QosFlowItemWithDataForwarding_t, qosItem); + qosItem->qosFlowIdentifier = msg->pdusessions[pduSesIdx].ack_transfer.qos_setup_list[j].qfi; + qosItem->dataForwardingAccepted = malloc_or_fail(sizeof(*qosItem->dataForwardingAccepted)); + *qosItem->dataForwardingAccepted = NGAP_DataForwardingAccepted_data_forwarding_accepted; + } + + void *buf; + ssize_t encoded = aper_encode_to_new_buffer(&asn_DEF_NGAP_HandoverRequestAcknowledgeTransfer, NULL, &transfer, &buf); + AssertFatal(encoded > 0, "ASN1 message encoding failed !\n"); + item->handoverRequestAcknowledgeTransfer.buf = buf; + item->handoverRequestAcknowledgeTransfer.size = encoded; + + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_HandoverRequestAcknowledgeTransfer, &transfer); + } + } + + return pdu; +} + +void free_ng_handover_req_ack(ngap_handover_request_ack_t *msg) +{ + free_byte_array(msg->target2source); +} diff --git a/openair3/NGAP/ngap_gNB_mobility_management.h b/openair3/NGAP/ngap_gNB_mobility_management.h index 66e85e644e..dd0061ca35 100644 --- a/openair3/NGAP/ngap_gNB_mobility_management.h +++ b/openair3/NGAP/ngap_gNB_mobility_management.h @@ -29,5 +29,7 @@ NGAP_NGAP_PDU_t *encode_ng_handover_required(const ngap_handover_required_t *msg); NGAP_NGAP_PDU_t *encode_ng_handover_failure(const ngap_handover_failure_t *msg); int decode_ng_handover_request(ngap_handover_request_t *out, const NGAP_NGAP_PDU_t *pdu); +NGAP_NGAP_PDU_t *encode_ng_handover_request_ack(ngap_handover_request_ack_t *msg); +void free_ng_handover_req_ack(ngap_handover_request_ack_t *msg); #endif /* NGAP_GNB_MOBILITY_MANAGEMENT_H_ */ From 6fd02ee7e886b9a3fcfc044291761e173ff54fb2 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Mon, 26 May 2025 10:38:30 +0200 Subject: [PATCH 720/964] Handle N2 handover in UE Context Setup Response on the target NG-RAN * generate Handover Command for the source NG-RAN to be added to the target to source transparent container of the Handover Acknowledge message * add Handover Acknowledge callback for N2 * send NG Handover Acknowledge to AMF Co-authored-by: batuhan duyuler --- openair2/RRC/NR/MESSAGES/asn1_msg.c | 108 ++++++++++++++++++++++++++++ openair2/RRC/NR/MESSAGES/asn1_msg.h | 2 + openair2/RRC/NR/rrc_gNB_mobility.c | 67 +++++++++++++++++ openair2/RRC/NR/rrc_gNB_mobility.h | 1 + 4 files changed, 178 insertions(+) diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.c b/openair2/RRC/NR/MESSAGES/asn1_msg.c index 8bd9716107..fc3ca002f4 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.c +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.c @@ -82,6 +82,7 @@ #include "NR_UE-CapabilityRequestFilterNR.h" #include "NR_HandoverPreparationInformation.h" #include "NR_HandoverPreparationInformation-IEs.h" +#include "NR_HandoverCommand.h" #include "common/utils/nr/nr_common.h" #if defined(NR_Rel16) #include "NR_SCS-SpecificCarrier.h" @@ -1138,6 +1139,113 @@ NR_MeasConfig_t *get_MeasConfig(const NR_MeasTiming_t *mt, return mc; } +/** @brief Prepares removal of measurement configurations related to the source gNB. + * This function decodes the HandoverPreparationInformation received from the source gNB, + * extracts the source MeasConfig, and marks those entries (measurement objects, report + * configurations, and measurement IDs) for removal by populating the corresponding + * ToRemoveList fields in the UE's current measConfig. + * This ensures that obsolete or source-specific measurement configurations are removed + * from the UE after handover and allows the target gNB to install its own valid configuration. + * @param measConfig Target gNB's current measurement configuration to be updated. + * @param prep_info Encoded HandoverPreparationInformation received from the source gNB.*/ +void fill_removal_lists_from_source_measConfig(NR_MeasConfig_t *currentMC, byte_array_t prep_info) +{ + if (currentMC == NULL) { + LOG_E(NR_RRC, "HO LOG: UE's Measurement Configuration is NULL!\n"); + return; + } + + // Decodes the HandoverPreparationInformation message + NR_HandoverPreparationInformation_t *hpi = NULL; + asn_dec_rval_t hoPrep_dec_rval = uper_decode_complete(NULL, + &asn_DEF_NR_HandoverPreparationInformation, + (void **)&hpi, + (uint8_t *)prep_info.buf, + prep_info.len); + + if (hoPrep_dec_rval.code != RC_OK || hoPrep_dec_rval.consumed < 0) { + LOG_E(NR_RRC, "Handover Prep Info decode error while removing source gnb measurement configuration!\n"); + return; + } + + /* Decodes the RRCReconfiguration message within the HandoverPreparationInformation + and extract the measConfig provided by the source gNB */ + if (!hpi->criticalExtensions.choice.c1->choice.handoverPreparationInformation->sourceConfig) { + LOG_W(NR_RRC, "Missing sourceConfig: in source gNB rrcReconfiguration\n"); + return; + } + NR_RRCReconfiguration_t *rrcReconf = NULL; + NR_AS_Config_t *sourceConfig = hpi->criticalExtensions.choice.c1->choice.handoverPreparationInformation->sourceConfig; + asn_dec_rval_t rrcReconf_dec_rval = uper_decode_complete(NULL, + &asn_DEF_NR_RRCReconfiguration, + (void **)&rrcReconf, + (uint8_t *)sourceConfig->rrcReconfiguration.buf, + sourceConfig->rrcReconfiguration.size); + if (rrcReconf_dec_rval.code != RC_OK || rrcReconf_dec_rval.consumed < 0) { + LOG_E(NR_RRC, "Failed to decode source gNB rrcReconfiguration!\n"); + return; + } + + if (rrcReconf->criticalExtensions.choice.rrcReconfiguration->measConfig == NULL) + return; + + NR_MeasConfig_t *sourceMC = rrcReconf->criticalExtensions.choice.rrcReconfiguration->measConfig; + + /* Add measurement objects, report configurations, and measurement IDs + to the UE's measConfig removal lists, and update UE->measConfig */ + if (sourceMC->measObjectToAddModList->list.count > 0) { + currentMC->measObjectToRemoveList = calloc_or_fail(1, sizeof(*currentMC->measObjectToRemoveList)); + for (int i = 0; i < sourceMC->measObjectToAddModList->list.count; i++) { + NR_MeasObjectId_t *measObjId = calloc_or_fail(1, sizeof(NR_MeasObjectId_t)); + *measObjId = sourceMC->measObjectToAddModList->list.array[i]->measObjectId; + asn1cSeqAdd(¤tMC->measObjectToRemoveList->list, measObjId); + } + } + + if (sourceMC->reportConfigToAddModList->list.count > 0) { + currentMC->reportConfigToRemoveList = calloc_or_fail(1, sizeof(*currentMC->reportConfigToRemoveList)); + for (int i = 0; i < sourceMC->reportConfigToAddModList->list.count; i++) { + NR_ReportConfigId_t *reportConfigId = calloc_or_fail(1, sizeof(NR_ReportConfigId_t)); + *reportConfigId = sourceMC->reportConfigToAddModList->list.array[i]->reportConfigId; + asn1cSeqAdd(¤tMC->reportConfigToRemoveList->list, reportConfigId); + } + } + + if (sourceMC->measIdToAddModList->list.count > 0) { + currentMC->measIdToRemoveList = calloc_or_fail(1, sizeof(*currentMC->measIdToRemoveList)); + for (int i = 0; i < sourceMC->measIdToAddModList->list.count; i++) { + NR_MeasId_t *measId = calloc_or_fail(1, sizeof(NR_MeasId_t)); + *measId = sourceMC->measIdToAddModList->list.array[i]->measId; + asn1cSeqAdd(¤tMC->measIdToRemoveList->list, measId); + } + } +} + +byte_array_t get_HandoverCommandMessage(nr_rrc_reconfig_param_t *params) +{ + // Encode RRCReconfiguration to buffer + byte_array_t msg = do_HO_RRCReconfiguration(params); + + // Add RRCReconfiguration to handoverCommand + NR_HandoverCommand_t HoCommand = {0}; + HoCommand.criticalExtensions.present = NR_HandoverCommand__criticalExtensions_PR_c1; + asn1cCalloc(HoCommand.criticalExtensions.choice.c1, c1); + c1->present = NR_HandoverCommand__criticalExtensions__c1_PR_handoverCommand; + asn1cCalloc(HoCommand.criticalExtensions.choice.c1->choice.handoverCommand, hc); + OCTET_STRING_fromBuf(&hc->handoverCommandMessage, (const char *)msg.buf, msg.len); + free_byte_array(msg); + + if (LOG_DEBUGFLAG(DEBUG_ASN1)) + xer_fprint(stdout, &asn_DEF_NR_HandoverCommand, (void *)&HoCommand); + + // Encode handoverCommand to buffer + byte_array_t buffer = {.len = -1, .buf = NULL}; + buffer.len = uper_encode_to_new_buffer(&asn_DEF_NR_HandoverCommand, NULL, (void *)&HoCommand, (void **)&buffer.buf); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NR_HandoverCommand, &HoCommand); + + return buffer; +} + /** @brief HandoverPreparationInformation message (11.2.2 of TS 38.331) * 1) generate RRCReconfiguration to be transferred * 2) encodes UE Capabilities from UE Context diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.h b/openair2/RRC/NR/MESSAGES/asn1_msg.h index aab65f6685..668f2f8ade 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.h +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.h @@ -163,5 +163,7 @@ void free_MeasConfig(NR_MeasConfig_t *mc); int do_NR_Paging(uint8_t Mod_id, uint8_t *buffer, uint32_t tmsi); byte_array_t get_HandoverPreparationInformation(nr_rrc_reconfig_param_t *params, int scell_pci); +byte_array_t get_HandoverCommandMessage(nr_rrc_reconfig_param_t *params); +void fill_removal_lists_from_source_measConfig(NR_MeasConfig_t *measConfig, byte_array_t prep_info); #endif /* __RRC_NR_MESSAGES_ASN1_MSG__H__ */ diff --git a/openair2/RRC/NR/rrc_gNB_mobility.c b/openair2/RRC/NR/rrc_gNB_mobility.c index c9d60422e8..bf6ecb5865 100644 --- a/openair2/RRC/NR/rrc_gNB_mobility.c +++ b/openair2/RRC/NR/rrc_gNB_mobility.c @@ -408,6 +408,73 @@ static byte_array_t rrc_gNB_generate_HandoverPreparationInformation(gNB_RRC_INST return hoPrepInfo; } +static byte_array_t rrc_gNB_encode_HandoverCommand(gNB_RRC_UE_t *UE, gNB_RRC_INST *rrc) +{ + DevAssert(UE->ho_context); + DevAssert(UE->ho_context->target); + + NR_SecurityConfig_t *sec = calloc_or_fail(1, sizeof(*sec)); + sec->keyToUse = calloc_or_fail(1, sizeof(*sec->keyToUse)); + *sec->keyToUse = NR_SecurityConfig__keyToUse_master; + sec->securityAlgorithmConfig = calloc_or_fail(1, sizeof(*sec->securityAlgorithmConfig)); + struct NR_SecurityAlgorithmConfig *alg = sec->securityAlgorithmConfig; + alg->cipheringAlgorithm = UE->ciphering_algorithm; + alg->integrityProtAlgorithm = calloc_or_fail(1, sizeof(*alg->integrityProtAlgorithm)); + *alg->integrityProtAlgorithm = UE->integrity_algorithm; + + // Mark source gNB's measurement configuration for removal in UE->measConfig + if (UE->ho_context->target->ue_ho_prep_info.len) { + fill_removal_lists_from_source_measConfig(UE->measConfig, UE->ho_context->target->ue_ho_prep_info); + } + + /* 3GPP TS 38.331 RadioBearerConfig: re-establish PDCP whenever + the security key used for this radio bearer changes, e.g. for SRB2 + when receiving reconfiguration with sync [...]. Similarly, for DRBs + PDCP re-establishment is necessary with derivation of new UP keys */ + nr_rrc_reconfig_param_t params = get_RRCReconfiguration_params(rrc, UE, (1 << 1) | (1 << 2), true); + UE->xids[params.transaction_id] = RRC_DEDICATED_RECONF; + + params.security_config = sec; + params.masterKeyUpdate = true; + params.nextHopChainingCount = UE->nh_ncc; + byte_array_t out = get_HandoverCommandMessage(¶ms); + + // Free remove lists in UE->measConfig + ASN_STRUCT_FREE(asn_DEF_NR_MeasIdToRemoveList, UE->measConfig->measIdToRemoveList); + ASN_STRUCT_FREE(asn_DEF_NR_ReportConfigToRemoveList, UE->measConfig->reportConfigToRemoveList); + ASN_STRUCT_FREE(asn_DEF_NR_MeasObjectToRemoveList, UE->measConfig->measObjectToRemoveList); + + free_RRCReconfiguration_params(params); + return out; +} + +/** @brief This callback is used by the target gNB + * to trigger the Handover Request Acknowledge towards the AMF */ +static void nr_rrc_n2_ho_acknowledge(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE) +{ + AssertFatal(cu_exists_f1_ue_data(UE->rrc_ue_id), "No CU found for rrc_ue_id %d\n", UE->rrc_ue_id); + + f1_ue_data_t previous_data = cu_get_f1_ue_data(UE->rrc_ue_id); + /* this is the callback for N2 handover after F1 UE context setup response in + * the handover case. Check that there was no associated DU, then set it */ + AssertFatal(previous_data.secondary_ue == -1, "there was already a DU present\n"); + previous_data.secondary_ue = UE->ho_context->target->du_ue_id; + bool success = cu_update_f1_ue_data(UE->rrc_ue_id, &previous_data); + DevAssert(success); + LOG_I(NR_RRC, "Updated CU F1AP Context for UE %d, DU Id : %u\n", UE->rrc_ue_id, UE->ho_context->target->du_ue_id); + + byte_array_t hoCommand = rrc_gNB_encode_HandoverCommand(UE, rrc); + if (hoCommand.len < 0) { + LOG_E(NR_RRC, "ASN1 message encoding failed: failed to generate Handover Command Message\n"); + return; + } else { + LOG_D(NR_RRC, "HO LOG: Handover Command for UE %u Encoded (%ld bytes)\n", UE->rrc_ue_id, hoCommand.len); + } + + rrc_gNB_send_NGAP_HANDOVER_REQUEST_ACKNOWLEDGE(rrc, UE, hoCommand); + free_byte_array(hoCommand); +} + /** @brief Callback function to trigger NG Handover Failure on the target gNB, to inform the AMF * that the preparation of resources has failed (e.g. unsatisfied criteria, gNB is already loaded). * This message represents an Unsuccessful Outcome of the Handover Resource Allocation */ diff --git a/openair2/RRC/NR/rrc_gNB_mobility.h b/openair2/RRC/NR/rrc_gNB_mobility.h index 77b90ac3e0..4f31c433ec 100644 --- a/openair2/RRC/NR/rrc_gNB_mobility.h +++ b/openair2/RRC/NR/rrc_gNB_mobility.h @@ -53,6 +53,7 @@ typedef struct nr_ho_source_cu { /* acknowledgement of handover request. buf+len is the RRC Reconfiguration */ typedef void (*ho_req_ack_t)(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue); typedef void (*ho_success_t)(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue); +typedef void (*ho_failure_t)(gNB_RRC_INST *rrc, uint32_t gnb_ue_id, ngap_handover_failure_t *msg); typedef struct nr_ho_target_cu { /// pointer to the (target) DU structure From f66524879db7344aad3bbe3165aa5f8723238264 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Fri, 14 Mar 2025 11:26:16 +0100 Subject: [PATCH 721/964] Add NGAP Handover Command decoder and RRC handler on source gNB * add NG Handover Command message decoder * process in RRC: encode RRCReconfiguration message from the received HandoverCommandMessage * trigger RRCReconfiguration for handover Co-authored-by: batuhan duyuler --- openair2/COMMON/ngap_messages_def.h | 1 + openair2/COMMON/ngap_messages_types.h | 32 +++++++ openair2/RRC/NR/MESSAGES/asn1_msg.c | 39 ++++++++ openair2/RRC/NR/MESSAGES/asn1_msg.h | 1 + openair2/RRC/NR/rrc_gNB.c | 6 ++ openair2/RRC/NR/rrc_gNB_NGAP.c | 28 ++++++ openair2/RRC/NR/rrc_gNB_NGAP.h | 3 + openair2/RRC/NR/rrc_gNB_mobility.c | 3 +- openair2/RRC/NR/rrc_gNB_mobility.h | 2 + openair3/NGAP/ngap_gNB_handlers.c | 56 +++++++++++- .../NGAP/ngap_gNB_management_procedures.c | 8 ++ .../NGAP/ngap_gNB_management_procedures.h | 2 + openair3/NGAP/ngap_gNB_mobility_management.c | 88 +++++++++++++++++++ openair3/NGAP/ngap_gNB_mobility_management.h | 2 + 14 files changed, 269 insertions(+), 2 deletions(-) diff --git a/openair2/COMMON/ngap_messages_def.h b/openair2/COMMON/ngap_messages_def.h index e9e185e152..826c892533 100644 --- a/openair2/COMMON/ngap_messages_def.h +++ b/openair2/COMMON/ngap_messages_def.h @@ -85,6 +85,7 @@ MESSAGE_DEF(NGAP_PDUSESSION_MODIFY_REQ , MESSAGE_PRIORITY_MED, ngap_pd MESSAGE_DEF(NGAP_PDUSESSION_RELEASE_COMMAND , MESSAGE_PRIORITY_MED, ngap_pdusession_release_command_t , ngap_pdusession_release_command) MESSAGE_DEF(NGAP_UE_CONTEXT_RELEASE_COMMAND, MESSAGE_PRIORITY_MED, ngap_ue_release_command_t , ngap_ue_release_command) MESSAGE_DEF(NGAP_HANDOVER_REQUEST, MESSAGE_PRIORITY_MED, ngap_handover_request_t, ngap_handover_request) +MESSAGE_DEF(NGAP_HANDOVER_COMMAND, MESSAGE_PRIORITY_MED, ngap_handover_command_t, ngap_handover_command) /* NGAP <-> RRC messages (can be initiated either by MME or gNB) */ MESSAGE_DEF(NGAP_UE_CONTEXT_RELEASE_REQ , MESSAGE_PRIORITY_MED, ngap_ue_release_req_t , ngap_ue_release_req) diff --git a/openair2/COMMON/ngap_messages_types.h b/openair2/COMMON/ngap_messages_types.h index 5a5937500d..5d53c5c822 100644 --- a/openair2/COMMON/ngap_messages_types.h +++ b/openair2/COMMON/ngap_messages_types.h @@ -69,6 +69,7 @@ #define NGAP_HANDOVER_FAILURE(mSGpTR) (mSGpTR)->ittiMsg.ngap_handover_failure #define NGAP_HANDOVER_REQUEST(mSGpTR) (mSGpTR)->ittiMsg.ngap_handover_request #define NGAP_HANDOVER_REQUEST_ACKNOWLEDGE(mSGpTR) (mSGpTR)->ittiMsg.ngap_handover_request_ack +#define NGAP_HANDOVER_COMMAND(mSGpTR) (mSGpTR)->ittiMsg.ngap_handover_command #define NGAP_UE_CONTEXT_RELEASE_REQ(mSGpTR) (mSGpTR)->ittiMsg.ngap_ue_release_req #define NGAP_PDUSESSION_RELEASE_COMMAND(mSGpTR) (mSGpTR)->ittiMsg.ngap_pdusession_release_command @@ -648,6 +649,37 @@ typedef struct { byte_array_t target2source; } ngap_handover_request_ack_t; +/* 9.3.4.10 3GPP TS 38.413 */ +typedef struct { + // QoS Flow to be Forwarded List + uint8_t nb_of_qos_flow; + pdusession_associate_qosflow_t qos_setup_list[QOSFLOW_MAX_VALUE]; + // UL Forwarding UP TNL Information + uint32_t gtp_teid; + transport_layer_addr_t gNB_addr; +} ho_command_transfer_t; + +typedef struct { + // PDU Session ID (M) + uint8_t pdusession_id; + // Handover Command Transfer (M) + ho_command_transfer_t ho_command_transfer; +} pdusession_resource_handover_t; + +typedef struct { + // AMF UE NGAP ID + uint64_t amf_ue_ngap_id; + // RAN UE NGAP ID + uint32_t gNB_ue_ngap_id; + // Handover Type + ho_type_t handoverType; + // PDU Session Resource Handover List + uint8_t nb_of_pdusessions; + pdusession_resource_handover_t pdu_sessions[NGAP_MAX_PDU_SESSION]; + // Target to Source Transparent Container + byte_array_t handoverCommand; +} ngap_handover_command_t; + typedef struct ngap_ue_cap_info_ind_s { uint32_t gNB_ue_ngap_id; byte_array_t ue_radio_cap; diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.c b/openair2/RRC/NR/MESSAGES/asn1_msg.c index fc3ca002f4..20bf56390b 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.c +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.c @@ -64,6 +64,10 @@ #include "NR_LogicalChannelConfig.h" #include "NR_PDCP-Config.h" #include "NR_MAC-CellGroupConfig.h" +#include "NR_HandoverPreparationInformation.h" +#include "NR_HandoverCommand.h" +#include "NR_HandoverCommand-IEs.h" +#include "NR_AS-Config.h" #include "NR_SecurityModeCommand.h" #include "NR_CipheringAlgorithm.h" #include "NR_RRCReconfiguration-IEs.h" @@ -1221,6 +1225,41 @@ void fill_removal_lists_from_source_measConfig(NR_MeasConfig_t *currentMC, byte_ } } +int doRRCReconfiguration_from_HandoverCommand(byte_array_t *ba, const byte_array_t handoverCommand) +{ + // Decode Handover Command + NR_HandoverCommand_t *hoCommand = NULL; + asn_dec_rval_t dec_rval = uper_decode_complete(NULL, &asn_DEF_NR_HandoverCommand, (void **)&hoCommand, handoverCommand.buf, handoverCommand.len); + + if (dec_rval.code != RC_OK && dec_rval.consumed == 0) { + LOG_E(NR_RRC, "Can not decode Handover Command!\n"); + return -1; + } + + // Prepare DL DCCH message for RRCReconfiguration + NR_DL_DCCH_Message_t dl_dcch_msg = {0}; + asn_enc_rval_t enc_rval; + dl_dcch_msg.message.present = NR_DL_DCCH_MessageType_PR_c1; + asn1cCalloc(dl_dcch_msg.message.choice.c1, c1); + c1->present = NR_DL_DCCH_MessageType__c1_PR_rrcReconfiguration; + asn1cCalloc(c1->choice.rrcReconfiguration, rrcReconf); + + // Decode RRCReconfiguration from handoverCommandMessage + OCTET_STRING_t *ho = &hoCommand->criticalExtensions.choice.c1->choice.handoverCommand->handoverCommandMessage; + uper_decode_complete(NULL, &asn_DEF_NR_RRCReconfiguration, (void **)&rrcReconf, ho->buf, ho->size); + if (LOG_DEBUGFLAG(DEBUG_ASN1)) + xer_fprint(stdout, &asn_DEF_NR_DL_DCCH_Message, (void *)&dl_dcch_msg); + + // Encode DL DCCH message in buffer + enc_rval = uper_encode_to_buffer(&asn_DEF_NR_DL_DCCH_Message, NULL, &dl_dcch_msg, ba->buf, ba->len); + AssertFatal(enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", enc_rval.failed_type->name, enc_rval.encoded); + + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NR_DL_DCCH_Message, &dl_dcch_msg); + ASN_STRUCT_FREE(asn_DEF_NR_HandoverCommand, hoCommand); + + return ((enc_rval.encoded + 7) / 8); +} + byte_array_t get_HandoverCommandMessage(nr_rrc_reconfig_param_t *params) { // Encode RRCReconfiguration to buffer diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.h b/openair2/RRC/NR/MESSAGES/asn1_msg.h index 668f2f8ade..665edeef4b 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.h +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.h @@ -165,5 +165,6 @@ int do_NR_Paging(uint8_t Mod_id, uint8_t *buffer, uint32_t tmsi); byte_array_t get_HandoverPreparationInformation(nr_rrc_reconfig_param_t *params, int scell_pci); byte_array_t get_HandoverCommandMessage(nr_rrc_reconfig_param_t *params); void fill_removal_lists_from_source_measConfig(NR_MeasConfig_t *measConfig, byte_array_t prep_info); +int doRRCReconfiguration_from_HandoverCommand(byte_array_t *ba, byte_array_t handoverCommand); #endif /* __RRC_NR_MESSAGES_ASN1_MSG__H__ */ diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 48ea8e760e..32021d7f22 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -98,6 +98,7 @@ #include "NR_DL-DCCH-Message.h" #include "ds/byte_array.h" #include "alg/find.h" +#include "NR_HandoverCommand.h" #ifdef E2_AGENT #include "openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc_extern.h" @@ -2949,6 +2950,11 @@ void *rrc_gnb_task(void *args_p) { rrc_gNB_free_Handover_Request(&NGAP_HANDOVER_REQUEST(msg_p)); // Free transfered NG message break; + case NGAP_HANDOVER_COMMAND: + rrc_gNB_process_HandoverCommand(RC.nrrrc[instance], &NGAP_HANDOVER_COMMAND(msg_p)); + rrc_gNB_free_Handover_Command(&NGAP_HANDOVER_COMMAND(msg_p)); // Free transfered NG message + break; + default: LOG_E(NR_RRC, "[gNB %ld] Received unexpected message %s\n", instance, msg_name_p); break; diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index 19cd12704f..889cd810b2 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -39,6 +39,9 @@ #include #include "E1AP_ConfidentialityProtectionIndication.h" #include "E1AP_IntegrityProtectionIndication.h" +#include "NR_UE-CapabilityRAT-ContainerList.h" +#include "NR_HandoverCommand.h" +#include "NR_HandoverCommand-IEs.h" #include "NGAP_CauseRadioNetwork.h" #include "NGAP_Dynamic5QIDescriptor.h" #include "NGAP_GTPTunnel.h" @@ -1161,6 +1164,31 @@ void rrc_gNB_free_Handover_Request(ngap_handover_request_t *msg) free(msg->mobility_restriction); } +/** @brief Process NG Handover Command on Source gNB */ +void rrc_gNB_process_HandoverCommand(gNB_RRC_INST *rrc, const ngap_handover_command_t *msg) +{ + rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(rrc, msg->gNB_ue_ngap_id); + + if (ue_context_p == NULL) { + LOG_W(NR_RRC, "Unknown UE context associated to gNB_ue_ngap_id (%u)\n", msg->gNB_ue_ngap_id); + return; + } + gNB_RRC_UE_t *UE = &ue_context_p->ue_context; + + uint8_t buffer[NR_RRC_BUF_SIZE]; + byte_array_t ba = {.buf = buffer, .len = sizeof(buffer)}; + int enc = doRRCReconfiguration_from_HandoverCommand(&ba, msg->handoverCommand); + DevAssert(enc > 0); + + rrc_gNB_trigger_reconfiguration_for_handover(rrc, UE, buffer, enc); + LOG_A(NR_RRC, "Send reconfiguration (HO Command) to UE %u/RNTI %04x\n", UE->rrc_ue_id, UE->rnti); +} + +void rrc_gNB_free_Handover_Command(ngap_handover_command_t *msg) +{ + free_byte_array(msg->handoverCommand); +} + /* * Process the NG command NGAP_UE_CONTEXT_RELEASE_COMMAND, sent by AMF. * The gNB should remove all pdu session, NG context, and other context of the UE. diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.h b/openair2/RRC/NR/rrc_gNB_NGAP.h index 9d51db4186..c249711629 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.h +++ b/openair2/RRC/NR/rrc_gNB_NGAP.h @@ -101,4 +101,7 @@ void rrc_gNB_free_Handover_Request(ngap_handover_request_t *msg); void rrc_gNB_send_NGAP_HANDOVER_REQUEST_ACKNOWLEDGE(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, byte_array_t ho_command); +void rrc_gNB_process_HandoverCommand(gNB_RRC_INST *rrc, const ngap_handover_command_t *msg); +void rrc_gNB_free_Handover_Command(ngap_handover_command_t *msg); + #endif diff --git a/openair2/RRC/NR/rrc_gNB_mobility.c b/openair2/RRC/NR/rrc_gNB_mobility.c index bf6ecb5865..9e35b976e0 100644 --- a/openair2/RRC/NR/rrc_gNB_mobility.c +++ b/openair2/RRC/NR/rrc_gNB_mobility.c @@ -231,7 +231,8 @@ static void rrc_deliver_ue_ctxt_modif_req(void *deliver_pdu_data, ue_id_t ue_id, data->modification_req->rrc_container = &ba; data->rrc->mac_rrc.ue_context_modification_request(data->assoc_id, data->modification_req); } -static void rrc_gNB_trigger_reconfiguration_for_handover(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue, uint8_t *rrc_reconf, int rrc_reconf_len) + +void rrc_gNB_trigger_reconfiguration_for_handover(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue, uint8_t *rrc_reconf, int rrc_reconf_len) { f1_ue_data_t ue_data = cu_get_f1_ue_data(ue->rrc_ue_id); diff --git a/openair2/RRC/NR/rrc_gNB_mobility.h b/openair2/RRC/NR/rrc_gNB_mobility.h index 4f31c433ec..5a6542132c 100644 --- a/openair2/RRC/NR/rrc_gNB_mobility.h +++ b/openair2/RRC/NR/rrc_gNB_mobility.h @@ -89,4 +89,6 @@ void nr_rrc_trigger_n2_ho(gNB_RRC_INST *rrc, int serving_pci, const nr_neighbour_cell_t *neighbour_config); +void rrc_gNB_trigger_reconfiguration_for_handover(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue, uint8_t *rrc_reconf, int rrc_reconf_len); + #endif /* RRC_GNB_MOBILITY_H_ */ diff --git a/openair3/NGAP/ngap_gNB_handlers.c b/openair3/NGAP/ngap_gNB_handlers.c index 485d37236a..226c8e8fa0 100644 --- a/openair3/NGAP/ngap_gNB_handlers.c +++ b/openair3/NGAP/ngap_gNB_handlers.c @@ -997,6 +997,60 @@ static int ngap_gNB_handle_pdusession_setup_request(sctp_assoc_t assoc_id, uint3 return 0; } +/** @brief Handler for the NG Handover Command + * AMF -> source NG-RAN */ +static int ngap_gNB_handle_handover_command(sctp_assoc_t assoc_id, uint32_t stream, NGAP_NGAP_PDU_t *pdu) +{ + NGAP_INFO("Received NG Handover Command\n"); + ngap_gNB_amf_data_t *amf_desc_p = NULL; + DevAssert(pdu != NULL); + + if ((amf_desc_p = ngap_gNB_get_AMF(NULL, assoc_id, 0)) == NULL) { + NGAP_ERROR( + "[SCTP %u] Received Handover Command for non " + "existing AMF context\n", + assoc_id); + return -1; + } + + MessageDef *message_p = itti_alloc_new_message(TASK_NGAP, 0, NGAP_HANDOVER_COMMAND); + ngap_handover_command_t *msg = &NGAP_HANDOVER_COMMAND(message_p); + memset(msg, 0, sizeof(*msg)); + if (decode_ng_handover_command(msg, pdu) < 0) { + NGAP_ERROR("Failed to decode NG Handover Command"); + free_ng_handover_command(msg); + itti_free(TASK_NGAP, message_p); + return -1; + } + + ngap_gNB_ue_context_t *ue_desc_p = ngap_get_ue_context(msg->gNB_ue_ngap_id); + if (!ue_desc_p) { + NGAP_ERROR( + "[SCTP %u] Received HO Command Msg for non existing UE context (gNB_ue_ngap_id %d) \n", + assoc_id, + msg->gNB_ue_ngap_id); + free_ng_handover_command(msg); + itti_free(TASK_NGAP, message_p); + return -1; + } + + ue_desc_p->rx_stream = stream; + + if (ue_desc_p->amf_ue_ngap_id != msg->amf_ue_ngap_id) { + NGAP_ERROR("UE context amf_ue_ngap_id is different form that of the message (%ld != %ld)", + ue_desc_p->amf_ue_ngap_id, + msg->amf_ue_ngap_id); + free_ng_handover_command(msg); + itti_free(TASK_NGAP, message_p); + return -1; + } + + NGAP_DEBUG("Handover Command is parsed with a size of: %ld. Sending to RRC GNB!\n", msg->handoverCommand.len); + itti_send_msg_to_task(TASK_RRC_GNB, amf_desc_p->ngap_gNB_instance->instance, message_p); + + return 0; +} + static int ngap_gNB_handle_paging(sctp_assoc_t assoc_id, uint32_t stream, NGAP_NGAP_PDU_t *pdu) { ngap_gNB_amf_data_t *amf_desc_p = NULL; @@ -1338,7 +1392,7 @@ const ngap_message_decoded_callback ngap_messages_callback[][3] = { {ngap_gNB_handle_error_indication, 0, 0}, /* ErrorIndication */ {0, 0, 0}, /* HandoverCancel */ {0, 0, 0}, /* HandoverNotification */ - {0, 0, 0}, /* HandoverPreparation */ + {0, ngap_gNB_handle_handover_command, 0}, /* HandoverPreparation */ {ngap_gNB_handle_handover_request, 0, 0}, /* HandoverResourceAllocation */ {ngap_gNB_handle_initial_context_request, 0, 0}, /* InitialContextSetup */ {0, 0, 0}, /* InitialUEMessage */ diff --git a/openair3/NGAP/ngap_gNB_management_procedures.c b/openair3/NGAP/ngap_gNB_management_procedures.c index 6ffce99d9c..9d8748a88b 100644 --- a/openair3/NGAP/ngap_gNB_management_procedures.c +++ b/openair3/NGAP/ngap_gNB_management_procedures.c @@ -200,3 +200,11 @@ void tnl_to_bitstring(BIT_STRING_t *out, const transport_layer_addr_t in) out->bits_unused = 0; } } + +void bitstring_to_tnl(transport_layer_addr_t *out, const BIT_STRING_t in) +{ + if (in.size) { + memcpy(out->buffer, in.buf, in.size); + out->length = in.size; + } +} diff --git a/openair3/NGAP/ngap_gNB_management_procedures.h b/openair3/NGAP/ngap_gNB_management_procedures.h index 365fd0dd9d..28f4b24e7e 100644 --- a/openair3/NGAP/ngap_gNB_management_procedures.h +++ b/openair3/NGAP/ngap_gNB_management_procedures.h @@ -50,4 +50,6 @@ void ngap_gNB_prepare_internal_data(void); void tnl_to_bitstring(BIT_STRING_t *out, const transport_layer_addr_t in); +void bitstring_to_tnl(transport_layer_addr_t *out, const BIT_STRING_t in); + #endif /* NGAP_GNB_MANAGEMENT_PROCEDURES_H_ */ diff --git a/openair3/NGAP/ngap_gNB_mobility_management.c b/openair3/NGAP/ngap_gNB_mobility_management.c index 4c64659e01..68a6823d98 100644 --- a/openair3/NGAP/ngap_gNB_mobility_management.c +++ b/openair3/NGAP/ngap_gNB_mobility_management.c @@ -472,3 +472,91 @@ void free_ng_handover_req_ack(ngap_handover_request_ack_t *msg) { free_byte_array(msg->target2source); } + +/** @brief Decoder for the NG Handover Command */ +int decode_ng_handover_command(ngap_handover_command_t *msg, NGAP_NGAP_PDU_t *pdu) +{ + DevAssert(pdu != NULL); + NGAP_HandoverCommandIEs_t *ie; + NGAP_HandoverCommand_t *container = &pdu->choice.successfulOutcome->value.choice.HandoverCommand; + + // AMF UE NGAP ID (M) + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_HandoverCommandIEs_t, ie, container, NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID, true); + asn_INTEGER2ulong(&(ie->value.choice.AMF_UE_NGAP_ID), &msg->amf_ue_ngap_id); + + // RAN UE NGAP ID (M) + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_HandoverCommandIEs_t, ie, container, NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID, true); + msg->gNB_ue_ngap_id = ie->value.choice.RAN_UE_NGAP_ID; + + // Handover Type (M) + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_HandoverCommandIEs_t, ie, container, NGAP_ProtocolIE_ID_id_HandoverType, true); + if (ie->value.choice.HandoverType != HANDOVER_TYPE_INTRA5GS) { + NGAP_ERROR("Only Intra 5GS Handover is supported at the moment!\n"); + return -1; + } + + // PDU Session Resource Handover List (O) + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_HandoverCommandIEs_t, ie, container, NGAP_ProtocolIE_ID_id_HandoverType, false); + if (ie != NULL) { + msg->nb_of_pdusessions = ie->value.choice.PDUSessionResourceHandoverList.list.count; + + for (int i = 0; i < msg->nb_of_pdusessions; ++i) { + NGAP_PDUSessionResourceHandoverItem_t *item = ie->value.choice.PDUSessionResourceHandoverList.list.array[i]; + + // PDU Session ID (M) + msg->pdu_sessions[i].pdusession_id = item->pDUSessionID; + + // Handover Command Transfer (M) + NGAP_HandoverCommandTransfer_t *hoCommandTransfer = NULL; + asn_dec_rval_t dec_rval = uper_decode_complete(NULL, + &asn_DEF_NGAP_HandoverCommandTransfer, + (void **)&hoCommandTransfer, + item->handoverCommandTransfer.buf, + item->handoverCommandTransfer.size); + if (dec_rval.code != RC_OK) { + NGAP_ERROR("Failed to decode handoverCommandTransfer\n"); + continue; + } + + // DL Forwarding UP TNL Information (O) + if (hoCommandTransfer->dLForwardingUP_TNLInformation) { + NGAP_UPTransportLayerInformation_t *up_tnl = hoCommandTransfer->dLForwardingUP_TNLInformation; + if (hoCommandTransfer->dLForwardingUP_TNLInformation->present == NGAP_UPTransportLayerInformation_PR_gTPTunnel) { + OCTET_STRING_TO_INT32(&(up_tnl->choice.gTPTunnel->gTP_TEID), msg->pdu_sessions[i].ho_command_transfer.gtp_teid); + bitstring_to_tnl(&msg->pdu_sessions[i].ho_command_transfer.gNB_addr, up_tnl->choice.gTPTunnel->transportLayerAddress); + } else { + NGAP_WARN("Missing DL Forwarding UP TNL Information\n"); + } + } + ASN_STRUCT_FREE(asn_DEF_NGAP_HandoverCommandTransfer, hoCommandTransfer); + } + } + + // Target to Source Transparent Container (M) + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_HandoverCommandIEs_t, + ie, + container, + NGAP_ProtocolIE_ID_id_TargetToSource_TransparentContainer, + true); + NGAP_TargetToSource_TransparentContainer_t *target2source = &(ie->value.choice.TargetToSource_TransparentContainer); + NGAP_TargetNGRANNode_ToSourceNGRANNode_TransparentContainer_t *transparentContainer = NULL; + asn_dec_rval_t dec_rval = aper_decode_complete(NULL, + &asn_DEF_NGAP_TargetNGRANNode_ToSourceNGRANNode_TransparentContainer, + (void **)&transparentContainer, + target2source->buf, + target2source->size); + if (dec_rval.code != RC_OK) { + NGAP_ERROR("Failed to decode TargetToSource_TransparentContainer\n"); + return -1; + } + + msg->handoverCommand = create_byte_array(transparentContainer->rRCContainer.size, transparentContainer->rRCContainer.buf); + ASN_STRUCT_FREE(asn_DEF_NGAP_TargetNGRANNode_ToSourceNGRANNode_TransparentContainer, transparentContainer); + + return 0; +} + +void free_ng_handover_command(ngap_handover_command_t *msg) +{ + free_byte_array(msg->handoverCommand); +} diff --git a/openair3/NGAP/ngap_gNB_mobility_management.h b/openair3/NGAP/ngap_gNB_mobility_management.h index dd0061ca35..4ed3229a84 100644 --- a/openair3/NGAP/ngap_gNB_mobility_management.h +++ b/openair3/NGAP/ngap_gNB_mobility_management.h @@ -31,5 +31,7 @@ NGAP_NGAP_PDU_t *encode_ng_handover_failure(const ngap_handover_failure_t *msg); int decode_ng_handover_request(ngap_handover_request_t *out, const NGAP_NGAP_PDU_t *pdu); NGAP_NGAP_PDU_t *encode_ng_handover_request_ack(ngap_handover_request_ack_t *msg); void free_ng_handover_req_ack(ngap_handover_request_ack_t *msg); +int decode_ng_handover_command(ngap_handover_command_t *msg, NGAP_NGAP_PDU_t *pdu); +void free_ng_handover_command(ngap_handover_command_t *msg); #endif /* NGAP_GNB_MOBILITY_MANAGEMENT_H_ */ From e611d092e9927f7b99c0ab5bd15d6f0585732355 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Fri, 14 Mar 2025 12:35:46 +0100 Subject: [PATCH 722/964] Add NGAP Handover Notify encoder and trigger on the target NG-RAN This commit introduces the NG Mobility Management Procedure known as Handover Notification. The outbound message is sent by the target NG-RAN and is known as Handover Notify. The procedure is used to indicate to the AMF that the UE has arrived to the target cell and the NG-based handover has been successfully completed * after RRCReconfiguration complete, in the N2 callback for HO success * add NGAP encoder for the message * RRC callback to trigger Handover Notify message Co-authored-by: batuhan duyuler --- openair2/COMMON/ngap_messages_def.h | 1 + openair2/COMMON/ngap_messages_types.h | 18 +++++++ openair2/RRC/NR/rrc_gNB_NGAP.c | 22 ++++++++ openair2/RRC/NR/rrc_gNB_NGAP.h | 2 + openair2/RRC/NR/rrc_gNB_mobility.c | 7 +++ openair3/NGAP/ngap_gNB.c | 48 +++++++++++++++++ openair3/NGAP/ngap_gNB_encoder.c | 3 +- openair3/NGAP/ngap_gNB_mobility_management.c | 57 ++++++++++++++++++++ openair3/NGAP/ngap_gNB_mobility_management.h | 1 + openair3/NGAP/ngap_msg_includes.h | 1 + 10 files changed, 159 insertions(+), 1 deletion(-) diff --git a/openair2/COMMON/ngap_messages_def.h b/openair2/COMMON/ngap_messages_def.h index 826c892533..fc07cffc6d 100644 --- a/openair2/COMMON/ngap_messages_def.h +++ b/openair2/COMMON/ngap_messages_def.h @@ -74,6 +74,7 @@ MESSAGE_DEF(NGAP_PDUSESSION_RELEASE_RESPONSE , MESSAGE_PRIORITY_MED, ngap_pdu MESSAGE_DEF(NGAP_HANDOVER_REQUIRED, MESSAGE_PRIORITY_MED, ngap_handover_required_t, ngap_handover_required) MESSAGE_DEF(NGAP_HANDOVER_FAILURE, MESSAGE_PRIORITY_MED, ngap_handover_failure_t, ngap_handover_failure) MESSAGE_DEF(NGAP_HANDOVER_REQUEST_ACKNOWLEDGE, MESSAGE_PRIORITY_MED, ngap_handover_request_ack_t, ngap_handover_request_ack) +MESSAGE_DEF(NGAP_HANDOVER_NOTIFY, MESSAGE_PRIORITY_MED, ngap_handover_notify_t, ngap_handover_notify) /* NGAP -> RRC messages */ MESSAGE_DEF(NGAP_DOWNLINK_NAS , MESSAGE_PRIORITY_MED, ngap_downlink_nas_t , ngap_downlink_nas ) diff --git a/openair2/COMMON/ngap_messages_types.h b/openair2/COMMON/ngap_messages_types.h index 5d53c5c822..eb21935e03 100644 --- a/openair2/COMMON/ngap_messages_types.h +++ b/openair2/COMMON/ngap_messages_types.h @@ -70,6 +70,7 @@ #define NGAP_HANDOVER_REQUEST(mSGpTR) (mSGpTR)->ittiMsg.ngap_handover_request #define NGAP_HANDOVER_REQUEST_ACKNOWLEDGE(mSGpTR) (mSGpTR)->ittiMsg.ngap_handover_request_ack #define NGAP_HANDOVER_COMMAND(mSGpTR) (mSGpTR)->ittiMsg.ngap_handover_command +#define NGAP_HANDOVER_NOTIFY(mSGpTR) (mSGpTR)->ittiMsg.ngap_handover_notify #define NGAP_UE_CONTEXT_RELEASE_REQ(mSGpTR) (mSGpTR)->ittiMsg.ngap_ue_release_req #define NGAP_PDUSESSION_RELEASE_COMMAND(mSGpTR) (mSGpTR)->ittiMsg.ngap_pdusession_release_command @@ -680,6 +681,23 @@ typedef struct { byte_array_t handoverCommand; } ngap_handover_command_t; +/* 9.3.1.16 3GPP TS 38.413 */ +typedef struct { + // NR user location information + target_ran_node_id_t target_ng_ran; + uint32_t nrCellIdentity; +} user_location_information_t; + +/* 9.2.3.7 3GPP TS 38.413 */ +typedef struct { + // RAN UE NGAP ID + uint32_t gNB_ue_ngap_id; + // AMF UE NGAP ID + uint64_t amf_ue_ngap_id; + // User Location Information + user_location_information_t user_info; +} ngap_handover_notify_t; + typedef struct ngap_ue_cap_info_ind_s { uint32_t gNB_ue_ngap_id; byte_array_t ue_radio_cap; diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index 889cd810b2..e7459b1d49 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -1334,6 +1334,28 @@ void rrc_gNB_send_NGAP_HANDOVER_REQUEST_ACKNOWLEDGE(gNB_RRC_INST *rrc, gNB_RRC_U itti_send_msg_to_task(TASK_NGAP, rrc->module_id, msg_p); } +/** @brief Prepare NG Handover Notify message and inform NGAP */ +void rrc_gNB_send_NGAP_HANDOVER_NOTIFY(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE) +{ + LOG_I(NR_RRC, "Triggering NGAP Handover Notify\n"); + + MessageDef *msg_p = itti_alloc_new_message(TASK_RRC_GNB, 0, NGAP_HANDOVER_NOTIFY); + ngap_handover_notify_t *ho_notify = &NGAP_HANDOVER_NOTIFY(msg_p); + memset(ho_notify, 0, sizeof(*ho_notify)); + nr_rrc_du_container_t *du = get_du_by_cell_id(rrc, rrc->nr_cellid); + + ho_notify->gNB_ue_ngap_id = UE->rrc_ue_id; + ho_notify->amf_ue_ngap_id = UE->amf_ue_ngap_id; + ho_notify->user_info.nrCellIdentity = rrc->nr_cellid; + ho_notify->user_info.target_ng_ran.tac = *du->setup_req->cell->info.tac; + ho_notify->user_info.target_ng_ran.targetgNBId = rrc->node_id; + ho_notify->user_info.target_ng_ran.plmn_identity.mcc = du->setup_req->cell->info.plmn.mcc; + ho_notify->user_info.target_ng_ran.plmn_identity.mnc = du->setup_req->cell->info.plmn.mnc; + ho_notify->user_info.target_ng_ran.plmn_identity.mnc_digit_length = du->setup_req->cell->info.plmn.mnc_digit_length; + + itti_send_msg_to_task(TASK_NGAP, rrc->module_id, msg_p); +} + void rrc_gNB_send_NGAP_PDUSESSION_RELEASE_RESPONSE(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, uint8_t xid) { int pdu_sessions_released = 0; diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.h b/openair2/RRC/NR/rrc_gNB_NGAP.h index c249711629..4d44b7197c 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.h +++ b/openair2/RRC/NR/rrc_gNB_NGAP.h @@ -104,4 +104,6 @@ void rrc_gNB_send_NGAP_HANDOVER_REQUEST_ACKNOWLEDGE(gNB_RRC_INST *rrc, gNB_RRC_U void rrc_gNB_process_HandoverCommand(gNB_RRC_INST *rrc, const ngap_handover_command_t *msg); void rrc_gNB_free_Handover_Command(ngap_handover_command_t *msg); +void rrc_gNB_send_NGAP_HANDOVER_NOTIFY(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE); + #endif diff --git a/openair2/RRC/NR/rrc_gNB_mobility.c b/openair2/RRC/NR/rrc_gNB_mobility.c index 9e35b976e0..9e76217dc9 100644 --- a/openair2/RRC/NR/rrc_gNB_mobility.c +++ b/openair2/RRC/NR/rrc_gNB_mobility.c @@ -476,6 +476,13 @@ static void nr_rrc_n2_ho_acknowledge(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE) free_byte_array(hoCommand); } +/** @brief This callback is used by the target gNB + * to trigger the Handover Notify towards the AMF */ +static void nr_rrc_n2_ho_complete(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE) +{ + rrc_gNB_send_NGAP_HANDOVER_NOTIFY(rrc, UE); +} + /** @brief Callback function to trigger NG Handover Failure on the target gNB, to inform the AMF * that the preparation of resources has failed (e.g. unsatisfied criteria, gNB is already loaded). * This message represents an Unsuccessful Outcome of the Handover Resource Allocation */ diff --git a/openair3/NGAP/ngap_gNB.c b/openair3/NGAP/ngap_gNB.c index e80b914871..272759de4c 100644 --- a/openair3/NGAP/ngap_gNB.c +++ b/openair3/NGAP/ngap_gNB.c @@ -419,6 +419,50 @@ static int ngap_gNB_handover_request_acknowledge(instance_t instance, ngap_hando return 0; } +static int ngap_gNB_handover_notify(instance_t instance, const ngap_handover_notify_t *msg) +{ + LOG_D(NGAP, "Encode NGAP Handover Notify\n"); + ngap_gNB_ue_context_t *ue_context_p = NULL; + byte_array_t ba = { .buf = NULL, .len = 0}; + + /* Retrieve the NGAP gNB instance associated with Mod_id */ + ngap_gNB_instance_t *ngap_gNB_instance_p = ngap_gNB_get_instance(instance); + DevAssert(msg != NULL); + DevAssert(ngap_gNB_instance_p != NULL); + + if ((ue_context_p = ngap_get_ue_context(msg->gNB_ue_ngap_id)) == NULL) { + NGAP_ERROR("Failed to encode Handover Notify: no ue context associated with gNB_ue_ngap_id=%d\n", msg->gNB_ue_ngap_id); + return -1; + } + + if (ue_context_p->gNB_ue_ngap_id != msg->gNB_ue_ngap_id) { + NGAP_ERROR("Failed to encode Handover Notify: unknown gNB_ue_ngap_id=%d\n", msg->gNB_ue_ngap_id); + return -1; + } + + if (ue_context_p->amf_ue_ngap_id != msg->amf_ue_ngap_id) { + NGAP_ERROR("Failed to encode Handover Notify: unknown amf_ue_ngap_id=%ld\n", msg->amf_ue_ngap_id); + return -1; + } + + NGAP_NGAP_PDU_t *pdu = encode_ng_handover_notify(msg); + + if (ngap_gNB_encode_pdu(pdu, &ba.buf, (uint32_t *)&ba.len) < 0) { + NGAP_ERROR("Failed to encode NG Handover Notify message\n"); + ASN_STRUCT_FREE(asn_DEF_NGAP_NGAP_PDU, pdu); + return -1; + } + + /* UE associated signalling -> use the allocated stream */ + ngap_gNB_itti_send_sctp_data_req(ngap_gNB_instance_p->instance, + ue_context_p->amf_ref->assoc_id, + ba.buf, + ba.len, + ue_context_p->tx_stream); + + return 0; +} + void *ngap_gNB_process_itti_msg(void *notUsed) { MessageDef *received_msg = NULL; int result; @@ -509,6 +553,10 @@ void *ngap_gNB_process_itti_msg(void *notUsed) { free_ng_handover_req_ack(&NGAP_HANDOVER_REQUEST_ACKNOWLEDGE(received_msg)); break; + case NGAP_HANDOVER_NOTIFY: + ngap_gNB_handover_notify(instance, &NGAP_HANDOVER_NOTIFY(received_msg)); + break; + default: NGAP_ERROR("Received unhandled message: %d:%s\n", ITTI_MSG_ID(received_msg), ITTI_MSG_NAME(received_msg)); break; diff --git a/openair3/NGAP/ngap_gNB_encoder.c b/openair3/NGAP/ngap_gNB_encoder.c index 056aea2fe6..16954744e2 100644 --- a/openair3/NGAP/ngap_gNB_encoder.c +++ b/openair3/NGAP/ngap_gNB_encoder.c @@ -53,7 +53,8 @@ static inline int ngap_gNB_encode_initiating(NGAP_NGAP_PDU_t *pdu, uint8_t **buf NGAP_ProcedureCode_id_UEContextReleaseRequest, NGAP_ProcedureCode_id_PathSwitchRequest, NGAP_ProcedureCode_id_PDUSessionResourceModifyIndication, - NGAP_ProcedureCode_id_HandoverPreparation}; + NGAP_ProcedureCode_id_HandoverPreparation, + NGAP_ProcedureCode_id_HandoverNotification}; int i; for (i = 0; i < sizeofArray(tmp); i++) if (pdu->choice.initiatingMessage->procedureCode == tmp[i]) diff --git a/openair3/NGAP/ngap_gNB_mobility_management.c b/openair3/NGAP/ngap_gNB_mobility_management.c index 68a6823d98..565be7acd5 100644 --- a/openair3/NGAP/ngap_gNB_mobility_management.c +++ b/openair3/NGAP/ngap_gNB_mobility_management.c @@ -560,3 +560,60 @@ void free_ng_handover_command(ngap_handover_command_t *msg) { free_byte_array(msg->handoverCommand); } + +NGAP_NGAP_PDU_t *encode_ng_handover_notify(const ngap_handover_notify_t *msg) +{ + NGAP_NGAP_PDU_t *pdu = malloc_or_fail(sizeof(*pdu)); + + // Message Type (M) + pdu->present = NGAP_NGAP_PDU_PR_initiatingMessage; + asn1cCalloc(pdu->choice.initiatingMessage, head); + head->procedureCode = NGAP_ProcedureCode_id_HandoverNotification; + head->criticality = NGAP_Criticality_ignore; + head->value.present = NGAP_InitiatingMessage__value_PR_HandoverNotify; + NGAP_HandoverNotify_t *out = &head->value.choice.HandoverNotify; + + // AMF UE NGAP ID (M) + { + asn1cSequenceAdd(out->protocolIEs.list, NGAP_HandoverNotifyIEs_t, ie); + ie->id = NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID; + ie->criticality = NGAP_Criticality_reject; + ie->value.present = NGAP_HandoverNotifyIEs__value_PR_AMF_UE_NGAP_ID; + asn_uint642INTEGER(&ie->value.choice.AMF_UE_NGAP_ID, msg->amf_ue_ngap_id); + } + + // RAN UE NGAP ID (M) + { + asn1cSequenceAdd(out->protocolIEs.list, NGAP_HandoverNotifyIEs_t, ie); + ie->id = NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID; + ie->criticality = NGAP_Criticality_reject; + ie->value.present = NGAP_HandoverNotifyIEs__value_PR_RAN_UE_NGAP_ID; + ie->value.choice.RAN_UE_NGAP_ID = msg->gNB_ue_ngap_id; + } + + // User Location Information (M) + { + asn1cSequenceAdd(out->protocolIEs.list, NGAP_HandoverNotifyIEs_t, ie); + ie->id = NGAP_ProtocolIE_ID_id_UserLocationInformation; + ie->criticality = NGAP_Criticality_ignore; + ie->value.present = NGAP_HandoverNotifyIEs__value_PR_UserLocationInformation; + ie->value.choice.UserLocationInformation.present = NGAP_UserLocationInformation_PR_userLocationInformationNR; + asn1cCalloc(ie->value.choice.UserLocationInformation.choice.userLocationInformationNR, userinfo_nr_p); + // NR User Location Information + const target_ran_node_id_t *target = &msg->user_info.target_ng_ran; + // CGI (M) + MACRO_GNB_ID_TO_CELL_IDENTITY(target->targetgNBId, msg->user_info.nrCellIdentity, &userinfo_nr_p->nR_CGI.nRCellIdentity); + MCC_MNC_TO_TBCD(target->plmn_identity.mcc, + target->plmn_identity.mnc, + target->plmn_identity.mnc_digit_length, + &userinfo_nr_p->nR_CGI.pLMNIdentity); + // TAI (M) + INT24_TO_OCTET_STRING(target->tac, &userinfo_nr_p->tAI.tAC); + MCC_MNC_TO_PLMNID(target->plmn_identity.mcc, + target->plmn_identity.mnc, + target->plmn_identity.mnc_digit_length, + &userinfo_nr_p->tAI.pLMNIdentity); + } + + return pdu; +} diff --git a/openair3/NGAP/ngap_gNB_mobility_management.h b/openair3/NGAP/ngap_gNB_mobility_management.h index 4ed3229a84..d31bdb0caa 100644 --- a/openair3/NGAP/ngap_gNB_mobility_management.h +++ b/openair3/NGAP/ngap_gNB_mobility_management.h @@ -33,5 +33,6 @@ NGAP_NGAP_PDU_t *encode_ng_handover_request_ack(ngap_handover_request_ack_t *msg void free_ng_handover_req_ack(ngap_handover_request_ack_t *msg); int decode_ng_handover_command(ngap_handover_command_t *msg, NGAP_NGAP_PDU_t *pdu); void free_ng_handover_command(ngap_handover_command_t *msg); +NGAP_NGAP_PDU_t *encode_ng_handover_notify(const ngap_handover_notify_t *msg); #endif /* NGAP_GNB_MOBILITY_MANAGEMENT_H_ */ diff --git a/openair3/NGAP/ngap_msg_includes.h b/openair3/NGAP/ngap_msg_includes.h index a80df29401..4224660974 100644 --- a/openair3/NGAP/ngap_msg_includes.h +++ b/openair3/NGAP/ngap_msg_includes.h @@ -101,5 +101,6 @@ #include "NGAP_HandoverRequestAcknowledgeTransfer.h" #include "NGAP_QosFlowItemWithDataForwarding.h" #include "NR_HandoverPreparationInformation.h" +#include "NGAP_HandoverNotify.h" #endif // NGAP_MSG_INCLUDES_H From 28f926607e8ae1ccc77e48319340325f77943c05 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Fri, 14 Mar 2025 14:51:50 +0100 Subject: [PATCH 723/964] Add N2 HO trigger on Bearer Context Setup Response (target NG-RAN) * add trigger function to (1) add the callbacks and (2) initiate handover on the target NG-RAN * add handover failure callback on target NG-RAN: the Handover Failure is a procedure that belongs to the target NG-RAN and it is different from the Handover Cancel procedure Co-authored-by: batuhan duyuler --- openair2/RRC/NR/MESSAGES/asn1_msg.c | 43 +++++++++++++++++++++++++++++ openair2/RRC/NR/MESSAGES/asn1_msg.h | 4 +++ openair2/RRC/NR/rrc_gNB.c | 26 ++++++++--------- openair2/RRC/NR/rrc_gNB_NGAP.c | 1 + openair2/RRC/NR/rrc_gNB_mobility.c | 26 +++++++++++++++-- openair2/RRC/NR/rrc_gNB_mobility.h | 7 +++++ 6 files changed, 92 insertions(+), 15 deletions(-) diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.c b/openair2/RRC/NR/MESSAGES/asn1_msg.c index 20bf56390b..ac58b3a278 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.c +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.c @@ -87,6 +87,7 @@ #include "NR_HandoverPreparationInformation.h" #include "NR_HandoverPreparationInformation-IEs.h" #include "NR_HandoverCommand.h" +#include "NR_UE-CapabilityRAT-ContainerList.h" #include "common/utils/nr/nr_common.h" #if defined(NR_Rel16) #include "NR_SCS-SpecificCarrier.h" @@ -202,6 +203,48 @@ int xer_nr_sprint(char *string, size_t string_size, asn_TYPE_descriptor_t *td, v return er.encoded; } +struct NR_UE_NR_Capability *get_ue_nr_capability(int rnti, uint8_t *buf, uint32_t len) +{ + if (!buf || len == 0) return NULL; + + NR_UE_CapabilityRAT_ContainerList_t *clist = NULL; + asn_dec_rval_t rval = uper_decode(NULL, &asn_DEF_NR_UE_CapabilityRAT_ContainerList, + (void **)&clist, buf, len, 0, 0); + + if (rval.code != RC_OK) { + LOG_W(NR_MAC, "UE RNTI %04x: Failed to decode container list\n", rnti); + return NULL; + } + + NR_UE_NR_Capability_t *cap = decode_nr_ue_capability(rnti, clist); + ASN_STRUCT_FREE(asn_DEF_NR_UE_CapabilityRAT_ContainerList, clist); + return cap; +} + +NR_UE_NR_Capability_t *decode_nr_ue_capability(int rnti, const NR_UE_CapabilityRAT_ContainerList_t *clist) +{ + if (!clist) return NULL; + + for (int i = 0; i < clist->list.count; i++) { + const NR_UE_CapabilityRAT_Container_t *c = clist->list.array[i]; + if (c->rat_Type != NR_RAT_Type_nr) + continue; + + NR_UE_NR_Capability_t *cap = NULL; + asn_dec_rval_t rval = uper_decode(NULL, &asn_DEF_NR_UE_NR_Capability, + (void **)&cap, + c->ue_CapabilityRAT_Container.buf, + c->ue_CapabilityRAT_Container.size, + 0, 0); + if (rval.code == RC_OK) + return cap; + + LOG_W(NR_MAC, "UE RNTI %04x: Failed to decode NR capability (%zu bytes)\n", rnti, rval.consumed); + ASN_STRUCT_FREE(asn_DEF_NR_UE_NR_Capability, cap); + } + return NULL; +} + //------------------------------------------------------------------------------ int do_SIB2_NR(uint8_t **msg_SIB2, NR_SSB_MTC_t *ssbmtc) diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.h b/openair2/RRC/NR/MESSAGES/asn1_msg.h index 665edeef4b..fb43237d2a 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.h +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.h @@ -51,6 +51,7 @@ #include "NR_SRB-ToAddModList.h" #include "NR_SecurityConfig.h" #include "NR_MeasurementTimingConfiguration.h" +#include "NR_UE-CapabilityRAT-ContainerList.h" #include "ds/seq_arr.h" #include "ds/byte_array.h" #include "rrc_messages_types.h" @@ -167,4 +168,7 @@ byte_array_t get_HandoverCommandMessage(nr_rrc_reconfig_param_t *params); void fill_removal_lists_from_source_measConfig(NR_MeasConfig_t *measConfig, byte_array_t prep_info); int doRRCReconfiguration_from_HandoverCommand(byte_array_t *ba, byte_array_t handoverCommand); +struct NR_UE_NR_Capability *get_ue_nr_capability(int rnti, uint8_t *buf, uint32_t len); +NR_UE_NR_Capability_t *decode_nr_ue_capability(int rnti, const NR_UE_CapabilityRAT_ContainerList_t *clist); + #endif /* __RRC_NR_MESSAGES_ASN1_MSG__H__ */ diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 32021d7f22..75a3296b8f 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -1607,21 +1607,14 @@ static void handle_ueCapabilityInformation(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, UE->UE_Capability_nr = 0; } - asn_dec_rval_t dec_rval = uper_decode(NULL, - &asn_DEF_NR_UE_NR_Capability, - (void **)&UE->UE_Capability_nr, - ue_cap_container->ue_CapabilityRAT_Container.buf, - ue_cap_container->ue_CapabilityRAT_Container.size, - 0, - 0); - if (LOG_DEBUGFLAG(DEBUG_ASN1)) { - xer_fprint(stdout, &asn_DEF_NR_UE_NR_Capability, UE->UE_Capability_nr); + UE->UE_Capability_nr = decode_nr_ue_capability(UE->rnti, ue_CapabilityRAT_ContainerList); + if (!UE->UE_Capability_nr) { + LOG_E(NR_RRC, "UE %d: NR capability decoding failed\n", UE->rrc_ue_id); + return; } - if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) { - LOG_E(NR_RRC, "UE %d: Failed to decode nr UE capabilities (%zu bytes)\n", UE->rrc_ue_id, dec_rval.consumed); - ASN_STRUCT_FREE(asn_DEF_NR_UE_NR_Capability, UE->UE_Capability_nr); - UE->UE_Capability_nr = 0; + if (LOG_DEBUGFLAG(DEBUG_ASN1)) { + xer_fprint(stdout, &asn_DEF_NR_UE_NR_Capability, UE->UE_Capability_nr); } const NR_RedCapParameters_r17_t *redcap_p = get_redcapparam_r17(UE->UE_Capability_nr); @@ -2557,6 +2550,13 @@ void rrc_gNB_process_e1_bearer_context_setup_resp(e1ap_bearer_setup_resp_t *resp } } + // If HO Preparation Info is stored, N2 handover is ongoing + if (UE->ho_context) { + LOG_I(NR_RRC, "Received Bearer Context Setup Response for UE %d with valid HO Context\n", UE->rrc_ue_id); + UE->ho_context->target->ho_trigger(rrc, UE); + return; + } + if (!UE->f1_ue_context_active) rrc_gNB_generate_UeContextSetupRequest(rrc, ue_context_p, resp); else diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index e7459b1d49..961191d171 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -1111,6 +1111,7 @@ int rrc_gNB_process_Handover_Request(gNB_RRC_INST *rrc, instance_t instance, nga return -1; } UE->ho_context = alloc_ho_ctx(HO_CTX_TARGET); + UE->ho_context->target->ho_trigger = nr_rrc_trigger_n2_ho_target; // Store IDs in UE context UE->amf_ue_ngap_id = msg->amf_ue_ngap_id; diff --git a/openair2/RRC/NR/rrc_gNB_mobility.c b/openair2/RRC/NR/rrc_gNB_mobility.c index 9e76217dc9..a2978e2d56 100644 --- a/openair2/RRC/NR/rrc_gNB_mobility.c +++ b/openair2/RRC/NR/rrc_gNB_mobility.c @@ -122,7 +122,8 @@ static void nr_initiate_handover(const gNB_RRC_INST *rrc, byte_array_t *ho_prep_info, ho_req_ack_t ack, ho_success_t success, - ho_cancel_t cancel) + ho_cancel_t cancel, + ho_failure_t failure) { DevAssert(rrc != NULL); DevAssert(ue != NULL); @@ -145,6 +146,7 @@ static void nr_initiate_handover(const gNB_RRC_INST *rrc, // response ho_ctx->target->ho_req_ack = ack; ho_ctx->target->ho_success = success; + ho_ctx->target->ho_failure = failure; const f1_ue_data_t ue_data = cu_get_f1_ue_data(ue->rrc_ue_id); if (source_du != NULL) { @@ -353,7 +355,7 @@ void nr_rrc_trigger_f1_ho(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue, nr_rrc_du_contain ho_success_t success = nr_rrc_f1_ho_complete; ho_cancel_t cancel = nr_rrc_cancel_f1_ho; byte_array_t hpi = {.buf = buf, .len = size}; - nr_initiate_handover(rrc, ue, source_du, target_du, &hpi, ack, success, cancel); + nr_initiate_handover(rrc, ue, source_du, target_du, &hpi, ack, success, cancel, NULL); } void nr_rrc_finalize_ho(gNB_RRC_UE_t *ue) @@ -496,6 +498,26 @@ void nr_rrc_n2_ho_failure(gNB_RRC_INST *rrc, uint32_t gnb_ue_id, ngap_handover_f return; } +/** @brief Trigger N2 Handover on the target gNB: + * 1) set up callbacks + * 2) initiate N2 handover on target NG-RAN, which triggers the set up + * of HO context and UE Context Setup procedures */ +void nr_rrc_trigger_n2_ho_target(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue) +{ + ho_req_ack_t ack = nr_rrc_n2_ho_acknowledge; + ho_success_t success = nr_rrc_n2_ho_complete; + ho_failure_t failure = nr_rrc_n2_ho_failure; + + const nr_rrc_du_container_t *target_du = get_du_for_ue(rrc, ue->rrc_ue_id); + nr_initiate_handover(rrc, ue, NULL, target_du, &ue->ho_context->target->ue_ho_prep_info, ack, success, NULL, failure); + FREE_AND_ZERO_BYTE_ARRAY(ue->ho_context->target->ue_ho_prep_info); + + NR_UE_NR_Capability_t *ue_cap = get_ue_nr_capability(ue->rnti, ue->ue_cap_buffer.buf, ue->ue_cap_buffer.len); + ue->UE_Capability_nr = ue_cap; + ue->UE_Capability_size = ue->ue_cap_buffer.len; + +} + /** @brief Trigger N2 handover on source gNB: * 1) Prepare RRC Container with HandoverPreparationInformation message * 2) send NGAP Handover Required message */ diff --git a/openair2/RRC/NR/rrc_gNB_mobility.h b/openair2/RRC/NR/rrc_gNB_mobility.h index 5a6542132c..db0645c5e3 100644 --- a/openair2/RRC/NR/rrc_gNB_mobility.h +++ b/openair2/RRC/NR/rrc_gNB_mobility.h @@ -54,6 +54,7 @@ typedef struct nr_ho_source_cu { typedef void (*ho_req_ack_t)(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue); typedef void (*ho_success_t)(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue); typedef void (*ho_failure_t)(gNB_RRC_INST *rrc, uint32_t gnb_ue_id, ngap_handover_failure_t *msg); +typedef void (*ho_trigger_t)(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue); typedef struct nr_ho_target_cu { /// pointer to the (target) DU structure @@ -66,10 +67,14 @@ typedef struct nr_ho_target_cu { rnti_t new_rnti; /// Handover Preparation Buffer byte_array_t ue_ho_prep_info; + /// function pointer to trigger handover on target gNB + ho_trigger_t ho_trigger; /// function pointer to announce handover request acknowledgment ho_req_ack_t ho_req_ack; /// function pointer to announce handover success ho_success_t ho_success; + /// function pointer to announce the handover failure + ho_failure_t ho_failure; } nr_ho_target_cu_t; typedef struct nr_handover_context_s { @@ -91,4 +96,6 @@ void nr_rrc_trigger_n2_ho(gNB_RRC_INST *rrc, void rrc_gNB_trigger_reconfiguration_for_handover(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue, uint8_t *rrc_reconf, int rrc_reconf_len); +void nr_rrc_trigger_n2_ho_target(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue); + #endif /* RRC_GNB_MOBILITY_H_ */ From 984c0bff0f079ce2665edeccb5ec99986801c6c9 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Mon, 1 Sep 2025 15:05:54 +0200 Subject: [PATCH 724/964] Send NG HO failure message upon nr_rrc_n2_ho_acknowledge failure --- openair2/RRC/NR/rrc_gNB_mobility.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openair2/RRC/NR/rrc_gNB_mobility.c b/openair2/RRC/NR/rrc_gNB_mobility.c index a2978e2d56..3c9bf2c17b 100644 --- a/openair2/RRC/NR/rrc_gNB_mobility.c +++ b/openair2/RRC/NR/rrc_gNB_mobility.c @@ -469,6 +469,10 @@ static void nr_rrc_n2_ho_acknowledge(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE) byte_array_t hoCommand = rrc_gNB_encode_HandoverCommand(UE, rrc); if (hoCommand.len < 0) { LOG_E(NR_RRC, "ASN1 message encoding failed: failed to generate Handover Command Message\n"); + ngap_handover_failure_t fail = {.amf_ue_ngap_id = UE->amf_ue_ngap_id, + .cause.type = NGAP_CAUSE_RADIO_NETWORK, + .cause.value = NGAP_CAUSE_RADIO_NETWORK_HO_FAILURE_IN_TARGET_5GC_NGRAN_NODE_OR_TARGET_SYSTEM}; + UE->ho_context->target->ho_failure(rrc, UE->rrc_ue_id, &fail); return; } else { LOG_D(NR_RRC, "HO LOG: Handover Command for UE %u Encoded (%ld bytes)\n", UE->rrc_ue_id, hoCommand.len); From cb68d817f0c77740c3969837cb74eb83087744ed Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 2 Apr 2025 16:37:33 +0200 Subject: [PATCH 725/964] OAI UE: introduce AS security key update procedure (5.3.5.7 3GPP TS 38.331) * trigger upon reception of MasterKeyUpdate * derive NH, store NH NCC and valid NH key in RRC * masterKeyUpdate: derive enc/int keys after master key update and set PDCP security for SRB1 * call nr_rrc_process_reconfiguration_v1530 before nr_rrc_ue_process_RadioBearerConfig and move dedicatedNAS_MessageList processing at the end of the flow. The sequence shall be (1) keys/security update (2) radioBearerConfig processing, with PDCP entity creation, PDCP reestablishment, SDAP entity creation (3) NAS PDUs processing, which triggers PDU Session Establishment Accept, which sets up the TUN interface. SDAP entity is a pre-requisite, therefore the radioBearerConfig has to be processed (in nr_rrc_ue_process_RadioBearerConfig, add_drb) early enough, or it may cause a race condition in SDAP. --- openair2/RRC/NR_UE/rrc_UE.c | 108 ++++++++++++++++++++++++++++------ openair2/RRC/NR_UE/rrc_defs.h | 4 ++ 2 files changed, 93 insertions(+), 19 deletions(-) diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 52d9ecb50a..b639df31d6 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -532,19 +532,74 @@ static void nr_rrc_process_sib1(NR_UE_RRC_INST_t *rrc, NR_UE_RRC_SI_INFO *SI_inf nr_rrc_send_msg_to_mac(rrc, &rrc_msg); } -static void nr_rrc_process_reconfiguration_v1530(NR_UE_RRC_INST_t *rrc, NR_RRCReconfiguration_v1530_IEs_t *rec_1530, int gNB_index) +static void nr_rrc_nh_update(NR_UE_RRC_INST_t *rrc, uint8_t *kamf, uint8_t *sync_input) { - if (rec_1530->fullConfig) { - // TODO perform the full configuration procedure as specified in 5.3.5.11 of 331 - LOG_E(NR_RRC, "RRCReconfiguration includes fullConfig but this is not implemented yet\n"); + uint8_t nh[SECURITY_KEY_LEN] = {0}; + nr_derive_nh(kamf, sync_input, nh); + log_hex_buffer("Sync input = stored NH", rrc->nh, SECURITY_KEY_LEN); + memcpy(rrc->nh, nh, SECURITY_KEY_LEN); + rrc->nhcc++; // Increase stored nextHopChainingCount +} + +/** @brief AS security key update procedure (5.3.5.7 3GPP TS 38.331) */ +void as_security_key_update(NR_UE_RRC_INST_t *rrc, NR_MasterKeyUpdate_t *mku) +{ + if (mku->nas_Container) { + LOG_E(NR_RRC, "forward the nas-Container to the upper layers: not implemented yet\n"); } - if (rec_1530->masterCellGroup) - 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"); + if (mku->keySetChangeIndicator) { + LOG_E(NR_RRC, "derive or update the K gNB key based on the K AMF key, as specified in TS 33.501: not implemented yet\n"); + } else { + /* derive or update the K gNB key based on the current K gNB key or the NH, using the nextHopChainingCount + value indicated in the received masterKeyUpdate, as specified in 6.9.2.3.3 3GPP TS 33.501 */ + if (mku->nextHopChainingCount != rrc->nhcc) { + // - If the UE received an NCC value that was different from the NCC associated with the currently active + // K gNB/K eNB, the UE shall first synchronize the locally kept NH parameter by computing the function defined in + // Annex A.10 iteratively (and increasing the NCC value until it matches the NCC value received from the source + // ng-eNB/gNB via the HO command message. + LOG_A(NR_RRC, "Received masterKeyUpdate (nextHopChainingCount %ld): update security keys\n", mku->nextHopChainingCount); + /** @todo: The KAMF should be obtained from NAS. This exchange over ITTI must be synchronized + * with the rest of the RRCReconfiguration procedure, in particular, the RadioBearerConfig + * processing that triggers bearer modifications. Security configueration of bearers must + * complete using the newly derived keys. As a workaround NAS is directly accessed here. */ + nr_ue_nas_t *nas = get_ue_nas_info(rrc->ue_id); + uint8_t *kamf = nas->security.kamf; + log_hex_buffer("Stored kamf", kamf, SECURITY_KEY_LEN); + if (rrc->nhcc == 0) { // First derivation + derive_kgnb(kamf, 0, rrc->kgnb); + log_hex_buffer("Sync input = derived kgnb", rrc->kgnb, SECURITY_KEY_LEN); + nr_rrc_nh_update(rrc, kamf, rrc->kgnb); + } + for (int i = rrc->nhcc; i < mku->nextHopChainingCount; i++) { // Following derivations + LOG_D(NR_RRC, "Derive keys for ChainingCount = %d\n", i); + nr_rrc_nh_update(rrc, kamf, rrc->nh); + } + nr_derive_key_ng_ran_star(rrc->phyCellID, rrc->arfcn_ssb, rrc->nh, rrc->kgnb); + // When the NCC values match, the UE shall compute the K NG-RAN * + // from the synchronized NH parameter and the target PCI and its frequency ARFCN-DL/EARFCN-DL using the + // function defined in Annex A.11 and A.12. + // The UE shall use the KNG-RAN * as the K gNB when communicating with the target gNB and as the KeNB when + // communicating with the target ng-eNB. + } else { + nr_derive_key_ng_ran_star(rrc->phyCellID, rrc->arfcn_ssb, rrc->kgnb, rrc->kgnb); + } + log_hex_buffer("Derived kgnb", rrc->kgnb, SECURITY_KEY_LEN); } - /* Check if there is dedicated NAS information to forward to NAS */ +} + +static nr_pdcp_entity_security_keys_and_algos_t get_security_rrc_parameters(NR_UE_RRC_INST_t *ue, bool cp) +{ + nr_pdcp_entity_security_keys_and_algos_t out = {0}; + out.ciphering_algorithm = ue->cipheringAlgorithm; + out.integrity_algorithm = ue->integrityProtAlgorithm; + nr_derive_key(cp ? RRC_ENC_ALG : UP_ENC_ALG, ue->cipheringAlgorithm, ue->kgnb, out.ciphering_key); + nr_derive_key(cp ? RRC_INT_ALG : UP_INT_ALG, ue->integrityProtAlgorithm, ue->kgnb, out.integrity_key); + return out; +} + +/** @brief Check if there is dedicated NAS information to forward to NAS */ +static void nr_rrc_process_dedicatedNAS_MessageList(NR_UE_RRC_INST_t *rrc, NR_RRCReconfiguration_v1530_IEs_t *rec_1530) +{ if (rec_1530->dedicatedNAS_MessageList) { struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList *tmp = rec_1530->dedicatedNAS_MessageList; for (int i = 0; i < tmp->list.count; i++) { @@ -557,6 +612,21 @@ static void nr_rrc_process_reconfiguration_v1530(NR_UE_RRC_INST_t *rrc, NR_RRCRe } tmp->list.count = 0; // to prevent the automatic free by ASN1_FREE } +} + +static void nr_rrc_process_reconfiguration_v1530(NR_UE_RRC_INST_t *rrc, NR_RRCReconfiguration_v1530_IEs_t *rec_1530, int gNB_index) +{ + if (rec_1530->fullConfig) { + // TODO perform the full configuration procedure as specified in 5.3.5.11 of 331 + 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, gNB_index); + if (rec_1530->masterKeyUpdate) { + as_security_key_update(rrc, rec_1530->masterKeyUpdate); + nr_pdcp_entity_security_keys_and_algos_t sp = get_security_rrc_parameters(rrc, true); + nr_pdcp_config_set_security(rrc->ue_id, 1, true, &sp); + } NR_UE_RRC_SI_INFO *SI_info = &rrc->perNB[gNB_index].SInfo; if (rec_1530->dedicatedSIB1_Delivery) { NR_SIB1_t *sib1 = NULL; @@ -633,6 +703,9 @@ static void nr_rrc_ue_process_rrcReconfiguration(NR_UE_RRC_INST_t *rrc, int gNB_ case NR_RRCReconfiguration__criticalExtensions_PR_rrcReconfiguration: { NR_RRCReconfiguration_IEs_t *ie = reconfiguration->criticalExtensions.choice.rrcReconfiguration; + if (ie->nonCriticalExtension) + nr_rrc_process_reconfiguration_v1530(rrc, ie->nonCriticalExtension, gNB_index); + if (ie->radioBearerConfig) { LOG_I(NR_RRC, "RRCReconfiguration includes radio Bearer Configuration\n"); nr_rrc_ue_process_RadioBearerConfig(rrc, ie->radioBearerConfig); @@ -640,8 +713,11 @@ static void nr_rrc_ue_process_rrcReconfiguration(NR_UE_RRC_INST_t *rrc, int gNB_ xer_fprint(stdout, &asn_DEF_NR_RadioBearerConfig, (const void *)ie->radioBearerConfig); } + /** @note This triggers PDU Session Establishment Accept which sets up the TUN interface. + * SDAP entity is a pre-requisite, therefore the radioBearerConfig has to be processed + * (in nr_rrc_ue_process_RadioBearerConfig, add_drb) early enough, or it may cause a race condition in SDAP. */ if (ie->nonCriticalExtension) - nr_rrc_process_reconfiguration_v1530(rrc, ie->nonCriticalExtension, gNB_index); + nr_rrc_process_dedicatedNAS_MessageList(rrc, ie->nonCriticalExtension); if (ie->secondaryCellGroup) { NR_CellGroupConfig_t *cellGroupConfig = NULL; @@ -1940,14 +2016,8 @@ static void nr_rrc_ue_process_RadioBearerConfig(NR_UE_RRC_INST_t *ue_rrc, ue_rrc->integrityProtAlgorithm = *radioBearerConfig->securityConfig->securityAlgorithmConfig->integrityProtAlgorithm; } } - security_rrc_parameters.ciphering_algorithm = ue_rrc->cipheringAlgorithm; - security_rrc_parameters.integrity_algorithm = ue_rrc->integrityProtAlgorithm; - nr_derive_key(RRC_ENC_ALG, ue_rrc->cipheringAlgorithm, ue_rrc->kgnb, security_rrc_parameters.ciphering_key); - nr_derive_key(RRC_INT_ALG, ue_rrc->integrityProtAlgorithm, ue_rrc->kgnb, security_rrc_parameters.integrity_key); - security_up_parameters.ciphering_algorithm = ue_rrc->cipheringAlgorithm; - security_up_parameters.integrity_algorithm = ue_rrc->integrityProtAlgorithm; - nr_derive_key(UP_ENC_ALG, ue_rrc->cipheringAlgorithm, ue_rrc->kgnb, security_up_parameters.ciphering_key); - nr_derive_key(UP_INT_ALG, ue_rrc->integrityProtAlgorithm, ue_rrc->kgnb, security_up_parameters.integrity_key); + security_rrc_parameters = get_security_rrc_parameters(ue_rrc, true); + security_up_parameters = get_security_rrc_parameters(ue_rrc, false); } if (radioBearerConfig->srb_ToAddModList != NULL) { diff --git a/openair2/RRC/NR_UE/rrc_defs.h b/openair2/RRC/NR_UE/rrc_defs.h index bc645f7cc1..b745b5f1db 100644 --- a/openair2/RRC/NR_UE/rrc_defs.h +++ b/openair2/RRC/NR_UE/rrc_defs.h @@ -233,6 +233,10 @@ typedef struct NR_UE_RRC_INST_s { e_NR_IntegrityProtAlgorithm integrityProtAlgorithm; long keyToUse; bool as_security_activated; + /// Next Hop Chaining Count + uint8_t nh[32]; + uint64_t nhcc; + bool detach_after_release; NR_timer_t release_timer; NR_RRCRelease_t *RRCRelease; From 5227becf89349bf8aa5dedb0c0a9e4c995c4be48 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Thu, 12 Jun 2025 21:58:37 +0200 Subject: [PATCH 726/964] Add telnet trigger for N2 handover * the command gets in input the neighbour PCI and the UE ID * the telnet ci function to retrieve the UE context was extended in the process * add function to trigger handover on the same gNB for testing purposes Co-authored-by: batuhan duyuler --- common/utils/telnetsrv/telnetsrv_ci.c | 49 +++++++++++++++++++++++++++ openair2/RRC/NR/rrc_gNB_mobility.c | 49 +++++++++++++++++++++++++++ 2 files changed, 98 insertions(+) diff --git a/common/utils/telnetsrv/telnetsrv_ci.c b/common/utils/telnetsrv/telnetsrv_ci.c index 24dba02191..291f1f37a2 100644 --- a/common/utils/telnetsrv/telnetsrv_ci.c +++ b/common/utils/telnetsrv/telnetsrv_ci.c @@ -38,6 +38,7 @@ #include "openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.h" #include "openair2/LAYER2/nr_rlc/nr_rlc_entity_am.h" #include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h" +#include "openair2/RRC/NR/rrc_gNB_mobility.h" #define TELNETSERVERCODE #include "telnetsrv.h" @@ -196,6 +197,53 @@ int rrc_gNB_trigger_f1_ho(char *buf, int debug, telnet_printfunc_t prnt) return 0; } +extern void nr_HO_N2_trigger_telnet(gNB_RRC_INST *rrc, uint32_t neighbour_pci, uint32_t rrc_ue_id); + +/** @brief Trigger N2 handover for UE + * @param buf: Neighbour PCI, SCell PCI, RRC UE ID + * @param debug: Debug flag + * @param prnt: Print function + * @return 0 on success, -1 on failure */ +int rrc_gNB_trigger_n2_ho(char *buf, int debug, telnet_printfunc_t prnt) +{ + if (!RC.nrrrc) + ERROR_MSG_RET("no RRC present, cannot list counts\n"); + + if (!buf) { + ERROR_MSG_RET("Please provide neighbour cell id and ue id\n"); + } else { + // Parse neighbour cell PCI + char *token = strtok(buf, ","); + if (!token) { + ERROR_MSG_RET("Invalid input. Expected format: Neighbour PCI, ueId\n"); + } + uint32_t neighbour_pci = strtol(token, NULL, 10); + + // Parse ueId + token = strtok(NULL, ","); + if (!token) { + ERROR_MSG_RET("Missing UE ID\n"); + } + uint32_t ueId = strtol(token, NULL, 10); + + // Retrieve UE context + rrc_gNB_ue_context_t *ue_p = rrc_gNB_get_ue_context(RC.nrrrc[0], ueId); + if (!ue_p) { + ERROR_MSG_RET("UE with id %u not found\n", ueId); + } + gNB_RRC_UE_t *UE = &ue_p->ue_context; + + // Trigger N2 handover + nr_HO_N2_trigger_telnet(RC.nrrrc[0], neighbour_pci, UE->rrc_ue_id); + + // Print success message + prnt("RRC N2 handover triggered for UE %u with neighbour cell id %u\n", + ueId, + neighbour_pci); + } + return 0; +} + int force_ul_failure(char *buf, int debug, telnet_printfunc_t prnt) { if (!RC.nrmac) @@ -245,6 +293,7 @@ static telnetshell_cmddef_t cicmds[] = { {"trigger_f1_ho", "[rrc_ue_id(int,opt)]", rrc_gNB_trigger_f1_ho}, {"fetch_du_by_ue_id", "[rrc_ue_id(int,opt)]", fetch_du_by_ue_id}, {"get_current_bwp", "[rnti(hex,opt)]", get_current_bwp}, + {"trigger_n2_ho", "[neighbour_pci(uint32_t),ueId(uint32_t)]", rrc_gNB_trigger_n2_ho}, {"", "", NULL}, }; diff --git a/openair2/RRC/NR/rrc_gNB_mobility.c b/openair2/RRC/NR/rrc_gNB_mobility.c index 3c9bf2c17b..42214ecc55 100644 --- a/openair2/RRC/NR/rrc_gNB_mobility.c +++ b/openair2/RRC/NR/rrc_gNB_mobility.c @@ -549,3 +549,52 @@ void nr_rrc_trigger_n2_ho(gNB_RRC_INST *rrc, rrc_gNB_send_NGAP_HANDOVER_REQUIRED(rrc, ue, neighbour_config, hoPrepInfo); free_byte_array(hoPrepInfo); } + +extern const nr_neighbour_cell_t *get_neighbour_cell_by_pci(const neighbour_cell_configuration_t *cell, int pci); +extern const neighbour_cell_configuration_t *get_neighbour_cell_config(const gNB_RRC_INST *rrc, int cell_id); + +void nr_HO_N2_trigger_telnet(gNB_RRC_INST *rrc, uint32_t neighbour_pci, uint32_t rrc_ue_id) +{ + rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(rrc, rrc_ue_id); + if (ue_context_p == NULL) { + LOG_E(NR_RRC, "N2 HO trigger failed for UE %d: cannot find UE context\n", rrc_ue_id); + return; + } + gNB_RRC_UE_t *UE = &ue_context_p->ue_context; + + struct nr_rrc_du_container_t *du = get_du_for_ue(rrc, rrc_ue_id); + if (du == NULL) { + LOG_E(NR_RRC, "N2 HO trigger failed for UE %d: Unknown DU\n", rrc_ue_id); + return; + } + uint16_t scell_pci = du->setup_req->cell[0].info.nr_pci; + + // Simulate handover on the same cell (testing purposes) + if (neighbour_pci == scell_pci) { + LOG_I(NR_RRC, "UE %d: trigger handover on the same cell PCI=%d\n", rrc_ue_id, neighbour_pci); + nr_neighbour_cell_t neighbourConfig = { + .isIntraFrequencyNeighbour = true, + .gNB_ID = du->setup_req->gNB_DU_id, + .nrcell_id = du->setup_req->cell[0].info.nr_cellid, + .physicalCellId = du->setup_req->cell[0].info.nr_pci, + .plmn = du->setup_req->cell[0].info.plmn, + .subcarrierSpacing = du->setup_req->cell[0].info.tdd.tbw.scs, + }; + nr_rrc_trigger_n2_ho(rrc, UE, neighbour_pci, &neighbourConfig); + return; + } + + const f1ap_served_cell_info_t *scell_du = get_cell_information_by_phycellId(scell_pci); + DevAssert(scell_du); + LOG_I(NR_RRC, "UE %d: triggered N2 HO, source PCI=%d to target PCI=%d\n", rrc_ue_id, scell_pci, neighbour_pci); + + const neighbour_cell_configuration_t *cell = get_neighbour_cell_config(rrc, scell_du->nr_cellid); + const nr_neighbour_cell_t *neighbour = get_neighbour_cell_by_pci(cell, neighbour_pci); + + if (neighbour == NULL) { + LOG_E(NR_RRC, "N2 HO trigger failed for UE %d: could not find neighbour cell with PCI=%d\n", rrc_ue_id, neighbour_pci); + return; + } + + nr_rrc_trigger_n2_ho(rrc, UE, scell_du->nr_pci, neighbour); +} From 1015c1f5f0350500173bbe1e9741817544fa8ed7 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 20 Aug 2025 23:41:34 +0200 Subject: [PATCH 727/964] Add new CI pipeline for N2 Handover The pipeline is using the already existing conf files for the source/target gNB CUs/DUs. For the sake of simplicity, neighbour-config.conf has been rewritten and simplified in this commit, then adopted in this pipeline. The file was not used before. --- .../conf_files/gnb-cu.sa.band78.106prb.conf | 2 +- .../conf_files/gnb-cucp.sa.e1-ho-n2.conf | 82 +++++ ci-scripts/conf_files/neighbour-config.conf | 68 ++-- .../xml_files/container_5g_rfsim_n2_ho.xml | 207 ++++++++++++ .../5g_f1_rfsimulator/docker-compose.yaml | 1 + .../5g_rfsimulator_n2_ho/docker-compose.yaml | 308 ++++++++++++++++++ 6 files changed, 630 insertions(+), 38 deletions(-) create mode 100644 ci-scripts/conf_files/gnb-cucp.sa.e1-ho-n2.conf create mode 100644 ci-scripts/xml_files/container_5g_rfsim_n2_ho.xml create mode 100644 ci-scripts/yaml_files/5g_rfsimulator_n2_ho/docker-compose.yaml diff --git a/ci-scripts/conf_files/gnb-cu.sa.band78.106prb.conf b/ci-scripts/conf_files/gnb-cu.sa.band78.106prb.conf index 051ebd04fc..4294f920ad 100644 --- a/ci-scripts/conf_files/gnb-cu.sa.band78.106prb.conf +++ b/ci-scripts/conf_files/gnb-cu.sa.band78.106prb.conf @@ -15,7 +15,7 @@ gNBs = // Tracking area code, 0x0000 and 0xfffe are reserved values tracking_area_code = 1; plmn_list = ({ mcc = 208; mnc = 99; mnc_length = 2; snssaiList = ({ sst = 1, sd = 0xffffff }) }); - + @include "neighbour-config.conf" nr_cellid = 12345678L; diff --git a/ci-scripts/conf_files/gnb-cucp.sa.e1-ho-n2.conf b/ci-scripts/conf_files/gnb-cucp.sa.e1-ho-n2.conf new file mode 100644 index 0000000000..ad4cca969e --- /dev/null +++ b/ci-scripts/conf_files/gnb-cucp.sa.e1-ho-n2.conf @@ -0,0 +1,82 @@ +Active_gNBs = ( "cu-cp-0"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + +# cell_type = "CELL_MACRO_GNB"; + + gNB_name = "cu-cp-0"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + plmn_list = ({ mcc = 208; mnc = 99; mnc_length = 2; snssaiList = ({ sst = 1, sd = 0xffffff }) }); + @include "neighbour-config.conf" + + nr_cellid = 12345678L; + + tr_s_preference = "f1"; + + local_s_address = "192.168.71.150"; + remote_s_address = "192.168.71.171"; + local_s_portd = 2153; + remote_s_portd = 2153; + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// AMF parameters: + amf_ip_address = ({ ipv4 = "192.168.71.132"; }); + + E1_INTERFACE = + ( + { + type = "cp"; + ipv4_cucp = "192.168.71.150"; + port_cucp = 38462; + ipv4_cuup = "0.0.0.0"; # multiple CU-UPs + port_cuup = 38462; + } + ) + + NETWORK_INTERFACES : + { + GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.71.150"; + }; + } +); + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + +log_config : { + global_log_level = "info"; + pdcp_log_level = "info"; + rrc_log_level = "info"; + f1ap_log_level = "info"; + ngap_log_level = "info"; +}; diff --git a/ci-scripts/conf_files/neighbour-config.conf b/ci-scripts/conf_files/neighbour-config.conf index 875129365e..4d4cd8136c 100644 --- a/ci-scripts/conf_files/neighbour-config.conf +++ b/ci-scripts/conf_files/neighbour-config.conf @@ -1,52 +1,46 @@ neighbour_list = ( + ########################################################## + # Entry USED BY gNB_ID = 0xe00 (nr_cellid = 1) # + ########################################################## { - nr_cellid = 1; + nr_cellid = 0; # Serving cell of gNB 0xe00 neighbour_cell_configuration = ( { - gNB_ID = 0xb00; - nr_cellid = 2; - physical_cellId = 0x002; - absoluteFrequencySSB = 641280 ; - subcarrierSpacing = 1; #30 KHz - plmn = { mcc = 216; mnc = 03; mnc_length = 2}; - tracking_area_code = 2; - }, - { - gNB_ID = 0xa00; - nr_cellid = 3; - physical_cellId = 0x003; - absoluteFrequencySSB = 641280 ; - subcarrierSpacing = 1; #30 KHz - plmn = { mcc = 999; mnc = 99; mnc_length = 2}; - tracking_area_code = 3; - }, - { - gNB_ID = 0xc00; - nr_cellid = 4; - physical_cellId = 0x004; - absoluteFrequencySSB = 641280 ; - subcarrierSpacing = 1; #30 KHz - plmn = { mcc = 999; mnc = 99; mnc_length = 2}; - tracking_area_code = 4; + gNB_ID = 0xb00; + nr_cellid = 1; # Cell served by gNB 0xb00 + physical_cellId = 1; + absoluteFrequencySSB= 621312; + subcarrierSpacing = 1; # 30 kHz + band = 78; + plmn = { mcc = 208; mnc = 99; mnc_length = 2 }; + tracking_area_code = 1; } - ) + ); }, + + ########################################################## + # Entry USED BY gNB_ID = 0xb00 (nr_cellid = 2) # + ########################################################## { - nr_cellid = 2; + nr_cellid = 1; # Serving cell of gNB 0xb00 neighbour_cell_configuration = ( { - gNB_ID = 0xe00; - nr_cellid = 1; - physical_cellId = 0x000; - absoluteFrequencySSB = 641280 ; - subcarrierSpacing = 1; #30 KHz - plmn = { mcc = 001; mnc = 01; mnc_length = 2}; - tracking_area_code = 1; + gNB_ID = 0xe00; + nr_cellid = 0; # Cell served by gNB 0xe00 + physical_cellId = 0; + absoluteFrequencySSB= 641280; + subcarrierSpacing = 1; # 30 kHz + band = 78; + plmn = { mcc = 208; mnc = 99; mnc_length = 2 }; + tracking_area_code = 1; } - ) + ); } - ); +); +############################################################ +# Common NR measurement-event configuration # +############################################################ nr_measurement_configuration = { Periodical = { diff --git a/ci-scripts/xml_files/container_5g_rfsim_n2_ho.xml b/ci-scripts/xml_files/container_5g_rfsim_n2_ho.xml new file mode 100644 index 0000000000..1b2e84046c --- /dev/null +++ b/ci-scripts/xml_files/container_5g_rfsim_n2_ho.xml @@ -0,0 +1,207 @@ + + + rfsim-5gnr-f1-n2-ho + F1 SA TDD N2 Handover + wrench + + 111111 + 800813 + 000001 + 000002 + 000003 + 020001 + 020002 + 030001 + 030002 + 000004 + 040001 + 050001 + 020001 + 020002 + 050002 + 030001 + 030002 + 050003 + 020001 + 020002 + 050004 + 050001 + 020001 + 020002 + 050002 + 100001 + 222222 + + + + + Pull_Local_Registry + Pull Images from Local Registry + 0 + oai-gnb-asan oai-nr-cuup-asan oai-nr-ue-asan + + + + Create_Workspace + Create new Workspace + 0 + 0 + + + + Deploy_Object + Deploy OAI 5G CoreNetwork + ci-scripts/yaml_files/5g_rfsimulator_n2_ho + mysql oai-amf oai-smf oai-upf oai-ext-dn + 0 + 0 + + + + Deploy_Object + Deploy OAI 5G CU-CP/CU-UP/DU 0 + UE RFsim SA + ci-scripts/yaml_files/5g_rfsimulator_n2_ho + oai-cucp-0 oai-cuup-0 oai-du-0 oai-nr-ue + 0 + 0 + + + + Attach_UE + Attach OAI UE (Wait for IP) + rfsim5g_ue + acamas + + + + Deploy_Object + Deploy OAI 5G CU-CP/CU-UP/DU 1 RFsim SA + ci-scripts/yaml_files/5g_rfsimulator_n2_ho + oai-cucp-1 oai-cuup-1 oai-du-1 + 0 + 0 + + + + Ping + Ping NR-UE from ext-dn + rfsim5g_ext_dn + acamas + rfsim5g_ue + acamas + -c 100 -i 0.25 + 5 + + + + Ping + Ping ext-dn from NR-UE + rfsim5g_ue + acamas + rfsim5g_ext_dn + acamas + -c 100 -i 0.25 + 10 + + + + Iperf + Iperf (DL/10Mbps/UDP)(30 sec) + -u -b 3M -t 20 -R + rfsim5g_ue + acamas + rfsim5g_ext_dn + acamas + 5 + 90 + + + + Iperf + Iperf (UL/4Mbps/UDP)(30 sec) + -u -b 1M -t 20 + rfsim5g_ue + acamas + rfsim5g_ext_dn + acamas + 5 + 90 + + + + IdleSleep + Sleep + 5 + + + + Custom_Command + Trigger N2 Handover + acamas + echo ci trigger_n2_ho 1,1 | ncat 192.168.71.150 9090 + yes + + + + Custom_Command + UE (1) connected to DU-PCI 1? + acamas + echo ci fetch_du_by_ue_id 1 | ncat 192.168.71.180 9090 | grep "1234" + + + + Custom_Command + Trigger N2 Handover + acamas + echo ci trigger_n2_ho 0,1 | ncat 192.168.71.180 9090 + yes + + + + Custom_Command + UE (1) connected to DU-PCI 0? + acamas + echo ci fetch_du_by_ue_id 1 | ncat 192.168.71.150 9090 | grep "3584" + + + + Undeploy_Object + true + Undeploy all OAI 5G stack + ci-scripts/yaml_files/5g_rfsimulator_n2_ho + 0 + 0 + 10,100,100,100 + 10,100,100,100 + + + + Clean_Test_Server_Images + true + Clean Test Images on Test Server + 0 + oai-gnb-asan oai-nr-cuup-asan oai-nr-ue-asan + + + diff --git a/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml b/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml index 18313d0559..e5061ff679 100644 --- a/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml @@ -111,6 +111,7 @@ services: public_net: ipv4_address: 192.168.71.150 volumes: + - ../../conf_files/neighbour-config.conf:/opt/oai-gnb/etc/neighbour-config.conf - ../../conf_files/gnb-cu.sa.band78.106prb.conf:/opt/oai-gnb/etc/gnb.conf healthcheck: test: /bin/bash -c "pgrep nr-softmodem" diff --git a/ci-scripts/yaml_files/5g_rfsimulator_n2_ho/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_n2_ho/docker-compose.yaml new file mode 100644 index 0000000000..1149d4f156 --- /dev/null +++ b/ci-scripts/yaml_files/5g_rfsimulator_n2_ho/docker-compose.yaml @@ -0,0 +1,308 @@ +services: + mysql: + container_name: "rfsim5g-mysql" + image: mysql:8.0 + volumes: + - ../5g_rfsimulator/oai_db.sql:/docker-entrypoint-initdb.d/oai_db.sql + - ../5g_rfsimulator/mysql-healthcheck.sh:/tmp/mysql-healthcheck.sh + environment: + - TZ=Europe/Paris + - MYSQL_DATABASE=oai_db + - MYSQL_USER=test + - MYSQL_PASSWORD=test + - MYSQL_ROOT_PASSWORD=linux + healthcheck: + test: /bin/bash -c "/tmp/mysql-healthcheck.sh" + interval: 10s + timeout: 5s + retries: 30 + networks: + public_net: + ipv4_address: 192.168.71.131 + oai-amf: + container_name: "rfsim5g-oai-amf" + image: oaisoftwarealliance/oai-amf:ci-tmp-pr-372-26c14bcd + environment: + - TZ=Europe/paris + volumes: + - ../5g_rfsimulator/mini_nonrf_config.yaml:/openair-amf/etc/config.yaml + depends_on: + - mysql + networks: + public_net: + ipv4_address: 192.168.71.132 + oai-smf: + container_name: "rfsim5g-oai-smf" + image: oaisoftwarealliance/oai-smf:v2.1.9 + environment: + - TZ=Europe/Paris + volumes: + - ../5g_rfsimulator/mini_nonrf_config.yaml:/openair-smf/etc/config.yaml + depends_on: + - oai-amf + networks: + public_net: + ipv4_address: 192.168.71.133 + oai-upf: + container_name: "rfsim5g-oai-upf" + image: oaisoftwarealliance/oai-upf:v2.1.9 + environment: + - TZ=Europe/Paris + volumes: + - ../5g_rfsimulator/mini_nonrf_config.yaml:/openair-upf/etc/config.yaml + depends_on: + - oai-smf + cap_add: + - NET_ADMIN + - SYS_ADMIN + cap_drop: + - ALL + privileged: true + networks: + public_net: + ipv4_address: 192.168.71.134 + interface_name: eth0 + traffic_net: + ipv4_address: 192.168.72.134 + interface_name: eth1 + oai-ext-dn: + privileged: true + container_name: rfsim5g-oai-ext-dn + image: oaisoftwarealliance/trf-gen-cn5g:focal + entrypoint: /bin/bash -c \ + "iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE;"\ + "ip route add 12.1.1.0/24 via 192.168.72.134 dev eth0; sleep infinity" + depends_on: + - oai-upf + networks: + traffic_net: + ipv4_address: 192.168.72.135 + healthcheck: + test: /bin/bash -c "ping -c 2 192.168.72.134" + interval: 10s + timeout: 5s + retries: 5 + + oai-cucp-0: + image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop} + container_name: rfsim5g-oai-cucp-0 + cap_drop: + - ALL + environment: + USE_ADDITIONAL_OPTIONS: --rfsim --rfsimulator.serveraddr 192.168.71.190 + --telnetsrv --telnetsrv.shrmod ci + --telnetsrv.listenaddr 192.168.71.150 + --gNBs.[0].nr_cellid 0 + --log_config.global_log_options level,nocolor,time + ASAN_OPTIONS: detect_leaks=0:detect_odr_violation=0 + depends_on: + - oai-amf + networks: + public_net: + ipv4_address: 192.168.71.150 + volumes: + - ../../conf_files/neighbour-config.conf:/opt/oai-gnb/etc/neighbour-config.conf + - ../../conf_files/gnb-cucp.sa.e1-ho-n2.conf:/opt/oai-gnb/etc/gnb.conf + healthcheck: + test: /bin/bash -c "pgrep nr-softmodem" + start_period: 10s + start_interval: 500ms + interval: 10s + timeout: 5s + retries: 5 + + oai-cuup-0: + image: ${REGISTRY:-oaisoftwarealliance}/${NRCUUP_IMG:-oai-nr-cuup}:${TAG:-develop} + container_name: rfsim5g-oai-cuup-0 + cap_drop: + - ALL + environment: + USE_ADDITIONAL_OPTIONS: --log_config.global_log_options level,nocolor,time + --gNBs.[0].E1_INTERFACE.[0].ipv4_cucp 192.168.71.150 + --gNBs.[0].E1_INTERFACE.[0].ipv4_cuup 192.168.71.151 + --gNBs.[0].NETWORK_INTERFACES.GNB_IPV4_ADDRESS_FOR_NGU 192.168.71.151 + --gNBs.[0].local_s_address 192.168.71.151 + ASAN_OPTIONS: detect_leaks=0 + depends_on: + - oai-cucp-0 + networks: + public_net: + ipv4_address: 192.168.71.151 + volumes: + - ../../conf_files/gnb-cuup.sa.f1.conf:/opt/oai-gnb/etc/gnb.conf + healthcheck: + test: /bin/bash -c "pgrep nr-cuup" + start_period: 10s + start_interval: 500ms + interval: 10s + timeout: 5s + retries: 5 + + + oai-du-0: + image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop} + container_name: rfsim5g-oai-du-0 + cap_drop: + - ALL + environment: + USE_ADDITIONAL_OPTIONS: --rfsim + --log_config.global_log_options level,nocolor,time + --gNBs.[0].nr_cellid 0 + --telnetsrv --telnetsrv.listenaddr 192.168.71.171 + --telnetsrv.shrmod ci + --rfsimulator.serveraddr 192.168.71.190 + --gNBs.[0].servingCellConfigCommon.[0].ra_ResponseWindow 5 + ASAN_OPTIONS: detect_leaks=0:detect_odr_violation=0 + depends_on: + - oai-cucp-0 + networks: + public_net: + ipv4_address: 192.168.71.171 + volumes: + - ../../conf_files/neighbour-config.conf:/opt/oai-gnb/etc/neighbour-config.conf + - ../../conf_files/gnb-du.sa.band78.106prb.rfsim.conf:/opt/oai-gnb/etc/gnb.conf + healthcheck: + test: /bin/bash -c "pgrep nr-softmodem" + start_period: 10s + start_interval: 500ms + interval: 10s + timeout: 5s + retries: 5 + + oai-nr-ue: + image: ${REGISTRY:-oaisoftwarealliance}/${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} + container_name: rfsim5g-oai-nr-ue + cap_drop: + - ALL + cap_add: + - NET_ADMIN # for interface bringup + - NET_RAW # for ping + environment: + USE_ADDITIONAL_OPTIONS: --rfsim --rfsimulator.serveraddr server + --band 78 -C 3619200000 -r 106 --numerology 1 --ssb 516 + --uicc0.imsi 208990100001100 + --log_config.global_log_options level,nocolor,time + networks: + public_net: + ipv4_address: 192.168.71.190 + devices: + - /dev/net/tun:/dev/net/tun + volumes: + - ../../conf_files/nrue.uicc.conf:/opt/oai-nr-ue/etc/nr-ue.conf + healthcheck: + test: /bin/bash -c "pgrep nr-uesoftmodem" + interval: 10s + timeout: 5s + retries: 5 + + oai-cucp-1: + image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop} + container_name: rfsim5g-oai-cucp-1 + cap_drop: + - ALL + environment: + USE_ADDITIONAL_OPTIONS: --rfsim --rfsimulator.serveraddr 192.168.71.190 + --telnetsrv --telnetsrv.shrmod ci + --telnetsrv.listenaddr 192.168.71.180 + --gNBs.[0].E1_INTERFACE.[0].ipv4_cucp 192.168.71.180 + --gNBs.[0].E1_INTERFACE.[0].ipv4_cuup 192.168.71.181 + --gNBs.[0].local_s_address 192.168.71.180 + --gNBs.[0].remote_s_address 192.168.71.181 + --gNBs.[0].gNB_ID 0xb00 + --gNBs.[0].nr_cellid 1 + --gNBs.[0].NETWORK_INTERFACES.GNB_IPV4_ADDRESS_FOR_NG_AMF 192.168.71.180 + --gNBs.[0].NETWORK_INTERFACES.GNB_IPV4_ADDRESS_FOR_NGU 192.168.71.180 + --log_config.global_log_options level,nocolor,time + ASAN_OPTIONS: detect_leaks=0:detect_odr_violation=0 + networks: + public_net: + ipv4_address: 192.168.71.180 + volumes: + - ../../conf_files/neighbour-config.conf:/opt/oai-gnb/etc/neighbour-config.conf + - ../../conf_files/gnb-cucp.sa.e1-ho-n2.conf:/opt/oai-gnb/etc/gnb.conf + healthcheck: + test: /bin/bash -c "pgrep nr-softmodem" + start_period: 10s + start_interval: 500ms + interval: 10s + timeout: 5s + retries: 5 + + oai-cuup-1: + image: ${REGISTRY:-oaisoftwarealliance}/${NRCUUP_IMG:-oai-nr-cuup}:${TAG:-develop} + container_name: rfsim5g-oai-cuup-1 + cap_drop: + - ALL + environment: + USE_ADDITIONAL_OPTIONS: --log_config.global_log_options level,nocolor,time + --gNBs.[0].E1_INTERFACE.[0].ipv4_cucp 192.168.71.180 + --gNBs.[0].E1_INTERFACE.[0].ipv4_cuup 192.168.71.181 + --gNBs.[0].NETWORK_INTERFACES.GNB_IPV4_ADDRESS_FOR_NGU 192.168.71.181 + --gNBs.[0].local_s_address 192.168.71.181 + ASAN_OPTIONS: detect_leaks=0 + depends_on: + - oai-cucp-0 + networks: + public_net: + ipv4_address: 192.168.71.181 + volumes: + - ../../conf_files/gnb-cuup.sa.f1.conf:/opt/oai-gnb/etc/gnb.conf + healthcheck: + test: /bin/bash -c "pgrep nr-cuup" + start_period: 10s + start_interval: 500ms + interval: 10s + timeout: 5s + retries: 5 + + oai-du-1: + image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop} + container_name: rfsim5g-oai-du-1 + cap_drop: + - ALL + environment: + USE_ADDITIONAL_OPTIONS: --rfsim + --rfsimulator.serveraddr 192.168.71.190 + --log_config.global_log_options level,nocolor,time + --gNBs.[0].gNB_DU_ID 1234 + --gNBs.[0].gNB_ID 0xb00 + --gNBs.[0].nr_cellid 1 + --gNBs.[0].servingCellConfigCommon.[0].physCellId 1 + --gNBs.[0].servingCellConfigCommon.[0].absoluteFrequencySSB 621312 + --gNBs.[0].servingCellConfigCommon.[0].dl_absoluteFrequencyPointA 620040 + --MACRLCs.[0].local_n_address 192.168.71.182 + --MACRLCs.[0].remote_n_address 192.168.71.180 + ASAN_OPTIONS: detect_leaks=0:detect_odr_violation=0 + depends_on: + - oai-cucp-1 + networks: + public_net: + ipv4_address: 192.168.71.182 + volumes: + - ../../conf_files/neighbour-config.conf:/opt/oai-gnb/etc/neighbour-config.conf + - ../../conf_files/gnb-du.sa.band78.106prb.rfsim.conf:/opt/oai-gnb/etc/gnb.conf + healthcheck: + test: /bin/bash -c "pgrep nr-softmodem" + start_period: 10s + start_interval: 500ms + interval: 10s + timeout: 5s + retries: 5 + +networks: + public_net: + driver: bridge + name: rfsim5g-oai-public-net + ipam: + config: + - subnet: 192.168.71.128/26 + driver_opts: + com.docker.network.bridge.name: "rfsim5g-public" + traffic_net: + driver: bridge + name: rfsim5g-oai-traffic-net + ipam: + config: + - subnet: 192.168.72.128/26 + driver_opts: + com.docker.network.bridge.name: "rfsim5g-traffic" From bc9c59f186c19c9888cdf71790be0151515cde1f Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 20 Aug 2025 22:56:46 +0200 Subject: [PATCH 728/964] Add NGAP RAN Status Transfer enc/dec and handlers (UL and DL) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to 4.9.1.3.3 of 3GPP TS 23.502: > 2a. - 2c. The S-RAN sends the Uplink RAN Status Transfer message to the S-AMF, > as specified in TS 36.300 [46] and TS 38.300 [9]. The S-RAN may omit sending > this message if none of the radio bearers of the UE shall be treated with PDCP status preservation. TS 38.300 says: > For DRBs not configured with DAPS, the source gNB sends the SN STATUS TRANSFER message to the target > gNB to convey the uplink PDCP SN receiver status and the downlink PDCP SN transmitter status of DRBs for > which PDCP status preservation applies (i.e. for RLC AM). The uplink PDCP SN receiver status includes at > least the PDCP SN of the first missing UL PDCP SDU and may include a bit map of the receive status of the out > of sequence UL PDCP SDUs that the UE needs to retransmit in the target cell, if any. The downlink PDCP SN > transmitter status indicates the next PDCP SN that the target gNB shall assign to new PDCP SDUs, not having a > PDCP SN yet. i.e., for DRBs for which PDCP status preservation applies (i.e. for RLC AM), which is is our case. This commit introduces full support for NG-RAN Status Transfer message handling (TS 38.413 §9.2.3.13-14) in CU. It enables correct state transfer of PDCP COUNT values (SN + HFN) during mobility or recovery scenarios. Summary of changes - NGAP: * Added encoding/decoding support for UL/DL RAN Status Transfer message * Defined structures for: ngap_drb_count_value_t, ngap_drb_status_t, ngap_ran_status_container_t, ngap_ran_status_transfer_t --- openair2/COMMON/ngap_messages_def.h | 2 + openair2/COMMON/ngap_messages_types.h | 46 ++++++++++ openair3/NGAP/ngap_gNB.c | 34 +++++++ openair3/NGAP/ngap_gNB_decoder.c | 6 ++ openair3/NGAP/ngap_gNB_encoder.c | 1 + openair3/NGAP/ngap_gNB_handlers.c | 96 +++++++++++++++++++- openair3/NGAP/ngap_gNB_mobility_management.c | 70 ++++++++++++++ openair3/NGAP/ngap_gNB_mobility_management.h | 1 + openair3/NGAP/ngap_msg_includes.h | 7 ++ 9 files changed, 262 insertions(+), 1 deletion(-) diff --git a/openair2/COMMON/ngap_messages_def.h b/openair2/COMMON/ngap_messages_def.h index fc07cffc6d..bdeb2455b4 100644 --- a/openair2/COMMON/ngap_messages_def.h +++ b/openair2/COMMON/ngap_messages_def.h @@ -75,6 +75,8 @@ MESSAGE_DEF(NGAP_HANDOVER_REQUIRED, MESSAGE_PRIORITY_MED, ngap_handover_required MESSAGE_DEF(NGAP_HANDOVER_FAILURE, MESSAGE_PRIORITY_MED, ngap_handover_failure_t, ngap_handover_failure) MESSAGE_DEF(NGAP_HANDOVER_REQUEST_ACKNOWLEDGE, MESSAGE_PRIORITY_MED, ngap_handover_request_ack_t, ngap_handover_request_ack) MESSAGE_DEF(NGAP_HANDOVER_NOTIFY, MESSAGE_PRIORITY_MED, ngap_handover_notify_t, ngap_handover_notify) +MESSAGE_DEF(NGAP_UL_RAN_STATUS_TRANSFER, MESSAGE_PRIORITY_MED, ngap_ran_status_transfer_t, ngap_ul_ran_status_transfer) +MESSAGE_DEF(NGAP_DL_RAN_STATUS_TRANSFER, MESSAGE_PRIORITY_MED, ngap_ran_status_transfer_t, ngap_dl_ran_status_transfer) /* NGAP -> RRC messages */ MESSAGE_DEF(NGAP_DOWNLINK_NAS , MESSAGE_PRIORITY_MED, ngap_downlink_nas_t , ngap_downlink_nas ) diff --git a/openair2/COMMON/ngap_messages_types.h b/openair2/COMMON/ngap_messages_types.h index eb21935e03..a8c2bab58a 100644 --- a/openair2/COMMON/ngap_messages_types.h +++ b/openair2/COMMON/ngap_messages_types.h @@ -76,6 +76,9 @@ #define NGAP_PDUSESSION_RELEASE_COMMAND(mSGpTR) (mSGpTR)->ittiMsg.ngap_pdusession_release_command #define NGAP_PDUSESSION_RELEASE_RESPONSE(mSGpTR) (mSGpTR)->ittiMsg.ngap_pdusession_release_resp +#define NGAP_UL_RAN_STATUS_TRANSFER(mSGpTR) (mSGpTR)->ittiMsg.ngap_ul_ran_status_transfer +#define NGAP_DL_RAN_STATUS_TRANSFER(mSGpTR) (mSGpTR)->ittiMsg.ngap_dl_ran_status_transfer + //-------------------------------------------------------------------------------------------// /* Length of the transport layer address string @@ -963,4 +966,47 @@ typedef struct ngap_pdusession_release_resp_s { } ngap_pdusession_release_resp_t; +/** 9.2.3.14 Uplink RAN Status Transfer (3GPP TS 38.413) + * COUNT value used for both UL and DL PDCP SN + HFN (12-bit or 18-bit SN) */ + +// Indicates PDCP SN length +typedef enum { NGAP_SN_LENGTH_12 = 0, NGAP_SN_LENGTH_18 = 1 } ngap_sn_length_t; + +typedef struct { + // PDCP Sequence Number + uint32_t pdcp_sn; + // Hyper Frame Number + uint32_t hfn; + // SN length + ngap_sn_length_t sn_len; +} ngap_drb_count_value_t; + +// DRBs Subject to Status Transfer Item +typedef struct { + // DRB ID + uint8_t drb_id; + // UL COUNT value + ngap_drb_count_value_t ul_count; + // DL COUNT value + ngap_drb_count_value_t dl_count; +} ngap_drb_status_t; + +// RAN Status Transfer Transparent Container (9.3.1.108) +typedef struct { + // Number of DRBs in the list + uint8_t nb_drb; + // DRB Status List + ngap_drb_status_t drb_status_list[MAX_DRBS_PER_UE]; +} ngap_ran_status_container_t; + +// Uplink RAN Status Transfer message (9.2.3.14) +typedef struct { + // AMF UE NGAP ID (Mandatory) + uint64_t amf_ue_ngap_id; + // RAN UE NGAP ID (Mandatory) + uint32_t gnb_ue_ngap_id; + // RAN Status Transfer Transparent Container (Mandatory) + ngap_ran_status_container_t ran_status; +} ngap_ran_status_transfer_t; + #endif /* NGAP_MESSAGES_TYPES_H_ */ diff --git a/openair3/NGAP/ngap_gNB.c b/openair3/NGAP/ngap_gNB.c index 272759de4c..afa69c4c9d 100644 --- a/openair3/NGAP/ngap_gNB.c +++ b/openair3/NGAP/ngap_gNB.c @@ -463,6 +463,36 @@ static int ngap_gNB_handover_notify(instance_t instance, const ngap_handover_not return 0; } +int ngap_gNB_handle_ul_ran_status_transfer(instance_t instance, const ngap_ran_status_transfer_t *msg) +{ + NGAP_DEBUG("Triggered UL RAN Status Transfer\n"); + + ngap_gNB_instance_t *ngap_gNB_instance_p = ngap_gNB_get_instance(instance); + DevAssert(ngap_gNB_instance_p != NULL); + + ngap_gNB_ue_context_t *ue_context_p = ngap_get_ue_context(msg->gnb_ue_ngap_id); + if (!ue_context_p || ue_context_p->gNB_ue_ngap_id != msg->gnb_ue_ngap_id) { + NGAP_ERROR("Could not find UE context for gNB_ue_ngap_id %d\n", msg->gnb_ue_ngap_id); + return -1; + } + + NGAP_NGAP_PDU_t *pdu = encode_ng_ul_ran_status_transfer(msg); + if (!pdu) { + NGAP_ERROR("Failed to encode UL RAN Status Transfer\n"); + return -1; + } + + byte_array_t out = {.buf = NULL, .len = 0}; + if (ngap_gNB_encode_pdu(pdu, &out.buf, (uint32_t *)&out.len) < 0) { + NGAP_ERROR("UL RAN Status Transfer encoding failure\n"); + ASN_STRUCT_FREE(asn_DEF_NGAP_NGAP_PDU, pdu); + return -1; + } + + ngap_gNB_itti_send_sctp_data_req(instance, ue_context_p->amf_ref->assoc_id, out.buf, out.len, ue_context_p->tx_stream); + return 0; +} + void *ngap_gNB_process_itti_msg(void *notUsed) { MessageDef *received_msg = NULL; int result; @@ -557,6 +587,10 @@ void *ngap_gNB_process_itti_msg(void *notUsed) { ngap_gNB_handover_notify(instance, &NGAP_HANDOVER_NOTIFY(received_msg)); break; + case NGAP_UL_RAN_STATUS_TRANSFER: + ngap_gNB_handle_ul_ran_status_transfer(instance, &NGAP_UL_RAN_STATUS_TRANSFER(received_msg)); + break; + default: NGAP_ERROR("Received unhandled message: %d:%s\n", ITTI_MSG_ID(received_msg), ITTI_MSG_NAME(received_msg)); break; diff --git a/openair3/NGAP/ngap_gNB_decoder.c b/openair3/NGAP/ngap_gNB_decoder.c index a56357b55a..481cccf876 100644 --- a/openair3/NGAP/ngap_gNB_decoder.c +++ b/openair3/NGAP/ngap_gNB_decoder.c @@ -100,6 +100,12 @@ static int ngap_gNB_decode_initiating_message(NGAP_NGAP_PDU_t *pdu) { NGAP_INFO("Handover Resource Allocation initiating message\n"); break; + case NGAP_ProcedureCode_id_DownlinkRANStatusTransfer: + res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu); + free(res.buffer); + NGAP_INFO("DL RAN Status Transfer initiating message\n"); + break; + default: NGAP_ERROR("Unknown procedure ID (%d) for initiating message\n", (int)pdu->choice.initiatingMessage->procedureCode); diff --git a/openair3/NGAP/ngap_gNB_encoder.c b/openair3/NGAP/ngap_gNB_encoder.c index 16954744e2..7a7ce758e1 100644 --- a/openair3/NGAP/ngap_gNB_encoder.c +++ b/openair3/NGAP/ngap_gNB_encoder.c @@ -53,6 +53,7 @@ static inline int ngap_gNB_encode_initiating(NGAP_NGAP_PDU_t *pdu, uint8_t **buf NGAP_ProcedureCode_id_UEContextReleaseRequest, NGAP_ProcedureCode_id_PathSwitchRequest, NGAP_ProcedureCode_id_PDUSessionResourceModifyIndication, + NGAP_ProcedureCode_id_UplinkRANStatusTransfer, NGAP_ProcedureCode_id_HandoverPreparation, NGAP_ProcedureCode_id_HandoverNotification}; int i; diff --git a/openair3/NGAP/ngap_gNB_handlers.c b/openair3/NGAP/ngap_gNB_handlers.c index 226c8e8fa0..0257e49698 100644 --- a/openair3/NGAP/ngap_gNB_handlers.c +++ b/openair3/NGAP/ngap_gNB_handlers.c @@ -1378,6 +1378,100 @@ static int ngap_gNB_handle_ng_ENDC_pdusession_modification_confirm(sctp_assoc_t return 0; } +static int ngap_gNB_handle_dl_ran_status_transfer(sctp_assoc_t assoc_id, uint32_t stream, NGAP_NGAP_PDU_t *pdu) +{ + DevAssert(pdu != NULL); + + NGAP_DownlinkRANStatusTransfer_t *container = &pdu->choice.initiatingMessage->value.choice.DownlinkRANStatusTransfer; + NGAP_DownlinkRANStatusTransferIEs_t *ie = NULL; + + ngap_gNB_amf_data_t *amf_desc_p = ngap_gNB_get_AMF(NULL, assoc_id, 0); + if (!amf_desc_p) { + NGAP_ERROR("[SCTP %u] Received DL RAN Status Transfer for unknown AMF\n", assoc_id); + return -1; + } + + // AMF UE NGAP ID + uint64_t amf_ue_ngap_id = 0; + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_DownlinkRANStatusTransferIEs_t, ie, container, NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID, true); + asn_INTEGER2ulong(&ie->value.choice.AMF_UE_NGAP_ID, &amf_ue_ngap_id); + + // RAN UE NGAP ID + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_DownlinkRANStatusTransferIEs_t, ie, container, NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID, true); + NGAP_RAN_UE_NGAP_ID_t gnb_ue_ngap_id = ie->value.choice.RAN_UE_NGAP_ID; + + ngap_gNB_ue_context_t *ue_desc_p = ngap_get_ue_context(gnb_ue_ngap_id); + if (!ue_desc_p) { + NGAP_ERROR("No UE context for gNB_ue_ngap_id %lu\n", gnb_ue_ngap_id); + return -1; + } + + ue_desc_p->rx_stream = stream; + if (ue_desc_p->amf_ue_ngap_id != amf_ue_ngap_id) + NGAP_WARN("UE context mismatch: amf_ue_ngap_id (%lu != %lu)\n", ue_desc_p->amf_ue_ngap_id, amf_ue_ngap_id); + + // Transparent container + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_DownlinkRANStatusTransferIEs_t, + ie, + container, + NGAP_ProtocolIE_ID_id_RANStatusTransfer_TransparentContainer, + true); + NGAP_RANStatusTransfer_TransparentContainer_t *tcont = &ie->value.choice.RANStatusTransfer_TransparentContainer; + + MessageDef *message_p = itti_alloc_new_message(TASK_NGAP, 0, NGAP_DL_RAN_STATUS_TRANSFER); + ngap_ran_status_transfer_t *msg = &NGAP_DL_RAN_STATUS_TRANSFER(message_p); + memset(msg, 0, sizeof(*msg)); + + msg->amf_ue_ngap_id = amf_ue_ngap_id; + msg->gnb_ue_ngap_id = gnb_ue_ngap_id; + + int nb = tcont->dRBsSubjectToStatusTransferList.list.count; + for (int i = 0; i < nb; ++i) { + NGAP_DRBsSubjectToStatusTransferItem_t *item = tcont->dRBsSubjectToStatusTransferList.list.array[i]; + ngap_drb_status_t *s = &msg->ran_status.drb_status_list[i]; + s->drb_id = item->dRB_ID; + + // UL COUNT + switch (item->dRBStatusUL.present) { + case NGAP_DRBStatusUL_PR_dRBStatusUL18: + s->ul_count.sn_len = NGAP_SN_LENGTH_18; + s->ul_count.pdcp_sn = item->dRBStatusUL.choice.dRBStatusUL18->uL_COUNTValue.pDCP_SN18; + s->ul_count.hfn = item->dRBStatusUL.choice.dRBStatusUL18->uL_COUNTValue.hFN_PDCP_SN18; + break; + case NGAP_DRBStatusUL_PR_dRBStatusUL12: + s->ul_count.sn_len = NGAP_SN_LENGTH_12; + s->ul_count.pdcp_sn = item->dRBStatusUL.choice.dRBStatusUL12->uL_COUNTValue.pDCP_SN12; + s->ul_count.hfn = item->dRBStatusUL.choice.dRBStatusUL12->uL_COUNTValue.hFN_PDCP_SN12; + break; + default: + NGAP_ERROR("Unknown dRBStatusUL.present=%d\n", item->dRBStatusUL.present); + break; + } + + // DL COUNT + switch (item->dRBStatusDL.present) { + case NGAP_DRBStatusDL_PR_dRBStatusDL18: + s->dl_count.sn_len = NGAP_SN_LENGTH_18; + s->dl_count.pdcp_sn = item->dRBStatusDL.choice.dRBStatusDL18->dL_COUNTValue.pDCP_SN18; + s->dl_count.hfn = item->dRBStatusDL.choice.dRBStatusDL18->dL_COUNTValue.hFN_PDCP_SN18; + break; + case NGAP_DRBStatusDL_PR_dRBStatusDL12: + s->dl_count.sn_len = NGAP_SN_LENGTH_12; + s->dl_count.pdcp_sn = item->dRBStatusDL.choice.dRBStatusDL12->dL_COUNTValue.pDCP_SN12; + s->dl_count.hfn = item->dRBStatusDL.choice.dRBStatusDL12->dL_COUNTValue.hFN_PDCP_SN12; + break; + default: + NGAP_ERROR("Unknown dRBStatusDL.present=%d\n", item->dRBStatusDL.present); + break; + } + + msg->ran_status.nb_drb++; + } + + itti_send_msg_to_task(TASK_RRC_GNB, ue_desc_p->gNB_instance->instance, message_p); + return 0; +} + /* Handlers matrix. Only gNB related procedure present here */ const ngap_message_decoded_callback ngap_messages_callback[][3] = { {0, 0, 0}, /* AMFConfigurationUpdate */ @@ -1387,7 +1481,7 @@ const ngap_message_decoded_callback ngap_messages_callback[][3] = { {ngap_gNB_handle_nas_downlink, 0, 0}, /* DownlinkNASTransport */ {0, 0, 0}, /* DownlinkNonUEAssociatedNRPPaTransport */ {0, 0, 0}, /* DownlinkRANConfigurationTransfer */ - {0, 0, 0}, /* DownlinkRANStatusTransfer */ + {ngap_gNB_handle_dl_ran_status_transfer, 0, 0}, /* DownlinkRANStatusTransfer */ {0, 0, 0}, /* DownlinkUEAssociatedNRPPaTransport */ {ngap_gNB_handle_error_indication, 0, 0}, /* ErrorIndication */ {0, 0, 0}, /* HandoverCancel */ diff --git a/openair3/NGAP/ngap_gNB_mobility_management.c b/openair3/NGAP/ngap_gNB_mobility_management.c index 565be7acd5..4f1383e5e0 100644 --- a/openair3/NGAP/ngap_gNB_mobility_management.c +++ b/openair3/NGAP/ngap_gNB_mobility_management.c @@ -617,3 +617,73 @@ NGAP_NGAP_PDU_t *encode_ng_handover_notify(const ngap_handover_notify_t *msg) return pdu; } + +/** @brief Encode NGAP UL RAN Status Transfer (9.2.3.14 of 3GPP TS 38.413) */ +NGAP_NGAP_PDU_t *encode_ng_ul_ran_status_transfer(const ngap_ran_status_transfer_t *msg) +{ + NGAP_NGAP_PDU_t *pdu = malloc_or_fail(sizeof(*pdu)); + pdu->present = NGAP_NGAP_PDU_PR_initiatingMessage; + asn1cCalloc(pdu->choice.initiatingMessage, head); + head->procedureCode = NGAP_ProcedureCode_id_UplinkRANStatusTransfer; + head->criticality = NGAP_Criticality_ignore; + head->value.present = NGAP_InitiatingMessage__value_PR_UplinkRANStatusTransfer; + NGAP_UplinkRANStatusTransfer_t *out = &head->value.choice.UplinkRANStatusTransfer; + + // AMF UE NGAP ID (M) + asn1cSequenceAdd(out->protocolIEs.list, NGAP_UplinkRANStatusTransferIEs_t, ie1); + ie1->id = NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID; + ie1->criticality = NGAP_Criticality_reject; + ie1->value.present = NGAP_UplinkRANStatusTransferIEs__value_PR_AMF_UE_NGAP_ID; + asn_uint642INTEGER(&ie1->value.choice.AMF_UE_NGAP_ID, msg->amf_ue_ngap_id); + + // RAN UE NGAP ID (M) + asn1cSequenceAdd(out->protocolIEs.list, NGAP_UplinkRANStatusTransferIEs_t, ie2); + ie2->id = NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID; + ie2->criticality = NGAP_Criticality_reject; + ie2->value.present = NGAP_UplinkRANStatusTransferIEs__value_PR_RAN_UE_NGAP_ID; + ie2->value.choice.RAN_UE_NGAP_ID = msg->gnb_ue_ngap_id; + + // RAN Status Transfer Transparent Container (M) + asn1cSequenceAdd(out->protocolIEs.list, NGAP_UplinkRANStatusTransferIEs_t, ie3); + ie3->id = NGAP_ProtocolIE_ID_id_RANStatusTransfer_TransparentContainer; + ie3->criticality = NGAP_Criticality_reject; + ie3->value.present = NGAP_UplinkRANStatusTransferIEs__value_PR_RANStatusTransfer_TransparentContainer; + NGAP_RANStatusTransfer_TransparentContainer_t *container = &ie3->value.choice.RANStatusTransfer_TransparentContainer; + + for (int i = 0; i < msg->ran_status.nb_drb; ++i) { + const ngap_drb_status_t *s = &msg->ran_status.drb_status_list[i]; + asn1cSequenceAdd(container->dRBsSubjectToStatusTransferList.list, NGAP_DRBsSubjectToStatusTransferItem_t, drb_item); + drb_item->dRB_ID = s->drb_id; + + // UL COUNT + if (s->ul_count.sn_len == NGAP_SN_LENGTH_18) { + drb_item->dRBStatusUL.present = NGAP_DRBStatusUL_PR_dRBStatusUL18; + asn1cCalloc(drb_item->dRBStatusUL.choice.dRBStatusUL18, ul18); + ul18->uL_COUNTValue.pDCP_SN18 = s->ul_count.pdcp_sn; + ul18->uL_COUNTValue.hFN_PDCP_SN18 = s->ul_count.hfn; + } else { + drb_item->dRBStatusUL.present = NGAP_DRBStatusUL_PR_dRBStatusUL12; + asn1cCalloc(drb_item->dRBStatusUL.choice.dRBStatusUL12, ul12); + ul12->uL_COUNTValue.pDCP_SN12 = s->ul_count.pdcp_sn; + ul12->uL_COUNTValue.hFN_PDCP_SN12 = s->ul_count.hfn; + } + + // DL COUNT + if (s->dl_count.sn_len == NGAP_SN_LENGTH_18) { + drb_item->dRBStatusDL.present = NGAP_DRBStatusDL_PR_dRBStatusDL18; + asn1cCalloc(drb_item->dRBStatusDL.choice.dRBStatusDL18, dl18); + dl18->dL_COUNTValue.pDCP_SN18 = s->dl_count.pdcp_sn; + dl18->dL_COUNTValue.hFN_PDCP_SN18 = s->dl_count.hfn; + } else { + drb_item->dRBStatusDL.present = NGAP_DRBStatusDL_PR_dRBStatusDL12; + asn1cCalloc(drb_item->dRBStatusDL.choice.dRBStatusDL12, dl12); + dl12->dL_COUNTValue.pDCP_SN12 = s->dl_count.pdcp_sn; + dl12->dL_COUNTValue.hFN_PDCP_SN12 = s->dl_count.hfn; + } + } + + if (LOG_DEBUGFLAG(DEBUG_ASN1)) + xer_fprint(stdout, &asn_DEF_NGAP_RANStatusTransfer_TransparentContainer, &container); + + return pdu; +} diff --git a/openair3/NGAP/ngap_gNB_mobility_management.h b/openair3/NGAP/ngap_gNB_mobility_management.h index d31bdb0caa..b7a6f3547c 100644 --- a/openair3/NGAP/ngap_gNB_mobility_management.h +++ b/openair3/NGAP/ngap_gNB_mobility_management.h @@ -34,5 +34,6 @@ void free_ng_handover_req_ack(ngap_handover_request_ack_t *msg); int decode_ng_handover_command(ngap_handover_command_t *msg, NGAP_NGAP_PDU_t *pdu); void free_ng_handover_command(ngap_handover_command_t *msg); NGAP_NGAP_PDU_t *encode_ng_handover_notify(const ngap_handover_notify_t *msg); +NGAP_NGAP_PDU_t *encode_ng_ul_ran_status_transfer(const ngap_ran_status_transfer_t *msg); #endif /* NGAP_GNB_MOBILITY_MANAGEMENT_H_ */ diff --git a/openair3/NGAP/ngap_msg_includes.h b/openair3/NGAP/ngap_msg_includes.h index 4224660974..816cdfb979 100644 --- a/openair3/NGAP/ngap_msg_includes.h +++ b/openair3/NGAP/ngap_msg_includes.h @@ -102,5 +102,12 @@ #include "NGAP_QosFlowItemWithDataForwarding.h" #include "NR_HandoverPreparationInformation.h" #include "NGAP_HandoverNotify.h" +#include "NGAP_DRBsSubjectToStatusTransferItem.h" +#include "NGAP_DRBStatusUL.h" +#include "NGAP_DRBStatusUL18.h" +#include "NGAP_DRBStatusUL12.h" +#include "NGAP_DRBStatusDL.h" +#include "NGAP_DRBStatusDL18.h" +#include "NGAP_DRBStatusDL12.h" #endif // NGAP_MSG_INCLUDES_H From e527b99de120ff1a8776b0a1f79c353db96655b9 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 20 Aug 2025 12:45:36 +0200 Subject: [PATCH 729/964] PDCP Status Information: add enc/dec/cp/eq and test to E1AP lib Also: * remove unused oldQosFlows IEs * adopt new enc/dec functions * fix missing return in eq_bearer_context_mod_response --- openair2/COMMON/e1ap_messages_types.h | 23 ++++- .../E1AP/lib/e1ap_bearer_context_management.c | 83 +++++++++++++++++-- openair2/E1AP/tests/e1ap_lib_test.c | 18 ++++ 3 files changed, 116 insertions(+), 8 deletions(-) diff --git a/openair2/COMMON/e1ap_messages_types.h b/openair2/COMMON/e1ap_messages_types.h index f4e9090f66..788236ca05 100644 --- a/openair2/COMMON/e1ap_messages_types.h +++ b/openair2/COMMON/e1ap_messages_types.h @@ -283,6 +283,22 @@ typedef struct bearer_context_pdcp_config_s { bool pDCP_Reestablishment; } bearer_context_pdcp_config_t; +/* 9.3.1.35 3GPP TS 38.463 */ +typedef struct { + // PDCP SN + uint32_t sn; + // HFN + uint32_t hfn; +} e1_pdcp_count_t; + +/* 9.3.1.58 3GPP TS 38.463 */ +typedef struct { + // UL Count Value + e1_pdcp_count_t ul_count; + // DL Count Value + e1_pdcp_count_t dl_count; +} e1_pdcp_status_info_t; + typedef struct drb_to_setup_s { long drbId; bearer_context_pdcp_config_t pdcp_config; @@ -384,6 +400,8 @@ typedef struct DRB_nGRAN_to_modify_s { bearer_context_pdcp_config_t *pdcp_config; // PDCP SN Status Request (O) bool pdcp_sn_status_requested; + // PDCP SN Status Information + e1_pdcp_status_info_t *pdcp_status; // DL UP Transport Layer Information (O) (clause 9.3.1.13, 9.3.2.1) int numDlUpParam; up_params_t DlUpParamList[E1AP_MAX_NUM_UP_PARAM]; @@ -561,9 +579,8 @@ typedef struct DRB_nGRAN_modified_s { // Flow Failed List (O) int numQosFlowFailed; qos_flow_failed_t qosFlowsFailed[E1AP_MAX_NUM_QOS_FLOWS]; - // Old QoS Flow List (O) - int numOldQosFlow; - qos_flow_list_t oldQosFlows[E1AP_MAX_NUM_QOS_FLOWS]; + // PDCP SN Status Information (0) + e1_pdcp_status_info_t *pdcp_status; } DRB_nGRAN_modified_t; typedef struct DRB_nGRAN_failed_s { diff --git a/openair2/E1AP/lib/e1ap_bearer_context_management.c b/openair2/E1AP/lib/e1ap_bearer_context_management.c index f9afa06f69..0f2e5972e2 100644 --- a/openair2/E1AP/lib/e1ap_bearer_context_management.c +++ b/openair2/E1AP/lib/e1ap_bearer_context_management.c @@ -360,6 +360,39 @@ static E1AP_UP_Parameters_t encode_dl_up_parameters(const int numUpParam, const return out; } +/** @brief PDCP SN Status Information (9.3.1.58 3GPP TS 38.463) */ +static E1AP_PDCP_SN_Status_Information_t encode_pdcp_status_info(const e1_pdcp_status_info_t *in) +{ + E1AP_PDCP_SN_Status_Information_t pdcp = {0}; + pdcp.pdcpStatusTransfer_DL.hFN = in->dl_count.hfn; + pdcp.pdcpStatusTransfer_DL.pDCP_SN = in->dl_count.sn; + pdcp.pdcpStatusTransfer_UL.countValue.hFN = in->ul_count.hfn; + pdcp.pdcpStatusTransfer_UL.countValue.pDCP_SN = in->ul_count.sn; + return pdcp; +} + +/** @brief PDCP SN Status Information (9.3.1.58 3GPP TS 38.463) */ +static e1_pdcp_status_info_t decode_pdcp_status_info(const E1AP_PDCP_SN_Status_Information_t* in) +{ + e1_pdcp_status_info_t out = {0}; + const E1AP_PDCP_Count_t *dl = &in->pdcpStatusTransfer_DL; + const E1AP_PDCP_Count_t *ul = &in->pdcpStatusTransfer_UL.countValue; + out.dl_count.hfn = dl->hFN; + out.dl_count.sn = dl->pDCP_SN; + out.ul_count.hfn = ul->hFN; + out.ul_count.sn = ul->pDCP_SN; + return out; +} + +static bool eq_pdcp_info(const e1_pdcp_status_info_t *a, const e1_pdcp_status_info_t *b) +{ + _E1_EQ_CHECK_INT(a->dl_count.hfn, b->dl_count.hfn); + _E1_EQ_CHECK_INT(a->dl_count.sn, b->dl_count.sn); + _E1_EQ_CHECK_INT(a->ul_count.hfn, b->ul_count.hfn); + _E1_EQ_CHECK_INT(a->ul_count.sn, b->ul_count.sn); + return true; +} + /** * @brief Equality check for DRB_nGRAN_to_setup_t */ @@ -1409,6 +1442,11 @@ static E1AP_PDU_Session_Resource_To_Modify_Item_t e1_encode_pdu_session_to_mod_i asn1cCalloc(drb2Mod->pDCP_SN_Status_Request, pDCP_SN_Status_Request); *pDCP_SN_Status_Request = E1AP_PDCP_SN_Status_Request_requested; } + // PDCP Status Information (O) + if (j->pdcp_status) { + asn1cCalloc(drb2Mod->pdcp_SN_Status_Information, pdcp); + *pdcp = encode_pdcp_status_info(j->pdcp_status); + } // DL UP TNL parameters (O) if (j->numDlUpParam > 0) { asn1cCalloc(drb2Mod->dL_UP_Parameters, DL_UP_Param_List); @@ -1667,9 +1705,14 @@ static bool e1_decode_pdu_session_to_mod_item(pdu_session_to_mod_t *out, const E CHECK_E1AP_DEC(e1_decode_sdap_config(drb->sdap_config, drb2Mod->sDAP_Configuration)); } // PDCP SN Status Request (O) - if (drb2Mod->pDCP_SN_Status_Request) { + if (drb2Mod->pDCP_SN_Status_Request && *drb2Mod->pDCP_SN_Status_Request == E1AP_PDCP_SN_Status_Request_requested) { drb->pdcp_sn_status_requested = true; } + // PDCP SN Status Information (O) + if (drb2Mod->pdcp_SN_Status_Information) { + drb->pdcp_status = malloc_or_fail(sizeof(*drb->pdcp_status)); + *drb->pdcp_status = decode_pdcp_status_info(drb2Mod->pdcp_SN_Status_Information); + } // DL UP TNL parameters (O) if (drb2Mod->dL_UP_Parameters) { E1AP_UP_Parameters_t *dl_up_paramList = drb2Mod->dL_UP_Parameters; @@ -1843,6 +1886,7 @@ static DRB_nGRAN_to_mod_t cp_drb_to_mod_item(const DRB_nGRAN_to_mod_t *msg) cp = *msg; _E1_CP_OPTIONAL_IE(&cp, msg, sdap_config); _E1_CP_OPTIONAL_IE(&cp, msg, pdcp_config); + _E1_CP_OPTIONAL_IE(&cp, msg, pdcp_status); return cp; } @@ -1904,12 +1948,15 @@ static bool eq_drb_to_mod(const DRB_nGRAN_to_mod_t *a, const DRB_nGRAN_to_mod_t _E1_EQ_CHECK_INT(a->numDlUpParam, b->numDlUpParam); for (int i = 0; i < a->numDlUpParam; i++) { _E1_EQ_CHECK_INT(a->DlUpParamList[i].cell_group_id, b->DlUpParamList[i].cell_group_id); - eq_up_tl_info(&a->DlUpParamList[i].tl_info, &b->DlUpParamList[i].tl_info); + result &= eq_up_tl_info(&a->DlUpParamList[i].tl_info, &b->DlUpParamList[i].tl_info); } if (a->pdcp_config && b->pdcp_config) result &= eq_pdcp_config(a->pdcp_config, b->pdcp_config); if (a->sdap_config && b->sdap_config) result &= eq_sdap_config(a->sdap_config, b->sdap_config); + _E1_EQ_CHECK_OPTIONAL_PTR(a, b, pdcp_status); + if (a->pdcp_status && b->pdcp_status) + result &= eq_pdcp_info(a->pdcp_status, b->pdcp_status); return result; } @@ -1984,6 +2031,7 @@ static void free_drb_to_mod_item(const DRB_nGRAN_to_mod_t *msg) { free(msg->pdcp_config); free(msg->sdap_config); + free(msg->pdcp_status); } /* Free PDU Session to modify item */ @@ -2111,6 +2159,13 @@ struct E1AP_E1AP_PDU *encode_E1_bearer_context_mod_response(const e1ap_bearer_mo asn1cSequenceAdd(drb_mod->flow_Failed_List->list, E1AP_QoS_Flow_Failed_Item_t, fail); encode_qos_flow_failed_item(fail, &drb->qosFlowsFailed[q]); } + + // PDCP Status Information (O) + if (drb->pdcp_status) { + asn1cCalloc(drb_mod->pDCP_SN_Status_Information, pdcp); + *pdcp = encode_pdcp_status_info(drb->pdcp_status); + } + // UL UP Parameters (O) if (drb->numUpParam) drb_mod->uL_UP_Transport_Parameters = calloc_or_fail(1, sizeof(*drb_mod->uL_UP_Transport_Parameters)); @@ -2310,6 +2365,11 @@ bool decode_E1_bearer_context_mod_response(e1ap_bearer_modif_resp_t *out, const drbMod->qosFlowsFailed[i] = decode_qos_flow_failed_item(drbIE->flow_Failed_List->list.array[i]); } } + // PDCP Status Info (O) + if (drbIE->pDCP_SN_Status_Information) { + drbMod->pdcp_status = malloc_or_fail(sizeof(*drbMod->pdcp_status)); + *drbMod->pdcp_status = decode_pdcp_status_info(drbIE->pDCP_SN_Status_Information); + } } } // DRB Failed to Mod list @@ -2347,8 +2407,12 @@ e1ap_bearer_modif_resp_t cp_bearer_context_mod_response(const e1ap_bearer_modif_ // Shallow copy cp = *msg; // Deep copy PDU sessions modified items - for (int i = 0; i < msg->numPDUSessionsMod; i++) + for (int i = 0; i < msg->numPDUSessionsMod; i++) { cp.pduSessionMod[i] = cp_pdu_session_mod_item(&msg->pduSessionMod[i]); + for (int j = 0; j < msg->pduSessionMod[i].numDRBModified; j++) { + _E1_CP_OPTIONAL_IE(&cp.pduSessionMod[i].DRBnGRanModList[j], &msg->pduSessionMod[i].DRBnGRanModList[j], pdcp_status); + } + } return cp; } @@ -2359,6 +2423,8 @@ bool eq_bearer_context_mod_response(const e1ap_bearer_modif_resp_t *a, const e1a { if (!a || !b) return false; // Null-check both inputs + bool result = true; + // Basic members _E1_EQ_CHECK_INT(a->gNB_cu_cp_ue_id, b->gNB_cu_cp_ue_id); _E1_EQ_CHECK_INT(a->gNB_cu_up_ue_id, b->gNB_cu_up_ue_id); @@ -2375,7 +2441,7 @@ bool eq_bearer_context_mod_response(const e1ap_bearer_modif_resp_t *a, const e1a _E1_EQ_CHECK_OPTIONAL_PTR(pduA, pduB, ng_DL_UP_TL_info); if (pduA->ng_DL_UP_TL_info && pduB->ng_DL_UP_TL_info) - eq_up_tl_info(pduA->ng_DL_UP_TL_info, pduB->ng_DL_UP_TL_info); + result &= eq_up_tl_info(pduA->ng_DL_UP_TL_info, pduB->ng_DL_UP_TL_info); // DRB Modified List _E1_EQ_CHECK_INT(pduA->numDRBModified, pduB->numDRBModified); @@ -2387,6 +2453,10 @@ bool eq_bearer_context_mod_response(const e1ap_bearer_modif_resp_t *a, const e1a for (int j = 0; j < drbModA->numQosFlowSetup; j++) { _E1_EQ_CHECK_LONG(drbModA->qosFlows[j].qfi, drbModB->qosFlows[j].qfi); } + _E1_EQ_CHECK_OPTIONAL_PTR(drbModA, drbModB, pdcp_status); + if (drbModA->pdcp_status && drbModB->pdcp_status) { + result &= eq_pdcp_info(drbModA->pdcp_status, drbModA->pdcp_status); + } } // DRB Failed to Modify List @@ -2420,7 +2490,7 @@ bool eq_bearer_context_mod_response(const e1ap_bearer_modif_resp_t *a, const e1a } - return true; + return result; } /** @@ -2432,6 +2502,9 @@ void free_e1ap_context_mod_response(const e1ap_bearer_modif_resp_t *msg) free(msg->pduSessionMod[i].confidentialityProtectionIndication); free(msg->pduSessionMod[i].integrityProtectionIndication); free(msg->pduSessionMod[i].ng_DL_UP_TL_info); + for (int j = 0; j < msg->pduSessionMod[i].numDRBModified; j++) { + free(msg->pduSessionMod[i].DRBnGRanModList[j].pdcp_status); + } } } diff --git a/openair2/E1AP/tests/e1ap_lib_test.c b/openair2/E1AP/tests/e1ap_lib_test.c index a9fd7aa390..b168ff9e82 100644 --- a/openair2/E1AP/tests/e1ap_lib_test.c +++ b/openair2/E1AP/tests/e1ap_lib_test.c @@ -490,6 +490,13 @@ static void test_bearer_context_modification_request(void) .qos_params.qos_characteristics.non_dynamic.fiveqi = 9, }; + const e1_pdcp_status_info_t dummy_pdcp_status = { + .dl_count.hfn = 12, + .dl_count.sn = 34, + .ul_count.hfn = 56, + .ul_count.sn = 78, + }; + DRB_nGRAN_to_mod_t drb_to_mod = { .numDlUpParam = 1, .DlUpParamList[0].cell_group_id = MCG, @@ -497,10 +504,12 @@ static void test_bearer_context_modification_request(void) .id = 1, .pdcp_config = malloc_or_fail(sizeof(*drb_to_mod.pdcp_config)), .pdcp_sn_status_requested = true, + .pdcp_status = malloc_or_fail(sizeof(*drb_to_mod.pdcp_status)), .numQosFlow2Setup = 1, .qosFlows[0] = dummy_qos_flows, }; *drb_to_mod.pdcp_config = dummy_pdcp_config; + *drb_to_mod.pdcp_status = dummy_pdcp_status; pdu_session_to_mod_t pdusession_mod_item = { .sessionId = 1, @@ -592,12 +601,21 @@ const DRB_nGRAN_failed_t dummy_drb_failed = { */ static void test_bearer_context_modification_response(void) { + const e1_pdcp_status_info_t dummy_pdcp_status = { + .dl_count.hfn = 12, + .dl_count.sn = 2, + .ul_count.hfn = 12, + .ul_count.sn = 3, + }; + // DRB Modified List DRB_nGRAN_modified_t drb_mod = { .id = 1, .numQosFlowSetup = 1, .qosFlows[0].qfi = 1, + .pdcp_status = malloc_or_fail(sizeof(*drb_mod.pdcp_status)), }; + *drb_mod.pdcp_status = dummy_pdcp_status; // DRB Setup List DRB_nGRAN_setup_t setup = { From e96d7f9576225434af6d5e9031e2028423bed57d Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 20 Aug 2025 23:00:01 +0200 Subject: [PATCH 730/964] Add PDCP API getter and setter for PDCP count values in PDCP entity * Introduced nr_pdcp_count_update() to apply COUNT values to the PDCP entity: - Computes tx_next, rx_next, and rx_deliv from HFN+SN - Handles both 12-bit and 18-bit SN modes with dynamic bitmask * Introduced nr_pdcp_get_drb_count_values() to extract PDCP COUNT values from entity: - Used for building UL RAN Status Transfer on source CU side --- openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c | 94 +++++++++++++++++++++++ openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h | 13 +++- openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c | 54 +++++++++++++ openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h | 8 ++ 4 files changed, 168 insertions(+), 1 deletion(-) diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c index 41d41cf922..25081891d3 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c @@ -601,6 +601,94 @@ static void nr_pdcp_entity_get_stats(nr_pdcp_entity_t *entity, *out = entity->stats; } +/** @note: this function applies to the gNB only */ +static nr_pdcp_count_t nr_pdcp_entity_get_count_dl(nr_pdcp_entity_t *entity) +{ + nr_pdcp_count_t count = {0}; + const int sn_bits = entity->sn_size; + const uint32_t sn_mask = entity->sn_max; + count.hfn = entity->rx_deliv >> sn_bits; + count.sn = entity->rx_deliv & sn_mask; + return count; +} + +/** @note: this function applies to the gNB only */ +static nr_pdcp_count_t nr_pdcp_entity_get_count_ul(nr_pdcp_entity_t *entity) +{ + nr_pdcp_count_t count = {0}; + const int sn_bits = entity->sn_size; + const uint32_t sn_mask = entity->sn_max; + count.hfn = entity->tx_next >> sn_bits; + count.sn = entity->tx_next & sn_mask; + return count; +} + +/** @note: this function applies to the gNB only */ +static void nr_pdcp_entity_set_count_dl(nr_pdcp_entity_t *entity, nr_pdcp_count_t pdcp_count, int sn_size) +{ + // SN length in bits + const uint32_t sn_mask = (1 << sn_size) - 1; + + // Compose COUNT values for tx_next (DL) and rx_next (UL) + uint32_t count = (pdcp_count.hfn << sn_size) | (pdcp_count.sn & sn_mask); + + // Apply the COUNT values + entity->rx_next = count + 1; + entity->rx_deliv = count; + + LOG_I(PDCP, + "DRB %d: Applied PDCP Count\n" + " DL COUNT - SN: %d HFN: %d (COUNT=%u)\n" + " SN length: %s\n" + " PDCP entity state after update:\n" + " rx_next = %u\n" + " rx_deliv = %u\n" + " sn_size = %d\n" + " sn_max = %d\n" + " window = %d\n", + entity->rb_id, + pdcp_count.sn, + pdcp_count.hfn, + count, + sn_size == LONG_SN_SIZE ? "18-bit" : "12-bit", + entity->rx_next, + entity->rx_deliv, + entity->sn_size, + entity->sn_max, + entity->window_size); +} + +/** @note: this function applies to the gNB only */ +static void nr_pdcp_entity_set_count_ul(nr_pdcp_entity_t *entity, nr_pdcp_count_t pdcp_count, int sn_size) +{ + // SN length in bits + const uint32_t sn_mask = (1 << sn_size) - 1; + + // Compose COUNT values for tx_next (DL) and rx_next (UL) + uint32_t count = (pdcp_count.hfn << sn_size) | (pdcp_count.sn & sn_mask); + + // Apply the COUNT values + entity->tx_next = count; + + LOG_I(PDCP, + "DRB %d: Applied PDCP Count\n" + " UL COUNT - SN: %d HFN: %d (COUNT=%u)\n" + " SN length: %s\n" + " PDCP entity state after update:\n" + " tx_next = %u\n" + " sn_size = %d\n" + " sn_max = %d\n" + " window = %d\n", + entity->rb_id, + pdcp_count.sn, + pdcp_count.hfn, + count, + sn_size == LONG_SN_SIZE ? "18-bit" : "12-bit", + entity->tx_next, + entity->sn_size, + entity->sn_max, + entity->window_size); +} nr_pdcp_entity_t *new_nr_pdcp_entity( nr_pdcp_entity_type_t type, @@ -675,5 +763,11 @@ nr_pdcp_entity_t *new_nr_pdcp_entity( nr_pdcp_entity_set_security(ret, security_parameters); + /* PDCP Count API */ + ret->get_pdcp_count_dl = nr_pdcp_entity_get_count_dl; + ret->get_pdcp_count_ul = nr_pdcp_entity_get_count_ul; + ret->set_pdcp_count_dl = nr_pdcp_entity_set_count_dl; + ret->set_pdcp_count_ul = nr_pdcp_entity_set_count_ul; + return ret; } diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h index 7f1297ac3e..84ecce8997 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h @@ -55,6 +55,11 @@ typedef struct { uint8_t ciphering_key[NR_K_KEY_SIZE]; } nr_pdcp_entity_security_keys_and_algos_t; +typedef struct { + uint32_t sn; + uint32_t hfn; +} nr_pdcp_count_t; + typedef struct { //nr_pdcp_entity_type_t mode; /* PDU stats */ @@ -87,7 +92,6 @@ typedef struct { uint8_t mode; /* 0: PDCP AM, 1: PDCP UM, 2: PDCP TM */ } nr_pdcp_statistics_t; - typedef struct nr_pdcp_entity_t { nr_pdcp_entity_type_t type; @@ -180,6 +184,13 @@ typedef struct nr_pdcp_entity_t { /* Keep tracks of whether the PDCP entity was suspended or not */ bool entity_suspended; + + /* PDCP Count API */ + nr_pdcp_count_t (*get_pdcp_count_dl)(struct nr_pdcp_entity_t *entity); + nr_pdcp_count_t (*get_pdcp_count_ul)(struct nr_pdcp_entity_t *entity); + void (*set_pdcp_count_dl)(struct nr_pdcp_entity_t *entity, nr_pdcp_count_t count, int sn_size); + void (*set_pdcp_count_ul)(struct nr_pdcp_entity_t *entity, nr_pdcp_count_t count, int sn_size); + } nr_pdcp_entity_t; nr_pdcp_entity_t *new_nr_pdcp_entity( diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c index 4d1c0b5ba0..ce885b6b33 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c @@ -1072,3 +1072,57 @@ int nr_pdcp_get_num_ues(ue_id_t *ue_list, int len) return num_ues; } + +void nr_pdcp_count_update(ue_id_t ue_id, + rb_id_t drb_id, + nr_pdcp_count_t dl_count, + nr_pdcp_count_t ul_count, + int sn_size) +{ + nr_pdcp_manager_lock(nr_pdcp_ue_manager); + + nr_pdcp_ue_t *ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, ue_id); + if (ue == NULL) { + LOG_E(PDCP, "UE %ld not found in PDCP manager\n", ue_id); + nr_pdcp_manager_unlock(nr_pdcp_ue_manager); + return; + } + + nr_pdcp_entity_t *entity = nr_pdcp_get_rb(ue, drb_id, false); + if (entity == NULL) { + LOG_E(PDCP, "No PDCP entity found for UE %ld DRB %ld\n", ue_id, drb_id); + nr_pdcp_manager_unlock(nr_pdcp_ue_manager); + return; + } + + entity->set_pdcp_count_dl(entity, dl_count, sn_size); + entity->set_pdcp_count_ul(entity, ul_count, sn_size); + + nr_pdcp_manager_unlock(nr_pdcp_ue_manager); +} + +/** * @brief Get PDCP COUNT values (PDCP-SN and HFN) for UL and DL from the PDCP entity + * @param[in] ue_id Unique UE ID + * @param[in] rb_id Radio Bearer ID + * @param[out] ul_count UL PDCP count (SN, HFN) + * @param[out] dl_count DL PDCP count (SN, HFN) + */ +void nr_pdcp_get_drb_count_values(ue_id_t ue_id, rb_id_t rb_id, nr_pdcp_count_t *ul_count, nr_pdcp_count_t *dl_count) +{ + nr_pdcp_manager_lock(nr_pdcp_ue_manager); + + nr_pdcp_ue_t *ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, ue_id); + + nr_pdcp_entity_t *entity = nr_pdcp_get_rb(ue, rb_id, false); + + if (!entity) { + LOG_E(PDCP, "No entity found (DRB %ld)\n", rb_id); + nr_pdcp_manager_unlock(nr_pdcp_ue_manager); + return; + } + + *dl_count = entity->get_pdcp_count_dl(entity); + *ul_count = entity->get_pdcp_count_ul(entity); + + nr_pdcp_manager_unlock(nr_pdcp_ue_manager); +} diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h index 8d6a65cad6..375bd27458 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h @@ -125,4 +125,12 @@ int nr_pdcp_get_num_ues(ue_id_t *ue_list, int len); bool nr_pdcp_get_statistics(ue_id_t ue_id, int srb_flag, int rb_id, nr_pdcp_statistics_t *out); +void nr_pdcp_count_update(ue_id_t ue_id, + rb_id_t drb_id, + nr_pdcp_count_t dl_count, + nr_pdcp_count_t ul_count, + int sn_size); + +void nr_pdcp_get_drb_count_values(ue_id_t ue_id, rb_id_t rb_id, nr_pdcp_count_t *ul_count, nr_pdcp_count_t *dl_count); + #endif /* NR_PDCP_OAI_API_H */ From fc5e3ce61d17713523bfc4ee231067fc5596a3ca Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 20 Aug 2025 15:09:20 +0200 Subject: [PATCH 731/964] source-CU-CP: trigger E1 PDCP Status Request in UE Context Modification Response handler The E1 Bearer Context Modification Request shall send a PDCP Status Request IE during handover, e.g. the HO context is set to source, and it is not target, i.e. only in N2 not in F1. The current function "e1_send_bearer_updates" used to fill the E1 Request has been refactored only for the sake of this commit and to avoid duplicated and redundant code. The function itself deeper analysis and eventually a refactoring that will not be addressed in this commit. --- openair2/RRC/NR/rrc_gNB.c | 43 ++++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 75a3296b8f..4bfe0b7747 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -2091,20 +2091,34 @@ static void e1_send_bearer_updates(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, f .gNB_cu_up_ue_id = UE->rrc_ue_id, }; - for (int i = 0; i < n; i++) { - const f1ap_drb_setup_t *drb_f1 = &drbs[i]; - rrc_pdu_session_param_t *pdu_ue = find_pduSession_from_drbId(UE, drb_f1->id); - if (pdu_ue == NULL) { - LOG_E(RRC, "UE %d: UE Context Modif Response: no PDU session for DRB ID %d\n", UE->rrc_ue_id, drb_f1->id); - continue; + bool is_inter_cu_ho = UE->ho_context && UE->ho_context->source && !UE->ho_context->target; + for (int i = 0; i < MAX_DRBS_PER_UE; i++) { + int drb_id = i + 1; + DRB_nGRAN_to_mod_t drb_to_mod = {0}; + if (n > 0) { + /* DRBs to Setup in F1 UE Context Modifcation Response */ + if (i == n) + break; + const f1ap_drb_setup_t *drb_f1 = &drbs[i]; + drb_id = drb_f1->id; + fill_e1_bearer_modif(&drb_to_mod, drb_f1); + } else if (is_inter_cu_ho) { + /* On-going handover: send PDCP Status Request */ + if (UE->established_drbs[i].status == DRB_INACTIVE) + continue; + drb_to_mod.id = drb_id; + // PDCP SN Status Request + drb_to_mod.pdcp_sn_status_requested = true; + LOG_I(NR_RRC, "PDCP Status requested (drb_id=%d)\n", drb_id); } - pdu_session_to_mod_t *pdu_e1 = find_or_next_pdu_session(&req, pdu_ue->param.pdusession_id); - DevAssert(pdu_e1 != NULL); - pdu_e1->sessionId = pdu_ue->param.pdusession_id; - DRB_nGRAN_to_mod_t *drb_e1 = &pdu_e1->DRBnGRanModList[pdu_e1->numDRB2Modify]; - /* Fill E1 bearer context modification */ - fill_e1_bearer_modif(drb_e1, drb_f1); - pdu_e1->numDRB2Modify += 1; + rrc_pdu_session_param_t *pdu = find_pduSession_from_drbId(UE, drb_id); + if (!pdu) + continue; + pdu_session_to_mod_t *to_mod = find_or_next_pdu_session(&req, pdu->param.pdusession_id); + DevAssert(to_mod); + to_mod->sessionId = pdu->param.pdusession_id; + // Fill E1 DRB to Modify item + to_mod->DRBnGRanModList[to_mod->numDRB2Modify++] = drb_to_mod; } DevAssert(req.numPDUSessionsMod > 0); DevAssert(req.numPDUSessions == 0); @@ -2300,7 +2314,8 @@ static void rrc_CU_process_ue_context_modification_response(MessageDef *msg_p, i } gNB_RRC_UE_t *UE = &ue_context_p->ue_context; - if (resp->drbs_len > 0) { + bool is_inter_cu_ho = UE->ho_context && UE->ho_context->source && !UE->ho_context->target; + if (resp->drbs_len > 0 || is_inter_cu_ho) { store_du_f1u_tunnel(resp->drbs, resp->drbs_len, UE); e1_send_bearer_updates(rrc, UE, resp->drbs_len, resp->drbs); } From 44e4ebc4e29c0388e927805b44ce82f2d96cf153 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 20 Aug 2025 23:03:32 +0200 Subject: [PATCH 732/964] source-CU-UP: fill PDCP Status in response upon reception of E1 Bearer Context Modification Request * Check presence of PDCP Status Requested in Bearer Context Modification Request * Fetch PDCP Status from PDCP entity and fill in the Bearer Context Modification Response --- openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c b/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c index 99c427cc17..ae081e4376 100644 --- a/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c +++ b/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c @@ -291,6 +291,18 @@ void e1_bearer_context_modif(const e1ap_bearer_mod_req_t *req) &security_parameters); } + // PDCP Status Information requested + if (to_modif->pdcp_sn_status_requested) { + modified->pdcp_status = malloc_or_fail(sizeof(*modified->pdcp_status)); + nr_pdcp_count_t dl_count = {0}; + nr_pdcp_count_t ul_count = {0}; + nr_pdcp_get_drb_count_values(req->gNB_cu_cp_ue_id, to_modif->id, &ul_count, &dl_count); + modified->pdcp_status->dl_count.hfn = dl_count.hfn; + modified->pdcp_status->dl_count.sn = dl_count.sn; + modified->pdcp_status->ul_count.hfn = ul_count.hfn; + modified->pdcp_status->ul_count.sn = ul_count.sn; + } + if (f1inst < 0) // no F1-U? continue; // nothing to do @@ -300,6 +312,7 @@ void e1_bearer_context_modif(const e1ap_bearer_mod_req_t *req) in_addr_t addr = to_modif->DlUpParamList[k].tl_info.tlAddress; GtpuUpdateTunnelOutgoingAddressAndTeid(f1inst, req->gNB_cu_cp_ue_id, to_modif->id, addr, to_modif->DlUpParamList[k].tl_info.teId); } + } } From badb0c561a6cc1f6eec5331d34d7acb3ecad26b5 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 20 Aug 2025 23:00:49 +0200 Subject: [PATCH 733/964] source-CU-CP: trigger UL NG RAN Status Transfer upon reception of PDCP Status in E1 Bearer Context Modification Response Once fetched the PDCP Status from the PDCP entity over E1, the CU-CP triggers the NG RAN Status Transfer procedure to transfer the PDCP Status to the target CU. This commit is also introducing the RRC callback. --- openair2/RRC/NR/rrc_gNB.c | 15 +++++++++- openair2/RRC/NR/rrc_gNB_NGAP.c | 46 ++++++++++++++++++++++++++++++ openair2/RRC/NR/rrc_gNB_NGAP.h | 2 ++ openair2/RRC/NR/rrc_gNB_mobility.c | 1 + openair2/RRC/NR/rrc_gNB_mobility.h | 4 +++ 5 files changed, 67 insertions(+), 1 deletion(-) diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 4bfe0b7747..7e6cd00097 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -2600,10 +2600,23 @@ void rrc_gNB_process_e1_bearer_context_modif_resp(const e1ap_bearer_modif_resp_t return; } - // there is not really anything to do here as of now + int n_drb_mod = 0; + e1_pdcp_status_info_t pdcp_status[MAX_DRBS_PER_UE] = {0}; for (int i = 0; i < resp->numPDUSessionsMod; ++i) { const pdu_session_modif_t *pdu = &resp->pduSessionMod[i]; LOG_I(RRC, "UE %d: PDU session ID %ld modified %d bearers\n", resp->gNB_cu_cp_ue_id, pdu->id, pdu->numDRBModified); + for (int j = 0; j < pdu->numDRBModified; j++) { + // Trigger UL RAN Status Transfer + if (pdu->DRBnGRanModList[j].pdcp_status) { + pdcp_status[n_drb_mod++] = *pdu->DRBnGRanModList[j].pdcp_status; + } + } + } + if (n_drb_mod) { + LOG_I(NR_RRC, "UE %d: received PDU Status Info - send UL RAN Status Transfer\n", resp->gNB_cu_cp_ue_id); + gNB_RRC_UE_t *ue = &ue_context_p->ue_context; + if (ue->ho_context && ue->ho_context->source) + ue->ho_context->source->ho_status_transfer(rrc, ue, n_drb_mod, pdcp_status); } } diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index 961191d171..e845369951 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -1165,6 +1165,52 @@ void rrc_gNB_free_Handover_Request(ngap_handover_request_t *msg) free(msg->mobility_restriction); } +/** @brief Send NG Uplink RAN Status Transfer message (8.4.6 3GPP TS 38.413) + * Direction: source NG-RAN node -> AMF */ +int rrc_gNB_send_NGAP_ul_ran_status_transfer(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const int n_to_mod, const e1_pdcp_status_info_t *pdcp_status) +{ + AssertFatal(UE != NULL, "UE context is NULL\n"); + + LOG_I(NR_RRC, + "Sending NGAP Uplink RAN Status Transfer (AMF_UE_NGAP_ID=%" PRIu64 ", GNB_UE_NGAP_ID=%u)\n", + UE->amf_ue_ngap_id, + UE->rrc_ue_id); + + ngap_ran_status_transfer_t msg = { + .amf_ue_ngap_id = UE->amf_ue_ngap_id, + .gnb_ue_ngap_id = UE->rrc_ue_id, + }; + + // Loop through DRBs and extract COUNT values + for (int i = 0; i < n_to_mod; ++i) { + drb_t *drb = &UE->established_drbs[i]; + if (!drb->status) + continue; + + bool sn_length_18 = rrc->pdcp_config.drb.sn_size == 18; + + ngap_drb_status_t *item = &msg.ran_status.drb_status_list[msg.ran_status.nb_drb++]; + item->drb_id = drb->drb_id; + + const e1_pdcp_count_t *ul_pdcp = &pdcp_status[i].ul_count; + const e1_pdcp_count_t *dl_pdcp = &pdcp_status[i].dl_count; + + item->ul_count.pdcp_sn = ul_pdcp->sn; + item->ul_count.hfn = ul_pdcp->hfn; + item->ul_count.sn_len = sn_length_18 ? NGAP_SN_LENGTH_18 : NGAP_SN_LENGTH_12; + + item->dl_count.pdcp_sn = dl_pdcp->sn; + item->dl_count.hfn = dl_pdcp->hfn; + item->dl_count.sn_len = sn_length_18 ? NGAP_SN_LENGTH_18 : NGAP_SN_LENGTH_12; + } + + MessageDef *msg_p = itti_alloc_new_message(TASK_RRC_GNB, 0, NGAP_UL_RAN_STATUS_TRANSFER); + NGAP_UL_RAN_STATUS_TRANSFER(msg_p) = msg; + itti_send_msg_to_task(TASK_NGAP, rrc->module_id, msg_p); + + return 0; +} + /** @brief Process NG Handover Command on Source gNB */ void rrc_gNB_process_HandoverCommand(gNB_RRC_INST *rrc, const ngap_handover_command_t *msg) { diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.h b/openair2/RRC/NR/rrc_gNB_NGAP.h index 4d44b7197c..babd82cb01 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.h +++ b/openair2/RRC/NR/rrc_gNB_NGAP.h @@ -106,4 +106,6 @@ void rrc_gNB_free_Handover_Command(ngap_handover_command_t *msg); void rrc_gNB_send_NGAP_HANDOVER_NOTIFY(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE); +int rrc_gNB_send_NGAP_ul_ran_status_transfer(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const int n_to_mod, const e1_pdcp_status_info_t *pdcp_status); + #endif diff --git a/openair2/RRC/NR/rrc_gNB_mobility.c b/openair2/RRC/NR/rrc_gNB_mobility.c index 42214ecc55..614c27e242 100644 --- a/openair2/RRC/NR/rrc_gNB_mobility.c +++ b/openair2/RRC/NR/rrc_gNB_mobility.c @@ -545,6 +545,7 @@ void nr_rrc_trigger_n2_ho(gNB_RRC_INST *rrc, ue->ho_context = alloc_ho_ctx(HO_CTX_SOURCE); ue->ho_context->source->du = get_du_for_ue(rrc, ue->rrc_ue_id); + ue->ho_context->source->ho_status_transfer = rrc_gNB_send_NGAP_ul_ran_status_transfer; rrc_gNB_send_NGAP_HANDOVER_REQUIRED(rrc, ue, neighbour_config, hoPrepInfo); free_byte_array(hoPrepInfo); diff --git a/openair2/RRC/NR/rrc_gNB_mobility.h b/openair2/RRC/NR/rrc_gNB_mobility.h index db0645c5e3..40072abb2d 100644 --- a/openair2/RRC/NR/rrc_gNB_mobility.h +++ b/openair2/RRC/NR/rrc_gNB_mobility.h @@ -33,6 +33,8 @@ typedef struct nr_rrc_du_container_t nr_rrc_du_container_t; typedef struct NR_CellGroupConfig NR_CellGroupConfig_t; typedef void (*ho_cancel_t)(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue); +typedef int (*ho_status_transfer_t)(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const int n_to_mod, const e1_pdcp_status_info_t *pdcp_status); + typedef struct nr_ho_source_cu { /// pointer to the (source) DU structure const nr_rrc_du_container_t *du; @@ -48,6 +50,8 @@ typedef struct nr_ho_source_cu { /// function pointer to announce the handover cancellation, e.g., /// reestablishment ho_cancel_t ho_cancel; + /// status transfer + ho_status_transfer_t ho_status_transfer; } nr_ho_source_cu_t; /* acknowledgement of handover request. buf+len is the RRC Reconfiguration */ From a82353f42a63b197104c0d7810aeb4b19254ffaf Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 20 Aug 2025 23:00:38 +0200 Subject: [PATCH 734/964] target-CU-CP: Add RRC handler NG DL RAN Status Transfer --- openair2/RRC/NR/rrc_gNB.c | 4 +++ openair2/RRC/NR/rrc_gNB_NGAP.c | 48 ++++++++++++++++++++++++++++++++++ openair2/RRC/NR/rrc_gNB_NGAP.h | 2 ++ 3 files changed, 54 insertions(+) diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 7e6cd00097..de03f306cb 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -2854,6 +2854,10 @@ void *rrc_gnb_task(void *args_p) { rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND(msg_p, instance); break; + case NGAP_DL_RAN_STATUS_TRANSFER: + rrc_gNB_process_NGAP_DL_RAN_STATUS_TRANSFER(msg_p, instance); + break; + /* Messages from F1AP task */ case F1AP_SETUP_REQ: AssertFatal(!NODE_IS_DU(RC.nrrrc[instance]->node_type), "should not receive F1AP_SETUP_REQUEST in DU!\n"); diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index e845369951..bddd0521d2 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -1605,3 +1605,51 @@ void rrc_gNB_send_NGAP_HANDOVER_REQUIRED(gNB_RRC_INST *rrc, NGAP_HANDOVER_REQUIRED(msg_p) = msg; itti_send_msg_to_task(TASK_NGAP, rrc->module_id, msg_p); } + +int rrc_gNB_process_NGAP_DL_RAN_STATUS_TRANSFER(MessageDef *msg_p, instance_t instance) +{ + const ngap_ran_status_transfer_t *cmd = &NGAP_DL_RAN_STATUS_TRANSFER(msg_p); + gNB_RRC_INST *rrc = RC.nrrrc[instance]; + rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(rrc, cmd->gnb_ue_ngap_id); + + if (!ue_context_p) { + LOG_E(NR_RRC, "[gNB %ld] No UE context for gNB_ue_ngap_id %u\n", instance, cmd->gnb_ue_ngap_id); + return -1; + } + + gNB_RRC_UE_t *UE = &ue_context_p->ue_context; + LOG_I(NR_RRC, + "[gNB %ld] DL RAN Status Transfer for gNB_ue_ngap_id %u AMF_UE_NGAP_ID %lu\n", + instance, + cmd->gnb_ue_ngap_id, + cmd->amf_ue_ngap_id); + + for (int i = 0; i < cmd->ran_status.nb_drb; ++i) { + const ngap_drb_status_t *s = &cmd->ran_status.drb_status_list[i]; + LOG_I(NR_RRC, + "DL RAN Status Transfer - DRB ID %d:\n" + " UL COUNT: PDCP SN = %u, HFN = %u (%s)\n" + " DL COUNT: PDCP SN = %u, HFN = %u (%s)\n", + s->drb_id, + s->ul_count.pdcp_sn, + s->ul_count.hfn, + s->ul_count.sn_len == NGAP_SN_LENGTH_18 ? "18-bit" : "12-bit", + s->dl_count.pdcp_sn, + s->dl_count.hfn, + s->dl_count.sn_len == NGAP_SN_LENGTH_18 ? "18-bit" : "12-bit"); + + // Send to PDCP layer + for (int j = 0; j < MAX_DRBS_PER_UE; j++) { + if (UE->established_drbs[j].drb_id == s->drb_id) + nr_pdcp_update_ran_status(UE->rrc_ue_id, + s->drb_id, + s->ul_count.pdcp_sn, + s->ul_count.hfn, + s->dl_count.pdcp_sn, + s->dl_count.hfn, + s->dl_count.sn_len == NGAP_SN_LENGTH_18); + } + } + + return 0; +} diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.h b/openair2/RRC/NR/rrc_gNB_NGAP.h index babd82cb01..d1867173a2 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.h +++ b/openair2/RRC/NR/rrc_gNB_NGAP.h @@ -108,4 +108,6 @@ void rrc_gNB_send_NGAP_HANDOVER_NOTIFY(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE); int rrc_gNB_send_NGAP_ul_ran_status_transfer(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const int n_to_mod, const e1_pdcp_status_info_t *pdcp_status); +int rrc_gNB_process_NGAP_DL_RAN_STATUS_TRANSFER(MessageDef *msg_p, instance_t instance); + #endif From 4facb4d63534a5f88c32eae6851dbcd6caed61c4 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 20 Aug 2025 23:29:23 +0200 Subject: [PATCH 735/964] target-CU-CP: Transfer PDCP Count to target-CU-UP Upon reception of NG RAN Status at the target CU-CP, send PDCP Status via E1 Bearer Context Modification to the target CU-UP and update PDCP Count upon reception of the message. For the sake of simplicity, re-used and extended legacy e1_send_bearer_updates. Further refactoring is not addressed in this commit. --- openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c | 14 +++++++++ openair2/RRC/NR/nr_rrc_proto.h | 1 + openair2/RRC/NR/rrc_gNB.c | 32 +++++++++++++++++---- openair2/RRC/NR/rrc_gNB_NGAP.c | 11 +------ 4 files changed, 43 insertions(+), 15 deletions(-) diff --git a/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c b/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c index ae081e4376..b19ccceb22 100644 --- a/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c +++ b/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c @@ -303,6 +303,20 @@ void e1_bearer_context_modif(const e1ap_bearer_mod_req_t *req) modified->pdcp_status->ul_count.sn = ul_count.sn; } + // PDCP Status received (from source CU-UP) + if (to_modif->pdcp_status) { + DevAssert(to_modif->pdcp_config); + DevAssert(to_modif->pdcp_config->pDCP_SN_Size_DL == to_modif->pdcp_config->pDCP_SN_Size_UL); + bool is_sn_len_18 = to_modif->pdcp_config->pDCP_SN_Size_DL == NR_PDCP_Config__drb__pdcp_SN_SizeDL_len18bits; + nr_pdcp_count_t dl_count = { .hfn = to_modif->pdcp_status->dl_count.hfn, .sn = to_modif->pdcp_status->dl_count.sn}; + nr_pdcp_count_t ul_count = { .hfn = to_modif->pdcp_status->ul_count.hfn, .sn = to_modif->pdcp_status->ul_count.sn}; + nr_pdcp_count_update(req->gNB_cu_cp_ue_id, + to_modif->id, + dl_count, + ul_count, + is_sn_len_18 ? LONG_SN_SIZE : SHORT_SN_SIZE); + } + if (f1inst < 0) // no F1-U? continue; // nothing to do diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h index bbaaaf5774..0c545575ba 100644 --- a/openair2/RRC/NR/nr_rrc_proto.h +++ b/openair2/RRC/NR/nr_rrc_proto.h @@ -128,5 +128,6 @@ void openair_rrc_gNB_configuration(gNB_RRC_INST *rrc, gNB_RrcConfigurationReq *c NR_SRB_ToAddModList_t *createSRBlist(gNB_RRC_UE_t *ue, uint8_t reestablish); NR_DRB_ToAddModList_t *createDRBlist(gNB_RRC_UE_t *ue, bool reestablish); void activate_srb(gNB_RRC_UE_t *UE, int srb_id); +void e1_send_bearer_updates(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, f1ap_drb_setup_t *drbs, const ngap_drb_status_t *drb_status); #endif diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index de03f306cb..797aa19d88 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -2076,9 +2076,28 @@ static void store_du_f1u_tunnel(const f1ap_drb_setup_t *drbs, int n, gNB_RRC_UE_ } } -/* \brief use list of DRBs and send the corresponding bearer update message via - * E1 to the CU of this UE. Also updates TEID info internally */ -static void e1_send_bearer_updates(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, f1ap_drb_setup_t *drbs) +static void fill_e1_bearer_modif_pdcp_status(gNB_RRC_UE_t *UE, + DRB_nGRAN_to_mod_t *drb_to_mod, + const int drb_id, + const bool um_on_default_drb, + const ngap_drb_status_t *drb_status) +{ + DevAssert(drb_status); + drb_to_mod->id = drb_id; + drb_to_mod->pdcp_sn_status_requested = false; + // PDCP SN Status Information + drb_to_mod->pdcp_config = calloc_or_fail(1, sizeof(*drb_to_mod->pdcp_config)); + set_bearer_context_pdcp_config(drb_to_mod->pdcp_config, get_drb(UE, drb_id), um_on_default_drb); + drb_to_mod->pdcp_status = calloc_or_fail(1, sizeof(*drb_to_mod->pdcp_status)); + drb_to_mod->pdcp_status->dl_count.hfn = drb_status->dl_count.hfn; + drb_to_mod->pdcp_status->dl_count.sn = drb_status->dl_count.pdcp_sn; + drb_to_mod->pdcp_status->ul_count.hfn = drb_status->ul_count.hfn; + drb_to_mod->pdcp_status->ul_count.sn = drb_status->ul_count.pdcp_sn; +} + +/** @brief Fill and send Bearer Context Modification Request with: + * (1) from F1 UE Context DRB to setup list, or (2) with PDCP Status Request */ +void e1_send_bearer_updates(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, f1ap_drb_setup_t *drbs, const ngap_drb_status_t *drb_status) { // Quit bearer updates if no CU-UP is associated if (!is_cuup_associated(rrc)) { @@ -2110,6 +2129,9 @@ static void e1_send_bearer_updates(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, f // PDCP SN Status Request drb_to_mod.pdcp_sn_status_requested = true; LOG_I(NR_RRC, "PDCP Status requested (drb_id=%d)\n", drb_id); + } else if (drb_status) { + /* On-going handover: send PDCP Status */ + fill_e1_bearer_modif_pdcp_status(UE, &drb_to_mod, drb_id, rrc->configuration.um_on_default_drb, drb_status); } rrc_pdu_session_param_t *pdu = find_pduSession_from_drbId(UE, drb_id); if (!pdu) @@ -2183,7 +2205,7 @@ static void rrc_CU_process_ue_context_setup_response(MessageDef *msg_p, instance AssertFatal(UE->Srb[1].Active && UE->Srb[2].Active, "SRBs 1 and 2 must be active during DRB Establishment"); store_du_f1u_tunnel(resp->drbs, resp->drbs_len, UE); if (num_drb == 0) - e1_send_bearer_updates(rrc, UE, resp->drbs_len, resp->drbs); + e1_send_bearer_updates(rrc, UE, resp->drbs_len, resp->drbs, NULL); else cuup_notify_reestablishment(rrc, UE); } @@ -2317,7 +2339,7 @@ static void rrc_CU_process_ue_context_modification_response(MessageDef *msg_p, i bool is_inter_cu_ho = UE->ho_context && UE->ho_context->source && !UE->ho_context->target; if (resp->drbs_len > 0 || is_inter_cu_ho) { store_du_f1u_tunnel(resp->drbs, resp->drbs_len, UE); - e1_send_bearer_updates(rrc, UE, resp->drbs_len, resp->drbs); + e1_send_bearer_updates(rrc, UE, resp->drbs_len, resp->drbs, NULL); } if (resp->du_to_cu_rrc_info) { diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index bddd0521d2..d4068b46a5 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -1639,16 +1639,7 @@ int rrc_gNB_process_NGAP_DL_RAN_STATUS_TRANSFER(MessageDef *msg_p, instance_t in s->dl_count.sn_len == NGAP_SN_LENGTH_18 ? "18-bit" : "12-bit"); // Send to PDCP layer - for (int j = 0; j < MAX_DRBS_PER_UE; j++) { - if (UE->established_drbs[j].drb_id == s->drb_id) - nr_pdcp_update_ran_status(UE->rrc_ue_id, - s->drb_id, - s->ul_count.pdcp_sn, - s->ul_count.hfn, - s->dl_count.pdcp_sn, - s->dl_count.hfn, - s->dl_count.sn_len == NGAP_SN_LENGTH_18); - } + e1_send_bearer_updates(rrc, UE, 0, NULL, s); } return 0; From 85f586c76df8a8750191a86b56e801aee5f83312 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Fri, 12 Sep 2025 17:18:38 +0200 Subject: [PATCH 736/964] Add N2 Handover Cancel (8.4.5 of 3GPP TS 38.413) This commit completes the NGAP Mobility Management procedure for N2 handover. Upon failure on source gNB the Handover Cancel message is sent to the AMF which in return responds with an ack. --- openair2/COMMON/ngap_messages_def.h | 2 + openair2/COMMON/ngap_messages_types.h | 20 +++++++ openair2/RRC/NR/rrc_gNB_NGAP.c | 24 ++++++++ openair2/RRC/NR/rrc_gNB_NGAP.h | 1 + openair2/RRC/NR/rrc_gNB_mobility.c | 11 ++++ openair3/NGAP/ngap_gNB.c | 55 ++++++++++++++++++ openair3/NGAP/ngap_gNB_handlers.c | 42 +++++++++++++- openair3/NGAP/ngap_gNB_mobility_management.c | 59 ++++++++++++++++++++ openair3/NGAP/ngap_gNB_mobility_management.h | 2 + 9 files changed, 215 insertions(+), 1 deletion(-) diff --git a/openair2/COMMON/ngap_messages_def.h b/openair2/COMMON/ngap_messages_def.h index bdeb2455b4..98c1f82260 100644 --- a/openair2/COMMON/ngap_messages_def.h +++ b/openair2/COMMON/ngap_messages_def.h @@ -75,6 +75,7 @@ MESSAGE_DEF(NGAP_HANDOVER_REQUIRED, MESSAGE_PRIORITY_MED, ngap_handover_required MESSAGE_DEF(NGAP_HANDOVER_FAILURE, MESSAGE_PRIORITY_MED, ngap_handover_failure_t, ngap_handover_failure) MESSAGE_DEF(NGAP_HANDOVER_REQUEST_ACKNOWLEDGE, MESSAGE_PRIORITY_MED, ngap_handover_request_ack_t, ngap_handover_request_ack) MESSAGE_DEF(NGAP_HANDOVER_NOTIFY, MESSAGE_PRIORITY_MED, ngap_handover_notify_t, ngap_handover_notify) +MESSAGE_DEF(NGAP_HANDOVER_CANCEL, MESSAGE_PRIORITY_MED, ngap_handover_cancel_t, ngap_handover_cancel) MESSAGE_DEF(NGAP_UL_RAN_STATUS_TRANSFER, MESSAGE_PRIORITY_MED, ngap_ran_status_transfer_t, ngap_ul_ran_status_transfer) MESSAGE_DEF(NGAP_DL_RAN_STATUS_TRANSFER, MESSAGE_PRIORITY_MED, ngap_ran_status_transfer_t, ngap_dl_ran_status_transfer) @@ -89,6 +90,7 @@ MESSAGE_DEF(NGAP_PDUSESSION_RELEASE_COMMAND , MESSAGE_PRIORITY_MED, ngap_pdu MESSAGE_DEF(NGAP_UE_CONTEXT_RELEASE_COMMAND, MESSAGE_PRIORITY_MED, ngap_ue_release_command_t , ngap_ue_release_command) MESSAGE_DEF(NGAP_HANDOVER_REQUEST, MESSAGE_PRIORITY_MED, ngap_handover_request_t, ngap_handover_request) MESSAGE_DEF(NGAP_HANDOVER_COMMAND, MESSAGE_PRIORITY_MED, ngap_handover_command_t, ngap_handover_command) +MESSAGE_DEF(NGAP_HANDOVER_CANCEL_ACK, MESSAGE_PRIORITY_MED, ngap_handover_cancel_ack_t, ngap_handover_cancel_ack) /* NGAP <-> RRC messages (can be initiated either by MME or gNB) */ MESSAGE_DEF(NGAP_UE_CONTEXT_RELEASE_REQ , MESSAGE_PRIORITY_MED, ngap_ue_release_req_t , ngap_ue_release_req) diff --git a/openair2/COMMON/ngap_messages_types.h b/openair2/COMMON/ngap_messages_types.h index a8c2bab58a..ef25f6997d 100644 --- a/openair2/COMMON/ngap_messages_types.h +++ b/openair2/COMMON/ngap_messages_types.h @@ -71,6 +71,8 @@ #define NGAP_HANDOVER_REQUEST_ACKNOWLEDGE(mSGpTR) (mSGpTR)->ittiMsg.ngap_handover_request_ack #define NGAP_HANDOVER_COMMAND(mSGpTR) (mSGpTR)->ittiMsg.ngap_handover_command #define NGAP_HANDOVER_NOTIFY(mSGpTR) (mSGpTR)->ittiMsg.ngap_handover_notify +#define NGAP_HANDOVER_CANCEL(mSGpTR) (mSGpTR)->ittiMsg.ngap_handover_cancel +#define NGAP_HANDOVER_CANCEL_ACK(mSGpTR) (mSGpTR)->ittiMsg.ngap_handover_cancel_ack #define NGAP_UE_CONTEXT_RELEASE_REQ(mSGpTR) (mSGpTR)->ittiMsg.ngap_ue_release_req #define NGAP_PDUSESSION_RELEASE_COMMAND(mSGpTR) (mSGpTR)->ittiMsg.ngap_pdusession_release_command @@ -701,6 +703,24 @@ typedef struct { user_location_information_t user_info; } ngap_handover_notify_t; +/* 9.2.3.11 3GPP TS 38.413 */ +typedef struct { + // RAN UE NGAP ID + uint32_t gNB_ue_ngap_id; + // AMF UE NGAP ID + uint64_t amf_ue_ngap_id; + // Cause + ngap_cause_t cause; +} ngap_handover_cancel_t; + +/* 9.2.3.12 3GPP TS 38.413 */ +typedef struct { + // RAN UE NGAP ID + uint32_t gNB_ue_ngap_id; + // AMF UE NGAP ID + uint64_t amf_ue_ngap_id; +} ngap_handover_cancel_ack_t; + typedef struct ngap_ue_cap_info_ind_s { uint32_t gNB_ue_ngap_id; byte_array_t ue_radio_cap; diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index d4068b46a5..be7dce5ca1 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -1403,6 +1403,30 @@ void rrc_gNB_send_NGAP_HANDOVER_NOTIFY(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE) itti_send_msg_to_task(TASK_NGAP, rrc->module_id, msg_p); } +/** @brief Prepare NG Handover Cancel (source NG-RAN) and inform NGAP (N2-based HO only) + * 3GPP TS 38.413 §8.4.5 (Handover Cancellation) - source NG-RAN -> AMF + * 3GPP TS 38.413 §9.2.3.11 (HANDOVER CANCEL) + * @param rrc CU/RRC instance + * @param UE UE context + * @param cause cancellation cause */ +void rrc_gNB_send_NGAP_HANDOVER_CANCEL(int module_id, gNB_RRC_UE_t *UE, ngap_cause_t cause) +{ + DevAssert(UE != NULL); + + LOG_I(NR_RRC, "Triggering NGAP Handover Cancel (gNB_ue_ngap_id=%d, amf_ue_ngap_id=%ld)\n", UE->rrc_ue_id, UE->amf_ue_ngap_id); + + MessageDef *msg_p = itti_alloc_new_message(TASK_RRC_GNB, 0, NGAP_HANDOVER_CANCEL); + ngap_handover_cancel_t *ho_cancel = &NGAP_HANDOVER_CANCEL(msg_p); + memset(ho_cancel, 0, sizeof(*ho_cancel)); + + /* Mandatory IEs (38.413 §9.2.3.11) */ + ho_cancel->gNB_ue_ngap_id = UE->rrc_ue_id; + ho_cancel->amf_ue_ngap_id = UE->amf_ue_ngap_id; + ho_cancel->cause = cause; + + itti_send_msg_to_task(TASK_NGAP, module_id, msg_p); +} + void rrc_gNB_send_NGAP_PDUSESSION_RELEASE_RESPONSE(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, uint8_t xid) { int pdu_sessions_released = 0; diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.h b/openair2/RRC/NR/rrc_gNB_NGAP.h index d1867173a2..b90d9a1493 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.h +++ b/openair2/RRC/NR/rrc_gNB_NGAP.h @@ -105,6 +105,7 @@ void rrc_gNB_process_HandoverCommand(gNB_RRC_INST *rrc, const ngap_handover_comm void rrc_gNB_free_Handover_Command(ngap_handover_command_t *msg); void rrc_gNB_send_NGAP_HANDOVER_NOTIFY(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE); +void rrc_gNB_send_NGAP_HANDOVER_CANCEL(int module_id, gNB_RRC_UE_t *UE, ngap_cause_t cause); int rrc_gNB_send_NGAP_ul_ran_status_transfer(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const int n_to_mod, const e1_pdcp_status_info_t *pdcp_status); diff --git a/openair2/RRC/NR/rrc_gNB_mobility.c b/openair2/RRC/NR/rrc_gNB_mobility.c index 614c27e242..07b742e16c 100644 --- a/openair2/RRC/NR/rrc_gNB_mobility.c +++ b/openair2/RRC/NR/rrc_gNB_mobility.c @@ -489,6 +489,16 @@ static void nr_rrc_n2_ho_complete(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE) rrc_gNB_send_NGAP_HANDOVER_NOTIFY(rrc, UE); } +/** @brief This callback is used by the source gNB to inform the AMF + * about the cancellation of an ongoing handover */ +static void nr_rrc_n2_ho_cancel(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE) +{ + DevAssert(UE->ho_context); + DevAssert(UE->ho_context->source); + ngap_cause_t cause = {.type = NGAP_CAUSE_RADIO_NETWORK, .value = NGAP_CAUSE_RADIO_NETWORK_HANDOVER_CANCELLED}; + rrc_gNB_send_NGAP_HANDOVER_CANCEL(rrc->module_id, UE, cause); +} + /** @brief Callback function to trigger NG Handover Failure on the target gNB, to inform the AMF * that the preparation of resources has failed (e.g. unsatisfied criteria, gNB is already loaded). * This message represents an Unsuccessful Outcome of the Handover Resource Allocation */ @@ -546,6 +556,7 @@ void nr_rrc_trigger_n2_ho(gNB_RRC_INST *rrc, ue->ho_context = alloc_ho_ctx(HO_CTX_SOURCE); ue->ho_context->source->du = get_du_for_ue(rrc, ue->rrc_ue_id); ue->ho_context->source->ho_status_transfer = rrc_gNB_send_NGAP_ul_ran_status_transfer; + ue->ho_context->source->ho_cancel = nr_rrc_n2_ho_cancel; rrc_gNB_send_NGAP_HANDOVER_REQUIRED(rrc, ue, neighbour_config, hoPrepInfo); free_byte_array(hoPrepInfo); diff --git a/openair3/NGAP/ngap_gNB.c b/openair3/NGAP/ngap_gNB.c index afa69c4c9d..8c9ac6a973 100644 --- a/openair3/NGAP/ngap_gNB.c +++ b/openair3/NGAP/ngap_gNB.c @@ -463,6 +463,57 @@ static int ngap_gNB_handover_notify(instance_t instance, const ngap_handover_not return 0; } +/** @brief NGAP: Handover Cancel callback */ +static int ngap_gNB_handover_cancel(instance_t instance, const ngap_handover_cancel_t *msg) +{ + DevAssert(msg != NULL); + byte_array_t ba = {.buf = NULL, .len = 0}; + + // Retrieve NGAP gNB instance + ngap_gNB_instance_t *ngap_gNB_instance_p = ngap_gNB_get_instance(instance); + DevAssert(ngap_gNB_instance_p != NULL); + + // we must have the UE context by RAN UE NGAP ID + ngap_gNB_ue_context_t *ue_context_p = ngap_get_ue_context(msg->gNB_ue_ngap_id); + if (ue_context_p == NULL) { + NGAP_ERROR("Failed to encode Handover Cancel: no UE context for gNB_ue_ngap_id=%d\n", msg->gNB_ue_ngap_id); + return -1; + } + + if (ue_context_p->gNB_ue_ngap_id != msg->gNB_ue_ngap_id) { + NGAP_ERROR("Failed to encode Handover Cancel: mismatched gNB_ue_ngap_id=%d\n", msg->gNB_ue_ngap_id); + return -1; + } + + if (ue_context_p->amf_ue_ngap_id != msg->amf_ue_ngap_id) { + NGAP_ERROR("Failed to encode Handover Cancel: mismatched amf_ue_ngap_id=%ld\n", msg->amf_ue_ngap_id); + return -1; + } + + /* Encode NGAP PDU */ + NGAP_NGAP_PDU_t *pdu = encode_ng_handover_cancel(msg); + if (pdu == NULL) { + NGAP_ERROR("Failed to encode NG Handover Cancel\n"); + return -1; + } + + if (ngap_gNB_encode_pdu(pdu, &ba.buf, (uint32_t *)&ba.len) < 0) { + NGAP_ERROR("Failed to encode NG Handover Cancel message PDU\n"); + ASN_STRUCT_FREE(asn_DEF_NGAP_NGAP_PDU, pdu); + return -1; + } + ASN_STRUCT_FREE(asn_DEF_NGAP_NGAP_PDU, pdu); + + /* UE-associated signalling -> use the UE's allocated SCTP stream */ + ngap_gNB_itti_send_sctp_data_req(ngap_gNB_instance_p->instance, + ue_context_p->amf_ref->assoc_id, + ba.buf, + ba.len, + ue_context_p->tx_stream); + + return 0; +} + int ngap_gNB_handle_ul_ran_status_transfer(instance_t instance, const ngap_ran_status_transfer_t *msg) { NGAP_DEBUG("Triggered UL RAN Status Transfer\n"); @@ -587,6 +638,10 @@ void *ngap_gNB_process_itti_msg(void *notUsed) { ngap_gNB_handover_notify(instance, &NGAP_HANDOVER_NOTIFY(received_msg)); break; + case NGAP_HANDOVER_CANCEL: + ngap_gNB_handover_cancel(instance, &NGAP_HANDOVER_CANCEL(received_msg)); + break; + case NGAP_UL_RAN_STATUS_TRANSFER: ngap_gNB_handle_ul_ran_status_transfer(instance, &NGAP_UL_RAN_STATUS_TRANSFER(received_msg)); break; diff --git a/openair3/NGAP/ngap_gNB_handlers.c b/openair3/NGAP/ngap_gNB_handlers.c index 0257e49698..95c2dd45a7 100644 --- a/openair3/NGAP/ngap_gNB_handlers.c +++ b/openair3/NGAP/ngap_gNB_handlers.c @@ -1051,6 +1051,46 @@ static int ngap_gNB_handle_handover_command(sctp_assoc_t assoc_id, uint32_t stre return 0; } +/** @brief Handler for NG Handover Cancel Acknowledge */ +static int ngap_gNB_handle_handover_cancel_ack(sctp_assoc_t assoc_id, uint32_t stream, NGAP_NGAP_PDU_t *pdu) +{ + NGAP_INFO("Received NG Handover Cancel Acknowledge\n"); + ngap_gNB_amf_data_t *amf_desc_p = NULL; + DevAssert(pdu != NULL); + + amf_desc_p = ngap_gNB_get_AMF(NULL, assoc_id, 0); + if (amf_desc_p == NULL) { + NGAP_ERROR("[SCTP %u] Received Handover Cancel Ack for non-existing AMF context\n", assoc_id); + return -1; + } + + MessageDef *message_p = itti_alloc_new_message(TASK_NGAP, 0, NGAP_HANDOVER_CANCEL_ACK); + ngap_handover_cancel_ack_t *msg = &NGAP_HANDOVER_CANCEL_ACK(message_p); + + if (decode_ng_handover_cancel_ack(msg, pdu) < 0) { + NGAP_ERROR("Failed to decode NG Handover Cancel Acknowledge\n"); + itti_free(TASK_NGAP, message_p); + return -1; + } + + ngap_gNB_ue_context_t *ue_desc_p = ngap_get_ue_context(msg->gNB_ue_ngap_id); + if (!ue_desc_p) { + NGAP_ERROR("[SCTP %u] Handover Cancel Ack for unknown UE context (gNB_ue_ngap_id %d)\n", assoc_id, msg->gNB_ue_ngap_id); + itti_free(TASK_NGAP, message_p); + return -1; + } + + if (ue_desc_p->amf_ue_ngap_id != msg->amf_ue_ngap_id) { + NGAP_WARN("AMF UE NGAP ID mismatch in HO Cancel Ack (ctx %ld != msg %ld)", ue_desc_p->amf_ue_ngap_id, msg->amf_ue_ngap_id); + } + + ue_desc_p->rx_stream = stream; + + // cancel was already handled at RRC level, do not forward + + return 0; +} + static int ngap_gNB_handle_paging(sctp_assoc_t assoc_id, uint32_t stream, NGAP_NGAP_PDU_t *pdu) { ngap_gNB_amf_data_t *amf_desc_p = NULL; @@ -1484,7 +1524,7 @@ const ngap_message_decoded_callback ngap_messages_callback[][3] = { {ngap_gNB_handle_dl_ran_status_transfer, 0, 0}, /* DownlinkRANStatusTransfer */ {0, 0, 0}, /* DownlinkUEAssociatedNRPPaTransport */ {ngap_gNB_handle_error_indication, 0, 0}, /* ErrorIndication */ - {0, 0, 0}, /* HandoverCancel */ + {0, ngap_gNB_handle_handover_cancel_ack, 0}, /* HandoverCancel */ {0, 0, 0}, /* HandoverNotification */ {0, ngap_gNB_handle_handover_command, 0}, /* HandoverPreparation */ {ngap_gNB_handle_handover_request, 0, 0}, /* HandoverResourceAllocation */ diff --git a/openair3/NGAP/ngap_gNB_mobility_management.c b/openair3/NGAP/ngap_gNB_mobility_management.c index 4f1383e5e0..3d281be7c9 100644 --- a/openair3/NGAP/ngap_gNB_mobility_management.c +++ b/openair3/NGAP/ngap_gNB_mobility_management.c @@ -618,6 +618,65 @@ NGAP_NGAP_PDU_t *encode_ng_handover_notify(const ngap_handover_notify_t *msg) return pdu; } +/** @brief NGAP Handover Cancel encoding (9.2.3.11 3GPP TS 38.413 Handover Cancel) + * 8.4.5 Handover Cancellation (source NG-RAN -> AMF) */ +NGAP_NGAP_PDU_t *encode_ng_handover_cancel(const ngap_handover_cancel_t *msg) +{ + DevAssert(msg != NULL); + + NGAP_NGAP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); + + pdu->present = NGAP_NGAP_PDU_PR_initiatingMessage; + asn1cCalloc(pdu->choice.initiatingMessage, head); + head->procedureCode = NGAP_ProcedureCode_id_HandoverCancel; + head->criticality = NGAP_Criticality_reject; + head->value.present = NGAP_InitiatingMessage__value_PR_HandoverCancel; + NGAP_HandoverCancel_t *out = &head->value.choice.HandoverCancel; + + // AMF UE NGAP ID (M) + asn1cSequenceAdd(out->protocolIEs.list, NGAP_HandoverCancelIEs_t, ie1); + ie1->id = NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID; + ie1->criticality = NGAP_Criticality_reject; + ie1->value.present = NGAP_HandoverCancelIEs__value_PR_AMF_UE_NGAP_ID; + asn_uint642INTEGER(&ie1->value.choice.AMF_UE_NGAP_ID, msg->amf_ue_ngap_id); + + // RAN UE NGAP ID (M) + asn1cSequenceAdd(out->protocolIEs.list, NGAP_HandoverCancelIEs_t, ie2); + ie2->id = NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID; + ie2->criticality = NGAP_Criticality_reject; + ie2->value.present = NGAP_HandoverCancelIEs__value_PR_RAN_UE_NGAP_ID; + ie2->value.choice.RAN_UE_NGAP_ID = msg->gNB_ue_ngap_id; + + // Cause (M) + asn1cSequenceAdd(out->protocolIEs.list, NGAP_HandoverCancelIEs_t, ie3); + ie3->id = NGAP_ProtocolIE_ID_id_Cause; + ie3->criticality = NGAP_Criticality_reject; + ie3->value.present = NGAP_HandoverCancelIEs__value_PR_Cause; + encode_ngap_cause(&ie3->value.choice.Cause, &msg->cause); + + return pdu; +} + +/** @brief Decode NGAP Handover Cancel Acknowledge (9.2.3.12 3GPP TS 38.413) */ +int decode_ng_handover_cancel_ack(ngap_handover_cancel_ack_t *out, const NGAP_NGAP_PDU_t *pdu) +{ + DevAssert(out != NULL); + DevAssert(pdu != NULL); + + NGAP_HandoverCancelAcknowledge_t *container = &pdu->choice.successfulOutcome->value.choice.HandoverCancelAcknowledge; + NGAP_HandoverCancelAcknowledgeIEs_t *ie; + + /* AMF UE NGAP ID (M) */ + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_HandoverCancelAcknowledgeIEs_t, ie, container, NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID, true); + asn_INTEGER2ulong(&ie->value.choice.AMF_UE_NGAP_ID, &out->amf_ue_ngap_id); + + /* RAN UE NGAP ID (M) */ + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_HandoverCancelAcknowledgeIEs_t, ie, container, NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID, true); + out->gNB_ue_ngap_id = ie->value.choice.RAN_UE_NGAP_ID; + + return 0; +} + /** @brief Encode NGAP UL RAN Status Transfer (9.2.3.14 of 3GPP TS 38.413) */ NGAP_NGAP_PDU_t *encode_ng_ul_ran_status_transfer(const ngap_ran_status_transfer_t *msg) { diff --git a/openair3/NGAP/ngap_gNB_mobility_management.h b/openair3/NGAP/ngap_gNB_mobility_management.h index b7a6f3547c..18aac7c61d 100644 --- a/openair3/NGAP/ngap_gNB_mobility_management.h +++ b/openair3/NGAP/ngap_gNB_mobility_management.h @@ -35,5 +35,7 @@ int decode_ng_handover_command(ngap_handover_command_t *msg, NGAP_NGAP_PDU_t *pd void free_ng_handover_command(ngap_handover_command_t *msg); NGAP_NGAP_PDU_t *encode_ng_handover_notify(const ngap_handover_notify_t *msg); NGAP_NGAP_PDU_t *encode_ng_ul_ran_status_transfer(const ngap_ran_status_transfer_t *msg); +NGAP_NGAP_PDU_t *encode_ng_handover_cancel(const ngap_handover_cancel_t *msg); +int decode_ng_handover_cancel_ack(ngap_handover_cancel_ack_t *out, const NGAP_NGAP_PDU_t *pdu); #endif /* NGAP_GNB_MOBILITY_MANAGEMENT_H_ */ From f9f6e96d6b0f01480b2cc8a287d3abf345456c57 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 9 Jul 2025 19:16:05 +0200 Subject: [PATCH 737/964] Add N2 handover documentation --- ci-scripts/conf_files/neighbour-config.conf | 5 + doc/RRC/rrc-dev.md | 93 ++++++- doc/RRC/rrc-usage.md | 22 +- doc/handover-tutorial.md | 146 ++++++++++ .../gnb.sa.band78.fr1.106PRB.pci0.rfsim.conf | 251 ++++++++++++++++++ .../gnb.sa.band78.fr1.106PRB.pci1.rfsim.conf | 251 ++++++++++++++++++ .../CONF/neighbour-config-rfsim.conf | 78 ++++++ 7 files changed, 843 insertions(+), 3 deletions(-) create mode 100644 targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.pci0.rfsim.conf create mode 100644 targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.pci1.rfsim.conf create mode 100644 targets/PROJECTS/GENERIC-NR-5GC/CONF/neighbour-config-rfsim.conf diff --git a/ci-scripts/conf_files/neighbour-config.conf b/ci-scripts/conf_files/neighbour-config.conf index 4d4cd8136c..a498dbf157 100644 --- a/ci-scripts/conf_files/neighbour-config.conf +++ b/ci-scripts/conf_files/neighbour-config.conf @@ -1,3 +1,8 @@ +############################################################ +# gNB-to-gNB neighbour list + measurement configuration # +# for the 2-cell rfsim setup (gNB_ID 0xe00 & 0xb00) # +############################################################ + neighbour_list = ( ########################################################## # Entry USED BY gNB_ID = 0xe00 (nr_cellid = 1) # diff --git a/doc/RRC/rrc-dev.md b/doc/RRC/rrc-dev.md index e6eb3f97e0..43f0c7ed93 100644 --- a/doc/RRC/rrc-dev.md +++ b/doc/RRC/rrc-dev.md @@ -210,7 +210,7 @@ sequenceDiagram end ``` -## Handover +## Inter-DU Handover (F1) The basic handover (HO) structure is as follows. In order to support various handover "message passing implementation" (F1AP, NGAP, XnAP), RRC employs @@ -264,6 +264,94 @@ sequenceDiagram sdu->>cucp: F1AP UE Context Release Complete Note over ue,tdu: UE active on target DU ``` +## Inter-gNB Handover (N2) + +This is an inter-NG-RAN procedure. The N2 handover specification is defined in the following documents: + +* 3GPP TS 23.502, 4.9.1.3 Inter NG-RAN node N2 based handover: + - Outlines detailed handover signaling flows for N2-based handovers. + - Covers both intra-system (between 5G gNBs) and inter-system (between 5G and LTE eNBs) handovers. +* 3GPP TS 38.300, section 9 Mobility and State Transitions: + - describes mobility procedures at the NG-RAN level, depending on the RRC state. +* 3GPP TS 38.413 (NGAP), section 8.4 UE Mobility Management Procedures: + - Specifies the signaling procedures over the N2 interface. + - Includes messages like Handover Request, Handover Command, and Handover Preparation. +* 3GPP TS 38.331 (RRC): details the UE-level RRC procedures involved during handovers + +### End-to-end flow + +```mermaid +sequenceDiagram + participant ue as UE + participant sdu as source DU + participant scucp as source CU-CP + participant scuup as source CU-UP + participant tdu as target DU + participant tcucp as target CU-CP + participant tcuup as target CU-UP + participant amf as AMF + + Note over ue,sdu: UE active on source DU + alt HO triggered through A3 event + ue->>sdu: RRC Measurement Report + sdu->>scucp: F1AP UL RRC Msg Transfer (RRC Measurement Report) + Note over scucp: Handover decision (A3 event trigger) + else Manual Trigger + Note over scucp: Handover decision (e.g., telnet) + end + Note over scucp: nr_rrc_trigger_n2_ho() ("on source CU") + scucp->>amf: HANDOVER REQUIRED + amf->>tcucp: HANDOVER REQUEST + Note over tcucp: rrc_gNB_process_Handover_Request + Note over tcucp: trigger_bearer_setup + tcucp->>tcuup: Bearer Context Setup Request + tcuup->>tcucp: Bearer Context Setup Response + Note over tcucp: rrc_gNB_process_e1_bearer_context_setup_resp + Note over tcucp: nr_rrc_trigger_n2_ho_target() ("on target CU") + Note over tcucp: nr_initiate_handover() + tcucp->>tdu: F1AP UE Context Setup Req + Note over tdu: Create UE context + tdu->>tcucp: F1AP UE Context Setup Resp (incl. CellGroupConfig) + Note over tcucp: rrc_CU_process_ue_context_setup_response() ("on target CU") + Note over tcucp: e1_send_bearer_updates() + tcucp->>tcuup: E1AP Bearer Context Modification Req + tcuup->>tcucp: E1AP Bearer Context Modification Resp + tcucp-->>tcucp: callback: ho_req_ack() + Note over tcucp: nr_rrc_n2_ho_acknowledge() ("on target CU") + tcucp->>amf: HANDOVER REQUEST ACKNOWLEDGE (data forwarding info) + amf->>scucp: HANDOVER COMMAND + scucp->>sdu: F1AP UE Context Modification Req (RRC Reconfiguration) + sdu->>ue: RRC Reconfiguration + sdu->>scucp: F1AP UE Context Modification Resp + Note over sdu: Stop scheduling UE + Note over scucp: rrc_CU_process_ue_context_modification_response() + Note over scucp: e1_send_bearer_updates() + scucp->>scuup: E1 Bearer Context Modification Req (PDCP Status Request) + scuup->>scucp: E1 Bearer Context Modification Resp (PDCP Status Info) + scucp->>amf: NG Uplink RAN Status Transfer + amf->>tcucp: NG Downlink RAN Status Transfer + tcucp->>tcuup: E1 Bearer Context Modification Req (PDCP Status Info) + tcuup->>tcucp: E1 Bearer Context Modification Resp + Note over ue: UE attachment to target DU + Note over ue,tdu: RA (Msg1 + Msg2) + ue->>tdu: RRC Reconfiguration Complete + tdu->>tcucp: F1AP UL RRC Msg Transfer (RRC Reconfiguration Complete) + tcucp-->>tcucp: callback: ho_success() + Note over tcucp: nr_rrc_n2_ho_complete() ("on target CU") + Note over tcucp: handle_rrcReconfigurationComplete() ("on target CU") + tcucp->>amf: HANDOVER NOTIFY + amf->>scucp: UE Context Release Command + note over scucp: ngap_gNB_handle_ue_context_release_command + note over scucp: rrc_gNB_process_NGAP_UE_CONTEXT_RELEASE_COMMAND + scucp->>scuup: E1 Bearer Context Release Command + scuup->>scucp: E1 Bearer Context Release Complete + Note over scucp: rrc_gNB_generate_RRCRelease + scucp->>sdu: F1 UE Context Release Command + sdu->>scucp: F1 UE Context Release Complete + note over scucp: rrc_CU_process_ue_context_release_complete + note over scucp: rrc_remove_ue + Note over ue,tdu: UE active on target DU +``` # Structures @@ -308,7 +396,8 @@ corresponding CU. `nr_ho_source_cu_t` contains notably a function pointer `ho_cancel` for handover cancel. `nr_ho_target_cu_t` contains function pointers `ho_req_ack` -for handover request acknowledge and `ho_success` for handover success. As can +for handover request acknowledge, `ho_success` for handover success, +`ho_failure` for handover failure (N2 only). be seen in the sequence diagram above, either the "target CU" or "source CU" needs to do an operation, and a "switch" from target to source CU is done using these function pointers. For instance, in F1, the handover request acknowledge diff --git a/doc/RRC/rrc-usage.md b/doc/RRC/rrc-usage.md index 09c8952889..0eb7bc7195 100644 --- a/doc/RRC/rrc-usage.md +++ b/doc/RRC/rrc-usage.md @@ -99,6 +99,26 @@ the [MAC configuration](../MAC/mac-usage.md) as well for SIB configuration. ### Neighbor-gNB configuration - TBD +#### What is a gNB neighbor? + +Network continuity is a key aspect of 5G. In the 5G architecture, gNB neighbors play a central role in maintaining service continuity through mechanisms such as handover and load balancing. By definition, a gNB neighbor is another gNB that can be measured and linked by the UE. If the current serving gNB is no longer optimal, the UE may connect to a neighbor gNB. + +To support this behavior, the network configuration specifies additional frequencies and cells that the UE should measure. The UE reports these measurements to the network, which then decides whether or not to initiate a handover. + +Neighbor types include: +- **Intra-gNB neighbors** - cells belonging to the same gNB +- **Inter-gNB neighbors** - cells belonging to different gNBs +- **Inter-RAT neighbors** - cells belonging to another RAT (e.g., LTE) + +#### Required configuration parameters + +To define a neighbor cell in the configuration file, the following parameters are typically needed: +- **gNB ID** - unique identifier of the gNB +- **Cell ID** - identifier of the cell within the gNB +- **Physical Cell ID** - identifier of the cell’s synchronization signal (PCI) +- **Absolute Frequency** - frequency used by the SSB (absoluteFrequencySSB) +- **Subcarrier Spacing** - numerology (e.g., 15 kHz, 30 kHz) +- **PLMN configuration** - MCC, MNC, and MNC length +- **Tracking Area Code (TAC)** - identifier of the tracking area Refer to the [handover tutorial](../handover-tutorial.md) for more information. diff --git a/doc/handover-tutorial.md b/doc/handover-tutorial.md index 87a45ed1e5..67bf99b3c2 100644 --- a/doc/handover-tutorial.md +++ b/doc/handover-tutorial.md @@ -207,6 +207,7 @@ neighbour_list = ( physical_cellId = 1; absoluteFrequencySSB = 643296; subcarrierSpacing = 1; #30 KHz + band = 78; plmn = { mcc = 001; mnc = 01; mnc_length = 2}; tracking_area_code = 1; } @@ -221,6 +222,7 @@ neighbour_list = ( physical_cellId = 0; absoluteFrequencySSB = 643296; subcarrierSpacing = 1; #30 KHz + band = 78; plmn = { mcc = 001; mnc = 01; mnc_length = 2}; tracking_area_code = 1; } @@ -340,3 +342,147 @@ while true; do sleep 15 done ``` + +# N2 Handover + +## Run the setup + +An N2 handover involves the transfer of a UE from one gNB to another via the 5G core network. Unlike F1 handover, where the CU handles the process internally between its DUs, N2 handover requires signaling through the AMF, making it a core-network-based handover. + +We assume: + +* Two independent gNBs connected to the same 5GC via N2 interface. +* A UE initially connected to gNB-PCI0, which will be handed over to gNB-PCI1. +* Handover is triggered by either by decision based measurement event (e.g. A3) or telnet command. + +## Steps to run N2 handover with OAI UE + +1. Similarly to F1 handover, UE does not support any measurement reporting and handover is triggered by +telnet command. Therefore, ensure that both gNBs and UE are built with telnet support: + +```sh +./build_oai --ninja --nrUE --gNB --build-lib telnetsrv +``` + +Run the 5G Core Network if not already running. See [OAI CN5G tutorial](./NR_SA_Tutorial_OAI_CN5G.md). + +2. Start the source gNB (gNB-PCI0) e.g. + +```sh +sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.pci0.rfsim.conf --telnetsrv --telnetsrv.shrmod ci --gNBs.[0].min_rxtxtime 6 --rfsim --rfsimulator.serveraddr 127.0.0.1 +``` + +3. Start the UE e.g. + +```sh +sudo ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --rfsim --uicc0.imsi 001010000000001 -O ../../../ci-scripts/conf_files/nrue.uicc.conf --rfsimulator.serveraddr server +``` + +Ensure the UE successfully registers with the network. + +4. Start the target gNB (gNB PCI1) e.g. + +```sh +sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.pci1.rfsim.conf --sa --rfsim --telnetsrv --telnetsrv.shrmod ci --gNBs.[0].min_rxtxtime 6 --rfsimulator.serveraddr 127.0.0.1 +``` + +5. Trigger the N2 handover, e.g. + +From gNB-PCI0, trigger handover on target gNB with PCI 1 for UE ID 1: + +```sh +echo ci trigger_n2_ho 1,1 | nc 127.0.0.1 9090 && echo +``` +where the input parameters correspond to the PCI of the neighbor call and the RRC ID of the UE. + +This will initiate the N2 handover on the source gNB. + +## Neighbour list and measurement configuration + +Make sure the configuration file contains a neighbour list and measurement configuration, e.g. [neighbour-config-rfsim.conf](../../ci-scripts/conf_files/neighbour-config.conf). This configuration can also be present in a different file and included in the gNB configuration file with `@include "neighbour-config-rfsim.conf"`. + +For each gNB there is a `neighbour_cell_configuration` linked to its serving cell ID. + +The measurement configuration is based on A2 and A3 measurement events in 5G NR. These events are used by the UE to report radio conditions to the gNB. The A2 Measurement Event indicates that the serving cell’s signal quality has degraded below a defined threshold and the UE shall initiate measurement of neighboring cells. The A3 Measurement Event indicates that a neighboring cell’s signal quality is better than that of the serving cell by a certain offset and the UE shall trigger handover to a stronger neighboring cell + +This is an example with comments on how to use the configuration file: + +``` +############################################################ +# gNB-to-gNB neighbour list + measurement configuration # +# for the 2-cell rfsim setup (gNB_ID 0xe00 & 0xb00) # +############################################################ + +neighbour_list = ( + ########################################################## + # Entry USED BY gNB_ID = 0xe00 (nr_cellid = 12345678L) # + ########################################################## + { + nr_cellid = 12345678L; # Serving cell of gNB 0xe00 + neighbour_cell_configuration = ( + { + gNB_ID = 0xb00; + nr_cellid = 720898; # Cell served by gNB 0xb00 + physical_cellId = 1; + absoluteFrequencySSB= 621312; + subcarrierSpacing = 1; # 30 kHz + band = 78; + plmn = { mcc = 208; mnc = 99; mnc_length = 2 }; + tracking_area_code = 1; + } + ); + }, + + ########################################################## + # Entry USED BY gNB_ID = 0xb00 (nr_cellid = 720898) # + ########################################################## + { + nr_cellid = 720898; # Serving cell of gNB 0xb00 + neighbour_cell_configuration = ( + { + gNB_ID = 0xe00; + nr_cellid = 12345678L; # Cell served by gNB 0xe00 + physical_cellId = 0; + absoluteFrequencySSB= 641280; + subcarrierSpacing = 1; # 30 kHz + band = 78; + plmn = { mcc = 208; mnc = 99; mnc_length = 2 }; + tracking_area_code = 1; + } + ); + } +); + +############################################################ +# Common NR measurement-event configuration # +############################################################ + +nr_measurement_configuration = { + Periodical = { + enable = 1; + includeBeamMeasurements = 1; + maxNrofRS_IndexesToReport = 4; + }; + + A2 = { + enable = 1; + threshold = 60; + timeToTrigger = 1; + }; + + A3 = ( + { + cell_id = 720898; # neighbour of gNB 0xe00 + offset = 10; + hysteresis = 0; + timeToTrigger = 1; + }, + { + cell_id = 12345678; # neighbour of gNB 0xb00 + offset = 5; + hysteresis = 1; + timeToTrigger = 2; + } + ); +}; +``` diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.pci0.rfsim.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.pci0.rfsim.conf new file mode 100644 index 0000000000..b486b52dec --- /dev/null +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.pci0.rfsim.conf @@ -0,0 +1,251 @@ +Active_gNBs = ( "gNB-OAI"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + gNB_name = "gNB-OAI"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + plmn_list = ({ mcc = 001; mnc = 01; mnc_length = 2; snssaiList = ({ sst = 1; }) }); + @include "neighbour-config-rfsim.conf" + + nr_cellid = 12345678L; + + ////////// Physical parameters: + + do_CSIRS = 1; + do_SRS = 1; + + #uess_agg_levels = [0,1,2,2,1] + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP) + absoluteFrequencySSB = 641280; + dl_frequencyBand = 78; + # this is 3600 MHz + dl_absoluteFrequencyPointA = 640008; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 106; + #initialDownlinkBWP + #genericParameters + # this is RBstart=27,L=48 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 28875; # 6366 12925 12956 28875 12952 +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 12; + initialDLBWPsearchSpaceZero = 0; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 106; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 28875; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -96; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#one (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 14; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; + + ssb_PositionsInBurst_Bitmap = 1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = -25; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// AMF parameters: + amf_ip_address = ({ ipv4 = "192.168.70.132"; }); + + + NETWORK_INTERFACES : + { + GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.70.129/24"; + GNB_IPV4_ADDRESS_FOR_NGU = "192.168.70.129/24"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + } +); + +MACRLCs = ( +{ + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + pusch_TargetSNRx10 = 150; + pucch_TargetSNRx10 = 200; +} +); + +L1s = ( +{ + num_cc = 1; + tr_n_preference = "local_mac"; + prach_dtx_threshold = 120; + pucch0_dtx_threshold = 100; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 +} +); + +RUs = ( +{ + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 12; + att_rx = 12; + bands = [78]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 114; + eNB_instances = [0]; + clock_src = "internal"; +} +); + + +rfsimulator : +{ + serveraddr = "server"; + serverport = 4043; + options = (); #("saviq"); or/and "chanmod" + modelname = "AWGN"; + IQfile = "/tmp/rfsimulator.iqs"; +}; + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + +log_config : +{ + global_log_level ="info"; + hw_log_level ="info"; + phy_log_level ="info"; + mac_log_level ="info"; + rlc_log_level ="info"; + pdcp_log_level ="info"; + rrc_log_level ="info"; + ngap_log_level ="debug"; + f1ap_log_level ="debug"; +}; + +e2_agent = { + near_ric_ip_addr = "127.0.0.1"; + #sm_dir = "/path/where/the/SMs/are/located/" + sm_dir = "/usr/local/lib/flexric/" +}; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.pci1.rfsim.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.pci1.rfsim.conf new file mode 100644 index 0000000000..c649c8b0f8 --- /dev/null +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.pci1.rfsim.conf @@ -0,0 +1,251 @@ +Active_gNBs = ( "gNB-OAI"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xb00; + gNB_name = "gNB-OAI"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + plmn_list = ({ mcc = 001; mnc = 01; mnc_length = 2; snssaiList = ({ sst = 1; }) }); + @include "neighbour-config-rfsim.conf" + + nr_cellid = 720898; + + ////////// Physical parameters: + + do_CSIRS = 1; + do_SRS = 1; + + #uess_agg_levels = [0,1,2,2,1] + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 1; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP) + absoluteFrequencySSB = 621312; + dl_frequencyBand = 78; + # this is 3600 MHz + dl_absoluteFrequencyPointA = 620040; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 106; + #initialDownlinkBWP + #genericParameters + # this is RBstart=27,L=48 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 28875; # 6366 12925 12956 28875 12952 +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 12; + initialDLBWPsearchSpaceZero = 0; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 106; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 28875; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -96; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#one (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 14; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; + + ssb_PositionsInBurst_Bitmap = 1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = -25; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// AMF parameters: + amf_ip_address = ({ ipv4 = "192.168.70.132"; }); + + + NETWORK_INTERFACES : + { + GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.70.129/24"; + GNB_IPV4_ADDRESS_FOR_NGU = "192.168.70.129/24"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + } +); + +MACRLCs = ( +{ + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + pusch_TargetSNRx10 = 150; + pucch_TargetSNRx10 = 200; +} +); + +L1s = ( +{ + num_cc = 1; + tr_n_preference = "local_mac"; + prach_dtx_threshold = 120; + pucch0_dtx_threshold = 100; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 +} +); + +RUs = ( +{ + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 12; + att_rx = 12; + bands = [78]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 114; + eNB_instances = [0]; + clock_src = "internal"; +} +); + + +rfsimulator : +{ + serveraddr = "server"; + serverport = 4043; + options = (); #("saviq"); or/and "chanmod" + modelname = "AWGN"; + IQfile = "/tmp/rfsimulator.iqs"; +}; + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + +log_config : +{ + global_log_level ="info"; + hw_log_level ="info"; + phy_log_level ="info"; + mac_log_level ="info"; + rlc_log_level ="info"; + pdcp_log_level ="info"; + rrc_log_level ="info"; + ngap_log_level ="debug"; + f1ap_log_level ="debug"; +}; + +e2_agent = { + near_ric_ip_addr = "127.0.0.1"; + #sm_dir = "/path/where/the/SMs/are/located/" + sm_dir = "/usr/local/lib/flexric/" +}; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/neighbour-config-rfsim.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/neighbour-config-rfsim.conf new file mode 100644 index 0000000000..cff9d2b293 --- /dev/null +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/neighbour-config-rfsim.conf @@ -0,0 +1,78 @@ +############################################################ +# gNB-to-gNB neighbour list + measurement configuration # +# for the 2-cell rfsim setup (gNB_ID 0xe00 & 0xb00) # +############################################################ + +neighbour_list = ( + ########################################################## + # Entry USED BY gNB_ID = 0xe00 (nr_cellid = 12345678L) # + ########################################################## + { + nr_cellid = 12345678L; # Serving cell of gNB 0xe00 + neighbour_cell_configuration = ( + { + gNB_ID = 0xb00; + nr_cellid = 720898; # Cell served by gNB 0xb00 + physical_cellId = 1; + absoluteFrequencySSB= 621312; + subcarrierSpacing = 1; # 30 kHz + band = 78; + plmn = { mcc = 001; mnc = 01; mnc_length = 2 }; + tracking_area_code = 1; + } + ); + }, + + ########################################################## + # Entry USED BY gNB_ID = 0xb00 (nr_cellid = 720898) # + ########################################################## + { + nr_cellid = 720898; # Serving cell of gNB 0xb00 + neighbour_cell_configuration = ( + { + gNB_ID = 0xe00; + nr_cellid = 12345678L; # Cell served by gNB 0xe00 + physical_cellId = 0; + absoluteFrequencySSB= 641280; + subcarrierSpacing = 1; # 30 kHz + band = 78; + plmn = { mcc = 001; mnc = 01; mnc_length = 2 }; + tracking_area_code = 1; + } + ); + } +); + +############################################################ +# Common NR measurement-event configuration # +############################################################ + +nr_measurement_configuration = { + Periodical = { + enable = 1; + includeBeamMeasurements = 1; + maxNrofRS_IndexesToReport = 4; + }; + + A2 = { + enable = 1; + threshold = 60; + timeToTrigger = 1; + }; + + A3 = ( + { + cell_id = 720898; # neighbour of gNB 0xe00 + offset = 10; + hysteresis = 0; + timeToTrigger = 1; + }, + { + cell_id = 12345678; # neighbour of gNB 0xb00 + offset = 5; + hysteresis = 1; + timeToTrigger = 2; + } + ); +}; + From 72bfd1b5c3280725b44203f697cf98ebc84cebac Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 25 Aug 2025 19:04:22 +0200 Subject: [PATCH 738/964] switch to initial BWP if current BWP has no PRACH in gNB --- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index ae5305d77c..e718210e8b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -2718,8 +2718,7 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac, AssertFatal(dl_bwp_switch == ul_bwp_switch, "Different UL and DL BWP not supported\n"); DL_BWP->bwp_id = dl_bwp_switch; UL_BWP->bwp_id = ul_bwp_switch; - } - else { + } else { // (re)configuring BWP // TODO BWP switching not via RRC reconfiguration // via RRC if firstActiveXlinkBWP_Id is NULL, MAC stays on the same BWP as before @@ -2768,8 +2767,7 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac, UL_BWP->pusch_Config = ubwpd->pusch_Config->choice.setup; UL_BWP->pucch_Config = ubwpd->pucch_Config->choice.setup; UL_BWP->srs_Config = ubwpd->srs_Config->choice.setup; - } - else { + } else { DL_BWP->bwp_id = 0; UL_BWP->bwp_id = 0; DL_BWP->pdsch_Config = NULL; @@ -2778,11 +2776,6 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac, UL_BWP->configuredGrantConfig = NULL; } - if (old_dl_bwp_id != DL_BWP->bwp_id) - LOG_I(NR_MAC, "Switching to DL-BWP %li\n", DL_BWP->bwp_id); - if (old_ul_bwp_id != UL_BWP->bwp_id) - LOG_I(NR_MAC, "Switching to UL-BWP %li\n", UL_BWP->bwp_id); - // TDA lists if (DL_BWP->bwp_id>0) DL_BWP->tdaList_Common = dl_bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList; @@ -2832,6 +2825,19 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac, UL_BWP->rach_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; } + // if PRACH occasions are not configured for the active UL BWP + // switch the active UL BWP to BWP indicated by initialUplinkBWP + // as described in 5.15 of 38.321 + if (is_RA && !UL_BWP->rach_ConfigCommon) { + LOG_I(NR_MAC, "Cannot perform RA in current BWP, switching to initial BWP\n"); + configure_UE_BWP(nr_mac, scc, UE, is_RA, target_ss, 0, 0); + return; + } + if (old_dl_bwp_id != DL_BWP->bwp_id) + LOG_I(NR_MAC, "Switching to DL-BWP %li\n", DL_BWP->bwp_id); + if (old_ul_bwp_id != UL_BWP->bwp_id) + LOG_I(NR_MAC, "Switching to UL-BWP %li\n", UL_BWP->bwp_id); + NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; // Reset required fields in sched_ctrl (e.g. ul_ri and tpmi) reset_sched_ctrl(sched_ctrl); From 47554f89ce19ac89ecba526b357b139d2fe9418f Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 25 Aug 2025 16:14:56 +0200 Subject: [PATCH 739/964] fix switch to initial UL BWP if no PRACH common configuration in current BWP --- openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index 58269f769a..42712ebbb4 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -879,23 +879,23 @@ bool init_RA(NR_UE_MAC_INST_t *mac, int frame) // set POWER_OFFSET_2STEP_RA to 0 dB prach_resources->power_offset_2step = 0; - const NR_UE_UL_BWP_t *current_UL_BWP = mac->current_UL_BWP; // perform the BWP operation as specified in clause 5.15 // if PRACH occasions are not configured for the active UL BWP - if (!current_UL_BWP->rach_ConfigCommon) { + if (!mac->current_UL_BWP->rach_ConfigCommon) { // switch the active UL BWP to BWP indicated by initialUplinkBWP - current_UL_BWP = get_ul_bwp_structure(mac, 0, false); + mac->current_UL_BWP = get_ul_bwp_structure(mac, 0, false); // if the Serving Cell is an SpCell // switch the active DL BWP to BWP indicated by initialDownlinkBWP mac->current_DL_BWP = get_dl_bwp_structure(mac, 0, false); } else { // if the active DL BWP does not have the same bwp-Id as the active UL BWP - if (current_UL_BWP->bwp_id != mac->current_DL_BWP->bwp_id) { + if (mac->current_UL_BWP->bwp_id != mac->current_DL_BWP->bwp_id) { // switch the active DL BWP to the DL BWP with the same bwp-Id as the active UL BWP mac->current_DL_BWP = get_dl_bwp_structure(mac, 0, false); } } + const NR_UE_UL_BWP_t *current_UL_BWP = mac->current_UL_BWP; NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon = current_UL_BWP->rach_ConfigCommon; AssertFatal(nr_rach_ConfigCommon, "rach-ConfigCommon should be configured here\n"); // stop the bwp-InactivityTimer associated with the active DL BWP of this Serving Cell, if running From 38995aff5dedc216d739f0cc21369a1a097317a9 Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 9 Sep 2025 19:43:12 +0200 Subject: [PATCH 740/964] config files further cleanup --- .../gnb-du.sa.band78.51prb.usrpb210.ho-pci0.conf | 7 +------ .../gnb-du.sa.band78.51prb.usrpb210.ho-pci1.conf | 7 +------ .../gnb.sa.band77.273prb.fhi72.4x4.2L-metanoia.conf | 2 -- ci-scripts/conf_files/untested/benetel-5g.conf | 2 +- .../untested/gNB_SA_n78_106PRB.2x2_usrpn310.conf | 4 ++-- .../untested/gNB_SA_n78_133PRB.2x2_usrpn310.conf | 4 ++-- .../untested/gnb.band78.sa.fr1.106PRB.usrpn310.conf | 4 ++-- .../untested/gnb.band78.tm1.fr1.106PRB.usrpb210.conf | 2 +- .../untested/gnb.band78.tm1.fr1.106PRB.usrpn310.conf | 2 +- .../untested/gnb.sa.band66.fr1.106PRB.usrpn300.conf | 2 +- .../untested/gnb.sa.band78.fr1.51PRB.usrpb210.conf | 2 +- .../untested/proxy_gnb.band78.sa.fr1.106PRB.usrpn310.conf | 2 +- .../CONF/gnb-vnf.sa.band78.273prb.nfapi.conf | 4 ++-- .../CONF/gnb.band78.sa.fr1.106PRB.2x2.usrpn310.conf | 2 +- .../CONF/gnb.band78.sa.fr1.162PRB.2x2.usrpn310.conf | 2 +- .../CONF/gnb.sa.band78.273prb.fhi72.4x4-foxconn.conf | 6 +++--- .../CONF/gnb.sa.band78.fr1.106PRB.usrpb210.2pattern.conf | 1 - 17 files changed, 21 insertions(+), 34 deletions(-) diff --git a/ci-scripts/conf_files/gnb-du.sa.band78.51prb.usrpb210.ho-pci0.conf b/ci-scripts/conf_files/gnb-du.sa.band78.51prb.usrpb210.ho-pci0.conf index 6360d79124..216e2c3bd2 100644 --- a/ci-scripts/conf_files/gnb-du.sa.band78.51prb.usrpb210.ho-pci0.conf +++ b/ci-scripts/conf_files/gnb-du.sa.band78.51prb.usrpb210.ho-pci0.conf @@ -18,9 +18,6 @@ gNBs = ////////// Physical parameters: - do_CSIRS = 0; - do_SRS = 0; - servingCellConfigCommon = ( { #spCellConfigCommon @@ -84,7 +81,7 @@ gNBs = #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; -#oneHalf (0..15) 4,8,12,16,...60,64 +#one (0..15) 4,8,12,16,...60,64 ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 14; #ra_ContentionResolutionTimer #(0..7) 8,16,24,32,40,48,56,64 @@ -111,8 +108,6 @@ gNBs = hoppingId = 40; p0_nominal = -90; # ssb_PositionsInBurs_BitmapPR -# 1=short, 2=medium, 3=long - ssb_PositionsInBurst_PR = 2; ssb_PositionsInBurst_Bitmap = 1; # ssb_periodicityServingCell diff --git a/ci-scripts/conf_files/gnb-du.sa.band78.51prb.usrpb210.ho-pci1.conf b/ci-scripts/conf_files/gnb-du.sa.band78.51prb.usrpb210.ho-pci1.conf index d432d7323a..ff154f733f 100644 --- a/ci-scripts/conf_files/gnb-du.sa.band78.51prb.usrpb210.ho-pci1.conf +++ b/ci-scripts/conf_files/gnb-du.sa.band78.51prb.usrpb210.ho-pci1.conf @@ -18,9 +18,6 @@ gNBs = ////////// Physical parameters: - do_CSIRS = 0; - do_SRS = 0; - servingCellConfigCommon = ( { #spCellConfigCommon @@ -84,7 +81,7 @@ gNBs = #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; -#oneHalf (0..15) 4,8,12,16,...60,64 +#one (0..15) 4,8,12,16,...60,64 ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 14; #ra_ContentionResolutionTimer #(0..7) 8,16,24,32,40,48,56,64 @@ -111,8 +108,6 @@ gNBs = hoppingId = 40; p0_nominal = -90; # ssb_PositionsInBurs_BitmapPR -# 1=short, 2=medium, 3=long - ssb_PositionsInBurst_PR = 2; ssb_PositionsInBurst_Bitmap = 1; # ssb_periodicityServingCell diff --git a/ci-scripts/conf_files/gnb.sa.band77.273prb.fhi72.4x4.2L-metanoia.conf b/ci-scripts/conf_files/gnb.sa.band77.273prb.fhi72.4x4.2L-metanoia.conf index b1da98b85b..4be45f6e19 100644 --- a/ci-scripts/conf_files/gnb.sa.band77.273prb.fhi72.4x4.2L-metanoia.conf +++ b/ci-scripts/conf_files/gnb.sa.band77.273prb.fhi72.4x4.2L-metanoia.conf @@ -193,8 +193,6 @@ RUs = ( eNB_instances = [0]; ru_thread_core = 6; sl_ahead = 10; #5; - ##beamforming 1x2 matrix: 1 layer x 2 antennas - bf_weights = [0x00007fff, 0x0000,0x00007fff, 0x0000]; tr_preference = "raw_if4p5"; # important: activate FHI7.2 do_precoding = 0; # needs to match O-RU configuration } diff --git a/ci-scripts/conf_files/untested/benetel-5g.conf b/ci-scripts/conf_files/untested/benetel-5g.conf index 35eda8f6d6..80eef61908 100644 --- a/ci-scripts/conf_files/untested/benetel-5g.conf +++ b/ci-scripts/conf_files/untested/benetel-5g.conf @@ -86,7 +86,7 @@ gNBs = #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; -#oneHalf (0..15) 4,8,12,16,...60,64 +#one (0..15) 4,8,12,16,...60,64 ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 14; //15; #ra_ContentionResolutionTimer #(0..7) 8,16,24,32,40,48,56,64 diff --git a/ci-scripts/conf_files/untested/gNB_SA_n78_106PRB.2x2_usrpn310.conf b/ci-scripts/conf_files/untested/gNB_SA_n78_106PRB.2x2_usrpn310.conf index e442987316..c15e6d50c0 100644 --- a/ci-scripts/conf_files/untested/gNB_SA_n78_106PRB.2x2_usrpn310.conf +++ b/ci-scripts/conf_files/untested/gNB_SA_n78_106PRB.2x2_usrpn310.conf @@ -100,8 +100,8 @@ gNBs = powerRampingStep = 1; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen - ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 3; -#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#one (0..15) 4,8,12,16,...60,64 ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; #ra_ContentionResolutionTimer #(0..7) 8,16,24,32,40,48,56,64 diff --git a/ci-scripts/conf_files/untested/gNB_SA_n78_133PRB.2x2_usrpn310.conf b/ci-scripts/conf_files/untested/gNB_SA_n78_133PRB.2x2_usrpn310.conf index 9a9732f807..0fc59f4aff 100644 --- a/ci-scripts/conf_files/untested/gNB_SA_n78_133PRB.2x2_usrpn310.conf +++ b/ci-scripts/conf_files/untested/gNB_SA_n78_133PRB.2x2_usrpn310.conf @@ -96,8 +96,8 @@ gNBs = powerRampingStep = 1; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen - ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 3; -#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#one (0..15) 4,8,12,16,...60,64 ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; #ra_ContentionResolutionTimer #(0..7) 8,16,24,32,40,48,56,64 diff --git a/ci-scripts/conf_files/untested/gnb.band78.sa.fr1.106PRB.usrpn310.conf b/ci-scripts/conf_files/untested/gnb.band78.sa.fr1.106PRB.usrpn310.conf index b1b94da121..fac93fa30b 100644 --- a/ci-scripts/conf_files/untested/gnb.band78.sa.fr1.106PRB.usrpn310.conf +++ b/ci-scripts/conf_files/untested/gnb.band78.sa.fr1.106PRB.usrpn310.conf @@ -105,8 +105,8 @@ gNBs = powerRampingStep = 1; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen - ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 3; -#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#one (0..15) 4,8,12,16,...60,64 ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; #ra_ContentionResolutionTimer #(0..7) 8,16,24,32,40,48,56,64 diff --git a/ci-scripts/conf_files/untested/gnb.band78.tm1.fr1.106PRB.usrpb210.conf b/ci-scripts/conf_files/untested/gnb.band78.tm1.fr1.106PRB.usrpb210.conf index b9c29636be..85d8b99ed1 100644 --- a/ci-scripts/conf_files/untested/gnb.band78.tm1.fr1.106PRB.usrpb210.conf +++ b/ci-scripts/conf_files/untested/gnb.band78.tm1.fr1.106PRB.usrpb210.conf @@ -80,7 +80,7 @@ gNBs = #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; -#oneHalf (0..15) 4,8,12,16,...60,64 +#one (0..15) 4,8,12,16,...60,64 ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 14; //15; #ra_ContentionResolutionTimer #(0..7) 8,16,24,32,40,48,56,64 diff --git a/ci-scripts/conf_files/untested/gnb.band78.tm1.fr1.106PRB.usrpn310.conf b/ci-scripts/conf_files/untested/gnb.band78.tm1.fr1.106PRB.usrpn310.conf index 6a63b00e6f..b6852fa417 100644 --- a/ci-scripts/conf_files/untested/gnb.band78.tm1.fr1.106PRB.usrpn310.conf +++ b/ci-scripts/conf_files/untested/gnb.band78.tm1.fr1.106PRB.usrpn310.conf @@ -85,7 +85,7 @@ gNBs = #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; -#oneHalf (0..15) 4,8,12,16,...60,64 +#one (0..15) 4,8,12,16,...60,64 ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 14; //15; #ra_ContentionResolutionTimer #(0..7) 8,16,24,32,40,48,56,64 diff --git a/ci-scripts/conf_files/untested/gnb.sa.band66.fr1.106PRB.usrpn300.conf b/ci-scripts/conf_files/untested/gnb.sa.band66.fr1.106PRB.usrpn300.conf index 18228fde1d..36a79087ae 100644 --- a/ci-scripts/conf_files/untested/gnb.sa.band66.fr1.106PRB.usrpn300.conf +++ b/ci-scripts/conf_files/untested/gnb.sa.band66.fr1.106PRB.usrpn300.conf @@ -84,7 +84,7 @@ gNBs = #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; -#oneHalf (0..15) 4,8,12,16,...60,64 +#one (0..15) 4,8,12,16,...60,64 ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; #ra_ContentionResolutionTimer #(0..7) 8,16,24,32,40,48,56,64 diff --git a/ci-scripts/conf_files/untested/gnb.sa.band78.fr1.51PRB.usrpb210.conf b/ci-scripts/conf_files/untested/gnb.sa.band78.fr1.51PRB.usrpb210.conf index 62f5c042be..7242b91190 100644 --- a/ci-scripts/conf_files/untested/gnb.sa.band78.fr1.51PRB.usrpb210.conf +++ b/ci-scripts/conf_files/untested/gnb.sa.band78.fr1.51PRB.usrpb210.conf @@ -83,7 +83,7 @@ gNBs = #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; -#oneHalf (0..15) 4,8,12,16,...60,64 +#one (0..15) 4,8,12,16,...60,64 ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 14; #ra_ContentionResolutionTimer #(0..7) 8,16,24,32,40,48,56,64 diff --git a/ci-scripts/conf_files/untested/proxy_gnb.band78.sa.fr1.106PRB.usrpn310.conf b/ci-scripts/conf_files/untested/proxy_gnb.band78.sa.fr1.106PRB.usrpn310.conf index dd4a55c6a7..7018e6704e 100644 --- a/ci-scripts/conf_files/untested/proxy_gnb.band78.sa.fr1.106PRB.usrpn310.conf +++ b/ci-scripts/conf_files/untested/proxy_gnb.band78.sa.fr1.106PRB.usrpn310.conf @@ -82,7 +82,7 @@ gNBs = #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; -#oneHalf (0..15) 4,8,12,16,...60,64 +#one (0..15) 4,8,12,16,...60,64 ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 14; #ra_ContentionResolutionTimer #(0..7) 8,16,24,32,40,48,56,64 diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-vnf.sa.band78.273prb.nfapi.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-vnf.sa.band78.273prb.nfapi.conf index b5a124cf1a..750f8580b1 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-vnf.sa.band78.273prb.nfapi.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-vnf.sa.band78.273prb.nfapi.conf @@ -85,8 +85,8 @@ gNBs = powerRampingStep = 1; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen - ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 3; -#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#one (0..15) 4,8,12,16,...60,64 ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; #ra_ContentionResolutionTimer #(0..7) 8,16,24,32,40,48,56,64 diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.band78.sa.fr1.106PRB.2x2.usrpn310.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.band78.sa.fr1.106PRB.2x2.usrpn310.conf index d9eb5e9fa7..2081c86674 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.band78.sa.fr1.106PRB.2x2.usrpn310.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.band78.sa.fr1.106PRB.2x2.usrpn310.conf @@ -37,7 +37,7 @@ gNBs = ////////// Physical parameters: - pdsch_AntennaPorts = 1; + pdsch_AntennaPorts_XP = 2; pusch_AntennaPorts = 2; min_rxtxtime_pdsch = 5; ul_prbblacklist = "51,52,53,54" diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.band78.sa.fr1.162PRB.2x2.usrpn310.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.band78.sa.fr1.162PRB.2x2.usrpn310.conf index 15c9684706..76ba815e13 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.band78.sa.fr1.162PRB.2x2.usrpn310.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.band78.sa.fr1.162PRB.2x2.usrpn310.conf @@ -37,7 +37,7 @@ gNBs = ////////// Physical parameters: - pdsch_AntennaPorts = 1; + pdsch_AntennaPorts_XP = 2; pusch_AntennaPorts = 2; #pusch_TargetSNRx10 = 200; #pucch_TargetSNRx10 = 200; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-foxconn.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-foxconn.conf index 38f399c67f..e26e446f46 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-foxconn.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-foxconn.conf @@ -73,7 +73,7 @@ gNBs = initialULBWPsubcarrierSpacing = 1; #rach-ConfigCommon #rach-ConfigGeneric - prach_ConfigurationIndex = 151;# testMAC 158; OAI gNB 98 + prach_ConfigurationIndex = 152 #prach_msg1_FDM #0 = one, 1=two, 2=four, 3=eight prach_msg1_FDM = 0; @@ -87,8 +87,8 @@ gNBs = powerRampingStep = 1; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen - ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 3; -#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#one (0..15) 4,8,12,16,...60,64 ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; #ra_ContentionResolutionTimer #(0..7) 8,16,24,32,40,48,56,64 diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.2pattern.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.2pattern.conf index e29998478e..a8d65df77a 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.2pattern.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.2pattern.conf @@ -108,7 +108,6 @@ gNBs = # ssb_PositionsInBurs_BitmapPR # 1=short, 2=medium, 3=long - ssb_PositionsInBurst_PR = 2; ssb_PositionsInBurst_Bitmap = 1; # ssb_periodicityServingCell From 8051b5d14a9ba279aaa42f149c4b1a333220970b Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 9 Sep 2025 19:57:32 +0200 Subject: [PATCH 741/964] remove a couple of unnecessary include --- openair1/PHY/MODULATION/nr_modulation.h | 1 - openair1/PHY/NR_TRANSPORT/srs_rx.c | 1 - 2 files changed, 2 deletions(-) diff --git a/openair1/PHY/MODULATION/nr_modulation.h b/openair1/PHY/MODULATION/nr_modulation.h index 6977628187..64886a2809 100644 --- a/openair1/PHY/MODULATION/nr_modulation.h +++ b/openair1/PHY/MODULATION/nr_modulation.h @@ -25,7 +25,6 @@ #include #include "PHY/defs_nr_common.h" #include "PHY/defs_gNB.h" -#include "PHY/NR_UE_TRANSPORT/nr_transport_ue.h" #define DMRS_MOD_ORDER 2 /*Precoding matices: W[pmi][antenna_port][layer]*/ diff --git a/openair1/PHY/NR_TRANSPORT/srs_rx.c b/openair1/PHY/NR_TRANSPORT/srs_rx.c index c8b6d99c30..bab88344de 100644 --- a/openair1/PHY/NR_TRANSPORT/srs_rx.c +++ b/openair1/PHY/NR_TRANSPORT/srs_rx.c @@ -36,7 +36,6 @@ #include "PHY/defs_gNB.h" #include "PHY/defs_RU.h" #include "PHY/CODING/nrSmallBlock/nr_small_block_defs.h" -#include "PHY/NR_UE_TRANSPORT/srs_modulation_nr.h" #include "common/utils/LOG/log.h" #include "SCHED_NR/sched_nr.h" #include "nfapi/oai_integration/vendor_ext.h" From c9756c26ec25de4486fed5b7cae4505fb1bd273b Mon Sep 17 00:00:00 2001 From: francescomani Date: Wed, 10 Sep 2025 11:17:07 +0200 Subject: [PATCH 742/964] move PUCCH common tables to PHY common file --- openair1/PHY/NR_TRANSPORT/pucch_rx.c | 1 - openair1/PHY/NR_UE_TRANSPORT/pucch_nr.h | 313 +----------------- .../PHY/nr_phy_common/inc/nr_phy_common.h | 310 +++++++++++++++++ 3 files changed, 311 insertions(+), 313 deletions(-) diff --git a/openair1/PHY/NR_TRANSPORT/pucch_rx.c b/openair1/PHY/NR_TRANSPORT/pucch_rx.c index a9639ce0d7..ddf16a0541 100644 --- a/openair1/PHY/NR_TRANSPORT/pucch_rx.c +++ b/openair1/PHY/NR_TRANSPORT/pucch_rx.c @@ -41,7 +41,6 @@ #include "PHY/defs_nr_common.h" #include "PHY/defs_gNB.h" #include "PHY/sse_intrin.h" -#include "PHY/NR_UE_TRANSPORT/pucch_nr.h" #include "PHY/CODING/nrSmallBlock/nr_small_block_defs.h" #include "PHY/NR_TRANSPORT/nr_transport_common_proto.h" #include "PHY/NR_TRANSPORT/nr_transport_proto.h" diff --git a/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.h b/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.h index 54620f1ba0..97be0e274f 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.h +++ b/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.h @@ -72,318 +72,7 @@ void nr_generate_pucch3_4(const PHY_VARS_NR_UE *ue, const int nr_slot_tx, const fapi_nr_ul_config_pucch_pdu *pucch_pdu); -// tables for mcs values for different payloads - static const uint8_t table1_mcs[]={0,6,3,9}; - static const uint8_t table2_mcs[]={0,3,9,6,1,4,10,7}; - - /* - * The following tables implement TS 38.211 Subclause 5.2.2.2 Base sequences of length less than 36 (rows->u {0,1,..,29} / columns->n {0,1,...,M_ZC-1) - * Where base sequence r_u_v(n)=exp[j*phi(n)*pi/4] 0<=n<=M_ZC-1 and M_ZC={6,12,18,24} - * For M_ZC=30, base sequence r_u_v(n)=exp[-j((pi*[u+1]*[n+1]*[n+2])/31)] - */ - static const int16_t table_5_2_2_2_1_Re[30][6]={ // Table 5.2.2.2-1 (Re part) TS 38.211 Subclause 5.2.2.2 Base sequences of length less than 36 (M_ZC=6) - {-23170, 23170,-23170,-23170, 23170,-23170}, - {-23170,-23170, 23170, 23170,-23170,-23170}, - {-23170,-23170,-23170,-23170, 23170,-23170}, - { 23170, 23170, 23170,-23170, 23170,-23170}, - { 23170, 23170, 23170,-23170, 23170,-23170}, - {-23170, 23170, 23170,-23170,-23170,-23170}, - {-23170, 23170,-23170,-23170,-23170,-23170}, - {-23170, 23170, 23170,-23170, 23170, 23170}, - {-23170, 23170,-23170, 23170,-23170,-23170}, - {-23170,-23170, 23170,-23170,-23170,-23170}, - {-23170, 23170,-23170, 23170,-23170,-23170}, - {-23170, 23170,-23170, 23170, 23170,-23170}, - { 23170, 23170,-23170, 23170,-23170,-23170}, - { 23170, 23170,-23170,-23170, 23170,-23170}, - { 23170, 23170, 23170,-23170,-23170, 23170}, - { 23170, 23170, 23170, 23170,-23170,-23170}, - {-23170, 23170, 23170, 23170,-23170, 23170}, - {-23170,-23170, 23170, 23170, 23170,-23170}, - {-23170,-23170,-23170, 23170,-23170, 23170}, - {-23170, 23170, 23170,-23170, 23170,-23170}, - {-23170,-23170,-23170, 23170, 23170,-23170}, - {-23170, 23170,-23170,-23170,-23170, 23170}, - { 23170, 23170,-23170,-23170, 23170,-23170}, - { 23170, 23170,-23170,-23170, 23170,-23170}, - { 23170, 23170,-23170, 23170,-23170,-23170}, - { 23170, 23170,-23170, 23170,-23170,-23170}, - { 23170, 23170, 23170, 23170,-23170, 23170}, - { 23170, 23170, 23170,-23170, 23170, 23170}, - { 23170, 23170, 23170,-23170,-23170, 23170}, - { 23170, 23170,-23170, 23170, 23170, 23170} - }; - static const int16_t table_5_2_2_2_1_Im[30][6]={ // Table 5.2.2.2-1 (Im part) TS 38.211 Subclause 5.2.2.2 Base sequences of length less than 36 (M_ZC=6) - {-23170,-23170, 23170, 23170,-23170,-23170}, - {-23170, 23170,-23170,-23170, 23170,-23170}, - {-23170,-23170,-23170, 23170, 23170,-23170}, - { 23170, 23170, 23170, 23170,-23170,-23170}, - { 23170, 23170, 23170,-23170,-23170, 23170}, - {-23170, 23170,-23170,-23170,-23170,-23170}, - {-23170, 23170, 23170,-23170,-23170,-23170}, - {-23170,-23170, 23170,-23170, 23170,-23170}, - {-23170,-23170,-23170, 23170,-23170,-23170}, - {-23170,-23170, 23170,-23170, 23170,-23170}, - {-23170, 23170, 23170, 23170,-23170,-23170}, - {-23170,-23170,-23170, 23170, 23170,-23170}, - { 23170, 23170, 23170,-23170,-23170, 23170}, - { 23170, 23170, 23170, 23170,-23170, 23170}, - { 23170, 23170, 23170,-23170, 23170,-23170}, - { 23170, 23170, 23170,-23170, 23170,-23170}, - {-23170,-23170,-23170,-23170, 23170,-23170}, - {-23170,-23170,-23170, 23170,-23170,-23170}, - {-23170,-23170,-23170, 23170,-23170,-23170}, - {-23170, 23170, 23170,-23170,-23170,-23170}, - {-23170, 23170,-23170, 23170, 23170,-23170}, - {-23170, 23170,-23170,-23170,-23170,-23170}, - { 23170, 23170,-23170, 23170, 23170, 23170}, - { 23170, 23170,-23170,-23170, 23170,-23170}, - { 23170, 23170, 23170,-23170, 23170, 23170}, - { 23170, 23170,-23170, 23170, 23170, 23170}, - { 23170, 23170,-23170,-23170, 23170,-23170}, - { 23170, 23170,-23170, 23170,-23170,-23170}, - { 23170, 23170,-23170, 23170,-23170,-23170}, - { 23170, 23170,-23170, 23170,-23170,-23170} - }; - static const int16_t table_5_2_2_2_2_Re[30][12]={ // Table 5.2.2.2-2 (Re part) TS 38.211 Subclause 5.2.2.2 Base sequences of length less than 36 (M_ZC=12) - {-23170, 23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170, 23170, 23170,-23170}, - {-23170,-23170, 23170,-23170, 23170,-23170, 23170, 23170, 23170,-23170,-23170,-23170}, - {-23170,-23170,-23170, 23170,-23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170}, - {-23170,-23170, 23170,-23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170,-23170}, - {-23170, 23170, 23170, 23170,-23170, 23170, 23170, 23170, 23170, 23170,-23170, 23170}, - {-23170,-23170,-23170, 23170,-23170,-23170,-23170, 23170,-23170, 23170, 23170,-23170}, - { 23170, 23170,-23170, 23170, 23170, 23170,-23170, 23170, 23170, 23170, 23170,-23170}, - { 23170,-23170,-23170, 23170,-23170,-23170,-23170, 23170, 23170, 23170, 23170,-23170}, - {-23170, 23170,-23170, 23170,-23170, 23170,-23170,-23170, 23170,-23170,-23170, 23170}, - {-23170, 23170, 23170,-23170,-23170, 23170,-23170,-23170, 23170,-23170, 23170,-23170}, - {-23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170,-23170,-23170, 23170,-23170}, - {-23170, 23170,-23170, 23170, 23170,-23170,-23170,-23170, 23170, 23170, 23170,-23170}, - {-23170, 23170,-23170,-23170,-23170, 23170,-23170, 23170, 23170,-23170,-23170,-23170}, - {-23170, 23170, 23170, 23170,-23170,-23170,-23170, 23170, 23170,-23170, 23170,-23170}, - { 23170,-23170,-23170, 23170,-23170,-23170,-23170, 23170, 23170, 23170, 23170,-23170}, - {-23170, 23170,-23170, 23170, 23170,-23170,-23170, 23170, 23170,-23170, 23170,-23170}, - { 23170, 23170, 23170, 23170, 23170,-23170, 23170,-23170,-23170, 23170,-23170, 23170}, - { 23170, 23170, 23170, 23170, 23170,-23170,-23170, 23170, 23170,-23170, 23170,-23170}, - {-23170, 23170,-23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170,-23170}, - {-23170,-23170,-23170,-23170, 23170,-23170,-23170,-23170, 23170,-23170, 23170,-23170}, - {-23170, 23170,-23170, 23170,-23170,-23170, 23170, 23170,-23170, 23170, 23170,-23170}, - {-23170,-23170, 23170,-23170,-23170, 23170, 23170, 23170, 23170,-23170,-23170,-23170}, - {-23170,-23170,-23170,-23170, 23170,-23170,-23170, 23170,-23170, 23170,-23170,-23170}, - {-23170, 23170,-23170,-23170,-23170, 23170,-23170,-23170,-23170,-23170, 23170,-23170}, - {-23170, 23170, 23170,-23170, 23170,-23170,-23170,-23170, 23170,-23170,-23170,-23170}, - {-23170,-23170, 23170, 23170,-23170,-23170,-23170, 23170, 23170, 23170, 23170, 23170}, - { 23170, 23170,-23170,-23170, 23170, 23170, 23170, 23170, 23170,-23170, 23170, 23170}, - {-23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170,-23170,-23170, 23170,-23170}, - { 23170, 23170,-23170, 23170, 23170, 23170, 23170, 23170, 23170,-23170,-23170, 23170}, - {-23170,-23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170, 23170,-23170,-23170} - }; - static const int16_t table_5_2_2_2_2_Im[30][12]={ // Table 5.2.2.2-2 (Im part) TS 38.211 Subclause 5.2.2.2 Base sequences of length less than 36 (M_ZC=12) - {-23170, 23170,-23170,-23170,-23170, 23170,-23170,-23170, 23170, 23170, 23170,-23170}, - {-23170, 23170, 23170,-23170, 23170, 23170,-23170,-23170, 23170, 23170, 23170, 23170}, - {-23170, 23170, 23170, 23170,-23170, 23170,-23170, 23170, 23170,-23170, 23170,-23170}, - {-23170,-23170,-23170, 23170, 23170, 23170,-23170, 23170,-23170, 23170,-23170,-23170}, - {-23170,-23170,-23170, 23170, 23170, 23170, 23170,-23170, 23170,-23170,-23170, 23170}, - {-23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170, 23170,-23170, 23170, 23170}, - { 23170,-23170, 23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170, 23170,-23170}, - {-23170,-23170, 23170,-23170,-23170,-23170,-23170,-23170, 23170,-23170, 23170,-23170}, - {-23170,-23170, 23170, 23170,-23170,-23170,-23170, 23170, 23170, 23170, 23170, 23170}, - {-23170,-23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170, 23170,-23170,-23170}, - {-23170, 23170,-23170, 23170, 23170,-23170,-23170,-23170, 23170, 23170, 23170,-23170}, - {-23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170,-23170,-23170, 23170,-23170}, - {-23170,-23170, 23170,-23170,-23170,-23170,-23170, 23170,-23170,-23170, 23170, 23170}, - {-23170, 23170,-23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170,-23170}, - { 23170, 23170,-23170, 23170, 23170, 23170, 23170, 23170,-23170, 23170,-23170, 23170}, - {-23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170,-23170}, - {-23170,-23170,-23170,-23170, 23170,-23170,-23170, 23170, 23170,-23170,-23170, 23170}, - {-23170, 23170, 23170,-23170, 23170, 23170, 23170,-23170,-23170,-23170, 23170,-23170}, - {-23170, 23170, 23170, 23170,-23170,-23170,-23170, 23170, 23170,-23170, 23170,-23170}, - {-23170,-23170, 23170,-23170,-23170, 23170, 23170, 23170,-23170,-23170, 23170,-23170}, - { 23170, 23170, 23170, 23170, 23170,-23170,-23170, 23170, 23170, 23170,-23170,-23170}, - {-23170, 23170, 23170, 23170,-23170, 23170, 23170, 23170, 23170, 23170,-23170, 23170}, - {-23170, 23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170,-23170}, - { 23170,-23170,-23170, 23170,-23170,-23170, 23170, 23170, 23170,-23170,-23170,-23170}, - {-23170,-23170, 23170,-23170, 23170, 23170, 23170, 23170,-23170,-23170, 23170, 23170}, - {-23170, 23170, 23170,-23170, 23170, 23170,-23170, 23170,-23170, 23170,-23170, 23170}, - {-23170, 23170, 23170,-23170, 23170,-23170, 23170,-23170,-23170,-23170, 23170,-23170}, - {-23170,-23170, 23170, 23170, 23170,-23170,-23170, 23170,-23170, 23170, 23170,-23170}, - { 23170,-23170, 23170, 23170, 23170,-23170,-23170,-23170, 23170, 23170,-23170, 23170}, - {-23170, 23170,-23170, 23170,-23170,-23170, 23170,-23170,-23170, 23170, 23170,-23170} - }; - static const int16_t table_5_2_2_2_3_Re[30][18]={ // Table 5.2.2.2-3 (Re part) TS 38.211 Subclause 5.2.2.2 Base sequences of length less than 36 (M_ZC=18) - { 23170,-23170, 23170,-23170,-23170, 23170,-23170, 23170,-23170,-23170, 23170, 23170, 23170, 23170, 23170, 23170, 23170, 23170}, - {-23170,-23170,-23170, 23170, 23170,-23170,-23170, 23170,-23170,-23170, 23170,-23170,-23170, 23170, 23170,-23170,-23170,-23170}, - {-23170,-23170, 23170, 23170, 23170,-23170,-23170, 23170, 23170, 23170, 23170, 23170, 23170, 23170,-23170, 23170,-23170, 23170}, - {-23170,-23170,-23170,-23170,-23170, 23170,-23170, 23170,-23170,-23170, 23170,-23170,-23170,-23170, 23170,-23170, 23170, 23170}, - { 23170, 23170, 23170, 23170,-23170, 23170, 23170,-23170,-23170,-23170, 23170,-23170, 23170, 23170, 23170, 23170,-23170, 23170}, - {-23170,-23170, 23170, 23170,-23170, 23170, 23170, 23170, 23170,-23170, 23170, 23170, 23170,-23170,-23170,-23170,-23170, 23170}, - {-23170,-23170, 23170, 23170,-23170, 23170,-23170, 23170, 23170, 23170,-23170, 23170,-23170,-23170, 23170,-23170,-23170,-23170}, - { 23170, 23170,-23170,-23170,-23170, 23170,-23170,-23170,-23170, 23170, 23170, 23170, 23170, 23170,-23170,-23170, 23170,-23170}, - {-23170, 23170,-23170,-23170, 23170,-23170,-23170,-23170, 23170,-23170, 23170,-23170,-23170,-23170, 23170, 23170, 23170,-23170}, - {-23170, 23170,-23170, 23170,-23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170, 23170,-23170,-23170,-23170,-23170}, - {-23170,-23170,-23170, 23170,-23170,-23170, 23170, 23170,-23170,-23170,-23170, 23170,-23170, 23170,-23170,-23170,-23170,-23170}, - {-23170,-23170,-23170,-23170,-23170, 23170, 23170,-23170, 23170, 23170, 23170,-23170, 23170,-23170,-23170, 23170,-23170, 23170}, - {-23170, 23170,-23170,-23170, 23170, 23170, 23170,-23170, 23170,-23170, 23170, 23170,-23170,-23170, 23170,-23170, 23170,-23170}, - { 23170, 23170,-23170,-23170,-23170,-23170, 23170,-23170,-23170,-23170,-23170, 23170,-23170, 23170,-23170, 23170,-23170, 23170}, - {-23170,-23170, 23170,-23170, 23170,-23170, 23170, 23170,-23170,-23170, 23170, 23170,-23170,-23170, 23170,-23170, 23170, 23170}, - {-23170, 23170,-23170, 23170,-23170,-23170,-23170, 23170,-23170,-23170, 23170,-23170,-23170,-23170,-23170, 23170, 23170,-23170}, - {-23170, 23170,-23170, 23170,-23170, 23170,-23170,-23170, 23170,-23170,-23170,-23170, 23170, 23170,-23170,-23170, 23170,-23170}, - {-23170, 23170,-23170,-23170, 23170,-23170, 23170,-23170, 23170, 23170, 23170,-23170, 23170, 23170, 23170,-23170,-23170, 23170}, - {-23170, 23170,-23170, 23170, 23170,-23170, 23170,-23170,-23170,-23170, 23170,-23170,-23170, 23170, 23170, 23170, 23170, 23170}, - {-23170,-23170,-23170,-23170, 23170,-23170, 23170,-23170, 23170, 23170, 23170,-23170, 23170,-23170,-23170, 23170,-23170,-23170}, - {-23170, 23170, 23170,-23170, 23170, 23170,-23170,-23170, 23170,-23170, 23170,-23170,-23170,-23170, 23170, 23170, 23170,-23170}, - { 23170,-23170, 23170,-23170,-23170,-23170, 23170,-23170, 23170,-23170,-23170, 23170,-23170, 23170, 23170,-23170,-23170,-23170}, - {-23170,-23170, 23170, 23170, 23170, 23170, 23170,-23170, 23170,-23170,-23170,-23170,-23170, 23170,-23170, 23170,-23170, 23170}, - {-23170, 23170,-23170, 23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170,-23170, 23170,-23170, 23170, 23170,-23170,-23170}, - {-23170, 23170, 23170, 23170,-23170, 23170,-23170, 23170,-23170,-23170, 23170,-23170, 23170, 23170, 23170,-23170,-23170,-23170}, - {-23170,-23170, 23170,-23170,-23170,-23170,-23170, 23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170}, - {-23170, 23170, 23170,-23170, 23170,-23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170, 23170,-23170, 23170, 23170, 23170}, - {-23170,-23170,-23170,-23170,-23170, 23170,-23170, 23170,-23170, 23170, 23170,-23170,-23170,-23170, 23170, 23170, 23170,-23170}, - { 23170,-23170, 23170,-23170,-23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170,-23170, 23170,-23170,-23170, 23170}, - {-23170,-23170, 23170, 23170, 23170, 23170, 23170, 23170, 23170,-23170,-23170,-23170, 23170, 23170,-23170, 23170,-23170, 23170} - }; - static const int16_t table_5_2_2_2_3_Im[30][18]={ // Table 5.2.2.2-3 (Im part) TS 38.211 Subclause 5.2.2.2 Base sequences of length less than 36 (M_ZC=18) - {-23170, 23170,-23170,-23170, 23170, 23170,-23170,-23170, 23170,-23170,-23170,-23170, 23170, 23170, 23170,-23170,-23170,-23170}, - { 23170,-23170, 23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170,-23170, 23170,-23170, 23170}, - {-23170, 23170, 23170,-23170,-23170, 23170,-23170,-23170, 23170, 23170, 23170, 23170, 23170,-23170, 23170,-23170,-23170,-23170}, - {-23170,-23170, 23170, 23170, 23170, 23170,-23170, 23170, 23170, 23170, 23170,-23170,-23170, 23170,-23170,-23170,-23170, 23170}, - { 23170, 23170,-23170,-23170,-23170,-23170, 23170,-23170,-23170,-23170, 23170,-23170,-23170,-23170, 23170,-23170, 23170, 23170}, - { 23170,-23170, 23170, 23170, 23170,-23170, 23170,-23170,-23170,-23170, 23170, 23170,-23170, 23170, 23170,-23170, 23170,-23170}, - {-23170, 23170,-23170, 23170, 23170, 23170,-23170,-23170, 23170, 23170,-23170, 23170, 23170, 23170,-23170,-23170,-23170,-23170}, - { 23170, 23170,-23170, 23170, 23170, 23170, 23170,-23170, 23170,-23170, 23170, 23170,-23170, 23170,-23170,-23170,-23170, 23170}, - {-23170, 23170,-23170,-23170, 23170,-23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170, 23170}, - { 23170,-23170, 23170, 23170,-23170,-23170,-23170, 23170,-23170,-23170, 23170, 23170, 23170, 23170, 23170,-23170, 23170,-23170}, - {-23170,-23170,-23170, 23170,-23170, 23170, 23170, 23170, 23170,-23170,-23170, 23170, 23170,-23170, 23170,-23170,-23170, 23170}, - {-23170,-23170, 23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170,-23170,-23170,-23170, 23170,-23170}, - {-23170,-23170,-23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170,-23170, 23170, 23170, 23170}, - { 23170, 23170,-23170,-23170,-23170,-23170, 23170, 23170,-23170, 23170, 23170, 23170,-23170,-23170, 23170,-23170,-23170, 23170}, - {-23170, 23170,-23170,-23170,-23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170, 23170,-23170, 23170, 23170, 23170, 23170}, - { 23170, 23170,-23170, 23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170,-23170, 23170,-23170,-23170, 23170, 23170}, - {-23170,-23170,-23170,-23170,-23170, 23170, 23170,-23170,-23170, 23170, 23170, 23170, 23170,-23170,-23170, 23170,-23170,-23170}, - {-23170,-23170, 23170, 23170,-23170, 23170,-23170,-23170,-23170, 23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170, 23170}, - {-23170, 23170,-23170,-23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170, 23170,-23170,-23170}, - { 23170, 23170, 23170,-23170,-23170,-23170,-23170, 23170,-23170, 23170,-23170,-23170, 23170,-23170,-23170,-23170, 23170, 23170}, - {-23170, 23170, 23170,-23170, 23170, 23170, 23170,-23170,-23170,-23170,-23170, 23170,-23170, 23170,-23170,-23170,-23170,-23170}, - { 23170,-23170,-23170,-23170, 23170, 23170,-23170,-23170, 23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170, 23170, 23170}, - {-23170,-23170, 23170,-23170,-23170, 23170, 23170,-23170,-23170, 23170, 23170, 23170, 23170,-23170, 23170, 23170, 23170, 23170}, - { 23170,-23170,-23170, 23170,-23170,-23170,-23170, 23170, 23170,-23170, 23170,-23170,-23170, 23170, 23170, 23170, 23170, 23170}, - { 23170,-23170,-23170, 23170,-23170,-23170,-23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170, 23170,-23170,-23170, 23170}, - {-23170,-23170, 23170,-23170, 23170, 23170, 23170,-23170, 23170, 23170, 23170,-23170,-23170,-23170, 23170,-23170,-23170,-23170}, - {-23170,-23170,-23170,-23170, 23170,-23170, 23170,-23170,-23170,-23170, 23170, 23170,-23170,-23170, 23170,-23170,-23170,-23170}, - {-23170,-23170, 23170, 23170,-23170, 23170, 23170,-23170,-23170, 23170,-23170,-23170, 23170,-23170,-23170,-23170,-23170, 23170}, - {-23170,-23170, 23170,-23170,-23170,-23170, 23170, 23170, 23170, 23170,-23170, 23170, 23170,-23170,-23170, 23170,-23170, 23170}, - {-23170, 23170, 23170,-23170,-23170,-23170,-23170, 23170,-23170, 23170, 23170,-23170,-23170, 23170, 23170,-23170, 23170,-23170} - }; - static const int16_t table_5_2_2_2_4_Re[30][24]={ // Table 5.2.2.2-4 (Re part) TS 38.211 Subclause 5.2.2.2 Base sequences of length less than 36 (M_ZC=24) - { 23170,-23170,-23170, 23170,-23170, 23170,-23170, 23170, 23170,-23170, 23170,-23170, 23170, 23170,-23170,-23170, 23170,-23170,-23170,-23170,-23170,-23170,-23170,-23170}, - { 23170,-23170,-23170, 23170, 23170,-23170, 23170,-23170,-23170, 23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170,-23170, 23170,-23170,-23170,-23170,-23170}, - { 23170,-23170,-23170, 23170, 23170, 23170,-23170, 23170,-23170, 23170,-23170, 23170, 23170,-23170, 23170, 23170,-23170, 23170,-23170, 23170, 23170,-23170,-23170,-23170}, - { 23170,-23170,-23170, 23170,-23170, 23170,-23170,-23170, 23170, 23170, 23170, 23170,-23170,-23170, 23170,-23170,-23170,-23170, 23170,-23170,-23170, 23170,-23170,-23170}, - { 23170,-23170,-23170,-23170, 23170,-23170, 23170, 23170, 23170,-23170, 23170,-23170, 23170, 23170,-23170, 23170,-23170, 23170, 23170,-23170, 23170, 23170,-23170,-23170}, - {-23170, 23170, 23170,-23170,-23170, 23170, 23170,-23170,-23170, 23170, 23170,-23170, 23170,-23170, 23170, 23170,-23170, 23170,-23170, 23170,-23170,-23170,-23170,-23170}, - {-23170,-23170, 23170,-23170, 23170, 23170,-23170, 23170,-23170, 23170, 23170,-23170, 23170,-23170,-23170,-23170,-23170, 23170, 23170, 23170, 23170, 23170,-23170,-23170}, - {-23170, 23170,-23170, 23170, 23170, 23170,-23170,-23170,-23170, 23170,-23170, 23170,-23170,-23170, 23170, 23170, 23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170}, - {-23170, 23170,-23170,-23170, 23170, 23170, 23170,-23170,-23170, 23170, 23170,-23170, 23170, 23170,-23170, 23170, 23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170}, - { 23170, 23170, 23170,-23170, 23170, 23170, 23170,-23170, 23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170, 23170,-23170, 23170,-23170,-23170, 23170,-23170,-23170}, - {-23170,-23170,-23170, 23170,-23170,-23170,-23170, 23170,-23170, 23170,-23170, 23170, 23170,-23170, 23170, 23170,-23170, 23170, 23170,-23170,-23170, 23170,-23170,-23170}, - {-23170,-23170, 23170,-23170, 23170, 23170, 23170, 23170,-23170,-23170, 23170, 23170, 23170,-23170,-23170, 23170,-23170,-23170, 23170, 23170,-23170, 23170,-23170,-23170}, - {-23170,-23170,-23170, 23170,-23170, 23170,-23170, 23170, 23170, 23170,-23170, 23170,-23170,-23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170,-23170,-23170}, - {-23170,-23170, 23170,-23170, 23170,-23170,-23170, 23170, 23170,-23170, 23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170,-23170,-23170, 23170, 23170,-23170,-23170}, - {-23170, 23170,-23170, 23170, 23170,-23170, 23170,-23170,-23170, 23170, 23170,-23170,-23170, 23170,-23170,-23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170}, - {-23170, 23170, 23170,-23170, 23170,-23170,-23170, 23170, 23170,-23170, 23170, 23170, 23170,-23170, 23170,-23170, 23170,-23170, 23170, 23170, 23170, 23170,-23170,-23170}, - {-23170,-23170, 23170, 23170,-23170,-23170,-23170, 23170, 23170, 23170, 23170, 23170, 23170, 23170, 23170,-23170,-23170, 23170,-23170, 23170, 23170, 23170, 23170,-23170}, - {-23170, 23170,-23170, 23170, 23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170, 23170, 23170, 23170, 23170, 23170,-23170,-23170, 23170, 23170, 23170,-23170,-23170}, - {-23170, 23170,-23170, 23170,-23170,-23170, 23170,-23170, 23170,-23170,-23170,-23170,-23170,-23170, 23170,-23170,-23170, 23170, 23170,-23170, 23170, 23170,-23170,-23170}, - {-23170,-23170,-23170,-23170, 23170, 23170, 23170, 23170, 23170,-23170, 23170, 23170, 23170,-23170,-23170, 23170,-23170, 23170, 23170, 23170,-23170,-23170, 23170,-23170}, - {-23170,-23170, 23170, 23170, 23170,-23170, 23170, 23170,-23170, 23170,-23170,-23170, 23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170, 23170, 23170,-23170,-23170}, - {-23170, 23170, 23170, 23170,-23170,-23170, 23170, 23170,-23170, 23170,-23170,-23170, 23170,-23170,-23170, 23170, 23170, 23170, 23170, 23170,-23170,-23170,-23170,-23170}, - {-23170, 23170,-23170,-23170,-23170, 23170,-23170,-23170, 23170, 23170,-23170, 23170,-23170,-23170,-23170,-23170, 23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170}, - {-23170, 23170, 23170,-23170, 23170, 23170, 23170, 23170, 23170,-23170,-23170, 23170, 23170, 23170, 23170, 23170, 23170,-23170,-23170,-23170,-23170, 23170, 23170,-23170}, - {-23170,-23170, 23170,-23170, 23170, 23170, 23170,-23170, 23170, 23170,-23170,-23170, 23170,-23170,-23170,-23170,-23170, 23170,-23170, 23170, 23170, 23170,-23170,-23170}, - {-23170, 23170, 23170,-23170,-23170, 23170, 23170,-23170, 23170,-23170, 23170, 23170, 23170, 23170, 23170,-23170,-23170,-23170, 23170, 23170, 23170, 23170, 23170,-23170}, - { 23170,-23170, 23170, 23170,-23170,-23170, 23170, 23170, 23170,-23170, 23170,-23170, 23170,-23170, 23170, 23170,-23170,-23170,-23170, 23170,-23170, 23170,-23170,-23170}, - {-23170,-23170,-23170, 23170,-23170,-23170,-23170, 23170,-23170, 23170, 23170, 23170,-23170, 23170,-23170,-23170, 23170,-23170, 23170,-23170, 23170, 23170,-23170,-23170}, - {-23170, 23170,-23170, 23170,-23170, 23170, 23170,-23170, 23170,-23170,-23170, 23170, 23170,-23170, 23170,-23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170}, - {-23170,-23170, 23170, 23170,-23170, 23170, 23170,-23170, 23170,-23170, 23170,-23170, 23170,-23170,-23170, 23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170} - }; - static const int16_t table_5_2_2_2_4_Im[30][24]={ // Table 5.2.2.2-4 (Im part) TS 38.211 Subclause 5.2.2.2 Base sequences of length less than 36 (M_ZC=24) - {-23170,-23170, 23170,-23170, 23170, 23170, 23170,-23170, 23170,-23170,-23170,-23170,-23170, 23170, 23170,-23170,-23170,-23170, 23170, 23170, 23170,-23170,-23170,-23170}, - {-23170,-23170, 23170, 23170, 23170,-23170, 23170,-23170,-23170, 23170,-23170,-23170,-23170, 23170,-23170, 23170, 23170, 23170,-23170, 23170, 23170, 23170,-23170,-23170}, - {-23170,-23170,-23170, 23170,-23170,-23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170, 23170, 23170,-23170,-23170,-23170, 23170,-23170,-23170}, - { 23170,-23170, 23170,-23170,-23170,-23170, 23170, 23170, 23170,-23170, 23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170,-23170, 23170,-23170,-23170,-23170,-23170}, - {-23170, 23170,-23170,-23170,-23170, 23170,-23170,-23170, 23170, 23170, 23170, 23170,-23170,-23170,-23170, 23170, 23170, 23170,-23170,-23170, 23170,-23170,-23170,-23170}, - {-23170,-23170, 23170,-23170,-23170, 23170, 23170,-23170, 23170,-23170,-23170,-23170, 23170, 23170, 23170,-23170,-23170,-23170,-23170, 23170,-23170,-23170,-23170,-23170}, - {-23170, 23170, 23170, 23170,-23170, 23170,-23170, 23170,-23170, 23170,-23170,-23170,-23170,-23170,-23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170,-23170,-23170}, - {-23170, 23170, 23170,-23170, 23170,-23170, 23170,-23170, 23170,-23170,-23170,-23170,-23170, 23170,-23170,-23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170,-23170}, - {-23170, 23170,-23170, 23170,-23170,-23170,-23170,-23170, 23170, 23170,-23170,-23170,-23170, 23170, 23170,-23170, 23170,-23170, 23170,-23170,-23170,-23170,-23170,-23170}, - { 23170, 23170,-23170,-23170,-23170, 23170, 23170,-23170, 23170,-23170, 23170,-23170, 23170,-23170,-23170, 23170,-23170,-23170, 23170, 23170,-23170, 23170,-23170,-23170}, - {-23170,-23170,-23170,-23170, 23170,-23170, 23170, 23170, 23170, 23170,-23170,-23170,-23170,-23170, 23170, 23170, 23170, 23170,-23170,-23170, 23170, 23170, 23170,-23170}, - {-23170, 23170,-23170, 23170, 23170,-23170,-23170,-23170, 23170, 23170, 23170, 23170, 23170, 23170, 23170, 23170,-23170,-23170,-23170, 23170,-23170, 23170, 23170,-23170}, - { 23170,-23170, 23170,-23170,-23170, 23170, 23170, 23170,-23170,-23170,-23170,-23170, 23170,-23170, 23170,-23170,-23170, 23170, 23170,-23170,-23170, 23170,-23170,-23170}, - {-23170, 23170,-23170, 23170,-23170, 23170, 23170, 23170, 23170,-23170, 23170, 23170,-23170, 23170,-23170,-23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170}, - {-23170, 23170,-23170,-23170,-23170, 23170, 23170, 23170,-23170, 23170,-23170, 23170, 23170,-23170,-23170, 23170,-23170,-23170,-23170,-23170,-23170,-23170, 23170,-23170}, - {-23170,-23170,-23170,-23170, 23170,-23170,-23170,-23170,-23170, 23170,-23170, 23170,-23170, 23170, 23170,-23170,-23170, 23170, 23170, 23170,-23170,-23170,-23170,-23170}, - {-23170,-23170, 23170,-23170, 23170, 23170,-23170,-23170, 23170,-23170,-23170, 23170, 23170,-23170,-23170, 23170,-23170, 23170,-23170, 23170,-23170,-23170,-23170,-23170}, - { 23170,-23170, 23170,-23170, 23170,-23170, 23170, 23170,-23170,-23170, 23170,-23170,-23170,-23170,-23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170,-23170,-23170}, - {-23170, 23170,-23170, 23170,-23170,-23170, 23170,-23170, 23170,-23170,-23170,-23170,-23170,-23170, 23170,-23170,-23170, 23170, 23170,-23170, 23170, 23170,-23170,-23170}, - {-23170,-23170, 23170, 23170, 23170,-23170,-23170,-23170, 23170,-23170,-23170, 23170,-23170, 23170,-23170,-23170,-23170,-23170,-23170, 23170,-23170, 23170,-23170,-23170}, - {-23170,-23170,-23170,-23170,-23170,-23170, 23170,-23170,-23170,-23170, 23170,-23170, 23170,-23170, 23170,-23170, 23170, 23170, 23170,-23170,-23170, 23170,-23170,-23170}, - { 23170,-23170, 23170,-23170, 23170,-23170, 23170, 23170, 23170,-23170,-23170, 23170, 23170,-23170, 23170,-23170,-23170,-23170,-23170, 23170,-23170,-23170,-23170,-23170}, - {-23170, 23170,-23170, 23170,-23170, 23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170,-23170, 23170, 23170, 23170, 23170,-23170}, - {-23170,-23170, 23170,-23170,-23170,-23170, 23170, 23170, 23170, 23170, 23170,-23170, 23170,-23170, 23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170,-23170,-23170}, - {-23170, 23170,-23170,-23170,-23170,-23170,-23170, 23170,-23170,-23170, 23170,-23170,-23170, 23170,-23170, 23170,-23170,-23170, 23170, 23170, 23170,-23170,-23170,-23170}, - {-23170, 23170,-23170,-23170,-23170,-23170, 23170,-23170,-23170,-23170, 23170, 23170,-23170, 23170, 23170, 23170, 23170, 23170,-23170, 23170,-23170, 23170,-23170,-23170}, - {-23170, 23170,-23170,-23170, 23170, 23170,-23170,-23170,-23170, 23170,-23170,-23170, 23170, 23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170,-23170,-23170,-23170}, - { 23170,-23170,-23170,-23170, 23170, 23170,-23170,-23170, 23170, 23170, 23170, 23170, 23170,-23170, 23170,-23170,-23170, 23170,-23170, 23170, 23170,-23170,-23170,-23170}, - {-23170, 23170,-23170, 23170,-23170, 23170, 23170, 23170, 23170,-23170,-23170,-23170, 23170, 23170,-23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170,-23170}, - { 23170,-23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170, 23170,-23170,-23170,-23170,-23170, 23170,-23170, 23170, 23170, 23170,-23170, 23170,-23170,-23170,-23170} - }; - - /* - * The following tables implement TS 38.211 table 6.3.2.4.1-1: Number of PUCCH symbols and the corresponding N_SF_mprime_PUCCH_1 - * One table for no intra-slot hopping - * Two tables for intra-slot hopping (mprime=0 and mprime=1) - */ - static const uint8_t table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_noHop[14] = {0,0,0,2,2,3,3,4,4,5,5,6,6,7}; // for index PUCCH-length, we obtain N_SF_mprime_PUCCH_1 when no intra-slot hopping - static const uint8_t table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_m0Hop[14] = {0,0,0,1,1,1,1,2,2,2,2,3,3,3}; // for index PUCCH-length, we obtain N_SF_mprime_PUCCH_1 when intra-slot hopping and mprime=0 - static const uint8_t table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_m1Hop[14] = {0,0,0,1,1,2,2,2,2,3,3,3,3,4}; // for index PUCCH-length, we obtain N_SF_mprime_PUCCH_1 when intra-slot hopping and mprime=1 - /* - * The following tables implement TS 38.211 table 6.4.1.3.1.1-1: Number of DM-RS symbols and the corresponding N_SF_mprime_PUCCH_1 - * One table for no intra-slot hopping - * Two tables for intra-slot hopping (mprime=0 and mprime=1) - */ - static const uint8_t table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_noHop[14] = {0,0,0,2,3,3,4,4,5,5,6,6,7,7}; // for index PUCCH-DM-RS-length, we obtain N_SF_mprime_PUCCH_1 when no intra-slot hopping - static const uint8_t table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_m0Hop[14] = {0,0,0,1,1,2,2,2,2,3,3,3,3,4}; // for index PUCCH-DM-RS-length, we obtain N_SF_mprime_PUCCH_1 when intra-slot hopping and mprime=0 - static const uint8_t table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_m1Hop[14] = {0,0,0,1,2,1,2,2,3,2,3,3,4,3}; // for index PUCCH-DM-RS-length, we obtain N_SF_mprime_PUCCH_1 when intra-slot hopping and mprime=1 - /* The following tables implement TS 38.211 table 6.3.2.4.1-2: Orthogonal sequences wi(m)=exp(j*2*pi*phi(m)/N_SF) for PUCCH format 1 - uint16_t table_6_3_2_4_1_2_W2[2][2] = {{0,0}, {0,1}}; - uint16_t table_6_3_2_4_1_2_W3[3][3] = {{0,0,0}, {0,1,2}, {0,2,1}}; - uint16_t table_6_3_2_4_1_2_W4[4][4] = {{0,0,0,0}, {0,2,0,2}, {0,0,2,2} , {0,2,2,0}}; - uint16_t table_6_3_2_4_1_2_W5[2][2] = {{0,0,0,0,0}, {0,1,2,3,4}, {0,2,4,1,3}, {0,3,1,4,2}, {0,4,3,2,1}}; - uint16_t table_6_3_2_4_1_2_W6[2][2] = {{0,0,0,0,0,0}, {0,1,2,3,4,5}, {0,2,4,0,2,4}, {0,3,0,3,0,3}, {0,4,2,0,4,2}, {0,5,4,3,2,1}}; - uint16_t table_6_3_2_4_1_2_W7[2][2] = {{0,0,0,0,0,0,0},{0,1,2,3,4,5,6},{0,2,4,6,1,3,5},{0,3,6,2,5,1,4},{0,4,1,5,2,6,3},{0,5,3,1,6,4,2},{0,6,5,4,3,2,1}}; - */ - static const int16_t table_6_3_2_4_1_2_Wi_Re[8][7][7] = { - {{0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}}, - {{32767,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}}, - {{32767,32767,0,0,0,0,0}, {32767,-32767,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}}, - {{32767,32767,32767,0,0,0,0}, {32767,-16384,-16384,0,0,0,0}, {32767,-16384,-16384,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}}, - {{32767,32767,32767,32767,0,0,0}, {32767,-32767,32767,-32767,0,0,0}, {32767,32767,-32767,-32767,0,0,0}, {32767,-32767,-32767,32767,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}}, - {{32767,32767,32767,32767,32767,0,0}, {32767,10126,-26509,-26509,10126,0,0}, {32767,-26509,10126,10126,-26509,0,0}, {32767,-26509,10126,10126,-26509,0,0}, {32767,10126,-26509,-26509,10126,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}}, - {{32767,32767,32767,32767,32767,32767,0}, {32767,16384,-16384,-32767,-16384,16384,0}, {32767,-16384,-16384,32767,-16384,-16384,0}, {32767,-32767,32767,-32767,32767,-32767,0}, {32767,-16384,-16384,32767,-16384,-16384,0}, {32767,16384,-16384,-32767,-16384,16384,0}, {0,0,0,0,0,0,0}}, - {{32767,32767,32767,32767,32767,32767,32767},{32767,20430,-7291,-29522,-29522,-7291,20430},{32767,-7291,-29522,20430,20430,-29522,-7291},{32767,-29522,20430,-7291,-7291,20430,-29522},{32767,-29522,20430,-7291,-7291,20430,-29522},{32767,-7291,-29522,20430,20430,-29522,-7291},{32767,20430,-7291,-29522,-29522,-7291,20430}} - }; - static const int16_t table_6_3_2_4_1_2_Wi_Im[8][7][7] = { - {{0,0,0,0,0,0,0},{0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}}, - {{0,0,0,0,0,0,0},{0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}}, - {{0,0,0,0,0,0,0},{0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}}, - {{0,0,0,0,0,0,0},{0,28377,-28377,0,0,0,0}, {0,-28377,28377,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}}, - {{0,0,0,0,0,0,0},{0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}}, - {{0,0,0,0,0,0,0},{0,31163,19260,-19260,-31163,0,0}, {0,19260,-31163,31163,-19260,0,0}, {0,-19260,31163,-31163,19260,0,0}, {0,-31163,-19260,19260,31163,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}}, - {{0,0,0,0,0,0,0},{0,28377,28377,0,-28377,-28377,0}, {0,28377,-28377,0,28377,-28377,0}, {0,0,0,0,0,0,0}, {0,-28377,28377,0,-28377,28377,0}, {0,-28377,-28377,0,28377,28377,0}, {0,0,0,0,0,0,0}}, - {{0,0,0,0,0,0,0},{0,25618,31945,14217,-14217,-31945,-25618},{0,31945,-14217,-25618,25618,14217,-31945},{0,14217,-25618,31945,-31945,25618,-14217},{0,-14217,25618,-31945,31945,-25618,14217},{0,-31945,14217,25618,-25618,-14217,31945},{0,-25618,-31945,-14217,14217,31945,25618}} - }; - - static const uint8_t list_of_prime_numbers[46] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, +static const uint8_t list_of_prime_numbers[46] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101,103,107,109,113, 127,131,137,139,149,151,157,163,167,173, diff --git a/openair1/PHY/nr_phy_common/inc/nr_phy_common.h b/openair1/PHY/nr_phy_common/inc/nr_phy_common.h index 79e5b8746e..752353ad02 100644 --- a/openair1/PHY/nr_phy_common/inc/nr_phy_common.h +++ b/openair1/PHY/nr_phy_common/inc/nr_phy_common.h @@ -27,6 +27,316 @@ #include "PHY/MODULATION/nr_modulation.h" void init_byte2m128i(void); +// tables for mcs values for different payloads +static const uint8_t table1_mcs[] = {0, 6, 3, 9}; +static const uint8_t table2_mcs[] = {0, 3, 9, 6, 1, 4, 10, 7}; + + /* + * The following tables implement TS 38.211 Subclause 5.2.2.2 Base sequences of length less than 36 (rows->u {0,1,..,29} / columns->n {0,1,...,M_ZC-1) + * Where base sequence r_u_v(n)=exp[j*phi(n)*pi/4] 0<=n<=M_ZC-1 and M_ZC={6,12,18,24} + * For M_ZC=30, base sequence r_u_v(n)=exp[-j((pi*[u+1]*[n+1]*[n+2])/31)] + */ + static const int16_t table_5_2_2_2_1_Re[30][6]={ // Table 5.2.2.2-1 (Re part) TS 38.211 Subclause 5.2.2.2 Base sequences of length less than 36 (M_ZC=6) + {-23170, 23170,-23170,-23170, 23170,-23170}, + {-23170,-23170, 23170, 23170,-23170,-23170}, + {-23170,-23170,-23170,-23170, 23170,-23170}, + { 23170, 23170, 23170,-23170, 23170,-23170}, + { 23170, 23170, 23170,-23170, 23170,-23170}, + {-23170, 23170, 23170,-23170,-23170,-23170}, + {-23170, 23170,-23170,-23170,-23170,-23170}, + {-23170, 23170, 23170,-23170, 23170, 23170}, + {-23170, 23170,-23170, 23170,-23170,-23170}, + {-23170,-23170, 23170,-23170,-23170,-23170}, + {-23170, 23170,-23170, 23170,-23170,-23170}, + {-23170, 23170,-23170, 23170, 23170,-23170}, + { 23170, 23170,-23170, 23170,-23170,-23170}, + { 23170, 23170,-23170,-23170, 23170,-23170}, + { 23170, 23170, 23170,-23170,-23170, 23170}, + { 23170, 23170, 23170, 23170,-23170,-23170}, + {-23170, 23170, 23170, 23170,-23170, 23170}, + {-23170,-23170, 23170, 23170, 23170,-23170}, + {-23170,-23170,-23170, 23170,-23170, 23170}, + {-23170, 23170, 23170,-23170, 23170,-23170}, + {-23170,-23170,-23170, 23170, 23170,-23170}, + {-23170, 23170,-23170,-23170,-23170, 23170}, + { 23170, 23170,-23170,-23170, 23170,-23170}, + { 23170, 23170,-23170,-23170, 23170,-23170}, + { 23170, 23170,-23170, 23170,-23170,-23170}, + { 23170, 23170,-23170, 23170,-23170,-23170}, + { 23170, 23170, 23170, 23170,-23170, 23170}, + { 23170, 23170, 23170,-23170, 23170, 23170}, + { 23170, 23170, 23170,-23170,-23170, 23170}, + { 23170, 23170,-23170, 23170, 23170, 23170} + }; + static const int16_t table_5_2_2_2_1_Im[30][6]={ // Table 5.2.2.2-1 (Im part) TS 38.211 Subclause 5.2.2.2 Base sequences of length less than 36 (M_ZC=6) + {-23170,-23170, 23170, 23170,-23170,-23170}, + {-23170, 23170,-23170,-23170, 23170,-23170}, + {-23170,-23170,-23170, 23170, 23170,-23170}, + { 23170, 23170, 23170, 23170,-23170,-23170}, + { 23170, 23170, 23170,-23170,-23170, 23170}, + {-23170, 23170,-23170,-23170,-23170,-23170}, + {-23170, 23170, 23170,-23170,-23170,-23170}, + {-23170,-23170, 23170,-23170, 23170,-23170}, + {-23170,-23170,-23170, 23170,-23170,-23170}, + {-23170,-23170, 23170,-23170, 23170,-23170}, + {-23170, 23170, 23170, 23170,-23170,-23170}, + {-23170,-23170,-23170, 23170, 23170,-23170}, + { 23170, 23170, 23170,-23170,-23170, 23170}, + { 23170, 23170, 23170, 23170,-23170, 23170}, + { 23170, 23170, 23170,-23170, 23170,-23170}, + { 23170, 23170, 23170,-23170, 23170,-23170}, + {-23170,-23170,-23170,-23170, 23170,-23170}, + {-23170,-23170,-23170, 23170,-23170,-23170}, + {-23170,-23170,-23170, 23170,-23170,-23170}, + {-23170, 23170, 23170,-23170,-23170,-23170}, + {-23170, 23170,-23170, 23170, 23170,-23170}, + {-23170, 23170,-23170,-23170,-23170,-23170}, + { 23170, 23170,-23170, 23170, 23170, 23170}, + { 23170, 23170,-23170,-23170, 23170,-23170}, + { 23170, 23170, 23170,-23170, 23170, 23170}, + { 23170, 23170,-23170, 23170, 23170, 23170}, + { 23170, 23170,-23170,-23170, 23170,-23170}, + { 23170, 23170,-23170, 23170,-23170,-23170}, + { 23170, 23170,-23170, 23170,-23170,-23170}, + { 23170, 23170,-23170, 23170,-23170,-23170} + }; + static const int16_t table_5_2_2_2_2_Re[30][12]={ // Table 5.2.2.2-2 (Re part) TS 38.211 Subclause 5.2.2.2 Base sequences of length less than 36 (M_ZC=12) + {-23170, 23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170, 23170, 23170,-23170}, + {-23170,-23170, 23170,-23170, 23170,-23170, 23170, 23170, 23170,-23170,-23170,-23170}, + {-23170,-23170,-23170, 23170,-23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170}, + {-23170,-23170, 23170,-23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170,-23170}, + {-23170, 23170, 23170, 23170,-23170, 23170, 23170, 23170, 23170, 23170,-23170, 23170}, + {-23170,-23170,-23170, 23170,-23170,-23170,-23170, 23170,-23170, 23170, 23170,-23170}, + { 23170, 23170,-23170, 23170, 23170, 23170,-23170, 23170, 23170, 23170, 23170,-23170}, + { 23170,-23170,-23170, 23170,-23170,-23170,-23170, 23170, 23170, 23170, 23170,-23170}, + {-23170, 23170,-23170, 23170,-23170, 23170,-23170,-23170, 23170,-23170,-23170, 23170}, + {-23170, 23170, 23170,-23170,-23170, 23170,-23170,-23170, 23170,-23170, 23170,-23170}, + {-23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170,-23170,-23170, 23170,-23170}, + {-23170, 23170,-23170, 23170, 23170,-23170,-23170,-23170, 23170, 23170, 23170,-23170}, + {-23170, 23170,-23170,-23170,-23170, 23170,-23170, 23170, 23170,-23170,-23170,-23170}, + {-23170, 23170, 23170, 23170,-23170,-23170,-23170, 23170, 23170,-23170, 23170,-23170}, + { 23170,-23170,-23170, 23170,-23170,-23170,-23170, 23170, 23170, 23170, 23170,-23170}, + {-23170, 23170,-23170, 23170, 23170,-23170,-23170, 23170, 23170,-23170, 23170,-23170}, + { 23170, 23170, 23170, 23170, 23170,-23170, 23170,-23170,-23170, 23170,-23170, 23170}, + { 23170, 23170, 23170, 23170, 23170,-23170,-23170, 23170, 23170,-23170, 23170,-23170}, + {-23170, 23170,-23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170,-23170}, + {-23170,-23170,-23170,-23170, 23170,-23170,-23170,-23170, 23170,-23170, 23170,-23170}, + {-23170, 23170,-23170, 23170,-23170,-23170, 23170, 23170,-23170, 23170, 23170,-23170}, + {-23170,-23170, 23170,-23170,-23170, 23170, 23170, 23170, 23170,-23170,-23170,-23170}, + {-23170,-23170,-23170,-23170, 23170,-23170,-23170, 23170,-23170, 23170,-23170,-23170}, + {-23170, 23170,-23170,-23170,-23170, 23170,-23170,-23170,-23170,-23170, 23170,-23170}, + {-23170, 23170, 23170,-23170, 23170,-23170,-23170,-23170, 23170,-23170,-23170,-23170}, + {-23170,-23170, 23170, 23170,-23170,-23170,-23170, 23170, 23170, 23170, 23170, 23170}, + { 23170, 23170,-23170,-23170, 23170, 23170, 23170, 23170, 23170,-23170, 23170, 23170}, + {-23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170,-23170,-23170, 23170,-23170}, + { 23170, 23170,-23170, 23170, 23170, 23170, 23170, 23170, 23170,-23170,-23170, 23170}, + {-23170,-23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170, 23170,-23170,-23170} + }; + static const int16_t table_5_2_2_2_2_Im[30][12]={ // Table 5.2.2.2-2 (Im part) TS 38.211 Subclause 5.2.2.2 Base sequences of length less than 36 (M_ZC=12) + {-23170, 23170,-23170,-23170,-23170, 23170,-23170,-23170, 23170, 23170, 23170,-23170}, + {-23170, 23170, 23170,-23170, 23170, 23170,-23170,-23170, 23170, 23170, 23170, 23170}, + {-23170, 23170, 23170, 23170,-23170, 23170,-23170, 23170, 23170,-23170, 23170,-23170}, + {-23170,-23170,-23170, 23170, 23170, 23170,-23170, 23170,-23170, 23170,-23170,-23170}, + {-23170,-23170,-23170, 23170, 23170, 23170, 23170,-23170, 23170,-23170,-23170, 23170}, + {-23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170, 23170,-23170, 23170, 23170}, + { 23170,-23170, 23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170, 23170,-23170}, + {-23170,-23170, 23170,-23170,-23170,-23170,-23170,-23170, 23170,-23170, 23170,-23170}, + {-23170,-23170, 23170, 23170,-23170,-23170,-23170, 23170, 23170, 23170, 23170, 23170}, + {-23170,-23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170, 23170,-23170,-23170}, + {-23170, 23170,-23170, 23170, 23170,-23170,-23170,-23170, 23170, 23170, 23170,-23170}, + {-23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170,-23170,-23170, 23170,-23170}, + {-23170,-23170, 23170,-23170,-23170,-23170,-23170, 23170,-23170,-23170, 23170, 23170}, + {-23170, 23170,-23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170,-23170}, + { 23170, 23170,-23170, 23170, 23170, 23170, 23170, 23170,-23170, 23170,-23170, 23170}, + {-23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170,-23170}, + {-23170,-23170,-23170,-23170, 23170,-23170,-23170, 23170, 23170,-23170,-23170, 23170}, + {-23170, 23170, 23170,-23170, 23170, 23170, 23170,-23170,-23170,-23170, 23170,-23170}, + {-23170, 23170, 23170, 23170,-23170,-23170,-23170, 23170, 23170,-23170, 23170,-23170}, + {-23170,-23170, 23170,-23170,-23170, 23170, 23170, 23170,-23170,-23170, 23170,-23170}, + { 23170, 23170, 23170, 23170, 23170,-23170,-23170, 23170, 23170, 23170,-23170,-23170}, + {-23170, 23170, 23170, 23170,-23170, 23170, 23170, 23170, 23170, 23170,-23170, 23170}, + {-23170, 23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170,-23170}, + { 23170,-23170,-23170, 23170,-23170,-23170, 23170, 23170, 23170,-23170,-23170,-23170}, + {-23170,-23170, 23170,-23170, 23170, 23170, 23170, 23170,-23170,-23170, 23170, 23170}, + {-23170, 23170, 23170,-23170, 23170, 23170,-23170, 23170,-23170, 23170,-23170, 23170}, + {-23170, 23170, 23170,-23170, 23170,-23170, 23170,-23170,-23170,-23170, 23170,-23170}, + {-23170,-23170, 23170, 23170, 23170,-23170,-23170, 23170,-23170, 23170, 23170,-23170}, + { 23170,-23170, 23170, 23170, 23170,-23170,-23170,-23170, 23170, 23170,-23170, 23170}, + {-23170, 23170,-23170, 23170,-23170,-23170, 23170,-23170,-23170, 23170, 23170,-23170} + }; + static const int16_t table_5_2_2_2_3_Re[30][18]={ // Table 5.2.2.2-3 (Re part) TS 38.211 Subclause 5.2.2.2 Base sequences of length less than 36 (M_ZC=18) + { 23170,-23170, 23170,-23170,-23170, 23170,-23170, 23170,-23170,-23170, 23170, 23170, 23170, 23170, 23170, 23170, 23170, 23170}, + {-23170,-23170,-23170, 23170, 23170,-23170,-23170, 23170,-23170,-23170, 23170,-23170,-23170, 23170, 23170,-23170,-23170,-23170}, + {-23170,-23170, 23170, 23170, 23170,-23170,-23170, 23170, 23170, 23170, 23170, 23170, 23170, 23170,-23170, 23170,-23170, 23170}, + {-23170,-23170,-23170,-23170,-23170, 23170,-23170, 23170,-23170,-23170, 23170,-23170,-23170,-23170, 23170,-23170, 23170, 23170}, + { 23170, 23170, 23170, 23170,-23170, 23170, 23170,-23170,-23170,-23170, 23170,-23170, 23170, 23170, 23170, 23170,-23170, 23170}, + {-23170,-23170, 23170, 23170,-23170, 23170, 23170, 23170, 23170,-23170, 23170, 23170, 23170,-23170,-23170,-23170,-23170, 23170}, + {-23170,-23170, 23170, 23170,-23170, 23170,-23170, 23170, 23170, 23170,-23170, 23170,-23170,-23170, 23170,-23170,-23170,-23170}, + { 23170, 23170,-23170,-23170,-23170, 23170,-23170,-23170,-23170, 23170, 23170, 23170, 23170, 23170,-23170,-23170, 23170,-23170}, + {-23170, 23170,-23170,-23170, 23170,-23170,-23170,-23170, 23170,-23170, 23170,-23170,-23170,-23170, 23170, 23170, 23170,-23170}, + {-23170, 23170,-23170, 23170,-23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170, 23170,-23170,-23170,-23170,-23170}, + {-23170,-23170,-23170, 23170,-23170,-23170, 23170, 23170,-23170,-23170,-23170, 23170,-23170, 23170,-23170,-23170,-23170,-23170}, + {-23170,-23170,-23170,-23170,-23170, 23170, 23170,-23170, 23170, 23170, 23170,-23170, 23170,-23170,-23170, 23170,-23170, 23170}, + {-23170, 23170,-23170,-23170, 23170, 23170, 23170,-23170, 23170,-23170, 23170, 23170,-23170,-23170, 23170,-23170, 23170,-23170}, + { 23170, 23170,-23170,-23170,-23170,-23170, 23170,-23170,-23170,-23170,-23170, 23170,-23170, 23170,-23170, 23170,-23170, 23170}, + {-23170,-23170, 23170,-23170, 23170,-23170, 23170, 23170,-23170,-23170, 23170, 23170,-23170,-23170, 23170,-23170, 23170, 23170}, + {-23170, 23170,-23170, 23170,-23170,-23170,-23170, 23170,-23170,-23170, 23170,-23170,-23170,-23170,-23170, 23170, 23170,-23170}, + {-23170, 23170,-23170, 23170,-23170, 23170,-23170,-23170, 23170,-23170,-23170,-23170, 23170, 23170,-23170,-23170, 23170,-23170}, + {-23170, 23170,-23170,-23170, 23170,-23170, 23170,-23170, 23170, 23170, 23170,-23170, 23170, 23170, 23170,-23170,-23170, 23170}, + {-23170, 23170,-23170, 23170, 23170,-23170, 23170,-23170,-23170,-23170, 23170,-23170,-23170, 23170, 23170, 23170, 23170, 23170}, + {-23170,-23170,-23170,-23170, 23170,-23170, 23170,-23170, 23170, 23170, 23170,-23170, 23170,-23170,-23170, 23170,-23170,-23170}, + {-23170, 23170, 23170,-23170, 23170, 23170,-23170,-23170, 23170,-23170, 23170,-23170,-23170,-23170, 23170, 23170, 23170,-23170}, + { 23170,-23170, 23170,-23170,-23170,-23170, 23170,-23170, 23170,-23170,-23170, 23170,-23170, 23170, 23170,-23170,-23170,-23170}, + {-23170,-23170, 23170, 23170, 23170, 23170, 23170,-23170, 23170,-23170,-23170,-23170,-23170, 23170,-23170, 23170,-23170, 23170}, + {-23170, 23170,-23170, 23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170,-23170, 23170,-23170, 23170, 23170,-23170,-23170}, + {-23170, 23170, 23170, 23170,-23170, 23170,-23170, 23170,-23170,-23170, 23170,-23170, 23170, 23170, 23170,-23170,-23170,-23170}, + {-23170,-23170, 23170,-23170,-23170,-23170,-23170, 23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170}, + {-23170, 23170, 23170,-23170, 23170,-23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170, 23170,-23170, 23170, 23170, 23170}, + {-23170,-23170,-23170,-23170,-23170, 23170,-23170, 23170,-23170, 23170, 23170,-23170,-23170,-23170, 23170, 23170, 23170,-23170}, + { 23170,-23170, 23170,-23170,-23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170,-23170, 23170,-23170,-23170, 23170}, + {-23170,-23170, 23170, 23170, 23170, 23170, 23170, 23170, 23170,-23170,-23170,-23170, 23170, 23170,-23170, 23170,-23170, 23170} + }; + static const int16_t table_5_2_2_2_3_Im[30][18]={ // Table 5.2.2.2-3 (Im part) TS 38.211 Subclause 5.2.2.2 Base sequences of length less than 36 (M_ZC=18) + {-23170, 23170,-23170,-23170, 23170, 23170,-23170,-23170, 23170,-23170,-23170,-23170, 23170, 23170, 23170,-23170,-23170,-23170}, + { 23170,-23170, 23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170,-23170, 23170,-23170, 23170}, + {-23170, 23170, 23170,-23170,-23170, 23170,-23170,-23170, 23170, 23170, 23170, 23170, 23170,-23170, 23170,-23170,-23170,-23170}, + {-23170,-23170, 23170, 23170, 23170, 23170,-23170, 23170, 23170, 23170, 23170,-23170,-23170, 23170,-23170,-23170,-23170, 23170}, + { 23170, 23170,-23170,-23170,-23170,-23170, 23170,-23170,-23170,-23170, 23170,-23170,-23170,-23170, 23170,-23170, 23170, 23170}, + { 23170,-23170, 23170, 23170, 23170,-23170, 23170,-23170,-23170,-23170, 23170, 23170,-23170, 23170, 23170,-23170, 23170,-23170}, + {-23170, 23170,-23170, 23170, 23170, 23170,-23170,-23170, 23170, 23170,-23170, 23170, 23170, 23170,-23170,-23170,-23170,-23170}, + { 23170, 23170,-23170, 23170, 23170, 23170, 23170,-23170, 23170,-23170, 23170, 23170,-23170, 23170,-23170,-23170,-23170, 23170}, + {-23170, 23170,-23170,-23170, 23170,-23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170, 23170}, + { 23170,-23170, 23170, 23170,-23170,-23170,-23170, 23170,-23170,-23170, 23170, 23170, 23170, 23170, 23170,-23170, 23170,-23170}, + {-23170,-23170,-23170, 23170,-23170, 23170, 23170, 23170, 23170,-23170,-23170, 23170, 23170,-23170, 23170,-23170,-23170, 23170}, + {-23170,-23170, 23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170,-23170,-23170,-23170, 23170,-23170}, + {-23170,-23170,-23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170,-23170, 23170, 23170, 23170}, + { 23170, 23170,-23170,-23170,-23170,-23170, 23170, 23170,-23170, 23170, 23170, 23170,-23170,-23170, 23170,-23170,-23170, 23170}, + {-23170, 23170,-23170,-23170,-23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170, 23170,-23170, 23170, 23170, 23170, 23170}, + { 23170, 23170,-23170, 23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170,-23170, 23170,-23170,-23170, 23170, 23170}, + {-23170,-23170,-23170,-23170,-23170, 23170, 23170,-23170,-23170, 23170, 23170, 23170, 23170,-23170,-23170, 23170,-23170,-23170}, + {-23170,-23170, 23170, 23170,-23170, 23170,-23170,-23170,-23170, 23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170, 23170}, + {-23170, 23170,-23170,-23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170, 23170,-23170,-23170}, + { 23170, 23170, 23170,-23170,-23170,-23170,-23170, 23170,-23170, 23170,-23170,-23170, 23170,-23170,-23170,-23170, 23170, 23170}, + {-23170, 23170, 23170,-23170, 23170, 23170, 23170,-23170,-23170,-23170,-23170, 23170,-23170, 23170,-23170,-23170,-23170,-23170}, + { 23170,-23170,-23170,-23170, 23170, 23170,-23170,-23170, 23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170, 23170, 23170}, + {-23170,-23170, 23170,-23170,-23170, 23170, 23170,-23170,-23170, 23170, 23170, 23170, 23170,-23170, 23170, 23170, 23170, 23170}, + { 23170,-23170,-23170, 23170,-23170,-23170,-23170, 23170, 23170,-23170, 23170,-23170,-23170, 23170, 23170, 23170, 23170, 23170}, + { 23170,-23170,-23170, 23170,-23170,-23170,-23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170, 23170,-23170,-23170, 23170}, + {-23170,-23170, 23170,-23170, 23170, 23170, 23170,-23170, 23170, 23170, 23170,-23170,-23170,-23170, 23170,-23170,-23170,-23170}, + {-23170,-23170,-23170,-23170, 23170,-23170, 23170,-23170,-23170,-23170, 23170, 23170,-23170,-23170, 23170,-23170,-23170,-23170}, + {-23170,-23170, 23170, 23170,-23170, 23170, 23170,-23170,-23170, 23170,-23170,-23170, 23170,-23170,-23170,-23170,-23170, 23170}, + {-23170,-23170, 23170,-23170,-23170,-23170, 23170, 23170, 23170, 23170,-23170, 23170, 23170,-23170,-23170, 23170,-23170, 23170}, + {-23170, 23170, 23170,-23170,-23170,-23170,-23170, 23170,-23170, 23170, 23170,-23170,-23170, 23170, 23170,-23170, 23170,-23170} + }; + static const int16_t table_5_2_2_2_4_Re[30][24]={ // Table 5.2.2.2-4 (Re part) TS 38.211 Subclause 5.2.2.2 Base sequences of length less than 36 (M_ZC=24) + { 23170,-23170,-23170, 23170,-23170, 23170,-23170, 23170, 23170,-23170, 23170,-23170, 23170, 23170,-23170,-23170, 23170,-23170,-23170,-23170,-23170,-23170,-23170,-23170}, + { 23170,-23170,-23170, 23170, 23170,-23170, 23170,-23170,-23170, 23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170,-23170, 23170,-23170,-23170,-23170,-23170}, + { 23170,-23170,-23170, 23170, 23170, 23170,-23170, 23170,-23170, 23170,-23170, 23170, 23170,-23170, 23170, 23170,-23170, 23170,-23170, 23170, 23170,-23170,-23170,-23170}, + { 23170,-23170,-23170, 23170,-23170, 23170,-23170,-23170, 23170, 23170, 23170, 23170,-23170,-23170, 23170,-23170,-23170,-23170, 23170,-23170,-23170, 23170,-23170,-23170}, + { 23170,-23170,-23170,-23170, 23170,-23170, 23170, 23170, 23170,-23170, 23170,-23170, 23170, 23170,-23170, 23170,-23170, 23170, 23170,-23170, 23170, 23170,-23170,-23170}, + {-23170, 23170, 23170,-23170,-23170, 23170, 23170,-23170,-23170, 23170, 23170,-23170, 23170,-23170, 23170, 23170,-23170, 23170,-23170, 23170,-23170,-23170,-23170,-23170}, + {-23170,-23170, 23170,-23170, 23170, 23170,-23170, 23170,-23170, 23170, 23170,-23170, 23170,-23170,-23170,-23170,-23170, 23170, 23170, 23170, 23170, 23170,-23170,-23170}, + {-23170, 23170,-23170, 23170, 23170, 23170,-23170,-23170,-23170, 23170,-23170, 23170,-23170,-23170, 23170, 23170, 23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170}, + {-23170, 23170,-23170,-23170, 23170, 23170, 23170,-23170,-23170, 23170, 23170,-23170, 23170, 23170,-23170, 23170, 23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170}, + { 23170, 23170, 23170,-23170, 23170, 23170, 23170,-23170, 23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170, 23170,-23170, 23170,-23170,-23170, 23170,-23170,-23170}, + {-23170,-23170,-23170, 23170,-23170,-23170,-23170, 23170,-23170, 23170,-23170, 23170, 23170,-23170, 23170, 23170,-23170, 23170, 23170,-23170,-23170, 23170,-23170,-23170}, + {-23170,-23170, 23170,-23170, 23170, 23170, 23170, 23170,-23170,-23170, 23170, 23170, 23170,-23170,-23170, 23170,-23170,-23170, 23170, 23170,-23170, 23170,-23170,-23170}, + {-23170,-23170,-23170, 23170,-23170, 23170,-23170, 23170, 23170, 23170,-23170, 23170,-23170,-23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170,-23170,-23170}, + {-23170,-23170, 23170,-23170, 23170,-23170,-23170, 23170, 23170,-23170, 23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170,-23170,-23170, 23170, 23170,-23170,-23170}, + {-23170, 23170,-23170, 23170, 23170,-23170, 23170,-23170,-23170, 23170, 23170,-23170,-23170, 23170,-23170,-23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170}, + {-23170, 23170, 23170,-23170, 23170,-23170,-23170, 23170, 23170,-23170, 23170, 23170, 23170,-23170, 23170,-23170, 23170,-23170, 23170, 23170, 23170, 23170,-23170,-23170}, + {-23170,-23170, 23170, 23170,-23170,-23170,-23170, 23170, 23170, 23170, 23170, 23170, 23170, 23170, 23170,-23170,-23170, 23170,-23170, 23170, 23170, 23170, 23170,-23170}, + {-23170, 23170,-23170, 23170, 23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170, 23170, 23170, 23170, 23170, 23170,-23170,-23170, 23170, 23170, 23170,-23170,-23170}, + {-23170, 23170,-23170, 23170,-23170,-23170, 23170,-23170, 23170,-23170,-23170,-23170,-23170,-23170, 23170,-23170,-23170, 23170, 23170,-23170, 23170, 23170,-23170,-23170}, + {-23170,-23170,-23170,-23170, 23170, 23170, 23170, 23170, 23170,-23170, 23170, 23170, 23170,-23170,-23170, 23170,-23170, 23170, 23170, 23170,-23170,-23170, 23170,-23170}, + {-23170,-23170, 23170, 23170, 23170,-23170, 23170, 23170,-23170, 23170,-23170,-23170, 23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170, 23170, 23170,-23170,-23170}, + {-23170, 23170, 23170, 23170,-23170,-23170, 23170, 23170,-23170, 23170,-23170,-23170, 23170,-23170,-23170, 23170, 23170, 23170, 23170, 23170,-23170,-23170,-23170,-23170}, + {-23170, 23170,-23170,-23170,-23170, 23170,-23170,-23170, 23170, 23170,-23170, 23170,-23170,-23170,-23170,-23170, 23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170}, + {-23170, 23170, 23170,-23170, 23170, 23170, 23170, 23170, 23170,-23170,-23170, 23170, 23170, 23170, 23170, 23170, 23170,-23170,-23170,-23170,-23170, 23170, 23170,-23170}, + {-23170,-23170, 23170,-23170, 23170, 23170, 23170,-23170, 23170, 23170,-23170,-23170, 23170,-23170,-23170,-23170,-23170, 23170,-23170, 23170, 23170, 23170,-23170,-23170}, + {-23170, 23170, 23170,-23170,-23170, 23170, 23170,-23170, 23170,-23170, 23170, 23170, 23170, 23170, 23170,-23170,-23170,-23170, 23170, 23170, 23170, 23170, 23170,-23170}, + { 23170,-23170, 23170, 23170,-23170,-23170, 23170, 23170, 23170,-23170, 23170,-23170, 23170,-23170, 23170, 23170,-23170,-23170,-23170, 23170,-23170, 23170,-23170,-23170}, + {-23170,-23170,-23170, 23170,-23170,-23170,-23170, 23170,-23170, 23170, 23170, 23170,-23170, 23170,-23170,-23170, 23170,-23170, 23170,-23170, 23170, 23170,-23170,-23170}, + {-23170, 23170,-23170, 23170,-23170, 23170, 23170,-23170, 23170,-23170,-23170, 23170, 23170,-23170, 23170,-23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170}, + {-23170,-23170, 23170, 23170,-23170, 23170, 23170,-23170, 23170,-23170, 23170,-23170, 23170,-23170,-23170, 23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170} + }; + static const int16_t table_5_2_2_2_4_Im[30][24]={ // Table 5.2.2.2-4 (Im part) TS 38.211 Subclause 5.2.2.2 Base sequences of length less than 36 (M_ZC=24) + {-23170,-23170, 23170,-23170, 23170, 23170, 23170,-23170, 23170,-23170,-23170,-23170,-23170, 23170, 23170,-23170,-23170,-23170, 23170, 23170, 23170,-23170,-23170,-23170}, + {-23170,-23170, 23170, 23170, 23170,-23170, 23170,-23170,-23170, 23170,-23170,-23170,-23170, 23170,-23170, 23170, 23170, 23170,-23170, 23170, 23170, 23170,-23170,-23170}, + {-23170,-23170,-23170, 23170,-23170,-23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170, 23170, 23170,-23170,-23170,-23170, 23170,-23170,-23170}, + { 23170,-23170, 23170,-23170,-23170,-23170, 23170, 23170, 23170,-23170, 23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170,-23170, 23170,-23170,-23170,-23170,-23170}, + {-23170, 23170,-23170,-23170,-23170, 23170,-23170,-23170, 23170, 23170, 23170, 23170,-23170,-23170,-23170, 23170, 23170, 23170,-23170,-23170, 23170,-23170,-23170,-23170}, + {-23170,-23170, 23170,-23170,-23170, 23170, 23170,-23170, 23170,-23170,-23170,-23170, 23170, 23170, 23170,-23170,-23170,-23170,-23170, 23170,-23170,-23170,-23170,-23170}, + {-23170, 23170, 23170, 23170,-23170, 23170,-23170, 23170,-23170, 23170,-23170,-23170,-23170,-23170,-23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170,-23170,-23170}, + {-23170, 23170, 23170,-23170, 23170,-23170, 23170,-23170, 23170,-23170,-23170,-23170,-23170, 23170,-23170,-23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170,-23170}, + {-23170, 23170,-23170, 23170,-23170,-23170,-23170,-23170, 23170, 23170,-23170,-23170,-23170, 23170, 23170,-23170, 23170,-23170, 23170,-23170,-23170,-23170,-23170,-23170}, + { 23170, 23170,-23170,-23170,-23170, 23170, 23170,-23170, 23170,-23170, 23170,-23170, 23170,-23170,-23170, 23170,-23170,-23170, 23170, 23170,-23170, 23170,-23170,-23170}, + {-23170,-23170,-23170,-23170, 23170,-23170, 23170, 23170, 23170, 23170,-23170,-23170,-23170,-23170, 23170, 23170, 23170, 23170,-23170,-23170, 23170, 23170, 23170,-23170}, + {-23170, 23170,-23170, 23170, 23170,-23170,-23170,-23170, 23170, 23170, 23170, 23170, 23170, 23170, 23170, 23170,-23170,-23170,-23170, 23170,-23170, 23170, 23170,-23170}, + { 23170,-23170, 23170,-23170,-23170, 23170, 23170, 23170,-23170,-23170,-23170,-23170, 23170,-23170, 23170,-23170,-23170, 23170, 23170,-23170,-23170, 23170,-23170,-23170}, + {-23170, 23170,-23170, 23170,-23170, 23170, 23170, 23170, 23170,-23170, 23170, 23170,-23170, 23170,-23170,-23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170}, + {-23170, 23170,-23170,-23170,-23170, 23170, 23170, 23170,-23170, 23170,-23170, 23170, 23170,-23170,-23170, 23170,-23170,-23170,-23170,-23170,-23170,-23170, 23170,-23170}, + {-23170,-23170,-23170,-23170, 23170,-23170,-23170,-23170,-23170, 23170,-23170, 23170,-23170, 23170, 23170,-23170,-23170, 23170, 23170, 23170,-23170,-23170,-23170,-23170}, + {-23170,-23170, 23170,-23170, 23170, 23170,-23170,-23170, 23170,-23170,-23170, 23170, 23170,-23170,-23170, 23170,-23170, 23170,-23170, 23170,-23170,-23170,-23170,-23170}, + { 23170,-23170, 23170,-23170, 23170,-23170, 23170, 23170,-23170,-23170, 23170,-23170,-23170,-23170,-23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170,-23170,-23170}, + {-23170, 23170,-23170, 23170,-23170,-23170, 23170,-23170, 23170,-23170,-23170,-23170,-23170,-23170, 23170,-23170,-23170, 23170, 23170,-23170, 23170, 23170,-23170,-23170}, + {-23170,-23170, 23170, 23170, 23170,-23170,-23170,-23170, 23170,-23170,-23170, 23170,-23170, 23170,-23170,-23170,-23170,-23170,-23170, 23170,-23170, 23170,-23170,-23170}, + {-23170,-23170,-23170,-23170,-23170,-23170, 23170,-23170,-23170,-23170, 23170,-23170, 23170,-23170, 23170,-23170, 23170, 23170, 23170,-23170,-23170, 23170,-23170,-23170}, + { 23170,-23170, 23170,-23170, 23170,-23170, 23170, 23170, 23170,-23170,-23170, 23170, 23170,-23170, 23170,-23170,-23170,-23170,-23170, 23170,-23170,-23170,-23170,-23170}, + {-23170, 23170,-23170, 23170,-23170, 23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170,-23170, 23170, 23170, 23170, 23170,-23170}, + {-23170,-23170, 23170,-23170,-23170,-23170, 23170, 23170, 23170, 23170, 23170,-23170, 23170,-23170, 23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170,-23170,-23170}, + {-23170, 23170,-23170,-23170,-23170,-23170,-23170, 23170,-23170,-23170, 23170,-23170,-23170, 23170,-23170, 23170,-23170,-23170, 23170, 23170, 23170,-23170,-23170,-23170}, + {-23170, 23170,-23170,-23170,-23170,-23170, 23170,-23170,-23170,-23170, 23170, 23170,-23170, 23170, 23170, 23170, 23170, 23170,-23170, 23170,-23170, 23170,-23170,-23170}, + {-23170, 23170,-23170,-23170, 23170, 23170,-23170,-23170,-23170, 23170,-23170,-23170, 23170, 23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170,-23170,-23170,-23170}, + { 23170,-23170,-23170,-23170, 23170, 23170,-23170,-23170, 23170, 23170, 23170, 23170, 23170,-23170, 23170,-23170,-23170, 23170,-23170, 23170, 23170,-23170,-23170,-23170}, + {-23170, 23170,-23170, 23170,-23170, 23170, 23170, 23170, 23170,-23170,-23170,-23170, 23170, 23170,-23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170,-23170}, + { 23170,-23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170, 23170,-23170,-23170,-23170,-23170, 23170,-23170, 23170, 23170, 23170,-23170, 23170,-23170,-23170,-23170} + }; + + /* + * The following tables implement TS 38.211 table 6.3.2.4.1-1: Number of PUCCH symbols and the corresponding N_SF_mprime_PUCCH_1 + * One table for no intra-slot hopping + * Two tables for intra-slot hopping (mprime=0 and mprime=1) + */ + static const uint8_t table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_noHop[14] = {0,0,0,2,2,3,3,4,4,5,5,6,6,7}; // for index PUCCH-length, we obtain N_SF_mprime_PUCCH_1 when no intra-slot hopping + static const uint8_t table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_m0Hop[14] = {0,0,0,1,1,1,1,2,2,2,2,3,3,3}; // for index PUCCH-length, we obtain N_SF_mprime_PUCCH_1 when intra-slot hopping and mprime=0 + static const uint8_t table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_m1Hop[14] = {0,0,0,1,1,2,2,2,2,3,3,3,3,4}; // for index PUCCH-length, we obtain N_SF_mprime_PUCCH_1 when intra-slot hopping and mprime=1 + /* + * The following tables implement TS 38.211 table 6.4.1.3.1.1-1: Number of DM-RS symbols and the corresponding N_SF_mprime_PUCCH_1 + * One table for no intra-slot hopping + * Two tables for intra-slot hopping (mprime=0 and mprime=1) + */ + static const uint8_t table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_noHop[14] = {0,0,0,2,3,3,4,4,5,5,6,6,7,7}; // for index PUCCH-DM-RS-length, we obtain N_SF_mprime_PUCCH_1 when no intra-slot hopping + static const uint8_t table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_m0Hop[14] = {0,0,0,1,1,2,2,2,2,3,3,3,3,4}; // for index PUCCH-DM-RS-length, we obtain N_SF_mprime_PUCCH_1 when intra-slot hopping and mprime=0 + static const uint8_t table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_m1Hop[14] = {0,0,0,1,2,1,2,2,3,2,3,3,4,3}; // for index PUCCH-DM-RS-length, we obtain N_SF_mprime_PUCCH_1 when intra-slot hopping and mprime=1 + /* The following tables implement TS 38.211 table 6.3.2.4.1-2: Orthogonal sequences wi(m)=exp(j*2*pi*phi(m)/N_SF) for PUCCH format 1 + uint16_t table_6_3_2_4_1_2_W2[2][2] = {{0,0}, {0,1}}; + uint16_t table_6_3_2_4_1_2_W3[3][3] = {{0,0,0}, {0,1,2}, {0,2,1}}; + uint16_t table_6_3_2_4_1_2_W4[4][4] = {{0,0,0,0}, {0,2,0,2}, {0,0,2,2} , {0,2,2,0}}; + uint16_t table_6_3_2_4_1_2_W5[2][2] = {{0,0,0,0,0}, {0,1,2,3,4}, {0,2,4,1,3}, {0,3,1,4,2}, {0,4,3,2,1}}; + uint16_t table_6_3_2_4_1_2_W6[2][2] = {{0,0,0,0,0,0}, {0,1,2,3,4,5}, {0,2,4,0,2,4}, {0,3,0,3,0,3}, {0,4,2,0,4,2}, {0,5,4,3,2,1}}; + uint16_t table_6_3_2_4_1_2_W7[2][2] = {{0,0,0,0,0,0,0},{0,1,2,3,4,5,6},{0,2,4,6,1,3,5},{0,3,6,2,5,1,4},{0,4,1,5,2,6,3},{0,5,3,1,6,4,2},{0,6,5,4,3,2,1}}; + */ + static const int16_t table_6_3_2_4_1_2_Wi_Re[8][7][7] = { + {{0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}}, + {{32767,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}}, + {{32767,32767,0,0,0,0,0}, {32767,-32767,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}}, + {{32767,32767,32767,0,0,0,0}, {32767,-16384,-16384,0,0,0,0}, {32767,-16384,-16384,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}}, + {{32767,32767,32767,32767,0,0,0}, {32767,-32767,32767,-32767,0,0,0}, {32767,32767,-32767,-32767,0,0,0}, {32767,-32767,-32767,32767,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}}, + {{32767,32767,32767,32767,32767,0,0}, {32767,10126,-26509,-26509,10126,0,0}, {32767,-26509,10126,10126,-26509,0,0}, {32767,-26509,10126,10126,-26509,0,0}, {32767,10126,-26509,-26509,10126,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}}, + {{32767,32767,32767,32767,32767,32767,0}, {32767,16384,-16384,-32767,-16384,16384,0}, {32767,-16384,-16384,32767,-16384,-16384,0}, {32767,-32767,32767,-32767,32767,-32767,0}, {32767,-16384,-16384,32767,-16384,-16384,0}, {32767,16384,-16384,-32767,-16384,16384,0}, {0,0,0,0,0,0,0}}, + {{32767,32767,32767,32767,32767,32767,32767},{32767,20430,-7291,-29522,-29522,-7291,20430},{32767,-7291,-29522,20430,20430,-29522,-7291},{32767,-29522,20430,-7291,-7291,20430,-29522},{32767,-29522,20430,-7291,-7291,20430,-29522},{32767,-7291,-29522,20430,20430,-29522,-7291},{32767,20430,-7291,-29522,-29522,-7291,20430}} + }; + static const int16_t table_6_3_2_4_1_2_Wi_Im[8][7][7] = { + {{0,0,0,0,0,0,0},{0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}}, + {{0,0,0,0,0,0,0},{0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}}, + {{0,0,0,0,0,0,0},{0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}}, + {{0,0,0,0,0,0,0},{0,28377,-28377,0,0,0,0}, {0,-28377,28377,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}}, + {{0,0,0,0,0,0,0},{0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}}, + {{0,0,0,0,0,0,0},{0,31163,19260,-19260,-31163,0,0}, {0,19260,-31163,31163,-19260,0,0}, {0,-19260,31163,-31163,19260,0,0}, {0,-31163,-19260,19260,31163,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}}, + {{0,0,0,0,0,0,0},{0,28377,28377,0,-28377,-28377,0}, {0,28377,-28377,0,28377,-28377,0}, {0,0,0,0,0,0,0}, {0,-28377,28377,0,-28377,28377,0}, {0,-28377,-28377,0,28377,28377,0}, {0,0,0,0,0,0,0}}, + {{0,0,0,0,0,0,0},{0,25618,31945,14217,-14217,-31945,-25618},{0,31945,-14217,-25618,25618,14217,-31945},{0,14217,-25618,31945,-31945,25618,-14217},{0,-14217,25618,-31945,31945,-25618,14217},{0,-31945,14217,25618,-25618,-14217,31945},{0,-25618,-31945,-14217,14217,31945,25618}} + }; typedef struct { int size; From 870b25e95ddf41fed739e3af7db6d37bd8e7a05c Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 18 Sep 2025 14:54:36 +0200 Subject: [PATCH 743/964] Fix: define_property() needs FULL_DOCS define_property() has optional FULL_DOCS in cmake 3.23+, but before it's required. I did not notice when adding this. --- openair1/SIMULATION/tests/CMakeLists.txt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/openair1/SIMULATION/tests/CMakeLists.txt b/openair1/SIMULATION/tests/CMakeLists.txt index 273142a1d7..9602d6d1f4 100644 --- a/openair1/SIMULATION/tests/CMakeLists.txt +++ b/openair1/SIMULATION/tests/CMakeLists.txt @@ -1,4 +1,6 @@ -define_property(TEST PROPERTY TEST_DESCRIPTION BRIEF_DOCS "A human-readable description of this test") +define_property(TEST PROPERTY TEST_DESCRIPTION + BRIEF_DOCS "A human-readable description of this test" + FULL_DOCS "A human-readable description of this test") # Define a macro to add tests for different physical simulators macro(add_physim_test test_name test_description test_exec) @@ -23,7 +25,9 @@ macro(add_physim_test test_name test_description test_exec) add_dependencies(tests ${test_exec}) endmacro() -define_property(TEST PROPERTY CHECK_COUNT BRIEF_DOCS "helper property to enumerate checks in environment") +define_property(TEST PROPERTY CHECK_COUNT + BRIEF_DOCS "helper property to enumerate checks in environment" + FULL_DOCS "the property counts the number of threshold checks, used to enumerate environment variables given to analyze-timing.sh") function(add_timed_physim_test test_name test_description test_exec) # catch all the arguments past the last expected arqument and store them in the options_list if (NOT TARGET ${test_exec}) From b03d8abd039a6af44c27dc04e3edf5bcb4abbc05 Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 11 Sep 2025 14:09:41 +0200 Subject: [PATCH 744/964] use common structure to store SRS information for common function (also avoid bad cast) --- .../PHY/NR_UE_TRANSPORT/srs_modulation_nr.c | 161 ++++++++++-------- .../PHY/NR_UE_TRANSPORT/srs_modulation_nr.h | 4 +- openair1/PHY/defs_nr_common.h | 19 ++- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 70 ++++++-- 4 files changed, 166 insertions(+), 88 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.c b/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.c index 44be6a578e..4d1d36a8a6 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.c @@ -177,61 +177,41 @@ uint16_t compute_n_b(frame_t frame_number, * See TS 38.211 - Section 6.4.1.4 Sounding reference signal * ***************************************************************************/ -int generate_srs_nr(nfapi_nr_srs_pdu_t *srs_config_pdu, - NR_DL_FRAME_PARMS *frame_parms, +int generate_srs_nr(NR_DL_FRAME_PARMS *frame_parms, c16_t **txdataF, uint16_t symbol_offset, + int bwp_start, nr_srs_info_t *nr_srs_info, int16_t amp, frame_t frame_number, slot_t slot_number) { -#ifdef SRS_DEBUG - LOG_I(NR_PHY,"Calling %s function\n", __FUNCTION__); -#endif - - // SRS config parameters - uint8_t B_SRS = srs_config_pdu->bandwidth_index; - uint8_t C_SRS = srs_config_pdu->config_index; - uint8_t b_hop = srs_config_pdu->frequency_hopping; - uint8_t K_TC = 2<comb_size; - uint8_t K_TC_overbar = srs_config_pdu->comb_offset; - uint8_t n_SRS_cs = srs_config_pdu->cyclic_shift; - uint8_t n_ID_SRS = srs_config_pdu->sequence_id; - uint8_t n_shift = srs_config_pdu->frequency_position; // It adjusts the SRS allocation to align with the common resource block grid in multiples of four - uint8_t n_RRC = srs_config_pdu->frequency_shift; - uint8_t groupOrSequenceHopping = srs_config_pdu->group_or_sequence_hopping; - uint8_t l_offset = srs_config_pdu->time_start_position; - uint16_t T_SRS = srs_config_pdu->t_srs; - uint16_t T_offset = srs_config_pdu->t_offset; - uint8_t R = 1<num_repetitions; + uint8_t K_TC = 2 << nr_srs_info->comb_size; /* Number of antenna ports (M) can't be higher than number of physical antennas (N): M <= N */ - uint8_t num_ant_ports = 1 << srs_config_pdu->num_ant_ports; // Number of antenna port for transmission - int N_ap = num_ant_ports > frame_parms->nb_antennas_tx ? frame_parms->nb_antennas_tx : num_ant_ports; - uint8_t N_symb_SRS = 1<num_symbols; // Number of consecutive OFDM symbols - uint8_t l0 = frame_parms->symbols_per_slot - 1 - l_offset; // Starting symbol position in the time domain - uint8_t n_SRS_cs_max = srs_max_number_cs[srs_config_pdu->comb_size]; - uint16_t m_SRS_b = get_m_srs(C_SRS, B_SRS); // Number of resource blocks + int N_ap = nr_srs_info->n_srs_ports > frame_parms->nb_antennas_tx ? frame_parms->nb_antennas_tx : nr_srs_info->n_srs_ports; + uint8_t l0 = frame_parms->symbols_per_slot - 1 - nr_srs_info->l_offset; // Starting symbol position in the time domain + uint8_t n_SRS_cs_max = srs_max_number_cs[nr_srs_info->comb_size]; + uint16_t m_SRS_b = get_m_srs(nr_srs_info->C_SRS, nr_srs_info->B_SRS); // Number of resource blocks uint16_t M_sc_b_SRS = m_SRS_b * NR_NB_SC_PER_RB/K_TC; // Length of the SRS sequence #ifdef SRS_DEBUG LOG_I(NR_PHY,"Frame = %i, slot = %i\n", frame_number, slot_number); - LOG_I(NR_PHY,"B_SRS = %i\n", B_SRS); - LOG_I(NR_PHY,"C_SRS = %i\n", C_SRS); - LOG_I(NR_PHY,"b_hop = %i\n", b_hop); + LOG_I(NR_PHY,"B_SRS = %i\n", nr_srs_info->B_SRS); + LOG_I(NR_PHY,"C_SRS = %i\n", nr_srs_info->C_SRS); + LOG_I(NR_PHY,"b_hop = %i\n", nr_srs_info->b_hop); LOG_I(NR_PHY,"K_TC = %i\n", K_TC); - LOG_I(NR_PHY,"K_TC_overbar = %i\n", K_TC_overbar); - LOG_I(NR_PHY,"n_SRS_cs = %i\n", n_SRS_cs); - LOG_I(NR_PHY,"n_ID_SRS = %i\n", n_ID_SRS); - LOG_I(NR_PHY,"n_shift = %i\n", n_shift); - LOG_I(NR_PHY,"n_RRC = %i\n", n_RRC); - LOG_I(NR_PHY,"groupOrSequenceHopping = %i\n", groupOrSequenceHopping); - LOG_I(NR_PHY,"l_offset = %i\n", l_offset); - LOG_I(NR_PHY,"T_SRS = %i\n", T_SRS); - LOG_I(NR_PHY,"T_offset = %i\n", T_offset); - LOG_I(NR_PHY,"R = %i\n", R); + LOG_I(NR_PHY,"K_TC_overbar = %i\n", nr_srs_info->K_TC_overbar); + LOG_I(NR_PHY,"n_SRS_cs = %i\n", nr_srs_info->n_SRS_cs); + LOG_I(NR_PHY,"n_ID_SRS = %i\n", nr_srs_info->n_ID_SRS); + LOG_I(NR_PHY,"n_shift = %i\n", nr_srs_info->n_shift); + LOG_I(NR_PHY,"n_RRC = %i\n", nr_srs_info->n_RRC); + LOG_I(NR_PHY,"groupOrSequenceHopping = %i\n", nr_srs_info->groupOrSequenceHopping); + LOG_I(NR_PHY,"l_offset = %i\n", nr_srs_info->l_offset); + LOG_I(NR_PHY,"T_SRS = %i\n", nr_srs_info->T_SRS); + LOG_I(NR_PHY,"T_offset = %i\n", nr_srs_info->T_offset); + LOG_I(NR_PHY,"R = %i\n", nr_srs_info->R); LOG_I(NR_PHY,"N_ap = %i\n", N_ap); - LOG_I(NR_PHY,"N_symb_SRS = %i\n", N_symb_SRS); + LOG_I(NR_PHY,"N_symb_SRS = %i\n", nr_srs_info->N_symb_SRS); LOG_I(NR_PHY,"l0 = %i\n", l0); LOG_I(NR_PHY,"n_SRS_cs_max = %i\n", n_SRS_cs_max); LOG_I(NR_PHY,"m_SRS_b = %i\n", m_SRS_b); @@ -240,28 +220,28 @@ int generate_srs_nr(nfapi_nr_srs_pdu_t *srs_config_pdu, // Validation of SRS config parameters - if (R == 0) { - LOG_E(NR_PHY, "generate_srs: this parameter repetition factor %d is not consistent !\n", R); + if (nr_srs_info->R == 0) { + LOG_E(NR_PHY, "generate_srs: this parameter repetition factor %d is not consistent !\n", nr_srs_info->R); return -1; - } else if (R > N_symb_SRS) { - LOG_E(NR_PHY, "generate_srs: R %d can not be greater than N_symb_SRS %d !\n", R, N_symb_SRS); + } else if (nr_srs_info->R > nr_srs_info->N_symb_SRS) { + LOG_E(NR_PHY, "generate_srs: R %d can not be greater than N_symb_SRS %d !\n", nr_srs_info->R, nr_srs_info->N_symb_SRS); return -1; } - if (n_SRS_cs >= n_SRS_cs_max) { - LOG_E(NR_PHY, "generate_srs: inconsistent parameter n_SRS_cs %d >= n_SRS_cs_max %d !\n", n_SRS_cs, n_SRS_cs_max); + if (nr_srs_info->n_SRS_cs >= n_SRS_cs_max) { + LOG_E(NR_PHY, "generate_srs: inconsistent parameter n_SRS_cs %d >= n_SRS_cs_max %d !\n", nr_srs_info->n_SRS_cs, n_SRS_cs_max); return -1; } - if (T_SRS == 0) { - LOG_E(NR_PHY, "generate_srs: inconsistent parameter T_SRS %d can not be equal to zero !\n", T_SRS); + if (nr_srs_info->T_SRS == 0) { + LOG_E(NR_PHY, "generate_srs: inconsistent parameter T_SRS %d can not be equal to zero !\n", nr_srs_info->T_SRS); return -1; } else { int index = 0; - while (srs_periodicity[index] != T_SRS) { + while (srs_periodicity[index] != nr_srs_info->T_SRS) { index++; if (index == SRS_PERIODICITY) { - LOG_E(NR_PHY, "generate_srs: inconsistent parameter T_SRS %d not specified !\n", T_SRS); + LOG_E(NR_PHY, "generate_srs: inconsistent parameter T_SRS %d not specified !\n", nr_srs_info->T_SRS); return -1; } } @@ -271,9 +251,9 @@ int generate_srs_nr(nfapi_nr_srs_pdu_t *srs_config_pdu, if(nr_srs_info) { nr_srs_info->srs_generated_signal_bits = log2_approx(amp); } - uint64_t subcarrier_offset = frame_parms->first_carrier_offset + srs_config_pdu->bwp_start*NR_NB_SC_PER_RB; + uint64_t subcarrier_offset = frame_parms->first_carrier_offset + bwp_start * NR_NB_SC_PER_RB; double sqrt_N_ap = sqrt(N_ap); - uint16_t n_b[B_SRS + 1]; + uint16_t n_b[nr_srs_info->B_SRS + 1]; // Find index of table which is for this SRS length uint16_t M_sc_b_SRS_index = 0; @@ -288,7 +268,7 @@ int generate_srs_nr(nfapi_nr_srs_pdu_t *srs_config_pdu, LOG_I(NR_PHY,"============ port %d ============\n", p_index); #endif - uint16_t n_SRS_cs_i = (n_SRS_cs + (n_SRS_cs_max * (SRS_antenna_port[p_index] - 1000)/N_ap))%n_SRS_cs_max; + uint16_t n_SRS_cs_i = (nr_srs_info->n_SRS_cs + (n_SRS_cs_max * (SRS_antenna_port[p_index] - 1000)/N_ap))%n_SRS_cs_max; double alpha_i = 2 * M_PI * ((double)n_SRS_cs_i / (double)n_SRS_cs_max); #ifdef SRS_DEBUG @@ -296,7 +276,7 @@ int generate_srs_nr(nfapi_nr_srs_pdu_t *srs_config_pdu, LOG_I(NR_PHY,"alpha_i = %f\n", alpha_i); #endif - for (int l_line = 0; l_line < N_symb_SRS; l_line++) { + for (int l_line = 0; l_line < nr_srs_info->N_symb_SRS; l_line++) { #ifdef SRS_DEBUG LOG_I(NR_PHY,":::::::: OFDM symbol %d ::::::::\n", l0+l_line); @@ -305,21 +285,21 @@ int generate_srs_nr(nfapi_nr_srs_pdu_t *srs_config_pdu, // Set group and sequence numbers (u,v) per OFDM symbol uint16_t u = 0; uint16_t v = 0; - switch(groupOrSequenceHopping) { + switch(nr_srs_info->groupOrSequenceHopping) { case neitherHopping: - u = n_ID_SRS%U_GROUP_NUMBER; + u = nr_srs_info->n_ID_SRS % U_GROUP_NUMBER; v = 0; break; case groupHopping: - u = group_number_hopping(slot_number, n_ID_SRS, l0, l_line); + u = group_number_hopping(slot_number, nr_srs_info->n_ID_SRS, l0, l_line); v = 0; break; case sequenceHopping: - u = n_ID_SRS%U_GROUP_NUMBER; - v = sequence_number_hopping(slot_number, n_ID_SRS, M_sc_b_SRS, l0, l_line); + u = nr_srs_info->n_ID_SRS % U_GROUP_NUMBER; + v = sequence_number_hopping(slot_number, nr_srs_info->n_ID_SRS, M_sc_b_SRS, l0, l_line); break; default: - LOG_E(NR_PHY, "generate_srs: unknown hopping setting %d !\n", groupOrSequenceHopping); + LOG_E(NR_PHY, "generate_srs: unknown hopping setting %d !\n", nr_srs_info->groupOrSequenceHopping); return -1; } @@ -330,16 +310,27 @@ int generate_srs_nr(nfapi_nr_srs_pdu_t *srs_config_pdu, // Compute the frequency position index n_b uint16_t sum_n_b = 0; - for (int b = 0; b <= B_SRS; b++) { - n_b[b] = compute_n_b(frame_number, slot_number, frame_parms->slots_per_frame, N_symb_SRS, B_SRS, - C_SRS, b_hop, n_RRC, R, T_offset, T_SRS, srs_config_pdu->resource_type, l_line, b); + for (int b = 0; b <= nr_srs_info->B_SRS; b++) { + n_b[b] = compute_n_b(frame_number, + slot_number, + frame_parms->slots_per_frame, + nr_srs_info->N_symb_SRS, + nr_srs_info->B_SRS, + nr_srs_info->C_SRS, + nr_srs_info->b_hop, + nr_srs_info->n_RRC, + nr_srs_info->R, + nr_srs_info->T_offset, + nr_srs_info->T_SRS, + nr_srs_info->resource_type, + l_line, + b); sum_n_b += n_b[b]; #ifdef SRS_DEBUG LOG_I(NR_PHY,"n_b[%i] = %i\n", b, n_b[b]); #endif - } #ifdef SRS_DEBUG @@ -348,14 +339,17 @@ int generate_srs_nr(nfapi_nr_srs_pdu_t *srs_config_pdu, // Compute the frequency-domain starting position uint8_t K_TC_p = 0; - if((n_SRS_cs >= n_SRS_cs_max/2)&&(n_SRS_cs < n_SRS_cs_max)&&(N_ap == 4) && ((SRS_antenna_port[p_index] == 1001) || (SRS_antenna_port[p_index] == 1003))) { - K_TC_p = (K_TC_overbar + K_TC/2)%K_TC; + if((nr_srs_info->n_SRS_cs >= n_SRS_cs_max/2) + && (nr_srs_info->n_SRS_cs < n_SRS_cs_max) + && (N_ap == 4) + && ((SRS_antenna_port[p_index] == 1001) || (SRS_antenna_port[p_index] == 1003))) { + K_TC_p = (nr_srs_info->K_TC_overbar + K_TC/2)%K_TC; } else { - K_TC_p = K_TC_overbar; + K_TC_p = nr_srs_info->K_TC_overbar; } uint8_t k_l_offset = 0; // If the SRS is configured by the IE SRS-PosResource-r16, the quantity k_l_offset is // given by TS 38.211 - Table 6.4.1.4.3-2, otherwise k_l_offset = 0. - uint8_t k_0_overbar_p = (n_shift*NR_NB_SC_PER_RB + (K_TC_p+k_l_offset))%K_TC; + uint8_t k_0_overbar_p = (nr_srs_info->n_shift * NR_NB_SC_PER_RB + (K_TC_p + k_l_offset)) % K_TC; uint8_t k_0_p = k_0_overbar_p + K_TC*M_sc_b_SRS*sum_n_b; nr_srs_info->k_0_p[p_index][l_line] = k_0_p; @@ -409,6 +403,28 @@ int generate_srs_nr(nfapi_nr_srs_pdu_t *srs_config_pdu, return 0; } +static void configure_srs_info(fapi_nr_ul_config_srs_pdu *srs_config_pdu, nr_srs_info_t *nr_srs_info) +{ + nr_srs_info->B_SRS = srs_config_pdu->bandwidth_index; + nr_srs_info->C_SRS = srs_config_pdu->config_index; + nr_srs_info->b_hop = srs_config_pdu->frequency_hopping; + nr_srs_info->comb_size = srs_config_pdu->comb_size; + nr_srs_info->K_TC_overbar = srs_config_pdu->comb_offset; + nr_srs_info->n_SRS_cs = srs_config_pdu->cyclic_shift; + nr_srs_info->n_ID_SRS = srs_config_pdu->sequence_id; + // It adjusts the SRS allocation to align with the common resource block grid in multiples of four + nr_srs_info->n_shift = srs_config_pdu->frequency_position; + nr_srs_info->n_RRC = srs_config_pdu->frequency_shift; + nr_srs_info->groupOrSequenceHopping = srs_config_pdu->group_or_sequence_hopping; + nr_srs_info->l_offset = srs_config_pdu->time_start_position; + nr_srs_info->T_SRS = srs_config_pdu->t_srs; + nr_srs_info->T_offset = srs_config_pdu->t_offset; + nr_srs_info->R = 1 << srs_config_pdu->num_repetitions; + nr_srs_info->N_symb_SRS = 1 << srs_config_pdu->num_symbols; // Number of consecutive OFDM symbols + nr_srs_info->n_srs_ports = 1 << srs_config_pdu->num_ant_ports; // Number of antenna port for transmission + nr_srs_info->resource_type = srs_config_pdu->resource_type; +} + /******************************************************************* * * NAME : ue_srs_procedures_nr @@ -433,9 +449,7 @@ int ue_srs_procedures_nr(PHY_VARS_NR_UE *ue, return -1; } - // TODO: This is wrong: casting from UE fapi to gNB NFAPI srs pdu - nfapi_nr_srs_pdu_t *srs_config_pdu = (nfapi_nr_srs_pdu_t *)&phy_data->srs_vars.srs_config_pdu; - + fapi_nr_ul_config_srs_pdu *srs_config_pdu = &phy_data->srs_vars.srs_config_pdu; int first_srs_symbol = ue->frame_parms.symbols_per_slot - 1 - srs_config_pdu->time_start_position; // Num consecutive SRS symbols according to 38.211 6.4.1.4.1 int num_srs_symbols[] = {1, 2, 4, 8, 12}; @@ -471,10 +485,11 @@ int ue_srs_procedures_nr(PHY_VARS_NR_UE *ue, LOG_I(NR_PHY,"srs_config_pdu->t_offset = %u\n", srs_config_pdu->t_offset); #endif + configure_srs_info(srs_config_pdu, ue->nr_srs_info); NR_DL_FRAME_PARMS *frame_parms = &(ue->frame_parms); uint16_t symbol_offset = (frame_parms->symbols_per_slot - 1 - srs_config_pdu->time_start_position)*frame_parms->ofdm_symbol_size; - if (generate_srs_nr(srs_config_pdu, frame_parms, txdataF, symbol_offset, ue->nr_srs_info, AMP, proc->frame_tx, proc->nr_slot_tx) + if (generate_srs_nr(frame_parms, txdataF, symbol_offset, srs_config_pdu->bwp_start, ue->nr_srs_info, AMP, proc->frame_tx, proc->nr_slot_tx) == 0) { return 0; } else { diff --git a/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.h b/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.h index 1bbe3a27ef..8735ca4527 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.h +++ b/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.h @@ -54,10 +54,10 @@ static const uint16_t srs_max_number_cs[3] = {8, 12, 6}; @param slot_number slot number @returns 0 on success -1 on error with message */ -int generate_srs_nr(nfapi_nr_srs_pdu_t *srs_config_pdu, - NR_DL_FRAME_PARMS *frame_parms, +int generate_srs_nr(NR_DL_FRAME_PARMS *frame_parms, c16_t **txdataF, uint16_t symbol_offset, + int bwp_start, nr_srs_info_t *nr_srs_info, int16_t amp, frame_t frame_number, diff --git a/openair1/PHY/defs_nr_common.h b/openair1/PHY/defs_nr_common.h index 67f7470d29..0d1cab4045 100644 --- a/openair1/PHY/defs_nr_common.h +++ b/openair1/PHY/defs_nr_common.h @@ -113,7 +113,24 @@ typedef struct { uint8_t k_0_p[MAX_NUM_NR_SRS_AP][MAX_NUM_NR_SRS_SYMBOLS]; uint8_t srs_generated_signal_bits; c16_t **srs_generated_signal; - nfapi_nr_srs_pdu_t srs_pdu; + bool is_signal_generated; + int B_SRS; + int C_SRS; + int b_hop; + int comb_size; + int K_TC_overbar; + int n_SRS_cs; + int n_ID_SRS; + int n_shift; + int n_RRC; + int groupOrSequenceHopping; + int l_offset; + int T_SRS; + int T_offset; + int R; + int N_symb_SRS; + int n_srs_ports; + int resource_type; } nr_srs_info_t; typedef struct NR_DL_FRAME_PARMS NR_DL_FRAME_PARMS; diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 1e33183567..542e3377e2 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -779,18 +779,56 @@ int fill_srs_channel_matrix(uint8_t *channel_matrix, return 0; } -int check_srs_pdu(const nfapi_nr_srs_pdu_t *srs_pdu, nfapi_nr_srs_pdu_t *saved_srs_pdu) +static void copy_srs_info(const nfapi_nr_srs_pdu_t *srs_config_pdu, nr_srs_info_t *nr_srs_info) { - if (saved_srs_pdu->bwp_start == srs_pdu->bwp_start && - saved_srs_pdu->bwp_size == srs_pdu->bwp_size && - saved_srs_pdu->num_ant_ports == srs_pdu->num_ant_ports && - saved_srs_pdu->time_start_position == srs_pdu->time_start_position && - saved_srs_pdu->num_symbols == srs_pdu->num_symbols && - saved_srs_pdu->config_index == srs_pdu->config_index) { - return 1; + nr_srs_info->B_SRS = srs_config_pdu->bandwidth_index; + nr_srs_info->C_SRS = srs_config_pdu->config_index; + nr_srs_info->b_hop = srs_config_pdu->frequency_hopping; + nr_srs_info->comb_size = srs_config_pdu->comb_size; + nr_srs_info->K_TC_overbar = srs_config_pdu->comb_offset; + nr_srs_info->n_SRS_cs = srs_config_pdu->cyclic_shift; + nr_srs_info->n_ID_SRS = srs_config_pdu->sequence_id; + // It adjusts the SRS allocation to align with the common resource block grid in multiples of four + nr_srs_info->n_shift = srs_config_pdu->frequency_position; + nr_srs_info->n_RRC = srs_config_pdu->frequency_shift; + nr_srs_info->groupOrSequenceHopping = srs_config_pdu->group_or_sequence_hopping; + nr_srs_info->l_offset = srs_config_pdu->time_start_position; + nr_srs_info->T_SRS = srs_config_pdu->t_srs; + nr_srs_info->T_offset = srs_config_pdu->t_offset; + nr_srs_info->R = 1 << srs_config_pdu->num_repetitions; + nr_srs_info->N_symb_SRS = 1 << srs_config_pdu->num_symbols; // Number of consecutive OFDM symbols + nr_srs_info->n_srs_ports = 1 << srs_config_pdu->num_ant_ports; // Number of antenna port for transmission + nr_srs_info->resource_type = srs_config_pdu->resource_type; +} + +static bool srs_has_changed(const nfapi_nr_srs_pdu_t *srs_config_pdu, nr_srs_info_t *nr_srs_info) +{ + return nr_srs_info->B_SRS != srs_config_pdu->bandwidth_index + || nr_srs_info->C_SRS != srs_config_pdu->config_index + || nr_srs_info->b_hop != srs_config_pdu->frequency_hopping + || nr_srs_info->comb_size != srs_config_pdu->comb_size + || nr_srs_info->K_TC_overbar != srs_config_pdu->comb_offset + || nr_srs_info->n_SRS_cs != srs_config_pdu->cyclic_shift + || nr_srs_info->n_ID_SRS != srs_config_pdu->sequence_id + || nr_srs_info->n_shift != srs_config_pdu->frequency_position + || nr_srs_info->n_RRC != srs_config_pdu->frequency_shift + || nr_srs_info->groupOrSequenceHopping != srs_config_pdu->group_or_sequence_hopping + || nr_srs_info->l_offset != srs_config_pdu->time_start_position + || nr_srs_info->T_SRS != srs_config_pdu->t_srs + || nr_srs_info->T_offset != srs_config_pdu->t_offset + || nr_srs_info->R != 1 << srs_config_pdu->num_repetitions + || nr_srs_info->N_symb_SRS != 1 << srs_config_pdu->num_symbols + || nr_srs_info->n_srs_ports != 1 << srs_config_pdu->num_ant_ports + || nr_srs_info->resource_type != srs_config_pdu->resource_type; +} + +static bool check_and_configure_srs_info(nfapi_nr_srs_pdu_t *srs_config_pdu, nr_srs_info_t *nr_srs_info) +{ + if (srs_has_changed(srs_config_pdu, nr_srs_info)) { + copy_srs_info(srs_config_pdu, nr_srs_info); + return true; } - *saved_srs_pdu = *srs_pdu; - return 0; + return false; } int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, NR_UL_IND_t *UL_INFO) @@ -1017,8 +1055,16 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N int8_t snr_per_rb[srs_pdu->bwp_size]; start_meas(&gNB->generate_srs_stats); - if (check_srs_pdu(srs_pdu, &gNB->nr_srs_info[i]->srs_pdu) == 0) { - generate_srs_nr(srs_pdu, frame_parms, gNB->nr_srs_info[i]->srs_generated_signal, 0, gNB->nr_srs_info[i], AMP, frame_rx, slot_rx); + + if (check_and_configure_srs_info(srs_pdu, gNB->nr_srs_info[i])) { + generate_srs_nr(frame_parms, + gNB->nr_srs_info[i]->srs_generated_signal, + 0, + srs_pdu->bwp_start, + gNB->nr_srs_info[i], + AMP, + frame_rx, + slot_rx); } stop_meas(&gNB->generate_srs_stats); c16_t **rxdataF = gNB->common_vars.rxdataF[srs->beam_nb]; From 607d8a0bc220dc6a88876f14a7381088e71d62c8 Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 11 Sep 2025 14:28:21 +0200 Subject: [PATCH 745/964] simplify compute_n_b and compute_F_b functions by using common structure --- .../PHY/NR_UE_TRANSPORT/srs_modulation_nr.c | 108 ++++++------------ 1 file changed, 38 insertions(+), 70 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.c b/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.c index 4d1d36a8a6..954ea09b14 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.c @@ -85,80 +85,62 @@ uint16_t sequence_number_hopping(int slot_number, return v; } -uint16_t compute_F_b(frame_t frame_number, - slot_t slot_number, - uint16_t slots_per_frame, - uint8_t N_symb_SRS, - uint8_t B_SRS, - uint8_t C_SRS, - uint8_t b_hop, - uint8_t R, - uint16_t T_offset, - uint16_t T_SRS, - resourceType_t resource_type, - uint8_t l_line, - uint8_t b) { - +static int compute_F_b(frame_t frame_number, + slot_t slot_number, + int slots_per_frame, + nr_srs_info_t *nr_srs_info, + uint8_t l_line, + uint8_t b) +{ // Compute the number of SRS transmissions uint16_t n_SRS = 0; - if (resource_type == aperiodic) { - n_SRS = l_line / R; + if (nr_srs_info->resource_type == aperiodic) { + n_SRS = l_line / nr_srs_info->R; } else { - n_SRS = ((slots_per_frame*frame_number + slot_number - T_offset)/T_SRS)*(N_symb_SRS/R)+(l_line / R); + int t = (slots_per_frame * frame_number + slot_number - nr_srs_info->T_offset) / nr_srs_info->T_SRS; + n_SRS = t * (nr_srs_info->N_symb_SRS / nr_srs_info->R) + (l_line / nr_srs_info->R); } uint16_t product_N_b = 1; - for (unsigned int b_prime = b_hop; b_prime < B_SRS; b_prime++) { - if (b_prime != b_hop) { - product_N_b *= get_N_b_srs(C_SRS, b_prime); + for (unsigned int b_prime = nr_srs_info->b_hop; b_prime < nr_srs_info->B_SRS; b_prime++) { + if (b_prime != nr_srs_info->b_hop) { + product_N_b *= get_N_b_srs(nr_srs_info->C_SRS, b_prime); } } - uint16_t F_b = 0; - uint8_t N_b = get_N_b_srs(C_SRS, b); + int F_b = 0; + uint8_t N_b = get_N_b_srs(nr_srs_info->C_SRS, b); if (N_b & 1) { // Nb odd - F_b = (N_b/2)*(n_SRS/product_N_b); + F_b = (N_b / 2) * (n_SRS / product_N_b); } else { // Nb even uint16_t product_N_b_B_SRS = product_N_b; - product_N_b_B_SRS *= get_N_b_srs(C_SRS, B_SRS); /* product for b_hop to b */ - F_b = (N_b/2)*((n_SRS%product_N_b_B_SRS)/product_N_b) + ((n_SRS%product_N_b_B_SRS)/2*product_N_b); + product_N_b_B_SRS *= get_N_b_srs(nr_srs_info->C_SRS, nr_srs_info->B_SRS); /* product for b_hop to b */ + F_b = (N_b / 2) * ((n_SRS % product_N_b_B_SRS) / product_N_b) + ((n_SRS % product_N_b_B_SRS) / 2 * product_N_b); } - return F_b; } -uint16_t compute_n_b(frame_t frame_number, - slot_t slot_number, - uint16_t slots_per_frame, - uint8_t N_symb_SRS, - uint8_t B_SRS, - uint8_t C_SRS, - uint8_t b_hop, - uint8_t n_RRC, - uint8_t R, - uint16_t T_offset, - uint16_t T_SRS, - resourceType_t resource_type, - uint8_t l_line, - uint8_t b) { - - uint8_t N_b = get_N_b_srs(C_SRS, b); - uint16_t m_SRS_b = get_m_srs(C_SRS, B_SRS); - - uint16_t n_b = 0; - if (b_hop >= B_SRS) { - n_b = (4 * n_RRC/m_SRS_b)%N_b; +static int compute_n_b(frame_t frame_number, + slot_t slot_number, + uint16_t slots_per_frame, + nr_srs_info_t *nr_srs_info, + uint8_t l_line, + uint8_t b, + int m_SRS_b) +{ + uint8_t N_b = get_N_b_srs(nr_srs_info->C_SRS, b); + int n_b = 0; + if (nr_srs_info->b_hop >= nr_srs_info->B_SRS) { + n_b = (4 * nr_srs_info->n_RRC / m_SRS_b) % N_b; } else { - if (b <= b_hop) { - n_b = (4 * n_RRC/m_SRS_b)%N_b; + if (b <= nr_srs_info->b_hop) { + n_b = (4 * nr_srs_info->n_RRC / m_SRS_b) % N_b; } else { // Compute the hopping offset Fb - uint16_t F_b = compute_F_b(frame_number, slot_number, slots_per_frame, N_symb_SRS, B_SRS, C_SRS, b_hop, R, - T_offset, T_SRS, resource_type, l_line, b); - n_b = (F_b + (4 * n_RRC/m_SRS_b))%N_b; + int F_b = compute_F_b(frame_number, slot_number, slots_per_frame, nr_srs_info, l_line, b); + n_b = (F_b + (4 * nr_srs_info->n_RRC / m_SRS_b)) % N_b; } } - return n_b; } @@ -191,7 +173,7 @@ int generate_srs_nr(NR_DL_FRAME_PARMS *frame_parms, int N_ap = nr_srs_info->n_srs_ports > frame_parms->nb_antennas_tx ? frame_parms->nb_antennas_tx : nr_srs_info->n_srs_ports; uint8_t l0 = frame_parms->symbols_per_slot - 1 - nr_srs_info->l_offset; // Starting symbol position in the time domain uint8_t n_SRS_cs_max = srs_max_number_cs[nr_srs_info->comb_size]; - uint16_t m_SRS_b = get_m_srs(nr_srs_info->C_SRS, nr_srs_info->B_SRS); // Number of resource blocks + int m_SRS_b = get_m_srs(nr_srs_info->C_SRS, nr_srs_info->B_SRS); // Number of resource blocks uint16_t M_sc_b_SRS = m_SRS_b * NR_NB_SC_PER_RB/K_TC; // Length of the SRS sequence #ifdef SRS_DEBUG @@ -253,7 +235,7 @@ int generate_srs_nr(NR_DL_FRAME_PARMS *frame_parms, } uint64_t subcarrier_offset = frame_parms->first_carrier_offset + bwp_start * NR_NB_SC_PER_RB; double sqrt_N_ap = sqrt(N_ap); - uint16_t n_b[nr_srs_info->B_SRS + 1]; + int n_b[nr_srs_info->B_SRS + 1]; // Find index of table which is for this SRS length uint16_t M_sc_b_SRS_index = 0; @@ -311,21 +293,7 @@ int generate_srs_nr(NR_DL_FRAME_PARMS *frame_parms, // Compute the frequency position index n_b uint16_t sum_n_b = 0; for (int b = 0; b <= nr_srs_info->B_SRS; b++) { - n_b[b] = compute_n_b(frame_number, - slot_number, - frame_parms->slots_per_frame, - nr_srs_info->N_symb_SRS, - nr_srs_info->B_SRS, - nr_srs_info->C_SRS, - nr_srs_info->b_hop, - nr_srs_info->n_RRC, - nr_srs_info->R, - nr_srs_info->T_offset, - nr_srs_info->T_SRS, - nr_srs_info->resource_type, - l_line, - b); - + n_b[b] = compute_n_b(frame_number, slot_number, frame_parms->slots_per_frame, nr_srs_info, l_line, b, m_SRS_b); sum_n_b += n_b[b]; #ifdef SRS_DEBUG From 740e9c5c9cbf4d485697cb296fdef3e8abd08475 Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 11 Sep 2025 14:54:42 +0200 Subject: [PATCH 746/964] move common SRS functions to common folder --- CMakeLists.txt | 1 + openair1/PHY/NR_REFSIG/ss_pbch_nr.h | 1 - .../PHY/NR_UE_TRANSPORT/srs_modulation_nr.c | 356 +----------------- .../PHY/NR_UE_TRANSPORT/srs_modulation_nr.h | 35 -- .../PHY/nr_phy_common/inc/nr_phy_common.h | 8 + .../PHY/nr_phy_common/src/nr_phy_common_srs.c | 344 +++++++++++++++++ openair1/SCHED_NR/phy_procedures_nr_gNB.c | 1 - 7 files changed, 362 insertions(+), 384 deletions(-) create mode 100644 openair1/PHY/nr_phy_common/src/nr_phy_common_srs.c diff --git a/CMakeLists.txt b/CMakeLists.txt index fa2d497589..83fb33b1d2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -941,6 +941,7 @@ set(PHY_SRC_UE ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_tbs_tools.c ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_prach_common.c ${OPENAIR1_DIR}/PHY/nr_phy_common/src/nr_phy_common_csirs.c + ${OPENAIR1_DIR}/PHY/nr_phy_common/src/nr_phy_common_srs.c ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_scrambling.c ${OPENAIR1_DIR}/PHY/NR_REFSIG/refsig.c ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/srs_modulation_nr.c diff --git a/openair1/PHY/NR_REFSIG/ss_pbch_nr.h b/openair1/PHY/NR_REFSIG/ss_pbch_nr.h index 0929d483cd..e3b9b0e8ed 100644 --- a/openair1/PHY/NR_REFSIG/ss_pbch_nr.h +++ b/openair1/PHY/NR_REFSIG/ss_pbch_nr.h @@ -78,7 +78,6 @@ #define NR_N_SYMBOLS_SSB (4) #define IQ_SIZE sizeof(c16_t) /* I and Q are alternatively stored into buffers */ -#define N_SYMB_SLOT (14) /* SS/PBCH parameters : see from TS 38.211 table 7.4.3.1-1: Resources within an SS/PBCH block for PSS... */ #define DMRS_PBCH_PER_RB (N_SC_RB >> 4) /* at 0+v, 4+v, 8+v for a resource block with v = NcellID modulo 4 */ diff --git a/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.c b/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.c index 954ea09b14..e97f887673 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.c @@ -38,338 +38,8 @@ #include "PHY/NR_REFSIG/ss_pbch_nr.h" #include "PHY/NR_REFSIG/dmrs_nr.h" #include "PHY/NR_REFSIG/ul_ref_seq_nr.h" - +#include "PHY/nr_phy_common/inc/nr_phy_common.h" #include "PHY/NR_UE_TRANSPORT/srs_modulation_nr.h" -//#define SRS_DEBUG - - -uint16_t group_number_hopping(int slot_number, - uint8_t n_ID_SRS, - uint8_t l0, - uint8_t l_line) { - - // Pseudo-random sequence c(i) defined by TS 38.211 - Section 5.2.1 - uint32_t cinit = n_ID_SRS; - uint8_t c_last_index = 8 * (slot_number * N_SYMB_SLOT + l0 + l_line) + 7; - uint32_t *c_sequence = calloc(c_last_index+1, sizeof(uint32_t)); - pseudo_random_sequence(c_last_index+1, c_sequence, cinit); - - // TS 38.211 - 6.4.1.4.2 Sequence generation - uint32_t f_gh = 0; - for (int m = 0; m <= 7; m++) { - f_gh += c_sequence[8 * (slot_number * N_SYMB_SLOT + l0 + l_line) + m] << m; - } - f_gh = f_gh%30; - uint8_t u = (f_gh + n_ID_SRS)%U_GROUP_NUMBER; - - free(c_sequence); - return u; -} - -uint16_t sequence_number_hopping(int slot_number, - uint8_t n_ID_SRS, - uint16_t M_sc_b_SRS, - uint8_t l0, - uint8_t l_line) { - uint16_t v = 0; - if (M_sc_b_SRS > 6 * NR_NB_SC_PER_RB) { - // Pseudo-random sequence c(i) defined by TS 38.211 - Section 5.2.1 - uint32_t cinit = n_ID_SRS; - uint8_t c_last_index = (slot_number * N_SYMB_SLOT + l0 + l_line); - uint32_t *c_sequence = calloc(c_last_index+1, sizeof(uint32_t)); - pseudo_random_sequence(c_last_index+1, c_sequence, cinit); - // TS 38.211 - 6.4.1.4.2 Sequence generation - v = c_sequence[c_last_index]; - free(c_sequence); - } - return v; -} - -static int compute_F_b(frame_t frame_number, - slot_t slot_number, - int slots_per_frame, - nr_srs_info_t *nr_srs_info, - uint8_t l_line, - uint8_t b) -{ - // Compute the number of SRS transmissions - uint16_t n_SRS = 0; - if (nr_srs_info->resource_type == aperiodic) { - n_SRS = l_line / nr_srs_info->R; - } else { - int t = (slots_per_frame * frame_number + slot_number - nr_srs_info->T_offset) / nr_srs_info->T_SRS; - n_SRS = t * (nr_srs_info->N_symb_SRS / nr_srs_info->R) + (l_line / nr_srs_info->R); - } - - uint16_t product_N_b = 1; - for (unsigned int b_prime = nr_srs_info->b_hop; b_prime < nr_srs_info->B_SRS; b_prime++) { - if (b_prime != nr_srs_info->b_hop) { - product_N_b *= get_N_b_srs(nr_srs_info->C_SRS, b_prime); - } - } - - int F_b = 0; - uint8_t N_b = get_N_b_srs(nr_srs_info->C_SRS, b); - if (N_b & 1) { // Nb odd - F_b = (N_b / 2) * (n_SRS / product_N_b); - } else { // Nb even - uint16_t product_N_b_B_SRS = product_N_b; - product_N_b_B_SRS *= get_N_b_srs(nr_srs_info->C_SRS, nr_srs_info->B_SRS); /* product for b_hop to b */ - F_b = (N_b / 2) * ((n_SRS % product_N_b_B_SRS) / product_N_b) + ((n_SRS % product_N_b_B_SRS) / 2 * product_N_b); - } - return F_b; -} - -static int compute_n_b(frame_t frame_number, - slot_t slot_number, - uint16_t slots_per_frame, - nr_srs_info_t *nr_srs_info, - uint8_t l_line, - uint8_t b, - int m_SRS_b) -{ - uint8_t N_b = get_N_b_srs(nr_srs_info->C_SRS, b); - int n_b = 0; - if (nr_srs_info->b_hop >= nr_srs_info->B_SRS) { - n_b = (4 * nr_srs_info->n_RRC / m_SRS_b) % N_b; - } else { - if (b <= nr_srs_info->b_hop) { - n_b = (4 * nr_srs_info->n_RRC / m_SRS_b) % N_b; - } else { - // Compute the hopping offset Fb - int F_b = compute_F_b(frame_number, slot_number, slots_per_frame, nr_srs_info, l_line, b); - n_b = (F_b + (4 * nr_srs_info->n_RRC / m_SRS_b)) % N_b; - } - } - return n_b; -} - -/************************************************************************* -* -* NAME : generate_srs_nr -* -* PARAMETERS : pointer to srs config pdu -* pointer to transmit buffer -* amplitude scaling for this physical signal -* slot number of transmission -* RETURN : 0 if srs sequence has been successfully generated -* -1 if sequence can not be properly generated -* -* DESCRIPTION : generate/map srs symbol into transmit buffer -* See TS 38.211 - Section 6.4.1.4 Sounding reference signal -* -***************************************************************************/ -int generate_srs_nr(NR_DL_FRAME_PARMS *frame_parms, - c16_t **txdataF, - uint16_t symbol_offset, - int bwp_start, - nr_srs_info_t *nr_srs_info, - int16_t amp, - frame_t frame_number, - slot_t slot_number) -{ - uint8_t K_TC = 2 << nr_srs_info->comb_size; - /* Number of antenna ports (M) can't be higher than number of physical antennas (N): M <= N */ - int N_ap = nr_srs_info->n_srs_ports > frame_parms->nb_antennas_tx ? frame_parms->nb_antennas_tx : nr_srs_info->n_srs_ports; - uint8_t l0 = frame_parms->symbols_per_slot - 1 - nr_srs_info->l_offset; // Starting symbol position in the time domain - uint8_t n_SRS_cs_max = srs_max_number_cs[nr_srs_info->comb_size]; - int m_SRS_b = get_m_srs(nr_srs_info->C_SRS, nr_srs_info->B_SRS); // Number of resource blocks - uint16_t M_sc_b_SRS = m_SRS_b * NR_NB_SC_PER_RB/K_TC; // Length of the SRS sequence - -#ifdef SRS_DEBUG - LOG_I(NR_PHY,"Frame = %i, slot = %i\n", frame_number, slot_number); - LOG_I(NR_PHY,"B_SRS = %i\n", nr_srs_info->B_SRS); - LOG_I(NR_PHY,"C_SRS = %i\n", nr_srs_info->C_SRS); - LOG_I(NR_PHY,"b_hop = %i\n", nr_srs_info->b_hop); - LOG_I(NR_PHY,"K_TC = %i\n", K_TC); - LOG_I(NR_PHY,"K_TC_overbar = %i\n", nr_srs_info->K_TC_overbar); - LOG_I(NR_PHY,"n_SRS_cs = %i\n", nr_srs_info->n_SRS_cs); - LOG_I(NR_PHY,"n_ID_SRS = %i\n", nr_srs_info->n_ID_SRS); - LOG_I(NR_PHY,"n_shift = %i\n", nr_srs_info->n_shift); - LOG_I(NR_PHY,"n_RRC = %i\n", nr_srs_info->n_RRC); - LOG_I(NR_PHY,"groupOrSequenceHopping = %i\n", nr_srs_info->groupOrSequenceHopping); - LOG_I(NR_PHY,"l_offset = %i\n", nr_srs_info->l_offset); - LOG_I(NR_PHY,"T_SRS = %i\n", nr_srs_info->T_SRS); - LOG_I(NR_PHY,"T_offset = %i\n", nr_srs_info->T_offset); - LOG_I(NR_PHY,"R = %i\n", nr_srs_info->R); - LOG_I(NR_PHY,"N_ap = %i\n", N_ap); - LOG_I(NR_PHY,"N_symb_SRS = %i\n", nr_srs_info->N_symb_SRS); - LOG_I(NR_PHY,"l0 = %i\n", l0); - LOG_I(NR_PHY,"n_SRS_cs_max = %i\n", n_SRS_cs_max); - LOG_I(NR_PHY,"m_SRS_b = %i\n", m_SRS_b); - LOG_I(NR_PHY,"M_sc_b_SRS = %i\n", M_sc_b_SRS); -#endif - - // Validation of SRS config parameters - - if (nr_srs_info->R == 0) { - LOG_E(NR_PHY, "generate_srs: this parameter repetition factor %d is not consistent !\n", nr_srs_info->R); - return -1; - } else if (nr_srs_info->R > nr_srs_info->N_symb_SRS) { - LOG_E(NR_PHY, "generate_srs: R %d can not be greater than N_symb_SRS %d !\n", nr_srs_info->R, nr_srs_info->N_symb_SRS); - return -1; - } - - if (nr_srs_info->n_SRS_cs >= n_SRS_cs_max) { - LOG_E(NR_PHY, "generate_srs: inconsistent parameter n_SRS_cs %d >= n_SRS_cs_max %d !\n", nr_srs_info->n_SRS_cs, n_SRS_cs_max); - return -1; - } - - if (nr_srs_info->T_SRS == 0) { - LOG_E(NR_PHY, "generate_srs: inconsistent parameter T_SRS %d can not be equal to zero !\n", nr_srs_info->T_SRS); - return -1; - } else { - int index = 0; - while (srs_periodicity[index] != nr_srs_info->T_SRS) { - index++; - if (index == SRS_PERIODICITY) { - LOG_E(NR_PHY, "generate_srs: inconsistent parameter T_SRS %d not specified !\n", nr_srs_info->T_SRS); - return -1; - } - } - } - - // Variable initialization - if(nr_srs_info) { - nr_srs_info->srs_generated_signal_bits = log2_approx(amp); - } - uint64_t subcarrier_offset = frame_parms->first_carrier_offset + bwp_start * NR_NB_SC_PER_RB; - double sqrt_N_ap = sqrt(N_ap); - int n_b[nr_srs_info->B_SRS + 1]; - - // Find index of table which is for this SRS length - uint16_t M_sc_b_SRS_index = 0; - while((ul_allocated_re[M_sc_b_SRS_index] != M_sc_b_SRS) && (M_sc_b_SRS_index < SRS_SB_CONF)){ - M_sc_b_SRS_index++; - } - - // SRS sequence generation and mapping, TS 38.211 - Section 6.4.1.4 - for (int p_index = 0; p_index < N_ap; p_index++) { - -#ifdef SRS_DEBUG - LOG_I(NR_PHY,"============ port %d ============\n", p_index); -#endif - - uint16_t n_SRS_cs_i = (nr_srs_info->n_SRS_cs + (n_SRS_cs_max * (SRS_antenna_port[p_index] - 1000)/N_ap))%n_SRS_cs_max; - double alpha_i = 2 * M_PI * ((double)n_SRS_cs_i / (double)n_SRS_cs_max); - -#ifdef SRS_DEBUG - LOG_I(NR_PHY,"n_SRS_cs_i = %i\n", n_SRS_cs_i); - LOG_I(NR_PHY,"alpha_i = %f\n", alpha_i); -#endif - - for (int l_line = 0; l_line < nr_srs_info->N_symb_SRS; l_line++) { - -#ifdef SRS_DEBUG - LOG_I(NR_PHY,":::::::: OFDM symbol %d ::::::::\n", l0+l_line); -#endif - - // Set group and sequence numbers (u,v) per OFDM symbol - uint16_t u = 0; - uint16_t v = 0; - switch(nr_srs_info->groupOrSequenceHopping) { - case neitherHopping: - u = nr_srs_info->n_ID_SRS % U_GROUP_NUMBER; - v = 0; - break; - case groupHopping: - u = group_number_hopping(slot_number, nr_srs_info->n_ID_SRS, l0, l_line); - v = 0; - break; - case sequenceHopping: - u = nr_srs_info->n_ID_SRS % U_GROUP_NUMBER; - v = sequence_number_hopping(slot_number, nr_srs_info->n_ID_SRS, M_sc_b_SRS, l0, l_line); - break; - default: - LOG_E(NR_PHY, "generate_srs: unknown hopping setting %d !\n", nr_srs_info->groupOrSequenceHopping); - return -1; - } - -#ifdef SRS_DEBUG - LOG_I(NR_PHY,"u = %i\n", u); - LOG_I(NR_PHY,"v = %i\n", v); -#endif - - // Compute the frequency position index n_b - uint16_t sum_n_b = 0; - for (int b = 0; b <= nr_srs_info->B_SRS; b++) { - n_b[b] = compute_n_b(frame_number, slot_number, frame_parms->slots_per_frame, nr_srs_info, l_line, b, m_SRS_b); - sum_n_b += n_b[b]; - -#ifdef SRS_DEBUG - LOG_I(NR_PHY,"n_b[%i] = %i\n", b, n_b[b]); -#endif - } - -#ifdef SRS_DEBUG - LOG_I(NR_PHY,"sum_n_b = %i\n", sum_n_b); -#endif - - // Compute the frequency-domain starting position - uint8_t K_TC_p = 0; - if((nr_srs_info->n_SRS_cs >= n_SRS_cs_max/2) - && (nr_srs_info->n_SRS_cs < n_SRS_cs_max) - && (N_ap == 4) - && ((SRS_antenna_port[p_index] == 1001) || (SRS_antenna_port[p_index] == 1003))) { - K_TC_p = (nr_srs_info->K_TC_overbar + K_TC/2)%K_TC; - } else { - K_TC_p = nr_srs_info->K_TC_overbar; - } - uint8_t k_l_offset = 0; // If the SRS is configured by the IE SRS-PosResource-r16, the quantity k_l_offset is - // given by TS 38.211 - Table 6.4.1.4.3-2, otherwise k_l_offset = 0. - uint8_t k_0_overbar_p = (nr_srs_info->n_shift * NR_NB_SC_PER_RB + (K_TC_p + k_l_offset)) % K_TC; - uint8_t k_0_p = k_0_overbar_p + K_TC*M_sc_b_SRS*sum_n_b; - nr_srs_info->k_0_p[p_index][l_line] = k_0_p; - -#ifdef SRS_DEBUG - LOG_I(NR_PHY,"K_TC_p = %i\n", K_TC_p); - LOG_I(NR_PHY,"k_0_overbar_p = %i\n", k_0_overbar_p); - LOG_I(NR_PHY,"k_0_p = %i\n", k_0_p); -#endif - - uint16_t subcarrier = subcarrier_offset + k_0_p; - if (subcarrier>frame_parms->ofdm_symbol_size) { - subcarrier -= frame_parms->ofdm_symbol_size; - } - uint16_t l_line_offset = l_line*frame_parms->ofdm_symbol_size; - - // For each port, and for each OFDM symbol, here it is computed and mapped an SRS sequence with M_sc_b_SRS symbols - for (int k = 0; k < M_sc_b_SRS; k++) { - cd_t shift = {cos(alpha_i * k), sin(alpha_i * k)}; - const c16_t tmp = rv_ul_ref_sig[u][v][M_sc_b_SRS_index][k]; - cd_t r_overbar = {tmp.r, tmp.i}; - - // cos(x+y) = cos(x)cos(y) - sin(x)sin(y) - cd_t r = cdMul(shift, r_overbar); - - c16_t r_amp = {(((int32_t)round((double)amp * r.r / sqrt_N_ap)) >> 15), - (((int32_t)round((double)amp * r.i / sqrt_N_ap)) >> 15)}; - -#ifdef SRS_DEBUG - int subcarrier_log = subcarrier-subcarrier_offset; - if(subcarrier_log < 0) { - subcarrier_log = subcarrier_log + frame_parms->ofdm_symbol_size; - } - if(subcarrier_log%12 == 0) { - LOG_I(NR_PHY,"------------ %d ------------\n", subcarrier_log/12); - } - LOG_I(NR_PHY, "(%d) \t%i\t%i\n", subcarrier_log, r_amp.r, r_amp.i); -#endif - - txdataF[p_index][symbol_offset + l_line_offset + subcarrier] = r_amp; - - // Subcarrier increment - subcarrier += K_TC; - if (subcarrier >= frame_parms->ofdm_symbol_size) { - subcarrier=subcarrier-frame_parms->ofdm_symbol_size; - } - - } // for (int k = 0; k < M_sc_b_SRS; k++) - } // for (int l_line = 0; l_line < N_symb_SRS; l_line++) - } // for (int p_index = 0; p_index < N_ap; p_index++) - - return 0; -} static void configure_srs_info(fapi_nr_ul_config_srs_pdu *srs_config_pdu, nr_srs_info_t *nr_srs_info) { @@ -457,24 +127,16 @@ int ue_srs_procedures_nr(PHY_VARS_NR_UE *ue, NR_DL_FRAME_PARMS *frame_parms = &(ue->frame_parms); uint16_t symbol_offset = (frame_parms->symbols_per_slot - 1 - srs_config_pdu->time_start_position)*frame_parms->ofdm_symbol_size; - if (generate_srs_nr(frame_parms, txdataF, symbol_offset, srs_config_pdu->bwp_start, ue->nr_srs_info, AMP, proc->frame_tx, proc->nr_slot_tx) - == 0) { + if (generate_srs_nr(frame_parms, + txdataF, + symbol_offset, + srs_config_pdu->bwp_start, + ue->nr_srs_info, + AMP, + proc->frame_tx, + proc->nr_slot_tx)) { return 0; } else { return -1; } } - - - - - - - - - - - - - - diff --git a/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.h b/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.h index 8735ca4527..8a413f1611 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.h +++ b/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.h @@ -35,43 +35,8 @@ #include "PHY/defs_nr_UE.h" -#define SRS_PERIODICITY (17) - -static const uint16_t srs_periodicity[SRS_PERIODICITY] = {1, 2, 4, 5, 8, 10, 16, 20, 32, 40, 64, 80, 160, 320, 640, 1280, 2560}; - -// TS 38.211 - Table 6.4.1.4.2-1 -static const uint16_t srs_max_number_cs[3] = {8, 12, 6}; - /*************** FUNCTIONS *****************************************/ -/** \brief This function generates the sounding reference symbol (SRS) for the uplink according to 38.211 6.4.1.4 Sounding reference signal - @param frame_parms NR DL Frame parameters - @param txdataF pointer to the frequency domain TX signal - @param symbol_offset symbol offset added in txdataF - @param nr_srs_info pointer to the srs info structure - @param amp amplitude of generated signal - @param frame_number frame number - @param slot_number slot number - @returns 0 on success -1 on error with message */ - -int generate_srs_nr(NR_DL_FRAME_PARMS *frame_parms, - c16_t **txdataF, - uint16_t symbol_offset, - int bwp_start, - nr_srs_info_t *nr_srs_info, - int16_t amp, - frame_t frame_number, - slot_t slot_number); - -/** \brief This function checks for periodic srs if srs should be transmitted in this slot - * @param p_SRS_Resource pointer to active resource - @param frame_parms NR DL Frame parameters - @param txdataF pointer to the frequency domain TX signal - @returns 0 if srs should be transmitted -1 on error with message */ - -int is_srs_period_nr(SRS_Resource_t *p_SRS_Resource, - NR_DL_FRAME_PARMS *frame_parms, - int frame_tx, int slot_tx); /** \brief This function processes srs configuration * @param ue context diff --git a/openair1/PHY/nr_phy_common/inc/nr_phy_common.h b/openair1/PHY/nr_phy_common/inc/nr_phy_common.h index 752353ad02..95383c40b3 100644 --- a/openair1/PHY/nr_phy_common/inc/nr_phy_common.h +++ b/openair1/PHY/nr_phy_common/inc/nr_phy_common.h @@ -364,6 +364,14 @@ void nr_channel_level(const int symbol, const int Nl, int32_t avg[nb_rx * Nl], const uint32_t len); +bool generate_srs_nr(NR_DL_FRAME_PARMS *frame_parms, + c16_t **txdataF, + uint16_t symbol_offset, + int bwp_start, + nr_srs_info_t *nr_srs_info, + int16_t amp, + frame_t frame_number, + slot_t slot_number); void nr_generate_csi_rs(const NR_DL_FRAME_PARMS *frame_parms, const csi_mapping_parms_t *phy_csi_parms, const int16_t amp, diff --git a/openair1/PHY/nr_phy_common/src/nr_phy_common_srs.c b/openair1/PHY/nr_phy_common/src/nr_phy_common_srs.c new file mode 100644 index 0000000000..dce62add0b --- /dev/null +++ b/openair1/PHY/nr_phy_common/src/nr_phy_common_srs.c @@ -0,0 +1,344 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include "PHY/nr_phy_common/inc/nr_phy_common.h" +#include "PHY/NR_REFSIG/dmrs_nr.h" +#include "PHY/NR_REFSIG/ul_ref_seq_nr.h" + +#define SRS_PERIODICITY (17) +static const uint16_t srs_periodicity[SRS_PERIODICITY] = {1, 2, 4, 5, 8, 10, 16, 20, 32, 40, 64, 80, 160, 320, 640, 1280, 2560}; +// TS 38.211 - Table 6.4.1.4.2-1 +static const uint16_t srs_max_number_cs[3] = {8, 12, 6}; + +//#define SRS_DEBUG + +static int group_number_hopping(int slot_number, uint8_t n_ID_SRS, uint8_t l0, uint8_t l_line) +{ + // Pseudo-random sequence c(i) defined by TS 38.211 - Section 5.2.1 + uint32_t cinit = n_ID_SRS; + uint8_t c_last_index = 8 * (slot_number * NR_SYMBOLS_PER_SLOT + l0 + l_line) + 7; + uint32_t *c_sequence = calloc(c_last_index + 1, sizeof(uint32_t)); + pseudo_random_sequence(c_last_index + 1, c_sequence, cinit); + + // TS 38.211 - 6.4.1.4.2 Sequence generation + uint32_t f_gh = 0; + for (int m = 0; m <= 7; m++) { + f_gh += c_sequence[8 * (slot_number * NR_SYMBOLS_PER_SLOT + l0 + l_line) + m] << m; + } + f_gh = f_gh % 30; + int u = (f_gh + n_ID_SRS) % U_GROUP_NUMBER; + free(c_sequence); + return u; +} + +static int sequence_number_hopping(int slot_number, uint8_t n_ID_SRS, uint16_t M_sc_b_SRS, uint8_t l0, uint8_t l_line) +{ + int v = 0; + if (M_sc_b_SRS > 6 * NR_NB_SC_PER_RB) { + // Pseudo-random sequence c(i) defined by TS 38.211 - Section 5.2.1 + uint32_t cinit = n_ID_SRS; + uint8_t c_last_index = (slot_number * NR_SYMBOLS_PER_SLOT + l0 + l_line); + uint32_t *c_sequence = calloc(c_last_index + 1, sizeof(uint32_t)); + pseudo_random_sequence(c_last_index + 1, c_sequence, cinit); + // TS 38.211 - 6.4.1.4.2 Sequence generation + v = c_sequence[c_last_index]; + free(c_sequence); + } + return v; +} + +static int compute_F_b(frame_t frame_number, + slot_t slot_number, + int slots_per_frame, + nr_srs_info_t *nr_srs_info, + uint8_t l_line, + uint8_t b) +{ + // Compute the number of SRS transmissions + uint16_t n_SRS = 0; + if (nr_srs_info->resource_type == aperiodic) { + n_SRS = l_line / nr_srs_info->R; + } else { + int t = (slots_per_frame * frame_number + slot_number - nr_srs_info->T_offset) / nr_srs_info->T_SRS; + n_SRS = t * (nr_srs_info->N_symb_SRS / nr_srs_info->R) + (l_line / nr_srs_info->R); + } + + uint16_t product_N_b = 1; + for (unsigned int b_prime = nr_srs_info->b_hop; b_prime < nr_srs_info->B_SRS; b_prime++) { + if (b_prime != nr_srs_info->b_hop) { + product_N_b *= get_N_b_srs(nr_srs_info->C_SRS, b_prime); + } + } + + int F_b = 0; + uint8_t N_b = get_N_b_srs(nr_srs_info->C_SRS, b); + if (N_b & 1) { // Nb odd + F_b = (N_b / 2) * (n_SRS / product_N_b); + } else { // Nb even + uint16_t product_N_b_B_SRS = product_N_b; + product_N_b_B_SRS *= get_N_b_srs(nr_srs_info->C_SRS, nr_srs_info->B_SRS); /* product for b_hop to b */ + F_b = (N_b / 2) * ((n_SRS % product_N_b_B_SRS) / product_N_b) + ((n_SRS % product_N_b_B_SRS) / 2 * product_N_b); + } + return F_b; +} + +static int compute_n_b(frame_t frame_number, + slot_t slot_number, + uint16_t slots_per_frame, + nr_srs_info_t *nr_srs_info, + uint8_t l_line, + uint8_t b, + int m_SRS_b) +{ + uint8_t N_b = get_N_b_srs(nr_srs_info->C_SRS, b); + int n_b = 0; + if (nr_srs_info->b_hop >= nr_srs_info->B_SRS) { + n_b = (4 * nr_srs_info->n_RRC / m_SRS_b) % N_b; + } else { + if (b <= nr_srs_info->b_hop) { + n_b = (4 * nr_srs_info->n_RRC / m_SRS_b) % N_b; + } else { + // Compute the hopping offset Fb + int F_b = compute_F_b(frame_number, slot_number, slots_per_frame, nr_srs_info, l_line, b); + n_b = (F_b + (4 * nr_srs_info->n_RRC / m_SRS_b)) % N_b; + } + } + return n_b; +} + +/************************************************************************* +* +* NAME : generate_srs_nr +* +* PARAMETERS : pointer to srs config pdu +* pointer to transmit buffer +* amplitude scaling for this physical signal +* slot number of transmission +* RETURN : 0 if srs sequence has been successfully generated +* -1 if sequence can not be properly generated +* +* DESCRIPTION : generate/map srs symbol into transmit buffer +* See TS 38.211 - Section 6.4.1.4 Sounding reference signal +* +***************************************************************************/ +bool generate_srs_nr(NR_DL_FRAME_PARMS *frame_parms, + c16_t **txdataF, + uint16_t symbol_offset, + int bwp_start, + nr_srs_info_t *nr_srs_info, + int16_t amp, + frame_t frame_number, + slot_t slot_number) +{ + uint8_t K_TC = 2 << nr_srs_info->comb_size; + /* Number of antenna ports (M) can't be higher than number of physical antennas (N): M <= N */ + int N_ap = nr_srs_info->n_srs_ports > frame_parms->nb_antennas_tx ? frame_parms->nb_antennas_tx : nr_srs_info->n_srs_ports; + uint8_t l0 = frame_parms->symbols_per_slot - 1 - nr_srs_info->l_offset; // Starting symbol position in the time domain + uint8_t n_SRS_cs_max = srs_max_number_cs[nr_srs_info->comb_size]; + int m_SRS_b = get_m_srs(nr_srs_info->C_SRS, nr_srs_info->B_SRS); // Number of resource blocks + uint16_t M_sc_b_SRS = m_SRS_b * NR_NB_SC_PER_RB/K_TC; // Length of the SRS sequence + +#ifdef SRS_DEBUG + LOG_I(NR_PHY,"Frame = %i, slot = %i\n", frame_number, slot_number); + LOG_I(NR_PHY,"B_SRS = %i\n", nr_srs_info->B_SRS); + LOG_I(NR_PHY,"C_SRS = %i\n", nr_srs_info->C_SRS); + LOG_I(NR_PHY,"b_hop = %i\n", nr_srs_info->b_hop); + LOG_I(NR_PHY,"K_TC = %i\n", K_TC); + LOG_I(NR_PHY,"K_TC_overbar = %i\n", nr_srs_info->K_TC_overbar); + LOG_I(NR_PHY,"n_SRS_cs = %i\n", nr_srs_info->n_SRS_cs); + LOG_I(NR_PHY,"n_ID_SRS = %i\n", nr_srs_info->n_ID_SRS); + LOG_I(NR_PHY,"n_shift = %i\n", nr_srs_info->n_shift); + LOG_I(NR_PHY,"n_RRC = %i\n", nr_srs_info->n_RRC); + LOG_I(NR_PHY,"groupOrSequenceHopping = %i\n", nr_srs_info->groupOrSequenceHopping); + LOG_I(NR_PHY,"l_offset = %i\n", nr_srs_info->l_offset); + LOG_I(NR_PHY,"T_SRS = %i\n", nr_srs_info->T_SRS); + LOG_I(NR_PHY,"T_offset = %i\n", nr_srs_info->T_offset); + LOG_I(NR_PHY,"R = %i\n", nr_srs_info->R); + LOG_I(NR_PHY,"N_ap = %i\n", N_ap); + LOG_I(NR_PHY,"N_symb_SRS = %i\n", nr_srs_info->N_symb_SRS); + LOG_I(NR_PHY,"l0 = %i\n", l0); + LOG_I(NR_PHY,"n_SRS_cs_max = %i\n", n_SRS_cs_max); + LOG_I(NR_PHY,"m_SRS_b = %i\n", m_SRS_b); + LOG_I(NR_PHY,"M_sc_b_SRS = %i\n", M_sc_b_SRS); +#endif + + // Validation of SRS config parameters + + if (nr_srs_info->R == 0) { + LOG_E(NR_PHY, "generate_srs: this parameter repetition factor %d is not consistent !\n", nr_srs_info->R); + return false; + } else if (nr_srs_info->R > nr_srs_info->N_symb_SRS) { + LOG_E(NR_PHY, "generate_srs: R %d can not be greater than N_symb_SRS %d !\n", nr_srs_info->R, nr_srs_info->N_symb_SRS); + return false; + } + + if (nr_srs_info->n_SRS_cs >= n_SRS_cs_max) { + LOG_E(NR_PHY, "generate_srs: inconsistent parameter n_SRS_cs %d >= n_SRS_cs_max %d !\n", nr_srs_info->n_SRS_cs, n_SRS_cs_max); + return false; + } + + if (nr_srs_info->T_SRS == 0) { + LOG_E(NR_PHY, "generate_srs: inconsistent parameter T_SRS %d can not be equal to zero !\n", nr_srs_info->T_SRS); + return false; + } else { + int index = 0; + while (srs_periodicity[index] != nr_srs_info->T_SRS) { + index++; + if (index == SRS_PERIODICITY) { + LOG_E(NR_PHY, "generate_srs: inconsistent parameter T_SRS %d not specified !\n", nr_srs_info->T_SRS); + return false; + } + } + } + + // Variable initialization + if(nr_srs_info) { + nr_srs_info->srs_generated_signal_bits = log2_approx(amp); + } + uint64_t subcarrier_offset = frame_parms->first_carrier_offset + bwp_start * NR_NB_SC_PER_RB; + double sqrt_N_ap = sqrt(N_ap); + int n_b[nr_srs_info->B_SRS + 1]; + + // Find index of table which is for this SRS length + uint16_t M_sc_b_SRS_index = 0; + while((ul_allocated_re[M_sc_b_SRS_index] != M_sc_b_SRS) && (M_sc_b_SRS_index < SRS_SB_CONF)) + M_sc_b_SRS_index++; + + // SRS sequence generation and mapping, TS 38.211 - Section 6.4.1.4 + for (int p_index = 0; p_index < N_ap; p_index++) { +#ifdef SRS_DEBUG + LOG_I(NR_PHY,"============ port %d ============\n", p_index); +#endif + + uint16_t n_SRS_cs_i = (nr_srs_info->n_SRS_cs + (n_SRS_cs_max * (SRS_antenna_port[p_index] - 1000) / N_ap)) % n_SRS_cs_max; + double alpha_i = 2 * M_PI * ((double)n_SRS_cs_i / (double)n_SRS_cs_max); + +#ifdef SRS_DEBUG + LOG_I(NR_PHY,"n_SRS_cs_i = %i\n", n_SRS_cs_i); + LOG_I(NR_PHY,"alpha_i = %f\n", alpha_i); +#endif + + for (int l_line = 0; l_line < nr_srs_info->N_symb_SRS; l_line++) { +#ifdef SRS_DEBUG + LOG_I(NR_PHY,":::::::: OFDM symbol %d ::::::::\n", l0+l_line); +#endif + + // Set group and sequence numbers (u,v) per OFDM symbol + int u = 0, v = 0; + switch(nr_srs_info->groupOrSequenceHopping) { + case neitherHopping: + u = nr_srs_info->n_ID_SRS % U_GROUP_NUMBER; + v = 0; + break; + case groupHopping: + u = group_number_hopping(slot_number, nr_srs_info->n_ID_SRS, l0, l_line); + v = 0; + break; + case sequenceHopping: + u = nr_srs_info->n_ID_SRS % U_GROUP_NUMBER; + v = sequence_number_hopping(slot_number, nr_srs_info->n_ID_SRS, M_sc_b_SRS, l0, l_line); + break; + default: + LOG_E(NR_PHY, "generate_srs: unknown hopping setting %d !\n", nr_srs_info->groupOrSequenceHopping); + return false; + } + +#ifdef SRS_DEBUG + LOG_I(NR_PHY,"u = %i\n", u); + LOG_I(NR_PHY,"v = %i\n", v); +#endif + + // Compute the frequency position index n_b + uint16_t sum_n_b = 0; + for (int b = 0; b <= nr_srs_info->B_SRS; b++) { + n_b[b] = compute_n_b(frame_number, slot_number, frame_parms->slots_per_frame, nr_srs_info, l_line, b, m_SRS_b); + sum_n_b += n_b[b]; + +#ifdef SRS_DEBUG + LOG_I(NR_PHY,"n_b[%i] = %i\n", b, n_b[b]); +#endif + } + +#ifdef SRS_DEBUG + LOG_I(NR_PHY,"sum_n_b = %i\n", sum_n_b); +#endif + + // Compute the frequency-domain starting position + uint8_t K_TC_p = 0; + if((nr_srs_info->n_SRS_cs >= n_SRS_cs_max / 2) + && (nr_srs_info->n_SRS_cs < n_SRS_cs_max) + && (N_ap == 4) + && ((SRS_antenna_port[p_index] == 1001) || (SRS_antenna_port[p_index] == 1003))) { + K_TC_p = (nr_srs_info->K_TC_overbar + K_TC / 2) % K_TC; + } else { + K_TC_p = nr_srs_info->K_TC_overbar; + } + uint8_t k_l_offset = 0; // If the SRS is configured by the IE SRS-PosResource-r16, the quantity k_l_offset is + // given by TS 38.211 - Table 6.4.1.4.3-2, otherwise k_l_offset = 0. + uint8_t k_0_overbar_p = (nr_srs_info->n_shift * NR_NB_SC_PER_RB + (K_TC_p + k_l_offset)) % K_TC; + uint8_t k_0_p = k_0_overbar_p + K_TC * M_sc_b_SRS * sum_n_b; + nr_srs_info->k_0_p[p_index][l_line] = k_0_p; + +#ifdef SRS_DEBUG + LOG_I(NR_PHY,"K_TC_p = %i\n", K_TC_p); + LOG_I(NR_PHY,"k_0_overbar_p = %i\n", k_0_overbar_p); + LOG_I(NR_PHY,"k_0_p = %i\n", k_0_p); +#endif + + uint16_t subcarrier = subcarrier_offset + k_0_p; + if (subcarrier>frame_parms->ofdm_symbol_size) + subcarrier -= frame_parms->ofdm_symbol_size; + uint16_t l_line_offset = l_line * frame_parms->ofdm_symbol_size; + // For each port, and for each OFDM symbol, here it is computed and mapped an SRS sequence with M_sc_b_SRS symbols + for (int k = 0; k < M_sc_b_SRS; k++) { + cd_t shift = {cos(alpha_i * k), sin(alpha_i * k)}; + const c16_t tmp = rv_ul_ref_sig[u][v][M_sc_b_SRS_index][k]; + cd_t r_overbar = {tmp.r, tmp.i}; + + // cos(x+y) = cos(x)cos(y) - sin(x)sin(y) + cd_t r = cdMul(shift, r_overbar); + c16_t r_amp = {(((int32_t)round((double)amp * r.r / sqrt_N_ap)) >> 15), + (((int32_t)round((double)amp * r.i / sqrt_N_ap)) >> 15)}; + +#ifdef SRS_DEBUG + int subcarrier_log = subcarrier-subcarrier_offset; + if(subcarrier_log < 0) { + subcarrier_log = subcarrier_log + frame_parms->ofdm_symbol_size; + } + if(subcarrier_log%12 == 0) { + LOG_I(NR_PHY,"------------ %d ------------\n", subcarrier_log/12); + } + LOG_I(NR_PHY, "(%d) \t%i\t%i\n", subcarrier_log, r_amp.r, r_amp.i); +#endif + + txdataF[p_index][symbol_offset + l_line_offset + subcarrier] = r_amp; + + // Subcarrier increment + subcarrier += K_TC; + if (subcarrier >= frame_parms->ofdm_symbol_size) { + subcarrier=subcarrier-frame_parms->ofdm_symbol_size; + } + + } // for (int k = 0; k < M_sc_b_SRS; k++) + } // for (int l_line = 0; l_line < N_symb_SRS; l_line++) + } // for (int p_index = 0; p_index < N_ap; p_index++) + return true; +} diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 542e3377e2..406fcc8038 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -32,7 +32,6 @@ #include "common/utils/LOG/vcd_signal_dumper.h" #include "PHY/INIT/nr_phy_init.h" #include "PHY/MODULATION/nr_modulation.h" -#include "PHY/NR_UE_TRANSPORT/srs_modulation_nr.h" #include "T.h" #include "executables/nr-softmodem.h" #include "executables/softmodem-common.h" From 614b6a0eef1083d98732efff0ab19195391df6f3 Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 11 Sep 2025 15:02:21 +0200 Subject: [PATCH 747/964] remove unnecessary srs_modulation files and move what's left into UE phy_procedures --- CMakeLists.txt | 1 - .../NR_ESTIMATION/nr_ul_channel_estimation.c | 1 - .../PHY/NR_UE_TRANSPORT/srs_modulation_nr.c | 142 ------------------ .../PHY/NR_UE_TRANSPORT/srs_modulation_nr.h | 52 ------- openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 98 +++++++++++- 5 files changed, 97 insertions(+), 197 deletions(-) delete mode 100644 openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.c delete mode 100644 openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 83fb33b1d2..1ec7d382fb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -944,7 +944,6 @@ set(PHY_SRC_UE ${OPENAIR1_DIR}/PHY/nr_phy_common/src/nr_phy_common_srs.c ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_scrambling.c ${OPENAIR1_DIR}/PHY/NR_REFSIG/refsig.c - ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/srs_modulation_nr.c ) set(PHY_NR_SRC diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c index 3b644ba4d3..7ec67ffbc5 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c @@ -28,7 +28,6 @@ #include "PHY/NR_REFSIG/dmrs_nr.h" #include "PHY/NR_REFSIG/ptrs_nr.h" #include "PHY/NR_TRANSPORT/nr_transport_proto.h" -#include "PHY/NR_UE_TRANSPORT/srs_modulation_nr.h" #include "PHY/NR_UE_ESTIMATION/filt16a_32.h" #include "PHY/NR_TRANSPORT/nr_sch_dmrs.h" #include "PHY/NR_REFSIG/ul_ref_seq_nr.h" diff --git a/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.c b/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.c deleted file mode 100644 index e97f887673..0000000000 --- a/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.c +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.openairinterface.org/?page_id=698 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -/*********************************************************************** -* -* FILENAME : srs_modulation_nr_nr.c -* -* MODULE : -* -* DESCRIPTION : function to set uplink reference symbols -* see TS 38211 6.4.1.4 Sounding reference signal -* -************************************************************************/ - -#include -#include - -#include "PHY/impl_defs_nr.h" -#include "PHY/defs_nr_UE.h" -#include "PHY/NR_REFSIG/ss_pbch_nr.h" -#include "PHY/NR_REFSIG/dmrs_nr.h" -#include "PHY/NR_REFSIG/ul_ref_seq_nr.h" -#include "PHY/nr_phy_common/inc/nr_phy_common.h" -#include "PHY/NR_UE_TRANSPORT/srs_modulation_nr.h" - -static void configure_srs_info(fapi_nr_ul_config_srs_pdu *srs_config_pdu, nr_srs_info_t *nr_srs_info) -{ - nr_srs_info->B_SRS = srs_config_pdu->bandwidth_index; - nr_srs_info->C_SRS = srs_config_pdu->config_index; - nr_srs_info->b_hop = srs_config_pdu->frequency_hopping; - nr_srs_info->comb_size = srs_config_pdu->comb_size; - nr_srs_info->K_TC_overbar = srs_config_pdu->comb_offset; - nr_srs_info->n_SRS_cs = srs_config_pdu->cyclic_shift; - nr_srs_info->n_ID_SRS = srs_config_pdu->sequence_id; - // It adjusts the SRS allocation to align with the common resource block grid in multiples of four - nr_srs_info->n_shift = srs_config_pdu->frequency_position; - nr_srs_info->n_RRC = srs_config_pdu->frequency_shift; - nr_srs_info->groupOrSequenceHopping = srs_config_pdu->group_or_sequence_hopping; - nr_srs_info->l_offset = srs_config_pdu->time_start_position; - nr_srs_info->T_SRS = srs_config_pdu->t_srs; - nr_srs_info->T_offset = srs_config_pdu->t_offset; - nr_srs_info->R = 1 << srs_config_pdu->num_repetitions; - nr_srs_info->N_symb_SRS = 1 << srs_config_pdu->num_symbols; // Number of consecutive OFDM symbols - nr_srs_info->n_srs_ports = 1 << srs_config_pdu->num_ant_ports; // Number of antenna port for transmission - nr_srs_info->resource_type = srs_config_pdu->resource_type; -} - -/******************************************************************* -* -* NAME : ue_srs_procedures_nr -* -* PARAMETERS : pointer to ue context -* pointer to rxtx context* -* -* RETURN : 0 if it is a valid slot for transmitting srs -* -1 if srs should not be transmitted -* -* DESCRIPTION : ue srs procedure -* send srs according to current configuration -* -*********************************************************************/ -int ue_srs_procedures_nr(PHY_VARS_NR_UE *ue, - const UE_nr_rxtx_proc_t *proc, - c16_t **txdataF, - nr_phy_data_tx_t *phy_data, - bool was_symbol_used[NR_NUMBER_OF_SYMBOLS_PER_SLOT]) -{ - if(phy_data->srs_vars.active == false) { - return -1; - } - - fapi_nr_ul_config_srs_pdu *srs_config_pdu = &phy_data->srs_vars.srs_config_pdu; - int first_srs_symbol = ue->frame_parms.symbols_per_slot - 1 - srs_config_pdu->time_start_position; - // Num consecutive SRS symbols according to 38.211 6.4.1.4.1 - int num_srs_symbols[] = {1, 2, 4, 8, 12}; - int last_srs_symbol = first_srs_symbol + num_srs_symbols[srs_config_pdu->num_symbols] - 1; - for (int i = first_srs_symbol; i <= last_srs_symbol; i++) { - was_symbol_used[i] = true; - } - -#ifdef SRS_DEBUG - LOG_I(NR_PHY,"Frame = %i, slot = %i\n", proc->frame_tx, proc->nr_slot_tx); - LOG_I(NR_PHY,"srs_config_pdu->rnti = 0x%04x\n", srs_config_pdu->rnti); - LOG_I(NR_PHY,"srs_config_pdu->handle = %u\n", srs_config_pdu->handle); - LOG_I(NR_PHY,"srs_config_pdu->bwp_size = %u\n", srs_config_pdu->bwp_size); - LOG_I(NR_PHY,"srs_config_pdu->bwp_start = %u\n", srs_config_pdu->bwp_start); - LOG_I(NR_PHY,"srs_config_pdu->subcarrier_spacing = %u\n", srs_config_pdu->subcarrier_spacing); - LOG_I(NR_PHY,"srs_config_pdu->cyclic_prefix = %u (0: Normal; 1: Extended)\n", srs_config_pdu->cyclic_prefix); - LOG_I(NR_PHY,"srs_config_pdu->num_ant_ports = %u (0 = 1 port, 1 = 2 ports, 2 = 4 ports)\n", srs_config_pdu->num_ant_ports); - LOG_I(NR_PHY,"srs_config_pdu->num_symbols = %u (0 = 1 symbol, 1 = 2 symbols, 2 = 4 symbols)\n", srs_config_pdu->num_symbols); - LOG_I(NR_PHY,"srs_config_pdu->num_repetitions = %u (0 = 1, 1 = 2, 2 = 4)\n", srs_config_pdu->num_repetitions); - LOG_I(NR_PHY,"srs_config_pdu->time_start_position = %u\n", srs_config_pdu->time_start_position); - LOG_I(NR_PHY,"srs_config_pdu->config_index = %u\n", srs_config_pdu->config_index); - LOG_I(NR_PHY,"srs_config_pdu->sequence_id = %u\n", srs_config_pdu->sequence_id); - LOG_I(NR_PHY,"srs_config_pdu->bandwidth_index = %u\n", srs_config_pdu->bandwidth_index); - LOG_I(NR_PHY,"srs_config_pdu->comb_size = %u (0 = comb size 2, 1 = comb size 4, 2 = comb size 8)\n", srs_config_pdu->comb_size); - LOG_I(NR_PHY,"srs_config_pdu->comb_offset = %u\n", srs_config_pdu->comb_offset); - LOG_I(NR_PHY,"srs_config_pdu->cyclic_shift = %u\n", srs_config_pdu->cyclic_shift); - LOG_I(NR_PHY,"srs_config_pdu->frequency_position = %u\n", srs_config_pdu->frequency_position); - LOG_I(NR_PHY,"srs_config_pdu->frequency_shift = %u\n", srs_config_pdu->frequency_shift); - LOG_I(NR_PHY,"srs_config_pdu->frequency_hopping = %u\n", srs_config_pdu->frequency_hopping); - LOG_I(NR_PHY,"srs_config_pdu->group_or_sequence_hopping = %u (0 = No hopping, 1 = Group hopping groupOrSequenceHopping, 2 = Sequence hopping)\n", srs_config_pdu->group_or_sequence_hopping); - LOG_I(NR_PHY,"srs_config_pdu->resource_type = %u (0: aperiodic, 1: semi-persistent, 2: periodic)\n", srs_config_pdu->resource_type); - LOG_I(NR_PHY,"srs_config_pdu->t_srs = %u\n", srs_config_pdu->t_srs); - LOG_I(NR_PHY,"srs_config_pdu->t_offset = %u\n", srs_config_pdu->t_offset); -#endif - - configure_srs_info(srs_config_pdu, ue->nr_srs_info); - NR_DL_FRAME_PARMS *frame_parms = &(ue->frame_parms); - uint16_t symbol_offset = (frame_parms->symbols_per_slot - 1 - srs_config_pdu->time_start_position)*frame_parms->ofdm_symbol_size; - - if (generate_srs_nr(frame_parms, - txdataF, - symbol_offset, - srs_config_pdu->bwp_start, - ue->nr_srs_info, - AMP, - proc->frame_tx, - proc->nr_slot_tx)) { - return 0; - } else { - return -1; - } -} diff --git a/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.h b/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.h deleted file mode 100644 index 8a413f1611..0000000000 --- a/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.openairinterface.org/?page_id=698 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -/*********************************************************************** -* -* FILENAME : srs_modulation_nr.h -* -* MODULE : -* -* DESCRIPTION : function to generate uplink reference sequences -* see 3GPP TS 38.211 6.4.1.4 Sounding reference signal -* -************************************************************************/ - -#ifndef SRS_MODULATION_NR_H -#define SRS_MODULATION_NR_H - -#include "PHY/defs_nr_UE.h" - -/*************** FUNCTIONS *****************************************/ - - -/** \brief This function processes srs configuration - * @param ue context - @param rxtx context - @param current gNB_id identifier - @returns 0 if srs is transmitted -1 otherwise */ -int ue_srs_procedures_nr(PHY_VARS_NR_UE *ue, - const UE_nr_rxtx_proc_t *proc, - c16_t **txdataF, - nr_phy_data_tx_t *phy_data, - bool was_symbol_used[NR_NUMBER_OF_SYMBOLS_PER_SLOT]); - -#endif /* SRS_MODULATION_NR_H */ diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index f683a2098d..c9cca526cd 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -40,10 +40,10 @@ #include "PHY/phy_extern_nr_ue.h" #include "PHY/MODULATION/modulation_UE.h" #include "PHY/INIT/nr_phy_init.h" +#include "PHY/nr_phy_common/inc/nr_phy_common.h" #include "PHY/NR_REFSIG/ptrs_nr.h" #include "PHY/NR_UE_TRANSPORT/nr_transport_ue.h" #include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h" -#include "PHY/NR_UE_TRANSPORT/srs_modulation_nr.h" #include "SCHED_NR_UE/phy_sch_processing_time.h" #include "PHY/NR_UE_ESTIMATION/nr_estimation.h" #ifdef EMOS @@ -270,6 +270,102 @@ void ue_ta_procedures(PHY_VARS_NR_UE *ue, int slot_tx, int frame_tx) } } +static void configure_srs_info(fapi_nr_ul_config_srs_pdu *srs_config_pdu, nr_srs_info_t *nr_srs_info) +{ + nr_srs_info->B_SRS = srs_config_pdu->bandwidth_index; + nr_srs_info->C_SRS = srs_config_pdu->config_index; + nr_srs_info->b_hop = srs_config_pdu->frequency_hopping; + nr_srs_info->comb_size = srs_config_pdu->comb_size; + nr_srs_info->K_TC_overbar = srs_config_pdu->comb_offset; + nr_srs_info->n_SRS_cs = srs_config_pdu->cyclic_shift; + nr_srs_info->n_ID_SRS = srs_config_pdu->sequence_id; + // It adjusts the SRS allocation to align with the common resource block grid in multiples of four + nr_srs_info->n_shift = srs_config_pdu->frequency_position; + nr_srs_info->n_RRC = srs_config_pdu->frequency_shift; + nr_srs_info->groupOrSequenceHopping = srs_config_pdu->group_or_sequence_hopping; + nr_srs_info->l_offset = srs_config_pdu->time_start_position; + nr_srs_info->T_SRS = srs_config_pdu->t_srs; + nr_srs_info->T_offset = srs_config_pdu->t_offset; + nr_srs_info->R = 1 << srs_config_pdu->num_repetitions; + nr_srs_info->N_symb_SRS = 1 << srs_config_pdu->num_symbols; // Number of consecutive OFDM symbols + nr_srs_info->n_srs_ports = 1 << srs_config_pdu->num_ant_ports; // Number of antenna port for transmission + nr_srs_info->resource_type = srs_config_pdu->resource_type; +} + +/******************************************************************* +* +* NAME : ue_srs_procedures_nr +* +* PARAMETERS : pointer to ue context +* pointer to rxtx context* +* +* RETURN : 0 if it is a valid slot for transmitting srs +* -1 if srs should not be transmitted +* +* DESCRIPTION : ue srs procedure +* send srs according to current configuration +* +*********************************************************************/ +static bool ue_srs_procedures_nr(PHY_VARS_NR_UE *ue, + const UE_nr_rxtx_proc_t *proc, + c16_t **txdataF, + nr_phy_data_tx_t *phy_data, + bool was_symbol_used[NR_NUMBER_OF_SYMBOLS_PER_SLOT]) +{ + if(phy_data->srs_vars.active == false) { + return false; + } + + fapi_nr_ul_config_srs_pdu *srs_config_pdu = &phy_data->srs_vars.srs_config_pdu; + int first_srs_symbol = ue->frame_parms.symbols_per_slot - 1 - srs_config_pdu->time_start_position; + // Num consecutive SRS symbols according to 38.211 6.4.1.4.1 + int num_srs_symbols[] = {1, 2, 4, 8, 12}; + int last_srs_symbol = first_srs_symbol + num_srs_symbols[srs_config_pdu->num_symbols] - 1; + for (int i = first_srs_symbol; i <= last_srs_symbol; i++) { + was_symbol_used[i] = true; + } + +#ifdef SRS_DEBUG + LOG_I(NR_PHY,"Frame = %i, slot = %i\n", proc->frame_tx, proc->nr_slot_tx); + LOG_I(NR_PHY,"srs_config_pdu->rnti = 0x%04x\n", srs_config_pdu->rnti); + LOG_I(NR_PHY,"srs_config_pdu->handle = %u\n", srs_config_pdu->handle); + LOG_I(NR_PHY,"srs_config_pdu->bwp_size = %u\n", srs_config_pdu->bwp_size); + LOG_I(NR_PHY,"srs_config_pdu->bwp_start = %u\n", srs_config_pdu->bwp_start); + LOG_I(NR_PHY,"srs_config_pdu->subcarrier_spacing = %u\n", srs_config_pdu->subcarrier_spacing); + LOG_I(NR_PHY,"srs_config_pdu->cyclic_prefix = %u (0: Normal; 1: Extended)\n", srs_config_pdu->cyclic_prefix); + LOG_I(NR_PHY,"srs_config_pdu->num_ant_ports = %u (0 = 1 port, 1 = 2 ports, 2 = 4 ports)\n", srs_config_pdu->num_ant_ports); + LOG_I(NR_PHY,"srs_config_pdu->num_symbols = %u (0 = 1 symbol, 1 = 2 symbols, 2 = 4 symbols)\n", srs_config_pdu->num_symbols); + LOG_I(NR_PHY,"srs_config_pdu->num_repetitions = %u (0 = 1, 1 = 2, 2 = 4)\n", srs_config_pdu->num_repetitions); + LOG_I(NR_PHY,"srs_config_pdu->time_start_position = %u\n", srs_config_pdu->time_start_position); + LOG_I(NR_PHY,"srs_config_pdu->config_index = %u\n", srs_config_pdu->config_index); + LOG_I(NR_PHY,"srs_config_pdu->sequence_id = %u\n", srs_config_pdu->sequence_id); + LOG_I(NR_PHY,"srs_config_pdu->bandwidth_index = %u\n", srs_config_pdu->bandwidth_index); + LOG_I(NR_PHY,"srs_config_pdu->comb_size = %u (0 = comb size 2, 1 = comb size 4, 2 = comb size 8)\n", srs_config_pdu->comb_size); + LOG_I(NR_PHY,"srs_config_pdu->comb_offset = %u\n", srs_config_pdu->comb_offset); + LOG_I(NR_PHY,"srs_config_pdu->cyclic_shift = %u\n", srs_config_pdu->cyclic_shift); + LOG_I(NR_PHY,"srs_config_pdu->frequency_position = %u\n", srs_config_pdu->frequency_position); + LOG_I(NR_PHY,"srs_config_pdu->frequency_shift = %u\n", srs_config_pdu->frequency_shift); + LOG_I(NR_PHY,"srs_config_pdu->frequency_hopping = %u\n", srs_config_pdu->frequency_hopping); + LOG_I(NR_PHY,"srs_config_pdu->group_or_sequence_hopping = %u (0 = No hopping, 1 = Group hopping groupOrSequenceHopping, 2 = Sequence hopping)\n", srs_config_pdu->group_or_sequence_hopping); + LOG_I(NR_PHY,"srs_config_pdu->resource_type = %u (0: aperiodic, 1: semi-persistent, 2: periodic)\n", srs_config_pdu->resource_type); + LOG_I(NR_PHY,"srs_config_pdu->t_srs = %u\n", srs_config_pdu->t_srs); + LOG_I(NR_PHY,"srs_config_pdu->t_offset = %u\n", srs_config_pdu->t_offset); +#endif + + configure_srs_info(srs_config_pdu, ue->nr_srs_info); + NR_DL_FRAME_PARMS *frame_parms = &(ue->frame_parms); + uint16_t symbol_offset = (frame_parms->symbols_per_slot - 1 - srs_config_pdu->time_start_position)*frame_parms->ofdm_symbol_size; + bool generated = generate_srs_nr(frame_parms, + txdataF, + symbol_offset, + srs_config_pdu->bwp_start, + ue->nr_srs_info, + AMP, + proc->frame_tx, + proc->nr_slot_tx); + return generated; +} + void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_tx_t *phy_data, c16_t **txp) { const int slot_tx = proc->nr_slot_tx; From e82bb5cb6de7778383321e13b18832f72aacc0f9 Mon Sep 17 00:00:00 2001 From: francescomani Date: Wed, 17 Sep 2025 14:08:00 +0200 Subject: [PATCH 748/964] remove unnecessary printf in dlsim --- openair1/SIMULATION/NR_PHY/dlsim.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index c4efb2752e..88ac4349b8 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -647,7 +647,7 @@ int main(int argc, char **argv) break; } } -printf("%d\n", slot); + logInit(); set_glog(loglvl); /* initialize the sin table */ From 52af5e5642f180bb879a2a90b31613c6f00657eb Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 30 Sep 2024 16:39:40 +0200 Subject: [PATCH 749/964] preventing UE to schedule SR on PUCCH in the same slot when MSG4 ACK is sent --- openair2/LAYER2/NR_MAC_UE/mac_defs.h | 36 +++++---- openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c | 20 ++--- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 78 +++++++++++--------- 3 files changed, 73 insertions(+), 61 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index d734870f52..25d1dd5808 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -303,6 +303,26 @@ typedef struct { uint32_t prach_mask; } NR_pdcch_order_config_t; +typedef struct { + NR_PUCCH_Resource_t *pucch_resource; + uint32_t ack_payload; + uint8_t sr_payload; + uint32_t csi_part1_payload; + uint32_t csi_part2_payload; + int n_sr; + int n_csi; + int n_harq; + int n_CCE; + int N_CCE; + int initial_pucch_id; +} PUCCH_sched_t; + +typedef struct { + int sched_frame; + int sched_slot; + PUCCH_sched_t pucch_sched; +} RA_PUCCH_SCHED_t; + typedef struct { // pointer to RACH config dedicated NR_RACH_ConfigDedicated_t *rach_ConfigDedicated; @@ -354,6 +374,8 @@ typedef struct { int preambleRxTargetPower; int msg3_deltaPreamble; int preambleReceivedTargetPower_config; + RA_PUCCH_SCHED_t *ra_pucch; + /// Random-access Contention Resolution Timer NR_timer_t contention_resolution_timer; /// Transmitted UE Contention Resolution Identifier @@ -403,20 +425,6 @@ typedef struct { uint16_t Msg3_f_alloc; } RAR_grant_t; -typedef struct { - NR_PUCCH_Resource_t *pucch_resource; - uint32_t ack_payload; - uint8_t sr_payload; - uint32_t csi_part1_payload; - uint32_t csi_part2_payload; - int n_sr; - int n_csi; - int n_harq; - int n_CCE; - int N_CCE; - int initial_pucch_id; -} PUCCH_sched_t; - typedef struct { uint32_t ssb_index; /// SSB RSRP in dBm diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index 58269f769a..dc5c00bcfc 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -1141,7 +1141,7 @@ void nr_get_Msg3_MsgA_PUSCH_payload(NR_UE_MAC_INST_t *mac, uint8_t *buf, int TBS *(NR_MAC_SUBHEADER_FIXED *)pdu = (NR_MAC_SUBHEADER_FIXED){.LCID = UL_SCH_LCID_PADDING}; pdu += sizeof(NR_MAC_SUBHEADER_FIXED); } - ra->Msg3_buffer = calloc(TBS_max, sizeof(uint8_t)); + ra->Msg3_buffer = calloc_or_fail(TBS_max, sizeof(uint8_t)); memcpy(ra->Msg3_buffer, buf, sizeof(uint8_t) * TBS_max); } @@ -1258,18 +1258,12 @@ void prepare_msg4_msgb_feedback(NR_UE_MAC_INST_t *mac, int pid, int ack_nack) .n_harq = 1}; current_harq->active = false; current_harq->ack_received = false; - if (get_softmodem_params()->emulate_l1) { - mac->nr_ue_emul_l1.harq[pid].active = true; - mac->nr_ue_emul_l1.harq[pid].active_dl_harq_sfn = sched_frame; - mac->nr_ue_emul_l1.harq[pid].active_dl_harq_slot = sched_slot; - } - fapi_nr_ul_config_request_pdu_t *pdu = lockGet_ul_config(mac, sched_frame, sched_slot, FAPI_NR_UL_CONFIG_TYPE_PUCCH); - if (!pdu) - return; - int ret = nr_ue_configure_pucch(mac, sched_slot, sched_frame, mac->ra.t_crnti, &pucch, &pdu->pucch_config_pdu); - if (ret != 0) - remove_ul_config_last_item(pdu); - release_ul_config(pdu, false); + + RA_config_t *ra = &mac->ra; + ra->ra_pucch = calloc_or_fail(1, sizeof(*ra->ra_pucch)); + ra->ra_pucch->pucch_sched = pucch; + ra->ra_pucch->sched_frame = sched_frame; + ra->ra_pucch->sched_slot = sched_slot; } void reset_ra(NR_UE_MAC_INST_t *nr_mac, bool free_prach) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index cf7fda5ccf..1df5e52e35 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -1713,7 +1713,7 @@ static bool schedule_uci_on_pusch(NR_UE_MAC_INST_t *mac, return mux_done; } -static void nr_ue_pucch_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, int slotP) +static void nr_ue_pucch_scheduler(NR_UE_MAC_INST_t *mac, frame_t frame, int slot) { PUCCH_sched_t pucch[3] = {0}; // TODO the size might change in the future in case of multiple SR or multiple CSI in a slot @@ -1722,40 +1722,50 @@ static void nr_ue_pucch_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, int slo mac->nr_ue_emul_l1.num_csi_reports = 0; int num_res = 0; - // SR - if (mac->state == UE_CONNECTED && trigger_periodic_scheduling_request(mac, &pucch[0], frameP, slotP)) { - num_res++; - // TODO check if the PUCCH resource for the SR transmission occasion overlap with a UL-SCH resource + if (mac->ra.ra_pucch) { + // scheduling PUCCH prepared in advance for MSG4 + RA_PUCCH_SCHED_t *ra_pucch = mac->ra.ra_pucch; + if (ra_pucch->sched_frame == frame && ra_pucch->sched_slot == slot) { + pucch[0] = ra_pucch->pucch_sched; + num_res++; + free_and_zero(mac->ra.ra_pucch); + } + } else { + // SR + if (mac->state == UE_CONNECTED && trigger_periodic_scheduling_request(mac, &pucch[0], frame, slot)) { + num_res++; + // TODO check if the PUCCH resource for the SR transmission occasion overlap with a UL-SCH resource + } + + // CSI + int csi_res = 0; + if (mac->state == UE_CONNECTED) + csi_res = nr_get_csi_measurements(mac, frame, slot, &pucch[num_res]); + if (csi_res > 0) { + num_res += csi_res; + } + + // ACKNACK + bool any_harq = get_downlink_ack(mac, frame, slot, &pucch[num_res]); + if (any_harq) + num_res++; + + if (num_res == 0) + return; + // do no transmit pucch if only SR scheduled and it is negative + if (num_res == 1 && pucch[0].n_sr > 0 && pucch[0].sr_payload == 0) + return; + + if (num_res > 1) + multiplex_pucch_resource(mac, pucch, num_res); } - // CSI - int csi_res = 0; - if (mac->state == UE_CONNECTED) - csi_res = nr_get_csi_measurements(mac, frameP, slotP, &pucch[num_res]); - if (csi_res > 0) { - num_res += csi_res; - } - - // ACKNACK - bool any_harq = get_downlink_ack(mac, frameP, slotP, &pucch[num_res]); - if (any_harq) - num_res++; - - if (num_res == 0) - return; - // do no transmit pucch if only SR scheduled and it is negative - if (num_res == 1 && pucch[0].n_sr > 0 && pucch[0].sr_payload == 0) - return; - - if (num_res > 1) - multiplex_pucch_resource(mac, pucch, num_res); - for (int j = 0; j < num_res; j++) { if (pucch[j].n_harq + pucch[j].n_sr + pucch[j].n_csi != 0) { LOG_D(NR_MAC, "%d.%d configure pucch, O_ACK %d, O_SR %d, O_CSI %d\n", - frameP, - slotP, + frame, + slot, pucch[j].n_harq, pucch[j].n_sr, pucch[j].n_csi); @@ -1764,20 +1774,20 @@ static void nr_ue_pucch_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, int slo mac->nr_ue_emul_l1.num_csi_reports = pucch[j].n_csi; // checking if we need to schedule pucch[j] on PUSCH - if (schedule_uci_on_pusch(mac, frameP, slotP, &pucch[j], mac->current_UL_BWP)) + if (schedule_uci_on_pusch(mac, frame, slot, &pucch[j], mac->current_UL_BWP)) continue; - fapi_nr_ul_config_request_pdu_t *pdu = lockGet_ul_config(mac, frameP, slotP, FAPI_NR_UL_CONFIG_TYPE_PUCCH); + fapi_nr_ul_config_request_pdu_t *pdu = lockGet_ul_config(mac, frame, slot, FAPI_NR_UL_CONFIG_TYPE_PUCCH); if (!pdu) { LOG_E(NR_MAC, "Error in pucch allocation\n"); return; } DevAssert(mac->current_DL_BWP != NULL); int mu = mac->current_DL_BWP->scs; - mac->nr_ue_emul_l1.active_uci_sfn_slot = NFAPI_SFNSLOT2DEC(mu, frameP, slotP); + mac->nr_ue_emul_l1.active_uci_sfn_slot = NFAPI_SFNSLOT2DEC(mu, frame, slot); int ret = nr_ue_configure_pucch(mac, - slotP, - frameP, + slot, + frame, mac->crnti, // FIXME not sure this is valid for all pucch instances &pucch[j], &pdu->pucch_config_pdu); From 84c51802daab8fd1f775f430d695520537e3622e Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 18 Sep 2025 15:27:11 +0200 Subject: [PATCH 750/964] CI RFsim test N2: remove RFsim config in CU-CP --- .../yaml_files/5g_rfsimulator_n2_ho/docker-compose.yaml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/ci-scripts/yaml_files/5g_rfsimulator_n2_ho/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_n2_ho/docker-compose.yaml index 1149d4f156..6c03a02443 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_n2_ho/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_n2_ho/docker-compose.yaml @@ -89,8 +89,7 @@ services: cap_drop: - ALL environment: - USE_ADDITIONAL_OPTIONS: --rfsim --rfsimulator.serveraddr 192.168.71.190 - --telnetsrv --telnetsrv.shrmod ci + USE_ADDITIONAL_OPTIONS: --telnetsrv --telnetsrv.shrmod ci --telnetsrv.listenaddr 192.168.71.150 --gNBs.[0].nr_cellid 0 --log_config.global_log_options level,nocolor,time @@ -201,8 +200,7 @@ services: cap_drop: - ALL environment: - USE_ADDITIONAL_OPTIONS: --rfsim --rfsimulator.serveraddr 192.168.71.190 - --telnetsrv --telnetsrv.shrmod ci + USE_ADDITIONAL_OPTIONS: --telnetsrv --telnetsrv.shrmod ci --telnetsrv.listenaddr 192.168.71.180 --gNBs.[0].E1_INTERFACE.[0].ipv4_cucp 192.168.71.180 --gNBs.[0].E1_INTERFACE.[0].ipv4_cuup 192.168.71.181 From fc4bd2e20ced1e5db83c9df9fa0cfa8473b328ec Mon Sep 17 00:00:00 2001 From: francescomani Date: Wed, 28 May 2025 16:25:30 +0200 Subject: [PATCH 751/964] RRC configuration for more than 1 reported RS option via configuration file to limit the number of reports to be configured --- openair2/GNB_APP/gnb_config.c | 1 + openair2/GNB_APP/gnb_paramdef.h | 4 ++ openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 1 + openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c | 55 +++++++++++++++++--- 4 files changed, 53 insertions(+), 8 deletions(-) diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 55110fc449..6f33946d93 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -1431,6 +1431,7 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg) LOG_I(GNB_APP, "SIB1 TDA %d\n", config.sib1_tda); config.do_CSIRS = *GNBParamList.paramarray[0][GNB_DO_CSIRS_IDX].iptr; config.do_SRS = *GNBParamList.paramarray[0][GNB_DO_SRS_IDX].iptr; + config.max_num_rsrp = *GNBParamList.paramarray[0][GNB_LIMIT_RSRP_REPORT_IDX].iptr; config.do_SINR = *GNBParamList.paramarray[0][GNB_DO_SINR_IDX].iptr; config.force_256qam_off = *GNBParamList.paramarray[0][GNB_FORCE256QAMOFF_IDX].iptr; config.force_UL256qam_off = *GNBParamList.paramarray[0][GNB_FORCEUL256QAMOFF_IDX].iptr; diff --git a/openair2/GNB_APP/gnb_paramdef.h b/openair2/GNB_APP/gnb_paramdef.h index 373958b1e8..e4e4bc3d2a 100644 --- a/openair2/GNB_APP/gnb_paramdef.h +++ b/openair2/GNB_APP/gnb_paramdef.h @@ -139,6 +139,7 @@ typedef enum { #define GNB_CONFIG_STRING_DU_SIB_LIST "du_sibs" #define GNB_CONFIG_STRING_DOSINR "do_SINR" #define GNB_CONFIG_STRING_1ST_ACTIVE_BWP "first_active_bwp" +#define GNB_CONFIG_STRING_LIMIT_RSRP_REPORT "max_num_RSRP_reported" #define GNB_CONFIG_HLP_STRING_ENABLE_SDAP "enable the SDAP layer\n" #define GNB_CONFIG_HLP_FORCE256QAMOFF "suppress activation of 256 QAM despite UE support" @@ -202,6 +203,7 @@ typedef enum { {GNB_CONFIG_STRING_DU_SIB_LIST, GNB_CONFIG_HLP_DU_SIBS, 0, .iptr=NULL, .defintarrayval=0, TYPE_INTARRAY, 0}, \ {GNB_CONFIG_STRING_DOSINR, GNB_CONFIG_HLP_DOSINR, 0, .iptr=NULL, .defintval=0, TYPE_INT, 0}, \ {GNB_CONFIG_STRING_1ST_ACTIVE_BWP, NULL, 0, .iptr=NULL, .defintval=0, TYPE_INT, 0}, \ +{GNB_CONFIG_STRING_LIMIT_RSRP_REPORT, NULL, 0, .iptr=NULL, .defintval=0, TYPE_INT, 0}, \ } // clang-format on @@ -246,6 +248,7 @@ typedef enum { #define GNB_DU_SIBS_IDX 37 #define GNB_DO_SINR_IDX 38 #define GNB_1ST_ACTIVE_BWP_IDX 39 +#define GNB_LIMIT_RSRP_REPORT_IDX 40 #define TRACKING_AREA_CODE_OKRANGE {0x0001,0xFFFD} #define NUM_DL_HARQ_OKVALUES {2,4,6,8,10,12,16,32} @@ -292,6 +295,7 @@ typedef enum { { .s5 = { NULL } }, \ { .s5 = { NULL } }, \ { .s5 = { NULL } }, \ + { .s5 = { NULL } }, \ } /*-------------------------------------------------------------------------------------------------------------------------------------------------*/ diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 50f77b681c..026d8d563e 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -186,6 +186,7 @@ typedef struct nr_mac_config_t { int minRXTXTIME; int do_CSIRS; int do_SRS; + int max_num_rsrp; bool force_256qam_off; bool force_UL256qam_off; bool use_deltaMCS; diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c index bb108d4004..f8919a3fa8 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c @@ -2094,21 +2094,52 @@ static void config_csi_meas_report(NR_CSI_MeasConfig_t *csi_MeasConfig, asn1cSeqAdd(&csi_MeasConfig->csi_ReportConfigToAddModList->list, csirep); } +static long config_nrofReportedRS(const NR_UE_NR_Capability_t *uecap, + uint64_t ssb_bitmap, + const NR_ServingCellConfigCommon_t *scc, + int max_num_reported_rs) +{ + long nb_band = *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]; + int num_supported_rs = 0; + if (uecap) { + for (int i = 0; i < uecap->rf_Parameters.supportedBandListNR.list.count; i++) { + NR_BandNR_t *band = uecap->rf_Parameters.supportedBandListNR.list.array[i]; + if (band->bandNR == nb_band) { + if (band->mimo_ParametersPerBand && band->mimo_ParametersPerBand->maxNumberNonGroupBeamReporting) { + int maxNumberNonGroupBeamReporting = 1 << *band->mimo_ParametersPerBand->maxNumberNonGroupBeamReporting; + if (num_supported_rs == 0 || num_supported_rs > maxNumberNonGroupBeamReporting) + num_supported_rs = maxNumberNonGroupBeamReporting; + } + } + } + } + int configured_rs = max_num_reported_rs > 0 ? min(num_supported_rs, max_num_reported_rs) : num_supported_rs; + uint32_t num_ssb = count_bits64(ssb_bitmap); + if (num_ssb == 1 || configured_rs < 2) + return NR_CSI_ReportConfig__groupBasedBeamReporting__disabled__nrofReportedRS_n1; + if (num_ssb == 2 || configured_rs == 2) + return NR_CSI_ReportConfig__groupBasedBeamReporting__disabled__nrofReportedRS_n2; + if (num_ssb == 3 || configured_rs == 3) + return NR_CSI_ReportConfig__groupBasedBeamReporting__disabled__nrofReportedRS_n3; + return NR_CSI_ReportConfig__groupBasedBeamReporting__disabled__nrofReportedRS_n4; +} + static void config_rsrp_meas_report(NR_CSI_MeasConfig_t *csi_MeasConfig, + const NR_UE_NR_Capability_t *uecap, const NR_ServingCellConfigCommon_t *servingcellconfigcommon, NR_PUCCH_CSI_Resource_t *pucchcsires, - int do_csi, // if rsrp is based on CSI or SSB + const nr_mac_config_t *configuration, int rep_id, int uid, int curr_bwp, int num_antenna_ports, - bool do_sinr) + uint64_t ssb_bitmap) { int resource_id = -1; for (int csi_list = 0; csi_list < csi_MeasConfig->csi_ResourceConfigToAddModList->list.count; csi_list++) { NR_CSI_ResourceConfig_t *csires = csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[csi_list]; if (csires->csi_RS_ResourceSetList.present == NR_CSI_ResourceConfig__csi_RS_ResourceSetList_PR_nzp_CSI_RS_SSB) { - if (do_csi && num_antenna_ports < 4) { + if (configuration->do_CSIRS && num_antenna_ports < 4) { if (csires->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList) resource_id = csires->csi_ResourceConfigId; } else { @@ -2130,13 +2161,13 @@ static void config_rsrp_meas_report(NR_CSI_MeasConfig_t *csi_MeasConfig, csirep->reportConfigType.choice.periodic = calloc(1, sizeof(*csirep->reportConfigType.choice.periodic)); set_csi_meas_periodicity(servingcellconfigcommon, csirep, uid, curr_bwp, true); asn1cSeqAdd(&csirep->reportConfigType.choice.periodic->pucch_CSI_ResourceList.list, pucchcsires); - if (do_csi && num_antenna_ports < 4) { + if (configuration->do_CSIRS && num_antenna_ports < 4) { csirep->reportQuantity.present = NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP; csirep->reportQuantity.choice.cri_RSRP = (NULL_t)0; } else { csirep->reportQuantity.present = NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP; csirep->reportQuantity.choice.ssb_Index_RSRP = (NULL_t)0; - if (do_sinr) { + if (configuration->do_SINR) { csirep->reportQuantity.present = NR_CSI_ReportConfig__reportQuantity_PR_none; csirep->reportQuantity.choice.none = (NULL_t)0; csirep->ext2 = calloc(1, sizeof(*csirep->ext2)); @@ -2148,7 +2179,10 @@ static void config_rsrp_meas_report(NR_CSI_MeasConfig_t *csi_MeasConfig, csirep->groupBasedBeamReporting.present = NR_CSI_ReportConfig__groupBasedBeamReporting_PR_disabled; csirep->groupBasedBeamReporting.choice.disabled = calloc(1, sizeof(*csirep->groupBasedBeamReporting.choice.disabled)); csirep->groupBasedBeamReporting.choice.disabled->nrofReportedRS = calloc(1, sizeof(*csirep->groupBasedBeamReporting.choice.disabled->nrofReportedRS)); - *csirep->groupBasedBeamReporting.choice.disabled->nrofReportedRS = NR_CSI_ReportConfig__groupBasedBeamReporting__disabled__nrofReportedRS_n1; + *csirep->groupBasedBeamReporting.choice.disabled->nrofReportedRS = config_nrofReportedRS(uecap, + ssb_bitmap, + servingcellconfigcommon, + configuration->max_num_rsrp); asn1cSeqAdd(&csi_MeasConfig->csi_ReportConfigToAddModList->list, csirep); } @@ -3292,6 +3326,7 @@ static NR_BWP_DownlinkDedicated_t *configure_initial_dl_bwp(const NR_ServingCell } static NR_CSI_MeasConfig_t *get_csiMeasConfig(const NR_ServingCellConfig_t *configDedicated, + const NR_UE_NR_Capability_t *uecap, const NR_ServingCellConfigCommon_t *scc, const nr_mac_config_t *configuration, int uid, @@ -3396,14 +3431,15 @@ static NR_CSI_MeasConfig_t *get_csiMeasConfig(const NR_ServingCellConfig_t *conf pucchrsrp->uplinkBandwidthPartId = bwp_id; pucchrsrp->pucch_Resource = pucch_Resource; config_rsrp_meas_report(csi_MeasConfig, + uecap, scc, pucchrsrp, - configuration->do_CSIRS, + configuration, bwp_id + 10, uid, curr_bwp, pdsch_AntennaPorts, - configuration->do_SINR); + bitmap); return csi_MeasConfig; } @@ -3482,6 +3518,7 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid, configDedicated->csi_MeasConfig = calloc(1, sizeof(*configDedicated->csi_MeasConfig)); configDedicated->csi_MeasConfig->present = NR_SetupRelease_CSI_MeasConfig_PR_setup; configDedicated->csi_MeasConfig->choice.setup = get_csiMeasConfig(configDedicated, + NULL, scc, configuration, uid, @@ -3786,6 +3823,7 @@ NR_CellGroupConfig_t * update_cellGroupConfig_for_BWP_switch(NR_CellGroupConfig_ ASN_STRUCT_FREE(asn_DEF_NR_CSI_MeasConfig, configDedicated->csi_MeasConfig->choice.setup); configDedicated->csi_MeasConfig->choice.setup = get_csiMeasConfig(configDedicated, + uecap, scc, configuration, uid, @@ -4101,6 +4139,7 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC configDedicated->csi_MeasConfig = calloc(1, sizeof(*configDedicated->csi_MeasConfig)); configDedicated->csi_MeasConfig->present = NR_SetupRelease_CSI_MeasConfig_PR_setup; configDedicated->csi_MeasConfig->choice.setup = get_csiMeasConfig(configDedicated, + uecap, servingcellconfigcommon, configuration, uid, From e5ea77f629f7cc8be8756ae837de30b455a6d386 Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 18 Aug 2025 14:41:04 +0200 Subject: [PATCH 752/964] separate UE fapi message for SSB measurements --- .../nfapi/public_inc/fapi_nr_ue_interface.h | 7 +++---- openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c | 1 + openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 2 -- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 5 +++++ openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c | 14 +------------- 5 files changed, 10 insertions(+), 19 deletions(-) diff --git a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h index a9e83758f6..6bea8f55cc 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h @@ -59,7 +59,9 @@ typedef struct { uint16_t Nid_cell; nfapi_nr_meas_type_e meas_type; bool is_neighboring_cell; - uint8_t rsrp_dBm; + int ssb_index; + int rsrp_dBm; + float sinr_dB; uint8_t rank_indicator; uint16_t i1; uint8_t i2; @@ -133,11 +135,8 @@ typedef struct { uint8_t ssb_length; uint16_t cell_id; uint16_t ssb_start_subcarrier; - short rsrp_dBm; long arfcn; rlm_t radiolink_monitoring; // -1 no monitoring, 0 out_of_sync, 1 in_sync - // SINR value times 10 as reporting granularity is 0.5 - float sinr_dB; } fapi_nr_ssb_pdu_t; typedef struct { diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c b/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c index 825e025308..747a000c4d 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c @@ -264,6 +264,7 @@ void nr_ue_ssb_rsrp_measurements(PHY_VARS_NR_UE *ue, .gNB_index = proc->gNB_id, .meas_type = NFAPI_NR_SS_MEAS, .Nid_cell = ue->frame_parms.Nid_cell, + .ssb_index = ssb_index, .is_neighboring_cell = false, }; int ssb_rsrp_dBm = ue->measurements.ssb_rsrp_dBm[ssb_index]; diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index 25447e4bb4..065cea8f72 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -176,8 +176,6 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind, rx->ssb_pdu.ssb_length = frame_parms->Lmax; rx->ssb_pdu.cell_id = frame_parms->Nid_cell; rx->ssb_pdu.ssb_start_subcarrier = frame_parms->ssb_start_subcarrier; - rx->ssb_pdu.rsrp_dBm = ue->measurements.ssb_rsrp_dBm[frame_parms->ssb_index]; - rx->ssb_pdu.sinr_dB = ue->measurements.ssb_sinr_dB[frame_parms->ssb_index]; rx->ssb_pdu.arfcn = get_ssb_arfcn(frame_parms); rx->ssb_pdu.radiolink_monitoring = RLM_in_sync; // TODO to be removed from here rx->ssb_pdu.decoded_pdu = true; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index ab13c9dd07..683834d736 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -1509,6 +1509,11 @@ void nr_ue_process_l1_measurements(NR_UE_MAC_INST_t *mac, frame_t frame, int slo LOG_D(NR_MAC, "(%d.%d) Received CSI-RS measurements\n", frame, slot); memcpy(&mac->l1_measurements, l1_measurements, sizeof(*l1_measurements)); bool csi_meas = l1_measurements->meas_type == NFAPI_NR_CSI_MEAS; + if (!csi_meas && !l1_measurements->is_neighboring_cell) { + mac->ssb_measurements.ssb_index = l1_measurements->ssb_index; + mac->ssb_measurements.ssb_rsrp_dBm = l1_measurements->rsrp_dBm; + mac->ssb_measurements.ssb_sinr_dB = l1_measurements->sinr_dB; + } nr_mac_rrc_meas_ind_ue(mac->ue_id, l1_measurements->gNB_index, l1_measurements->Nid_cell, diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c index 3f765bf6c9..1f86c61be5 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c @@ -374,7 +374,6 @@ static void fill_mib_in_rx_ind(nfapi_nr_dl_tti_request_pdu_t *pdu_list, fapi_nr_ rx_ind->rx_indication_body[pdu_idx].ssb_pdu.pdu[0] = (ssb_pdu->bchPayload) & 0xff; rx_ind->rx_indication_body[pdu_idx].ssb_pdu.pdu[1] = (ssb_pdu->bchPayload >> 8) & 0xff; rx_ind->rx_indication_body[pdu_idx].ssb_pdu.pdu[2] = (ssb_pdu->bchPayload >> 16) & 0xff; - rx_ind->rx_indication_body[pdu_idx].ssb_pdu.rsrp_dBm = ssb_pdu->ssbRsrp; rx_ind->rx_indication_body[pdu_idx].ssb_pdu.ssb_index = ssb_pdu->SsbBlockIndex; rx_ind->rx_indication_body[pdu_idx].ssb_pdu.ssb_length = pdu_list->PDUSize; rx_ind->rx_indication_body[pdu_idx].ssb_pdu.ssb_start_subcarrier = ssb_pdu->SsbSubcarrierOffset; @@ -1138,13 +1137,6 @@ static nr_dci_format_t handle_dci(NR_UE_MAC_INST_t *mac, return nr_ue_process_dci_indication_pdu(mac, frame, slot, dci); } -static void handle_ssb_meas(NR_UE_MAC_INST_t *mac, uint8_t ssb_index, int16_t rsrp_dbm, float_t sinr_dB) -{ - mac->ssb_measurements.ssb_index = ssb_index; - mac->ssb_measurements.ssb_rsrp_dBm = rsrp_dbm; - mac->ssb_measurements.ssb_sinr_dB = sinr_dB; -} - // L2 Abstraction Layer // Note: sdu should always be processed because data and timing advance updates are transmitted by the UE static int8_t handle_dlsch(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_info, int pdu_id) @@ -1268,16 +1260,12 @@ static uint32_t nr_ue_dl_processing(NR_UE_MAC_INST_t *mac, nr_downlink_indicatio rx_indication_body.pdu_type, dl_info->rx_ind->number_pdus); - switch(rx_indication_body.pdu_type){ + switch(rx_indication_body.pdu_type) { case FAPI_NR_RX_PDU_TYPE_SSB: handle_rlm(rx_indication_body.ssb_pdu.radiolink_monitoring, dl_info->frame, mac); if(rx_indication_body.ssb_pdu.decoded_pdu) { - handle_ssb_meas(mac, - rx_indication_body.ssb_pdu.ssb_index, - rx_indication_body.ssb_pdu.rsrp_dBm, - rx_indication_body.ssb_pdu.sinr_dB); ret_mask |= (handle_bcch_bch(mac, dl_info->cc_id, dl_info->gNB_index, From b462fa45e81dcc17c3de966c3e3558108126fc68 Mon Sep 17 00:00:00 2001 From: Jan Fromme Date: Thu, 14 Aug 2025 12:29:12 +0200 Subject: [PATCH 753/964] Fix RSRP report unpacking logic in gNB scheduler UCI Correctly handle unpacking of the first RSRP report and its resource ID before processing additional reports. Use the initial RSRP value as the reference for differential RSRP calculations in subsequent reports. --- .../LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index 682ea765ac..7edbf95600 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -588,28 +588,29 @@ static void evaluate_rsrp_report(gNB_MAC_INST *nrmac, } rsrp_report->nr_reports = csi_report->CSI_report_bitlen.nb_ssbri_cri; - uint16_t curr_payload; - for (int i = 0; i < rsrp_report->nr_reports; i++) { - int bitlen = csi_report->CSI_report_bitlen.cri_ssbri_bitlen; - curr_payload = pickandreverse_bits(payload, bitlen, *cumul_bits); - rsrp_report->resource_id[i] = *(index_list[bitlen > 0 ? ((curr_payload) & ~(~1U << (bitlen - 1))) : bitlen]); - LOG_D(MAC,"SSB/CSI-RS index = %d\n", rsrp_report->resource_id[i]); - *cumul_bits += bitlen; - } + int bitlen = csi_report->CSI_report_bitlen.cri_ssbri_bitlen; + uint8_t curr_payload = pickandreverse_bits(payload, bitlen, *cumul_bits); + rsrp_report->resource_id[0] = *(index_list[bitlen > 0 ? ((curr_payload) & ~(~1U << (bitlen - 1))) : bitlen]); + LOG_D(NR_MAC, "SSB/CSI-RS index = %d\n", rsrp_report->resource_id[0]); + *cumul_bits += bitlen; curr_payload = pickandreverse_bits(payload, 7, *cumul_bits); - int rsrp_index = curr_payload & 0x7f; + int rsrp = curr_payload & 0x7f; *cumul_bits += 7; - csi_report->nb_of_csi_ssb_report++; - bool valid = get_measured_rsrp(rsrp_index, &rsrp_report->RSRP[0]); + bool valid = get_measured_rsrp(rsrp, &rsrp_report->RSRP[0]); if (!valid) { - LOG_E(NR_MAC, "UE %04x: reported RSRP index %d invalid\n", UE->rnti, rsrp_index); + LOG_E(NR_MAC, "UE %04x: reported RSRP index %d invalid\n", UE->rnti, rsrp); return; } for (int i = 1; i < rsrp_report->nr_reports; i++) { + curr_payload = pickandreverse_bits(payload, bitlen, *cumul_bits); + rsrp_report->resource_id[i] = *(index_list[bitlen > 0 ? ((curr_payload) & ~(~1U << (bitlen - 1))) : bitlen]); + *cumul_bits += bitlen; + curr_payload = pickandreverse_bits(payload, 4, *cumul_bits); + csi_report->nb_of_csi_ssb_report++; rsrp_report->RSRP[i] = get_diff_rsrp(curr_payload & 0x0f, rsrp_report->RSRP[0]); *cumul_bits += 4; } From 5903806d2e2fe82d5cf2f780d18893c562162be1 Mon Sep 17 00:00:00 2001 From: Jan Fromme Date: Thu, 14 Aug 2025 16:44:25 +0200 Subject: [PATCH 754/964] enabled transmission of up to 4 RSRP measurement reports from UE to gNB --- openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 53 ++++---- openair2/LAYER2/NR_MAC_UE/mac_defs.h | 13 +- openair2/LAYER2/NR_MAC_UE/mac_proto.h | 2 +- openair2/LAYER2/NR_MAC_UE/main_ue_nr.c | 5 + openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c | 6 +- .../LAYER2/NR_MAC_UE/nr_ue_power_procedures.c | 19 +-- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 126 +++++++++++------- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 4 +- 8 files changed, 137 insertions(+), 91 deletions(-) diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index 065cea8f72..afb71ed164 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -965,31 +965,38 @@ int pbch_pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_ nr_ue_ssb_rsrp_measurements(ue, ssb_index, proc, rxdataF); // resetting ssb index for PBCH detection if there is a stronger SSB index - if(ue->measurements.ssb_rsrp_dBm[ssb_index] > ue->measurements.ssb_rsrp_dBm[fp->ssb_index]) + if(ue->measurements.ssb_rsrp_dBm[ssb_index] > ue->measurements.ssb_rsrp_dBm[fp->ssb_index]) { fp->ssb_index = ssb_index; - - if(ssb_index == fp->ssb_index) { - - LOG_D(PHY," ------ Decode MIB: frame.slot %d.%d ------ \n", frame_rx%1024, nr_slot_rx); - const int pbchSuccess = nr_ue_pbch_procedures(ue, proc, estimateSz, dl_ch_estimates, rxdataF); - - if (ue->no_timing_correction==0 && pbchSuccess == 0) { - LOG_D(PHY,"start adjust sync slot = %d no timing %d\n", nr_slot_rx, ue->no_timing_correction); - sampleShift = - nr_adjust_synch_ue(fp, ue, gNB_id, fp->ofdm_symbol_size, dl_ch_estimates_time, frame_rx, nr_slot_rx, 16384); - } - - if (get_nrUE_params()->cont_fo_comp && pbchSuccess == 0) { - double freq_offset = nr_ue_pbch_freq_offset(fp, estimateSz, dl_ch_estimates); - LOG_D(PHY,"compensated frequency offset = %.3f Hz, detected residual frequency offset = %.3f Hz, accumulated frequency offset = %.3f Hz\n", ue->freq_offset, freq_offset, ue->freq_off_acc); - - // PI controller - const double PID_P = get_nrUE_params()->freq_sync_P; - const double PID_I = get_nrUE_params()->freq_sync_I; - ue->freq_offset += freq_offset * PID_P + ue->freq_off_acc * PID_I; - ue->freq_off_acc += freq_offset; - } + LOG_D(PHY, "New best SSB: index %d RSRP %d\n", ssb_index, ue->measurements.ssb_rsrp_dBm[ssb_index]); } + + if(ssb_index != fp->ssb_index) + continue; + + LOG_D(PHY, " ------ Decode MIB: frame.slot %d.%d ------ \n", frame_rx % 1024, nr_slot_rx); + const int pbchSuccess = nr_ue_pbch_procedures(ue, proc, estimateSz, dl_ch_estimates, rxdataF); + + if (ue->no_timing_correction == 0 && pbchSuccess == 0) { + LOG_D(PHY,"start adjust sync slot = %d no timing %d\n", nr_slot_rx, ue->no_timing_correction); + sampleShift = + nr_adjust_synch_ue(fp, ue, gNB_id, fp->ofdm_symbol_size, dl_ch_estimates_time, frame_rx, nr_slot_rx, 16384); + } + + if (get_nrUE_params()->cont_fo_comp && pbchSuccess == 0) { + double freq_offset = nr_ue_pbch_freq_offset(fp, estimateSz, dl_ch_estimates); + LOG_D(PHY, + "compensated freq offset = %.3f Hz, detected residual freq offset = %.3f Hz, accumulated freq offset = %.3f Hz\n", + ue->freq_offset, + freq_offset, + ue->freq_off_acc); + + // PI controller + const double PID_P = get_nrUE_params()->freq_sync_P; + const double PID_I = get_nrUE_params()->freq_sync_I; + ue->freq_offset += freq_offset * PID_P + ue->freq_off_acc * PID_I; + ue->freq_off_acc += freq_offset; + } + LOG_D(PHY, "Doing N0 measurements in %s\n", __FUNCTION__); nr_ue_rrc_measurements(ue, proc, rxdataF); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PBCH, VCD_FUNCTION_OUT); diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index 680b5138df..1db7d33afc 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -407,8 +407,8 @@ typedef struct { NR_PUCCH_Resource_t *pucch_resource; uint32_t ack_payload; uint8_t sr_payload; - uint32_t csi_part1_payload; - uint32_t csi_part2_payload; + uint64_t csi_part1_payload; + uint64_t csi_part2_payload; int n_sr; int n_csi; int n_harq; @@ -418,9 +418,8 @@ typedef struct { } PUCCH_sched_t; typedef struct { - uint32_t ssb_index; /// SSB RSRP in dBm - short ssb_rsrp_dBm; + int ssb_rsrp_dBm; float_t ssb_sinr_dB; } NR_SSB_meas_t; @@ -473,8 +472,8 @@ typedef struct { } NR_BWP_PDCCH_t; typedef struct csi_payload { - uint32_t part1_payload; - uint32_t part2_payload; + uint64_t part1_payload; + uint64_t part2_payload; int p1_bits; int p2_bits; } csi_payload_t; @@ -625,7 +624,7 @@ typedef struct NR_UE_MAC_INST_s { uint8_t ssb_subcarrier_offset; int ssb_start_subcarrier; - NR_SSB_meas_t ssb_measurements; + NR_SSB_meas_t ssb_measurements[MAX_NB_SSB]; dci_pdu_rel15_t def_dci_pdu_rel15[NR_MAX_SLOTS_PER_FRAME][8]; diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index 035e59c09c..4897a8fab8 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -289,7 +289,7 @@ void remove_ul_config_last_item(fapi_nr_ul_config_request_pdu_t *pdu); fapi_nr_ul_config_request_pdu_t *fapiLockIterator(fapi_nr_ul_config_request_t *ul_config, frame_t frame_tx, int slot_tx); void release_ul_config(fapi_nr_ul_config_request_pdu_t *pdu, bool clearIt); -int16_t compute_nr_SSB_PL(NR_UE_MAC_INST_t *mac, short ssb_rsrp_dBm); +int16_t compute_nr_SSB_PL(NR_UE_MAC_INST_t *mac); // PUSCH scheduler: // - Calculate the slot in which ULSCH should be scheduled. This is current slot + K2, diff --git a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c index 78bfb1021c..1f35df5c4b 100644 --- a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c +++ b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c @@ -77,6 +77,11 @@ void nr_ue_init_mac(NR_UE_MAC_INST_t *mac) nr_timer_stop(&mac->scheduling_info.sr_DelayTimer); memset(&mac->ssb_measurements, 0, sizeof(mac->ssb_measurements)); + for (int i = 0; i < MAX_NB_SSB; i++) { + mac->ssb_measurements[i].ssb_rsrp_dBm = INT_MIN; + mac->ssb_measurements[i].ssb_sinr_dB = INT_MIN; + } + memset(&mac->ul_time_alignment, 0, sizeof(mac->ul_time_alignment)); memset(&mac->ssb_list, 0, sizeof(mac->ssb_list)); diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index bc29f7a9b9..9f962efc6e 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -42,7 +42,7 @@ int16_t get_prach_tx_power(NR_UE_MAC_INST_t *mac) { RA_config_t *ra = &mac->ra; - int16_t pathloss = compute_nr_SSB_PL(mac, mac->ssb_measurements.ssb_rsrp_dBm); + int16_t pathloss = compute_nr_SSB_PL(mac); int16_t ra_preamble_rx_power = (int16_t)(ra->prach_resources.ra_preamble_rx_target_power + pathloss); return min(ra->prach_resources.Pc_max, ra_preamble_rx_power); } @@ -177,7 +177,7 @@ static void select_preamble_group(NR_UE_MAC_INST_t *mac) // – preambleReceivedTargetPower – msg3-DeltaPreamble – messagePowerOffsetGroupB int groupB_pow_offset = get_messagePowerOffsetGroupB(groupB->messagePowerOffsetGroupB); int PLThreshold = ra->prach_resources.Pc_max - ra->preambleRxTargetPower - ra->msg3_deltaPreamble - groupB_pow_offset; - int pathloss = compute_nr_SSB_PL(mac, mac->ssb_measurements.ssb_rsrp_dBm); + int pathloss = compute_nr_SSB_PL(mac); // TODO if the Random Access procedure was initiated for the CCCH logical channel and the CCCH SDU size // plus MAC subheader is greater than ra-Msg3SizeGroupA if (ra->Msg3_size > get_Msg3SizeGroupA(groupB->ra_Msg3SizeGroupA) && pathloss < PLThreshold) @@ -971,7 +971,7 @@ bool init_RA(NR_UE_MAC_INST_t *mac, int frame) "msgA_RSRP_Threshold_r16 is mandatory present if both 2-step and 4-step random access types are configured\n"); // For thresholds the RSRP value is (IE value – 156) dBm except for the IE 127 in which case the actual value is infinity int rsrp_msga_thr = *twostep_conf->msgA_RSRP_Threshold_r16 - 156; - if (*twostep_conf->msgA_RSRP_Threshold_r16 != 127 && mac->ssb_measurements.ssb_rsrp_dBm > rsrp_msga_thr) + if (*twostep_conf->msgA_RSRP_Threshold_r16 != 127 && mac->ssb_measurements[mac->mib_ssb].ssb_rsrp_dBm > rsrp_msga_thr) twostep = true; } else { // if the BWP selected for Random Access procedure is only configured with 2-step RA type Random Access diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_power_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_power_procedures.c index 1efa0f1f12..860089165f 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_power_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_power_procedures.c @@ -358,7 +358,7 @@ int16_t get_pucch_tx_power_ue(NR_UE_MAC_INST_t *mac, 1, start_prb); float P_CMIN = current_UL_BWP->P_CMIN; - int16_t pathloss = compute_nr_SSB_PL(mac, mac->ssb_measurements.ssb_rsrp_dBm); + int16_t pathloss = compute_nr_SSB_PL(mac); if (power_config->twoPUCCH_PC_AdjustmentStates && *power_config->twoPUCCH_PC_AdjustmentStates > 1) { LOG_E(MAC,"PUCCH power control adjustment states with 2 states not yet implemented\n"); @@ -427,20 +427,23 @@ static int get_deltatf(uint16_t nb_of_prbs, // - PRACH transmission from a UE is not in response to a detection of a PDCCH order by the UE // Measurement units: // - referenceSignalPower: dBm/RE (average EPRE of the resources elements that carry secondary synchronization signals in dBm) -int16_t compute_nr_SSB_PL(NR_UE_MAC_INST_t *mac, short ssb_rsrp_dBm) +int16_t compute_nr_SSB_PL(NR_UE_MAC_INST_t *mac) { + // getting the maximum SSB RSRP from the SSB measurements + int max_ssb_rsrp_dBm = mac->ssb_measurements[mac->mib_ssb].ssb_rsrp_dBm; fapi_nr_config_request_t *cfg = &mac->phy_config.config_req; int referenceSignalPower = cfg->ssb_config.ss_pbch_power; + //TODO improve PL measurements. Probably not correct as it is. - int16_t pathloss = (int16_t)(referenceSignalPower - ssb_rsrp_dBm); + int16_t pathloss = (int16_t)(referenceSignalPower - max_ssb_rsrp_dBm); LOG_D(NR_MAC, "pathloss %d dB, referenceSignalPower %d dBm/RE (%f mW), RSRP %d dBm (%f mW)\n", pathloss, referenceSignalPower, pow(10, referenceSignalPower/10), - ssb_rsrp_dBm, - pow(10, ssb_rsrp_dBm/10)); + max_ssb_rsrp_dBm, + pow(10, max_ssb_rsrp_dBm/10)); return pathloss; } @@ -557,8 +560,8 @@ int get_pusch_tx_power_ue(NR_UE_MAC_INST_t *mac, DELTA_TF = 10 * log10(pow(2, BPRE * 1.25f) * beta_offset); } - // TODO: compute pathoss using correct reference - int16_t pathloss = compute_nr_SSB_PL(mac, mac->ssb_measurements.ssb_rsrp_dBm); + // TODO: compute pathloss using correct reference + int16_t pathloss = compute_nr_SSB_PL(mac); int P_CMIN = mac->current_UL_BWP->P_CMIN; float pusch_power_without_f_b_f_c = P_O_PUSCH + M_pusch_component + alpha * pathloss + DELTA_TF; @@ -626,7 +629,7 @@ int get_srs_tx_power_ue(NR_UE_MAC_INST_t *mac, get_m_srs(srs_resource->freqHopping.c_SRS, srs_resource->freqHopping.b_SRS), 0); // TODO: Determine SRS start RB - int16_t pathloss = compute_nr_SSB_PL(mac, mac->ssb_measurements.ssb_rsrp_dBm); + int16_t pathloss = compute_nr_SSB_PL(mac); int srs_power_without_h_b_f_c = P_0_SRS + alpha * pathloss + m_srs_component; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 683834d736..9c9d01fa1f 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -78,6 +78,12 @@ const uint16_t table_7_2_1[16] = { 1920, // row index 13 }; +typedef struct { + uint32_t ssb_index; + short ssb_rsrp_dBm; + float_t ssb_sinr_dB; +} NR_RSRP_meas_t; + /* TS 36.213 Table 9.2.3-3: Mapping of values for one HARQ-ACK bit to sequences */ static const int sequence_cyclic_shift_1_harq_ack_bit[2] /* HARQ-ACK Value 0 1 */ @@ -1510,9 +1516,9 @@ void nr_ue_process_l1_measurements(NR_UE_MAC_INST_t *mac, frame_t frame, int slo memcpy(&mac->l1_measurements, l1_measurements, sizeof(*l1_measurements)); bool csi_meas = l1_measurements->meas_type == NFAPI_NR_CSI_MEAS; if (!csi_meas && !l1_measurements->is_neighboring_cell) { - mac->ssb_measurements.ssb_index = l1_measurements->ssb_index; - mac->ssb_measurements.ssb_rsrp_dBm = l1_measurements->rsrp_dBm; - mac->ssb_measurements.ssb_sinr_dB = l1_measurements->sinr_dB; + int ssb_index = l1_measurements->ssb_index; + mac->ssb_measurements[ssb_index].ssb_rsrp_dBm = l1_measurements->rsrp_dBm; + mac->ssb_measurements[ssb_index].ssb_sinr_dB = l1_measurements->sinr_dB; } nr_mac_rrc_meas_ind_ue(mac->ue_id, l1_measurements->gNB_index, @@ -2764,6 +2770,14 @@ static uint8_t get_sinr_diff_index(float best_sinr, float current_sinr) return diff; } +// Comparison function for sorting SSB SINR measurements in descending order +static int compare_ssb_sinr(const void *a, const void *b) +{ + const NR_RSRP_meas_t *ma = (const NR_RSRP_meas_t *)a; + const NR_RSRP_meas_t *mb = (const NR_RSRP_meas_t *)b; + return mb->ssb_sinr_dB - ma->ssb_sinr_dB; +} + static csi_payload_t get_ssb_sinr_payload(NR_UE_MAC_INST_t *mac, struct NR_CSI_ReportConfig *csi_reportconfig, NR_CSI_ResourceConfigId_t csi_ResourceConfigId, @@ -2772,7 +2786,7 @@ static csi_payload_t get_ssb_sinr_payload(NR_UE_MAC_INST_t *mac, int nb_ssb = 0; // nb of ssb in the resource int nb_meas = 0; // nb of ssb to report measurements on int bits = 0; - uint32_t temp_payload = 0; + uint64_t temp_payload = 0; for (int csi_resourceidx = 0; csi_resourceidx < csi_MeasConfig->csi_ResourceConfigToAddModList->list.count; csi_resourceidx++) { struct NR_CSI_ResourceConfig *csi_resourceconfig = csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[csi_resourceidx]; @@ -2797,51 +2811,55 @@ static csi_payload_t get_ssb_sinr_payload(NR_UE_MAC_INST_t *mac, } AssertFatal(nb_ssb > 0, "No SSB found in the resource set\n"); - AssertFatal(nb_meas == 1, "PHY currently reports only the strongest SSB to MAC. Can't report more than 1 RSRP\n"); + AssertFatal(nb_meas <= 4,"Can't report more than 4 RSRPs\n"); int ssbri_bits = ceil(log2(nb_ssb)); - int ssb_index[nb_meas]; // the array contains index and RSRP of each SSB to be reported (nb_meas highest RSRPs) - float ssb_sinr[nb_meas]; - - // TODO replace the following 2 lines with a function to order the nb_meas highest SSB RSRPs - for (int i = 0; i < nb_ssb; i++) { - ssb_index[i] = -1;//Invalid index - if (*SSB_resource.list.array[i] == mac->mib_ssb) { - ssb_index[0] = i; - break; + // map SSB index to SSB resource table index, copy measurements, sort in descending order + NR_RSRP_meas_t sorted_sinr_measurements[nb_ssb]; + int sorted_idx = 0; + for (int measured_ssb_idx = 0; measured_ssb_idx < MAX_NB_SSB; measured_ssb_idx++) { + // searching for the SSB index in the SSB resource table + for (int ssb_resource = 0; ssb_resource < nb_ssb; ssb_resource++) { + if (*SSB_resource.list.array[ssb_resource] == measured_ssb_idx) { + sorted_sinr_measurements[sorted_idx].ssb_index = ssb_resource; + sorted_sinr_measurements[sorted_idx].ssb_rsrp_dBm = mac->ssb_measurements[measured_ssb_idx].ssb_rsrp_dBm; + sorted_sinr_measurements[sorted_idx].ssb_sinr_dB = mac->ssb_measurements[measured_ssb_idx].ssb_sinr_dB; + sorted_idx++; + break; + } } } - AssertFatal(ssb_index[0] >= 0, "Couldn't find corresponding SSB in csi_SSB_ResourceList\n"); - ssb_sinr[0] = mac->ssb_measurements.ssb_sinr_dB; + qsort(sorted_sinr_measurements, nb_ssb, sizeof(NR_RSRP_meas_t), compare_ssb_sinr); uint8_t ssbi; // TS38.212 v16.5.0: Table 6.3.1.1.2-8A if (ssbri_bits > 0) { - ssbi = ssb_index[0]; + ssbi = sorted_sinr_measurements[0].ssb_index; temp_payload = reverse_bits(ssbi, ssbri_bits); bits += ssbri_bits; } - uint8_t sinr_idx = get_sinr_index(ssb_sinr[0]); + uint8_t sinr_idx = get_sinr_index(sorted_sinr_measurements[0].ssb_sinr_dB); temp_payload |= (reverse_bits(sinr_idx, 7) << bits); bits += 7; // 7 bits for highest SINR // from the second SSB, differential report for (int i = 1; i < nb_meas; i++) { - ssbi = ssb_index[i]; + ssbi = sorted_sinr_measurements[i].ssb_index; temp_payload = reverse_bits(ssbi, ssbri_bits); bits += ssbri_bits; - sinr_idx = get_sinr_diff_index(ssb_sinr[0], ssb_sinr[i]); + sinr_idx = get_sinr_diff_index(sorted_sinr_measurements[0].ssb_sinr_dB, sorted_sinr_measurements[i].ssb_sinr_dB); temp_payload |= (reverse_bits(sinr_idx, 4) << bits); - bits += 4; // 7 bits for highest SINR + bits += 4; // 4 bits for differential SINR } break; // resource found } } - AssertFatal(bits <= 32, "Not supporting CSI report with more than 32 bits\n"); - csi_payload_t csi = {.part1_payload = temp_payload, .p1_bits = bits, csi.p2_bits = 0}; + int max_bits = sizeof(((csi_payload_t *)0)->part1_payload) * 8; + AssertFatal(bits <= max_bits, "Not supporting CSI report with more than %d bits (payload: %d bits)\n", max_bits, bits); + csi_payload_t csi = {.part1_payload = temp_payload, .part2_payload = 0, .p1_bits = bits, csi.p2_bits = 0}; return csi; } @@ -2891,6 +2909,14 @@ csi_payload_t nr_get_csi_payload(NR_UE_MAC_INST_t *mac, return csi; } +// Comparison function for sorting SSB RSRP measurements in descending order +static int compare_ssb_rsrp(const void *a, const void *b) +{ + const NR_RSRP_meas_t *ma = (const NR_RSRP_meas_t *)a; + const NR_RSRP_meas_t *mb = (const NR_RSRP_meas_t *)b; + return mb->ssb_rsrp_dBm - ma->ssb_rsrp_dBm; +} + static csi_payload_t get_ssb_rsrp_payload(NR_UE_MAC_INST_t *mac, struct NR_CSI_ReportConfig *csi_reportconfig, NR_CSI_ResourceConfigId_t csi_ResourceConfigId, @@ -2899,7 +2925,7 @@ static csi_payload_t get_ssb_rsrp_payload(NR_UE_MAC_INST_t *mac, int nb_ssb = 0; // nb of ssb in the resource int nb_meas = 0; // nb of ssb to report measurements on int bits = 0; - uint32_t temp_payload = 0; + uint64_t temp_payload = 0; for (int csi_resourceidx = 0; csi_resourceidx < csi_MeasConfig->csi_ResourceConfigToAddModList->list.count; csi_resourceidx++) { struct NR_CSI_ResourceConfig *csi_resourceconfig = csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[csi_resourceidx]; @@ -2907,7 +2933,7 @@ static csi_payload_t get_ssb_rsrp_payload(NR_UE_MAC_INST_t *mac, if (csi_reportconfig->groupBasedBeamReporting.present == NR_CSI_ReportConfig__groupBasedBeamReporting_PR_disabled) { if (csi_reportconfig->groupBasedBeamReporting.choice.disabled->nrofReportedRS != NULL) - nb_meas = *(csi_reportconfig->groupBasedBeamReporting.choice.disabled->nrofReportedRS)+1; + nb_meas = *(csi_reportconfig->groupBasedBeamReporting.choice.disabled->nrofReportedRS) + 1; else nb_meas = 1; } else @@ -2924,50 +2950,56 @@ static csi_payload_t get_ssb_rsrp_payload(NR_UE_MAC_INST_t *mac, } } - AssertFatal(nb_ssb>0,"No SSB found in the resource set\n"); - AssertFatal(nb_meas==1,"PHY currently reports only the strongest SSB to MAC. Can't report more than 1 RSRP\n"); + AssertFatal(nb_ssb > 0,"No SSB found in the resource set\n"); + AssertFatal(nb_meas <= 4,"Can't report more than 4 RSRPs\n"); int ssbri_bits = ceil(log2(nb_ssb)); - int ssb_rsrp[2][nb_meas]; // the array contains index and RSRP of each SSB to be reported (nb_meas highest RSRPs) - memset(ssb_rsrp, 0, sizeof(ssb_rsrp)); - - //TODO replace the following 2 lines with a function to order the nb_meas highest SSB RSRPs - for (int i=0; imib_ssb) { - ssb_rsrp[0][0] = i; - break; + // map SSB index to SSB resource table index, copy measurements, sort in descending order + NR_RSRP_meas_t sorted_rsrp_measurements[nb_ssb]; + int sorted_idx = 0; + for (int measured_ssb_idx = 0; measured_ssb_idx < MAX_NB_SSB; measured_ssb_idx++) { + // searching for the SSB index in the SSB resource table + for (int ssb_resource = 0; ssb_resource < nb_ssb; ssb_resource++) { + if (*SSB_resource.list.array[ssb_resource] == measured_ssb_idx) { + sorted_rsrp_measurements[sorted_idx].ssb_index = ssb_resource; + sorted_rsrp_measurements[sorted_idx].ssb_rsrp_dBm = mac->ssb_measurements[measured_ssb_idx].ssb_rsrp_dBm; + sorted_rsrp_measurements[sorted_idx].ssb_sinr_dB = mac->ssb_measurements[measured_ssb_idx].ssb_sinr_dB; + sorted_idx++; + break; + } } } - AssertFatal(*SSB_resource.list.array[ssb_rsrp[0][0]] == mac->mib_ssb, "Couldn't find corresponding SSB in csi_SSB_ResourceList\n"); - ssb_rsrp[1][0] = mac->ssb_measurements.ssb_rsrp_dBm; + qsort(sorted_rsrp_measurements, nb_ssb, sizeof(NR_RSRP_meas_t), compare_ssb_rsrp); - uint8_t ssbi; + uint32_t ssbi; if (ssbri_bits > 0) { - ssbi = ssb_rsrp[0][0]; + ssbi = sorted_rsrp_measurements[0].ssb_index; temp_payload = reverse_bits(ssbi, ssbri_bits); bits += ssbri_bits; } - uint8_t rsrp_idx = get_rsrp_index(ssb_rsrp[1][0]); + uint8_t rsrp_idx = get_rsrp_index(sorted_rsrp_measurements[0].ssb_rsrp_dBm); temp_payload |= (reverse_bits(rsrp_idx, 7) << bits); bits += 7; // 7 bits for highest RSRP // from the second SSB, differential report - for (int i=1; ipart1_payload) * 8; + AssertFatal(bits <= max_bits, "Not supporting CSI report with more than %d bits (payload: %d bits)\n", max_bits, bits); + + csi_payload_t csi = {.part1_payload = temp_payload, .part2_payload = 0, .p1_bits = bits, .p2_bits = 0}; return csi; } diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index cf7fda5ccf..fed19223f3 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -260,7 +260,7 @@ void update_mac_ul_timers(NR_UE_MAC_INST_t *mac) if (phr_info->is_configured) { bool prohibit_expired = nr_timer_tick(&phr_info->prohibitPHR_Timer); if (prohibit_expired) { - int16_t pathloss = compute_nr_SSB_PL(mac, mac->ssb_measurements.ssb_rsrp_dBm); + int16_t pathloss = compute_nr_SSB_PL(mac); if (abs(pathloss - phr_info->PathlossLastValue) > phr_info->PathlossChange_db) { phr_info->phr_reporting |= (1 << phr_cause_prohibit_timer); } @@ -2905,7 +2905,7 @@ static void nr_ue_fill_phr(NR_UE_MAC_INST_t *mac, headroom, tx_power); - phr_info->PathlossLastValue = compute_nr_SSB_PL(mac, mac->ssb_measurements.ssb_rsrp_dBm); + phr_info->PathlossLastValue = compute_nr_SSB_PL(mac); // Restart both timers according to 38.321 nr_timer_start(&phr_info->periodicPHR_Timer); nr_timer_start(&phr_info->prohibitPHR_Timer); From df9c41f36428679117a6342cfef40f56f19618ec Mon Sep 17 00:00:00 2001 From: Jan Fromme Date: Thu, 21 Aug 2025 09:16:07 +0000 Subject: [PATCH 755/964] Accumulate SSB indices in the SINR payload instead of overwriting the payload --- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 9c9d01fa1f..f2f783869c 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -2847,7 +2847,7 @@ static csi_payload_t get_ssb_sinr_payload(NR_UE_MAC_INST_t *mac, // from the second SSB, differential report for (int i = 1; i < nb_meas; i++) { ssbi = sorted_sinr_measurements[i].ssb_index; - temp_payload = reverse_bits(ssbi, ssbri_bits); + temp_payload |= (reverse_bits(ssbi, ssbri_bits) << bits); bits += ssbri_bits; sinr_idx = get_sinr_diff_index(sorted_sinr_measurements[0].ssb_sinr_dB, sorted_sinr_measurements[i].ssb_sinr_dB); From ca7fadfe075ccdc241d879f70c5409413831eef2 Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 19 Sep 2025 11:07:28 +0200 Subject: [PATCH 756/964] improved logs to evaluate RSRP report --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index 7edbf95600..f3de970683 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -591,7 +591,6 @@ static void evaluate_rsrp_report(gNB_MAC_INST *nrmac, int bitlen = csi_report->CSI_report_bitlen.cri_ssbri_bitlen; uint8_t curr_payload = pickandreverse_bits(payload, bitlen, *cumul_bits); rsrp_report->resource_id[0] = *(index_list[bitlen > 0 ? ((curr_payload) & ~(~1U << (bitlen - 1))) : bitlen]); - LOG_D(NR_MAC, "SSB/CSI-RS index = %d\n", rsrp_report->resource_id[0]); *cumul_bits += bitlen; curr_payload = pickandreverse_bits(payload, 7, *cumul_bits); @@ -599,6 +598,7 @@ static void evaluate_rsrp_report(gNB_MAC_INST *nrmac, *cumul_bits += 7; csi_report->nb_of_csi_ssb_report++; bool valid = get_measured_rsrp(rsrp, &rsrp_report->RSRP[0]); + LOG_D(NR_MAC, "SSB/CSI-RS index %d RSRP %d\n", rsrp_report->resource_id[0], rsrp_report->RSRP[0]); if (!valid) { LOG_E(NR_MAC, "UE %04x: reported RSRP index %d invalid\n", UE->rnti, rsrp); return; @@ -612,6 +612,7 @@ static void evaluate_rsrp_report(gNB_MAC_INST *nrmac, curr_payload = pickandreverse_bits(payload, 4, *cumul_bits); csi_report->nb_of_csi_ssb_report++; rsrp_report->RSRP[i] = get_diff_rsrp(curr_payload & 0x0f, rsrp_report->RSRP[0]); + LOG_D(NR_MAC, "SSB/CSI-RS index %d RSRP %d\n", rsrp_report->resource_id[i], rsrp_report->RSRP[i]); *cumul_bits += 4; } From 272be719ddef445d8017bb59b9f4577f9891577e Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Fri, 19 Sep 2025 12:11:58 +0200 Subject: [PATCH 757/964] NR UE: in nr_ue_scheduler.c set LCID_buffer_remain to 0 if RLC indicates not more bytes in buffer If the RLC indicates that there is no more data in the buffer, also the scheduler's LCID_buffer_remain should be set to 0. Else the UE sends BSR indicating it has data to be transmitted. The gNB would then unnecessarily schedule UL for this UE, which would not be used, as there is no actual data to be transmitted. --- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 2 +- 1 file changed, 1 insertion(+), 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 cf7fda5ccf..8253608335 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -1299,8 +1299,8 @@ static void nr_update_rlc_buffers_status(NR_UE_MAC_INST_t *mac, frame_t frameP, rlc_status.bytes_in_buffer, frameP, slotP); - lc_sched_info->LCID_buffer_remain = rlc_status.bytes_in_buffer; } + lc_sched_info->LCID_buffer_remain = rlc_status.bytes_in_buffer; } } From 5c1675838690b91409ffd4414efd600996aa5b94 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Thu, 18 Sep 2025 14:12:00 +0200 Subject: [PATCH 758/964] gNB: when creating a ReconfigurationWithSync, make sure epochTime_r17 is present if there is a ntn_Config_r17 Fixes #995 --- openair1/SIMULATION/NR_PHY/dlsim.c | 2 +- openair1/SIMULATION/NR_PHY/ulsim.c | 2 +- openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c | 4 ++-- openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c | 15 ++++++++++++++- openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h | 2 +- 5 files changed, 19 insertions(+), 6 deletions(-) diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index c4efb2752e..b713fe5f5f 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -804,7 +804,7 @@ printf("%d\n", slot); rnti_t rnti = 0x1234; int uid = 0; NR_CellGroupConfig_t *secondaryCellGroup = get_default_secondaryCellGroup(scc, UE_Capability_nr, 0, 1, &conf, uid); - secondaryCellGroup->spCellConfig->reconfigurationWithSync = get_reconfiguration_with_sync(rnti, uid, scc); + secondaryCellGroup->spCellConfig->reconfigurationWithSync = get_reconfiguration_with_sync(rnti, uid, scc, frame); /* -U option modify DMRS */ if(modify_dmrs) { diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index 0d3687bb4d..ec4a7190fa 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -708,7 +708,7 @@ int main(int argc, char *argv[]) rnti_t rnti = 0x1234; int uid = 0; NR_CellGroupConfig_t *secondaryCellGroup = get_default_secondaryCellGroup(scc, UE_Capability_nr, 0, 1, &conf, uid); - secondaryCellGroup->spCellConfig->reconfigurationWithSync = get_reconfiguration_with_sync(rnti, uid, scc); + secondaryCellGroup->spCellConfig->reconfigurationWithSync = get_reconfiguration_with_sync(rnti, uid, scc, frame); NR_BCCH_BCH_Message_t *mib = get_new_MIB_NR(scc); diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c index f73f4b8f70..b3d596b524 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -572,11 +572,11 @@ static NR_UE_info_t *create_new_UE(gNB_MAC_INST *mac, uint32_t cu_id, const NR_C const nr_mac_config_t *configuration = &mac->radio_config; if (is_SA) { cellGroupConfig = get_initial_cellGroupConfig(UE->uid, scc, &mac->radio_config, &mac->rlc_config); - cellGroupConfig->spCellConfig->reconfigurationWithSync = get_reconfiguration_with_sync(UE->rnti, UE->uid, scc); + cellGroupConfig->spCellConfig->reconfigurationWithSync = get_reconfiguration_with_sync(UE->rnti, UE->uid, scc, mac->frame); } else { NR_UE_NR_Capability_t *cap = get_ue_nr_cap_from_cg_config_info(cgci); cellGroupConfig = get_default_secondaryCellGroup(scc, cap, 1, 1, configuration, UE->uid); - cellGroupConfig->spCellConfig->reconfigurationWithSync = get_reconfiguration_with_sync(UE->rnti, UE->uid, scc); + cellGroupConfig->spCellConfig->reconfigurationWithSync = get_reconfiguration_with_sync(UE->rnti, UE->uid, scc, mac->frame); // TODO: in NSA we assign capabilities here, otherwise outside => not logic UE->capability = cap; } diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c index bb108d4004..197c5d54b9 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c @@ -4123,7 +4123,7 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC return secondaryCellGroup; } -NR_ReconfigurationWithSync_t *get_reconfiguration_with_sync(rnti_t rnti, uid_t uid, const NR_ServingCellConfigCommon_t *scc) +NR_ReconfigurationWithSync_t *get_reconfiguration_with_sync(rnti_t rnti, uid_t uid, const NR_ServingCellConfigCommon_t *scc, int frame) { NR_ReconfigurationWithSync_t *reconfigurationWithSync = calloc(1, sizeof(*reconfigurationWithSync)); reconfigurationWithSync->newUE_Identity = rnti; @@ -4133,6 +4133,19 @@ NR_ReconfigurationWithSync_t *get_reconfiguration_with_sync(rnti_t rnti, uid_t u reconfigurationWithSync->spCellConfigCommon = clone_ServingCellConfigCommon(scc); + // in case of ReconfigurationWithSync, the epochTime_r17 must be present if there is a ntn_Config_r17 + if (reconfigurationWithSync->spCellConfigCommon->ext2 && reconfigurationWithSync->spCellConfigCommon->ext2->ntn_Config_r17) { + NR_NTN_Config_r17_t *ntncfg = reconfigurationWithSync->spCellConfigCommon->ext2->ntn_Config_r17; + if (!ntncfg->epochTime_r17) { + ntncfg->epochTime_r17 = calloc(1, sizeof(*ntncfg->epochTime_r17)); + // the epochTime_r17 is esp. relevant for the timer T430, which runs for multiples of 5 seconds. + // here we don't have access to the current subFrame number, so we only set the SFN. + // the error of up to 10 ms should be acceptable for this long running timer. + ntncfg->epochTime_r17->sfn_r17 = frame; + ntncfg->epochTime_r17->subFrameNR_r17 = 0; + } + } + reconfigurationWithSync->rach_ConfigDedicated = calloc(1, sizeof(*reconfigurationWithSync->rach_ConfigDedicated)); reconfigurationWithSync->rach_ConfigDedicated->present = NR_ReconfigurationWithSync__rach_ConfigDedicated_PR_uplink; NR_RACH_ConfigDedicated_t *uplink = calloc(1, sizeof(*uplink)); diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h index d5df69b3c6..89ce03e7f5 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h @@ -110,7 +110,7 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC const nr_mac_config_t *configuration, int uid); -NR_ReconfigurationWithSync_t *get_reconfiguration_with_sync(rnti_t rnti, uid_t uid, const NR_ServingCellConfigCommon_t *scc); +NR_ReconfigurationWithSync_t *get_reconfiguration_with_sync(rnti_t rnti, uid_t uid, const NR_ServingCellConfigCommon_t *scc, int frame); NR_RLC_BearerConfig_t *get_SRB_RLC_BearerConfig(long channelId, long priority, From a43fbe1bacb244c13ebc183b082ee677f2a85807 Mon Sep 17 00:00:00 2001 From: Bartosz Podrygajlo Date: Fri, 19 Sep 2025 15:04:43 +0200 Subject: [PATCH 759/964] NR UE: Add UE id to RRC timer timeout LOGs --- openair2/RRC/NR_UE/rrc_timers_and_constants.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/openair2/RRC/NR_UE/rrc_timers_and_constants.c b/openair2/RRC/NR_UE/rrc_timers_and_constants.c index 694656736a..133ffb8d8e 100644 --- a/openair2/RRC/NR_UE/rrc_timers_and_constants.c +++ b/openair2/RRC/NR_UE/rrc_timers_and_constants.c @@ -162,7 +162,7 @@ void nr_rrc_handle_timers(NR_UE_RRC_INST_t *rrc) bool t300_expired = nr_timer_tick(&timers->T300); if(t300_expired) { - LOG_W(NR_RRC, "Timer T300 expired! No timely response to RRCSetupRequest\n"); + LOG_W(NR_RRC, "[UE %ld] Timer T300 expired! No timely response to RRCSetupRequest\n", rrc->ue_id); handle_t300_expiry(rrc); } @@ -170,7 +170,7 @@ void nr_rrc_handle_timers(NR_UE_RRC_INST_t *rrc) // Upon T301 expiry, the UE shall perform the actions upon going to RRC_IDLE // with release cause 'RRC connection failure' if(t301_expired) { - LOG_W(NR_RRC, "Timer T301 expired! No timely response to RRCReestabilshmentRequest\n"); + LOG_W(NR_RRC, "[UE %ld] Timer T301 expired! No timely response to RRCReestabilshmentRequest\n", rrc->ue_id); nr_rrc_going_to_IDLE(rrc, RRC_CONNECTION_FAILURE, NULL); } @@ -178,13 +178,13 @@ void nr_rrc_handle_timers(NR_UE_RRC_INST_t *rrc) // 5.3.14.4 in 38.331 // consider the barring for this Access Category to be alleviated if (t302_expired) { - LOG_W(NR_RRC, "Timer T302 expired! Access barring alleviated!\n"); + LOG_W(NR_RRC, "[UE %ld] Timer T302 expired! Access barring alleviated!\n", rrc->ue_id); handle_302_expired_stopped(rrc); } bool t304_expired = nr_timer_tick(&timers->T304); if(t304_expired) { - LOG_W(NR_RRC, "Timer T304 expired\n"); + LOG_W(NR_RRC, "[UE %ld] Timer T304 expired\n", rrc->ue_id); // TODO // For T304 of MCG, in case of the handover from NR or intra-NR // handover, initiate the RRC re-establishment procedure; @@ -194,15 +194,15 @@ void nr_rrc_handle_timers(NR_UE_RRC_INST_t *rrc) bool t310_expired = nr_timer_tick(&timers->T310); if(t310_expired) { - LOG_W(NR_RRC, "Timer T310 expired\n"); + LOG_W(NR_RRC, "[UE %ld] Timer T310 expired\n", rrc->ue_id); // handle detection of radio link failure // as described in 5.3.10.3 of 38.331 handle_rlf_detection(rrc); } bool t311_expired = nr_timer_tick(&timers->T311); - if(t311_expired) { - LOG_W(NR_RRC, "Timer T311 expired! No suitable cell found in time after initiation of re-establishment\n"); + if (t311_expired) { + LOG_W(NR_RRC, "[UE %ld] Timer T311 expired! No suitable cell found in time after initiation of re-establishment\n", rrc->ue_id); // Upon T311 expiry, the UE shall perform the actions upon going to RRC_IDLE // with release cause 'RRC connection failure' nr_rrc_going_to_IDLE(rrc, RRC_CONNECTION_FAILURE, NULL); @@ -210,7 +210,7 @@ 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! Indicate UL SYNC LOSS to MAC\n"); + LOG_W(NR_RRC, "[UE %ld] Timer T430 expired! Indicate UL SYNC LOSS to MAC\n", rrc->ue_id); // Upon T430 expiry, the UE shall reacquire SIB19 and re-obtain UL-SYNC // Spec 38.331 Section 5.2.2.6 handle_t430_expiry(rrc); From d38ce7c1c9cdba0b58cce5930d91c492eabd938f Mon Sep 17 00:00:00 2001 From: Bartosz Podrygajlo Date: Fri, 19 Sep 2025 15:09:10 +0200 Subject: [PATCH 760/964] Extend t300 in multi_ue rfsim testcase Extend t300 to 1000 to increase the time the gNB has to handle MSG3. Hopefully this prevents the UEs from timing out after MSG3. --- .../yaml_files/5g_rfsimulator_multiue/docker-compose.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci-scripts/yaml_files/5g_rfsimulator_multiue/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_multiue/docker-compose.yaml index d0b76fc165..9d660e0c3b 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_multiue/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_multiue/docker-compose.yaml @@ -88,7 +88,7 @@ services: cap_drop: - ALL environment: - USE_ADDITIONAL_OPTIONS: -E --rfsim --log_config.global_log_options level,nocolor,time + USE_ADDITIONAL_OPTIONS: -E --rfsim --log_config.global_log_options level,nocolor,time --gNBs.[0].TIMERS.t300 1000 ASAN_OPTIONS: detect_leaks=0 depends_on: - oai-ext-dn From a71a813a7c152eaa0cfcaf1c38e4ad8f7ce9f65e Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Mon, 11 Aug 2025 17:13:45 +0200 Subject: [PATCH 761/964] replace bad DCI by specific message for each case and add checks for bad pointers, or sanitize detected warnings --- openair1/PHY/LTE_UE_TRANSPORT/dci_tools_ue.c | 189 ++++++++++--------- openair1/PHY/LTE_UE_TRANSPORT/dci_ue.c | 8 +- 2 files changed, 99 insertions(+), 98 deletions(-) diff --git a/openair1/PHY/LTE_UE_TRANSPORT/dci_tools_ue.c b/openair1/PHY/LTE_UE_TRANSPORT/dci_tools_ue.c index e567dc3d9b..9f850cf2b9 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/dci_tools_ue.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/dci_tools_ue.c @@ -941,17 +941,17 @@ void extract_dci2A_info(uint8_t N_RB_DL, frame_type_t frame_type, uint8_t nb_ant pdci_info_extarcted->tpmi = tpmi; } -int check_dci_format1_1a_coherency(DCI_format_t dci_format, - uint8_t N_RB_DL, - uint16_t rnti, - uint16_t tc_rnti, - uint16_t si_rnti, - uint16_t ra_rnti, - uint16_t p_rnti, - uint32_t frame, - uint8_t subframe, - DCI_INFO_EXTRACTED_t *pdci_info_extarcted, - LTE_DL_UE_HARQ_t *pdlsch0_harq) +static int check_dci_format1_1a_coherency(DCI_format_t dci_format, + uint8_t N_RB_DL, + uint16_t rnti, + uint16_t tc_rnti, + uint16_t si_rnti, + uint16_t ra_rnti, + uint16_t p_rnti, + uint32_t frame, + uint8_t subframe, + DCI_INFO_EXTRACTED_t *pdci_info_extarcted, + LTE_DL_UE_HARQ_t *pdlsch0_harq) { uint8_t harq_pid = pdci_info_extarcted->harq_pid; uint32_t rballoc = pdci_info_extarcted->rballoc; @@ -982,34 +982,39 @@ int check_dci_format1_1a_coherency(DCI_format_t dci_format, // I- check dci content minimum coherency if( ((rnti==si_rnti) || (rnti==p_rnti) || (rnti==ra_rnti)) && harq_pid > 0) { - return(0); + LOG_I(PHY, "bad system or random access rnti %x id, harq %d \n", rnti, harq_pid); + return (0); } if(harq_pid>=8) { - // LOG_I(PHY,"bad harq id \n"); - return(0); + LOG_I(PHY, "bad harq id %d\n", harq_pid); + return (0); } if(dci_format == format1 && ((rnti==si_rnti) || (rnti==p_rnti) || (rnti==ra_rnti)) ) { - // LOG_I(PHY,"bad dci format \n"); - return(0); + LOG_I(PHY, "bad dci format 1 with system rnti %x\n", rnti); + return (0); } if( mcs1 > 28) { + if (!pdlsch0_harq) { + LOG_E(PHY, "pointer to pdlsch0_harq is NULL\n"); + return 0; + } if(pdlsch0_harq->round == 0) { - // LOG_I(PHY,"bad dci mcs + round \n"); - return(0); + LOG_I(PHY, "bad dci mcs %d + round %d\n", mcs1, pdlsch0_harq->round); + return (0); } if((rnti==si_rnti) || (rnti==p_rnti) || (rnti==ra_rnti)) { - // LOG_I(PHY,"bad dci mcs + rnti \n"); - return(0); + LOG_I(PHY, "bad dci mcs %d + rnti %x\n", mcs1, rnti); + return (0); } } @@ -1065,47 +1070,47 @@ int check_dci_format1_1a_coherency(DCI_format_t dci_format, } } - - else if (dci_format == format1) - { - NPRB = conv_nprb(rah, rballoc, N_RB_DL); + else if (dci_format == format1) { + NPRB = conv_nprb(rah, rballoc, N_RB_DL); } - if(dci_format == format1A && rballoc > RIV_max) { - // LOG_I(PHY,"bad dci rballoc rballoc %d RIV_max %lld \n",rballoc, RIV_max); - // DCI false detection - return(0); + LOG_I(PHY, "bad dci rballoc rballoc %d RIV_max %lld \n", rballoc, RIV_max); + // DCI false detection + return (0); } if(NPRB == 0) { // DCI false detection - // LOG_I(PHY,"bad NPRB = 0 \n"); + LOG_I(PHY, "bad dci NPRB = 0 \n"); return(0); } // this a retransmission + if (!pdlsch0_harq) { + LOG_E(PHY, "pointer to pdlsch0_harq is NULL\n"); + return 0; + } if(pdlsch0_harq->round>0) { // compare old TBS to new TBS if((mcs1<29) && (pdlsch0_harq->TBS != TBStable[get_I_TBS(mcs1)][NPRB-1])) { - // this is an eNB issue - // retransmisison but old and new TBS are different !!! - // work around, consider it as a new transmission - LOG_E(PHY, - "Format1A Retransmission but TBS are different: consider it as new transmission !!!, round %d, mcs 1 %d, NPRB %d \n", - pdlsch0_harq->round, - mcs1, - NPRB); - pdlsch0_harq->round = 0; - //return(0); // ?? to cross check - return(0); // ?? to cross check + // this is an eNB issue + // retransmisison but old and new TBS are different !!! + // we have missed DCIs, consider it as a new transmission + LOG_W(PHY, + "dci format1A Retransmission but TBS are different: consider it as new transmission !!!, round %d, mcs 1 %d, NPRB " + "%d \n", + pdlsch0_harq->round, + mcs1, + NPRB); + pdlsch0_harq->round = 0; + return (0); } } - return(1); } @@ -1148,14 +1153,15 @@ int check_dci_format1c_coherency(uint8_t N_RB_DL, if(rballoc > RIV_max) { - // DCI false detection - return(0); + LOG_I(PHY, "bad dci format 1c rballoc rballoc %d RIV_max %u \n", rballoc, RIV_max); // DCI false detection + return (0); } if(NPRB == 0) { - // DCI false detection - return(0); + LOG_I(PHY, "bad dci format 1c NPRB = 0 \n"); + // DCI false detection + return (0); } return(1); @@ -1204,53 +1210,44 @@ int check_dci_format2_2a_coherency(DCI_format_t dci_format, #endif // I- check dci content minimum coherency - if(harq_pid>=8) - { - // LOG_I(PHY,"bad harq pid\n"); + if (harq_pid >= 8) { + LOG_I(PHY, "bad dci foramt2 harq pid %d\n", harq_pid); return(0); } - if( (rnti==si_rnti) || (rnti==p_rnti) || (rnti==ra_rnti) ) - { - // LOG_I(PHY,"bad rnti\n"); - return(0); + if ((rnti == si_rnti) || (rnti == p_rnti) || (rnti == ra_rnti)) { + LOG_I(PHY, "bad dci format 2 rnti %x\n", rnti); + return (0); } - - if( mcs1 > 28) - { - if(pdlsch0_harq->round == 0) - { - // LOG_I(PHY,"bad mcs1\n"); - return(0); - } + if (!pdlsch0_harq) { + LOG_E(PHY, "pointer to pdlsch0_harq is NULL\n"); + return 0; + } + if ((mcs1 > 28) && !pdlsch0_harq->round) { + LOG_I(PHY, "bad mcs1 %d while round is %d\n", mcs1, pdlsch0_harq->round); + return (0); } - if( mcs2 > 28) - { - if(pdlsch1_harq->round == 0) - { - // LOG_I(PHY,"bad mcs2\n"); - return(0); - } + if (!pdlsch1_harq) { + LOG_E(PHY, "pointer to pdlsch0_harq is NULL\n"); + return 0; + } + if ((mcs2 > 28) && !pdlsch1_harq->round) { + LOG_I(PHY, "bad mcs2 %d while round is %d\n", mcs2, pdlsch0_harq->round); + return (0); } - - if((pdlsch0_harq->round == 0) && (rv1 > 0) && (mcs1 != 0)) - { - // DCI false detection - // LOG_I(PHY,"bad rv1\n"); + if ((pdlsch0_harq->round == 0) && (rv1 > 0) && (mcs1 != 0)) { + LOG_I(PHY, "bad mcs2 %d while round is %d and rv1 %d and mcs1 %d\n", mcs2, pdlsch0_harq->round, rv1, mcs1); return(0); } - if((pdlsch1_harq->round == 0) && (rv2 > 0) && (mcs2 != 0)) - { - // DCI false detection - // LOG_I(PHY,"bad rv2\n"); + if ((pdlsch1_harq->round == 0) && (rv2 > 0) && (mcs2 != 0)) { + LOG_I(PHY, "bad mcs2 %d while round is %d and rv2 %d \n", mcs2, pdlsch0_harq->round, rv2); return(0); } - switch (N_RB_DL) { case 6: if (rah == 0) @@ -1307,14 +1304,14 @@ int check_dci_format2_2a_coherency(DCI_format_t dci_format, if( (rballoc > RIV_max) && (rah == 1) ) { // DCI false detection - // LOG_I(PHY,"bad rballoc %d RIV_max %lld\n", rballoc, RIV_max); + LOG_I(PHY, "bad rballoc %d RIV_max %lld\n", rballoc, RIV_max); return(0); } if(NPRB == 0) { // DCI false detection - // LOG_I(PHY,"bad NPRB\n"); + LOG_I(PHY, "dci format 2 bad NPRB %d\n", NPRB); return(0); } @@ -1627,8 +1624,13 @@ void prepare_dl_decoding_format1_1A(DCI_format_t dci_format, { if(mcs1 < 29) { - pdlsch0_harq->TBS = TBStable[get_I_TBS(mcs1)][NPRB4TBS-1]; - pdlsch0_harq->Qm = get_Qm(mcs1); + int tbs = get_I_TBS(mcs1); + if (NPRB4TBS > 110 || tbs >= TBStable_rowCnt) { + LOG_E(PHY, "NPRB4TBS %d out of array\n", NPRB4TBS); + pdlsch0_harq->TBS = 0; + } else + pdlsch0_harq->TBS = TBStable[tbs][NPRB4TBS - 1]; + pdlsch0_harq->Qm = get_Qm(mcs1); } } @@ -2304,11 +2306,8 @@ int generate_ue_dlsch_params_from_dci(int frame, p_rnti,frame,subframe, &dci_info_extarcted, dlsch0_harq); - if(status == 0) - { - printf("bad DCI 1A !!! \n"); - return(-1); - } + if (status == 0) // log of error is done + return (-1); // dci is correct ==> update internal structure and prepare dl decoding #ifdef DEBUG_DCI @@ -2412,12 +2411,8 @@ int generate_ue_dlsch_params_from_dci(int frame, p_rnti,frame,subframe, &dci_info_extarcted, dlsch0_harq); - if(status == 0) - { - printf("bad DCI 1 !!! \n"); - return(-1); - } - + if (status == 0) // log of error is done + return (-1); // dci is correct ==> update internal structure and prepare dl decoding #ifdef DEBUG_DCI @@ -3528,8 +3523,14 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu, if (rballoc > RIV_max) { - LOG_E(PHY,"frame %d, subframe %d, rnti %x, format %d: FATAL ERROR: generate_ue_ulsch_params_from_dci, rb_alloc[%d] > RIV_max[%d]\n", - proc->frame_rx, subframe, rnti, dci_format,rballoc,RIV_max); + LOG_W(PHY, + "frame %d, subframe %d, rnti %x, format %d, generate_ue_ulsch_params_from_dci impossible rb_alloc[%d] > RIV_max[%d]\n", + proc->frame_rx, + subframe, + rnti, + dci_format, + rballoc, + RIV_max); LOG_E(PHY,"Wrong DCI0 detection, do not transmit PUSCH for HARQID: %d\n",harq_pid); ulsch->harq_processes[harq_pid]->subframe_scheduling_flag = 0; return(-1); diff --git a/openair1/PHY/LTE_UE_TRANSPORT/dci_ue.c b/openair1/PHY/LTE_UE_TRANSPORT/dci_ue.c index 5dba6257df..9bc8cddbe2 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/dci_ue.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/dci_ue.c @@ -1593,19 +1593,19 @@ void dci_decoding_procedure0(LTE_UE_PDCCH **pdcch_vars, switch (L2) { case 1: - CCEmap_mask = (1<<(CCEind&0x1f)); + CCEmap_mask = (1U << (CCEind & 0x1f)); break; case 2: - CCEmap_mask = (3<<(CCEind&0x1f)); + CCEmap_mask = (3U << (CCEind & 0x1f)); break; case 4: - CCEmap_mask = (0xf<<(CCEind&0x1f)); + CCEmap_mask = (0xfU << (CCEind & 0x1f)); break; case 8: - CCEmap_mask = (0xff<<(CCEind&0x1f)); + CCEmap_mask = (0xffU << (CCEind & 0x1f)); break; default: From 311a857cb35dc7b5469bf4eca704bdf584aad7c4 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Mon, 11 Aug 2025 17:18:52 +0200 Subject: [PATCH 762/964] move a bad global var in a better place --- openair1/PHY/LTE_UE_TRANSPORT/dci_ue.c | 65 +++++++------------------- 1 file changed, 18 insertions(+), 47 deletions(-) diff --git a/openair1/PHY/LTE_UE_TRANSPORT/dci_ue.c b/openair1/PHY/LTE_UE_TRANSPORT/dci_ue.c index 9bc8cddbe2..ecd565194f 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/dci_ue.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/dci_ue.c @@ -1381,12 +1381,6 @@ void dci_decoding(uint8_t DCI_LENGTH, //debug_printf("Done DCI Viterbi \n"); } - -static uint8_t dci_decoded_output[RX_NB_TH][(MAX_DCI_SIZE_BITS+64)/8]; - - - - int get_nCCE_offset_l1(int *CCE_table, const unsigned char L, const int nCCE, @@ -1625,25 +1619,14 @@ void dci_decoding_procedure0(LTE_UE_PDCCH **pdcch_vars, else LOG_D(PHY,"[DCI search nPdcch %d - ue spec %x] Attempting candidate %d Aggregation Level %d DCI length %d at CCE %d/%d (CCEmap %x,CCEmap_cand %x) format %d\n", pdcch_vars[eNB_id]->num_pdcch_symbols,pdcch_vars[eNB_id]->crnti,m,L2,sizeof_bits,CCEind,nCCE,*CCEmap,CCEmap_mask,format_c); - - dci_decoding(sizeof_bits, - L, - &pdcch_vars[eNB_id]->e_rx[CCEind*72], - &dci_decoded_output[current_thread_id][0]); - /* - for (i=0;i<3+(sizeof_bits>>3);i++) - printf("dci_decoded_output[%d][%d] => %x\n",current_thread_id,i,dci_decoded_output[current_thread_id][i]); - */ - - crc = (crc16(&dci_decoded_output[current_thread_id][0],sizeof_bits)>>16) ^ extract_crc(&dci_decoded_output[current_thread_id][0],sizeof_bits); + uint8_t dci_decoded_output[(MAX_DCI_SIZE_BITS + 64) / 8] = {}; + dci_decoding(sizeof_bits, L, &pdcch_vars[eNB_id]->e_rx[CCEind * 72], dci_decoded_output); + crc = (crc16(dci_decoded_output, sizeof_bits) >> 16) ^ extract_crc(dci_decoded_output, sizeof_bits); #ifdef DEBUG_DCI_DECODING printf("crc =>%x\n",crc); #endif - - if (((L>1) && ((crc == si_rnti)|| - (crc == p_rnti)|| - (crc == ra_rnti)/*||(crc == 0xfff9)*/))|| - (crc == pdcch_vars[eNB_id]->crnti)) { + uint8_t *ptr = dci_decoded_output; + if (( (L>1) && (crc == si_rnti||crc == p_rnti||crc == ra_rnti))|| (crc == pdcch_vars[eNB_id]->crnti)) { dci_alloc[*dci_cnt].dci_length = sizeof_bits; dci_alloc[*dci_cnt].rnti = crc; dci_alloc[*dci_cnt].L = L; @@ -1651,30 +1634,19 @@ void dci_decoding_procedure0(LTE_UE_PDCCH **pdcch_vars, //printf("DCI FOUND !!! crc =>%x, sizeof_bits %d, sizeof_bytes %d \n",crc, sizeof_bits, sizeof_bytes); if (sizeof_bytes<=4) { - dci_alloc[*dci_cnt].dci_pdu[3] = dci_decoded_output[current_thread_id][0]; - dci_alloc[*dci_cnt].dci_pdu[2] = dci_decoded_output[current_thread_id][1]; - dci_alloc[*dci_cnt].dci_pdu[1] = dci_decoded_output[current_thread_id][2]; - dci_alloc[*dci_cnt].dci_pdu[0] = dci_decoded_output[current_thread_id][3]; -#ifdef DEBUG_DCI_DECODING - printf("DCI => %x,%x,%x,%x\n",dci_decoded_output[current_thread_id][0], - dci_decoded_output[current_thread_id][1], - dci_decoded_output[current_thread_id][2], - dci_decoded_output[current_thread_id][3]); -#endif + dci_alloc[*dci_cnt].dci_pdu[3] = *ptr++; + dci_alloc[*dci_cnt].dci_pdu[2] = *ptr++; + dci_alloc[*dci_cnt].dci_pdu[1] = *ptr++; + dci_alloc[*dci_cnt].dci_pdu[0] = *ptr++; } else { - dci_alloc[*dci_cnt].dci_pdu[7] = dci_decoded_output[current_thread_id][0]; - dci_alloc[*dci_cnt].dci_pdu[6] = dci_decoded_output[current_thread_id][1]; - dci_alloc[*dci_cnt].dci_pdu[5] = dci_decoded_output[current_thread_id][2]; - dci_alloc[*dci_cnt].dci_pdu[4] = dci_decoded_output[current_thread_id][3]; - dci_alloc[*dci_cnt].dci_pdu[3] = dci_decoded_output[current_thread_id][4]; - dci_alloc[*dci_cnt].dci_pdu[2] = dci_decoded_output[current_thread_id][5]; - dci_alloc[*dci_cnt].dci_pdu[1] = dci_decoded_output[current_thread_id][6]; - dci_alloc[*dci_cnt].dci_pdu[0] = dci_decoded_output[current_thread_id][7]; -#ifdef DEBUG_DCI_DECODING - printf("DCI => %x,%x,%x,%x,%x,%x,%x,%x\n", - dci_decoded_output[current_thread_id][0],dci_decoded_output[current_thread_id][1],dci_decoded_output[current_thread_id][2],dci_decoded_output[current_thread_id][3], - dci_decoded_output[current_thread_id][4],dci_decoded_output[current_thread_id][5],dci_decoded_output[current_thread_id][6],dci_decoded_output[current_thread_id][7]); -#endif + dci_alloc[*dci_cnt].dci_pdu[7] = *ptr++; + dci_alloc[*dci_cnt].dci_pdu[6] = *ptr++; + dci_alloc[*dci_cnt].dci_pdu[5] = *ptr++; + dci_alloc[*dci_cnt].dci_pdu[4] = *ptr++; + dci_alloc[*dci_cnt].dci_pdu[3] = *ptr++; + dci_alloc[*dci_cnt].dci_pdu[2] = *ptr++; + dci_alloc[*dci_cnt].dci_pdu[1] = *ptr++; + dci_alloc[*dci_cnt].dci_pdu[0] = *ptr++; } if (crc==si_rnti /*|| crc==0xfff9*/) { @@ -1689,8 +1661,7 @@ void dci_decoding_procedure0(LTE_UE_PDCCH **pdcch_vars, pdcch_vars[eNB_id]->nCCE[subframe]=CCEind; *dci_cnt = *dci_cnt+1; } else if (crc==pdcch_vars[eNB_id]->crnti) { - - if ((mode&UL_DCI)&&(format_c == format0)&&((dci_decoded_output[current_thread_id][0]&0x80)==0)) {// check if pdu is format 0 or 1A + if ((mode & UL_DCI) && (format_c == format0) && ((dci_decoded_output[0] & 0x80) == 0)) { // check if pdu is format 0 or 1A if (*format0_found == 0) { dci_alloc[*dci_cnt].format = format0; *format0_found = 1; From 06914f3dded5771a7dc06458079df6024132663e Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Mon, 11 Aug 2025 17:37:56 +0200 Subject: [PATCH 763/964] improve dci rejection test: system DCIs are tackled only if we expect system DCIs --- openair1/PHY/LTE_UE_TRANSPORT/dci_ue.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/openair1/PHY/LTE_UE_TRANSPORT/dci_ue.c b/openair1/PHY/LTE_UE_TRANSPORT/dci_ue.c index ecd565194f..24c32729aa 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/dci_ue.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/dci_ue.c @@ -1626,7 +1626,7 @@ void dci_decoding_procedure0(LTE_UE_PDCCH **pdcch_vars, printf("crc =>%x\n",crc); #endif uint8_t *ptr = dci_decoded_output; - if (( (L>1) && (crc == si_rnti||crc == p_rnti||crc == ra_rnti))|| (crc == pdcch_vars[eNB_id]->crnti)) { + if ((do_common && (L > 1) && (crc == si_rnti || crc == p_rnti || crc == ra_rnti)) || (crc == pdcch_vars[eNB_id]->crnti)) { dci_alloc[*dci_cnt].dci_length = sizeof_bits; dci_alloc[*dci_cnt].rnti = crc; dci_alloc[*dci_cnt].L = L; @@ -1743,8 +1743,7 @@ uint16_t dci_CRNTI_decoding_procedure(PHY_VARS_UE *ue, int16_t eNB_id, uint8_t subframe) { - - uint8_t dci_cnt=0,old_dci_cnt=0; + uint8_t dci_cnt = 0; uint32_t CCEmap0=0,CCEmap1=0,CCEmap2=0; LTE_UE_PDCCH **pdcch_vars = ue->pdcch_vars[ue->current_thread_id[subframe]]; LTE_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; @@ -1850,8 +1849,7 @@ uint16_t dci_CRNTI_decoding_procedure(PHY_VARS_UE *ue, &CCEmap1, &CCEmap2); - if ((CCEmap0==0xffff)|| - ((format0_found==1)&&(format_c_found==1))) + if ((CCEmap0 == 0xffff) || ((format0_found == 1) && (format_c_found == 1))) return(dci_cnt); if (DCIFormat == format1) @@ -1863,7 +1861,7 @@ uint16_t dci_CRNTI_decoding_procedure(PHY_VARS_UE *ue, //printf("[DCI search] Format 1/1A aggregation 1\n"); - old_dci_cnt=dci_cnt; + int old_dci_cnt = dci_cnt; dci_decoding_procedure0(pdcch_vars,0,mode,subframe, dci_alloc, eNB_id, @@ -1887,15 +1885,12 @@ uint16_t dci_CRNTI_decoding_procedure(PHY_VARS_UE *ue, &CCEmap1, &CCEmap2); - if ((CCEmap0==0xffff) || - (format_c_found==1)) + if ((CCEmap0 == 0xffff) || (format_c_found == 1)) return(dci_cnt); if (dci_cnt>old_dci_cnt) return(dci_cnt); - //printf("Crnti 1 decoding frame param agregation %d DCI %d \n",agregationLevel,DCIFormat); - } else if (DCIFormat == format1A) { From 7083e08175c8ee78ffbf5d88fe4642aa7759d525 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Mon, 22 Sep 2025 22:30:09 +0200 Subject: [PATCH 764/964] Fix variable shadowing in E1 bearer context setup - Changed inner loop variable from 'i' to 'j' in rrc_gNB_process_e1_bearer_context_setup_resp - Eliminates variable shadowing between outer PDU session loop and inner DRB loop - Improves code readability and prevents potential bugs --- openair2/RRC/NR/rrc_gNB.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 797aa19d88..2ade816666 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -2577,8 +2577,8 @@ void rrc_gNB_process_e1_bearer_context_setup_resp(e1ap_bearer_setup_resp_t *resp rrc_pdu->param.n3_outgoing = f1u_gtp_update(e1_pdu->tl_info.teId, e1_pdu->tl_info.tlAddress); // save the tunnel address for the DRBs - for (int i = 0; i < e1_pdu->numDRBSetup; i++) { - DRB_nGRAN_setup_t *drb_config = &e1_pdu->DRBnGRanList[i]; + for (int j = 0; j < e1_pdu->numDRBSetup; j++) { + DRB_nGRAN_setup_t *drb_config = &e1_pdu->DRBnGRanList[j]; // numUpParam only relevant in F1, but not monolithic AssertFatal(drb_config->numUpParam <= 1, "can only up to one UP param\n"); drb_t *drb = get_drb(UE, drb_config->id); From 966bab9cca9bf9a9578ab065d27df6d90fecc423 Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 23 Sep 2025 08:39:41 +0200 Subject: [PATCH 765/964] do not assert for mismatched TBS in phy-test mode --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index 552b1fa041..44c9072a15 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -1250,10 +1250,16 @@ void nr_schedule_ue_spec(module_id_t module_id, current_harq_pid, harq->round, harq->ndi); - AssertFatal(harq->sched_pdsch.tb_size == TBS, - "UE %04x mismatch between scheduled TBS and buffered TB for HARQ PID %d\n", - UE->rnti, - current_harq_pid); + if (!get_softmodem_params()->phy_test) + AssertFatal(harq->sched_pdsch.tb_size == TBS, + "UE %04x mismatch between scheduled TBS and buffered TB for HARQ PID %d\n", + UE->rnti, + current_harq_pid); + else if (harq->sched_pdsch.tb_size != TBS) + LOG_E(NR_MAC, + "Mismatch between scheduled TBS and buffered TB for HARQ PID %d. No RTX control in phy-test mode. " + "Possible causes: presence of CSI-RS or DLSCH scheduled in the mixed slot.\n", + current_harq_pid); T(T_GNB_MAC_RETRANSMISSION_DL_PDU_WITH_DATA, T_INT(module_id), T_INT(CC_id), T_INT(rnti), T_INT(frame), T_INT(slot), T_INT(current_harq_pid), T_INT(harq->round), T_BUFFER(harq->transportBlock.buf, TBS)); UE->mac_stats.dl.total_rbs_retx += sched_pdsch->rbSize; From ccad50daca250c7c4fb66fa62ca0db100bfd82e9 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Tue, 23 Sep 2025 11:17:44 +0200 Subject: [PATCH 766/964] NR UE: do not consider suspended logical channels in nr_update_bsr() While a logical channel is suspended, we should not consider it in the BSR, as we cannot transmit any data from it. --- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 8253608335..523a858b8f 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -1331,6 +1331,8 @@ static void nr_update_bsr(NR_UE_MAC_INST_t *mac, uint32_t *LCG_bytes) bool bsr_regular_triggered = mac->scheduling_info.BSR_reporting_active & NR_BSR_TRIGGER_REGULAR; 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); int lcgid = lc_sched_info->LCGID; From 7e1eabe70070753cb396d5baf196b0efdd72c289 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 24 Jul 2025 14:13:15 +0200 Subject: [PATCH 767/964] Switch to new (internal) registry --- ci-scripts/Jenkinsfile-GitLab-Container | 6 ++++-- ci-scripts/Jenkinsfile-push-registry | 17 ++++++++++------- ci-scripts/cls_containerize.py | 5 +++-- ci-scripts/tests/pull-clean-int-registry.py | 2 +- 4 files changed, 18 insertions(+), 12 deletions(-) diff --git a/ci-scripts/Jenkinsfile-GitLab-Container b/ci-scripts/Jenkinsfile-GitLab-Container index 4bdb20d371..c3f3037c78 100644 --- a/ci-scripts/Jenkinsfile-GitLab-Container +++ b/ci-scripts/Jenkinsfile-GitLab-Container @@ -35,6 +35,8 @@ def gitCommitAuthorEmailAddr // list of failing stages def failingStages = "" +def OAI_Registry = "gracehopper3-oai.sboai.cs.eurecom.fr" + pipeline { agent { label nodeExecutor @@ -834,11 +836,11 @@ def triggerCN5GSlaveJob (jobName, gitlabStatusName) { shortenShaOne = sh returnStdout: true, script: 'git log -1 --pretty=format:"%h" --abbrev=8 ' + env.gitlabMergeRequestLastCommit shortenShaOne = shortenShaOne.trim() branchName = env.gitlabSourceBranch.replaceAll("/", "-").trim() - fullRanTag = 'porcepix.sboai.cs.eurecom.fr/oai-gnb:' + env.gitlabSourceBranch + '-' + shortenShaOne + fullRanTag = OAI_Registry + '/oai-gnb:' + env.gitlabSourceBranch + '-' + shortenShaOne } else { shortenShaOne = sh returnStdout: true, script: 'git log -1 --pretty=format:"%h" --abbrev=8 ' + env.GIT_COMMIT shortenShaOne = shortenShaOne.trim() - fullRanTag = 'porcepix.sboai.cs.eurecom.fr/oai-gnb:develop-' + shortenShaOne + fullRanTag = OAI_Registry + '/oai-gnb:develop-' + shortenShaOne } // Workaround for the "cancelled" GitLab pipeline notification // The slave job is triggered with the propagate false so the following commands are executed diff --git a/ci-scripts/Jenkinsfile-push-registry b/ci-scripts/Jenkinsfile-push-registry index d3bd5e6e64..8f54d352b1 100644 --- a/ci-scripts/Jenkinsfile-push-registry +++ b/ci-scripts/Jenkinsfile-push-registry @@ -31,6 +31,9 @@ if (params.LockResources != null && params.LockResources.trim().length() > 0) // Docker Hub account to push to def DH_Account = "oaisoftwarealliance" +// internal registry to use +def OAI_Registry = "gracehopper3-oai.sboai.cs.eurecom.fr" + pipeline { agent { label nodeExecutor @@ -79,14 +82,14 @@ pipeline { def listOfImages = ["oai-enb", "oai-gnb", "oai-lte-ue", "oai-nr-ue", "oai-nr-cuup", "oai-gnb-fhi72"] // Logging in on both registries sh "docker login -u ${DH_Username} -p ${DH_Password} > /dev/null 2>&1" - sh "docker login -u oaicicd -p oaicicd porcepix.sboai.cs.eurecom.fr > /dev/null 2>&1" + sh "docker login -u oaicicd -p oaicicd ${OAI_Registry} > /dev/null 2>&1" listOfImages.eachWithIndex { item, iindex -> - sh "docker pull --quiet porcepix.sboai.cs.eurecom.fr/${item}:develop-${WEEK_SHA}" - sh "docker image tag porcepix.sboai.cs.eurecom.fr/${item}:develop-${WEEK_SHA} ${DH_Account}/${item}:develop" - sh "docker image tag porcepix.sboai.cs.eurecom.fr/${item}:develop-${WEEK_SHA} ${DH_Account}/${item}:${WEEK_TAG}" + sh "docker pull --quiet ${OAI_Registry}/${item}:develop-${WEEK_SHA}" + sh "docker image tag ${OAI_Registry}/${item}:develop-${WEEK_SHA} ${DH_Account}/${item}:develop" + sh "docker image tag ${OAI_Registry}/${item}:develop-${WEEK_SHA} ${DH_Account}/${item}:${WEEK_TAG}" sh "docker push --quiet ${DH_Account}/${item}:${WEEK_TAG}" sh "docker push --quiet ${DH_Account}/${item}:develop" - sh "docker rmi ${DH_Account}/${item}:${WEEK_TAG} ${DH_Account}/${item}:develop porcepix.sboai.cs.eurecom.fr/${item}:develop-${WEEK_SHA}" + sh "docker rmi ${DH_Account}/${item}:${WEEK_TAG} ${DH_Account}/${item}:develop ${OAI_Registry}/${item}:develop-${WEEK_SHA}" } // Proxy is not following the same pattern. sh "docker image tag proxy:develop ${DH_Account}/proxy:develop" @@ -95,7 +98,7 @@ pipeline { sh "docker push --quiet ${DH_Account}/proxy:${WEEK_TAG}" sh "docker rmi ${DH_Account}/proxy:develop ${DH_Account}/proxy:${WEEK_TAG}" // Logging out on both registries - sh "docker logout porcepix.sboai.cs.eurecom.fr > /dev/null 2>&1" + sh "docker logout ${OAI_Registry} > /dev/null 2>&1" sh "docker logout > /dev/null 2>&1" } } @@ -105,7 +108,7 @@ pipeline { post { always { script { - sh "docker logout porcepix.sboai.cs.eurecom.fr > /dev/null 2>&1" + sh "docker logout ${OAI_Registry} > /dev/null 2>&1" sh "docker logout > /dev/null 2>&1" echo "End of Registry Push" } diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index 965ff6a6db..3fe2729c77 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -53,6 +53,7 @@ from cls_ci_helper import archiveArtifact # (e.g., cls_cluster.py) #----------------------------------------------------------- IMAGES = ['oai-enb', 'oai-lte-ru', 'oai-lte-ue', 'oai-gnb', 'oai-nr-cuup', 'oai-gnb-aw2s', 'oai-nr-ue', 'oai-enb-asan', 'oai-gnb-asan', 'oai-lte-ue-asan', 'oai-nr-ue-asan', 'oai-nr-cuup-asan', 'oai-gnb-aerial', 'oai-gnb-fhi72'] +DEFAULT_REGISTRY = "gracehopper3-oai.sboai.cs.eurecom.fr" def CreateWorkspace(host, sourcePath, ranRepository, ranCommitID, ranTargetBranch, ranAllowMerge): if ranCommitID == '': @@ -596,7 +597,7 @@ class Containerize(): lSourcePath = self.eNBSourceCodePath logging.debug('Pushing images to server: ' + node) ssh = cls_cmd.getConnection(node) - imagePrefix = 'porcepix.sboai.cs.eurecom.fr' + imagePrefix = DEFAULT_REGISTRY ret = ssh.run(f'docker login -u oaicicd -p oaicicd {imagePrefix}') if ret.returncode != 0: msg = 'Could not log into local registry' @@ -667,7 +668,7 @@ class Containerize(): msg = "Pulled Images:\n" + '\n'.join(pulled_images) return True, msg - def Pull_Image_from_Registry(self, HTML, node, images, tag=None, tag_prefix="", registry="porcepix.sboai.cs.eurecom.fr", username="oaicicd", password="oaicicd"): + def Pull_Image_from_Registry(self, HTML, node, images, tag=None, tag_prefix="", registry=DEFAULT_REGISTRY, username="oaicicd", password="oaicicd"): logging.debug(f'\u001B[1m Pulling image(s) on server: {node}\u001B[0m') if not tag: tag = CreateTag(self.ranCommitID, self.ranBranch, self.ranAllowMerge) diff --git a/ci-scripts/tests/pull-clean-int-registry.py b/ci-scripts/tests/pull-clean-int-registry.py index f17c1c7a1d..3bf4b9e67e 100644 --- a/ci-scripts/tests/pull-clean-int-registry.py +++ b/ci-scripts/tests/pull-clean-int-registry.py @@ -26,7 +26,7 @@ class TestDeploymentMethods(unittest.TestCase): # the pull function has the authentication at the internal cluster hardcoded # this is a refactoring opportunity: we should do it in a separate step # and allow to have pull work with any registry - registry = "porcepix.sboai.cs.eurecom.fr" + registry = cls_containerize.DEFAULT_REGISTRY with cls_cmd.getConnection("localhost") as cmd: ret = cmd.run(f"ping -c1 -w1 {registry}") if ret.returncode != 0: # could not ping once -> skip test From 69f0bb2b966e4e5c8571dec6fd804b5ac71e2a46 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Tue, 23 Sep 2025 17:13:20 +0200 Subject: [PATCH 768/964] Fix PDU session counter overflow issues: max number of PDU Sessions is 256 - Upgrade PDU session counters from uint8_t to uint16_t in ngap_messages_types.h Co-authored-by: Assistant --- openair2/COMMON/ngap_messages_types.h | 42 +++++++++----------- openair2/RRC/NR/rrc_gNB_NGAP.c | 4 +- openair3/NGAP/ngap_gNB_mobility_management.c | 2 +- 3 files changed, 22 insertions(+), 26 deletions(-) diff --git a/openair2/COMMON/ngap_messages_types.h b/openair2/COMMON/ngap_messages_types.h index ef25f6997d..c4bafcee85 100644 --- a/openair2/COMMON/ngap_messages_types.h +++ b/openair2/COMMON/ngap_messages_types.h @@ -562,7 +562,7 @@ typedef struct { // Target ID target_ran_node_id_t target_gnb_id; // PDU Session Resource List - uint8_t nb_of_pdusessions; + uint16_t nb_of_pdusessions; pdusession_resource_t pdusessions[NGAP_MAX_PDU_SESSION]; // Source to Target Transparent Container source_to_target_transparent_container_t *source2target; @@ -610,7 +610,7 @@ typedef struct { // Security Context ngap_security_context_t security_context; // PDU Session Resource Setup List - uint8_t nb_of_pdusessions; + uint16_t nb_of_pdusessions; ho_request_pdusession_t pduSessionResourceSetupList[NGAP_MAX_PDU_SESSION]; // Allowed NSSAI uint8_t nb_allowed_nssais; @@ -650,7 +650,7 @@ typedef struct { uint64_t amf_ue_ngap_id; // PDU Session Resource Admitted List pdu_session_resource_admitted_t pdusessions[NGAP_MAX_PDU_SESSION]; - uint8_t nb_of_pdusessions; + uint16_t nb_of_pdusessions; // Target to Source Transparent Container byte_array_t target2source; } ngap_handover_request_ack_t; @@ -680,7 +680,7 @@ typedef struct { // Handover Type ho_type_t handoverType; // PDU Session Resource Handover List - uint8_t nb_of_pdusessions; + uint16_t nb_of_pdusessions; pdusession_resource_handover_t pdu_sessions[NGAP_MAX_PDU_SESSION]; // Target to Source Transparent Container byte_array_t handoverCommand; @@ -730,12 +730,12 @@ typedef struct ngap_initial_context_setup_resp_s { uint32_t gNB_ue_ngap_id; /* Number of pdusession setup-ed in the list */ - uint8_t nb_of_pdusessions; + uint16_t nb_of_pdusessions; /* list of pdusession setup-ed by RRC layers */ pdusession_setup_t pdusessions[NGAP_MAX_PDU_SESSION]; /* Number of pdusession failed to be setup in list */ - uint8_t nb_of_pdusessions_failed; + uint16_t nb_of_pdusessions_failed; /* list of pdusessions that failed to be setup */ pdusession_failed_t pdusessions_failed[NGAP_MAX_PDU_SESSION]; } ngap_initial_context_setup_resp_t; @@ -823,7 +823,7 @@ typedef struct ngap_initial_context_setup_req_s { uint8_t security_key[SECURITY_KEY_LENGTH]; /* Number of pdusession to be setup in the list */ - uint8_t nb_of_pdusessions; + uint16_t nb_of_pdusessions; // PDU Session Resource Setup Request List pdusession_resource_item_t pdusession[NGAP_MAX_PDU_SESSION]; @@ -871,7 +871,7 @@ typedef struct ngap_pdusession_setup_req_s { nssai_t allowed_nssai[8]; /* Number of pdusession to be setup in the list */ - uint8_t nb_pdusessions_tosetup; + uint16_t nb_pdusessions_tosetup; // PDU Session Resource Setup Request List pdusession_resource_item_t pdusession[NGAP_MAX_PDU_SESSION]; @@ -885,12 +885,12 @@ typedef struct ngap_pdusession_setup_req_s { typedef struct ngap_pdusession_setup_resp_s { uint32_t gNB_ue_ngap_id; /* Number of pdusession setup-ed in the list */ - uint8_t nb_of_pdusessions; + uint16_t nb_of_pdusessions; /* list of pdusession setup-ed by RRC layers */ pdusession_setup_t pdusessions[NGAP_MAX_PDU_SESSION]; /* Number of pdusession failed to be setup in list */ - uint8_t nb_of_pdusessions_failed; + uint16_t nb_of_pdusessions_failed; /* list of pdusessions that failed to be setup */ pdusession_failed_t pdusessions_failed[NGAP_MAX_PDU_SESSION]; } ngap_pdusession_setup_resp_t; @@ -914,7 +914,7 @@ typedef struct pdusession_release_s { typedef struct ngap_ue_release_req_s { uint32_t gNB_ue_ngap_id; /* Number of pdusession resource in the list */ - uint8_t nb_of_pdusessions; + uint16_t nb_of_pdusessions; /* list of pdusession resource by RRC layers */ pdusession_release_t pdusessions[NGAP_MAX_PDU_SESSION]; ngap_cause_t cause; @@ -928,7 +928,7 @@ typedef struct ngap_pdusession_modify_req_s { uint32_t gNB_ue_ngap_id; /* Number of pdusession to be modify in the list */ - uint8_t nb_pdusessions_tomodify; + uint16_t nb_pdusessions_tomodify; // PDU Session Resource Modify Request List pdusession_resource_item_t pdusession[NGAP_MAX_PDU_SESSION]; @@ -938,12 +938,12 @@ typedef struct ngap_pdusession_modify_resp_s { uint32_t gNB_ue_ngap_id; /* Number of pdusession modify-ed in the list */ - uint8_t nb_of_pdusessions; + uint16_t nb_of_pdusessions; /* list of pdusession modify-ed by RRC layers */ pdusession_modify_t pdusessions[NGAP_MAX_PDU_SESSION]; /* Number of pdusession failed to be modify in list */ - uint8_t nb_of_pdusessions_failed; + uint16_t nb_of_pdusessions_failed; /* list of pdusessions that failed to be modify */ pdusession_failed_t pdusessions_failed[NGAP_MAX_PDU_SESSION]; } ngap_pdusession_modify_resp_t; @@ -959,7 +959,7 @@ typedef struct ngap_pdusession_release_command_s { byte_array_t nas_pdu; /* Number of pdusession to be released in the list */ - uint8_t nb_pdusessions_torelease; + uint16_t nb_pdusessions_torelease; /* PDUSession release command */ pdusession_release_t pdusession_release_params[NGAP_MAX_PDU_SESSION]; @@ -969,14 +969,10 @@ typedef struct ngap_pdusession_release_command_s { typedef struct ngap_pdusession_release_resp_s { /* AMF UE id */ uint64_t amf_ue_ngap_id; - - /* gNB ue ngap id as initialized by NGAP layer */ - uint32_t gNB_ue_ngap_id; - - /* Number of pdusession released in the list */ - uint8_t nb_of_pdusessions_released; - - /* list of pdusessions released */ + // RAN UE NGAP ID + uint32_t gNB_ue_ngap_id; + // PDU Session Resource Released List + uint16_t nb_of_pdusessions_released; pdusession_release_t pdusession_release[NGAP_MAX_PDU_SESSION]; /* Number of pdusession failed to be released in list */ diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index be7dce5ca1..bdaa3e170e 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -944,8 +944,8 @@ int rrc_gNB_process_NGAP_PDUSESSION_MODIFY_REQ(MessageDef *msg_p, instance_t ins int rrc_gNB_send_NGAP_PDUSESSION_MODIFY_RESP(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, uint8_t xid) { MessageDef *msg_p = NULL; - uint8_t pdu_sessions_failed = 0; - uint8_t pdu_sessions_done = 0; + uint16_t pdu_sessions_failed = 0; + uint16_t pdu_sessions_done = 0; msg_p = itti_alloc_new_message (TASK_RRC_GNB, rrc->module_id, NGAP_PDUSESSION_MODIFY_RESP); if (msg_p == NULL) { diff --git a/openair3/NGAP/ngap_gNB_mobility_management.c b/openair3/NGAP/ngap_gNB_mobility_management.c index 3d281be7c9..bfea97c8ff 100644 --- a/openair3/NGAP/ngap_gNB_mobility_management.c +++ b/openair3/NGAP/ngap_gNB_mobility_management.c @@ -123,7 +123,7 @@ NGAP_NGAP_PDU_t *encode_ng_handover_required(const ngap_handover_required_t *msg // PDU Session Resource Information List (O) asn1cCalloc(source2target->pDUSessionResourceInformationList, pduSessionList); - for (uint8_t i = 0; i < msg->nb_of_pdusessions; ++i) { + for (uint16_t i = 0; i < msg->nb_of_pdusessions; ++i) { const pdusession_resource_t *pduSession = &msg->pdusessions[i]; NGAP_DEBUG("Handover Required: preparing PDU Session Resource Information List for PDU Session ID %d\n", pduSession->pdusession_id); From 1ee2298a88d58a69d910005e1fbe960386d10306 Mon Sep 17 00:00:00 2001 From: francescomani Date: Wed, 24 Sep 2025 10:15:17 +0200 Subject: [PATCH 769/964] remove unnecessary declaration of nr_rrc_manage_rlc_bearers --- openair2/RRC/NR_UE/rrc_UE.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index c167982859..913b281c1d 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -134,9 +134,6 @@ static const char nr_nas_attach_req_imsi_dummy_NSA_case[] = { 0x11, }; -static void nr_rrc_manage_rlc_bearers(NR_UE_RRC_INST_t *rrc, - const NR_CellGroupConfig_t *cellGroupConfig); - static void nr_rrc_ue_process_RadioBearerConfig(NR_UE_RRC_INST_t *ue_rrc, NR_RadioBearerConfig_t *const radioBearerConfig); static void nr_rrc_ue_generate_rrcReestablishmentComplete(const NR_UE_RRC_INST_t *rrc, const NR_RRCReestablishment_t *rrcReestablishment); @@ -1229,8 +1226,7 @@ static void nr_rrc_signal_maxrtxindication(int ue_id) itti_send_msg_to_task(TASK_RRC_NRUE, ue_id, msg); } -static void nr_rrc_manage_rlc_bearers(NR_UE_RRC_INST_t *rrc, - const NR_CellGroupConfig_t *cellGroupConfig) +static void nr_rrc_manage_rlc_bearers(NR_UE_RRC_INST_t *rrc, const NR_CellGroupConfig_t *cellGroupConfig) { if (cellGroupConfig->rlc_BearerToReleaseList != NULL) { for (int i = 0; i < cellGroupConfig->rlc_BearerToReleaseList->list.count; i++) { From 719ae673a367555ea1e8b512cd74381df6988a85 Mon Sep 17 00:00:00 2001 From: francescomani Date: Wed, 24 Sep 2025 10:18:34 +0200 Subject: [PATCH 770/964] move nr_rrc_ue_process_RadioBearerConfig before its usage --- openair2/RRC/NR_UE/rrc_UE.c | 244 ++++++++++++++++++------------------ 1 file changed, 120 insertions(+), 124 deletions(-) diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 913b281c1d..56657b41b3 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -134,8 +134,6 @@ static const char nr_nas_attach_req_imsi_dummy_NSA_case[] = { 0x11, }; -static void nr_rrc_ue_process_RadioBearerConfig(NR_UE_RRC_INST_t *ue_rrc, - NR_RadioBearerConfig_t *const radioBearerConfig); static void nr_rrc_ue_generate_rrcReestablishmentComplete(const NR_UE_RRC_INST_t *rrc, const NR_RRCReestablishment_t *rrcReestablishment); static void process_lte_nsa_msg(NR_UE_RRC_INST_t *rrc, nsa_msg_t *msg, int msg_len); static void nr_rrc_ue_process_ueCapabilityEnquiry(NR_UE_RRC_INST_t *rrc, NR_UECapabilityEnquiry_t *UECapabilityEnquiry); @@ -611,6 +609,125 @@ static void nr_rrc_process_dedicatedNAS_MessageList(NR_UE_RRC_INST_t *rrc, NR_RR } } +/** + * @brief add, modify and release SRBs and/or DRBs + * @ref 3GPP TS 38.331 + */ +static void nr_rrc_ue_process_RadioBearerConfig(NR_UE_RRC_INST_t *ue_rrc, NR_RadioBearerConfig_t *const radioBearerConfig) +{ + if (LOG_DEBUGFLAG(DEBUG_ASN1)) + xer_fprint(stdout, &asn_DEF_NR_RadioBearerConfig, (const void *)radioBearerConfig); + + if (radioBearerConfig->srb3_ToRelease) { + nr_pdcp_release_srb(ue_rrc->ue_id, 3); + ue_rrc->Srb[3] = RB_NOT_PRESENT; + } + + nr_pdcp_entity_security_keys_and_algos_t security_rrc_parameters = {0}; + nr_pdcp_entity_security_keys_and_algos_t security_up_parameters = {0}; + + if (ue_rrc->as_security_activated) { + if (radioBearerConfig->securityConfig != NULL) { + // When the field is not included, continue to use the currently configured keyToUse + if (radioBearerConfig->securityConfig->keyToUse) { + AssertFatal(*radioBearerConfig->securityConfig->keyToUse == NR_SecurityConfig__keyToUse_master, + "Secondary key usage seems not to be implemented\n"); + ue_rrc->keyToUse = *radioBearerConfig->securityConfig->keyToUse; + } + // When the field is not included, continue to use the currently configured security algorithm + if (radioBearerConfig->securityConfig->securityAlgorithmConfig) { + ue_rrc->cipheringAlgorithm = radioBearerConfig->securityConfig->securityAlgorithmConfig->cipheringAlgorithm; + ue_rrc->integrityProtAlgorithm = *radioBearerConfig->securityConfig->securityAlgorithmConfig->integrityProtAlgorithm; + } + } + security_rrc_parameters = get_security_rrc_parameters(ue_rrc, true); + security_up_parameters = get_security_rrc_parameters(ue_rrc, false); + } + + if (radioBearerConfig->srb_ToAddModList != NULL) { + for (int cnt = 0; cnt < radioBearerConfig->srb_ToAddModList->list.count; cnt++) { + struct NR_SRB_ToAddMod *srb = radioBearerConfig->srb_ToAddModList->list.array[cnt]; + if (ue_rrc->Srb[srb->srb_Identity] == RB_NOT_PRESENT) { + ue_rrc->Srb[srb->srb_Identity] = RB_ESTABLISHED; + add_srb(false, + ue_rrc->ue_id, + radioBearerConfig->srb_ToAddModList->list.array[cnt], + &security_rrc_parameters); + } + else { + AssertFatal(srb->discardOnPDCP == NULL, "discardOnPDCP not yet implemented\n"); + if (srb->reestablishPDCP) { + ue_rrc->Srb[srb->srb_Identity] = RB_ESTABLISHED; + nr_pdcp_reestablishment(ue_rrc->ue_id, + srb->srb_Identity, + true, + &security_rrc_parameters); + } + if (srb->pdcp_Config && srb->pdcp_Config->t_Reordering) + nr_pdcp_reconfigure_srb(ue_rrc->ue_id, srb->srb_Identity, *srb->pdcp_Config->t_Reordering); + } + } + } + + if (radioBearerConfig->drb_ToReleaseList) { + for (int cnt = 0; cnt < radioBearerConfig->drb_ToReleaseList->list.count; cnt++) { + NR_DRB_Identity_t *DRB_id = radioBearerConfig->drb_ToReleaseList->list.array[cnt]; + if (DRB_id) { + nr_pdcp_release_drb(ue_rrc->ue_id, *DRB_id); + set_DRB_status(ue_rrc, *DRB_id, RB_NOT_PRESENT); + } + } + } + + /** + * Establish/reconfig DRBs if DRB-ToAddMod is present + * according to 3GPP TS 38.331 clause 5.3.5.6.5 DRB addition/modification + */ + if (radioBearerConfig->drb_ToAddModList != NULL) { + for (int cnt = 0; cnt < radioBearerConfig->drb_ToAddModList->list.count; cnt++) { + struct NR_DRB_ToAddMod *drb = radioBearerConfig->drb_ToAddModList->list.array[cnt]; + int DRB_id = drb->drb_Identity; + if (get_DRB_status(ue_rrc, DRB_id) != RB_NOT_PRESENT) { + if (drb->reestablishPDCP) { + set_DRB_status(ue_rrc, DRB_id, RB_ESTABLISHED); + /* get integrity and cipehring settings from radioBearerConfig */ + bool has_integrity = drb->pdcp_Config != NULL + && drb->pdcp_Config->drb != NULL + && drb->pdcp_Config->drb->integrityProtection != NULL; + bool has_ciphering = !(drb->pdcp_Config != NULL + && drb->pdcp_Config->ext1 != NULL + && drb->pdcp_Config->ext1->cipheringDisabled != NULL); + security_up_parameters.ciphering_algorithm = has_ciphering ? ue_rrc->cipheringAlgorithm : 0; + security_up_parameters.integrity_algorithm = has_integrity ? ue_rrc->integrityProtAlgorithm : 0; + /* re-establish */ + nr_pdcp_reestablishment(ue_rrc->ue_id, + DRB_id, + false, + &security_up_parameters); + } + AssertFatal(drb->recoverPDCP == NULL, "recoverPDCP not yet implemented\n"); + /* sdap-Config is included (SA mode) */ + NR_SDAP_Config_t *sdap_Config = drb->cnAssociation ? drb->cnAssociation->choice.sdap_Config : NULL; + /* PDCP reconfiguration */ + if (drb->pdcp_Config) + nr_pdcp_reconfigure_drb(ue_rrc->ue_id, DRB_id, drb->pdcp_Config); + /* SDAP entity reconfiguration */ + if (sdap_Config) + nr_reconfigure_sdap_entity(sdap_Config, ue_rrc->ue_id, sdap_Config->pdu_Session, DRB_id); + } else { + set_DRB_status(ue_rrc ,DRB_id, RB_ESTABLISHED); + add_drb(false, + ue_rrc->ue_id, + radioBearerConfig->drb_ToAddModList->list.array[cnt], + &security_up_parameters); + } + } + } // drb_ToAddModList // + + ue_rrc->nrRrcState = RRC_STATE_CONNECTED_NR; + LOG_I(NR_RRC, "State = NR_RRC_CONNECTED\n"); +} + static void nr_rrc_process_reconfiguration_v1530(NR_UE_RRC_INST_t *rrc, NR_RRCReconfiguration_v1530_IEs_t *rec_1530, int gNB_index) { if (rec_1530->fullConfig) { @@ -1466,8 +1583,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, 0); // perform the radio bearer configuration procedure in accordance with the received radioBearerConfig - nr_rrc_ue_process_RadioBearerConfig(rrc, - &rrcSetup->criticalExtensions.choice.rrcSetup->radioBearerConfig); + nr_rrc_ue_process_RadioBearerConfig(rrc, &rrcSetup->criticalExtensions.choice.rrcSetup->radioBearerConfig); // TODO (not handled) if stored, discard the cell reselection priority information provided by // the cellReselectionPriorities or inherited from another RAT @@ -1999,126 +2115,6 @@ static void nr_rrc_ue_process_measConfig(rrcPerNB_t *rrc, NR_MeasConfig_t *const } } -/** - * @brief add, modify and release SRBs and/or DRBs - * @ref 3GPP TS 38.331 - */ -static void nr_rrc_ue_process_RadioBearerConfig(NR_UE_RRC_INST_t *ue_rrc, - NR_RadioBearerConfig_t *const radioBearerConfig) -{ - if (LOG_DEBUGFLAG(DEBUG_ASN1)) - xer_fprint(stdout, &asn_DEF_NR_RadioBearerConfig, (const void *)radioBearerConfig); - - if (radioBearerConfig->srb3_ToRelease) { - nr_pdcp_release_srb(ue_rrc->ue_id, 3); - ue_rrc->Srb[3] = RB_NOT_PRESENT; - } - - nr_pdcp_entity_security_keys_and_algos_t security_rrc_parameters = {0}; - nr_pdcp_entity_security_keys_and_algos_t security_up_parameters = {0}; - - if (ue_rrc->as_security_activated) { - if (radioBearerConfig->securityConfig != NULL) { - // When the field is not included, continue to use the currently configured keyToUse - if (radioBearerConfig->securityConfig->keyToUse) { - AssertFatal(*radioBearerConfig->securityConfig->keyToUse == NR_SecurityConfig__keyToUse_master, - "Secondary key usage seems not to be implemented\n"); - ue_rrc->keyToUse = *radioBearerConfig->securityConfig->keyToUse; - } - // When the field is not included, continue to use the currently configured security algorithm - if (radioBearerConfig->securityConfig->securityAlgorithmConfig) { - ue_rrc->cipheringAlgorithm = radioBearerConfig->securityConfig->securityAlgorithmConfig->cipheringAlgorithm; - ue_rrc->integrityProtAlgorithm = *radioBearerConfig->securityConfig->securityAlgorithmConfig->integrityProtAlgorithm; - } - } - security_rrc_parameters = get_security_rrc_parameters(ue_rrc, true); - security_up_parameters = get_security_rrc_parameters(ue_rrc, false); - } - - if (radioBearerConfig->srb_ToAddModList != NULL) { - for (int cnt = 0; cnt < radioBearerConfig->srb_ToAddModList->list.count; cnt++) { - struct NR_SRB_ToAddMod *srb = radioBearerConfig->srb_ToAddModList->list.array[cnt]; - if (ue_rrc->Srb[srb->srb_Identity] == RB_NOT_PRESENT) { - ue_rrc->Srb[srb->srb_Identity] = RB_ESTABLISHED; - add_srb(false, - ue_rrc->ue_id, - radioBearerConfig->srb_ToAddModList->list.array[cnt], - &security_rrc_parameters); - } - else { - AssertFatal(srb->discardOnPDCP == NULL, "discardOnPDCP not yet implemented\n"); - if (srb->reestablishPDCP) { - ue_rrc->Srb[srb->srb_Identity] = RB_ESTABLISHED; - nr_pdcp_reestablishment(ue_rrc->ue_id, - srb->srb_Identity, - true, - &security_rrc_parameters); - } - if (srb->pdcp_Config && srb->pdcp_Config->t_Reordering) - nr_pdcp_reconfigure_srb(ue_rrc->ue_id, srb->srb_Identity, *srb->pdcp_Config->t_Reordering); - } - } - } - - if (radioBearerConfig->drb_ToReleaseList) { - for (int cnt = 0; cnt < radioBearerConfig->drb_ToReleaseList->list.count; cnt++) { - NR_DRB_Identity_t *DRB_id = radioBearerConfig->drb_ToReleaseList->list.array[cnt]; - if (DRB_id) { - nr_pdcp_release_drb(ue_rrc->ue_id, *DRB_id); - set_DRB_status(ue_rrc, *DRB_id, RB_NOT_PRESENT); - } - } - } - - /** - * Establish/reconfig DRBs if DRB-ToAddMod is present - * according to 3GPP TS 38.331 clause 5.3.5.6.5 DRB addition/modification - */ - if (radioBearerConfig->drb_ToAddModList != NULL) { - for (int cnt = 0; cnt < radioBearerConfig->drb_ToAddModList->list.count; cnt++) { - struct NR_DRB_ToAddMod *drb = radioBearerConfig->drb_ToAddModList->list.array[cnt]; - int DRB_id = drb->drb_Identity; - if (get_DRB_status(ue_rrc, DRB_id) != RB_NOT_PRESENT) { - if (drb->reestablishPDCP) { - set_DRB_status(ue_rrc, DRB_id, RB_ESTABLISHED); - /* get integrity and cipehring settings from radioBearerConfig */ - bool has_integrity = drb->pdcp_Config != NULL - && drb->pdcp_Config->drb != NULL - && drb->pdcp_Config->drb->integrityProtection != NULL; - bool has_ciphering = !(drb->pdcp_Config != NULL - && drb->pdcp_Config->ext1 != NULL - && drb->pdcp_Config->ext1->cipheringDisabled != NULL); - security_up_parameters.ciphering_algorithm = has_ciphering ? ue_rrc->cipheringAlgorithm : 0; - security_up_parameters.integrity_algorithm = has_integrity ? ue_rrc->integrityProtAlgorithm : 0; - /* re-establish */ - nr_pdcp_reestablishment(ue_rrc->ue_id, - DRB_id, - false, - &security_up_parameters); - } - AssertFatal(drb->recoverPDCP == NULL, "recoverPDCP not yet implemented\n"); - /* sdap-Config is included (SA mode) */ - NR_SDAP_Config_t *sdap_Config = drb->cnAssociation ? drb->cnAssociation->choice.sdap_Config : NULL; - /* PDCP reconfiguration */ - if (drb->pdcp_Config) - nr_pdcp_reconfigure_drb(ue_rrc->ue_id, DRB_id, drb->pdcp_Config); - /* SDAP entity reconfiguration */ - if (sdap_Config) - nr_reconfigure_sdap_entity(sdap_Config, ue_rrc->ue_id, sdap_Config->pdu_Session, DRB_id); - } else { - set_DRB_status(ue_rrc ,DRB_id, RB_ESTABLISHED); - add_drb(false, - ue_rrc->ue_id, - radioBearerConfig->drb_ToAddModList->list.array[cnt], - &security_up_parameters); - } - } - } // drb_ToAddModList // - - ue_rrc->nrRrcState = RRC_STATE_CONNECTED_NR; - LOG_I(NR_RRC, "State = NR_RRC_CONNECTED\n"); -} - static void nr_rrc_ue_generate_RRCReconfigurationComplete(NR_UE_RRC_INST_t *rrc, const int srb_id, const uint8_t Transaction_id) { uint8_t buffer[32]; From fc8854a04029801db1014605d34655694dc3c480 Mon Sep 17 00:00:00 2001 From: francescomani Date: Wed, 24 Sep 2025 10:19:51 +0200 Subject: [PATCH 771/964] move nr_rrc_ue_generate_rrcReestablishmentComplete before its usage --- openair2/RRC/NR_UE/rrc_UE.c | 61 ++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 31 deletions(-) diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 56657b41b3..d3d8d8916e 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -134,7 +134,6 @@ static const char nr_nas_attach_req_imsi_dummy_NSA_case[] = { 0x11, }; -static void nr_rrc_ue_generate_rrcReestablishmentComplete(const NR_UE_RRC_INST_t *rrc, const NR_RRCReestablishment_t *rrcReestablishment); static void process_lte_nsa_msg(NR_UE_RRC_INST_t *rrc, nsa_msg_t *msg, int msg_len); 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, @@ -2129,6 +2128,36 @@ static void nr_rrc_ue_generate_RRCReconfigurationComplete(NR_UE_RRC_INST_t *rrc, nr_pdcp_data_req_srb(rrc->ue_id, srb_id, 0, size, buffer, deliver_pdu_srb_rlc, NULL); } +static void nr_rrc_ue_generate_rrcReestablishmentComplete(const NR_UE_RRC_INST_t *rrc, + const NR_RRCReestablishment_t *rrcReestablishment) +{ + uint8_t buffer[NR_RRC_BUF_SIZE] = {0}; + int size = do_RRCReestablishmentComplete(buffer, NR_RRC_BUF_SIZE, rrcReestablishment->rrc_TransactionIdentifier); + LOG_I(NR_RRC, "[RAPROC] Logical Channel UL-DCCH (SRB1), Generating RRCReestablishmentComplete (bytes %d)\n", size); + int srb_id = 1; // RRC re-establishment complete on SRB1 + nr_pdcp_data_req_srb(rrc->ue_id, srb_id, 0, size, buffer, deliver_pdu_srb_rlc, NULL); +} + +void *recv_msgs_from_lte_ue(void *args_p) +{ + itti_mark_task_ready (TASK_RRC_NSA_NRUE); + int from_lte_ue_fd = get_from_lte_ue_fd(); + for (;;) { + nsa_msg_t msg; + int recvLen = recvfrom(from_lte_ue_fd, &msg, sizeof(msg), MSG_WAITALL | MSG_TRUNC, NULL, NULL); + if (recvLen == -1) { + LOG_E(NR_RRC, "%s: recvfrom: %s\n", __func__, strerror(errno)); + continue; + } + if (recvLen > sizeof(msg)) { + LOG_E(NR_RRC, "%s: Received truncated message %d\n", __func__, recvLen); + continue; + } + process_lte_nsa_msg(get_NR_UE_rrc_inst(0), &msg, recvLen); + } + return NULL; +} + static void nr_rrc_ue_process_rrcReestablishment(NR_UE_RRC_INST_t *rrc, const int gNB_index, const NR_RRCReestablishment_t *rrcReestablishment, @@ -2781,36 +2810,6 @@ static void nr_rrc_initiate_rrcReestablishment(NR_UE_RRC_INST_t *rrc, NR_Reestab nr_rrc_send_msg_to_mac(rrc, &rrc_msg); } -static void nr_rrc_ue_generate_rrcReestablishmentComplete(const NR_UE_RRC_INST_t *rrc, - const NR_RRCReestablishment_t *rrcReestablishment) -{ - uint8_t buffer[NR_RRC_BUF_SIZE] = {0}; - int size = do_RRCReestablishmentComplete(buffer, NR_RRC_BUF_SIZE, rrcReestablishment->rrc_TransactionIdentifier); - LOG_I(NR_RRC, "[RAPROC] Logical Channel UL-DCCH (SRB1), Generating RRCReestablishmentComplete (bytes %d)\n", size); - int srb_id = 1; // RRC re-establishment complete on SRB1 - nr_pdcp_data_req_srb(rrc->ue_id, srb_id, 0, size, buffer, deliver_pdu_srb_rlc, NULL); -} - -void *recv_msgs_from_lte_ue(void *args_p) -{ - itti_mark_task_ready (TASK_RRC_NSA_NRUE); - int from_lte_ue_fd = get_from_lte_ue_fd(); - for (;;) { - nsa_msg_t msg; - int recvLen = recvfrom(from_lte_ue_fd, &msg, sizeof(msg), MSG_WAITALL | MSG_TRUNC, NULL, NULL); - if (recvLen == -1) { - LOG_E(NR_RRC, "%s: recvfrom: %s\n", __func__, strerror(errno)); - continue; - } - if (recvLen > sizeof(msg)) { - LOG_E(NR_RRC, "%s: Received truncated message %d\n", __func__, recvLen); - continue; - } - process_lte_nsa_msg(get_NR_UE_rrc_inst(0), &msg, recvLen); - } - return NULL; -} - static void nsa_rrc_ue_process_ueCapabilityEnquiry(NR_UE_RRC_INST_t *rrc) { NR_UE_NR_Capability_t *UE_Capability_nr = rrc->UECap.UE_NR_Capability = CALLOC(1, sizeof(NR_UE_NR_Capability_t)); From 6009b06101991fe75b4f25d92e230711d0b5e506 Mon Sep 17 00:00:00 2001 From: francescomani Date: Wed, 24 Sep 2025 10:23:37 +0200 Subject: [PATCH 772/964] move nr_rrc_ue_process_measConfig (and its functions) before usage --- openair2/RRC/NR_UE/rrc_UE.c | 538 ++++++++++++++++++------------------ 1 file changed, 268 insertions(+), 270 deletions(-) diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index d3d8d8916e..56e1fe5504 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -141,8 +141,6 @@ static void nr_rrc_ue_process_masterCellGroup(NR_UE_RRC_INST_t *rrc, 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); - /** * @brief Sends an RRC message to the connected UE MAC instance. * @@ -808,6 +806,274 @@ static void nr_rrc_process_reconfiguration_v1530(NR_UE_RRC_INST_t *rrc, NR_RRCRe } } +static void handle_meas_reporting_remove(rrcPerNB_t *rrc, int id, NR_UE_Timers_Constants_t *timers) +{ + // remove the measurement reporting entry for this measId if included + asn1cFreeStruc(asn_DEF_NR_VarMeasReport, rrc->MeasReport[id]); + // TODO stop the periodical reporting timer or timer T321, whichever is running, + // and reset the associated information (e.g. timeToTrigger) for this measId + nr_timer_stop(&timers->T321); + + l3_measurements_t *l3_measurements = &rrc->l3_measurements; + nr_timer_stop(&l3_measurements->TA2); + nr_timer_stop(&l3_measurements->periodic_report_timer); + + l3_measurements->reports_sent = 0; + l3_measurements->max_reports = 0; + l3_measurements->report_interval_ms = 0; +} + +static void handle_measobj_remove(rrcPerNB_t *rrc, struct NR_MeasObjectToRemoveList *remove_list, NR_UE_Timers_Constants_t *timers) +{ + // section 5.5.2.4 in 38.331 + for (int i = 0; i < remove_list->list.count; i++) { + // for each measObjectId included in the received measObjectToRemoveList + // that is part of measObjectList in the configuration + NR_MeasObjectId_t id = *remove_list->list.array[i]; + if (rrc->MeasObj[id - 1]) { + // remove the entry with the matching measObjectId from the measObjectList + asn1cFreeStruc(asn_DEF_NR_MeasObjectToAddMod, rrc->MeasObj[id - 1]); + // remove all measId associated with this measObjectId from the measIdList + for (int j = 0; j < MAX_MEAS_ID; j++) { + if (rrc->MeasId[j] && rrc->MeasId[j]->measObjectId == id) { + asn1cFreeStruc(asn_DEF_NR_MeasIdToAddMod, rrc->MeasId[j]); + handle_meas_reporting_remove(rrc, j, timers); + } + } + } + } +} + +static void update_ssb_configmob(NR_SSB_ConfigMobility_t *source, NR_SSB_ConfigMobility_t *target) +{ + if (source->ssb_ToMeasure) + HANDLE_SETUPRELEASE_IE(target->ssb_ToMeasure, source->ssb_ToMeasure, NR_SSB_ToMeasure_t, asn_DEF_NR_SSB_ToMeasure); + target->deriveSSB_IndexFromCell = source->deriveSSB_IndexFromCell; + if (source->ss_RSSI_Measurement) + UPDATE_IE(target->ss_RSSI_Measurement, source->ss_RSSI_Measurement, NR_SS_RSSI_Measurement_t); +} + +static void update_nr_measobj(NR_MeasObjectNR_t *source, NR_MeasObjectNR_t *target) +{ + UPDATE_IE(target->ssbFrequency, source->ssbFrequency, NR_ARFCN_ValueNR_t); + UPDATE_IE(target->ssbSubcarrierSpacing, source->ssbSubcarrierSpacing, NR_SubcarrierSpacing_t); + UPDATE_IE(target->smtc1, source->smtc1, NR_SSB_MTC_t); + if (source->smtc2) { + target->smtc2->periodicity = source->smtc2->periodicity; + if (source->smtc2->pci_List) + UPDATE_IE(target->smtc2->pci_List, source->smtc2->pci_List, struct NR_SSB_MTC2__pci_List); + } + else + asn1cFreeStruc(asn_DEF_NR_SSB_MTC2, target->smtc2); + UPDATE_IE(target->refFreqCSI_RS, source->refFreqCSI_RS, NR_ARFCN_ValueNR_t); + if (source->referenceSignalConfig.ssb_ConfigMobility) + update_ssb_configmob(source->referenceSignalConfig.ssb_ConfigMobility, target->referenceSignalConfig.ssb_ConfigMobility); + UPDATE_IE(target->absThreshSS_BlocksConsolidation, source->absThreshSS_BlocksConsolidation, NR_ThresholdNR_t); + UPDATE_IE(target->absThreshCSI_RS_Consolidation, source->absThreshCSI_RS_Consolidation, NR_ThresholdNR_t); + UPDATE_IE(target->nrofSS_BlocksToAverage, source->nrofSS_BlocksToAverage, long); + UPDATE_IE(target->nrofCSI_RS_ResourcesToAverage, source->nrofCSI_RS_ResourcesToAverage, long); + target->quantityConfigIndex = source->quantityConfigIndex; + target->offsetMO = source->offsetMO; + if (source->cellsToRemoveList) { + RELEASE_IE_FROMLIST(source->cellsToRemoveList, target->cellsToAddModList, physCellId); + } + if (source->cellsToAddModList) { + if (!target->cellsToAddModList) + target->cellsToAddModList = calloc(1, sizeof(*target->cellsToAddModList)); + ADDMOD_IE_FROMLIST(source->cellsToAddModList, target->cellsToAddModList, physCellId, NR_CellsToAddMod_t); + } + if (source->excludedCellsToRemoveList) { + RELEASE_IE_FROMLIST(source->excludedCellsToRemoveList, target->excludedCellsToAddModList, pci_RangeIndex); + } + if (source->excludedCellsToAddModList) { + if (!target->excludedCellsToAddModList) + target->excludedCellsToAddModList = calloc(1, sizeof(*target->excludedCellsToAddModList)); + ADDMOD_IE_FROMLIST(source->excludedCellsToAddModList, target->excludedCellsToAddModList, pci_RangeIndex, NR_PCI_RangeElement_t); + } + if (source->allowedCellsToRemoveList) { + RELEASE_IE_FROMLIST(source->allowedCellsToRemoveList, target->allowedCellsToAddModList, pci_RangeIndex); + } + if (source->allowedCellsToAddModList) { + if (!target->allowedCellsToAddModList) + target->allowedCellsToAddModList = calloc(1, sizeof(*target->allowedCellsToAddModList)); + ADDMOD_IE_FROMLIST(source->allowedCellsToAddModList, target->allowedCellsToAddModList, pci_RangeIndex, NR_PCI_RangeElement_t); + } + if (source->ext1) { + UPDATE_IE(target->ext1->freqBandIndicatorNR, source->ext1->freqBandIndicatorNR, NR_FreqBandIndicatorNR_t); + UPDATE_IE(target->ext1->measCycleSCell, source->ext1->measCycleSCell, long); + } +} + +static void handle_measobj_addmod(rrcPerNB_t *rrc, struct NR_MeasObjectToAddModList *addmod_list) +{ + // section 5.5.2.5 in 38.331 + for (int i = 0; i < addmod_list->list.count; i++) { + NR_MeasObjectToAddMod_t *measObj = addmod_list->list.array[i]; + if (measObj->measObject.present != NR_MeasObjectToAddMod__measObject_PR_measObjectNR) { + LOG_E(NR_RRC, "Cannot handle MeasObjt other than NR\n"); + continue; + } + NR_MeasObjectId_t id = measObj->measObjectId; + if (rrc->MeasObj[id]) { + update_nr_measobj(measObj->measObject.choice.measObjectNR, rrc->MeasObj[id]->measObject.choice.measObjectNR); + } + else { + // add a new entry for the received measObject to the measObjectList + UPDATE_IE(rrc->MeasObj[id], addmod_list->list.array[i], NR_MeasObjectToAddMod_t); + } + } +} + +static void handle_reportconfig_remove(rrcPerNB_t *rrc, + struct NR_ReportConfigToRemoveList *remove_list, + NR_UE_Timers_Constants_t *timers) +{ + for (int i = 0; i < remove_list->list.count; i++) { + NR_ReportConfigId_t id = *remove_list->list.array[i]; + // remove the entry with the matching reportConfigId from the reportConfigList + asn1cFreeStruc(asn_DEF_NR_ReportConfigToAddMod, rrc->ReportConfig[id]); + for (int j = 0; j < MAX_MEAS_ID; j++) { + if (rrc->MeasId[j] && rrc->MeasId[j]->reportConfigId == id) { + // remove all measId associated with the reportConfigId from the measIdList + asn1cFreeStruc(asn_DEF_NR_MeasIdToAddMod, rrc->MeasId[j]); + handle_meas_reporting_remove(rrc, j, timers); + } + } + } +} + +static void handle_reportconfig_addmod(rrcPerNB_t *rrc, + struct NR_ReportConfigToAddModList *addmod_list, + NR_UE_Timers_Constants_t *timers) +{ + for (int i = 0; i < addmod_list->list.count; i++) { + NR_ReportConfigToAddMod_t *rep = addmod_list->list.array[i]; + if (rep->reportConfig.present != NR_ReportConfigToAddMod__reportConfig_PR_reportConfigNR) { + LOG_E(NR_RRC, "Cannot handle reportConfig type other than NR\n"); + continue; + } + NR_ReportConfigId_t id = rep->reportConfigId; + if (rrc->ReportConfig[id]) { + for (int j = 0; j < MAX_MEAS_ID; j++) { + // for each measId associated with this reportConfigId included in the measIdList + if (rrc->MeasId[j] && rrc->MeasId[j]->reportConfigId == id) + handle_meas_reporting_remove(rrc, j, timers); + } + } + UPDATE_IE(rrc->ReportConfig[id], addmod_list->list.array[i], NR_ReportConfigToAddMod_t); + } +} + +static void handle_quantityconfig(rrcPerNB_t *rrc, NR_QuantityConfig_t *quantityConfig, NR_UE_Timers_Constants_t *timers) +{ + if (quantityConfig->quantityConfigNR_List) { + for (int i = 0; i < quantityConfig->quantityConfigNR_List->list.count; i++) { + NR_QuantityConfigNR_t *quantityNR = quantityConfig->quantityConfigNR_List->list.array[i]; + if (!rrc->QuantityConfig[i]) + rrc->QuantityConfig[i] = calloc(1, sizeof(*rrc->QuantityConfig[i])); + rrc->QuantityConfig[i]->quantityConfigCell = quantityNR->quantityConfigCell; + // TODO: It remains to compute ssb_filter_coeff_rsrp and csi_RS_filter_coeff_rsrp for multiple quantityConfig + // TS 38.331 - 5.5.3.2 Layer 3 filtering + NR_QuantityConfigRS_t *qcc = &quantityNR->quantityConfigCell; + l3_measurements_t *l3_measurements = &rrc->l3_measurements; + if (qcc->ssb_FilterConfig.filterCoefficientRSRP) + l3_measurements->ssb_filter_coeff_rsrp = 1. / pow(2, (*qcc->ssb_FilterConfig.filterCoefficientRSRP) / 4); + if (qcc->csi_RS_FilterConfig.filterCoefficientRSRP) + l3_measurements->csi_RS_filter_coeff_rsrp = 1. / pow(2, (*qcc->csi_RS_FilterConfig.filterCoefficientRSRP) / 4); + if (quantityNR->quantityConfigRS_Index) + UPDATE_IE(rrc->QuantityConfig[i]->quantityConfigRS_Index, quantityNR->quantityConfigRS_Index, struct NR_QuantityConfigRS); + } + } + for (int j = 0; j < MAX_MEAS_ID; j++) { + // for each measId included in the measIdList + if (rrc->MeasId[j]) + handle_meas_reporting_remove(rrc, j, timers); + } +} + +static void handle_measid_remove(rrcPerNB_t *rrc, struct NR_MeasIdToRemoveList *remove_list, NR_UE_Timers_Constants_t *timers) +{ + for (int i = 0; i < remove_list->list.count; i++) { + NR_MeasId_t id = *remove_list->list.array[i]; + if (rrc->MeasId[id]) { + asn1cFreeStruc(asn_DEF_NR_MeasIdToAddMod, rrc->MeasId[id]); + handle_meas_reporting_remove(rrc, id, timers); + } + } +} + +static void handle_measid_addmod(rrcPerNB_t *rrc, struct NR_MeasIdToAddModList *addmod_list, NR_UE_Timers_Constants_t *timers) +{ + for (int i = 0; i < addmod_list->list.count; i++) { + NR_MeasId_t id = addmod_list->list.array[i]->measId; + NR_ReportConfigId_t reportId = addmod_list->list.array[i]->reportConfigId; + NR_MeasObjectId_t measObjectId = addmod_list->list.array[i]->measObjectId; + UPDATE_IE(rrc->MeasId[id], addmod_list->list.array[i], NR_MeasIdToAddMod_t); + handle_meas_reporting_remove(rrc, id, timers); + if (rrc->ReportConfig[reportId]) { + NR_ReportConfigToAddMod_t *report = rrc->ReportConfig[reportId]; + AssertFatal(report->reportConfig.present == NR_ReportConfigToAddMod__reportConfig_PR_reportConfigNR, + "Only NR config report is supported\n"); + NR_ReportConfigNR_t *reportNR = report->reportConfig.choice.reportConfigNR; + // if the reportType is set to reportCGI in the reportConfig associated with this measId + if (reportNR->reportType.present == NR_ReportConfigNR__reportType_PR_reportCGI) { + if (rrc->MeasObj[measObjectId]) { + if (rrc->MeasObj[measObjectId]->measObject.present == NR_MeasObjectToAddMod__measObject_PR_measObjectNR) { + NR_MeasObjectNR_t *obj_nr = rrc->MeasObj[measObjectId]->measObject.choice.measObjectNR; + NR_ARFCN_ValueNR_t freq = 0; + if (obj_nr->ssbFrequency) + freq = *obj_nr->ssbFrequency; + else if (obj_nr->refFreqCSI_RS) + freq = *obj_nr->refFreqCSI_RS; + AssertFatal(freq > 0, "Invalid ARFCN frequency for this measurement object\n"); + if (get_freq_range_from_arfcn(freq) == FR2) + nr_timer_setup(&timers->T321, 16000, 10); // 16 seconds for FR2 + else + nr_timer_setup(&timers->T321, 2000, 10); // 2 seconds for FR1 + } + else // EUTRA + nr_timer_setup(&timers->T321, 1000, 10); // 1 second for EUTRA + nr_timer_start(&timers->T321); + } + } + } + } +} + +static void nr_rrc_ue_process_measConfig(rrcPerNB_t *rrc, NR_MeasConfig_t *const measConfig, NR_UE_Timers_Constants_t *timers) +{ + if (measConfig->measObjectToRemoveList) + handle_measobj_remove(rrc, measConfig->measObjectToRemoveList, timers); + + if (measConfig->measObjectToAddModList) + handle_measobj_addmod(rrc, measConfig->measObjectToAddModList); + + if (measConfig->reportConfigToRemoveList) + handle_reportconfig_remove(rrc, measConfig->reportConfigToRemoveList, timers); + + if (measConfig->reportConfigToAddModList) + handle_reportconfig_addmod(rrc, measConfig->reportConfigToAddModList, timers); + + if (measConfig->quantityConfig) + handle_quantityconfig(rrc, measConfig->quantityConfig, timers); + + if (measConfig->measIdToRemoveList) + handle_measid_remove(rrc, measConfig->measIdToRemoveList, timers); + + if (measConfig->measIdToAddModList) + handle_measid_addmod(rrc, measConfig->measIdToAddModList, timers); + + LOG_W(NR_RRC, "Measurement gaps not yet supported!\n"); + + if (measConfig->s_MeasureConfig) { + if (measConfig->s_MeasureConfig->present == NR_MeasConfig__s_MeasureConfig_PR_ssb_RSRP) { + rrc->s_measure = measConfig->s_MeasureConfig->choice.ssb_RSRP; + } else if (measConfig->s_MeasureConfig->present == NR_MeasConfig__s_MeasureConfig_PR_csi_RSRP) { + rrc->s_measure = measConfig->s_MeasureConfig->choice.csi_RSRP; + } + } +} + static void nr_rrc_ue_process_rrcReconfiguration(NR_UE_RRC_INST_t *rrc, int gNB_index, NR_RRCReconfiguration_t *reconfiguration) { rrcPerNB_t *rrcNB = rrc->perNB + gNB_index; @@ -1846,274 +2112,6 @@ static void nr_rrc_ue_process_securityModeCommand(NR_UE_RRC_INST_t *ue_rrc, } } -static void handle_meas_reporting_remove(rrcPerNB_t *rrc, int id, NR_UE_Timers_Constants_t *timers) -{ - // remove the measurement reporting entry for this measId if included - asn1cFreeStruc(asn_DEF_NR_VarMeasReport, rrc->MeasReport[id]); - // TODO stop the periodical reporting timer or timer T321, whichever is running, - // and reset the associated information (e.g. timeToTrigger) for this measId - nr_timer_stop(&timers->T321); - - l3_measurements_t *l3_measurements = &rrc->l3_measurements; - nr_timer_stop(&l3_measurements->TA2); - nr_timer_stop(&l3_measurements->periodic_report_timer); - - l3_measurements->reports_sent = 0; - l3_measurements->max_reports = 0; - l3_measurements->report_interval_ms = 0; -} - -static void handle_measobj_remove(rrcPerNB_t *rrc, struct NR_MeasObjectToRemoveList *remove_list, NR_UE_Timers_Constants_t *timers) -{ - // section 5.5.2.4 in 38.331 - for (int i = 0; i < remove_list->list.count; i++) { - // for each measObjectId included in the received measObjectToRemoveList - // that is part of measObjectList in the configuration - NR_MeasObjectId_t id = *remove_list->list.array[i]; - if (rrc->MeasObj[id - 1]) { - // remove the entry with the matching measObjectId from the measObjectList - asn1cFreeStruc(asn_DEF_NR_MeasObjectToAddMod, rrc->MeasObj[id - 1]); - // remove all measId associated with this measObjectId from the measIdList - for (int j = 0; j < MAX_MEAS_ID; j++) { - if (rrc->MeasId[j] && rrc->MeasId[j]->measObjectId == id) { - asn1cFreeStruc(asn_DEF_NR_MeasIdToAddMod, rrc->MeasId[j]); - handle_meas_reporting_remove(rrc, j, timers); - } - } - } - } -} - -static void update_ssb_configmob(NR_SSB_ConfigMobility_t *source, NR_SSB_ConfigMobility_t *target) -{ - if (source->ssb_ToMeasure) - HANDLE_SETUPRELEASE_IE(target->ssb_ToMeasure, source->ssb_ToMeasure, NR_SSB_ToMeasure_t, asn_DEF_NR_SSB_ToMeasure); - target->deriveSSB_IndexFromCell = source->deriveSSB_IndexFromCell; - if (source->ss_RSSI_Measurement) - UPDATE_IE(target->ss_RSSI_Measurement, source->ss_RSSI_Measurement, NR_SS_RSSI_Measurement_t); -} - -static void update_nr_measobj(NR_MeasObjectNR_t *source, NR_MeasObjectNR_t *target) -{ - UPDATE_IE(target->ssbFrequency, source->ssbFrequency, NR_ARFCN_ValueNR_t); - UPDATE_IE(target->ssbSubcarrierSpacing, source->ssbSubcarrierSpacing, NR_SubcarrierSpacing_t); - UPDATE_IE(target->smtc1, source->smtc1, NR_SSB_MTC_t); - if (source->smtc2) { - target->smtc2->periodicity = source->smtc2->periodicity; - if (source->smtc2->pci_List) - UPDATE_IE(target->smtc2->pci_List, source->smtc2->pci_List, struct NR_SSB_MTC2__pci_List); - } - else - asn1cFreeStruc(asn_DEF_NR_SSB_MTC2, target->smtc2); - UPDATE_IE(target->refFreqCSI_RS, source->refFreqCSI_RS, NR_ARFCN_ValueNR_t); - if (source->referenceSignalConfig.ssb_ConfigMobility) - update_ssb_configmob(source->referenceSignalConfig.ssb_ConfigMobility, target->referenceSignalConfig.ssb_ConfigMobility); - UPDATE_IE(target->absThreshSS_BlocksConsolidation, source->absThreshSS_BlocksConsolidation, NR_ThresholdNR_t); - UPDATE_IE(target->absThreshCSI_RS_Consolidation, source->absThreshCSI_RS_Consolidation, NR_ThresholdNR_t); - UPDATE_IE(target->nrofSS_BlocksToAverage, source->nrofSS_BlocksToAverage, long); - UPDATE_IE(target->nrofCSI_RS_ResourcesToAverage, source->nrofCSI_RS_ResourcesToAverage, long); - target->quantityConfigIndex = source->quantityConfigIndex; - target->offsetMO = source->offsetMO; - if (source->cellsToRemoveList) { - RELEASE_IE_FROMLIST(source->cellsToRemoveList, target->cellsToAddModList, physCellId); - } - if (source->cellsToAddModList) { - if (!target->cellsToAddModList) - target->cellsToAddModList = calloc(1, sizeof(*target->cellsToAddModList)); - ADDMOD_IE_FROMLIST(source->cellsToAddModList, target->cellsToAddModList, physCellId, NR_CellsToAddMod_t); - } - if (source->excludedCellsToRemoveList) { - RELEASE_IE_FROMLIST(source->excludedCellsToRemoveList, target->excludedCellsToAddModList, pci_RangeIndex); - } - if (source->excludedCellsToAddModList) { - if (!target->excludedCellsToAddModList) - target->excludedCellsToAddModList = calloc(1, sizeof(*target->excludedCellsToAddModList)); - ADDMOD_IE_FROMLIST(source->excludedCellsToAddModList, target->excludedCellsToAddModList, pci_RangeIndex, NR_PCI_RangeElement_t); - } - if (source->allowedCellsToRemoveList) { - RELEASE_IE_FROMLIST(source->allowedCellsToRemoveList, target->allowedCellsToAddModList, pci_RangeIndex); - } - if (source->allowedCellsToAddModList) { - if (!target->allowedCellsToAddModList) - target->allowedCellsToAddModList = calloc(1, sizeof(*target->allowedCellsToAddModList)); - ADDMOD_IE_FROMLIST(source->allowedCellsToAddModList, target->allowedCellsToAddModList, pci_RangeIndex, NR_PCI_RangeElement_t); - } - if (source->ext1) { - UPDATE_IE(target->ext1->freqBandIndicatorNR, source->ext1->freqBandIndicatorNR, NR_FreqBandIndicatorNR_t); - UPDATE_IE(target->ext1->measCycleSCell, source->ext1->measCycleSCell, long); - } -} - -static void handle_measobj_addmod(rrcPerNB_t *rrc, struct NR_MeasObjectToAddModList *addmod_list) -{ - // section 5.5.2.5 in 38.331 - for (int i = 0; i < addmod_list->list.count; i++) { - NR_MeasObjectToAddMod_t *measObj = addmod_list->list.array[i]; - if (measObj->measObject.present != NR_MeasObjectToAddMod__measObject_PR_measObjectNR) { - LOG_E(NR_RRC, "Cannot handle MeasObjt other than NR\n"); - continue; - } - NR_MeasObjectId_t id = measObj->measObjectId; - if (rrc->MeasObj[id]) { - update_nr_measobj(measObj->measObject.choice.measObjectNR, rrc->MeasObj[id]->measObject.choice.measObjectNR); - } - else { - // add a new entry for the received measObject to the measObjectList - UPDATE_IE(rrc->MeasObj[id], addmod_list->list.array[i], NR_MeasObjectToAddMod_t); - } - } -} - -static void handle_reportconfig_remove(rrcPerNB_t *rrc, - struct NR_ReportConfigToRemoveList *remove_list, - NR_UE_Timers_Constants_t *timers) -{ - for (int i = 0; i < remove_list->list.count; i++) { - NR_ReportConfigId_t id = *remove_list->list.array[i]; - // remove the entry with the matching reportConfigId from the reportConfigList - asn1cFreeStruc(asn_DEF_NR_ReportConfigToAddMod, rrc->ReportConfig[id]); - for (int j = 0; j < MAX_MEAS_ID; j++) { - if (rrc->MeasId[j] && rrc->MeasId[j]->reportConfigId == id) { - // remove all measId associated with the reportConfigId from the measIdList - asn1cFreeStruc(asn_DEF_NR_MeasIdToAddMod, rrc->MeasId[j]); - handle_meas_reporting_remove(rrc, j, timers); - } - } - } -} - -static void handle_reportconfig_addmod(rrcPerNB_t *rrc, - struct NR_ReportConfigToAddModList *addmod_list, - NR_UE_Timers_Constants_t *timers) -{ - for (int i = 0; i < addmod_list->list.count; i++) { - NR_ReportConfigToAddMod_t *rep = addmod_list->list.array[i]; - if (rep->reportConfig.present != NR_ReportConfigToAddMod__reportConfig_PR_reportConfigNR) { - LOG_E(NR_RRC, "Cannot handle reportConfig type other than NR\n"); - continue; - } - NR_ReportConfigId_t id = rep->reportConfigId; - if (rrc->ReportConfig[id]) { - for (int j = 0; j < MAX_MEAS_ID; j++) { - // for each measId associated with this reportConfigId included in the measIdList - if (rrc->MeasId[j] && rrc->MeasId[j]->reportConfigId == id) - handle_meas_reporting_remove(rrc, j, timers); - } - } - UPDATE_IE(rrc->ReportConfig[id], addmod_list->list.array[i], NR_ReportConfigToAddMod_t); - } -} - -static void handle_quantityconfig(rrcPerNB_t *rrc, NR_QuantityConfig_t *quantityConfig, NR_UE_Timers_Constants_t *timers) -{ - if (quantityConfig->quantityConfigNR_List) { - for (int i = 0; i < quantityConfig->quantityConfigNR_List->list.count; i++) { - NR_QuantityConfigNR_t *quantityNR = quantityConfig->quantityConfigNR_List->list.array[i]; - if (!rrc->QuantityConfig[i]) - rrc->QuantityConfig[i] = calloc(1, sizeof(*rrc->QuantityConfig[i])); - rrc->QuantityConfig[i]->quantityConfigCell = quantityNR->quantityConfigCell; - // TODO: It remains to compute ssb_filter_coeff_rsrp and csi_RS_filter_coeff_rsrp for multiple quantityConfig - // TS 38.331 - 5.5.3.2 Layer 3 filtering - NR_QuantityConfigRS_t *qcc = &quantityNR->quantityConfigCell; - l3_measurements_t *l3_measurements = &rrc->l3_measurements; - if (qcc->ssb_FilterConfig.filterCoefficientRSRP) - l3_measurements->ssb_filter_coeff_rsrp = 1. / pow(2, (*qcc->ssb_FilterConfig.filterCoefficientRSRP) / 4); - if (qcc->csi_RS_FilterConfig.filterCoefficientRSRP) - l3_measurements->csi_RS_filter_coeff_rsrp = 1. / pow(2, (*qcc->csi_RS_FilterConfig.filterCoefficientRSRP) / 4); - if (quantityNR->quantityConfigRS_Index) - UPDATE_IE(rrc->QuantityConfig[i]->quantityConfigRS_Index, quantityNR->quantityConfigRS_Index, struct NR_QuantityConfigRS); - } - } - for (int j = 0; j < MAX_MEAS_ID; j++) { - // for each measId included in the measIdList - if (rrc->MeasId[j]) - handle_meas_reporting_remove(rrc, j, timers); - } -} - -static void handle_measid_remove(rrcPerNB_t *rrc, struct NR_MeasIdToRemoveList *remove_list, NR_UE_Timers_Constants_t *timers) -{ - for (int i = 0; i < remove_list->list.count; i++) { - NR_MeasId_t id = *remove_list->list.array[i]; - if (rrc->MeasId[id]) { - asn1cFreeStruc(asn_DEF_NR_MeasIdToAddMod, rrc->MeasId[id]); - handle_meas_reporting_remove(rrc, id, timers); - } - } -} - -static void handle_measid_addmod(rrcPerNB_t *rrc, struct NR_MeasIdToAddModList *addmod_list, NR_UE_Timers_Constants_t *timers) -{ - for (int i = 0; i < addmod_list->list.count; i++) { - NR_MeasId_t id = addmod_list->list.array[i]->measId; - NR_ReportConfigId_t reportId = addmod_list->list.array[i]->reportConfigId; - NR_MeasObjectId_t measObjectId = addmod_list->list.array[i]->measObjectId; - UPDATE_IE(rrc->MeasId[id], addmod_list->list.array[i], NR_MeasIdToAddMod_t); - handle_meas_reporting_remove(rrc, id, timers); - if (rrc->ReportConfig[reportId]) { - NR_ReportConfigToAddMod_t *report = rrc->ReportConfig[reportId]; - AssertFatal(report->reportConfig.present == NR_ReportConfigToAddMod__reportConfig_PR_reportConfigNR, - "Only NR config report is supported\n"); - NR_ReportConfigNR_t *reportNR = report->reportConfig.choice.reportConfigNR; - // if the reportType is set to reportCGI in the reportConfig associated with this measId - if (reportNR->reportType.present == NR_ReportConfigNR__reportType_PR_reportCGI) { - if (rrc->MeasObj[measObjectId]) { - if (rrc->MeasObj[measObjectId]->measObject.present == NR_MeasObjectToAddMod__measObject_PR_measObjectNR) { - NR_MeasObjectNR_t *obj_nr = rrc->MeasObj[measObjectId]->measObject.choice.measObjectNR; - NR_ARFCN_ValueNR_t freq = 0; - if (obj_nr->ssbFrequency) - freq = *obj_nr->ssbFrequency; - else if (obj_nr->refFreqCSI_RS) - freq = *obj_nr->refFreqCSI_RS; - AssertFatal(freq > 0, "Invalid ARFCN frequency for this measurement object\n"); - if (get_freq_range_from_arfcn(freq) == FR2) - nr_timer_setup(&timers->T321, 16000, 10); // 16 seconds for FR2 - else - nr_timer_setup(&timers->T321, 2000, 10); // 2 seconds for FR1 - } - else // EUTRA - nr_timer_setup(&timers->T321, 1000, 10); // 1 second for EUTRA - nr_timer_start(&timers->T321); - } - } - } - } -} - -static void nr_rrc_ue_process_measConfig(rrcPerNB_t *rrc, NR_MeasConfig_t *const measConfig, NR_UE_Timers_Constants_t *timers) -{ - if (measConfig->measObjectToRemoveList) - handle_measobj_remove(rrc, measConfig->measObjectToRemoveList, timers); - - if (measConfig->measObjectToAddModList) - handle_measobj_addmod(rrc, measConfig->measObjectToAddModList); - - if (measConfig->reportConfigToRemoveList) - handle_reportconfig_remove(rrc, measConfig->reportConfigToRemoveList, timers); - - if (measConfig->reportConfigToAddModList) - handle_reportconfig_addmod(rrc, measConfig->reportConfigToAddModList, timers); - - if (measConfig->quantityConfig) - handle_quantityconfig(rrc, measConfig->quantityConfig, timers); - - if (measConfig->measIdToRemoveList) - handle_measid_remove(rrc, measConfig->measIdToRemoveList, timers); - - if (measConfig->measIdToAddModList) - handle_measid_addmod(rrc, measConfig->measIdToAddModList, timers); - - LOG_W(NR_RRC, "Measurement gaps not yet supported!\n"); - - if (measConfig->s_MeasureConfig) { - if (measConfig->s_MeasureConfig->present == NR_MeasConfig__s_MeasureConfig_PR_ssb_RSRP) { - rrc->s_measure = measConfig->s_MeasureConfig->choice.ssb_RSRP; - } else if (measConfig->s_MeasureConfig->present == NR_MeasConfig__s_MeasureConfig_PR_csi_RSRP) { - rrc->s_measure = measConfig->s_MeasureConfig->choice.csi_RSRP; - } - } -} - static void nr_rrc_ue_generate_RRCReconfigurationComplete(NR_UE_RRC_INST_t *rrc, const int srb_id, const uint8_t Transaction_id) { uint8_t buffer[32]; From a49d496b63e14ff63738c507fed1132ecc6ee182 Mon Sep 17 00:00:00 2001 From: francescomani Date: Wed, 24 Sep 2025 10:27:44 +0200 Subject: [PATCH 773/964] move process_lte_nsa_msg before usage --- openair2/RRC/NR_UE/rrc_UE.c | 317 ++++++++++++++++++------------------ 1 file changed, 159 insertions(+), 158 deletions(-) diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 56e1fe5504..661221a458 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -134,7 +134,6 @@ static const char nr_nas_attach_req_imsi_dummy_NSA_case[] = { 0x11, }; -static void process_lte_nsa_msg(NR_UE_RRC_INST_t *rrc, nsa_msg_t *msg, int msg_len); 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, @@ -2126,6 +2125,165 @@ static void nr_rrc_ue_generate_RRCReconfigurationComplete(NR_UE_RRC_INST_t *rrc, nr_pdcp_data_req_srb(rrc->ue_id, srb_id, 0, size, buffer, deliver_pdu_srb_rlc, NULL); } +static void nsa_rrc_ue_process_ueCapabilityEnquiry(NR_UE_RRC_INST_t *rrc) +{ + NR_UE_NR_Capability_t *UE_Capability_nr = rrc->UECap.UE_NR_Capability = CALLOC(1, sizeof(NR_UE_NR_Capability_t)); + NR_BandNR_t *nr_bandnr = CALLOC(1, sizeof(NR_BandNR_t)); + nr_bandnr->bandNR = 78; + asn1cSeqAdd(&UE_Capability_nr->rf_Parameters.supportedBandListNR.list, nr_bandnr); + OAI_NR_UECapability_t *UECap = CALLOC(1, sizeof(OAI_NR_UECapability_t)); + UECap->UE_NR_Capability = UE_Capability_nr; + + asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_UE_NR_Capability, + NULL, + (void *)UE_Capability_nr, + &UECap->sdu[0], + MAX_UE_NR_CAPABILITY_SIZE); + AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", enc_rval.failed_type->name, enc_rval.encoded); + UECap->sdu_size = (enc_rval.encoded + 7) / 8; + LOG_A(NR_RRC, "[NR_RRC] NRUE Capability encoded, %d bytes (%zd bits)\n", UECap->sdu_size, enc_rval.encoded + 7); + + NR_UE_CapabilityRAT_Container_t ue_CapabilityRAT_Container; + memset(&ue_CapabilityRAT_Container, 0, sizeof(NR_UE_CapabilityRAT_Container_t)); + ue_CapabilityRAT_Container.rat_Type = NR_RAT_Type_nr; + OCTET_STRING_fromBuf(&ue_CapabilityRAT_Container.ue_CapabilityRAT_Container, (const char *)rrc->UECap.sdu, rrc->UECap.sdu_size); + + nsa_sendmsg_to_lte_ue(ue_CapabilityRAT_Container.ue_CapabilityRAT_Container.buf, + ue_CapabilityRAT_Container.ue_CapabilityRAT_Container.size, + NRUE_CAPABILITY_INFO); +} + +static void process_lte_nsa_msg(NR_UE_RRC_INST_t *rrc, nsa_msg_t *msg, int msg_len) +{ + if (msg_len < sizeof(msg->msg_type)) { + LOG_E(RRC, "Msg_len = %d\n", msg_len); + return; + } + LOG_D(NR_RRC, "Processing an NSA message\n"); + Rrc_Msg_Type_t msg_type = msg->msg_type; + uint8_t *const msg_buffer = msg->msg_buffer; + msg_len -= sizeof(msg->msg_type); + switch (msg_type) { + case UE_CAPABILITY_ENQUIRY: { + LOG_D(NR_RRC, "We are processing a %d message \n", msg_type); + NR_FreqBandList_t *nr_freq_band_list = NULL; + asn_dec_rval_t dec_rval = uper_decode_complete(NULL, + &asn_DEF_NR_FreqBandList, + (void **)&nr_freq_band_list, + msg_buffer, + msg_len); + if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) { + SEQUENCE_free(&asn_DEF_NR_FreqBandList, nr_freq_band_list, ASFM_FREE_EVERYTHING); + LOG_E(RRC, "Failed to decode UECapabilityInfo (%zu bits)\n", dec_rval.consumed); + break; + } + for (int i = 0; i < nr_freq_band_list->list.count; i++) { + LOG_D(NR_RRC, "Received NR band information: %ld.\n", + nr_freq_band_list->list.array[i]->choice.bandInformationNR->bandNR); + } + int dummy_msg = 0;// whatever piece of data, it will never be used by sendee + LOG_D(NR_RRC, "We are calling nsa_sendmsg_to_lte_ue to send a UE_CAPABILITY_DUMMY\n"); + nsa_sendmsg_to_lte_ue(&dummy_msg, sizeof(dummy_msg), UE_CAPABILITY_DUMMY); + LOG_A(NR_RRC, "Sent initial NRUE Capability response to LTE UE\n"); + break; + } + + case NRUE_CAPABILITY_ENQUIRY: { + LOG_I(NR_RRC, "We are processing a %d message \n", msg_type); + NR_FreqBandList_t *nr_freq_band_list = NULL; + asn_dec_rval_t dec_rval = uper_decode_complete(NULL, + &asn_DEF_NR_FreqBandList, + (void **)&nr_freq_band_list, + msg_buffer, + msg_len); + if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) { + SEQUENCE_free(&asn_DEF_NR_FreqBandList, nr_freq_band_list, ASFM_FREE_EVERYTHING); + LOG_E(NR_RRC, "Failed to decode UECapabilityInfo (%zu bits)\n", dec_rval.consumed); + break; + } + LOG_I(NR_RRC, "Calling nsa_rrc_ue_process_ueCapabilityEnquiry\n"); + nsa_rrc_ue_process_ueCapabilityEnquiry(rrc); + break; + } + + case RRC_MEASUREMENT_PROCEDURE: { + LOG_I(NR_RRC, "We are processing a %d message \n", msg_type); + + LTE_MeasObjectToAddMod_t *nr_meas_obj = NULL; + asn_dec_rval_t dec_rval = uper_decode_complete(NULL, + &asn_DEF_NR_MeasObjectToAddMod, + (void **)&nr_meas_obj, + msg_buffer, + msg_len); + if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) { + SEQUENCE_free(&asn_DEF_NR_MeasObjectToAddMod, nr_meas_obj, ASFM_FREE_EVERYTHING); + LOG_E(RRC, "Failed to decode measurement object (%zu bits) %d\n", dec_rval.consumed, dec_rval.code); + break; + } + LOG_D(NR_RRC, "NR carrierFreq_r15 (ssb): %ld and sub carrier spacing:%ld\n", + nr_meas_obj->measObject.choice.measObjectNR_r15.carrierFreq_r15, + nr_meas_obj->measObject.choice.measObjectNR_r15.rs_ConfigSSB_r15.subcarrierSpacingSSB_r15); + start_oai_nrue_threads(); + break; + } + + case RRC_CONFIG_COMPLETE_REQ: { + struct msg { + uint32_t RadioBearer_size; + uint32_t SecondaryCellGroup_size; + uint8_t trans_id; + uint8_t padding[3]; + uint8_t buffer[]; + } hdr; + AssertFatal(msg_len >= sizeof(hdr), "Bad received msg\n"); + memcpy(&hdr, msg_buffer, sizeof(hdr)); + LOG_I(NR_RRC, "We got an RRC_CONFIG_COMPLETE_REQ\n"); + uint32_t nr_RadioBearer_size = hdr.RadioBearer_size; + uint32_t nr_SecondaryCellGroup_size = hdr.SecondaryCellGroup_size; + AssertFatal(sizeof(hdr) + nr_RadioBearer_size + nr_SecondaryCellGroup_size <= msg_len, + "nr_RadioBearerConfig1_r15 size %u nr_SecondaryCellGroupConfig_r15 size %u sizeof(hdr) %zu, msg_len = %d\n", + nr_RadioBearer_size, + nr_SecondaryCellGroup_size, + sizeof(hdr), + msg_len); + NR_RRC_TransactionIdentifier_t t_id = hdr.trans_id; + LOG_I(NR_RRC, "nr_RadioBearerConfig1_r15 size %d nr_SecondaryCellGroupConfig_r15 size %d t_id %ld\n", + nr_RadioBearer_size, + nr_SecondaryCellGroup_size, + t_id); + + uint8_t *nr_RadioBearer_buffer = msg_buffer + offsetof(struct msg, buffer); + uint8_t *nr_SecondaryCellGroup_buffer = nr_RadioBearer_buffer + nr_RadioBearer_size; + process_nsa_message(get_NR_UE_rrc_inst(0), + nr_SecondaryCellGroupConfig_r15, + nr_SecondaryCellGroup_buffer, + nr_SecondaryCellGroup_size); + process_nsa_message(get_NR_UE_rrc_inst(0), + nr_RadioBearerConfigX_r15, + nr_RadioBearer_buffer, + nr_RadioBearer_size); + LOG_I(NR_RRC, "Calling do_NR_RRCReconfigurationComplete. t_id %ld \n", t_id); + uint8_t buffer[NR_RRC_BUF_SIZE]; + size_t size = do_NR_RRCReconfigurationComplete_for_nsa(buffer, sizeof(buffer), t_id); + nsa_sendmsg_to_lte_ue(buffer, size, NR_RRC_CONFIG_COMPLETE_REQ); + break; + } + + case OAI_TUN_IFACE_NSA: { + LOG_I(NR_RRC, "We got an OAI_TUN_IFACE_NSA!!\n"); + char cmd_line[NR_RRC_BUF_SIZE]; + memcpy(cmd_line, msg_buffer, sizeof(cmd_line)); + LOG_D(NR_RRC, "Command line: %s\n", cmd_line); + if (background_system(cmd_line) != 0) + LOG_E(NR_RRC, "ESM-PROC - failed command '%s'", cmd_line); + break; + } + + default: + LOG_E(NR_RRC, "No NSA Message Found\n"); + } +} + static void nr_rrc_ue_generate_rrcReestablishmentComplete(const NR_UE_RRC_INST_t *rrc, const NR_RRCReestablishment_t *rrcReestablishment) { @@ -2808,163 +2966,6 @@ static void nr_rrc_initiate_rrcReestablishment(NR_UE_RRC_INST_t *rrc, NR_Reestab nr_rrc_send_msg_to_mac(rrc, &rrc_msg); } -static void nsa_rrc_ue_process_ueCapabilityEnquiry(NR_UE_RRC_INST_t *rrc) -{ - NR_UE_NR_Capability_t *UE_Capability_nr = rrc->UECap.UE_NR_Capability = CALLOC(1, sizeof(NR_UE_NR_Capability_t)); - NR_BandNR_t *nr_bandnr = CALLOC(1, sizeof(NR_BandNR_t)); - nr_bandnr->bandNR = 78; - asn1cSeqAdd(&UE_Capability_nr->rf_Parameters.supportedBandListNR.list, nr_bandnr); - OAI_NR_UECapability_t *UECap = CALLOC(1, sizeof(OAI_NR_UECapability_t)); - UECap->UE_NR_Capability = UE_Capability_nr; - - asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_UE_NR_Capability, - NULL, - (void *)UE_Capability_nr, - &UECap->sdu[0], - MAX_UE_NR_CAPABILITY_SIZE); - AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", - enc_rval.failed_type->name, enc_rval.encoded); - UECap->sdu_size = (enc_rval.encoded + 7) / 8; - LOG_A(NR_RRC, "[NR_RRC] NRUE Capability encoded, %d bytes (%zd bits)\n", - UECap->sdu_size, enc_rval.encoded + 7); - - NR_UE_CapabilityRAT_Container_t ue_CapabilityRAT_Container; - memset(&ue_CapabilityRAT_Container, 0, sizeof(NR_UE_CapabilityRAT_Container_t)); - ue_CapabilityRAT_Container.rat_Type = NR_RAT_Type_nr; - OCTET_STRING_fromBuf(&ue_CapabilityRAT_Container.ue_CapabilityRAT_Container, - (const char *)rrc->UECap.sdu, - rrc->UECap.sdu_size); - - nsa_sendmsg_to_lte_ue(ue_CapabilityRAT_Container.ue_CapabilityRAT_Container.buf, - ue_CapabilityRAT_Container.ue_CapabilityRAT_Container.size, - NRUE_CAPABILITY_INFO); -} - -static void process_lte_nsa_msg(NR_UE_RRC_INST_t *rrc, nsa_msg_t *msg, int msg_len) -{ - if (msg_len < sizeof(msg->msg_type)) { - LOG_E(RRC, "Msg_len = %d\n", msg_len); - return; - } - LOG_D(NR_RRC, "Processing an NSA message\n"); - Rrc_Msg_Type_t msg_type = msg->msg_type; - uint8_t *const msg_buffer = msg->msg_buffer; - msg_len -= sizeof(msg->msg_type); - switch (msg_type) { - case UE_CAPABILITY_ENQUIRY: { - LOG_D(NR_RRC, "We are processing a %d message \n", msg_type); - NR_FreqBandList_t *nr_freq_band_list = NULL; - asn_dec_rval_t dec_rval = uper_decode_complete(NULL, - &asn_DEF_NR_FreqBandList, - (void **)&nr_freq_band_list, - msg_buffer, - msg_len); - if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) { - SEQUENCE_free(&asn_DEF_NR_FreqBandList, nr_freq_band_list, ASFM_FREE_EVERYTHING); - LOG_E(RRC, "Failed to decode UECapabilityInfo (%zu bits)\n", dec_rval.consumed); - break; - } - for (int i = 0; i < nr_freq_band_list->list.count; i++) { - LOG_D(NR_RRC, "Received NR band information: %ld.\n", - nr_freq_band_list->list.array[i]->choice.bandInformationNR->bandNR); - } - int dummy_msg = 0;// whatever piece of data, it will never be used by sendee - LOG_D(NR_RRC, "We are calling nsa_sendmsg_to_lte_ue to send a UE_CAPABILITY_DUMMY\n"); - nsa_sendmsg_to_lte_ue(&dummy_msg, sizeof(dummy_msg), UE_CAPABILITY_DUMMY); - LOG_A(NR_RRC, "Sent initial NRUE Capability response to LTE UE\n"); - break; - } - - case NRUE_CAPABILITY_ENQUIRY: { - LOG_I(NR_RRC, "We are processing a %d message \n", msg_type); - NR_FreqBandList_t *nr_freq_band_list = NULL; - asn_dec_rval_t dec_rval = uper_decode_complete(NULL, - &asn_DEF_NR_FreqBandList, - (void **)&nr_freq_band_list, - msg_buffer, - msg_len); - if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) { - SEQUENCE_free(&asn_DEF_NR_FreqBandList, nr_freq_band_list, ASFM_FREE_EVERYTHING); - LOG_E(NR_RRC, "Failed to decode UECapabilityInfo (%zu bits)\n", dec_rval.consumed); - break; - } - LOG_I(NR_RRC, "Calling nsa_rrc_ue_process_ueCapabilityEnquiry\n"); - nsa_rrc_ue_process_ueCapabilityEnquiry(rrc); - break; - } - - case RRC_MEASUREMENT_PROCEDURE: { - LOG_I(NR_RRC, "We are processing a %d message \n", msg_type); - - LTE_MeasObjectToAddMod_t *nr_meas_obj = NULL; - asn_dec_rval_t dec_rval = uper_decode_complete(NULL, - &asn_DEF_NR_MeasObjectToAddMod, - (void **)&nr_meas_obj, - msg_buffer, - msg_len); - if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) { - SEQUENCE_free(&asn_DEF_NR_MeasObjectToAddMod, nr_meas_obj, ASFM_FREE_EVERYTHING); - LOG_E(RRC, "Failed to decode measurement object (%zu bits) %d\n", dec_rval.consumed, dec_rval.code); - break; - } - LOG_D(NR_RRC, "NR carrierFreq_r15 (ssb): %ld and sub carrier spacing:%ld\n", - nr_meas_obj->measObject.choice.measObjectNR_r15.carrierFreq_r15, - nr_meas_obj->measObject.choice.measObjectNR_r15.rs_ConfigSSB_r15.subcarrierSpacingSSB_r15); - start_oai_nrue_threads(); - break; - } - - case RRC_CONFIG_COMPLETE_REQ: { - struct msg { - uint32_t RadioBearer_size; - uint32_t SecondaryCellGroup_size; - uint8_t trans_id; - uint8_t padding[3]; - uint8_t buffer[]; - } hdr; - AssertFatal(msg_len >= sizeof(hdr), "Bad received msg\n"); - memcpy(&hdr, msg_buffer, sizeof(hdr)); - LOG_I(NR_RRC, "We got an RRC_CONFIG_COMPLETE_REQ\n"); - uint32_t nr_RadioBearer_size = hdr.RadioBearer_size; - uint32_t nr_SecondaryCellGroup_size = hdr.SecondaryCellGroup_size; - AssertFatal(sizeof(hdr) + nr_RadioBearer_size + nr_SecondaryCellGroup_size <= msg_len, - "nr_RadioBearerConfig1_r15 size %u nr_SecondaryCellGroupConfig_r15 size %u sizeof(hdr) %zu, msg_len = %d\n", - nr_RadioBearer_size, - nr_SecondaryCellGroup_size, - sizeof(hdr), - msg_len); - NR_RRC_TransactionIdentifier_t t_id = hdr.trans_id; - LOG_I(NR_RRC, "nr_RadioBearerConfig1_r15 size %d nr_SecondaryCellGroupConfig_r15 size %d t_id %ld\n", - nr_RadioBearer_size, - nr_SecondaryCellGroup_size, - t_id); - - uint8_t *nr_RadioBearer_buffer = msg_buffer + offsetof(struct msg, buffer); - uint8_t *nr_SecondaryCellGroup_buffer = nr_RadioBearer_buffer + nr_RadioBearer_size; - process_nsa_message(get_NR_UE_rrc_inst(0), nr_SecondaryCellGroupConfig_r15, nr_SecondaryCellGroup_buffer, nr_SecondaryCellGroup_size); - process_nsa_message(get_NR_UE_rrc_inst(0), nr_RadioBearerConfigX_r15, nr_RadioBearer_buffer, nr_RadioBearer_size); - LOG_I(NR_RRC, "Calling do_NR_RRCReconfigurationComplete. t_id %ld \n", t_id); - uint8_t buffer[NR_RRC_BUF_SIZE]; - size_t size = do_NR_RRCReconfigurationComplete_for_nsa(buffer, sizeof(buffer), t_id); - nsa_sendmsg_to_lte_ue(buffer, size, NR_RRC_CONFIG_COMPLETE_REQ); - break; - } - - case OAI_TUN_IFACE_NSA: { - LOG_I(NR_RRC, "We got an OAI_TUN_IFACE_NSA!!\n"); - char cmd_line[NR_RRC_BUF_SIZE]; - memcpy(cmd_line, msg_buffer, sizeof(cmd_line)); - LOG_D(NR_RRC, "Command line: %s\n", cmd_line); - if (background_system(cmd_line) != 0) - LOG_E(NR_RRC, "ESM-PROC - failed command '%s'", cmd_line); - break; - } - - default: - LOG_E(NR_RRC, "No NSA Message Found\n"); - } -} - void handle_RRCRelease(NR_UE_RRC_INST_t *rrc) { NR_UE_Timers_Constants_t *tac = &rrc->timers_and_constants; From faf230612bbaf8e232d77b4447232d2765d12fdf Mon Sep 17 00:00:00 2001 From: francescomani Date: Wed, 24 Sep 2025 10:30:08 +0200 Subject: [PATCH 774/964] move nr_rrc_ue_process_ueCapabilityEnquiry before usage --- openair2/RRC/NR_UE/rrc_UE.c | 137 ++++++++++++++++++------------------ 1 file changed, 67 insertions(+), 70 deletions(-) diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 661221a458..b052d089eb 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -134,7 +134,6 @@ static const char nr_nas_attach_req_imsi_dummy_NSA_case[] = { 0x11, }; -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, @@ -2373,6 +2372,73 @@ static void nr_rrc_ue_process_rrcReestablishment(NR_UE_RRC_INST_t *rrc, nr_rrc_ue_generate_rrcReestablishmentComplete(rrc, rrcReestablishment); } +static void nr_rrc_ue_process_ueCapabilityEnquiry(NR_UE_RRC_INST_t *rrc, NR_UECapabilityEnquiry_t *UECapabilityEnquiry) +{ + NR_UL_DCCH_Message_t ul_dcch_msg = {0}; + LOG_I(NR_RRC, "Receiving from SRB1 (DL-DCCH), Processing UECapabilityEnquiry\n"); + + ul_dcch_msg.message.present = NR_UL_DCCH_MessageType_PR_c1; + asn1cCalloc(ul_dcch_msg.message.choice.c1, c1); + c1->present = NR_UL_DCCH_MessageType__c1_PR_ueCapabilityInformation; + asn1cCalloc(c1->choice.ueCapabilityInformation, info); + info->rrc_TransactionIdentifier = UECapabilityEnquiry->rrc_TransactionIdentifier; + if (!rrc->UECap.UE_NR_Capability) { + rrc->UECap.UE_NR_Capability = CALLOC(1, sizeof(NR_UE_NR_Capability_t)); + asn1cSequenceAdd(rrc->UECap.UE_NR_Capability->rf_Parameters.supportedBandListNR.list, NR_BandNR_t, nr_bandnr); + nr_bandnr->bandNR = 1; + } + xer_fprint(stdout, &asn_DEF_NR_UE_NR_Capability, (void *)rrc->UECap.UE_NR_Capability); + + asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_UE_NR_Capability, + NULL, + (void *)rrc->UECap.UE_NR_Capability, + &rrc->UECap.sdu[0], + MAX_UE_NR_CAPABILITY_SIZE); + AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", enc_rval.failed_type->name, enc_rval.encoded); + rrc->UECap.sdu_size = (enc_rval.encoded + 7) / 8; + LOG_I(PHY, "[RRC]UE NR Capability encoded, %d bytes (%zd bits)\n", rrc->UECap.sdu_size, enc_rval.encoded + 7); + /* RAT Container */ + NR_UE_CapabilityRAT_Container_t *ue_CapabilityRAT_Container = CALLOC(1, sizeof(NR_UE_CapabilityRAT_Container_t)); + ue_CapabilityRAT_Container->rat_Type = NR_RAT_Type_nr; + OCTET_STRING_fromBuf(&ue_CapabilityRAT_Container->ue_CapabilityRAT_Container, (const char *)rrc->UECap.sdu, rrc->UECap.sdu_size); + NR_UECapabilityEnquiry_IEs_t *ueCapabilityEnquiry_ie = UECapabilityEnquiry->criticalExtensions.choice.ueCapabilityEnquiry; + if (get_softmodem_params()->nsa == 1) { + OCTET_STRING_t *requestedFreqBandsNR = ueCapabilityEnquiry_ie->ue_CapabilityEnquiryExt; + nsa_sendmsg_to_lte_ue(requestedFreqBandsNR->buf, requestedFreqBandsNR->size, UE_CAPABILITY_INFO); + } + // ue_CapabilityRAT_Container.ueCapabilityRAT_Container.buf = UE_rrc_inst[ue_mod_idP].UECapability; + // ue_CapabilityRAT_Container.ueCapabilityRAT_Container.size = UE_rrc_inst[ue_mod_idP].UECapability_size; + AssertFatal(UECapabilityEnquiry->criticalExtensions.present == NR_UECapabilityEnquiry__criticalExtensions_PR_ueCapabilityEnquiry, + "UECapabilityEnquiry->criticalExtensions.present (%d) != UECapabilityEnquiry__criticalExtensions_PR_c1 (%d)\n", + UECapabilityEnquiry->criticalExtensions.present,NR_UECapabilityEnquiry__criticalExtensions_PR_ueCapabilityEnquiry); + + NR_UECapabilityInformation_t *ueCapabilityInformation = ul_dcch_msg.message.choice.c1->choice.ueCapabilityInformation; + ueCapabilityInformation->criticalExtensions.present = NR_UECapabilityInformation__criticalExtensions_PR_ueCapabilityInformation; + asn1cCalloc(ueCapabilityInformation->criticalExtensions.choice.ueCapabilityInformation, infoIE); + asn1cCalloc(infoIE->ue_CapabilityRAT_ContainerList, UEcapList); + UEcapList->list.count = 0; + + for (int i = 0; i < ueCapabilityEnquiry_ie->ue_CapabilityRAT_RequestList.list.count; i++) { + if (ueCapabilityEnquiry_ie->ue_CapabilityRAT_RequestList.list.array[i]->rat_Type == NR_RAT_Type_nr) { + asn1cSeqAdd(&UEcapList->list, ue_CapabilityRAT_Container); + uint8_t buffer[500]; + asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_UL_DCCH_Message, NULL, (void *)&ul_dcch_msg, buffer, 500); + AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %jd)!\n", enc_rval.failed_type->name, enc_rval.encoded); + + if (LOG_DEBUGFLAG(DEBUG_ASN1)) { + xer_fprint(stdout, &asn_DEF_NR_UL_DCCH_Message, (void *)&ul_dcch_msg); + } + LOG_I(NR_RRC, "UECapabilityInformation Encoded %zd bits (%zd bytes)\n", enc_rval.encoded, (enc_rval.encoded + 7) / 8); + int srb_id = 1; // UECapabilityInformation on SRB1 + nr_pdcp_data_req_srb(rrc->ue_id, srb_id, 0, (enc_rval.encoded + 7) / 8, buffer, deliver_pdu_srb_rlc, NULL); + } + } + /* Free struct members after it's done + including locally allocated ue_CapabilityRAT_Container */ + ASN_STRUCT_RESET(asn_DEF_NR_UL_DCCH_Message, &ul_dcch_msg); +} + + static int nr_rrc_ue_decode_dcch(NR_UE_RRC_INST_t *rrc, const srb_id_t Srb_id, const uint8_t *const Buffer, @@ -2858,75 +2924,6 @@ void nr_rrc_ue_process_sidelink_radioResourceConfig(NR_SetupRelease_SL_ConfigDed } } -static void nr_rrc_ue_process_ueCapabilityEnquiry(NR_UE_RRC_INST_t *rrc, NR_UECapabilityEnquiry_t *UECapabilityEnquiry) -{ - NR_UL_DCCH_Message_t ul_dcch_msg = {0}; - // - LOG_I(NR_RRC, "Receiving from SRB1 (DL-DCCH), Processing UECapabilityEnquiry\n"); - - ul_dcch_msg.message.present = NR_UL_DCCH_MessageType_PR_c1; - asn1cCalloc(ul_dcch_msg.message.choice.c1, c1); - c1->present = NR_UL_DCCH_MessageType__c1_PR_ueCapabilityInformation; - asn1cCalloc(c1->choice.ueCapabilityInformation, info); - info->rrc_TransactionIdentifier = UECapabilityEnquiry->rrc_TransactionIdentifier; - if (!rrc->UECap.UE_NR_Capability) { - rrc->UECap.UE_NR_Capability = CALLOC(1, sizeof(NR_UE_NR_Capability_t)); - asn1cSequenceAdd(rrc->UECap.UE_NR_Capability->rf_Parameters.supportedBandListNR.list, NR_BandNR_t, nr_bandnr); - nr_bandnr->bandNR = 1; - } - xer_fprint(stdout, &asn_DEF_NR_UE_NR_Capability, (void *)rrc->UECap.UE_NR_Capability); - - asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_UE_NR_Capability, - NULL, - (void *)rrc->UECap.UE_NR_Capability, - &rrc->UECap.sdu[0], - MAX_UE_NR_CAPABILITY_SIZE); - AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", - enc_rval.failed_type->name, enc_rval.encoded); - rrc->UECap.sdu_size = (enc_rval.encoded + 7) / 8; - LOG_I(PHY, "[RRC]UE NR Capability encoded, %d bytes (%zd bits)\n", rrc->UECap.sdu_size, enc_rval.encoded + 7); - /* RAT Container */ - NR_UE_CapabilityRAT_Container_t *ue_CapabilityRAT_Container = CALLOC(1, sizeof(NR_UE_CapabilityRAT_Container_t)); - ue_CapabilityRAT_Container->rat_Type = NR_RAT_Type_nr; - OCTET_STRING_fromBuf(&ue_CapabilityRAT_Container->ue_CapabilityRAT_Container, (const char *)rrc->UECap.sdu, rrc->UECap.sdu_size); - NR_UECapabilityEnquiry_IEs_t *ueCapabilityEnquiry_ie = UECapabilityEnquiry->criticalExtensions.choice.ueCapabilityEnquiry; - if (get_softmodem_params()->nsa == 1) { - OCTET_STRING_t *requestedFreqBandsNR = ueCapabilityEnquiry_ie->ue_CapabilityEnquiryExt; - nsa_sendmsg_to_lte_ue(requestedFreqBandsNR->buf, requestedFreqBandsNR->size, UE_CAPABILITY_INFO); - } - // ue_CapabilityRAT_Container.ueCapabilityRAT_Container.buf = UE_rrc_inst[ue_mod_idP].UECapability; - // ue_CapabilityRAT_Container.ueCapabilityRAT_Container.size = UE_rrc_inst[ue_mod_idP].UECapability_size; - AssertFatal(UECapabilityEnquiry->criticalExtensions.present == NR_UECapabilityEnquiry__criticalExtensions_PR_ueCapabilityEnquiry, - "UECapabilityEnquiry->criticalExtensions.present (%d) != UECapabilityEnquiry__criticalExtensions_PR_c1 (%d)\n", - UECapabilityEnquiry->criticalExtensions.present,NR_UECapabilityEnquiry__criticalExtensions_PR_ueCapabilityEnquiry); - - NR_UECapabilityInformation_t *ueCapabilityInformation = ul_dcch_msg.message.choice.c1->choice.ueCapabilityInformation; - ueCapabilityInformation->criticalExtensions.present = NR_UECapabilityInformation__criticalExtensions_PR_ueCapabilityInformation; - asn1cCalloc(ueCapabilityInformation->criticalExtensions.choice.ueCapabilityInformation, infoIE); - asn1cCalloc(infoIE->ue_CapabilityRAT_ContainerList, UEcapList); - UEcapList->list.count = 0; - - for (int i = 0; i < ueCapabilityEnquiry_ie->ue_CapabilityRAT_RequestList.list.count; i++) { - if (ueCapabilityEnquiry_ie->ue_CapabilityRAT_RequestList.list.array[i]->rat_Type == NR_RAT_Type_nr) { - asn1cSeqAdd(&UEcapList->list, ue_CapabilityRAT_Container); - uint8_t buffer[500]; - asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_UL_DCCH_Message, NULL, (void *)&ul_dcch_msg, buffer, 500); - AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %jd)!\n", - enc_rval.failed_type->name, enc_rval.encoded); - - if (LOG_DEBUGFLAG(DEBUG_ASN1)) { - xer_fprint(stdout, &asn_DEF_NR_UL_DCCH_Message, (void *)&ul_dcch_msg); - } - LOG_I(NR_RRC, "UECapabilityInformation Encoded %zd bits (%zd bytes)\n",enc_rval.encoded,(enc_rval.encoded+7)/8); - int srb_id = 1; // UECapabilityInformation on SRB1 - nr_pdcp_data_req_srb(rrc->ue_id, srb_id, 0, (enc_rval.encoded + 7) / 8, buffer, deliver_pdu_srb_rlc, NULL); - } - } - /* Free struct members after it's done - including locally allocated ue_CapabilityRAT_Container */ - ASN_STRUCT_RESET(asn_DEF_NR_UL_DCCH_Message, &ul_dcch_msg); -} - static void nr_rrc_initiate_rrcReestablishment(NR_UE_RRC_INST_t *rrc, NR_ReestablishmentCause_t cause) { rrc->reestablishment_cause = cause; From 24ac0b5602ebf5f9b6902130275dc124124e4f5a Mon Sep 17 00:00:00 2001 From: francescomani Date: Wed, 24 Sep 2025 10:31:40 +0200 Subject: [PATCH 775/964] move nr_rrc_ue_process_masterCellGroup before usage --- openair2/RRC/NR_UE/rrc_UE.c | 61 +++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 33 deletions(-) diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index b052d089eb..238e1a72e0 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -134,11 +134,6 @@ static const char nr_nas_attach_req_imsi_dummy_NSA_case[] = { 0x11, }; -static void nr_rrc_ue_process_masterCellGroup(NR_UE_RRC_INST_t *rrc, - OCTET_STRING_t *masterCellGroup, - long *fullConfig, - int gNB_index); - /** * @brief Sends an RRC message to the connected UE MAC instance. * @@ -723,6 +718,34 @@ static void nr_rrc_ue_process_RadioBearerConfig(NR_UE_RRC_INST_t *ue_rrc, NR_Rad LOG_I(NR_RRC, "State = NR_RRC_CONNECTED\n"); } +static void nr_rrc_ue_process_masterCellGroup(NR_UE_RRC_INST_t *rrc, + OCTET_STRING_t *masterCellGroup, + long *fullConfig, + int gNB_index) +{ + AssertFatal(!fullConfig, "fullConfig not supported yet\n"); + NR_CellGroupConfig_t *cellGroupConfig = NULL; + uper_decode(NULL, + &asn_DEF_NR_CellGroupConfig, //might be added prefix later + (void **)&cellGroupConfig, + (uint8_t *)masterCellGroup->buf, + masterCellGroup->size, 0, 0); + + if (LOG_DEBUGFLAG(DEBUG_ASN1)) { + xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void *) cellGroupConfig); + } + + nr_rrc_cellgroup_configuration(rrc, cellGroupConfig, gNB_index); + + LOG_D(RRC, "Sending CellGroupConfig to MAC the pointer will be managed by mac\n"); + nr_mac_rrc_message_t rrc_msg = {0}; + rrc_msg.payload_type = NR_MAC_RRC_CONFIG_CG; + nr_mac_rrc_config_cg_t *mac_msg = &rrc_msg.payload.config_cg; + mac_msg->cellGroupConfig = cellGroupConfig; + mac_msg->UE_NR_Capability = rrc->UECap.UE_NR_Capability; + nr_rrc_send_msg_to_mac(rrc, &rrc_msg); +} + static void nr_rrc_process_reconfiguration_v1530(NR_UE_RRC_INST_t *rrc, NR_RRCReconfiguration_v1530_IEs_t *rec_1530, int gNB_index) { if (rec_1530->fullConfig) { @@ -1717,34 +1740,6 @@ 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, - int gNB_index) -{ - AssertFatal(!fullConfig, "fullConfig not supported yet\n"); - NR_CellGroupConfig_t *cellGroupConfig = NULL; - uper_decode(NULL, - &asn_DEF_NR_CellGroupConfig, //might be added prefix later - (void **)&cellGroupConfig, - (uint8_t *)masterCellGroup->buf, - masterCellGroup->size, 0, 0); - - if (LOG_DEBUGFLAG(DEBUG_ASN1)) { - xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void *) cellGroupConfig); - } - - nr_rrc_cellgroup_configuration(rrc, cellGroupConfig, gNB_index); - - LOG_D(RRC, "Sending CellGroupConfig to MAC the pointer will be managed by mac\n"); - nr_mac_rrc_message_t rrc_msg = {0}; - rrc_msg.payload_type = NR_MAC_RRC_CONFIG_CG; - nr_mac_rrc_config_cg_t *mac_msg = &rrc_msg.payload.config_cg; - mac_msg->cellGroupConfig = cellGroupConfig; - mac_msg->UE_NR_Capability = rrc->UECap.UE_NR_Capability; - nr_rrc_send_msg_to_mac(rrc, &rrc_msg); -} - static void rrc_ue_generate_RRCSetupComplete(const NR_UE_RRC_INST_t *rrc, const uint8_t Transaction_id) { uint8_t buffer[100]; From 609700207fc2959c07c55f9f1f49473d9a78fdfc Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Tue, 23 Sep 2025 23:12:43 +0200 Subject: [PATCH 776/964] Fix handover required: set pdusession_id in pdu_info structure for consistency --- openair2/RRC/NR/rrc_gNB_NGAP.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index bdaa3e170e..6b6c579071 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -1609,17 +1609,19 @@ void rrc_gNB_send_NGAP_HANDOVER_REQUIRED(gNB_RRC_INST *rrc, rrc_pdu_session_param_t *pduSession = find_pduSession(UE, UE->pduSession[i].param.pdusession_id, false); if (!pduSession) continue; + pdusession_t *session = &pduSession->param; // Handover Required Transfer (M) uint8_t ho_required_transfer[128] = {0}; msg.pdusessions[i].ho_required_transfer.buf = ho_required_transfer; msg.pdusessions[i].ho_required_transfer.len = sizeof(ho_required_transfer); // PDU Session ID - msg.pdusessions[i].pdusession_id = pduSession->param.pdusession_id; - + msg.pdusessions[i].pdusession_id = session->pdusession_id; // PDU Session Resource Information List (O) - msg.source2target->pdu_session_resource[i].nb_of_qos_flow = pduSession->param.nb_qos; - for (int j = 0; j < pduSession->param.nb_qos; ++j) { - msg.source2target->pdu_session_resource[i].qos_flow_info[j].qfi = pduSession->param.qos[j].qfi; + pdusession_resource_info_t *pdu_info = &msg.source2target->pdu_session_resource[msg.source2target->nb_pdu_session_resource++]; + pdu_info->pdusession_id = session->pdusession_id; + pdu_info->nb_of_qos_flow = session->nb_qos; + for (int j = 0; j < session->nb_qos; ++j) { + pdu_info->qos_flow_info[j].qfi = session->qos[j].qfi; } msg.source2target->nb_pdu_session_resource++; } From 9a4fd1bf769f7162101ecf0cffc4fa3bf0b4403b Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 24 Sep 2025 14:34:46 +0200 Subject: [PATCH 777/964] Cleanup handover required transfer IE Previously, the RRC layer was incorrectly allocating stack memory for the ho_required_transfer field and passing it to NGAP, however it was not used. The IE is mandatory but contains only 1 optional IE, therefore is encoded in the NG message with empty content. Changes: - Remove unnecessary ho_required_transfer field from pdusession_resource_t definition, the IE is encoded anyway with empty content. If Direct Forwarding Path Availability is needed at any stage in the future it can be added to pdusession_resource_t and filled in RRC. - Add clarifying comment about empty HandoverRequiredTransfer structure --- openair2/COMMON/ngap_messages_types.h | 2 -- openair2/RRC/NR/rrc_gNB_NGAP.c | 4 ---- openair3/NGAP/ngap_gNB_mobility_management.c | 4 +++- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/openair2/COMMON/ngap_messages_types.h b/openair2/COMMON/ngap_messages_types.h index c4bafcee85..d5a5aca5aa 100644 --- a/openair2/COMMON/ngap_messages_types.h +++ b/openair2/COMMON/ngap_messages_types.h @@ -545,8 +545,6 @@ typedef enum { typedef struct { // PDU Session ID uint8_t pdusession_id; - // Handover Required Transfer - byte_array_t ho_required_transfer; } pdusession_resource_t; /* 3GPP TS 38.413 9.2.3.1 */ diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index 6b6c579071..dba6fde8ae 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -1610,10 +1610,6 @@ void rrc_gNB_send_NGAP_HANDOVER_REQUIRED(gNB_RRC_INST *rrc, if (!pduSession) continue; pdusession_t *session = &pduSession->param; - // Handover Required Transfer (M) - uint8_t ho_required_transfer[128] = {0}; - msg.pdusessions[i].ho_required_transfer.buf = ho_required_transfer; - msg.pdusessions[i].ho_required_transfer.len = sizeof(ho_required_transfer); // PDU Session ID msg.pdusessions[i].pdusession_id = session->pdusession_id; // PDU Session Resource Information List (O) diff --git a/openair3/NGAP/ngap_gNB_mobility_management.c b/openair3/NGAP/ngap_gNB_mobility_management.c index bfea97c8ff..a6ff4b39a1 100644 --- a/openair3/NGAP/ngap_gNB_mobility_management.c +++ b/openair3/NGAP/ngap_gNB_mobility_management.c @@ -88,7 +88,9 @@ NGAP_NGAP_PDU_t *encode_ng_handover_required(const ngap_handover_required_t *msg asn1cSequenceAdd(ie6->value.choice.PDUSessionResourceListHORqd.list, NGAP_PDUSessionResourceItemHORqd_t, hoRequiredPduSession); // PDU Session ID (M) hoRequiredPduSession->pDUSessionID = msg->pdusessions[i].pdusession_id; - // Handover Required Transfer (M) + // Handover Required Transfer (M) - ASN.1 encoding of empty transfer structure + // This is a mandatory field in the NGAP Handover Required message, however it contains + // only Direct Forwarding Path Availability IE, which is optional and is not sent NGAP_HandoverRequiredTransfer_t hoRequiredTransfer = {0}; uint8_t ho_req_transfer_transparent_container_buffer[128] = {0}; if (LOG_DEBUGFLAG(DEBUG_ASN1)) From 42a9f2f08fef426b8da326dca99793101927e2e8 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Mon, 22 Sep 2025 22:42:33 +0200 Subject: [PATCH 778/964] Enable multiple PDU Sessions in handover request logic - Process all PDU sessions in handover request instead of only the first one - Add DevAssert for bounds checking on nb_of_pdusessions - Fix logic error where multiple PDU sessions were ignored in handover scenarios --- openair2/RRC/NR/rrc_gNB_NGAP.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index dba6fde8ae..77682998f4 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -1138,14 +1138,19 @@ int rrc_gNB_process_Handover_Request(gNB_RRC_INST *rrc, instance_t instance, nga activate_srb(UE, SRB2); nr_rrc_pdcp_config_security(UE, false); - // Copy PDU Session Resource Setup item to RRC struct and do PDU Session Resource Setup procedure - pdusession_t to_setup = { - .nssai = msg->pduSessionResourceSetupList->nssai, - .pdu_session_type = msg->pduSessionResourceSetupList->pdu_session_type , - .pdusession_id = msg->pduSessionResourceSetupList->pdusession_id, - }; - cp_pdusession_transfer_to_pdusession(&to_setup, &msg->pduSessionResourceSetupList->pdusessionTransfer); - if (!trigger_bearer_setup(rrc, UE, msg->nb_of_pdusessions, &to_setup, msg->ue_ambr.br_dl)) { + // Process all PDU Session Resource Setup items from handover request + DevAssert(msg->nb_of_pdusessions <= NGAP_MAX_PDU_SESSION); + pdusession_t to_setup[NGAP_MAX_PDU_SESSION]; + for (int i = 0; i < msg->nb_of_pdusessions; i++) { + ho_request_pdusession_t *ho_pdu = &msg->pduSessionResourceSetupList[i]; + pdusession_t *pdu = &to_setup[i]; + pdu->nssai = ho_pdu->nssai; + pdu->pdu_session_type = ho_pdu->pdu_session_type; + pdu->pdusession_id = ho_pdu->pdusession_id; + cp_pdusession_transfer_to_pdusession(pdu, &ho_pdu->pdusessionTransfer); + } + + if (!trigger_bearer_setup(rrc, UE, msg->nb_of_pdusessions, to_setup, msg->ue_ambr.br_dl)) { LOG_E(NR_RRC, "Failed to establish PDU session: handover failed\n"); ngap_handover_failure_t fail = { .amf_ue_ngap_id = msg->amf_ue_ngap_id, From ae1de1aeaa244da8fb064f53ea3adb3be69f49ff Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Tue, 22 Jul 2025 16:28:25 +0200 Subject: [PATCH 779/964] Refactoring: fix inconsistency in nr_sdap_delete_entity The function was printing a "not found" error message even in the case the return value was set to "true". Return directly true/false. This is relevant in PDU Session Release procedures. --- openair2/SDAP/nr_sdap/nr_sdap_entity.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/openair2/SDAP/nr_sdap/nr_sdap_entity.c b/openair2/SDAP/nr_sdap/nr_sdap_entity.c index 7f2f3dd07c..6860fba6e6 100644 --- a/openair2/SDAP/nr_sdap/nr_sdap_entity.c +++ b/openair2/SDAP/nr_sdap/nr_sdap_entity.c @@ -577,12 +577,11 @@ bool nr_sdap_delete_entity(ue_id_t ue_id, int pdusession_id) { nr_sdap_entity_t *entityPtr = sdap_info.sdap_entity_llist; nr_sdap_entity_t *entityPrev = NULL; - bool ret = false; int upperBound = 0; if (entityPtr == NULL && (pdusession_id) * (pdusession_id - NGAP_MAX_PDU_SESSION) > 0) { LOG_E(SDAP, "SDAP entities not established or Invalid range of pdusession_id [0, 256].\n"); - return ret; + return false; } LOG_D(SDAP, "Deleting SDAP entity for UE %lx and PDU Session id %d\n", ue_id, entityPtr->pdusession_id); @@ -592,7 +591,7 @@ bool nr_sdap_delete_entity(ue_id_t ue_id, int pdusession_id) remove_ip_if(entityPtr); free(entityPtr); LOG_D(SDAP, "Successfully deleted Entity.\n"); - ret = true; + return true; } else { while ((entityPtr->ue_id != ue_id || entityPtr->pdusession_id != pdusession_id) && entityPtr->next_entity != NULL && upperBound < SDAP_MAX_NUM_OF_ENTITIES) { @@ -608,11 +607,11 @@ bool nr_sdap_delete_entity(ue_id_t ue_id, int pdusession_id) } free(entityPtr); LOG_D(SDAP, "Successfully deleted Entity.\n"); - ret = true; + return true; } } LOG_E(SDAP, "Entity does not exist or it was not found.\n"); - return ret; + return false; } bool nr_sdap_delete_ue_entities(ue_id_t ue_id) From bd41e8f883f9b15b3d8328ac272dbb087bc9bdd4 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Thu, 14 Aug 2025 12:57:04 +0200 Subject: [PATCH 780/964] Refactoring: limit scope of config_pdcp to config module --- openair2/GNB_APP/gnb_config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 55110fc449..292fbfdab0 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -1344,7 +1344,7 @@ void config_rlc(configmodule_interface_t *cfg, nr_rlc_configuration_t *rlc_confi rlc_config->drb_um.sn_field_length = config_get_processedint(cfg, &rlc_drb_um_params[CONFIG_NR_RLC_DRB_UM_SN_FIELD_LENGTH_IDX]); } -void config_pdcp(configmodule_interface_t *cfg, nr_pdcp_configuration_t *pdcp_config) +static void config_pdcp(configmodule_interface_t *cfg, nr_pdcp_configuration_t *pdcp_config) { /* DRB configuration */ paramdef_t pdcp_params[] = NR_PDCP_DRB_GLOBALPARAMS_DESC; From e4a910f0bbfc465f33516f49662140725ca464d7 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Thu, 28 Aug 2025 09:58:22 +0200 Subject: [PATCH 781/964] Refactoring: add utility function to fill NG PDU Session Setup item * fills from stored setup PDU Session in RRC list * reduces duplicated code --- openair2/RRC/NR/rrc_gNB_NGAP.c | 44 ++++++++++++++++------------------ 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index 77682998f4..a087942837 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -493,6 +493,25 @@ static gtpu_tunnel_t cp_gtp_tunnel(const gtpu_tunnel_t in) return out; } +/** @brief Fill NG PDU Session Setup item from stored setup PDU Session in RRC list */ +static pdusession_setup_t fill_ngap_pdusession_setup(pdusession_t *session) +{ + DevAssert(session != NULL); + pdusession_setup_t out = {0}; + out.pdusession_id = session->pdusession_id; + out.pdu_session_type = session->pdu_session_type; + out.n3_outgoing = cp_gtp_tunnel(session->n3_outgoing); + out.nb_of_qos_flow = session->nb_qos; + for (int q = 0; q < session->nb_qos; q++) { + out.associated_qos_flows[q].qfi = session->qos[q].qfi; + out.associated_qos_flows[q].qos_flow_mapping_ind = QOSFLOW_MAPPING_INDICATION_DL; + } + char ip_str[INET_ADDRSTRLEN] = {0}; + inet_ntop(AF_INET, out.n3_outgoing.addr.buffer, ip_str, sizeof(ip_str)); + LOG_I(NR_RRC, "PDU Session Setup: ID=%d, outgoing TEID=0x%08x, Addr=%s\n", out.pdusession_id, out.n3_outgoing.teid, ip_str); + return out; +} + void rrc_gNB_send_NGAP_INITIAL_CONTEXT_SETUP_RESP(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE) { MessageDef *msg_p = NULL; @@ -506,14 +525,7 @@ void rrc_gNB_send_NGAP_INITIAL_CONTEXT_SETUP_RESP(gNB_RRC_INST *rrc, gNB_RRC_UE_ for (int pdusession = 0; pdusession < UE->nb_of_pdusessions; pdusession++) { rrc_pdu_session_param_t *session = &UE->pduSession[pdusession]; if (session->status == PDU_SESSION_STATUS_DONE) { - pdu_sessions_done++; - resp->pdusessions[pdusession].pdusession_id = session->param.pdusession_id; - resp->pdusessions[pdusession].n3_outgoing = cp_gtp_tunnel(session->param.n3_outgoing); - resp->pdusessions[pdusession].nb_of_qos_flow = session->param.nb_qos; - for (int qos_flow_index = 0; qos_flow_index < session->param.nb_qos; qos_flow_index++) { - resp->pdusessions[pdusession].associated_qos_flows[qos_flow_index].qfi = session->param.qos[qos_flow_index].qfi; - resp->pdusessions[pdusession].associated_qos_flows[qos_flow_index].qos_flow_mapping_ind = QOSFLOW_MAPPING_INDICATION_DL; - } + resp->pdusessions[pdu_sessions_done++] = fill_ngap_pdusession_setup(&session->param); } else if (session->status != PDU_SESSION_STATUS_ESTABLISHED) { session->status = PDU_SESSION_STATUS_FAILED; ngap_cause_t cause = {.type = NGAP_CAUSE_RADIO_NETWORK, .value = NGAP_CAUSE_RADIO_NETWORK_UNKNOWN_PDU_SESSION_ID}; @@ -696,22 +708,8 @@ void rrc_gNB_send_NGAP_PDUSESSION_SETUP_RESP(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE for (int pdusession = 0; pdusession < UE->nb_of_pdusessions; pdusession++) { rrc_pdu_session_param_t *session = &UE->pduSession[pdusession]; if (session->status == PDU_SESSION_STATUS_DONE) { - pdusession_setup_t *tmp = &resp->pdusessions[pdu_sessions_done]; - tmp->pdusession_id = session->param.pdusession_id; - tmp->nb_of_qos_flow = session->param.nb_qos; - tmp->n3_outgoing = cp_gtp_tunnel(session->param.n3_outgoing); - tmp->pdu_session_type = session->param.pdu_session_type; - - for (int qos_flow_index = 0; qos_flow_index < tmp->nb_of_qos_flow; qos_flow_index++) { - tmp->associated_qos_flows[qos_flow_index].qfi = session->param.qos[qos_flow_index].qfi; - tmp->associated_qos_flows[qos_flow_index].qos_flow_mapping_ind = QOSFLOW_MAPPING_INDICATION_DL; - } - + resp->pdusessions[pdu_sessions_done++] = fill_ngap_pdusession_setup(&session->param); session->status = PDU_SESSION_STATUS_ESTABLISHED; - char ip_str[INET_ADDRSTRLEN] = {0}; - inet_ntop(AF_INET, tmp->n3_outgoing.addr.buffer, ip_str, sizeof(ip_str)); - LOG_I(NR_RRC, "PDU Session Setup Response: ID=%d, outgoing TEID=0x%08x, Addr=%s\n", tmp->pdusession_id, tmp->n3_outgoing.teid, ip_str); - pdu_sessions_done++; } else if (session->status != PDU_SESSION_STATUS_ESTABLISHED) { session->status = PDU_SESSION_STATUS_FAILED; pdusession_failed_t *fail = &resp->pdusessions_failed[pdu_sessions_failed]; From 5bcc9b9e5e5c524a75ab3cfaa5584bc72ee643ce Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Tue, 22 Jul 2025 16:25:41 +0200 Subject: [PATCH 782/964] Adopt dynamic seq_arr in PDU Session handling (RRC PDU Session) The RRC PDU Session struct is converted from a fixed-size array to a dynamically sized seq_arr. This improves flexibility and simplifies session management by eliminating arbitrary size limits and enabling dynamic addition/removal of PDU sessions. Helper functions and loops have been adapted to use the seq_arr API. This change is a step toward more robust and maintainable handling of PDU sessions in the gNB RRC layer. The "status" state machine remains untouched in this commit and is refactored in a later commit. Also: * add macro to push to seq_arr and return the new element * move initialization of xid (RRC PDU Session struct) to find_pduSession (temporary, will be finalized in a later commit) since with the new seq_arr design the initialization is no longer possible in the UE context generation (also does not belong to it, initialize when adding a new PDU Session) --- CMakeLists.txt | 1 + .../RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.c | 16 +- .../E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c | 5 +- openair2/RRC/NR/nr_rrc_defs.h | 4 +- openair2/RRC/NR/rrc_gNB.c | 105 +++---- openair2/RRC/NR/rrc_gNB_NGAP.c | 256 +++++++++--------- openair2/RRC/NR/rrc_gNB_NGAP.h | 5 +- openair2/RRC/NR/rrc_gNB_UE_context.c | 7 +- openair2/RRC/NR/rrc_gNB_mobility.c | 1 + openair2/RRC/NR/rrc_gNB_radio_bearers.c | 80 ++++-- openair2/RRC/NR/rrc_gNB_radio_bearers.h | 15 +- 11 files changed, 261 insertions(+), 234 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 058bfd7a39..528b3e6482 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1893,6 +1893,7 @@ target_link_libraries(nr-cuup PRIVATE CONFIG_LIB ITTI SCTP_CLIENT GTPV1U e1ap f1ap time_management + alg z dl pthread shlib_loader ${T_LIB}) target_link_libraries(nr-cuup PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs) if(E2_AGENT) diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.c b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.c index 158c126c39..4213ea8aa3 100644 --- a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.c +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.c @@ -27,10 +27,11 @@ #include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h" #include "openair2/E2AP/flexric/src/util/time_now_us.h" #include "openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h" - +#include "ds/seq_arr.h" #if defined (NGRAN_GNB_CUCP) #include "openair2/RRC/NR/rrc_gNB_UE_context.h" +#include "openair2/RRC/NR/rrc_gNB_radio_bearers.h" #endif bool read_gtp_sm(void * data) @@ -62,16 +63,15 @@ bool read_gtp_sm(void * data) rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(RC.nrrrc[0], ue_id_list[i]); gtp->msg.ngut[i].rnti = ue_id_list[i]; - int nb_pdu_session = ue_context_p->ue_context.nb_of_pdusessions; - if (nb_pdu_session > 0) { - int nb_pdu_idx = nb_pdu_session - 1; - gtp->msg.ngut[i].teidgnb = ue_context_p->ue_context.pduSession[nb_pdu_idx].param.n3_outgoing.teid; - gtp->msg.ngut[i].teidupf = ue_context_p->ue_context.pduSession[nb_pdu_idx].param.n3_incoming.teid; + FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t*, session, &ue_context_p->ue_context.pduSessions) { + gtp->msg.ngut[i].teidgnb = session->param.n3_outgoing.teid; + gtp->msg.ngut[i].teidupf = session->param.n3_incoming.teid; // TODO: one PDU session has multiple QoS Flow - int nb_qos_flow = ue_context_p->ue_context.pduSession[nb_pdu_idx].param.nb_qos; + int nb_qos_flow = session->param.nb_qos; if (nb_qos_flow > 0) { - gtp->msg.ngut[i].qfi = ue_context_p->ue_context.pduSession[nb_pdu_idx].param.qos[nb_qos_flow - 1].qfi; + gtp->msg.ngut[i].qfi = session->param.qos[nb_qos_flow - 1].qfi; } + break; } } diff --git a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c index aa68ba7d9d..02760c4984 100644 --- a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c +++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c @@ -27,6 +27,7 @@ #include "openair2/E1AP/e1ap_common.h" #include "openair2/E2AP/flexric/src/util/time_now_us.h" #include "openair2/F1AP/f1ap_ids.h" +#include "ds/seq_arr.h" static pthread_once_t once_kpm_mutex = PTHREAD_ONCE_INIT; @@ -212,8 +213,8 @@ static arr_ue_id_t filter_ues_by_s_nssai_in_cu(const test_info_lst_t test_info) /* UE has no AMF UE NGAP ID yet => can't send message */ if (ue->amf_ue_ngap_id >= (1LL << 40)) continue; - for (int p = 0; p < ue->nb_of_pdusessions; ++p) { - pdusession_t *pdu = &ue->pduSession[p].param; + FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t*, item, &ue->pduSessions) { + pdusession_t* pdu = &item->param; if (nssai_matches(pdu->nssai, sst, sd)) { arr_ue_id.ue_id[arr_ue_id.sz] = fill_ue_id_data[ngran_gNB_CU](ue, 0, 0); diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index f670dc4f86..4f06fbd0d0 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -238,8 +238,8 @@ typedef struct gNB_RRC_UE_s { rb_id_t nsa_gtp_psi[S1AP_MAX_E_RAB]; //SA block - int nb_of_pdusessions; - rrc_pdu_session_param_t pduSession[NGAP_MAX_PDU_SESSION]; + seq_arr_t pduSessions; + rrc_action_t xids[NR_RRC_TRANSACTION_IDENTIFIER_NUMBER]; uint8_t e_rab_release_command_flag; uint32_t ue_rrc_inactivity_timer; diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 2ade816666..ca8a46a705 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -656,14 +656,16 @@ nr_rrc_reconfig_param_t get_RRCReconfiguration_params(gNB_RRC_INST *rrc, gNB_RRC .srb_config_list = SRBs}; UE->DRB_ReleaseList = NULL; // pointer transferred to params - for (int i = 0; i < UE->nb_of_pdusessions; i++) { - if (UE->pduSession[i].param.nas_pdu.len > 0) { - params.dedicated_NAS_msg_list[params.num_nas_msg++] = UE->pduSession[i].param.nas_pdu; - UE->pduSession[i].param.nas_pdu.buf = NULL; - UE->pduSession[i].param.nas_pdu.len = 0; - LOG_D(NR_RRC, "Transfer NAS info with size %ld (pdusession idx %d) to RRCReconfiguration params\n", UE->pduSession[i].param.nas_pdu.len, i); + FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t *, item, &UE->pduSessions) { + pdusession_t *session = &item->param; + if (session->nas_pdu.len > 0) { + params.dedicated_NAS_msg_list[params.num_nas_msg++] = session->nas_pdu; + session->nas_pdu.buf = NULL; + session->nas_pdu.len = 0; + LOG_D(NR_RRC, "Transfer NAS info with size %ld to RRCReconfiguration params\n", session->nas_pdu.len); } } + if (UE->nas_pdu.len > 0) { params.dedicated_NAS_msg_list[params.num_nas_msg++] = UE->nas_pdu; UE->nas_pdu.buf = NULL; @@ -696,12 +698,11 @@ static void rrc_gNB_generate_dedicatedRRCReconfiguration(gNB_RRC_INST *rrc, gNB_ return; } - for (int i = 0; i < ue_p->nb_of_pdusessions; i++) { - if (ue_p->pduSession[i].param.nas_pdu.buf != NULL) { - ue_p->pduSession[i].xid = params.transaction_id; - } - if (ue_p->pduSession[i].status < PDU_SESSION_STATUS_ESTABLISHED) { - ue_p->pduSession[i].status = PDU_SESSION_STATUS_DONE; + FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t *, item, &ue_p->pduSessions) { + if (item->param.nas_pdu.buf) + item->xid = params.transaction_id; + if (item->status < PDU_SESSION_STATUS_ESTABLISHED) { + item->status = PDU_SESSION_STATUS_DONE; } } @@ -718,40 +719,41 @@ void rrc_gNB_modify_dedicatedRRCReconfiguration(gNB_RRC_INST *rrc, gNB_RRC_UE_t nr_rrc_reconfig_param_t params = get_RRCReconfiguration_params(rrc, ue_p, 0, false); ue_p->xids[params.transaction_id] = RRC_PDUSESSION_MODIFY; - for (int i = 0; i < ue_p->nb_of_pdusessions; i++) { - rrc_pdu_session_param_t *session = &ue_p->pduSession[i]; + FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t *, item, &ue_p->pduSessions) { + pdusession_t *session = &item->param; // bypass the new and already configured pdu sessions - if (session->status >= PDU_SESSION_STATUS_DONE) { - session->xid = params.transaction_id; + if (item->status >= PDU_SESSION_STATUS_DONE) { + item->xid = params.transaction_id; continue; } - if (session->cause.type != NGAP_CAUSE_NOTHING) { + if (item->cause.type != NGAP_CAUSE_NOTHING) { // set xid of failure pdu session - session->xid = params.transaction_id; - session->status = PDU_SESSION_STATUS_FAILED; + item->xid = params.transaction_id; + item->status = PDU_SESSION_STATUS_FAILED; continue; } // search exist DRB_config int j; - for (j = 0; i < MAX_DRBS_PER_UE; j++) { + for (j = 0; j < MAX_DRBS_PER_UE; j++) { if (ue_p->established_drbs[j].status != DRB_INACTIVE - && ue_p->established_drbs[j].cnAssociation.sdap_config.pdusession_id == session->param.pdusession_id) + && ue_p->established_drbs[j].cnAssociation.sdap_config.pdusession_id == session->pdusession_id) break; } if (j == MAX_DRBS_PER_UE) { ngap_cause_t cause = {.type = NGAP_CAUSE_RADIO_NETWORK, .value = NGAP_CauseRadioNetwork_unspecified}; - session->xid = params.transaction_id; - session->status = PDU_SESSION_STATUS_FAILED; - session->cause = cause; + item->xid = params.transaction_id; + item->status = PDU_SESSION_STATUS_FAILED; + item->cause = cause; continue; } // Reference TS23501 Table 5.7.4-1: Standardized 5QI to QoS characteristics mapping - for (qos_flow_index = 0; qos_flow_index < session->param.nb_qos; qos_flow_index++) { - switch (session->param.qos[qos_flow_index].fiveQI) { + for (qos_flow_index = 0; qos_flow_index < session->nb_qos; qos_flow_index++) { + pdusession_level_qos_parameter_t *qos = &session->qos[qos_flow_index]; + switch (qos->fiveQI) { case 1: //100ms case 2: //150ms case 3: //50ms @@ -765,18 +767,17 @@ void rrc_gNB_modify_dedicatedRRCReconfiguration(gNB_RRC_INST *rrc, gNB_RRC_UE_t break; default: - LOG_E(NR_RRC, "not supported 5qi %lu\n", session->param.qos[qos_flow_index].fiveQI); + LOG_E(NR_RRC, "not supported 5qi %lu\n", qos->fiveQI); ngap_cause_t cause = {.type = NGAP_CAUSE_RADIO_NETWORK, .value = NGAP_CauseRadioNetwork_not_supported_5QI_value}; - session->status = PDU_SESSION_STATUS_FAILED; - session->xid = params.transaction_id; - session->cause = cause; + item->status = PDU_SESSION_STATUS_FAILED; + item->xid = params.transaction_id; + item->cause = cause; continue; } - LOG_I(NR_RRC, "index %d, QOS flow %d, 5QI %ld \n", i, qos_flow_index, session->param.qos[qos_flow_index].fiveQI); + LOG_I(NR_RRC, "PDU Session ID %d, QOS flow %d, 5QI %ld \n", session->pdusession_id, qos_flow_index, qos->fiveQI); } - - session->status = PDU_SESSION_STATUS_DONE; - session->xid = params.transaction_id; + item->status = PDU_SESSION_STATUS_DONE; + item->xid = params.transaction_id; } byte_array_t msg = do_RRCReconfiguration(¶ms); @@ -800,16 +801,18 @@ void rrc_gNB_generate_dedicatedRRCReconfiguration_release(gNB_RRC_INST *rrc, uint8_t *nas_buffer) //----------------------------------------------------------------------------- { - NR_DRB_ToReleaseList_t *DRB_Release_configList2 = CALLOC(sizeof(*DRB_Release_configList2), 1); + nr_rrc_reconfig_param_t params = {.transaction_id = xid}; - for (int i = 0; i < NB_RB_MAX; i++) { - if ((ue_p->pduSession[i].status == PDU_SESSION_STATUS_TORELEASE) && ue_p->pduSession[i].xid == xid) { - asn1cSequenceAdd(DRB_Release_configList2->list, NR_DRB_Identity_t, DRB_release); - *DRB_release = i + 1; + NR_DRB_ToReleaseList_t *to_release = CALLOC(sizeof(*to_release), 1); + int i = 0; + FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t *, item, &ue_p->pduSessions) { + if ((item->status == PDU_SESSION_STATUS_TORELEASE) && item->xid == xid) { + asn1cSequenceAdd(to_release->list, NR_DRB_Identity_t, DRB_release); + *DRB_release = ++i; // DRB ID } } + params.drb_release_list = to_release; - nr_rrc_reconfig_param_t params = {.drb_release_list = DRB_Release_configList2, .transaction_id = xid}; if (nas_length > 0) { params.dedicated_NAS_msg_list[params.num_nas_msg].buf = nas_buffer; params.dedicated_NAS_msg_list[params.num_nas_msg++].len = nas_length; @@ -1783,8 +1786,12 @@ static void handle_rrcReconfigurationComplete(gNB_RRC_INST *rrc, gNB_RRC_UE_t *U UE->n_initial_pdu = 0; free(UE->initial_pdus); UE->initial_pdus = NULL; - } else if (UE->nb_of_pdusessions > 0) + } else if (seq_arr_size(&UE->pduSessions) > 0) rrc_gNB_send_NGAP_PDUSESSION_SETUP_RESP(rrc, UE, xid); + else + LOG_W(NR_RRC, + "UE %d: RRC Reconfiguration Complete for PDU session establishment, but no PDU sessions were setup\n", + UE->rrc_ue_id); break; case RRC_PDUSESSION_MODIFY: rrc_gNB_send_NGAP_PDUSESSION_MODIFY_RESP(rrc, UE, xid); @@ -2288,6 +2295,7 @@ static void rrc_delete_ue_data(gNB_RRC_UE_t *UE) free_MeasConfig(UE->measConfig); free(UE->redcap_cap); UE->redcap_cap = NULL; + seq_arr_free(&UE->pduSessions, free_pdusession); } void rrc_remove_ue(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p) @@ -2318,9 +2326,7 @@ static void rrc_CU_process_ue_context_release_complete(MessageDef *msg_p) /* only trigger release if it has been requested by core * otherwise, it might be CU that requested release on a DU during normal * operation (i.e, handover) */ - uint32_t pdu_sessions[NGAP_MAX_PDU_SESSION]; - get_pduSession_array(UE, pdu_sessions); - rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE(0, UE->rrc_ue_id, UE->nb_of_pdusessions, pdu_sessions); + rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE(0, UE->rrc_ue_id, &UE->pduSessions); rrc_remove_ue(RC.nrrrc[0], ue_context_p); } } @@ -2500,7 +2506,7 @@ static int fill_drb_to_be_setup_from_e1_resp(const gNB_RRC_INST *rrc, { int nb_drb = 0; for (int p = 0; p < numPduSession; ++p) { - rrc_pdu_session_param_t *pdu = find_pduSession(UE, pduSession[p].id, false); + rrc_pdu_session_param_t *pdu = find_pduSession(&UE->pduSessions, pduSession[p].id); DevAssert(pdu); for (int i = 0; i < pduSession[p].numDRBSetup; i++) { const DRB_nGRAN_setup_t *drb_config = &pduSession[p].DRBnGRanList[i]; @@ -2569,7 +2575,7 @@ void rrc_gNB_process_e1_bearer_context_setup_resp(e1ap_bearer_setup_resp_t *resp // save the tunnel address for the PDU sessions for (int i = 0; i < resp->numPDUSessions; i++) { pdu_session_setup_t *e1_pdu = &resp->pduSession[i]; - rrc_pdu_session_param_t *rrc_pdu = find_pduSession(UE, e1_pdu->id, false); + rrc_pdu_session_param_t *rrc_pdu = find_pduSession(&UE->pduSessions, e1_pdu->id); if (rrc_pdu == NULL) { LOG_W(RRC, "E1: received setup for PDU session %ld, but has not been requested\n", e1_pdu->id); continue; @@ -2774,11 +2780,8 @@ static bool write_rrc_stats(const gNB_RRC_INST *rrc) time_t last_seen = now - ue_ctxt->last_seen; fprintf(f, " last RRC activity: %ld seconds ago\n", last_seen); - if (ue_ctxt->nb_of_pdusessions == 0) - fprintf(f, " (no PDU sessions)\n"); - for (int nb_pdu = 0; nb_pdu < ue_ctxt->nb_of_pdusessions; ++nb_pdu) { - const rrc_pdu_session_param_t *pdu = &ue_ctxt->pduSession[nb_pdu]; - fprintf(f, " PDU session %d ID %d status %s\n", nb_pdu, pdu->param.pdusession_id, get_pdusession_status_text(pdu->status)); + FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t *, pdu, &ue_ctxt->pduSessions) { + fprintf(f, " PDU session ID %d status %s\n", pdu->param.pdusession_id, get_pdusession_status_text(pdu->status)); } fprintf(f, " associated DU: "); diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index a087942837..b1f1e3fc85 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -88,6 +88,7 @@ #include "uper_encoder.h" #include "rrc_gNB_mobility.h" #include "rrc_gNB_du.h" +#include "common/utils/alg/find.h" #ifdef E2_AGENT #include "openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc_extern.h" @@ -278,9 +279,14 @@ bool trigger_bearer_setup(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, pdusession e1ap_nssai_t cuup_nssai = {0}; for (int i = 0; i < n; i++) { - rrc_pdu_session_param_t *pduSession = find_pduSession(UE, sessions[i].pdusession_id, true); + rrc_pdu_session_param_t *pduSession = add_pduSession(&UE->pduSessions, &sessions[i]); + if (!pduSession) { + LOG_E(NR_RRC, "Could not add PDU Session %d for UE %d\n", sessions[i].pdusession_id, UE->rrc_ue_id); + continue; + } pdusession_t *session = &pduSession->param; - cp_pdusession(session, &sessions[i]); + LOG_I(NR_RRC, "Add PDU Session %d (total nb of sessions = %ld)\n", session->pdusession_id, seq_arr_size(&UE->pduSessions)); + // Fill E1 Bearer Context Modification Request bearer_req.gNB_cu_cp_ue_id = UE->rrc_ue_id; security_information_t *secInfo = &bearer_req.secInfo; secInfo->cipheringAlgorithm = rrc->security.do_drb_ciphering ? UE->ciphering_algorithm : 0; @@ -312,7 +318,7 @@ bool trigger_bearer_setup(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, pdusession int drb_id = get_next_available_drb_id(UE); drb_t *rrc_drb = generateDRB(UE, drb_id, - pduSession, + session, rrc->configuration.enable_sdap, rrc->security.do_drb_integrity, rrc->security.do_drb_ciphering, @@ -522,8 +528,8 @@ void rrc_gNB_send_NGAP_INITIAL_CONTEXT_SETUP_RESP(gNB_RRC_INST *rrc, gNB_RRC_UE_ resp->gNB_ue_ngap_id = UE->rrc_ue_id; - for (int pdusession = 0; pdusession < UE->nb_of_pdusessions; pdusession++) { - rrc_pdu_session_param_t *session = &UE->pduSession[pdusession]; + // Optional: PDU Sessions to Setup + FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t *, session, &UE->pduSessions) { if (session->status == PDU_SESSION_STATUS_DONE) { resp->pdusessions[pdu_sessions_done++] = fill_ngap_pdusession_setup(&session->param); } else if (session->status != PDU_SESSION_STATUS_ESTABLISHED) { @@ -705,8 +711,7 @@ void rrc_gNB_send_NGAP_PDUSESSION_SETUP_RESP(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE ngap_pdusession_setup_resp_t *resp = &NGAP_PDUSESSION_SETUP_RESP(msg_p); resp->gNB_ue_ngap_id = UE->rrc_ue_id; - for (int pdusession = 0; pdusession < UE->nb_of_pdusessions; pdusession++) { - rrc_pdu_session_param_t *session = &UE->pduSession[pdusession]; + FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t *, session, &UE->pduSessions) { if (session->status == PDU_SESSION_STATUS_DONE) { resp->pdusessions[pdu_sessions_done++] = fill_ngap_pdusession_setup(&session->param); session->status = PDU_SESSION_STATUS_ESTABLISHED; @@ -727,8 +732,8 @@ void rrc_gNB_send_NGAP_PDUSESSION_SETUP_RESP(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE itti_send_msg_to_task(TASK_NGAP, rrc->module_id, msg_p); } - for(int i = 0; i < NB_RB_MAX; i++) { - UE->pduSession[i].xid = -1; + FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t *, session, &UE->pduSessions) { + session->xid = -1; } return; @@ -816,7 +821,7 @@ void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(MessageDef *msg_p, instance_t ins // might be more work than is worth it. See 8.2.1.4 in 38.413 for (int i = 0; i < msg->nb_pdusessions_tosetup; ++i) { const pdusession_resource_item_t *p = &msg->pdusession[i]; - rrc_pdu_session_param_t *exist = find_pduSession(UE, p->pdusession_id, false /* don't create */); + rrc_pdu_session_param_t *exist = find_pduSession(&UE->pduSessions, p->pdusession_id); if (exist) { LOG_E(NR_RRC, "UE %d: already has existing PDU session %d rejecting PDU Session Resource Setup Request\n", UE->rrc_ue_id, p->pdusession_id); ngap_cause_t cause = {.type = NGAP_CAUSE_RADIO_NETWORK, .value = NGAP_CAUSE_RADIO_NETWORK_MULTIPLE_PDU_SESSION_ID_INSTANCES}; @@ -883,33 +888,21 @@ int rrc_gNB_process_NGAP_PDUSESSION_MODIFY_REQ(MessageDef *msg_p, instance_t ins gNB_RRC_UE_t *UE = &ue_context_p->ue_context; bool all_failed = true; for (int i = 0; i < req->nb_pdusessions_tomodify; i++) { - rrc_pdu_session_param_t *sess; - const pdusession_resource_item_t *sessMod = req->pdusession + i; - for (sess = UE->pduSession; sess < UE->pduSession + UE->nb_of_pdusessions; sess++) - if (sess->param.pdusession_id == sessMod->pdusession_id) - break; - if (sess == UE->pduSession + UE->nb_of_pdusessions) { + const pdusession_resource_item_t *sessMod = &req->pdusession[i]; + rrc_pdu_session_param_t *session = find_pduSession(&UE->pduSessions, sessMod->pdusession_id); + if (!session) { LOG_W(NR_RRC, "Requested modification of non-existing PDU session, refusing modification\n"); - UE->nb_of_pdusessions++; - sess->status = PDU_SESSION_STATUS_FAILED; - sess->param.pdusession_id = sessMod->pdusession_id; - sess->cause.type = NGAP_CAUSE_RADIO_NETWORK; - UE->pduSession[i].cause.type = NGAP_CAUSE_RADIO_NETWORK; - UE->pduSession[i].cause.value = NGAP_CAUSE_RADIO_NETWORK_UNKNOWN_PDU_SESSION_ID; + rrc_pdu_session_param_t to_add = {0}; + to_add.status = PDU_SESSION_STATUS_FAILED; + to_add.param.pdusession_id = sessMod->pdusession_id; + to_add.cause.type = NGAP_CAUSE_RADIO_NETWORK; + to_add.cause.value = NGAP_CAUSE_RADIO_NETWORK_UNKNOWN_PDU_SESSION_ID; + seq_arr_push_back(&UE->pduSessions, &to_add, sizeof(to_add)); } else { all_failed = false; - sess->status = PDU_SESSION_STATUS_NEW; - sess->param.pdusession_id = sessMod->pdusession_id; - sess->cause.type = NGAP_CAUSE_RADIO_NETWORK; - sess->cause.value = NGAP_CAUSE_RADIO_NETWORK_MULTIPLE_PDU_SESSION_ID_INSTANCES; - sess->status = PDU_SESSION_STATUS_NEW; - sess->param.pdusession_id = sessMod->pdusession_id; - sess->cause.type = NGAP_CAUSE_NOTHING; - if (sessMod->nas_pdu.buf != NULL) { - UE->pduSession[i].param.nas_pdu = sessMod->nas_pdu; - } - for (int i = 0; i < req->nb_pdusessions_tomodify; ++i) - cp_pdusession_resource_item_to_pdusession(&UE->pduSession[i].param, &req->pdusession[i]); + session->status = PDU_SESSION_STATUS_NEW; + session->cause.type = NGAP_CAUSE_NOTHING; + cp_pdusession_resource_item_to_pdusession(&session->param, sessMod); } } @@ -927,11 +920,12 @@ int rrc_gNB_process_NGAP_PDUSESSION_MODIFY_REQ(MessageDef *msg_p, instance_t ins msg->gNB_ue_ngap_id = req->gNB_ue_ngap_id; msg->nb_of_pdusessions = 0; - for (int i = 0; i < UE->nb_of_pdusessions; i++) { - if (UE->pduSession[i].status == PDU_SESSION_STATUS_FAILED) { - msg->pdusessions_failed[i].pdusession_id = UE->pduSession[i].param.pdusession_id; - msg->pdusessions_failed[i].cause.type = UE->pduSession[i].cause.type; - msg->pdusessions_failed[i].cause.value = UE->pduSession[i].cause.value; + FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t *, session, &UE->pduSessions) { + if (session->status == PDU_SESSION_STATUS_FAILED) { + msg->pdusessions_failed[msg->nb_of_pdusessions_failed].pdusession_id = session->param.pdusession_id; + msg->pdusessions_failed[msg->nb_of_pdusessions_failed].cause.type = session->cause.type; + msg->pdusessions_failed[msg->nb_of_pdusessions_failed].cause.value = session->cause.value; + msg->nb_of_pdusessions_failed++; } } itti_send_msg_to_task(TASK_NGAP, instance, msg_fail_p); @@ -945,6 +939,11 @@ int rrc_gNB_send_NGAP_PDUSESSION_MODIFY_RESP(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE uint16_t pdu_sessions_failed = 0; uint16_t pdu_sessions_done = 0; + if (!seq_arr_size(&UE->pduSessions)) { + LOG_W(NR_RRC, "UE %d: No PDU sessions in the list, don't send NG PDU Session Modify Response\n", UE->rrc_ue_id); + return -1; + } + msg_p = itti_alloc_new_message (TASK_RRC_GNB, rrc->module_id, NGAP_PDUSESSION_MODIFY_RESP); if (msg_p == NULL) { LOG_E(NR_RRC, "itti_alloc_new_message failed, msg_p is NULL \n"); @@ -955,63 +954,54 @@ int rrc_gNB_send_NGAP_PDUSESSION_MODIFY_RESP(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE resp->gNB_ue_ngap_id = UE->rrc_ue_id; - for (int i = 0; i < UE->nb_of_pdusessions; i++) { - if (xid != UE->pduSession[i].xid) { - LOG_W(NR_RRC, "xid does not correspond (context pdu session index %d, status %d, xid %d/%d) \n ", i, UE->pduSession[i].status, xid, UE->pduSession[i].xid); + FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t *, session, &UE->pduSessions) { + if (xid != session->xid) { + LOG_W(NR_RRC, + "xid does not correspond (PDU Session %d, status %d, xid %d/%d) \n ", + session->param.pdusession_id, + session->status, + xid, + session->xid); continue; } - if (UE->pduSession[i].status == PDU_SESSION_STATUS_DONE) { - rrc_pdu_session_param_t *pduSession = find_pduSession(UE, UE->pduSession[i].param.pdusession_id, false); - if (pduSession) { - LOG_I(NR_RRC, "update pdu session %d \n", pduSession->param.pdusession_id); - // Update UE->pduSession - pduSession->status = PDU_SESSION_STATUS_ESTABLISHED; - pduSession->cause.type = NGAP_CAUSE_NOTHING; - for (int qos_flow_index = 0; qos_flow_index < UE->pduSession[i].param.nb_qos; qos_flow_index++) { - pduSession->param.qos[qos_flow_index] = UE->pduSession[i].param.qos[qos_flow_index]; - } - resp->pdusessions[pdu_sessions_done].pdusession_id = UE->pduSession[i].param.pdusession_id; - for (int qos_flow_index = 0; qos_flow_index < UE->pduSession[i].param.nb_qos; qos_flow_index++) { - resp->pdusessions[pdu_sessions_done].qos[qos_flow_index].qfi = UE->pduSession[i].param.qos[qos_flow_index].qfi; - } - resp->pdusessions[pdu_sessions_done].pdusession_id = UE->pduSession[i].param.pdusession_id; - resp->pdusessions[pdu_sessions_done].nb_of_qos_flow = UE->pduSession[i].param.nb_qos; - LOG_I(NR_RRC, - "Modify Resp (msg index %d, pdu session index %d, status %d, xid %d): nb_of_pduSessions %d, pdusession_id %d \n ", - pdu_sessions_done, - i, - UE->pduSession[i].status, - xid, - UE->nb_of_pdusessions, - resp->pdusessions[pdu_sessions_done].pdusession_id); - pdu_sessions_done++; - } else { - LOG_W(NR_RRC, "PDU SESSION modify of a not existing pdu session %d \n", UE->pduSession[i].param.pdusession_id); - resp->pdusessions_failed[pdu_sessions_failed].pdusession_id = UE->pduSession[i].param.pdusession_id; - ngap_cause_t cause = {.type = NGAP_CAUSE_RADIO_NETWORK, .value = NGAP_CAUSE_RADIO_NETWORK_UNKNOWN_PDU_SESSION_ID}; - resp->pdusessions_failed[pdu_sessions_failed].cause = cause; - pdu_sessions_failed++; + if (session->status == PDU_SESSION_STATUS_DONE) { + LOG_I(NR_RRC, "Successfully modified PDU Session %d \n", session->param.pdusession_id); + // Update status + session->status = PDU_SESSION_STATUS_ESTABLISHED; + session->cause.type = NGAP_CAUSE_NOTHING; + // Fill response + DevAssert(pdu_sessions_done < NGAP_MAX_PDU_SESSION); + resp->pdusessions[pdu_sessions_done].pdusession_id = session->param.pdusession_id; + for (int qos_flow_index = 0; qos_flow_index < session->param.nb_qos; qos_flow_index++) { + resp->pdusessions[pdu_sessions_done].qos[qos_flow_index].qfi = session->param.qos[qos_flow_index].qfi; } - } else if ((UE->pduSession[i].status == PDU_SESSION_STATUS_NEW) || (UE->pduSession[i].status == PDU_SESSION_STATUS_ESTABLISHED)) { + resp->pdusessions[pdu_sessions_done].pdusession_id = session->param.pdusession_id; + resp->pdusessions[pdu_sessions_done].nb_of_qos_flow = session->param.nb_qos; + LOG_I(NR_RRC, + "Modify Resp (msg index %d, status %d, xid %d): nb_of_pduSessions %ld, pdusession_id %d \n ", + pdu_sessions_done, + session->status, + xid, + seq_arr_size(&UE->pduSessions), + resp->pdusessions[pdu_sessions_done].pdusession_id); + pdu_sessions_done++; + } else if ((session->status == PDU_SESSION_STATUS_NEW) || (session->status == PDU_SESSION_STATUS_ESTABLISHED)) { LOG_D(NR_RRC, "PDU SESSION is NEW or already ESTABLISHED\n"); - } else if (UE->pduSession[i].status == PDU_SESSION_STATUS_FAILED) { - resp->pdusessions_failed[pdu_sessions_failed].pdusession_id = UE->pduSession[i].param.pdusession_id; - resp->pdusessions_failed[pdu_sessions_failed].cause.type = UE->pduSession[i].cause.type; - resp->pdusessions_failed[pdu_sessions_failed].cause.value = UE->pduSession[i].cause.value; + } else if (session->status == PDU_SESSION_STATUS_FAILED) { + DevAssert(pdu_sessions_failed < NGAP_MAX_PDU_SESSION); + resp->pdusessions_failed[pdu_sessions_failed].pdusession_id = session->param.pdusession_id; + resp->pdusessions_failed[pdu_sessions_failed].cause.type = session->cause.type; + resp->pdusessions_failed[pdu_sessions_failed].cause.value = session->cause.value; pdu_sessions_failed++; - } - else - LOG_W(NR_RRC, - "Modify pdu session %d, unknown state %d \n ", - UE->pduSession[i].param.pdusession_id, - UE->pduSession[i].status); + } else + LOG_W(NR_RRC, "Modify pdu session %d, unknown state %d \n ", session->param.pdusession_id, session->status); } resp->nb_of_pdusessions = pdu_sessions_done; resp->nb_of_pdusessions_failed = pdu_sessions_failed; if (pdu_sessions_done > 0 || pdu_sessions_failed > 0) { - LOG_D(NR_RRC, "NGAP_PDUSESSION_MODIFY_RESP: sending the message (total pdu session %d)\n", UE->nb_of_pdusessions); + LOG_D(NR_RRC, "NGAP_PDUSESSION_MODIFY_RESP: sending the message (total pdu session %ld)\n", seq_arr_size(&UE->pduSessions)); itti_send_msg_to_task (TASK_NGAP, rrc->module_id, msg_p); } else { itti_free (ITTI_MSG_ORIGIN_ID(msg_p), msg_p); @@ -1036,8 +1026,10 @@ void rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_REQ(const module_id_t gnb_mod_idP, req->gNB_ue_ngap_id = UE->rrc_ue_id; req->cause.type = causeP.type; req->cause.value = causeP.value; - for (int i = 0; i < UE->nb_of_pdusessions; i++) { - req->pdusessions[i].pdusession_id = UE->pduSession[i].param.pdusession_id; + // PDU Session Resource List (optional) + FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t *, session, &UE->pduSessions) { + DevAssert(req->nb_of_pdusessions < NGAP_MAX_PDU_SESSION); + req->pdusessions[req->nb_of_pdusessions].pdusession_id = session->param.pdusession_id; req->nb_of_pdusessions++; } itti_send_msg_to_task(TASK_NGAP, GNB_MODULE_ID_TO_INSTANCE(gnb_mod_idP), msg); @@ -1255,7 +1247,7 @@ int rrc_gNB_process_NGAP_UE_CONTEXT_RELEASE_COMMAND(MessageDef *msg_p, instance_ LOG_W(NR_RRC, "[gNB %ld] In NGAP_UE_CONTEXT_RELEASE_COMMAND: unknown UE from gNB_ue_ngap_id (%u)\n", instance, gNB_ue_ngap_id); - rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE(instance, gNB_ue_ngap_id, 0, NULL); + rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE(instance, gNB_ue_ngap_id, NULL); return -1; } @@ -1286,25 +1278,24 @@ int rrc_gNB_process_NGAP_UE_CONTEXT_RELEASE_COMMAND(MessageDef *msg_p, instance_ /* UE will be freed after UE context release complete */ } else { // the DU is offline already - uint32_t pdu_sessions[NGAP_MAX_PDU_SESSION]; - get_pduSession_array(UE, pdu_sessions); - rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE(0, UE->rrc_ue_id, UE->nb_of_pdusessions, pdu_sessions); + rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE(0, UE->rrc_ue_id, &UE->pduSessions); rrc_remove_ue(rrc, ue_context_p); } return 0; } -void rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE(instance_t instance, - uint32_t gNB_ue_ngap_id, - int num_pdu, - uint32_t pdu_session_id[256]) +void rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE(instance_t instance, uint32_t gNB_ue_ngap_id, seq_arr_t *pdusessions) { MessageDef *msg = itti_alloc_new_message(TASK_RRC_GNB, 0, NGAP_UE_CONTEXT_RELEASE_COMPLETE); - NGAP_UE_CONTEXT_RELEASE_COMPLETE(msg).gNB_ue_ngap_id = gNB_ue_ngap_id; - NGAP_UE_CONTEXT_RELEASE_COMPLETE(msg).num_pdu_sessions = num_pdu; - for (int i = 0; i < num_pdu; ++i) - NGAP_UE_CONTEXT_RELEASE_COMPLETE(msg).pdu_session_id[i] = pdu_session_id[i]; + ngap_ue_release_complete_t *complete = &NGAP_UE_CONTEXT_RELEASE_COMPLETE(msg); + complete->gNB_ue_ngap_id = gNB_ue_ngap_id; + // PDU Session Resource List (Optional) + if (pdusessions && seq_arr_size(pdusessions)) { + FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t *, session, pdusessions) { + complete->pdu_session_id[complete->num_pdu_sessions++] = session->param.pdusession_id; + } + } itti_send_msg_to_task(TASK_NGAP, instance, msg); } @@ -1361,14 +1352,14 @@ void rrc_gNB_send_NGAP_HANDOVER_REQUEST_ACKNOWLEDGE(gNB_RRC_INST *rrc, gNB_RRC_U // AMF UE NGAP ID msg->amf_ue_ngap_id = UE->amf_ue_ngap_id; // PDU Session Resource Admitted List - msg->nb_of_pdusessions = UE->nb_of_pdusessions; - for (int i = 0; i < UE->nb_of_pdusessions; i++) { - rrc_pdu_session_param_t *session = &UE->pduSession[i]; + FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t*, session, &UE->pduSessions) { session->status = PDU_SESSION_STATUS_ESTABLISHED; // PDU Session ID - msg->pdusessions[i].pdu_session_id = session->param.pdusession_id; + DevAssert(msg->nb_of_pdusessions < NGAP_MAX_PDU_SESSION); + pdu_session_resource_admitted_t *pdu = &msg->pdusessions[msg->nb_of_pdusessions++]; + pdu->pdu_session_id = session->param.pdusession_id; // Handover Request Acknowledge Transfer - ho_request_ack_transfer_t *transfer = &msg->pdusessions[i].ack_transfer; + ho_request_ack_transfer_t *transfer = &pdu->ack_transfer; transfer->gtp_teid = session->param.n3_outgoing.teid; memcpy(transfer->gNB_addr.buffer, session->param.n3_outgoing.addr.buffer, session->param.n3_outgoing.addr.length); transfer->gNB_addr.length = session->param.n3_outgoing.addr.length; @@ -1439,19 +1430,19 @@ void rrc_gNB_send_NGAP_PDUSESSION_RELEASE_RESPONSE(gNB_RRC_INST *rrc, gNB_RRC_UE memset(resp, 0, sizeof(*resp)); resp->gNB_ue_ngap_id = UE->rrc_ue_id; - for (int i = 0; i < UE->nb_of_pdusessions; i++) { - if (xid == UE->pduSession[i].xid) { - resp->pdusession_release[pdu_sessions_released].pdusession_id = UE->pduSession[i].param.pdusession_id; + FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t *, session, &UE->pduSessions) { + if (xid == session->xid) { + const pdusession_t *pdusession = &session->param; + resp->pdusession_release[pdu_sessions_released].pdusession_id = pdusession->pdusession_id; + session->status = PDU_SESSION_STATUS_RELEASED; pdu_sessions_released++; - //clear - memset(&UE->pduSession[i], 0, sizeof(*UE->pduSession)); - UE->pduSession[i].status = PDU_SESSION_STATUS_RELEASED; - LOG_W(NR_RRC, "Released pdu session, but code to finish to free memory\n"); } } resp->nb_of_pdusessions_released = pdu_sessions_released; resp->nb_of_pdusessions_failed = 0; + DevAssert(resp->nb_of_pdusessions_released < NGAP_MAX_PDU_SESSION); + LOG_I(NR_RRC, "NGAP PDUSESSION RELEASE RESPONSE: rrc_ue_id %u release_pdu_sessions %d\n", resp->gNB_ue_ngap_id, pdu_sessions_released); itti_send_msg_to_task (TASK_NGAP, rrc->module_id, msg_p); } @@ -1479,14 +1470,15 @@ int rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND(MessageDef *msg_p, instance_ uint8_t xid = rrc_gNB_get_next_transaction_identifier(rrc->module_id); UE->xids[xid] = RRC_PDUSESSION_RELEASE; for (int pdusession = 0; pdusession < cmd->nb_pdusessions_torelease; pdusession++) { - rrc_pdu_session_param_t *pduSession = find_pduSession(UE, cmd->pdusession_release_params[pdusession].pdusession_id, false); + rrc_pdu_session_param_t *pduSession = find_pduSession(&UE->pduSessions, cmd->pdusession_release_params[pdusession].pdusession_id); if (!pduSession) { LOG_I(NR_RRC, "no pdusession_id, AMF requested to close it id=%d\n", cmd->pdusession_release_params[pdusession].pdusession_id); - int j=UE->nb_of_pdusessions++; - UE->pduSession[j].status = PDU_SESSION_STATUS_FAILED; - UE->pduSession[j].param.pdusession_id = cmd->pdusession_release_params[pdusession].pdusession_id; + rrc_pdu_session_param_t item = {0}; + item.status = PDU_SESSION_STATUS_FAILED; + item.param.pdusession_id = cmd->pdusession_release_params[pdusession].pdusession_id; ngap_cause_t cause = {.type = NGAP_CAUSE_RADIO_NETWORK, .value = NGAP_CAUSE_RADIO_NETWORK_UNKNOWN_PDU_SESSION_ID}; - UE->pduSession[j].cause = cause; + item.cause = cause; + seq_arr_push_back(&UE->pduSessions, &item, sizeof(item)); continue; } if (pduSession->status == PDU_SESSION_STATUS_FAILED) { @@ -1578,7 +1570,6 @@ void rrc_gNB_send_NGAP_HANDOVER_REQUIRED(gNB_RRC_INST *rrc, ngap_handover_required_t msg = { .amf_ue_ngap_id = UE->amf_ue_ngap_id, .gNB_ue_ngap_id = UE->rrc_ue_id, - .nb_of_pdusessions = UE->nb_of_pdusessions, .cause.type = NGAP_CAUSE_RADIO_NETWORK, .cause.value = NGAP_CAUSE_RADIO_NETWORK_HANDOVER_DESIRABLE_FOR_RADIO_REASON, .handoverType = HANDOVER_TYPE_INTRA5GS, @@ -1607,22 +1598,21 @@ void rrc_gNB_send_NGAP_HANDOVER_REQUIRED(gNB_RRC_INST *rrc, /* Fill both PDU Session Resource List IE (M) in Handover Required and PDU Session Resource Information List IE (O) in the Source NG-RAN Node to Target NG-RAN Node Transparent Container */ - for (int i = 0; i < UE->nb_of_pdusessions; ++i) { - if (UE->pduSession[i].status == PDU_SESSION_STATUS_DONE || UE->pduSession[i].status == PDU_SESSION_STATUS_ESTABLISHED) { - rrc_pdu_session_param_t *pduSession = find_pduSession(UE, UE->pduSession[i].param.pdusession_id, false); - if (!pduSession) - continue; - pdusession_t *session = &pduSession->param; - // PDU Session ID - msg.pdusessions[i].pdusession_id = session->pdusession_id; - // PDU Session Resource Information List (O) - pdusession_resource_info_t *pdu_info = &msg.source2target->pdu_session_resource[msg.source2target->nb_pdu_session_resource++]; - pdu_info->pdusession_id = session->pdusession_id; - pdu_info->nb_of_qos_flow = session->nb_qos; - for (int j = 0; j < session->nb_qos; ++j) { - pdu_info->qos_flow_info[j].qfi = session->qos[j].qfi; - } - msg.source2target->nb_pdu_session_resource++; + FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t*, pduSession, &UE->pduSessions) { + if (pduSession->status != PDU_SESSION_STATUS_DONE && pduSession->status != PDU_SESSION_STATUS_ESTABLISHED) + continue; + pdusession_t *session = &pduSession->param; + DevAssert(msg.nb_of_pdusessions < NGAP_MAX_PDU_SESSION); + pdusession_resource_t *pdu = &msg.pdusessions[msg.nb_of_pdusessions++]; + // PDU Session ID + pdu->pdusession_id = session->pdusession_id; + // PDU Session Resource Information List (O) + DevAssert(msg.source2target->nb_pdu_session_resource < NGAP_MAX_PDU_SESSION); + pdusession_resource_info_t *pdu_info = &msg.source2target->pdu_session_resource[msg.source2target->nb_pdu_session_resource++]; + pdu_info->pdusession_id = session->pdusession_id; + pdu_info->nb_of_qos_flow = session->nb_qos; + for (int j = 0; j < pdu_info->nb_of_qos_flow; ++j) { + pdu_info->qos_flow_info[j].qfi = session->qos[j].qfi; } } diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.h b/openair2/RRC/NR/rrc_gNB_NGAP.h index b90d9a1493..c07cb04be0 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.h +++ b/openair2/RRC/NR/rrc_gNB_NGAP.h @@ -74,10 +74,7 @@ int rrc_gNB_process_NGAP_UE_CONTEXT_RELEASE_REQ(MessageDef *msg_p, instance_t in int rrc_gNB_process_NGAP_UE_CONTEXT_RELEASE_COMMAND(MessageDef *msg_p, instance_t instance); -void rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE(instance_t instance, - uint32_t gNB_ue_ngap_id, - int num_pdu, - uint32_t pdu_session_id[256]); +void rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE(instance_t instance, uint32_t gNB_ue_ngap_id, seq_arr_t *pduSessions); void rrc_gNB_send_NGAP_UE_CAPABILITIES_IND(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const NR_UECapabilityInformation_t *const ue_cap_info); diff --git a/openair2/RRC/NR/rrc_gNB_UE_context.c b/openair2/RRC/NR/rrc_gNB_UE_context.c index cb3a04fbce..d8d83505b9 100644 --- a/openair2/RRC/NR/rrc_gNB_UE_context.c +++ b/openair2/RRC/NR/rrc_gNB_UE_context.c @@ -40,6 +40,7 @@ #include "linear_alloc.h" #include "openair2/F1AP/f1ap_ids.h" #include "tree.h" +#include "rrc_gNB_radio_bearers.h" static void rrc_gNB_ue_context_update_time(rrc_gNB_ue_context_t *ctxt) { @@ -78,9 +79,6 @@ rrc_gNB_ue_context_t *rrc_gNB_allocate_new_ue_context(gNB_RRC_INST *rrc_instance new_p->ue_context.rrc_ue_id = uid_linear_allocator_new(&rrc_instance_pP->uid_allocator) + 1; rrc_gNB_ue_context_update_time(new_p); - for(int i = 0; i < NB_RB_MAX; i++) - new_p->ue_context.pduSession[i].xid = -1; - LOG_D(NR_RRC, "Returning new RRC UE context RRC ue id: %d\n", new_p->ue_context.rrc_ue_id); return(new_p); } @@ -211,6 +209,9 @@ rrc_gNB_ue_context_t *rrc_gNB_create_ue_context(sctp_assoc_t assoc_id, ue->max_delays_pdu_session = 20; /* see rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ() */ ue->ongoing_pdusession_setup_request = false; + // Initialise setup PDU Sessions list + seq_arr_init(&ue->pduSessions, sizeof(rrc_pdu_session_param_t)); + RB_INSERT(rrc_nr_ue_tree_s, &rrc_instance_pP->rrc_ue_head, ue_context_p); LOG_UE_EVENT(ue, "Create UE context: CU UE ID %u DU UE ID %u (rnti: %04x, random ue id %lx)\n", diff --git a/openair2/RRC/NR/rrc_gNB_mobility.c b/openair2/RRC/NR/rrc_gNB_mobility.c index 07b742e16c..40ff7d8ab2 100644 --- a/openair2/RRC/NR/rrc_gNB_mobility.c +++ b/openair2/RRC/NR/rrc_gNB_mobility.c @@ -76,6 +76,7 @@ static int fill_drb_to_be_setup(const gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue, f1ap_ /* fetch an existing PDU session for this DRB */ rrc_pdu_session_param_t *pdu = find_pduSession_from_drbId(ue, rrc_drb->drb_id); AssertFatal(pdu != NULL, "no PDU session for DRB ID %d\n", rrc_drb->drb_id); + // for the moment, we only support one QoS flow. Put a reminder in case // this changes AssertFatal(pdu->param.nb_qos == 1, "only 1 Qos flow supported\n"); diff --git a/openair2/RRC/NR/rrc_gNB_radio_bearers.c b/openair2/RRC/NR/rrc_gNB_radio_bearers.c index d91c866cd4..0192203af1 100644 --- a/openair2/RRC/NR/rrc_gNB_radio_bearers.c +++ b/openair2/RRC/NR/rrc_gNB_radio_bearers.c @@ -31,6 +31,14 @@ #include "ngap_messages_types.h" #include "oai_asn1.h" #include "openair2/LAYER2/nr_pdcp/nr_pdcp_asn1_utils.h" +#include "common/utils/alg/find.h" + +static bool eq_pdu_session_id(const void *vval, const void *vit) +{ + const int id = *(const int *)vval; + const rrc_pdu_session_param_t *elem = vit; + return elem->param.pdusession_id == id; +} /** @brief Deep copy pdusession_t */ void cp_pdusession(pdusession_t *dst, const pdusession_t *src) @@ -41,19 +49,49 @@ void cp_pdusession(pdusession_t *dst, const pdusession_t *src) dst->nas_pdu = copy_byte_array(src->nas_pdu); } -rrc_pdu_session_param_t *find_pduSession(gNB_RRC_UE_t *ue, int id, bool create) +/** @brief Free pdusession_t */ +void free_pdusession(void *ptr) { - int j; - for (j = 0; j < ue->nb_of_pdusessions; j++) - if (id == ue->pduSession[j].param.pdusession_id) - break; - if (j == ue->nb_of_pdusessions) { - if (create) - ue->nb_of_pdusessions++; - else - return NULL; + rrc_pdu_session_param_t *elem = ptr; + free_byte_array(elem->param.nas_pdu); +} + +/** @brief Retrieves PDU Session for the input ID + * @return pointer to the found PDU Session, NULL if not found */ +rrc_pdu_session_param_t *find_pduSession(seq_arr_t *seq, int id) +{ + DevAssert(seq); + elm_arr_t elm = find_if(seq, &id, eq_pdu_session_id); + if (elm.found) + return (rrc_pdu_session_param_t *)elm.it; + return NULL; +} + +/** @brief Adds a new PDU Session to the list + * @return pointer to the new PDU Session */ +rrc_pdu_session_param_t *add_pduSession(seq_arr_t *sessions_ptr, const pdusession_t *in) +{ + DevAssert(sessions_ptr); + DevAssert(in); + + if (seq_arr_size(sessions_ptr) == NGAP_MAX_PDU_SESSION) { + LOG_W(NR_RRC, "Reached maximum number of PDU Session = %ld\n", seq_arr_size(sessions_ptr)); + return NULL; } - return ue->pduSession + j; + + rrc_pdu_session_param_t *exists = find_pduSession(sessions_ptr, in->pdusession_id); + if (exists) { + LOG_E(NR_RRC, "Trying to add an already existing PDU Session with ID=%d\n", in->pdusession_id); + return NULL; + } + + rrc_pdu_session_param_t new = {.param = *in, .status = PDU_SESSION_STATUS_NEW, .xid = -1}; + seq_arr_push_back(sessions_ptr, &new, sizeof(rrc_pdu_session_param_t)); + rrc_pdu_session_param_t *added = find_pduSession(sessions_ptr, in->pdusession_id); + DevAssert(added); + LOG_I(NR_RRC, "Added PDU Session %d, (total nb of sessions = %ld)\n", in->pdusession_id, seq_arr_size(sessions_ptr)); + + return added; } rrc_pdu_session_param_t *find_pduSession_from_drbId(gNB_RRC_UE_t *ue, int drb_id) @@ -65,13 +103,7 @@ rrc_pdu_session_param_t *find_pduSession_from_drbId(gNB_RRC_UE_t *ue, int drb_id return NULL; } int id = drb->cnAssociation.sdap_config.pdusession_id; - return find_pduSession(ue, id, false); -} - -void get_pduSession_array(gNB_RRC_UE_t *ue, uint32_t pdu_sessions[NGAP_MAX_PDU_SESSION]) -{ - for (int i = 0; i < ue->nb_of_pdusessions && i < NGAP_MAX_PDU_SESSION; ++i) - pdu_sessions[i] = ue->pduSession[i].param.pdusession_id; + return find_pduSession(&ue->pduSessions, id); } drb_t *get_drb(gNB_RRC_UE_t *ue, uint8_t drb_id) @@ -117,7 +149,7 @@ void set_bearer_context_pdcp_config(bearer_context_pdcp_config_t *pdcp_config, d drb_t *generateDRB(gNB_RRC_UE_t *ue, uint8_t drb_id, - const rrc_pdu_session_param_t *pduSession, + const pdusession_t *pduSession, bool enable_sdap, int do_drb_integrity, int do_drb_ciphering, @@ -125,7 +157,7 @@ drb_t *generateDRB(gNB_RRC_UE_t *ue, { DevAssert(ue != NULL); - LOG_I(NR_RRC, "UE %d: configure DRB ID %d for PDU session ID %d\n", ue->rrc_ue_id, drb_id, pduSession->param.pdusession_id); + LOG_I(NR_RRC, "UE %d: configure DRB ID %d for PDU session ID %d\n", ue->rrc_ue_id, drb_id, pduSession->pdusession_id); drb_t *est_drb = &ue->established_drbs[drb_id - 1]; DevAssert(est_drb->status == DRB_INACTIVE); @@ -136,7 +168,7 @@ drb_t *generateDRB(gNB_RRC_UE_t *ue, /* SDAP Configuration */ est_drb->cnAssociation.present = NR_DRB_ToAddMod__cnAssociation_PR_sdap_Config; - est_drb->cnAssociation.sdap_config.pdusession_id = pduSession->param.pdusession_id; + est_drb->cnAssociation.sdap_config.pdusession_id = pduSession->pdusession_id; if (enable_sdap) { est_drb->cnAssociation.sdap_config.sdap_HeaderDL = NR_SDAP_Config__sdap_HeaderDL_present; est_drb->cnAssociation.sdap_config.sdap_HeaderUL = NR_SDAP_Config__sdap_HeaderUL_present; @@ -144,9 +176,9 @@ drb_t *generateDRB(gNB_RRC_UE_t *ue, est_drb->cnAssociation.sdap_config.sdap_HeaderDL = NR_SDAP_Config__sdap_HeaderDL_absent; est_drb->cnAssociation.sdap_config.sdap_HeaderUL = NR_SDAP_Config__sdap_HeaderUL_absent; } - for (int qos_flow_index = 0; qos_flow_index < pduSession->param.nb_qos; qos_flow_index++) { - est_drb->cnAssociation.sdap_config.mappedQoS_FlowsToAdd[qos_flow_index] = pduSession->param.qos[qos_flow_index].qfi; - if (pduSession->param.qos[qos_flow_index].fiveQI > 5) + for (int qos_flow_index = 0; qos_flow_index < pduSession->nb_qos; qos_flow_index++) { + est_drb->cnAssociation.sdap_config.mappedQoS_FlowsToAdd[qos_flow_index] = pduSession->qos[qos_flow_index].qfi; + if (pduSession->qos[qos_flow_index].fiveQI > 5) est_drb->status = DRB_ACTIVE_NONGBR; else est_drb->status = DRB_ACTIVE; diff --git a/openair2/RRC/NR/rrc_gNB_radio_bearers.h b/openair2/RRC/NR/rrc_gNB_radio_bearers.h index 1eac60a609..fd37f82de0 100644 --- a/openair2/RRC/NR/rrc_gNB_radio_bearers.h +++ b/openair2/RRC/NR/rrc_gNB_radio_bearers.h @@ -53,7 +53,7 @@ drb_t *get_drb(gNB_RRC_UE_t *ue, uint8_t drb_id); /// @return returns a pointer to the generated DRB structure drb_t *generateDRB(gNB_RRC_UE_t *ue, uint8_t drb_id, - const rrc_pdu_session_param_t *pduSession, + const pdusession_t *pduSession, bool enable_sdap, int do_drb_integrity, int do_drb_ciphering, @@ -65,20 +65,21 @@ uint8_t get_next_available_drb_id(gNB_RRC_UE_t *ue); /// @brief returns the number of active DRBs for this UE int get_number_active_drbs(gNB_RRC_UE_t *ue); -/// @brief retrieve PDU session of UE ue with ID id, optionally creating it if -/// create is true -rrc_pdu_session_param_t *find_pduSession(gNB_RRC_UE_t *ue, int id, bool create); +/// @brief retrieve PDU session of UE ue with ID id +rrc_pdu_session_param_t *find_pduSession(seq_arr_t *seq, int id); + +/// @brief Add a new PDU session for UE @param ue and configuration @param in +rrc_pdu_session_param_t *add_pduSession(seq_arr_t *sessions_ptr, const pdusession_t *in); /// @brief get PDU session of UE ue through the DRB drb_id rrc_pdu_session_param_t *find_pduSession_from_drbId(gNB_RRC_UE_t *ue, int drb_id); -/// @brief get the PDU sessions of this UE in a single array -void get_pduSession_array(gNB_RRC_UE_t *ue, uint32_t pdu_sessions[NGAP_MAX_PDU_SESSION]); - /// @brief set PDCP configuration in a bearer context management message void set_bearer_context_pdcp_config(bearer_context_pdcp_config_t *pdcp_config, drb_t *rrc_drb, bool um_on_default_drb); /// @brief Deep copy an instance of struct pdusession_t void cp_pdusession(pdusession_t *dst, const pdusession_t *src); +void free_pdusession(void *ptr); + #endif From f15af7729718ae5c71117e180bd338798af1e232 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Fri, 29 Aug 2025 18:54:56 +0200 Subject: [PATCH 783/964] Cleanup: remove unused cp_pdusession The function is no longer relevant in the new design. --- openair2/RRC/NR/rrc_gNB_radio_bearers.c | 9 --------- openair2/RRC/NR/rrc_gNB_radio_bearers.h | 3 --- 2 files changed, 12 deletions(-) diff --git a/openair2/RRC/NR/rrc_gNB_radio_bearers.c b/openair2/RRC/NR/rrc_gNB_radio_bearers.c index 0192203af1..b55ce4e6ae 100644 --- a/openair2/RRC/NR/rrc_gNB_radio_bearers.c +++ b/openair2/RRC/NR/rrc_gNB_radio_bearers.c @@ -40,15 +40,6 @@ static bool eq_pdu_session_id(const void *vval, const void *vit) return elem->param.pdusession_id == id; } -/** @brief Deep copy pdusession_t */ -void cp_pdusession(pdusession_t *dst, const pdusession_t *src) -{ - // Shallow copy - *dst = *src; - // nas_pdu - dst->nas_pdu = copy_byte_array(src->nas_pdu); -} - /** @brief Free pdusession_t */ void free_pdusession(void *ptr) { diff --git a/openair2/RRC/NR/rrc_gNB_radio_bearers.h b/openair2/RRC/NR/rrc_gNB_radio_bearers.h index fd37f82de0..0a76c9d796 100644 --- a/openair2/RRC/NR/rrc_gNB_radio_bearers.h +++ b/openair2/RRC/NR/rrc_gNB_radio_bearers.h @@ -77,9 +77,6 @@ rrc_pdu_session_param_t *find_pduSession_from_drbId(gNB_RRC_UE_t *ue, int drb_id /// @brief set PDCP configuration in a bearer context management message void set_bearer_context_pdcp_config(bearer_context_pdcp_config_t *pdcp_config, drb_t *rrc_drb, bool um_on_default_drb); -/// @brief Deep copy an instance of struct pdusession_t -void cp_pdusession(pdusession_t *dst, const pdusession_t *src); - void free_pdusession(void *ptr); #endif From 7fa0ebb6b9a933f9114fb21840e23ecc03375afe Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Fri, 4 Jul 2025 17:23:14 +0200 Subject: [PATCH 784/964] Adopt dynamic seq_arr in DRB handling (RRC PDU Session) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous DRB management relied on a fixed-size array (established_drbs[MAX_DRBS_PER_UE]) and manual status tracking using DRB_ACTIVE/INACTIVE flags. This approach was inefficient, and made assumptions about DRB ID allocation that do not generalize well to dynamic procedures like bearer modification or removal. * Replace fixed-size array established_drbs[] with dynamic seq_arr_t *drbs in gNB_RRC_UE_t * Refactor get_drb() and added nr_rrc_add_drb() with clean abstractions using find and seq_arr lib * Updated all DRB-related logic (e.g., generateDRB, F1AP/E1AP tunnel config, reestablishment, mobility) to use seq_arr. * Removed status field and DRB_ACTIVE/INACTIVE logic: list presence implies active * DRB ID allocation now tracked via seq_arr size : simplifies DRB management and avoids DRB ID–indexed assumptions: code assumed DRB IDs mapped directly to array indices: established_drbs[drb_id - 1]. This could break when: DRB IDs are not sequential, DRBs are removed and re-added, or there are gaps in IDs --- openair2/RRC/NR/nr_rrc_defs.h | 3 +- openair2/RRC/NR/rrc_gNB.c | 59 ++++++------- openair2/RRC/NR/rrc_gNB_NGAP.c | 24 ++++-- openair2/RRC/NR/rrc_gNB_NGAP.h | 6 +- openair2/RRC/NR/rrc_gNB_UE_context.c | 2 + openair2/RRC/NR/rrc_gNB_mobility.c | 8 +- openair2/RRC/NR/rrc_gNB_mobility.h | 6 +- openair2/RRC/NR/rrc_gNB_radio_bearers.c | 108 ++++++++++++++---------- openair2/RRC/NR/rrc_gNB_radio_bearers.h | 21 ++--- 9 files changed, 133 insertions(+), 104 deletions(-) diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index 4f06fbd0d0..43909e0cd0 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -182,7 +182,6 @@ typedef struct nr_handover_context_s nr_handover_context_t; typedef struct gNB_RRC_UE_s { time_t last_seen; // last time this UE has been accessed - drb_t established_drbs[MAX_DRBS_PER_UE]; NR_DRB_ToReleaseList_t *DRB_ReleaseList; NR_SRB_INFO_TABLE_ENTRY Srb[NR_NUM_SRB]; @@ -239,6 +238,8 @@ typedef struct gNB_RRC_UE_s { //SA block seq_arr_t pduSessions; + // Established DRBs + seq_arr_t drbs; rrc_action_t xids[NR_RRC_TRANSACTION_IDENTIFIER_NUMBER]; uint8_t e_rab_release_command_flag; diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index ca8a46a705..1919ccaa5c 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -334,14 +334,12 @@ NR_DRB_ToAddModList_t *createDRBlist(gNB_RRC_UE_t *ue, bool reestablish) NR_DRB_ToAddMod_t *DRB_config = NULL; NR_DRB_ToAddModList_t *DRB_configList = CALLOC(sizeof(*DRB_configList), 1); - for (int i = 0; i < MAX_DRBS_PER_UE; i++) { - if (ue->established_drbs[i].status != DRB_INACTIVE) { - DRB_config = generateDRB_ASN1(&ue->established_drbs[i]); - if (reestablish) { - asn1cCallocOne(DRB_config->reestablishPDCP, NR_DRB_ToAddMod__reestablishPDCP_true); - } - asn1cSeqAdd(&DRB_configList->list, DRB_config); + FOR_EACH_SEQ_ARR(drb_t *, drb, &ue->drbs) { + DRB_config = generateDRB_ASN1(drb); + if (reestablish) { + asn1cCallocOne(DRB_config->reestablishPDCP, NR_DRB_ToAddMod__reestablishPDCP_true); } + asn1cSeqAdd(&DRB_configList->list, DRB_config); } if (DRB_configList->list.count == 0) { free(DRB_configList); @@ -734,22 +732,6 @@ void rrc_gNB_modify_dedicatedRRCReconfiguration(gNB_RRC_INST *rrc, gNB_RRC_UE_t continue; } - // search exist DRB_config - int j; - for (j = 0; j < MAX_DRBS_PER_UE; j++) { - if (ue_p->established_drbs[j].status != DRB_INACTIVE - && ue_p->established_drbs[j].cnAssociation.sdap_config.pdusession_id == session->pdusession_id) - break; - } - - if (j == MAX_DRBS_PER_UE) { - ngap_cause_t cause = {.type = NGAP_CAUSE_RADIO_NETWORK, .value = NGAP_CauseRadioNetwork_unspecified}; - item->xid = params.transaction_id; - item->status = PDU_SESSION_STATUS_FAILED; - item->cause = cause; - continue; - } - // Reference TS23501 Table 5.7.4-1: Standardized 5QI to QoS characteristics mapping for (qos_flow_index = 0; qos_flow_index < session->nb_qos; qos_flow_index++) { pdusession_level_qos_parameter_t *qos = &session->qos[qos_flow_index]; @@ -873,8 +855,8 @@ static void cuup_notify_reestablishment(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue_p) return; /* loop through active DRBs */ for (int drb_id = 1; drb_id <= MAX_DRBS_PER_UE; drb_id++) { - drb_t *drb = get_drb(ue_p, drb_id); - if (drb->status == DRB_INACTIVE) + drb_t *drb = get_drb(&ue_p->drbs, drb_id); + if (!drb) continue; /* fetch an existing PDU session for this DRB */ rrc_pdu_session_param_t *pdu = find_pduSession_from_drbId(ue_p, drb_id); @@ -2078,7 +2060,8 @@ static void store_du_f1u_tunnel(const f1ap_drb_setup_t *drbs, int n, gNB_RRC_UE_ const f1ap_drb_setup_t *drb_f1 = &drbs[i]; AssertFatal(drb_f1->up_dl_tnl_len == 1, "can handle only one UP param\n"); AssertFatal(drb_f1->id < MAX_DRBS_PER_UE, "illegal DRB ID %d\n", drb_f1->id); - drb_t *drb = get_drb(ue, drb_f1->id); + drb_t *drb = get_drb(&ue->drbs, drb_f1->id); + DevAssert(drb); drb->du_tunnel_config = f1u_gtp_update(drb_f1->up_dl_tnl[0].teid, drb_f1->up_dl_tnl[0].tl_address); } } @@ -2094,7 +2077,7 @@ static void fill_e1_bearer_modif_pdcp_status(gNB_RRC_UE_t *UE, drb_to_mod->pdcp_sn_status_requested = false; // PDCP SN Status Information drb_to_mod->pdcp_config = calloc_or_fail(1, sizeof(*drb_to_mod->pdcp_config)); - set_bearer_context_pdcp_config(drb_to_mod->pdcp_config, get_drb(UE, drb_id), um_on_default_drb); + set_bearer_context_pdcp_config(drb_to_mod->pdcp_config, get_drb(&UE->drbs, drb_id), um_on_default_drb); drb_to_mod->pdcp_status = calloc_or_fail(1, sizeof(*drb_to_mod->pdcp_status)); drb_to_mod->pdcp_status->dl_count.hfn = drb_status->dl_count.hfn; drb_to_mod->pdcp_status->dl_count.sn = drb_status->dl_count.pdcp_sn; @@ -2130,8 +2113,11 @@ void e1_send_bearer_updates(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, f1ap_drb fill_e1_bearer_modif(&drb_to_mod, drb_f1); } else if (is_inter_cu_ho) { /* On-going handover: send PDCP Status Request */ - if (UE->established_drbs[i].status == DRB_INACTIVE) + drb_t *drb = get_drb(&UE->drbs, drb_id); + if (!drb) { + LOG_E(NR_RRC, "Failed to send PDCP Status Request: DRB %d not found\n", drb_id); continue; + } drb_to_mod.id = drb_id; // PDCP SN Status Request drb_to_mod.pdcp_sn_status_requested = true; @@ -2204,7 +2190,7 @@ static void rrc_CU_process_ue_context_setup_response(MessageDef *msg_p, instance } if (resp->drbs_len > 0) { - int num_drb = get_number_active_drbs(UE); + int num_drb = seq_arr_size(&UE->drbs); DevAssert(num_drb == 0 || num_drb == resp->drbs_len); /* Note: we would ideally check that SRB2 is acked, but at least LiteOn DU @@ -2296,6 +2282,7 @@ static void rrc_delete_ue_data(gNB_RRC_UE_t *UE) free(UE->redcap_cap); UE->redcap_cap = NULL; seq_arr_free(&UE->pduSessions, free_pdusession); + seq_arr_free(&UE->drbs, free_drb); } void rrc_remove_ue(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p) @@ -2510,9 +2497,10 @@ static int fill_drb_to_be_setup_from_e1_resp(const gNB_RRC_INST *rrc, DevAssert(pdu); for (int i = 0; i < pduSession[p].numDRBSetup; i++) { const DRB_nGRAN_setup_t *drb_config = &pduSession[p].DRBnGRanList[i]; - drb_t *rrc_drb = get_drb(UE, pduSession[p].DRBnGRanList[i].id); + drb_t *rrc_drb = get_drb(&UE->drbs, pduSession[p].DRBnGRanList[i].id); DevAssert(rrc_drb); + DevAssert(nb_drb < MAX_DRBS_PER_UE); f1ap_drb_to_setup_t *drb = &drbs[nb_drb]; drb->id = rrc_drb->drb_id; @@ -2587,7 +2575,11 @@ void rrc_gNB_process_e1_bearer_context_setup_resp(e1ap_bearer_setup_resp_t *resp DRB_nGRAN_setup_t *drb_config = &e1_pdu->DRBnGRanList[j]; // numUpParam only relevant in F1, but not monolithic AssertFatal(drb_config->numUpParam <= 1, "can only up to one UP param\n"); - drb_t *drb = get_drb(UE, drb_config->id); + drb_t *drb = get_drb(&UE->drbs, drb_config->id); + if (!drb) { + LOG_E(RRC, "E1: DRB %ld not found for PDU session %ld\n", drb_config->id, e1_pdu->id); + continue; + } UP_TL_information_t *tl_info = &drb_config->UpParamList[0].tl_info; drb->cuup_tunnel_config = f1u_gtp_update(tl_info->teId, tl_info->tlAddress); } @@ -2629,6 +2621,7 @@ void rrc_gNB_process_e1_bearer_context_modif_resp(const e1ap_bearer_modif_resp_t } int n_drb_mod = 0; + int drb_ids[MAX_DRBS_PER_UE] = {0}; e1_pdcp_status_info_t pdcp_status[MAX_DRBS_PER_UE] = {0}; for (int i = 0; i < resp->numPDUSessionsMod; ++i) { const pdu_session_modif_t *pdu = &resp->pduSessionMod[i]; @@ -2636,6 +2629,8 @@ void rrc_gNB_process_e1_bearer_context_modif_resp(const e1ap_bearer_modif_resp_t for (int j = 0; j < pdu->numDRBModified; j++) { // Trigger UL RAN Status Transfer if (pdu->DRBnGRanModList[j].pdcp_status) { + DevAssert(n_drb_mod < MAX_DRBS_PER_UE); + drb_ids[n_drb_mod] = pdu->DRBnGRanModList[j].id; pdcp_status[n_drb_mod++] = *pdu->DRBnGRanModList[j].pdcp_status; } } @@ -2644,7 +2639,7 @@ void rrc_gNB_process_e1_bearer_context_modif_resp(const e1ap_bearer_modif_resp_t LOG_I(NR_RRC, "UE %d: received PDU Status Info - send UL RAN Status Transfer\n", resp->gNB_cu_cp_ue_id); gNB_RRC_UE_t *ue = &ue_context_p->ue_context; if (ue->ho_context && ue->ho_context->source) - ue->ho_context->source->ho_status_transfer(rrc, ue, n_drb_mod, pdcp_status); + ue->ho_context->source->ho_status_transfer(rrc, ue, n_drb_mod, drb_ids, pdcp_status); } } diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index b1f1e3fc85..ddf97b2499 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -315,9 +315,7 @@ bool trigger_bearer_setup(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, pdusession /* we assume for the moment one DRB per PDU session. Activate the bearer, * and configure in RRC. */ - int drb_id = get_next_available_drb_id(UE); drb_t *rrc_drb = generateDRB(UE, - drb_id, session, rrc->configuration.enable_sdap, rrc->security.do_drb_integrity, @@ -1162,9 +1160,15 @@ void rrc_gNB_free_Handover_Request(ngap_handover_request_t *msg) /** @brief Send NG Uplink RAN Status Transfer message (8.4.6 3GPP TS 38.413) * Direction: source NG-RAN node -> AMF */ -int rrc_gNB_send_NGAP_ul_ran_status_transfer(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const int n_to_mod, const e1_pdcp_status_info_t *pdcp_status) +int rrc_gNB_send_NGAP_ul_ran_status_transfer(gNB_RRC_INST *rrc, + gNB_RRC_UE_t *UE, + const int n_to_mod, + const int *drb_ids, + const e1_pdcp_status_info_t *pdcp_status) { AssertFatal(UE != NULL, "UE context is NULL\n"); + DevAssert(n_to_mod <= MAX_DRBS_PER_UE); + DevAssert(drb_ids); LOG_I(NR_RRC, "Sending NGAP Uplink RAN Status Transfer (AMF_UE_NGAP_ID=%" PRIu64 ", GNB_UE_NGAP_ID=%u)\n", @@ -1178,14 +1182,20 @@ int rrc_gNB_send_NGAP_ul_ran_status_transfer(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE // Loop through DRBs and extract COUNT values for (int i = 0; i < n_to_mod; ++i) { - drb_t *drb = &UE->established_drbs[i]; - if (!drb->status) + int drb_id = drb_ids[i]; + + // Find the DRB in the UE's DRB list + drb_t *drb = get_drb(&UE->drbs, drb_id); + if (!drb) { + LOG_E(NR_RRC, "Failed to send UL RAN Status Transfer: DRB %d not found\n", drb_id); continue; + } - bool sn_length_18 = rrc->pdcp_config.drb.sn_size == 18; + bool sn_length_18 = drb->pdcp_config.pdcp_SN_SizeDL == NR_PDCP_Config__drb__pdcp_SN_SizeUL_len18bits; + DevAssert(msg.ran_status.nb_drb < MAX_DRBS_PER_UE); ngap_drb_status_t *item = &msg.ran_status.drb_status_list[msg.ran_status.nb_drb++]; - item->drb_id = drb->drb_id; + item->drb_id = drb_id; const e1_pdcp_count_t *ul_pdcp = &pdcp_status[i].ul_count; const e1_pdcp_count_t *dl_pdcp = &pdcp_status[i].dl_count; diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.h b/openair2/RRC/NR/rrc_gNB_NGAP.h index c07cb04be0..91c7722c52 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.h +++ b/openair2/RRC/NR/rrc_gNB_NGAP.h @@ -104,7 +104,11 @@ void rrc_gNB_free_Handover_Command(ngap_handover_command_t *msg); void rrc_gNB_send_NGAP_HANDOVER_NOTIFY(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE); void rrc_gNB_send_NGAP_HANDOVER_CANCEL(int module_id, gNB_RRC_UE_t *UE, ngap_cause_t cause); -int rrc_gNB_send_NGAP_ul_ran_status_transfer(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const int n_to_mod, const e1_pdcp_status_info_t *pdcp_status); +int rrc_gNB_send_NGAP_ul_ran_status_transfer(gNB_RRC_INST *rrc, + gNB_RRC_UE_t *UE, + const int n_to_mod, + const int *drb_ids, + const e1_pdcp_status_info_t *pdcp_status); int rrc_gNB_process_NGAP_DL_RAN_STATUS_TRANSFER(MessageDef *msg_p, instance_t instance); diff --git a/openair2/RRC/NR/rrc_gNB_UE_context.c b/openair2/RRC/NR/rrc_gNB_UE_context.c index d8d83505b9..412c5231cc 100644 --- a/openair2/RRC/NR/rrc_gNB_UE_context.c +++ b/openair2/RRC/NR/rrc_gNB_UE_context.c @@ -211,6 +211,8 @@ rrc_gNB_ue_context_t *rrc_gNB_create_ue_context(sctp_assoc_t assoc_id, // Initialise setup PDU Sessions list seq_arr_init(&ue->pduSessions, sizeof(rrc_pdu_session_param_t)); + // Initialise setup DRBs list + seq_arr_init(&ue->drbs, sizeof(drb_t)); RB_INSERT(rrc_nr_ue_tree_s, &rrc_instance_pP->rrc_ue_head, ue_context_p); LOG_UE_EVENT(ue, diff --git a/openair2/RRC/NR/rrc_gNB_mobility.c b/openair2/RRC/NR/rrc_gNB_mobility.c index 40ff7d8ab2..3c17f45189 100644 --- a/openair2/RRC/NR/rrc_gNB_mobility.c +++ b/openair2/RRC/NR/rrc_gNB_mobility.c @@ -63,14 +63,14 @@ static void free_ho_ctx(nr_handover_context_t *ho_ctx) free(ho_ctx); } +/** @brief Fill DRB to Be Setup List in F1 UE Context Setup Request (optional list) + * @return 0 if list is empty, list size otherwise */ static int fill_drb_to_be_setup(const gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue, f1ap_drb_to_setup_t drbs[MAX_DRBS_PER_UE]) { int nb_drb = 0; - for (int i = 0; i < MAX_DRBS_PER_UE; ++i) { - drb_t *rrc_drb = &ue->established_drbs[i]; - if (rrc_drb->status == DRB_INACTIVE) - continue; + FOR_EACH_SEQ_ARR(drb_t *, rrc_drb, &ue->drbs) { + DevAssert(nb_drb < MAX_DRBS_PER_UE); f1ap_drb_to_setup_t *drb = &drbs[nb_drb]; nb_drb++; /* fetch an existing PDU session for this DRB */ diff --git a/openair2/RRC/NR/rrc_gNB_mobility.h b/openair2/RRC/NR/rrc_gNB_mobility.h index 40072abb2d..7010cc83ba 100644 --- a/openair2/RRC/NR/rrc_gNB_mobility.h +++ b/openair2/RRC/NR/rrc_gNB_mobility.h @@ -33,7 +33,11 @@ typedef struct nr_rrc_du_container_t nr_rrc_du_container_t; typedef struct NR_CellGroupConfig NR_CellGroupConfig_t; typedef void (*ho_cancel_t)(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue); -typedef int (*ho_status_transfer_t)(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const int n_to_mod, const e1_pdcp_status_info_t *pdcp_status); +typedef int (*ho_status_transfer_t)(gNB_RRC_INST *rrc, + gNB_RRC_UE_t *UE, + const int n_to_mod, + const int *drb_ids, + const e1_pdcp_status_info_t *pdcp_status); typedef struct nr_ho_source_cu { /// pointer to the (source) DU structure diff --git a/openair2/RRC/NR/rrc_gNB_radio_bearers.c b/openair2/RRC/NR/rrc_gNB_radio_bearers.c index b55ce4e6ae..1f2f721eaa 100644 --- a/openair2/RRC/NR/rrc_gNB_radio_bearers.c +++ b/openair2/RRC/NR/rrc_gNB_radio_bearers.c @@ -85,26 +85,70 @@ rrc_pdu_session_param_t *add_pduSession(seq_arr_t *sessions_ptr, const pdusessio return added; } +/** @brief Add drb_t item in the UE context list for @param pdusession_id */ +drb_t *nr_rrc_add_drb(seq_arr_t *drb_ptr, int pdusession_id) +{ + DevAssert(drb_ptr); + + // Get next available DRB ID + int drb_id = 0; + + // First, try to find the lowest available ID (prefer smaller IDs) + for (drb_id = 1; drb_id <= MAX_DRBS_PER_UE; drb_id++) { + if (get_drb(drb_ptr, drb_id) == NULL) { + break; // Found available ID + } + } + + if (drb_id > MAX_DRBS_PER_UE) { + LOG_E(NR_RRC, "Cannot set up new DRB for pdusession_id=%d - reached maximum capacity\n", pdusession_id); + return NULL; + } + + // Add item to the list + drb_t in = {.drb_id = drb_id, .cnAssociation.sdap_config.pdusession_id = pdusession_id}; + seq_arr_push_back(drb_ptr, &in, sizeof(drb_t)); + drb_t *out = get_drb(drb_ptr, drb_id); + DevAssert(out); + LOG_I(NR_RRC, "Added DRB %d to established list (PDU Session ID=%d, total DRBs = %ld)\n", out->drb_id, pdusession_id, seq_arr_size(drb_ptr)); + return out; +} + +static bool eq_drb_id(const void *vval, const void *vit) +{ + const int id = *(const int *)vval; + const drb_t *elem = (const drb_t *)vit; + return elem->drb_id == id; +} + +/** @brief Retrieves DRB for the input ID + * @return pointer to the found DRB, NULL if not found */ +drb_t *get_drb(seq_arr_t *seq, int id) +{ + DevAssert(id > 0 && id <= MAX_DRBS_PER_UE); + elm_arr_t elm = find_if(seq, &id, eq_drb_id); + if (elm.found) + return (drb_t *)elm.it; + return NULL; +} + +/** @brief Free pdusession_t */ +void free_drb(void *ptr) +{ + // do nothing +} + rrc_pdu_session_param_t *find_pduSession_from_drbId(gNB_RRC_UE_t *ue, int drb_id) { - DevAssert(drb_id > 0 && drb_id <= 32); - const drb_t *drb = &ue->established_drbs[drb_id - 1]; - if (drb->status == DRB_INACTIVE) { - LOG_E(NR_RRC, "UE %d: DRB %d inactive\n", ue->rrc_ue_id, drb_id); + const drb_t *drb = get_drb(&ue->drbs, drb_id); + if (!drb) { + LOG_E(NR_RRC, "UE %d: DRB %d not found\n", ue->rrc_ue_id, drb_id); return NULL; } int id = drb->cnAssociation.sdap_config.pdusession_id; return find_pduSession(&ue->pduSessions, id); } -drb_t *get_drb(gNB_RRC_UE_t *ue, uint8_t drb_id) -{ - DevAssert(drb_id > 0 && drb_id <= 32); - DevAssert(ue != NULL); - - return &ue->established_drbs[drb_id - 1]; -} - void set_default_drb_pdcp_config(struct pdcp_config_s *pdcp_config, int do_drb_integrity, int do_drb_ciphering, @@ -139,7 +183,6 @@ void set_bearer_context_pdcp_config(bearer_context_pdcp_config_t *pdcp_config, d } drb_t *generateDRB(gNB_RRC_UE_t *ue, - uint8_t drb_id, const pdusession_t *pduSession, bool enable_sdap, int do_drb_integrity, @@ -148,13 +191,13 @@ drb_t *generateDRB(gNB_RRC_UE_t *ue, { DevAssert(ue != NULL); - LOG_I(NR_RRC, "UE %d: configure DRB ID %d for PDU session ID %d\n", ue->rrc_ue_id, drb_id, pduSession->pdusession_id); + drb_t *est_drb = nr_rrc_add_drb(&ue->drbs, pduSession->pdusession_id); + if (!est_drb) { + LOG_E(NR_RRC, "UE %d: failed to add DRB for PDU session ID %d\n", ue->rrc_ue_id, pduSession->pdusession_id); + return NULL; + } + LOG_I(NR_RRC, "UE %d: configure DRB ID %d for PDU session ID %d\n", ue->rrc_ue_id, est_drb->drb_id, pduSession->pdusession_id); - drb_t *est_drb = &ue->established_drbs[drb_id - 1]; - DevAssert(est_drb->status == DRB_INACTIVE); - - est_drb->status = DRB_ACTIVE; - est_drb->drb_id = drb_id; est_drb->cnAssociation.sdap_config.defaultDRB = true; /* SDAP Configuration */ @@ -169,16 +212,12 @@ drb_t *generateDRB(gNB_RRC_UE_t *ue, } for (int qos_flow_index = 0; qos_flow_index < pduSession->nb_qos; qos_flow_index++) { est_drb->cnAssociation.sdap_config.mappedQoS_FlowsToAdd[qos_flow_index] = pduSession->qos[qos_flow_index].qfi; - if (pduSession->qos[qos_flow_index].fiveQI > 5) - est_drb->status = DRB_ACTIVE_NONGBR; - else - est_drb->status = DRB_ACTIVE; } /* PDCP Configuration */ set_default_drb_pdcp_config(&est_drb->pdcp_config, do_drb_integrity, do_drb_ciphering, pdcp_config, ue->redcap_cap); - drb_t *rrc_drb = get_drb(ue, drb_id); - DevAssert(rrc_drb == est_drb); /* to double check that we create the same which we would retrieve */ + drb_t *rrc_drb = get_drb(&ue->drbs, est_drb->drb_id); + DevAssert(rrc_drb); return rrc_drb; } @@ -229,22 +268,3 @@ NR_DRB_ToAddMod_t *generateDRB_ASN1(const drb_t *drb_asn1) return DRB_config; } - -uint8_t get_next_available_drb_id(gNB_RRC_UE_t *ue) -{ - for (uint8_t drb_id = 0; drb_id < MAX_DRBS_PER_UE; drb_id++) - if (ue->established_drbs[drb_id].status == DRB_INACTIVE) - return drb_id + 1; - /* From this point, we need to handle the case that all DRBs are already used by the UE. */ - LOG_E(RRC, "Error - All the DRBs are used - Handle this\n"); - return DRB_INACTIVE; -} - -int get_number_active_drbs(gNB_RRC_UE_t *ue) -{ - int n = 0; - for (int i = 0; i < MAX_DRBS_PER_UE; ++i) - if (ue->established_drbs[i].status != DRB_INACTIVE) - n++; - return n; -} diff --git a/openair2/RRC/NR/rrc_gNB_radio_bearers.h b/openair2/RRC/NR/rrc_gNB_radio_bearers.h index 0a76c9d796..982e7ea42d 100644 --- a/openair2/RRC/NR/rrc_gNB_radio_bearers.h +++ b/openair2/RRC/NR/rrc_gNB_radio_bearers.h @@ -28,19 +28,13 @@ #include "e1ap_messages_types.h" #include "nr_rrc_defs.h" -#define DRB_ACTIVE_NONGBR (2) /* DRB is used for Non-GBR Flows */ -#define DRB_ACTIVE (1) -#define DRB_INACTIVE (0) -#define GBR_FLOW (1) -#define NONGBR_FLOW (0) - /// @brief Generates an ASN1 DRB-ToAddMod, from the established_drbs in gNB_RRC_UE_t. /// @param drb_t drb_asn1 /// @return Returns the ASN1 DRB-ToAddMod structs. NR_DRB_ToAddMod_t *generateDRB_ASN1(const drb_t *drb_asn1); /// @brief retrieve the data structure representing DRB with ID drb_id of UE ue -drb_t *get_drb(gNB_RRC_UE_t *ue, uint8_t drb_id); +drb_t *get_drb(seq_arr_t *seq, int id); /// @brief Creates and stores a DRB in the gNB_RRC_UE_t struct /// @param ue The gNB_RRC_UE_t struct that holds information for the UEs @@ -52,19 +46,12 @@ drb_t *get_drb(gNB_RRC_UE_t *ue, uint8_t drb_id); /// @param pdcp_config /// @return returns a pointer to the generated DRB structure drb_t *generateDRB(gNB_RRC_UE_t *ue, - uint8_t drb_id, const pdusession_t *pduSession, bool enable_sdap, int do_drb_integrity, int do_drb_ciphering, const nr_pdcp_configuration_t *pdcp_config); -/// @brief return the next available (inactive) DRB ID of UE ue -uint8_t get_next_available_drb_id(gNB_RRC_UE_t *ue); - -/// @brief returns the number of active DRBs for this UE -int get_number_active_drbs(gNB_RRC_UE_t *ue); - /// @brief retrieve PDU session of UE ue with ID id rrc_pdu_session_param_t *find_pduSession(seq_arr_t *seq, int id); @@ -79,4 +66,10 @@ void set_bearer_context_pdcp_config(bearer_context_pdcp_config_t *pdcp_config, d void free_pdusession(void *ptr); +/// @brief Add DRB to RRC list +drb_t *nr_rrc_add_drb(seq_arr_t *drb_ptr, int pdusession_id); + +/// @brief Function to free DRB in RRC +void free_drb(void *ptr); + #endif From 45d989ec7b555a3ad994b15f4b040bcf5d07d23b Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 27 Aug 2025 17:29:46 +0200 Subject: [PATCH 785/964] Adopt dynamic seq_arr in QoS Flow list (RRC PDU Session) --- .../RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.c | 6 +- openair2/RRC/NR/nr_rrc_defs.h | 8 +- openair2/RRC/NR/nr_rrc_proto.h | 1 - openair2/RRC/NR/rrc_gNB.c | 35 +++--- openair2/RRC/NR/rrc_gNB_NGAP.c | 100 +++++++++++++----- openair2/RRC/NR/rrc_gNB_mobility.c | 7 +- openair2/RRC/NR/rrc_gNB_radio_bearers.c | 63 ++++++++++- openair2/RRC/NR/rrc_gNB_radio_bearers.h | 6 ++ 8 files changed, 162 insertions(+), 64 deletions(-) diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.c b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.c index 4213ea8aa3..4e30773313 100644 --- a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.c +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.c @@ -67,9 +67,9 @@ bool read_gtp_sm(void * data) gtp->msg.ngut[i].teidgnb = session->param.n3_outgoing.teid; gtp->msg.ngut[i].teidupf = session->param.n3_incoming.teid; // TODO: one PDU session has multiple QoS Flow - int nb_qos_flow = session->param.nb_qos; - if (nb_qos_flow > 0) { - gtp->msg.ngut[i].qfi = session->param.qos[nb_qos_flow - 1].qfi; + DevAssert(seq_arr_size(&session->param.qos) == 1); + FOR_EACH_SEQ_ARR(nr_rrc_qos_t *, qos, &session->param.qos) { + gtp->msg.ngut[i].qfi = qos->qos.qfi; } break; } diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index 43909e0cd0..3491154923 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -103,9 +103,8 @@ typedef struct pdusession_s { /* Unique pdusession_id for the UE. */ int pdusession_id; byte_array_t nas_pdu; - uint8_t nb_qos; /* Quality of service for this pdusession */ - pdusession_level_qos_parameter_t qos[QOSFLOW_MAX_VALUE]; + seq_arr_t qos; /* The transport layer address for the IP packets */ pdu_session_type_t pdu_session_type; // NG-RAN endpoint of the NG-U (N3) transport bearer @@ -176,6 +175,11 @@ typedef struct nr_redcap_ue_cap { bool rlc_am_drb_long_sn_redcap_r17; } nr_redcap_ue_cap_t; +typedef struct { + int drb_id; + pdusession_level_qos_parameter_t qos; +} nr_rrc_qos_t; + /* forward declaration */ typedef struct nr_handover_context_s nr_handover_context_t; diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h index 0c545575ba..d7c1c0efce 100644 --- a/openair2/RRC/NR/nr_rrc_proto.h +++ b/openair2/RRC/NR/nr_rrc_proto.h @@ -122,7 +122,6 @@ byte_array_t rrc_gNB_encode_RRCReconfiguration(gNB_RRC_INST *rrc, gNB_RRC_UE_t * nr_rrc_reconfig_param_t get_RRCReconfiguration_params(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, uint8_t srb_reest_bitmap, bool drb_reestablish); -pdusession_level_qos_parameter_t *get_qos_characteristics(const int qfi, rrc_pdu_session_param_t *pduSession); f1ap_qos_flow_param_t get_qos_char_from_qos_flow_param(const pdusession_level_qos_parameter_t *qos_param); void openair_rrc_gNB_configuration(gNB_RRC_INST *rrc, gNB_RrcConfigurationReq *configuration); NR_SRB_ToAddModList_t *createSRBlist(gNB_RRC_UE_t *ue, uint8_t reestablish); diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 1919ccaa5c..5e95ad690a 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -733,9 +733,8 @@ void rrc_gNB_modify_dedicatedRRCReconfiguration(gNB_RRC_INST *rrc, gNB_RRC_UE_t } // Reference TS23501 Table 5.7.4-1: Standardized 5QI to QoS characteristics mapping - for (qos_flow_index = 0; qos_flow_index < session->nb_qos; qos_flow_index++) { - pdusession_level_qos_parameter_t *qos = &session->qos[qos_flow_index]; - switch (qos->fiveQI) { + FOR_EACH_SEQ_ARR(nr_rrc_qos_t *, qos, &session->qos) { + switch (qos->qos.fiveQI) { case 1: //100ms case 2: //150ms case 3: //50ms @@ -749,14 +748,14 @@ void rrc_gNB_modify_dedicatedRRCReconfiguration(gNB_RRC_INST *rrc, gNB_RRC_UE_t break; default: - LOG_E(NR_RRC, "not supported 5qi %lu\n", qos->fiveQI); + LOG_E(NR_RRC, "not supported 5qi %lu\n", qos->qos.fiveQI); ngap_cause_t cause = {.type = NGAP_CAUSE_RADIO_NETWORK, .value = NGAP_CauseRadioNetwork_not_supported_5QI_value}; item->status = PDU_SESSION_STATUS_FAILED; item->xid = params.transaction_id; item->cause = cause; continue; } - LOG_I(NR_RRC, "PDU Session ID %d, QOS flow %d, 5QI %ld \n", session->pdusession_id, qos_flow_index, qos->fiveQI); + LOG_I(NR_RRC, "PDU Session ID %d, QOS flow %d, 5QI %ld \n", session->pdusession_id, qos_flow_index, qos->qos.fiveQI); } item->status = PDU_SESSION_STATUS_DONE; item->xid = params.transaction_id; @@ -2101,14 +2100,15 @@ void e1_send_bearer_updates(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, f1ap_drb }; bool is_inter_cu_ho = UE->ho_context && UE->ho_context->source && !UE->ho_context->target; - for (int i = 0; i < MAX_DRBS_PER_UE; i++) { - int drb_id = i + 1; + int drb_index = 0; + FOR_EACH_SEQ_ARR(drb_t *, drb, &UE->drbs) { + int drb_id = drb->drb_id; DRB_nGRAN_to_mod_t drb_to_mod = {0}; if (n > 0) { /* DRBs to Setup in F1 UE Context Modifcation Response */ - if (i == n) + if (drb_index == n) break; - const f1ap_drb_setup_t *drb_f1 = &drbs[i]; + const f1ap_drb_setup_t *drb_f1 = &drbs[drb_index]; drb_id = drb_f1->id; fill_e1_bearer_modif(&drb_to_mod, drb_f1); } else if (is_inter_cu_ho) { @@ -2134,6 +2134,8 @@ void e1_send_bearer_updates(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, f1ap_drb to_mod->sessionId = pdu->param.pdusession_id; // Fill E1 DRB to Modify item to_mod->DRBnGRanModList[to_mod->numDRB2Modify++] = drb_to_mod; + + drb_index++; } DevAssert(req.numPDUSessionsMod > 0); DevAssert(req.numPDUSessions == 0); @@ -2448,17 +2450,6 @@ unsigned int mask_flip(unsigned int x) { return((((x>>8) + (x<<8))&0xffff)>>6); } -pdusession_level_qos_parameter_t *get_qos_characteristics(const int qfi, rrc_pdu_session_param_t *pduSession) -{ - pdusession_t *pdu = &pduSession->param; - for (int i = 0; i < pdu->nb_qos; i++) { - if (qfi == pdu->qos[i].qfi) - return &pdu->qos[i]; - } - AssertFatal(1 == 0, "The pdu session %d does not contain a qos flow with qfi = %d\n", pdu->pdusession_id, qfi); - return NULL; -} - /* \bref return F1AP QoS characteristics based on Qos flow parameters */ f1ap_qos_flow_param_t get_qos_char_from_qos_flow_param(const pdusession_level_qos_parameter_t *qos_param) { @@ -2516,11 +2507,11 @@ static int fill_drb_to_be_setup_from_e1_resp(const gNB_RRC_INST *rrc, /* find the QoS characteristics stored at RRC based on QFI returned * from E1. We expect this to correspond to a QFI we passed to E1 * previously, so we expect it to exist. */ - pdusession_level_qos_parameter_t *qos_param = get_qos_characteristics(qfi, pdu); + nr_rrc_qos_t *qos_param = find_qos(&pdu->param.qos, qfi); DevAssert(qos_param); f1ap_drb_flows_mapped_t *flow = &drb->nr.flows[j]; flow->qfi = qfi; - flow->param = get_qos_char_from_qos_flow_param(qos_param); + flow->param = get_qos_char_from_qos_flow_param(&qos_param->qos); } /* the DRB QoS parameters: we just reuse the ones from the first flow */ drb->nr.drb_qos = drb->nr.flows[0].param; diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index ddf97b2499..e584912a38 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -172,20 +172,30 @@ static nr_guami_t get_guami(const uint32_t amf_Id, const plmn_id_t plmn) /** @brief Copy NGAP PDU Session Transfer item to RRC pdusession_t struct */ static void cp_pdusession_transfer_to_pdusession(pdusession_t *dst, const pdusession_transfer_t *src) { - dst->nb_qos = src->nb_qos; - for (uint8_t i = 0; i < src->nb_qos && i < QOSFLOW_MAX_VALUE; ++i) { - dst->qos[i] = src->qos[i]; - } dst->pdu_session_type = src->pdu_session_type; dst->n3_incoming = src->n3_incoming; + /* QoS handling */ + DevAssert(!dst->qos.data); + DevAssert(src->nb_qos < QOSFLOW_MAX_VALUE); + // Initialise mapped QoS list per PDU Session + seq_arr_init(&dst->qos, sizeof(nr_rrc_qos_t)); + // Add QoS flow to list + for (uint8_t i = 0; i < src->nb_qos; ++i) { + if (!add_qos(&dst->qos, &src->qos[i])) { + LOG_E(NR_RRC, "Failed to add QoS flow %d for PDU session %d\n", src->qos[i].qfi, dst->pdusession_id); + continue; + } + } } -/** @brief Copy NGAP PDU Session Resource item to RRC pdusession_t struct */ +/** @brief Copy NGAP PDU Session Resource item to RRC pdusession_t struct to setup */ static void cp_pdusession_resource_item_to_pdusession(pdusession_t *dst, const pdusession_resource_item_t *src) { dst->pdusession_id = src->pdusession_id; dst->nas_pdu = src->nas_pdu; dst->nssai = src->nssai; + + // Use the PDU session transfer function to handle QoS and other PDU session transfer-specific fields cp_pdusession_transfer_to_pdusession(dst, &src->pdusessionTransfer); } @@ -343,11 +353,10 @@ bool trigger_bearer_setup(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, pdusession *cellGroup = MCG; } - drb->numQosFlow2Setup = session->nb_qos; - for (int k=0; k < drb->numQosFlow2Setup; k++) { - qos_flow_to_setup_t *qos_flow = drb->qosFlows + k; - pdusession_level_qos_parameter_t *qos_session = session->qos + k; - + FOR_EACH_SEQ_ARR(nr_rrc_qos_t *, qos, &session->qos) { + pdusession_level_qos_parameter_t *qos_session = &qos->qos; + DevAssert(drb->numQosFlow2Setup < QOSFLOW_MAX_VALUE); + qos_flow_to_setup_t *qos_flow = &drb->qosFlows[drb->numQosFlow2Setup++]; qos_characteristics_t *qos_char = &qos_flow->qos_params.qos_characteristics; qos_flow->qfi = qos_session->qfi; qos_char->qos_type = qos_session->fiveQI_type; @@ -505,10 +514,11 @@ static pdusession_setup_t fill_ngap_pdusession_setup(pdusession_t *session) out.pdusession_id = session->pdusession_id; out.pdu_session_type = session->pdu_session_type; out.n3_outgoing = cp_gtp_tunnel(session->n3_outgoing); - out.nb_of_qos_flow = session->nb_qos; - for (int q = 0; q < session->nb_qos; q++) { - out.associated_qos_flows[q].qfi = session->qos[q].qfi; - out.associated_qos_flows[q].qos_flow_mapping_ind = QOSFLOW_MAPPING_INDICATION_DL; + FOR_EACH_SEQ_ARR(nr_rrc_qos_t *, qos_session, &session->qos) { + DevAssert(out.nb_of_qos_flow < QOSFLOW_MAX_VALUE); + pdusession_associate_qosflow_t *q = &out.associated_qos_flows[out.nb_of_qos_flow++]; + q->qfi = qos_session->qos.qfi; + q->qos_flow_mapping_ind = QOSFLOW_MAPPING_INDICATION_DL; } char ip_str[INET_ADDRSTRLEN] = {0}; inet_ntop(AF_INET, out.n3_outgoing.addr.buffer, ip_str, sizeof(ip_str)); @@ -868,6 +878,36 @@ void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(MessageDef *msg_p, instance_t ins } } +/** @brief Update existing QoS Flow mapped in the UE context */ +static void nr_rrc_update_qos(seq_arr_t *list, const int nb_qos, const pdusession_level_qos_parameter_t *in_qos) +{ + DevAssert(nb_qos == 1); + DevAssert(nb_qos < QOSFLOW_MAX_VALUE); + for (uint8_t i = 0; i < nb_qos; ++i) { + nr_rrc_qos_t *qos = find_qos(list, in_qos[i].qfi); + if (qos) { + AssertFatal(qos->qos.qfi == in_qos[i].qfi, "QoS Flow to modify must match existing one"); + LOG_I(NR_RRC, "Updating QoS for QFI=%d\n", in_qos[i].qfi); + qos->qos = in_qos[i]; + } else { + LOG_E(NR_RRC, "Failed to update QoS for QFI=%d: QoS flow not found\n", in_qos[i].qfi); + } + } +} + +/** @brief Update stored pdusession_t in list from NGAP PDU Session Resource item */ +static void nr_rrc_update_pdusession(pdusession_t *dst, const pdusession_resource_item_t *src) +{ + dst->pdusession_id = src->pdusession_id; + dst->nas_pdu = src->nas_pdu; + dst->pdu_session_type = src->pdusessionTransfer.pdu_session_type; + dst->n3_incoming = src->pdusessionTransfer.n3_incoming; + dst->nssai = src->nssai; + DevAssert(dst->qos.data); // QoS list has to be initialized at this stage + // Update QoS flow + nr_rrc_update_qos(&dst->qos, src->pdusessionTransfer.nb_qos, src->pdusessionTransfer.qos); +} + //------------------------------------------------------------------------------ int rrc_gNB_process_NGAP_PDUSESSION_MODIFY_REQ(MessageDef *msg_p, instance_t instance) //------------------------------------------------------------------------------ @@ -900,7 +940,7 @@ int rrc_gNB_process_NGAP_PDUSESSION_MODIFY_REQ(MessageDef *msg_p, instance_t ins all_failed = false; session->status = PDU_SESSION_STATUS_NEW; session->cause.type = NGAP_CAUSE_NOTHING; - cp_pdusession_resource_item_to_pdusession(&session->param, sessMod); + nr_rrc_update_pdusession(&session->param, sessMod); } } @@ -969,20 +1009,20 @@ int rrc_gNB_send_NGAP_PDUSESSION_MODIFY_RESP(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE session->cause.type = NGAP_CAUSE_NOTHING; // Fill response DevAssert(pdu_sessions_done < NGAP_MAX_PDU_SESSION); - resp->pdusessions[pdu_sessions_done].pdusession_id = session->param.pdusession_id; - for (int qos_flow_index = 0; qos_flow_index < session->param.nb_qos; qos_flow_index++) { - resp->pdusessions[pdu_sessions_done].qos[qos_flow_index].qfi = session->param.qos[qos_flow_index].qfi; + pdusession_modify_t *p = &resp->pdusessions[pdu_sessions_done++]; + p->pdusession_id = session->param.pdusession_id; + FOR_EACH_SEQ_ARR(nr_rrc_qos_t *, qos_session, &session->param.qos) { + DevAssert(p->nb_of_qos_flow < QOSFLOW_MAX_VALUE); + qos_flow_tobe_modified_t *q = &p->qos[p->nb_of_qos_flow++]; + q->qfi = qos_session->qos.qfi; } - resp->pdusessions[pdu_sessions_done].pdusession_id = session->param.pdusession_id; - resp->pdusessions[pdu_sessions_done].nb_of_qos_flow = session->param.nb_qos; LOG_I(NR_RRC, "Modify Resp (msg index %d, status %d, xid %d): nb_of_pduSessions %ld, pdusession_id %d \n ", pdu_sessions_done, session->status, xid, seq_arr_size(&UE->pduSessions), - resp->pdusessions[pdu_sessions_done].pdusession_id); - pdu_sessions_done++; + p->pdusession_id); } else if ((session->status == PDU_SESSION_STATUS_NEW) || (session->status == PDU_SESSION_STATUS_ESTABLISHED)) { LOG_D(NR_RRC, "PDU SESSION is NEW or already ESTABLISHED\n"); } else if (session->status == PDU_SESSION_STATUS_FAILED) { @@ -1373,10 +1413,11 @@ void rrc_gNB_send_NGAP_HANDOVER_REQUEST_ACKNOWLEDGE(gNB_RRC_INST *rrc, gNB_RRC_U transfer->gtp_teid = session->param.n3_outgoing.teid; memcpy(transfer->gNB_addr.buffer, session->param.n3_outgoing.addr.buffer, session->param.n3_outgoing.addr.length); transfer->gNB_addr.length = session->param.n3_outgoing.addr.length; - transfer->nb_of_qos_flow = session->param.nb_qos; - for (int q = 0; q < transfer->nb_of_qos_flow; q++) { - transfer->qos_setup_list[q].qfi = session->param.qos[q].qfi; - transfer->qos_setup_list[q].qos_flow_mapping_ind = QOSFLOW_MAPPING_INDICATION_DL; + FOR_EACH_SEQ_ARR(nr_rrc_qos_t *, qos, &session->param.qos) { + DevAssert(transfer->nb_of_qos_flow < QOSFLOW_MAX_VALUE); + pdusession_associate_qosflow_t *qos_setup = &transfer->qos_setup_list[transfer->nb_of_qos_flow++]; + qos_setup->qfi = qos->qos.qfi; + qos_setup->qos_flow_mapping_ind = QOSFLOW_MAPPING_INDICATION_DL; } } // Target to Source Transparent Container @@ -1620,9 +1661,10 @@ void rrc_gNB_send_NGAP_HANDOVER_REQUIRED(gNB_RRC_INST *rrc, DevAssert(msg.source2target->nb_pdu_session_resource < NGAP_MAX_PDU_SESSION); pdusession_resource_info_t *pdu_info = &msg.source2target->pdu_session_resource[msg.source2target->nb_pdu_session_resource++]; pdu_info->pdusession_id = session->pdusession_id; - pdu_info->nb_of_qos_flow = session->nb_qos; - for (int j = 0; j < pdu_info->nb_of_qos_flow; ++j) { - pdu_info->qos_flow_info[j].qfi = session->qos[j].qfi; + FOR_EACH_SEQ_ARR(nr_rrc_qos_t *, qos, &session->qos) { + DevAssert(pdu_info->nb_of_qos_flow < QOSFLOW_MAX_VALUE); + qosflow_info_t *qos_flow = &pdu_info->qos_flow_info[pdu_info->nb_of_qos_flow++]; + qos_flow->qfi = qos->qos.qfi; } } diff --git a/openair2/RRC/NR/rrc_gNB_mobility.c b/openair2/RRC/NR/rrc_gNB_mobility.c index 3c17f45189..0d97e5d30a 100644 --- a/openair2/RRC/NR/rrc_gNB_mobility.c +++ b/openair2/RRC/NR/rrc_gNB_mobility.c @@ -77,11 +77,8 @@ static int fill_drb_to_be_setup(const gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue, f1ap_ rrc_pdu_session_param_t *pdu = find_pduSession_from_drbId(ue, rrc_drb->drb_id); AssertFatal(pdu != NULL, "no PDU session for DRB ID %d\n", rrc_drb->drb_id); - // for the moment, we only support one QoS flow. Put a reminder in case - // this changes - AssertFatal(pdu->param.nb_qos == 1, "only 1 Qos flow supported\n"); int qfi = rrc_drb->cnAssociation.sdap_config.mappedQoS_FlowsToAdd[0]; - pdusession_level_qos_parameter_t *qos_param = get_qos_characteristics(qfi, pdu); + nr_rrc_qos_t *qos_param = find_qos(&pdu->param.qos, qfi); drb->id = rrc_drb->drb_id; @@ -91,7 +88,7 @@ static int fill_drb_to_be_setup(const gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue, f1ap_ drb->nr.flows = calloc_or_fail(1, sizeof(*drb->nr.flows)); DevAssert(qfi > 0); drb->nr.flows[0].qfi = qfi; - drb->nr.flows[0].param = get_qos_char_from_qos_flow_param(qos_param); + drb->nr.flows[0].param = get_qos_char_from_qos_flow_param(&qos_param->qos); /* the DRB QoS parameters: we just reuse the ones from the first flow */ drb->nr.drb_qos = drb->nr.flows[0].param; diff --git a/openair2/RRC/NR/rrc_gNB_radio_bearers.c b/openair2/RRC/NR/rrc_gNB_radio_bearers.c index 1f2f721eaa..ab68a4c367 100644 --- a/openair2/RRC/NR/rrc_gNB_radio_bearers.c +++ b/openair2/RRC/NR/rrc_gNB_radio_bearers.c @@ -33,6 +33,61 @@ #include "openair2/LAYER2/nr_pdcp/nr_pdcp_asn1_utils.h" #include "common/utils/alg/find.h" +static bool eq_qfi(const void *vval, const void *vit) +{ + const int id = *(const int *)vval; + const nr_rrc_qos_t *elem = (const nr_rrc_qos_t *)vit; + return elem->qos.qfi == id; +} + +/** @brief Retrieves mapped QoS in UE context for the input @param qfi + * @return pointer to the found QoS, NULL if not found */ +nr_rrc_qos_t *find_qos(seq_arr_t *seq, int qfi) +{ + DevAssert(seq); + elm_arr_t elm = find_if(seq, &qfi, eq_qfi); + if (elm.found) + return (nr_rrc_qos_t *)elm.it; + return NULL; +} + +/** @brief Adds a new QoS @param in to UE context the list + * @note A UE can have up to 64 QoS flows which can be multiplexed + * into one or more DRBs. The QFI is the unique ID of the mapping. + * @return pointer to the newly added QoS */ +nr_rrc_qos_t *add_qos(seq_arr_t *qos, const pdusession_level_qos_parameter_t *in) +{ + DevAssert(qos); + DevAssert(in); + + if (seq_arr_size(qos) == QOSFLOW_MAX_VALUE) { + LOG_W(NR_RRC, "Reached maximum number of QoS flows = %ld\n", seq_arr_size(qos)); + return NULL; + } + + nr_rrc_qos_t item = {.qos = *in}; + seq_arr_push_back(qos, &item, sizeof(nr_rrc_qos_t)); + + // Double check successful add + nr_rrc_qos_t *added = find_qos(qos, in->qfi); + DevAssert(added); + LOG_I(NR_RRC, "Added QoS flow with qfi=%d, total number of QoS flows = %ld\n", in->qfi, seq_arr_size(qos)); + + // Only one QoS flow is supported + AssertFatal(seq_arr_size(qos) == 1, "only 1 Qos flow supported\n"); + + return added; +} + +/** @brief Free QoS flows list items */ +static void free_qos(void *ptr) { /*nothing to do*/ } + +/** @brief Free QoS flows list */ +static void free_rrc_qos_list(seq_arr_t *seq) +{ + seq_arr_free(seq, free_qos); +} + static bool eq_pdu_session_id(const void *vval, const void *vit) { const int id = *(const int *)vval; @@ -44,6 +99,7 @@ static bool eq_pdu_session_id(const void *vval, const void *vit) void free_pdusession(void *ptr) { rrc_pdu_session_param_t *elem = ptr; + free_rrc_qos_list(&elem->param.qos); free_byte_array(elem->param.nas_pdu); } @@ -210,8 +266,11 @@ drb_t *generateDRB(gNB_RRC_UE_t *ue, est_drb->cnAssociation.sdap_config.sdap_HeaderDL = NR_SDAP_Config__sdap_HeaderDL_absent; est_drb->cnAssociation.sdap_config.sdap_HeaderUL = NR_SDAP_Config__sdap_HeaderUL_absent; } - for (int qos_flow_index = 0; qos_flow_index < pduSession->nb_qos; qos_flow_index++) { - est_drb->cnAssociation.sdap_config.mappedQoS_FlowsToAdd[qos_flow_index] = pduSession->qos[qos_flow_index].qfi; + int qos_flow_index = 0; + FOR_EACH_SEQ_ARR(nr_rrc_qos_t *, qos_session, &pduSession->qos) { + qos_session->drb_id = est_drb->drb_id; // Map DRB to QoS + est_drb->cnAssociation.sdap_config.mappedQoS_FlowsToAdd[qos_flow_index++] = qos_session->qos.qfi; + DevAssert(qos_flow_index <= QOSFLOW_MAX_VALUE); } /* PDCP Configuration */ set_default_drb_pdcp_config(&est_drb->pdcp_config, do_drb_integrity, do_drb_ciphering, pdcp_config, ue->redcap_cap); diff --git a/openair2/RRC/NR/rrc_gNB_radio_bearers.h b/openair2/RRC/NR/rrc_gNB_radio_bearers.h index 982e7ea42d..e5ec90c5c6 100644 --- a/openair2/RRC/NR/rrc_gNB_radio_bearers.h +++ b/openair2/RRC/NR/rrc_gNB_radio_bearers.h @@ -72,4 +72,10 @@ drb_t *nr_rrc_add_drb(seq_arr_t *drb_ptr, int pdusession_id); /// @brief Function to free DRB in RRC void free_drb(void *ptr); +/// @brief retrieve QoS flow associated to @param qfi +nr_rrc_qos_t *find_qos(seq_arr_t *seq, int qfi); + +/// @brief Add a new QoS to the list +nr_rrc_qos_t *add_qos(seq_arr_t *qos, const pdusession_level_qos_parameter_t *in); + #endif From 1711b1b4b8f2fbc19c6c5811032c60115df921a3 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 24 Sep 2025 14:55:52 +0200 Subject: [PATCH 786/964] Refactor ASN.1 PDCP configuration building - Limit scope of get_default_rbconfig function: from asn1_msg.c/.h to rrc_gNB_nsa.c where it's used - Create new rrc_gNB_asn1.c/h files for ASN.1 utility functions: they can be used in other RRC files - Add nr_rrc_build_pdcp_config_ie function for building PDCP configuration IEs - Update get_default_rbconfig to use the new PDCP config builder - Add rrc_gNB_asn1.c to CMakeLists.txt build configuration --- CMakeLists.txt | 1 + openair2/RRC/NR/MESSAGES/asn1_msg.c | 45 --------------------------- openair2/RRC/NR/MESSAGES/asn1_msg.h | 6 ---- openair2/RRC/NR/rrc_gNB_asn1.c | 48 +++++++++++++++++++++++++++++ openair2/RRC/NR/rrc_gNB_asn1.h | 33 ++++++++++++++++++++ openair2/RRC/NR/rrc_gNB_nsa.c | 27 ++++++++++++++++ 6 files changed, 109 insertions(+), 51 deletions(-) create mode 100644 openair2/RRC/NR/rrc_gNB_asn1.c create mode 100644 openair2/RRC/NR/rrc_gNB_asn1.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 528b3e6482..314ee0ee0b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1167,6 +1167,7 @@ set(L2_NR_SRC ${NR_RRC_DIR}/rrc_gNB.c ${NR_RRC_DIR}/mac_rrc_dl_direct.c ${NR_RRC_DIR}/mac_rrc_dl_f1ap.c + ${NR_RRC_DIR}/rrc_gNB_asn1.c ${NR_RRC_DIR}/rrc_gNB_nsa.c ${NR_RRC_DIR}/rrc_gNB_UE_context.c ${NR_RRC_DIR}/rrc_gNB_NGAP.c diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.c b/openair2/RRC/NR/MESSAGES/asn1_msg.c index 51618d1f3e..0ed1750d6b 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.c +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.c @@ -319,51 +319,6 @@ int do_RRCReject(uint8_t *const buffer) return (enc_rval.encoded + 7) / 8; } -/* returns a default radio bearer config suitable for NSA etc */ -NR_RadioBearerConfig_t *get_default_rbconfig(int eps_bearer_id, - int rb_id, - e_NR_CipheringAlgorithm ciphering_algorithm, - e_NR_SecurityConfig__keyToUse key_to_use, - const nr_pdcp_configuration_t *pdcp_config) -{ - NR_RadioBearerConfig_t *rbconfig = calloc(1, sizeof(*rbconfig)); - rbconfig->srb_ToAddModList = NULL; - rbconfig->srb3_ToRelease = NULL; - rbconfig->drb_ToAddModList = calloc(1,sizeof(*rbconfig->drb_ToAddModList)); - NR_DRB_ToAddMod_t *drb_ToAddMod = calloc(1,sizeof(*drb_ToAddMod)); - drb_ToAddMod->cnAssociation = calloc(1,sizeof(*drb_ToAddMod->cnAssociation)); - drb_ToAddMod->cnAssociation->present = NR_DRB_ToAddMod__cnAssociation_PR_eps_BearerIdentity; - drb_ToAddMod->cnAssociation->choice.eps_BearerIdentity= eps_bearer_id; - drb_ToAddMod->drb_Identity = rb_id; - drb_ToAddMod->reestablishPDCP = NULL; - drb_ToAddMod->recoverPDCP = NULL; - drb_ToAddMod->pdcp_Config = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config)); - asn1cCalloc(drb_ToAddMod->pdcp_Config->drb, drb); - asn1cCallocOne(drb->discardTimer, encode_discard_timer(pdcp_config->drb.discard_timer)); - asn1cCallocOne(drb->pdcp_SN_SizeUL, encode_sn_size_ul(pdcp_config->drb.sn_size)); - asn1cCallocOne(drb->pdcp_SN_SizeDL, encode_sn_size_dl(pdcp_config->drb.sn_size)); - drb->headerCompression.present = NR_PDCP_Config__drb__headerCompression_PR_notUsed; - drb->headerCompression.choice.notUsed = 0; - drb->integrityProtection = NULL; - drb->statusReportRequired = NULL; - drb->outOfOrderDelivery = NULL; - - drb_ToAddMod->pdcp_Config->moreThanOneRLC = NULL; - asn1cCallocOne(drb_ToAddMod->pdcp_Config->t_Reordering, encode_t_reordering(pdcp_config->drb.t_reordering)); - drb_ToAddMod->pdcp_Config->ext1 = NULL; - - asn1cSeqAdd(&rbconfig->drb_ToAddModList->list,drb_ToAddMod); - - rbconfig->drb_ToReleaseList = NULL; - - asn1cCalloc(rbconfig->securityConfig, secConf); - asn1cCalloc(secConf->securityAlgorithmConfig, secConfAlgo); - secConfAlgo->cipheringAlgorithm = ciphering_algorithm; - secConfAlgo->integrityProtAlgorithm = NULL; - asn1cCallocOne(secConf->keyToUse, key_to_use); - return rbconfig; -} - //------------------------------------------------------------------------------ int do_RRCSetup(uint8_t *const buffer, size_t buffer_size, diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.h b/openair2/RRC/NR/MESSAGES/asn1_msg.h index 607fa95994..f347f3428c 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.h +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.h @@ -89,12 +89,6 @@ int do_SIB2_NR(uint8_t **msg_SIB2, NR_SSB_MTC_t *ssbmtc); int do_RRCReject(uint8_t *const buffer); -NR_RadioBearerConfig_t *get_default_rbconfig(int eps_bearer_id, - int rb_id, - e_NR_CipheringAlgorithm ciphering_algorithm, - e_NR_SecurityConfig__keyToUse key_to_use, - const nr_pdcp_configuration_t *pdcp_config); - int do_RRCSetup(uint8_t *const buffer, size_t buffer_size, const uint8_t transaction_id, diff --git a/openair2/RRC/NR/rrc_gNB_asn1.c b/openair2/RRC/NR/rrc_gNB_asn1.c new file mode 100644 index 0000000000..17f4bb8af5 --- /dev/null +++ b/openair2/RRC/NR/rrc_gNB_asn1.c @@ -0,0 +1,48 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include +#include "NR_DRB-ToAddMod.h" +#include "NR_RadioBearerConfig.h" +#include "common/utils/oai_asn1.h" +#include "common/utils/LOG/log.h" +#include "openair2/LAYER2/nr_pdcp/nr_pdcp_configuration.h" +#include "openair2/LAYER2/nr_pdcp/nr_pdcp_asn1_utils.h" + +NR_PDCP_Config_t *nr_rrc_build_pdcp_config_ie(const bool integrity, const bool ciphering, const nr_pdcp_configuration_t *pdcp) +{ + NR_PDCP_Config_t *out = calloc_or_fail(1, sizeof(*out)); + asn1cCallocOne(out->t_Reordering, encode_t_reordering(pdcp->drb.t_reordering)); + if (!ciphering) { + asn1cCalloc(out->ext1, ext1); + asn1cCallocOne(ext1->cipheringDisabled, NR_PDCP_Config__ext1__cipheringDisabled_true); + } + asn1cCalloc(out->drb, drb); + asn1cCallocOne(drb->discardTimer, encode_discard_timer(pdcp->drb.discard_timer)); + asn1cCallocOne(drb->pdcp_SN_SizeUL, encode_sn_size_ul(pdcp->drb.sn_size)); + asn1cCallocOne(drb->pdcp_SN_SizeDL, encode_sn_size_dl(pdcp->drb.sn_size)); + drb->headerCompression.present = NR_PDCP_Config__drb__headerCompression_PR_notUsed; + drb->headerCompression.choice.notUsed = 0; + if (integrity) { + asn1cCallocOne(drb->integrityProtection, NR_PDCP_Config__drb__integrityProtection_enabled); + } + return out; +} diff --git a/openair2/RRC/NR/rrc_gNB_asn1.h b/openair2/RRC/NR/rrc_gNB_asn1.h new file mode 100644 index 0000000000..b706a68a15 --- /dev/null +++ b/openair2/RRC/NR/rrc_gNB_asn1.h @@ -0,0 +1,33 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef _RRC_GNB_ASN1_H_ +#define _RRC_GNB_ASN1_H_ + +#include +#include "seq_arr.h" +#include "NR_DRB-ToAddMod.h" +#include "NR_RadioBearerConfig.h" +#include "openair2/LAYER2/nr_pdcp/nr_pdcp_configuration.h" + +NR_PDCP_Config_t *nr_rrc_build_pdcp_config_ie(const bool integrity, const bool ciphering, const nr_pdcp_configuration_t *pdcp); + +#endif diff --git a/openair2/RRC/NR/rrc_gNB_nsa.c b/openair2/RRC/NR/rrc_gNB_nsa.c index aa97a026e0..f0f7201517 100644 --- a/openair2/RRC/NR/rrc_gNB_nsa.c +++ b/openair2/RRC/NR/rrc_gNB_nsa.c @@ -72,6 +72,7 @@ #include "xer_encoder.h" #include "f1ap_common.h" #include "lib/f1ap_ue_context.h" +#include "rrc_gNB_asn1.h" // In case of phy-test and do-ra mode, read UE capabilities directly from file // and put it into a CG-ConfigInfo field @@ -134,6 +135,32 @@ static instance_t get_f1_gtp_instance(void) return inst->gtpInst; } +/* returns a default radio bearer config suitable for NSA etc */ +static NR_RadioBearerConfig_t *get_default_rbconfig(int eps_bearer_id, + int rb_id, + e_NR_CipheringAlgorithm ciphering_algorithm, + e_NR_SecurityConfig__keyToUse key_to_use, + const nr_pdcp_configuration_t *pdcp_config) +{ + NR_RadioBearerConfig_t *rbconfig = calloc_or_fail(1, sizeof(*rbconfig)); + rbconfig->drb_ToAddModList = calloc_or_fail(1, sizeof(*rbconfig->drb_ToAddModList)); + NR_DRB_ToAddMod_t *drb_ToAddMod = calloc_or_fail(1, sizeof(*drb_ToAddMod)); + drb_ToAddMod->drb_Identity = rb_id; + drb_ToAddMod->pdcp_Config = nr_rrc_build_pdcp_config_ie(false, false, pdcp_config); + asn1cCalloc(drb_ToAddMod->cnAssociation, cn_association); + cn_association->present = NR_DRB_ToAddMod__cnAssociation_PR_eps_BearerIdentity; + cn_association->choice.eps_BearerIdentity = eps_bearer_id; + asn1cSeqAdd(&rbconfig->drb_ToAddModList->list, drb_ToAddMod); + asn1cCalloc(rbconfig->securityConfig, secConf); + asn1cCalloc(secConf->securityAlgorithmConfig, secConfAlgo); + secConfAlgo->cipheringAlgorithm = ciphering_algorithm; + secConfAlgo->integrityProtAlgorithm = NULL; + asn1cCallocOne(secConf->keyToUse, key_to_use); + if (LOG_DEBUGFLAG(DEBUG_ASN1)) + xer_fprint(stdout, &asn_DEF_NR_DRB_ToAddMod, drb_ToAddMod); + return rbconfig; +} + /* generate prototypes for the tree management functions (RB_INSERT used in rrc_add_nsa_user) */ RB_PROTOTYPE(rrc_nr_ue_tree_s, rrc_gNB_ue_context_s, entries, rrc_gNB_compare_ue_rnti_id); From 7254e59df911af627ee7410b7bf7eb5ae432af55 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 24 Sep 2025 15:34:01 +0200 Subject: [PATCH 787/964] Introduced MAX_QOS_FLOWS (64) and replaced QOSFLOW_MAX_VALUE The maximum number of QoS flows is 64. - Replace QOSFLOW_MAX_VALUE with MAX_QOS_FLOWS constant - Move MAX_QOS_FLOWS definition to common/platform_constants.h - Remove duplicate QOSFLOW_MAX_VALUE definition from ngap_messages_types.h This improves maintainability by centralizing the QoS flow limit constant and eliminates duplicate definitions across different header files. --- common/platform_constants.h | 3 +++ openair2/COMMON/ngap_messages_types.h | 14 ++++++-------- openair2/RRC/NR/nr_rrc_defs.h | 2 +- openair2/RRC/NR/rrc_gNB_NGAP.c | 14 +++++++------- openair2/RRC/NR/rrc_gNB_radio_bearers.c | 6 +++--- 5 files changed, 20 insertions(+), 19 deletions(-) diff --git a/common/platform_constants.h b/common/platform_constants.h index 00c68bd5b8..4000ffb001 100644 --- a/common/platform_constants.h +++ b/common/platform_constants.h @@ -97,4 +97,7 @@ #define UNUSED_VARIABLE(vARIABLE) (void)(vARIABLE) #define NUM_PRACH_RX_FOR_NOISE_ESTIMATE 100 +// SDAP +#define MAX_QOS_FLOWS 64 + #endif /* __PLATFORM_CONSTANTS_H__ */ diff --git a/openair2/COMMON/ngap_messages_types.h b/openair2/COMMON/ngap_messages_types.h index d5a5aca5aa..a07f798005 100644 --- a/openair2/COMMON/ngap_messages_types.h +++ b/openair2/COMMON/ngap_messages_types.h @@ -91,8 +91,6 @@ #define NGAP_MAX_NB_AMF_IP_ADDRESS 10 #define NGAP_IMSI_LENGTH 16 -#define QOSFLOW_MAX_VALUE 64 - #define NGAP_MAX_NO_TAI_PAGING 16 // 9.2.4.1 3GPP TS 38.413 /* Security key length used within gNB @@ -241,7 +239,7 @@ typedef struct ngap_mobility_restriction_s{ /* PDU Session Resource Setup Request Transfer (9.3.4.1 3GPP TS 38.413) */ typedef struct { uint8_t nb_qos; - pdusession_level_qos_parameter_t qos[QOSFLOW_MAX_VALUE]; + pdusession_level_qos_parameter_t qos[MAX_QOS_FLOWS]; pdu_session_type_t pdu_session_type; // UPF endpoint of the NG-U (N3) transport bearer gtpu_tunnel_t n3_incoming; @@ -272,7 +270,7 @@ typedef struct pdusession_setup_s { uint8_t nb_of_qos_flow; /* qos flow list(1 ~ 64) */ - pdusession_associate_qosflow_t associated_qos_flows[QOSFLOW_MAX_VALUE]; + pdusession_associate_qosflow_t associated_qos_flows[MAX_QOS_FLOWS]; } pdusession_setup_t; typedef struct qos_flow_tobe_modified_s { @@ -286,7 +284,7 @@ typedef struct pdusession_modify_s { uint8_t nb_of_qos_flow; // qos_flow_add_or_modify - qos_flow_tobe_modified_t qos[QOSFLOW_MAX_VALUE]; + qos_flow_tobe_modified_t qos[MAX_QOS_FLOWS]; } pdusession_modify_t; /* Cause (9.3.1.2 of 3GPP TS 38.413) */ @@ -506,7 +504,7 @@ typedef struct { uint8_t pdusession_id; // QoS Flow Information List uint8_t nb_of_qos_flow; - qosflow_info_t qos_flow_info[QOSFLOW_MAX_VALUE]; + qosflow_info_t qos_flow_info[MAX_QOS_FLOWS]; } pdusession_resource_info_t; /* 3GPP TS 38.413 9.3.1.97 */ @@ -627,7 +625,7 @@ typedef struct { typedef struct { // QoS Flow Setup Response List uint8_t nb_of_qos_flow; - pdusession_associate_qosflow_t qos_setup_list[QOSFLOW_MAX_VALUE]; + pdusession_associate_qosflow_t qos_setup_list[MAX_QOS_FLOWS]; // DL NG-U UP TNL Information uint32_t gtp_teid; transport_layer_addr_t gNB_addr; @@ -657,7 +655,7 @@ typedef struct { typedef struct { // QoS Flow to be Forwarded List uint8_t nb_of_qos_flow; - pdusession_associate_qosflow_t qos_setup_list[QOSFLOW_MAX_VALUE]; + pdusession_associate_qosflow_t qos_setup_list[MAX_QOS_FLOWS]; // UL Forwarding UP TNL Information uint32_t gtp_teid; transport_layer_addr_t gNB_addr; diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index 3491154923..65bb3095e7 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -132,7 +132,7 @@ typedef struct drb_s { int pdusession_id; int sdap_HeaderDL; int sdap_HeaderUL; - int mappedQoS_FlowsToAdd[QOSFLOW_MAX_VALUE]; + int mappedQoS_FlowsToAdd[MAX_QOS_FLOWS]; } sdap_config; } cnAssociation; struct pdcp_config_s { diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index e584912a38..4effc47935 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -176,7 +176,7 @@ static void cp_pdusession_transfer_to_pdusession(pdusession_t *dst, const pduses dst->n3_incoming = src->n3_incoming; /* QoS handling */ DevAssert(!dst->qos.data); - DevAssert(src->nb_qos < QOSFLOW_MAX_VALUE); + DevAssert(src->nb_qos < MAX_QOS_FLOWS); // Initialise mapped QoS list per PDU Session seq_arr_init(&dst->qos, sizeof(nr_rrc_qos_t)); // Add QoS flow to list @@ -355,7 +355,7 @@ bool trigger_bearer_setup(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, pdusession FOR_EACH_SEQ_ARR(nr_rrc_qos_t *, qos, &session->qos) { pdusession_level_qos_parameter_t *qos_session = &qos->qos; - DevAssert(drb->numQosFlow2Setup < QOSFLOW_MAX_VALUE); + DevAssert(drb->numQosFlow2Setup < MAX_QOS_FLOWS); qos_flow_to_setup_t *qos_flow = &drb->qosFlows[drb->numQosFlow2Setup++]; qos_characteristics_t *qos_char = &qos_flow->qos_params.qos_characteristics; qos_flow->qfi = qos_session->qfi; @@ -515,7 +515,7 @@ static pdusession_setup_t fill_ngap_pdusession_setup(pdusession_t *session) out.pdu_session_type = session->pdu_session_type; out.n3_outgoing = cp_gtp_tunnel(session->n3_outgoing); FOR_EACH_SEQ_ARR(nr_rrc_qos_t *, qos_session, &session->qos) { - DevAssert(out.nb_of_qos_flow < QOSFLOW_MAX_VALUE); + DevAssert(out.nb_of_qos_flow < MAX_QOS_FLOWS); pdusession_associate_qosflow_t *q = &out.associated_qos_flows[out.nb_of_qos_flow++]; q->qfi = qos_session->qos.qfi; q->qos_flow_mapping_ind = QOSFLOW_MAPPING_INDICATION_DL; @@ -882,7 +882,7 @@ void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(MessageDef *msg_p, instance_t ins static void nr_rrc_update_qos(seq_arr_t *list, const int nb_qos, const pdusession_level_qos_parameter_t *in_qos) { DevAssert(nb_qos == 1); - DevAssert(nb_qos < QOSFLOW_MAX_VALUE); + DevAssert(nb_qos < MAX_QOS_FLOWS); for (uint8_t i = 0; i < nb_qos; ++i) { nr_rrc_qos_t *qos = find_qos(list, in_qos[i].qfi); if (qos) { @@ -1012,7 +1012,7 @@ int rrc_gNB_send_NGAP_PDUSESSION_MODIFY_RESP(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE pdusession_modify_t *p = &resp->pdusessions[pdu_sessions_done++]; p->pdusession_id = session->param.pdusession_id; FOR_EACH_SEQ_ARR(nr_rrc_qos_t *, qos_session, &session->param.qos) { - DevAssert(p->nb_of_qos_flow < QOSFLOW_MAX_VALUE); + DevAssert(p->nb_of_qos_flow < MAX_QOS_FLOWS); qos_flow_tobe_modified_t *q = &p->qos[p->nb_of_qos_flow++]; q->qfi = qos_session->qos.qfi; } @@ -1414,7 +1414,7 @@ void rrc_gNB_send_NGAP_HANDOVER_REQUEST_ACKNOWLEDGE(gNB_RRC_INST *rrc, gNB_RRC_U memcpy(transfer->gNB_addr.buffer, session->param.n3_outgoing.addr.buffer, session->param.n3_outgoing.addr.length); transfer->gNB_addr.length = session->param.n3_outgoing.addr.length; FOR_EACH_SEQ_ARR(nr_rrc_qos_t *, qos, &session->param.qos) { - DevAssert(transfer->nb_of_qos_flow < QOSFLOW_MAX_VALUE); + DevAssert(transfer->nb_of_qos_flow < MAX_QOS_FLOWS); pdusession_associate_qosflow_t *qos_setup = &transfer->qos_setup_list[transfer->nb_of_qos_flow++]; qos_setup->qfi = qos->qos.qfi; qos_setup->qos_flow_mapping_ind = QOSFLOW_MAPPING_INDICATION_DL; @@ -1662,7 +1662,7 @@ void rrc_gNB_send_NGAP_HANDOVER_REQUIRED(gNB_RRC_INST *rrc, pdusession_resource_info_t *pdu_info = &msg.source2target->pdu_session_resource[msg.source2target->nb_pdu_session_resource++]; pdu_info->pdusession_id = session->pdusession_id; FOR_EACH_SEQ_ARR(nr_rrc_qos_t *, qos, &session->qos) { - DevAssert(pdu_info->nb_of_qos_flow < QOSFLOW_MAX_VALUE); + DevAssert(pdu_info->nb_of_qos_flow < MAX_QOS_FLOWS); qosflow_info_t *qos_flow = &pdu_info->qos_flow_info[pdu_info->nb_of_qos_flow++]; qos_flow->qfi = qos->qos.qfi; } diff --git a/openair2/RRC/NR/rrc_gNB_radio_bearers.c b/openair2/RRC/NR/rrc_gNB_radio_bearers.c index ab68a4c367..ccf3fbe99f 100644 --- a/openair2/RRC/NR/rrc_gNB_radio_bearers.c +++ b/openair2/RRC/NR/rrc_gNB_radio_bearers.c @@ -60,7 +60,7 @@ nr_rrc_qos_t *add_qos(seq_arr_t *qos, const pdusession_level_qos_parameter_t *in DevAssert(qos); DevAssert(in); - if (seq_arr_size(qos) == QOSFLOW_MAX_VALUE) { + if (seq_arr_size(qos) == MAX_QOS_FLOWS) { LOG_W(NR_RRC, "Reached maximum number of QoS flows = %ld\n", seq_arr_size(qos)); return NULL; } @@ -270,7 +270,7 @@ drb_t *generateDRB(gNB_RRC_UE_t *ue, FOR_EACH_SEQ_ARR(nr_rrc_qos_t *, qos_session, &pduSession->qos) { qos_session->drb_id = est_drb->drb_id; // Map DRB to QoS est_drb->cnAssociation.sdap_config.mappedQoS_FlowsToAdd[qos_flow_index++] = qos_session->qos.qfi; - DevAssert(qos_flow_index <= QOSFLOW_MAX_VALUE); + DevAssert(qos_flow_index <= MAX_QOS_FLOWS); } /* PDCP Configuration */ set_default_drb_pdcp_config(&est_drb->pdcp_config, do_drb_integrity, do_drb_ciphering, pdcp_config, ue->redcap_cap); @@ -299,7 +299,7 @@ NR_DRB_ToAddMod_t *generateDRB_ASN1(const drb_t *drb_asn1) SDAP_config->sdap_HeaderUL = drb_asn1->cnAssociation.sdap_config.sdap_HeaderUL; SDAP_config->defaultDRB = drb_asn1->cnAssociation.sdap_config.defaultDRB; - for (int qos_flow_index = 0; qos_flow_index < QOSFLOW_MAX_VALUE; qos_flow_index++) { + for (int qos_flow_index = 0; qos_flow_index < MAX_QOS_FLOWS; qos_flow_index++) { if (drb_asn1->cnAssociation.sdap_config.mappedQoS_FlowsToAdd[qos_flow_index] != 0) { asn1cSequenceAdd(sdapFlows->list, NR_QFI_t, qfi); *qfi = drb_asn1->cnAssociation.sdap_config.mappedQoS_FlowsToAdd[qos_flow_index]; From 50923823c0bd295e9ffa6b0a0ffa80a060038d88 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 24 Sep 2025 15:48:40 +0200 Subject: [PATCH 788/964] Refactor QoS parameter types and consolidate definitions - Move QoS-related enums and structures from ngap_messages_types.h to 5g_platform_types.h - Replace ngap_* QoS types with generic qos_* types for better reusability - Update field names from allocation_retention_priority to arp for consistency - Update all references across RRC and NGAP modules to use new type names - Remove duplicate QoS type definitions from NGAP-specific header This improves code organization by centralizing QoS parameter definitions in a common platform types header and eliminates NGAP-specific naming in favor of more generic, reusable type definitions. --- common/5g_platform_types.h | 49 +++++++++++++++++++++++++++ openair2/COMMON/ngap_messages_types.h | 45 ------------------------ openair2/RRC/NR/rrc_gNB.c | 11 +++--- openair2/RRC/NR/rrc_gNB_NGAP.c | 10 +++--- openair3/NGAP/ngap_common.c | 6 ++-- 5 files changed, 62 insertions(+), 59 deletions(-) diff --git a/common/5g_platform_types.h b/common/5g_platform_types.h index b46490a2e8..4ed7f33e47 100644 --- a/common/5g_platform_types.h +++ b/common/5g_platform_types.h @@ -55,4 +55,53 @@ typedef enum { typedef enum { NON_DYNAMIC, DYNAMIC } fiveQI_t; +/* QoS Priority Level */ +typedef enum { + QOS_PRIORITY_SPARE = 0, + QOS_PRIORITY_HIGHEST, + QOS_PRIORITY_2, + QOS_PRIORITY_3, + QOS_PRIORITY_4, + QOS_PRIORITY_5, + QOS_PRIORITY_6, + QOS_PRIORITY_7, + QOS_PRIORITY_8, + QOS_PRIORITY_9, + QOS_PRIORITY_10, + QOS_PRIORITY_11, + QOS_PRIORITY_12, + QOS_PRIORITY_13, + QOS_PRIORITY_LOWEST, + QOS_NO_PRIORITY +} qos_priority_t; + +/* Pre-emption Capability */ +typedef enum { + PEC_SHALL_NOT_TRIGGER_PREEMPTION = 0, + PEC_MAY_TRIGGER_PREEMPTION, + PEC_MAX, +} qos_pec_t; + +/* Pre-emption Vulnerability */ +typedef enum { + PEV_NOT_PREEMPTABLE = 0, + PEV_PREEMPTABLE = 1, + PEV_MAX, +} qos_pev_t; + +/* Allocation Retention Priority */ +typedef struct { + qos_priority_t priority_level; + qos_pec_t pre_emp_capability; + qos_pev_t pre_emp_vulnerability; +} qos_arp_t; + +typedef struct pdusession_level_qos_parameter_s { + uint8_t qfi; + uint64_t fiveQI; + uint64_t qos_priority; + fiveQI_t fiveQI_type; + qos_arp_t arp; +} pdusession_level_qos_parameter_t; + #endif diff --git a/openair2/COMMON/ngap_messages_types.h b/openair2/COMMON/ngap_messages_types.h index a07f798005..1c5fa90868 100644 --- a/openair2/COMMON/ngap_messages_types.h +++ b/openair2/COMMON/ngap_messages_types.h @@ -139,43 +139,6 @@ typedef struct ngap_ambr_s { bitrate_t br_dl; } ngap_ambr_t; -typedef enum ngap_priority_level_s { - NGAP_PRIORITY_LEVEL_SPARE = 0, - NGAP_PRIORITY_LEVEL_HIGHEST = 1, - NGAP_PRIORITY_LEVEL_2 = 2, - NGAP_PRIORITY_LEVEL_3 = 3, - NGAP_PRIORITY_LEVEL_4 = 4, - NGAP_PRIORITY_LEVEL_5 = 5, - NGAP_PRIORITY_LEVEL_6 = 6, - NGAP_PRIORITY_LEVEL_7 = 7, - NGAP_PRIORITY_LEVEL_8 = 8, - NGAP_PRIORITY_LEVEL_9 = 9, - NGAP_PRIORITY_LEVEL_10 = 10, - NGAP_PRIORITY_LEVEL_11 = 11, - NGAP_PRIORITY_LEVEL_12 = 12, - NGAP_PRIORITY_LEVEL_13 = 13, - NGAP_PRIORITY_LEVEL_LOWEST = 14, - NGAP_PRIORITY_LEVEL_NO_PRIORITY = 15 -} ngap_priority_level_t; - -typedef enum ngap_pre_emp_capability_e { - NGAP_PRE_EMPTION_CAPABILITY_SHALL_NOT_TRIGGER_PREEMPTION = 0, - NGAP_PRE_EMPTION_CAPABILITY_MAY_TRIGGER_PREEMPTION = 1, - NGAP_PRE_EMPTION_CAPABILITY_MAX, -} ngap_pre_emp_capability_t; - -typedef enum ngap_pre_emp_vulnerability_e { - NGAP_PRE_EMPTION_VULNERABILITY_NOT_PREEMPTABLE = 0, - NGAP_PRE_EMPTION_VULNERABILITY_PREEMPTABLE = 1, - NGAP_PRE_EMPTION_VULNERABILITY_MAX, -} ngap_pre_emp_vulnerability_t; - -typedef struct ngap_allocation_retention_priority_s { - ngap_priority_level_t priority_level; - ngap_pre_emp_capability_t pre_emp_capability; - ngap_pre_emp_vulnerability_t pre_emp_vulnerability; -} ngap_allocation_retention_priority_t; - typedef struct ngap_security_capabilities_s { uint16_t nRencryption_algorithms; uint16_t nRintegrity_algorithms; @@ -203,14 +166,6 @@ typedef enum ngap_rrc_establishment_cause_e { NGAP_RRC_CAUSE_LAST } ngap_rrc_establishment_cause_t; -typedef struct pdusession_level_qos_parameter_s { - uint8_t qfi; - uint64_t fiveQI; - uint64_t qos_priority; - fiveQI_t fiveQI_type; - ngap_allocation_retention_priority_t allocation_retention_priority; -} pdusession_level_qos_parameter_t; - typedef struct fiveg_s_tmsi_s { uint16_t amf_set_id; uint8_t amf_pointer; diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 5e95ad690a..6c1c80f30e 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -38,6 +38,7 @@ #include #include #include +#include "5g_platform_types.h" #include "openair2/RRC/NR/nr_rrc_proto.h" #include "openair2/RRC/NR/rrc_gNB_UE_context.h" #include "openair3/SECU/key_nas_deriver.h" @@ -2464,13 +2465,11 @@ f1ap_qos_flow_param_t get_qos_char_from_qos_flow_param(const pdusession_level_qo qos_char.qos_type = NON_DYNAMIC; qos_char.nondyn.fiveQI = qos_param->fiveQI; } - const ngap_allocation_retention_priority_t *a = &qos_param->allocation_retention_priority; + const qos_arp_t *a = &qos_param->arp; qos_char.arp.prio = a->priority_level; - qos_char.arp.preempt_cap = a->pre_emp_capability == NGAP_PRE_EMPTION_CAPABILITY_MAY_TRIGGER_PREEMPTION - ? MAY_TRIGGER_PREEMPTION - : SHALL_NOT_TRIGGER_PREEMPTION; - qos_char.arp.preempt_vuln = - a->pre_emp_vulnerability == NGAP_PRE_EMPTION_VULNERABILITY_PREEMPTABLE ? PREEMPTABLE : NOT_PREEMPTABLE; + qos_char.arp.preempt_cap = + a->pre_emp_capability == PEC_MAY_TRIGGER_PREEMPTION ? MAY_TRIGGER_PREEMPTION : SHALL_NOT_TRIGGER_PREEMPTION; + qos_char.arp.preempt_vuln = a->pre_emp_vulnerability == PEV_PREEMPTABLE ? PREEMPTABLE : NOT_PREEMPTABLE; return qos_char; } diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index 4effc47935..7afc7afa23 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -368,11 +368,11 @@ bool trigger_bearer_setup(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, pdusession qos_char->non_dynamic.qos_priority_level = qos_session->qos_priority; } - ngran_allocation_retention_priority_t *rent_priority = &qos_flow->qos_params.alloc_reten_priority; - ngap_allocation_retention_priority_t *rent_priority_in = &qos_session->allocation_retention_priority; - rent_priority->priority_level = rent_priority_in->priority_level; - rent_priority->preemption_capability = rent_priority_in->pre_emp_capability; - rent_priority->preemption_vulnerability = rent_priority_in->pre_emp_vulnerability; + ngran_allocation_retention_priority_t *arp_out = &qos_flow->qos_params.alloc_reten_priority; + qos_arp_t *arp_in = &qos_session->arp; + arp_out->priority_level = arp_in->priority_level; + arp_out->preemption_capability = arp_in->pre_emp_capability; + arp_out->preemption_vulnerability = arp_in->pre_emp_vulnerability; } } } diff --git a/openair3/NGAP/ngap_common.c b/openair3/NGAP/ngap_common.c index 9e3e2e9d13..c3865cff10 100644 --- a/openair3/NGAP/ngap_common.c +++ b/openair3/NGAP/ngap_common.c @@ -201,9 +201,9 @@ pdusession_level_qos_parameter_t fill_qos(uint8_t qfi, const NGAP_QosFlowLevelQo } // Allocation and Retention Priority const NGAP_AllocationAndRetentionPriority_t *arp = ¶ms->allocationAndRetentionPriority; - out.allocation_retention_priority.priority_level = arp->priorityLevelARP; - out.allocation_retention_priority.pre_emp_capability = arp->pre_emptionCapability; - out.allocation_retention_priority.pre_emp_vulnerability = arp->pre_emptionVulnerability; + out.arp.priority_level = arp->priorityLevelARP; + out.arp.pre_emp_capability = arp->pre_emptionCapability; + out.arp.pre_emp_vulnerability = arp->pre_emptionVulnerability; return out; } From 6ed08f15271e178a77850e973ea18c3f3e395f92 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 24 Sep 2025 16:04:23 +0200 Subject: [PATCH 789/964] Refactor DRB and QoS handling: centralize configuration logic Motivation: The previous architecture had several issues: - Duplicate DRB generation logic in generateDRB() and generateDRB_ASN1() - Embedded SDAP/PDCP configs in drb_t created tight coupling - No clear separation between RRC internal state and ASN.1 encoding - Maintenance burden due to duplicated configuration logic New Architecture: - drb_t now only stores DRB-specific data (ID, PDU session ID, PDCP config) - SDAP configuration moved to PDU session level (following PDCP design pattern) - ASN.1 encoding helpers (nr_rrc_build_*_config_ie()) handle conversion - Single source of truth for DRB creation in RRC via nr_rrc_add_drb() Key changes: - Store nr_sdap_configuration_t per PDU session - Simplified drb_t structure: removed embedded SDAP/PDCP configs, added pdusession_id - New helper: nr_rrc_build_sdap_config_ie() - Updated createDRBlist() to use new helper functions and proper DRB ID lookup - Refactored trigger_bearer_setup() to use nr_rrc_add_drb() and fill_e1_drb_to_setup() - Removed generateDRB() and generateDRB_ASN1() functions - Updated set_bearer_context_pdcp_config() to return config by value - Added SDAP configuration header file for type definitions This eliminates code duplication, improves maintainability, and creates a cleaner separation between RRC state management and ASN.1 encoding. --- openair2/RRC/NR/nr_rrc_defs.h | 32 +--- openair2/RRC/NR/nr_rrc_proto.h | 2 +- openair2/RRC/NR/rrc_gNB.c | 82 +++++++++-- openair2/RRC/NR/rrc_gNB_NGAP.c | 117 ++++++++------- openair2/RRC/NR/rrc_gNB_mobility.c | 18 ++- openair2/RRC/NR/rrc_gNB_radio_bearers.c | 137 +++--------------- openair2/RRC/NR/rrc_gNB_radio_bearers.h | 30 +--- openair2/SDAP/nr_sdap/nr_sdap_configuration.h | 33 +++++ 8 files changed, 209 insertions(+), 242 deletions(-) create mode 100644 openair2/SDAP/nr_sdap/nr_sdap_configuration.h diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index 65bb3095e7..e76802338c 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -56,6 +56,7 @@ #include "intertask_interface.h" #include "openair2/LAYER2/nr_pdcp/nr_pdcp_configuration.h" #include "openair2/LAYER2/nr_rlc/nr_rlc_configuration.h" +#include "openair2/SDAP/nr_sdap/nr_sdap_configuration.h" typedef enum { NR_RRC_OK=0, @@ -112,6 +113,8 @@ typedef struct pdusession_s { // UPF endpoint of the NG-U (N3) transport bearer gtpu_tunnel_t n3_incoming; nssai_t nssai; + // PDU Session specific SDAP configuration + nr_sdap_configuration_t sdap_config; } pdusession_t; typedef struct pdu_session_param_s { @@ -124,35 +127,13 @@ typedef struct pdu_session_param_s { typedef struct drb_s { int status; int drb_id; - struct cnAssociation_s { - int present; - int eps_BearerIdentity; - struct sdap_config_s { - bool defaultDRB; - int pdusession_id; - int sdap_HeaderDL; - int sdap_HeaderUL; - int mappedQoS_FlowsToAdd[MAX_QOS_FLOWS]; - } sdap_config; - } cnAssociation; - struct pdcp_config_s { - int discardTimer; - int pdcp_SN_SizeUL; - int pdcp_SN_SizeDL; - int t_Reordering; - int integrityProtection; - struct headerCompression_s { - int NotUsed; - int present; - } headerCompression; - struct ext1_s { - int cipheringDisabled; - } ext1; - } pdcp_config; + int pdusession_id; // F1-U Downlink Tunnel Config (on DU side) gtpu_tunnel_t du_tunnel_config; // F1-U Uplink Tunnel Config (on CU-UP side) gtpu_tunnel_t cuup_tunnel_config; + // DRB-specific PDCP configuration + nr_pdcp_configuration_t pdcp_config; } drb_t; typedef enum { @@ -405,6 +386,7 @@ typedef struct gNB_RRC_INST_s { RB_HEAD(rrc_cuup_tree, nr_rrc_cuup_container_t) cuups; // CU-UPs, indexed by assoc_id size_t num_cuups; + // PDCP configuration parameters loaded during startup nr_pdcp_configuration_t pdcp_config; nr_rlc_configuration_t rlc_config; } gNB_RRC_INST; diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h index d7c1c0efce..fbd09d20a1 100644 --- a/openair2/RRC/NR/nr_rrc_proto.h +++ b/openair2/RRC/NR/nr_rrc_proto.h @@ -125,7 +125,7 @@ nr_rrc_reconfig_param_t get_RRCReconfiguration_params(gNB_RRC_INST *rrc, gNB_RRC f1ap_qos_flow_param_t get_qos_char_from_qos_flow_param(const pdusession_level_qos_parameter_t *qos_param); void openair_rrc_gNB_configuration(gNB_RRC_INST *rrc, gNB_RrcConfigurationReq *configuration); NR_SRB_ToAddModList_t *createSRBlist(gNB_RRC_UE_t *ue, uint8_t reestablish); -NR_DRB_ToAddModList_t *createDRBlist(gNB_RRC_UE_t *ue, bool reestablish); +NR_DRB_ToAddModList_t *createDRBlist(gNB_RRC_UE_t *ue, bool reestablish, bool do_integrity, bool do_ciphering); void activate_srb(gNB_RRC_UE_t *UE, int srb_id); void e1_send_bearer_updates(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, f1ap_drb_setup_t *drbs, const ngap_drb_status_t *drb_status); diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 6c1c80f30e..4af378dd81 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -87,6 +87,7 @@ #include "rrc_gNB_mobility.h" #include "rrc_gNB_radio_bearers.h" #include "rrc_messages_types.h" +#include "rrc_gNB_asn1.h" #include "seq_arr.h" #include "tree.h" #include "uper_decoder.h" @@ -100,6 +101,7 @@ #include "ds/byte_array.h" #include "alg/find.h" #include "NR_HandoverCommand.h" +#include "openair2/SDAP/nr_sdap/nr_sdap_configuration.h" #ifdef E2_AGENT #include "openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc_extern.h" @@ -330,17 +332,63 @@ NR_SRB_ToAddModList_t *createSRBlist(gNB_RRC_UE_t *ue, uint8_t reestablish) return list; } -NR_DRB_ToAddModList_t *createDRBlist(gNB_RRC_UE_t *ue, bool reestablish) +static NR_SDAP_Config_t *nr_rrc_build_sdap_config_ie(const int pdusession_id, + uint8_t n_flows, + pdusession_level_qos_parameter_t *qos, + const nr_sdap_configuration_t *sdap_config) +{ + DevAssert(n_flows < MAX_QOS_FLOWS); + // SDAP + NR_SDAP_Config_t *sc = calloc_or_fail(1, sizeof(*sc)); + sc->defaultDRB = true; + sc->pdu_Session = pdusession_id; + sc->sdap_HeaderDL = sdap_config->header_dl_absent ? NR_SDAP_Config__sdap_HeaderDL_absent : NR_SDAP_Config__sdap_HeaderDL_present; + sc->sdap_HeaderUL = sdap_config->header_ul_absent ? NR_SDAP_Config__sdap_HeaderUL_absent : NR_SDAP_Config__sdap_HeaderUL_present; + // QoS + asn1cCalloc(sc->mappedQoS_FlowsToAdd, mappedQoS_FlowsToAdd); + for (uint8_t i = 0; i < n_flows; ++i) { + DevAssert(i < MAX_QOS_FLOWS); + NR_QFI_t *qfi = calloc_or_fail(1, sizeof(*qfi)); + *qfi = qos[i].qfi; + LOG_D(NR_RRC, "Adding QFI %ld to PDU Session %d\n", *qfi, pdusession_id); + asn1cSeqAdd(&mappedQoS_FlowsToAdd->list, qfi); + } + return sc; +} + +NR_DRB_ToAddModList_t *createDRBlist(gNB_RRC_UE_t *ue, bool reestablish, bool do_integrity, bool do_ciphering) { - NR_DRB_ToAddMod_t *DRB_config = NULL; NR_DRB_ToAddModList_t *DRB_configList = CALLOC(sizeof(*DRB_configList), 1); FOR_EACH_SEQ_ARR(drb_t *, drb, &ue->drbs) { - DRB_config = generateDRB_ASN1(drb); - if (reestablish) { - asn1cCallocOne(DRB_config->reestablishPDCP, NR_DRB_ToAddMod__reestablishPDCP_true); + rrc_pdu_session_param_t *pduSession = find_pduSession(&ue->pduSessions, drb->pdusession_id); + if (!pduSession) { + LOG_D(NR_RRC, "PDU Session %d not found, skip\n", drb->pdusession_id); + continue; } - asn1cSeqAdd(&DRB_configList->list, DRB_config); + pdusession_t *session = &pduSession->param; + NR_DRB_ToAddMod_t *drb_ToAddMod = calloc_or_fail(1, sizeof(*drb_ToAddMod)); + drb_ToAddMod->drb_Identity = drb->drb_id; + // PDCP config + drb_ToAddMod->pdcp_Config = nr_rrc_build_pdcp_config_ie(do_integrity, do_ciphering, &drb->pdcp_config); + if (reestablish) { + asn1cCallocOne(drb_ToAddMod->reestablishPDCP, NR_DRB_ToAddMod__reestablishPDCP_true); + } + // cn-association: SDAP config + // Get all QoS flows mapped to this DRB + pdusession_level_qos_parameter_t flows_to_add[MAX_QOS_FLOWS] = {0}; + uint8_t n_flows = 0; + FOR_EACH_SEQ_ARR(nr_rrc_qos_t *, q, &session->qos) + { + if (q->drb_id == drb->drb_id) { + DevAssert(n_flows < MAX_QOS_FLOWS); + flows_to_add[n_flows++] = q->qos; + } + } + asn1cCalloc(drb_ToAddMod->cnAssociation, cn_association); + cn_association->present = NR_DRB_ToAddMod__cnAssociation_PR_sdap_Config; + cn_association->choice.sdap_Config = nr_rrc_build_sdap_config_ie(drb->pdusession_id, n_flows, flows_to_add, &session->sdap_config); + asn1cSeqAdd(&DRB_configList->list, drb_ToAddMod); } if (DRB_configList->list.count == 0) { free(DRB_configList); @@ -644,8 +692,10 @@ nr_rrc_reconfig_param_t get_RRCReconfiguration_params(gNB_RRC_INST *rrc, gNB_RRC uint8_t xid = rrc_gNB_get_next_transaction_identifier(rrc->module_id); // Re-establish PDCP for SRB2 only + bool do_integrity = rrc->security.do_drb_integrity; + bool do_ciphering = rrc->security.do_drb_ciphering; NR_SRB_ToAddModList_t *SRBs = createSRBlist(UE, srb_reest_bitmap); - NR_DRB_ToAddModList_t *DRBs = createDRBlist(UE, drb_reestablish); + NR_DRB_ToAddModList_t *DRBs = createDRBlist(UE, drb_reestablish, do_integrity, do_ciphering); nr_rrc_reconfig_param_t params = {.cell_group_config = UE->masterCellGroup, .transaction_id = xid, @@ -882,9 +932,8 @@ static void cuup_notify_reestablishment(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue_p) /* PDCP configuration */ if (!drb_e1->pdcp_config) drb_e1->pdcp_config = malloc_or_fail(sizeof(*drb_e1->pdcp_config)); - bearer_context_pdcp_config_t *pdcp_config = drb_e1->pdcp_config; - set_bearer_context_pdcp_config(pdcp_config, drb, rrc->configuration.um_on_default_drb); - pdcp_config->pDCP_Reestablishment = true; + *drb_e1->pdcp_config = set_bearer_context_pdcp_config(drb->pdcp_config, rrc->configuration.um_on_default_drb, ue_p->redcap_cap); + drb_e1->pdcp_config->pDCP_Reestablishment = true; /* increase DRB to modify counter */ pdu_e1->numDRB2Modify += 1; } @@ -1048,7 +1097,9 @@ static void rrc_gNB_process_RRCReestablishmentComplete(gNB_RRC_INST *rrc, gNB_RR * or at the first reconfiguration after RRC connection reestablishment in NR */ NR_SRB_ToAddModList_t *SRBs = createSRBlist(ue_p, 1 << SRB2); // Re-establish PDCP for SRB2 only /* Create drb-ToAddModList */ - NR_DRB_ToAddModList_t *DRBs = createDRBlist(ue_p, true); + bool do_integrity = rrc->security.do_drb_integrity; + bool do_ciphering = rrc->security.do_drb_ciphering; + NR_DRB_ToAddModList_t *DRBs = createDRBlist(ue_p, true, do_integrity, do_ciphering); uint8_t new_xid = rrc_gNB_get_next_transaction_identifier(rrc->module_id); ue_p->xids[new_xid] = RRC_REESTABLISH_COMPLETE; @@ -2077,7 +2128,8 @@ static void fill_e1_bearer_modif_pdcp_status(gNB_RRC_UE_t *UE, drb_to_mod->pdcp_sn_status_requested = false; // PDCP SN Status Information drb_to_mod->pdcp_config = calloc_or_fail(1, sizeof(*drb_to_mod->pdcp_config)); - set_bearer_context_pdcp_config(drb_to_mod->pdcp_config, get_drb(&UE->drbs, drb_id), um_on_default_drb); + drb_t *drb = get_drb(&UE->drbs, drb_id); + *drb_to_mod->pdcp_config = set_bearer_context_pdcp_config(drb->pdcp_config, um_on_default_drb, UE->redcap_cap); drb_to_mod->pdcp_status = calloc_or_fail(1, sizeof(*drb_to_mod->pdcp_status)); drb_to_mod->pdcp_status->dl_count.hfn = drb_status->dl_count.hfn; drb_to_mod->pdcp_status->dl_count.sn = drb_status->dl_count.pdcp_sn; @@ -2488,6 +2540,7 @@ static int fill_drb_to_be_setup_from_e1_resp(const gNB_RRC_INST *rrc, for (int i = 0; i < pduSession[p].numDRBSetup; i++) { const DRB_nGRAN_setup_t *drb_config = &pduSession[p].DRBnGRanList[i]; drb_t *rrc_drb = get_drb(&UE->drbs, pduSession[p].DRBnGRanList[i].id); + nr_pdcp_configuration_t pdcp = rrc_drb->pdcp_config; DevAssert(rrc_drb); DevAssert(nb_drb < MAX_DRBS_PER_UE); @@ -2522,10 +2575,11 @@ static int fill_drb_to_be_setup_from_e1_resp(const gNB_RRC_INST *rrc, drb->up_ul_tnl[0].teid = drb_config->UpParamList[0].tl_info.teId; drb->up_ul_tnl_len = 1; drb->rlc_mode = rrc->configuration.um_on_default_drb ? F1AP_RLC_MODE_UM_BIDIR : F1AP_RLC_MODE_AM; + DevAssert(pdcp.drb.sn_size == 18 || pdcp.drb.sn_size == 12); drb->dl_pdcp_sn_len = malloc_or_fail(sizeof(*drb->dl_pdcp_sn_len)); - *drb->dl_pdcp_sn_len = rrc_drb->pdcp_config.pdcp_SN_SizeDL == 1 ? F1AP_PDCP_SN_18B : F1AP_PDCP_SN_12B; + *drb->dl_pdcp_sn_len = pdcp.drb.sn_size == 18 ? F1AP_PDCP_SN_18B : F1AP_PDCP_SN_12B; drb->ul_pdcp_sn_len = malloc_or_fail(sizeof(*drb->ul_pdcp_sn_len)); - *drb->ul_pdcp_sn_len = rrc_drb->pdcp_config.pdcp_SN_SizeUL == 1 ? F1AP_PDCP_SN_18B : F1AP_PDCP_SN_12B; + *drb->ul_pdcp_sn_len = pdcp.drb.sn_size == 18 ? F1AP_PDCP_SN_18B : F1AP_PDCP_SN_12B; nb_drb++; } diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index 7afc7afa23..90a0522886 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -42,6 +42,8 @@ #include "NR_UE-CapabilityRAT-ContainerList.h" #include "NR_HandoverCommand.h" #include "NR_HandoverCommand-IEs.h" +#include "E1AP_RLC-Mode.h" +#include "NR_PDCP-Config.h" #include "NGAP_CauseRadioNetwork.h" #include "NGAP_Dynamic5QIDescriptor.h" #include "NGAP_GTPTunnel.h" @@ -264,6 +266,57 @@ void rrc_gNB_send_NGAP_NAS_FIRST_REQ(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, NR_RRC itti_send_msg_to_task(TASK_NGAP, rrc->module_id, message_p); } +/** @brief Returns an instance of E1AP DRB To Setup List */ +static DRB_nGRAN_to_setup_t fill_e1_drb_to_setup(const drb_t *rrc_drb, + const pdusession_t *session, + bool const um_on_default_drb, + const nr_redcap_ue_cap_t *redcap_cap) +{ + DRB_nGRAN_to_setup_t drb_ngran = {0}; + drb_ngran.id = rrc_drb->drb_id; + + drb_ngran.sdap_config.defaultDRB = true; + drb_ngran.sdap_config.sDAP_Header_UL = session->sdap_config.header_ul_absent ? 1 : 0; + drb_ngran.sdap_config.sDAP_Header_DL = session->sdap_config.header_dl_absent ? 1 : 0; + + drb_ngran.pdcp_config = set_bearer_context_pdcp_config(rrc_drb->pdcp_config, um_on_default_drb, redcap_cap); + + drb_ngran.numCellGroups = 1; + for (int k = 0; k < drb_ngran.numCellGroups; k++) { + drb_ngran.cellGroupList[k] = MCG; // 1 cellGroup only + } + + FOR_EACH_SEQ_ARR(nr_rrc_qos_t *, qos, &session->qos) { + pdusession_level_qos_parameter_t *qos_session = &qos->qos; + DevAssert(drb_ngran.numQosFlow2Setup < MAX_QOS_FLOWS); + qos_flow_to_setup_t *qos_flow = &drb_ngran.qosFlows[drb_ngran.numQosFlow2Setup++]; + qos_characteristics_t *qos_char = &qos_flow->qos_params.qos_characteristics; + qos_flow->qfi = qos_session->qfi; + qos_char->qos_type = qos_session->fiveQI_type; + if (qos_char->qos_type == DYNAMIC) { + qos_char->dynamic.fiveqi = qos_session->fiveQI; + qos_char->dynamic.qos_priority_level = qos_session->qos_priority; + } else { + qos_char->non_dynamic.fiveqi = qos_session->fiveQI; + qos_char->non_dynamic.qos_priority_level = qos_session->qos_priority; + } + + ngran_allocation_retention_priority_t *arp_out = &qos_flow->qos_params.alloc_reten_priority; + qos_arp_t *arp_in = &qos_session->arp; + arp_out->priority_level = arp_in->priority_level; + arp_out->preemption_capability = arp_in->pre_emp_capability; + arp_out->preemption_vulnerability = arp_in->pre_emp_vulnerability; + } + + return drb_ngran; +} + +static nr_sdap_configuration_t get_sdap_config(const bool enable_sdap) +{ + nr_sdap_configuration_t sdap = {.header_dl_absent = !enable_sdap, .header_ul_absent = !enable_sdap}; + return sdap; +} + /** * @brief Triggers bearer setup for the specified UE. * @@ -289,13 +342,14 @@ bool trigger_bearer_setup(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, pdusession e1ap_nssai_t cuup_nssai = {0}; for (int i = 0; i < n; i++) { + // Retrieve SDAP configuration and PDU Session to the list + sessions[i].sdap_config = get_sdap_config(rrc->configuration.enable_sdap); rrc_pdu_session_param_t *pduSession = add_pduSession(&UE->pduSessions, &sessions[i]); if (!pduSession) { LOG_E(NR_RRC, "Could not add PDU Session %d for UE %d\n", sessions[i].pdusession_id, UE->rrc_ue_id); continue; } pdusession_t *session = &pduSession->param; - LOG_I(NR_RRC, "Add PDU Session %d (total nb of sessions = %ld)\n", session->pdusession_id, seq_arr_size(&UE->pduSessions)); // Fill E1 Bearer Context Modification Request bearer_req.gNB_cu_cp_ue_id = UE->rrc_ue_id; security_information_t *secInfo = &bearer_req.secInfo; @@ -323,57 +377,18 @@ bool trigger_bearer_setup(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, pdusession inet_ntop(AF_INET, n3_incoming->addr.buffer, ip_str, sizeof(ip_str)); LOG_I(NR_RRC, "Bearer Context Setup: PDU Session ID=%d, incoming TEID=0x%08x, Addr=%s\n", session->pdusession_id, n3_incoming->teid, ip_str); - /* we assume for the moment one DRB per PDU session. Activate the bearer, - * and configure in RRC. */ - drb_t *rrc_drb = generateDRB(UE, - session, - rrc->configuration.enable_sdap, - rrc->security.do_drb_integrity, - rrc->security.do_drb_ciphering, - &rrc->pdcp_config); - pdu->numDRB2Setup = 1; // One DRB per PDU Session. TODO: Remove hardcoding - for (int j=0; j < pdu->numDRB2Setup; j++) { - DRB_nGRAN_to_setup_t *drb = pdu->DRBnGRanList + j; - - drb->id = rrc_drb->drb_id; - /* SDAP */ - struct sdap_config_s *sdap_config = &rrc_drb->cnAssociation.sdap_config; - drb->sdap_config.defaultDRB = sdap_config->defaultDRB; - drb->sdap_config.sDAP_Header_UL = sdap_config->sdap_HeaderUL; - drb->sdap_config.sDAP_Header_DL = sdap_config->sdap_HeaderDL; - /* PDCP */ - set_bearer_context_pdcp_config(&drb->pdcp_config, rrc_drb, rrc->configuration.um_on_default_drb); - - drb->numCellGroups = 1; // assume one cell group associated with a DRB - - // Set all Cell Group IDs to MCG - for (int k=0; k < drb->numCellGroups; k++) { - cell_group_id_t *cellGroup = drb->cellGroupList + k; - *cellGroup = MCG; - } - - FOR_EACH_SEQ_ARR(nr_rrc_qos_t *, qos, &session->qos) { - pdusession_level_qos_parameter_t *qos_session = &qos->qos; - DevAssert(drb->numQosFlow2Setup < MAX_QOS_FLOWS); - qos_flow_to_setup_t *qos_flow = &drb->qosFlows[drb->numQosFlow2Setup++]; - qos_characteristics_t *qos_char = &qos_flow->qos_params.qos_characteristics; - qos_flow->qfi = qos_session->qfi; - qos_char->qos_type = qos_session->fiveQI_type; - if (qos_char->qos_type == DYNAMIC) { - qos_char->dynamic.fiveqi = qos_session->fiveQI; - qos_char->dynamic.qos_priority_level = qos_session->qos_priority; - } else { - qos_char->non_dynamic.fiveqi = qos_session->fiveQI; - qos_char->non_dynamic.qos_priority_level = qos_session->qos_priority; - } - - ngran_allocation_retention_priority_t *arp_out = &qos_flow->qos_params.alloc_reten_priority; - qos_arp_t *arp_in = &qos_session->arp; - arp_out->priority_level = arp_in->priority_level; - arp_out->preemption_capability = arp_in->pre_emp_capability; - arp_out->preemption_vulnerability = arp_in->pre_emp_vulnerability; + for (int j = 0; j < pdu->numDRB2Setup; j++) { + drb_t *rrc_drb = nr_rrc_add_drb(&UE->drbs, session->pdusession_id, &rrc->pdcp_config); + if (!rrc_drb) { + LOG_E(NR_RRC, "UE %d: failed to add DRB for PDU session ID %d\n", UE->rrc_ue_id, session->pdusession_id); + return false; } + DevAssert(seq_arr_size(&pduSession->param.qos) == 1); + nr_rrc_qos_t *qos = (nr_rrc_qos_t *)seq_arr_at(&pduSession->param.qos, 0); + qos->drb_id = rrc_drb->drb_id; // map DRB to QFI + LOG_I(NR_RRC, "UE %d: added DRB %d for PDU session ID %d\n", UE->rrc_ue_id, rrc_drb->drb_id, rrc_drb->pdusession_id); + pdu->DRBnGRanList[0] = fill_e1_drb_to_setup(rrc_drb, session, rrc->configuration.um_on_default_drb, UE->redcap_cap); } } /* Limitation: we assume one fixed CU-UP per UE. We base the selection on @@ -1231,7 +1246,7 @@ int rrc_gNB_send_NGAP_ul_ran_status_transfer(gNB_RRC_INST *rrc, continue; } - bool sn_length_18 = drb->pdcp_config.pdcp_SN_SizeDL == NR_PDCP_Config__drb__pdcp_SN_SizeUL_len18bits; + bool sn_length_18 = drb->pdcp_config.drb.sn_size == 18; DevAssert(msg.ran_status.nb_drb < MAX_DRBS_PER_UE); ngap_drb_status_t *item = &msg.ran_status.drb_status_list[msg.ran_status.nb_drb++]; diff --git a/openair2/RRC/NR/rrc_gNB_mobility.c b/openair2/RRC/NR/rrc_gNB_mobility.c index 0d97e5d30a..552cc881d6 100644 --- a/openair2/RRC/NR/rrc_gNB_mobility.c +++ b/openair2/RRC/NR/rrc_gNB_mobility.c @@ -72,22 +72,25 @@ static int fill_drb_to_be_setup(const gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue, f1ap_ FOR_EACH_SEQ_ARR(drb_t *, rrc_drb, &ue->drbs) { DevAssert(nb_drb < MAX_DRBS_PER_UE); f1ap_drb_to_setup_t *drb = &drbs[nb_drb]; + nr_pdcp_configuration_t *pdcp = &rrc_drb->pdcp_config; nb_drb++; /* fetch an existing PDU session for this DRB */ rrc_pdu_session_param_t *pdu = find_pduSession_from_drbId(ue, rrc_drb->drb_id); AssertFatal(pdu != NULL, "no PDU session for DRB ID %d\n", rrc_drb->drb_id); - int qfi = rrc_drb->cnAssociation.sdap_config.mappedQoS_FlowsToAdd[0]; - nr_rrc_qos_t *qos_param = find_qos(&pdu->param.qos, qfi); - drb->id = rrc_drb->drb_id; drb->qos_choice = F1AP_QOS_CHOICE_NR; drb->nr.nssai = pdu->param.nssai; drb->nr.flows_len = 1; drb->nr.flows = calloc_or_fail(1, sizeof(*drb->nr.flows)); - DevAssert(qfi > 0); - drb->nr.flows[0].qfi = qfi; + + // Find the QoS flow associated with this DRB + // Since we don't have QFI mapping in the new structure, we'll use the first QoS flow + AssertFatal(seq_arr_size(&pdu->param.qos) == 1, "only 1 Qos flow supported\n"); + nr_rrc_qos_t *qos_param = (nr_rrc_qos_t *)seq_arr_at(&pdu->param.qos, 0); + DevAssert(qos_param->qos.qfi > 0); + drb->nr.flows[0].qfi = qos_param->qos.qfi; drb->nr.flows[0].param = get_qos_char_from_qos_flow_param(&qos_param->qos); /* the DRB QoS parameters: we just reuse the ones from the first flow */ drb->nr.drb_qos = drb->nr.flows[0].param; @@ -97,10 +100,11 @@ static int fill_drb_to_be_setup(const gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue, f1ap_ drb->up_ul_tnl_len = 1; drb->rlc_mode = rrc->configuration.um_on_default_drb ? F1AP_RLC_MODE_UM_BIDIR : F1AP_RLC_MODE_AM; + DevAssert(pdcp->drb.sn_size == 18 || pdcp->drb.sn_size == 12); drb->dl_pdcp_sn_len = malloc_or_fail(sizeof(*drb->dl_pdcp_sn_len)); - *drb->dl_pdcp_sn_len = rrc_drb->pdcp_config.pdcp_SN_SizeDL == 1 ? F1AP_PDCP_SN_18B : F1AP_PDCP_SN_12B; + *drb->dl_pdcp_sn_len = pdcp->drb.sn_size == 18 ? F1AP_PDCP_SN_18B : F1AP_PDCP_SN_12B; drb->ul_pdcp_sn_len = malloc_or_fail(sizeof(*drb->ul_pdcp_sn_len)); - *drb->ul_pdcp_sn_len = rrc_drb->pdcp_config.pdcp_SN_SizeUL == 1 ? F1AP_PDCP_SN_18B : F1AP_PDCP_SN_12B;; + *drb->ul_pdcp_sn_len = pdcp->drb.sn_size == 18 ? F1AP_PDCP_SN_18B : F1AP_PDCP_SN_12B; } return nb_drb; } diff --git a/openair2/RRC/NR/rrc_gNB_radio_bearers.c b/openair2/RRC/NR/rrc_gNB_radio_bearers.c index ccf3fbe99f..5af84f0399 100644 --- a/openair2/RRC/NR/rrc_gNB_radio_bearers.c +++ b/openair2/RRC/NR/rrc_gNB_radio_bearers.c @@ -142,9 +142,11 @@ rrc_pdu_session_param_t *add_pduSession(seq_arr_t *sessions_ptr, const pdusessio } /** @brief Add drb_t item in the UE context list for @param pdusession_id */ -drb_t *nr_rrc_add_drb(seq_arr_t *drb_ptr, int pdusession_id) +drb_t *nr_rrc_add_drb(seq_arr_t *drb_ptr, int pdusession_id, nr_pdcp_configuration_t *pdcp) { DevAssert(drb_ptr); + DevAssert(pdcp != NULL); + DevAssert(pdusession_id > 0 && pdusession_id <= NGAP_MAX_PDU_SESSION); // Get next available DRB ID int drb_id = 0; @@ -162,7 +164,7 @@ drb_t *nr_rrc_add_drb(seq_arr_t *drb_ptr, int pdusession_id) } // Add item to the list - drb_t in = {.drb_id = drb_id, .cnAssociation.sdap_config.pdusession_id = pdusession_id}; + drb_t in = {.drb_id = drb_id, .pdusession_id = pdusession_id, .pdcp_config = *pdcp}; seq_arr_push_back(drb_ptr, &in, sizeof(drb_t)); drb_t *out = get_drb(drb_ptr, drb_id); DevAssert(out); @@ -201,129 +203,26 @@ rrc_pdu_session_param_t *find_pduSession_from_drbId(gNB_RRC_UE_t *ue, int drb_id LOG_E(NR_RRC, "UE %d: DRB %d not found\n", ue->rrc_ue_id, drb_id); return NULL; } - int id = drb->cnAssociation.sdap_config.pdusession_id; + int id = drb->pdusession_id; return find_pduSession(&ue->pduSessions, id); } -void set_default_drb_pdcp_config(struct pdcp_config_s *pdcp_config, - int do_drb_integrity, - int do_drb_ciphering, - const nr_pdcp_configuration_t *default_pdcp_config, - const nr_redcap_ue_cap_t *redcap_cap) +bearer_context_pdcp_config_t set_bearer_context_pdcp_config(const nr_pdcp_configuration_t pdcp, + bool um_on_default_drb, + const nr_redcap_ue_cap_t *redcap_cap) { - AssertError(pdcp_config != NULL, return, "Failed to set default PDCP configuration for DRB!\n"); - pdcp_config->discardTimer = encode_discard_timer(default_pdcp_config->drb.discard_timer); + bearer_context_pdcp_config_t out = {0}; if (redcap_cap && redcap_cap->support_of_redcap_r17 && !redcap_cap->pdcp_drb_long_sn_redcap_r17) { LOG_I(NR_RRC, "UE is RedCap without long PDCP SN support: overriding PDCP SN size to 12\n"); - pdcp_config->pdcp_SN_SizeDL = NR_PDCP_Config__drb__pdcp_SN_SizeDL_len12bits; - pdcp_config->pdcp_SN_SizeUL = NR_PDCP_Config__drb__pdcp_SN_SizeUL_len12bits; + out.pDCP_SN_Size_DL = NR_PDCP_Config__drb__pdcp_SN_SizeDL_len12bits; + out.pDCP_SN_Size_UL = NR_PDCP_Config__drb__pdcp_SN_SizeUL_len12bits; } else { - pdcp_config->pdcp_SN_SizeDL = encode_sn_size_dl(default_pdcp_config->drb.sn_size); - pdcp_config->pdcp_SN_SizeUL = encode_sn_size_ul(default_pdcp_config->drb.sn_size); + out.pDCP_SN_Size_DL = encode_sn_size_dl(pdcp.drb.sn_size); + out.pDCP_SN_Size_UL = encode_sn_size_ul(pdcp.drb.sn_size); } - pdcp_config->t_Reordering = encode_t_reordering(default_pdcp_config->drb.t_reordering); - pdcp_config->headerCompression.present = NR_PDCP_Config__drb__headerCompression_PR_notUsed; - pdcp_config->headerCompression.NotUsed = 0; - pdcp_config->integrityProtection = do_drb_integrity ? NR_PDCP_Config__drb__integrityProtection_enabled : 1; - pdcp_config->ext1.cipheringDisabled = do_drb_ciphering ? 1 : NR_PDCP_Config__ext1__cipheringDisabled_true; -} - -void set_bearer_context_pdcp_config(bearer_context_pdcp_config_t *pdcp_config, drb_t *rrc_drb, bool um_on_default_drb) -{ - AssertError(rrc_drb != NULL && pdcp_config != NULL, return, "Failed to set default bearer context PDCP configuration!\n"); - pdcp_config->pDCP_SN_Size_UL = rrc_drb->pdcp_config.pdcp_SN_SizeUL; - pdcp_config->pDCP_SN_Size_DL = rrc_drb->pdcp_config.pdcp_SN_SizeDL; - pdcp_config->discardTimer = rrc_drb->pdcp_config.discardTimer; - pdcp_config->reorderingTimer = rrc_drb->pdcp_config.t_Reordering; - pdcp_config->rLC_Mode = um_on_default_drb ? E1AP_RLC_Mode_rlc_um_bidirectional : E1AP_RLC_Mode_rlc_am; -} - -drb_t *generateDRB(gNB_RRC_UE_t *ue, - const pdusession_t *pduSession, - bool enable_sdap, - int do_drb_integrity, - int do_drb_ciphering, - const nr_pdcp_configuration_t *pdcp_config) -{ - DevAssert(ue != NULL); - - drb_t *est_drb = nr_rrc_add_drb(&ue->drbs, pduSession->pdusession_id); - if (!est_drb) { - LOG_E(NR_RRC, "UE %d: failed to add DRB for PDU session ID %d\n", ue->rrc_ue_id, pduSession->pdusession_id); - return NULL; - } - LOG_I(NR_RRC, "UE %d: configure DRB ID %d for PDU session ID %d\n", ue->rrc_ue_id, est_drb->drb_id, pduSession->pdusession_id); - - est_drb->cnAssociation.sdap_config.defaultDRB = true; - - /* SDAP Configuration */ - est_drb->cnAssociation.present = NR_DRB_ToAddMod__cnAssociation_PR_sdap_Config; - est_drb->cnAssociation.sdap_config.pdusession_id = pduSession->pdusession_id; - if (enable_sdap) { - est_drb->cnAssociation.sdap_config.sdap_HeaderDL = NR_SDAP_Config__sdap_HeaderDL_present; - est_drb->cnAssociation.sdap_config.sdap_HeaderUL = NR_SDAP_Config__sdap_HeaderUL_present; - } else { - est_drb->cnAssociation.sdap_config.sdap_HeaderDL = NR_SDAP_Config__sdap_HeaderDL_absent; - est_drb->cnAssociation.sdap_config.sdap_HeaderUL = NR_SDAP_Config__sdap_HeaderUL_absent; - } - int qos_flow_index = 0; - FOR_EACH_SEQ_ARR(nr_rrc_qos_t *, qos_session, &pduSession->qos) { - qos_session->drb_id = est_drb->drb_id; // Map DRB to QoS - est_drb->cnAssociation.sdap_config.mappedQoS_FlowsToAdd[qos_flow_index++] = qos_session->qos.qfi; - DevAssert(qos_flow_index <= MAX_QOS_FLOWS); - } - /* PDCP Configuration */ - set_default_drb_pdcp_config(&est_drb->pdcp_config, do_drb_integrity, do_drb_ciphering, pdcp_config, ue->redcap_cap); - - drb_t *rrc_drb = get_drb(&ue->drbs, est_drb->drb_id); - DevAssert(rrc_drb); - return rrc_drb; -} - -NR_DRB_ToAddMod_t *generateDRB_ASN1(const drb_t *drb_asn1) -{ - NR_DRB_ToAddMod_t *DRB_config = CALLOC(1, sizeof(*DRB_config)); - NR_SDAP_Config_t *SDAP_config = CALLOC(1, sizeof(NR_SDAP_Config_t)); - - asn1cCalloc(DRB_config->cnAssociation, association); - asn1cCalloc(SDAP_config->mappedQoS_FlowsToAdd, sdapFlows); - asn1cCalloc(DRB_config->pdcp_Config, pdcpConfig); - asn1cCalloc(pdcpConfig->drb, drb); - - DRB_config->drb_Identity = drb_asn1->drb_id; - association->present = drb_asn1->cnAssociation.present; - - /* SDAP Configuration */ - SDAP_config->pdu_Session = drb_asn1->cnAssociation.sdap_config.pdusession_id; - SDAP_config->sdap_HeaderDL = drb_asn1->cnAssociation.sdap_config.sdap_HeaderDL; - SDAP_config->sdap_HeaderUL = drb_asn1->cnAssociation.sdap_config.sdap_HeaderUL; - SDAP_config->defaultDRB = drb_asn1->cnAssociation.sdap_config.defaultDRB; - - for (int qos_flow_index = 0; qos_flow_index < MAX_QOS_FLOWS; qos_flow_index++) { - if (drb_asn1->cnAssociation.sdap_config.mappedQoS_FlowsToAdd[qos_flow_index] != 0) { - asn1cSequenceAdd(sdapFlows->list, NR_QFI_t, qfi); - *qfi = drb_asn1->cnAssociation.sdap_config.mappedQoS_FlowsToAdd[qos_flow_index]; - } - } - - association->choice.sdap_Config = SDAP_config; - - /* PDCP Configuration */ - asn1cCallocOne(drb->discardTimer, drb_asn1->pdcp_config.discardTimer); - asn1cCallocOne(drb->pdcp_SN_SizeUL, drb_asn1->pdcp_config.pdcp_SN_SizeUL); - asn1cCallocOne(drb->pdcp_SN_SizeDL, drb_asn1->pdcp_config.pdcp_SN_SizeDL); - asn1cCallocOne(pdcpConfig->t_Reordering, drb_asn1->pdcp_config.t_Reordering); - - drb->headerCompression.present = drb_asn1->pdcp_config.headerCompression.present; - drb->headerCompression.choice.notUsed = drb_asn1->pdcp_config.headerCompression.NotUsed; - - if (!drb_asn1->pdcp_config.integrityProtection) { - asn1cCallocOne(drb->integrityProtection, drb_asn1->pdcp_config.integrityProtection); - } - if (!drb_asn1->pdcp_config.ext1.cipheringDisabled) { - asn1cCalloc(pdcpConfig->ext1, ext1); - asn1cCallocOne(ext1->cipheringDisabled, drb_asn1->pdcp_config.ext1.cipheringDisabled); - } - - return DRB_config; + out.discardTimer = encode_discard_timer(pdcp.drb.discard_timer); + out.reorderingTimer = encode_t_reordering(pdcp.drb.t_reordering); + out.rLC_Mode = um_on_default_drb ? E1AP_RLC_Mode_rlc_um_bidirectional : E1AP_RLC_Mode_rlc_am; + out.pDCP_Reestablishment = false; + return out; } diff --git a/openair2/RRC/NR/rrc_gNB_radio_bearers.h b/openair2/RRC/NR/rrc_gNB_radio_bearers.h index e5ec90c5c6..f6821e314b 100644 --- a/openair2/RRC/NR/rrc_gNB_radio_bearers.h +++ b/openair2/RRC/NR/rrc_gNB_radio_bearers.h @@ -24,34 +24,12 @@ #include #include -#include "NR_DRB-ToAddMod.h" #include "e1ap_messages_types.h" #include "nr_rrc_defs.h" -/// @brief Generates an ASN1 DRB-ToAddMod, from the established_drbs in gNB_RRC_UE_t. -/// @param drb_t drb_asn1 -/// @return Returns the ASN1 DRB-ToAddMod structs. -NR_DRB_ToAddMod_t *generateDRB_ASN1(const drb_t *drb_asn1); - /// @brief retrieve the data structure representing DRB with ID drb_id of UE ue drb_t *get_drb(seq_arr_t *seq, int id); -/// @brief Creates and stores a DRB in the gNB_RRC_UE_t struct -/// @param ue The gNB_RRC_UE_t struct that holds information for the UEs -/// @param drb_id The Data Radio Bearer Identity to be created for the established DRB. -/// @param pduSession The PDU Session that the DRB is created for. -/// @param enable_sdap If true the SDAP header will be added to the packet, else it will not add or search for SDAP header. -/// @param do_drb_integrity -/// @param do_drb_ciphering -/// @param pdcp_config -/// @return returns a pointer to the generated DRB structure -drb_t *generateDRB(gNB_RRC_UE_t *ue, - const pdusession_t *pduSession, - bool enable_sdap, - int do_drb_integrity, - int do_drb_ciphering, - const nr_pdcp_configuration_t *pdcp_config); - /// @brief retrieve PDU session of UE ue with ID id rrc_pdu_session_param_t *find_pduSession(seq_arr_t *seq, int id); @@ -61,13 +39,15 @@ rrc_pdu_session_param_t *add_pduSession(seq_arr_t *sessions_ptr, const pdusessio /// @brief get PDU session of UE ue through the DRB drb_id rrc_pdu_session_param_t *find_pduSession_from_drbId(gNB_RRC_UE_t *ue, int drb_id); -/// @brief set PDCP configuration in a bearer context management message -void set_bearer_context_pdcp_config(bearer_context_pdcp_config_t *pdcp_config, drb_t *rrc_drb, bool um_on_default_drb); +/// @brief set PDCP configuration in E1 Bearer Context Management message +bearer_context_pdcp_config_t set_bearer_context_pdcp_config(const nr_pdcp_configuration_t pdcp, + bool um_on_default_drb, + const nr_redcap_ue_cap_t *redcap_cap); void free_pdusession(void *ptr); /// @brief Add DRB to RRC list -drb_t *nr_rrc_add_drb(seq_arr_t *drb_ptr, int pdusession_id); +drb_t *nr_rrc_add_drb(seq_arr_t *drb_ptr, int pdusession_id, nr_pdcp_configuration_t *pdcp); /// @brief Function to free DRB in RRC void free_drb(void *ptr); diff --git a/openair2/SDAP/nr_sdap/nr_sdap_configuration.h b/openair2/SDAP/nr_sdap/nr_sdap_configuration.h new file mode 100644 index 0000000000..f590278bf8 --- /dev/null +++ b/openair2/SDAP/nr_sdap/nr_sdap_configuration.h @@ -0,0 +1,33 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef _NR_SDAP_CONFIGURATION_H_ +#define _NR_SDAP_CONFIGURATION_H_ + +#include "stdbool.h" + +typedef struct { + // SDAP Headers + bool header_dl_absent; + bool header_ul_absent; +} nr_sdap_configuration_t; + +#endif /* _NR_SDAP_CONFIGURATION_H_ */ From 9bf79cd2c92a66b90360a072631230c8cf0ef05f Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Tue, 22 Jul 2025 15:35:16 +0200 Subject: [PATCH 790/964] PDU session release: refactor NGAP PDU Session Release command/response * There is no IE corresponding to PDU sessions failed to release in the PDU SESSION RESOURCE RELEASE RESPONSE message. This was removed and the corresponding code was refactored and cleaned up. * In the Release Command handler, only established PDU Session are set to be released. The Response message is filled accordingly. --- openair2/COMMON/ngap_messages_types.h | 8 +------- openair2/RRC/NR/rrc_gNB_NGAP.c | 21 ++++++--------------- openair3/NGAP/ngap_gNB_nas_procedures.c | 5 ++--- 3 files changed, 9 insertions(+), 25 deletions(-) diff --git a/openair2/COMMON/ngap_messages_types.h b/openair2/COMMON/ngap_messages_types.h index 1c5fa90868..2c4b0f8a0a 100644 --- a/openair2/COMMON/ngap_messages_types.h +++ b/openair2/COMMON/ngap_messages_types.h @@ -918,19 +918,13 @@ typedef struct ngap_pdusession_release_command_s { } ngap_pdusession_release_command_t; typedef struct ngap_pdusession_release_resp_s { - /* AMF UE id */ + // AMF UE NGAP ID uint64_t amf_ue_ngap_id; // RAN UE NGAP ID uint32_t gNB_ue_ngap_id; // PDU Session Resource Released List uint16_t nb_of_pdusessions_released; pdusession_release_t pdusession_release[NGAP_MAX_PDU_SESSION]; - - /* Number of pdusession failed to be released in list */ - uint8_t nb_of_pdusessions_failed; - /* list of pdusessions that failed to be released */ - pdusession_failed_t pdusessions_failed[NGAP_MAX_PDU_SESSION]; - } ngap_pdusession_release_resp_t; /** 9.2.3.14 Uplink RAN Status Transfer (3GPP TS 38.413) diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index 90a0522886..34666e3538 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -1489,7 +1489,6 @@ void rrc_gNB_send_NGAP_HANDOVER_CANCEL(int module_id, gNB_RRC_UE_t *UE, ngap_cau void rrc_gNB_send_NGAP_PDUSESSION_RELEASE_RESPONSE(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, uint8_t xid) { - int pdu_sessions_released = 0; MessageDef *msg_p; msg_p = itti_alloc_new_message (TASK_RRC_GNB, rrc->module_id, NGAP_PDUSESSION_RELEASE_RESPONSE); ngap_pdusession_release_resp_t *resp = &NGAP_PDUSESSION_RELEASE_RESPONSE(msg_p); @@ -1499,17 +1498,15 @@ void rrc_gNB_send_NGAP_PDUSESSION_RELEASE_RESPONSE(gNB_RRC_INST *rrc, gNB_RRC_UE FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t *, session, &UE->pduSessions) { if (xid == session->xid) { const pdusession_t *pdusession = &session->param; - resp->pdusession_release[pdu_sessions_released].pdusession_id = pdusession->pdusession_id; + if (session->status == PDU_SESSION_STATUS_TORELEASE) { + DevAssert(resp->nb_of_pdusessions_released < NGAP_MAX_PDU_SESSION); + resp->pdusession_release[resp->nb_of_pdusessions_released++].pdusession_id = pdusession->pdusession_id; + } session->status = PDU_SESSION_STATUS_RELEASED; - pdu_sessions_released++; } } - resp->nb_of_pdusessions_released = pdu_sessions_released; - resp->nb_of_pdusessions_failed = 0; - DevAssert(resp->nb_of_pdusessions_released < NGAP_MAX_PDU_SESSION); - - LOG_I(NR_RRC, "NGAP PDUSESSION RELEASE RESPONSE: rrc_ue_id %u release_pdu_sessions %d\n", resp->gNB_ue_ngap_id, pdu_sessions_released); + LOG_I(NR_RRC, "NGAP PDUSESSION RELEASE RESPONSE: rrc_ue_id %u release_pdu_sessions %d\n", resp->gNB_ue_ngap_id, resp->nb_of_pdusessions_released); itti_send_msg_to_task (TASK_NGAP, rrc->module_id, msg_p); } @@ -1538,13 +1535,7 @@ int rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND(MessageDef *msg_p, instance_ for (int pdusession = 0; pdusession < cmd->nb_pdusessions_torelease; pdusession++) { rrc_pdu_session_param_t *pduSession = find_pduSession(&UE->pduSessions, cmd->pdusession_release_params[pdusession].pdusession_id); if (!pduSession) { - LOG_I(NR_RRC, "no pdusession_id, AMF requested to close it id=%d\n", cmd->pdusession_release_params[pdusession].pdusession_id); - rrc_pdu_session_param_t item = {0}; - item.status = PDU_SESSION_STATUS_FAILED; - item.param.pdusession_id = cmd->pdusession_release_params[pdusession].pdusession_id; - ngap_cause_t cause = {.type = NGAP_CAUSE_RADIO_NETWORK, .value = NGAP_CAUSE_RADIO_NETWORK_UNKNOWN_PDU_SESSION_ID}; - item.cause = cause; - seq_arr_push_back(&UE->pduSessions, &item, sizeof(item)); + LOG_E(NR_RRC, "Failed to release non-existing PDU Session %d\n", cmd->pdusession_release_params[pdusession].pdusession_id); continue; } if (pduSession->status == PDU_SESSION_STATUS_FAILED) { diff --git a/openair3/NGAP/ngap_gNB_nas_procedures.c b/openair3/NGAP/ngap_gNB_nas_procedures.c index b5db821e36..fe86d7c5e0 100644 --- a/openair3/NGAP/ngap_gNB_nas_procedures.c +++ b/openair3/NGAP/ngap_gNB_nas_procedures.c @@ -1206,11 +1206,10 @@ int ngap_gNB_pdusession_release_resp(instance_t instance, ngap_pdusession_releas /* UE associated signalling -> use the allocated stream */ ngap_gNB_itti_send_sctp_data_req(ngap_gNB_instance_p->instance, ue_context_p->amf_ref->assoc_id, buffer, length, ue_context_p->tx_stream); - NGAP_INFO("pdusession_release_response sended gNB_UE_NGAP_ID %u amf_ue_ngap_id %lu nb_of_pdusessions_released %d nb_of_pdusessions_failed %d\n", + NGAP_INFO("pdusession_release_response sended gNB_UE_NGAP_ID %u amf_ue_ngap_id %lu nb_of_pdusessions_released %d \n", pdusession_release_resp_p->gNB_ue_ngap_id, (uint64_t)ue_context_p->amf_ue_ngap_id, - pdusession_release_resp_p->nb_of_pdusessions_released, - pdusession_release_resp_p->nb_of_pdusessions_failed); + pdusession_release_resp_p->nb_of_pdusessions_released); return 0; } From c99f836ad4e1b6a23c40385f7fc4b8a8fcabf532 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 24 Sep 2025 14:01:41 +0200 Subject: [PATCH 791/964] Refactor DRB release handling to use actual DRB IDs - Replace simple counter-based DRB ID assignment with actual DRB ID lookup - Add nested loop to iterate through DRBs for each PDU session to be release - Improve logic flow with early continue for non-matching PDU sessions This ensures DRB release list contains correct DRB IDs that correspond to actual DRB entities --- openair2/RRC/NR/rrc_gNB.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 4af378dd81..cc766b9d81 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -836,11 +836,14 @@ void rrc_gNB_generate_dedicatedRRCReconfiguration_release(gNB_RRC_INST *rrc, nr_rrc_reconfig_param_t params = {.transaction_id = xid}; NR_DRB_ToReleaseList_t *to_release = CALLOC(sizeof(*to_release), 1); - int i = 0; FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t *, item, &ue_p->pduSessions) { - if ((item->status == PDU_SESSION_STATUS_TORELEASE) && item->xid == xid) { - asn1cSequenceAdd(to_release->list, NR_DRB_Identity_t, DRB_release); - *DRB_release = ++i; // DRB ID + if ((item->status != PDU_SESSION_STATUS_TORELEASE) && item->xid != xid) + continue; + FOR_EACH_SEQ_ARR(drb_t *, drb, &ue_p->drbs) { + if (drb->pdusession_id == item->param.pdusession_id) { + asn1cSequenceAdd(to_release->list, NR_DRB_Identity_t, DRB_release); + *DRB_release = drb->drb_id; // DRB ID + } } } params.drb_release_list = to_release; From e6d8d6a07209e957629027deab6a263ff715e133 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 24 Sep 2025 16:34:52 +0200 Subject: [PATCH 792/964] Add tests for RRC radio bearers lib --- openair2/RRC/NR/CMakeLists.txt | 4 + openair2/RRC/NR/tests/CMakeLists.txt | 7 + openair2/RRC/NR/tests/rrc_bearers_test.c | 173 +++++++++++++++++++++++ 3 files changed, 184 insertions(+) create mode 100644 openair2/RRC/NR/tests/CMakeLists.txt create mode 100644 openair2/RRC/NR/tests/rrc_bearers_test.c diff --git a/openair2/RRC/NR/CMakeLists.txt b/openair2/RRC/NR/CMakeLists.txt index 7537bd661d..658bfeee5a 100644 --- a/openair2/RRC/NR/CMakeLists.txt +++ b/openair2/RRC/NR/CMakeLists.txt @@ -1 +1,5 @@ add_subdirectory(MESSAGES) + +if(ENABLE_TESTS) + add_subdirectory(tests) +endif() diff --git a/openair2/RRC/NR/tests/CMakeLists.txt b/openair2/RRC/NR/tests/CMakeLists.txt new file mode 100644 index 0000000000..f7a4a95b1b --- /dev/null +++ b/openair2/RRC/NR/tests/CMakeLists.txt @@ -0,0 +1,7 @@ + +add_executable(rrc_bearers_test rrc_bearers_test.c ../rrc_gNB_radio_bearers.c ${OPENAIR2_DIR}/LAYER2/nr_pdcp/asn1_utils.c) +add_dependencies(tests rrc_bearers_test) +add_test(NAME rrc_bearers_test COMMAND rrc_bearers_test) +target_include_directories(rrc_bearers_test PRIVATE ./common/utils/ds common/utils/LOG) +target_link_libraries(rrc_bearers_test PRIVATE ds alg asn1_e1ap asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs LOG T) +target_compile_definitions(rrc_bearers_test PRIVATE ENABLE_TESTS) diff --git a/openair2/RRC/NR/tests/rrc_bearers_test.c b/openair2/RRC/NR/tests/rrc_bearers_test.c new file mode 100644 index 0000000000..982a1b0cd9 --- /dev/null +++ b/openair2/RRC/NR/tests/rrc_bearers_test.c @@ -0,0 +1,173 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include +#include +#include +#include +#include "common/utils/utils.h" +#include "common/utils/assertions.h" +#include "openair2/RRC/NR/rrc_gNB_radio_bearers.h" +#include "ds/seq_arr.h" +#include "common/utils/LOG/log.h" + +int nr_rlc_get_available_tx_space(int module_id, int rnti, int drb_id) { return 0; } +softmodem_params_t *get_softmodem_params(void) { return NULL; } +configmodule_interface_t *uniqCfg = NULL; + +void exit_function(const char *file, const char *function, const int line, const char *s, const int assert) +{ + printf("detected error at %s:%d:%s: %s\n", file, line, function, s); + abort(); +} + +static void test_rrc_pdu_session(void) +{ + const int pdu_session_id = 3; + gNB_RRC_UE_t ue = {0}; + seq_arr_init(&ue.pduSessions, sizeof(rrc_pdu_session_param_t)); + + /* test add */ + pdusession_t p1 = {0}; + seq_arr_init(&p1.qos, sizeof(nr_rrc_qos_t)); + p1.pdusession_id = pdu_session_id; + p1.n3_incoming.teid = 2002; + LOG_I(NR_RRC, "Adding first PDU Session with ID %d\n", p1.pdusession_id); + rrc_pdu_session_param_t *s1 = add_pduSession(&ue.pduSessions, &p1); // add 1st PDU Session + AssertFatal(s1 != NULL, "Could not add PDU Session\n"); + AssertFatal(s1->param.pdusession_id == p1.pdusession_id, "PDU Session ID mismatch in added PDU Session\n"); + AssertFatal(s1->param.n3_incoming.teid == p1.n3_incoming.teid, "teid mismatch in added PDU Session\n"); + LOG_A(NR_RRC, "First PDU Session added successfully\n"); + + /* test find */ + rrc_pdu_session_param_t *a1 = find_pduSession(&ue.pduSessions, p1.pdusession_id); + AssertFatal(a1 != NULL, "Could not find PDU Session\n"); + AssertFatal(a1 == s1, "Found PDU Session mismatch\n"); + LOG_A(NR_RRC, "PDU Session find test passed\n"); + + /* test add duplicate */ + pdusession_t input2 = {0}; + seq_arr_init(&input2.qos, sizeof(nr_rrc_qos_t)); + input2.pdusession_id = pdu_session_id; + input2.n3_incoming.teid = 9999; + rrc_pdu_session_param_t *s2 = add_pduSession(&ue.pduSessions, &input2); // add 2nd PDU Session + AssertFatal(s2 == NULL, "Duplicated PDU session was added!\n"); + LOG_A(NR_RRC, "Duplicated PDU session test passed\n"); + seq_arr_free(&input2.qos, NULL); + + /* add DRB and fetch PDU Session */ + seq_arr_init(&ue.drbs, sizeof(drb_t)); + nr_pdcp_configuration_t pdcp = {.drb.discard_timer = 100, .drb.sn_size = 18, .drb.t_reordering = 50}; + drb_t *added = nr_rrc_add_drb(&ue.drbs, pdu_session_id, &pdcp); + AssertFatal(added != NULL, "Failed to add DRB"); + rrc_pdu_session_param_t *a2 = find_pduSession_from_drbId(&ue, added->drb_id); + AssertFatal(a2 && a2->param.pdusession_id == pdu_session_id, "find_pduSession_from_drbId failed"); + + seq_arr_free(&ue.pduSessions, free_pdusession); + seq_arr_free(&ue.drbs, free_drb); +} + +// ---------------- DRB TESTS ---------------- + +static void test_rrc_drb(void) +{ + LOG_I(NR_RRC, "Starting DRB test\n"); + seq_arr_t pduSessions = {0}; + seq_arr_t drbs = {0}; + seq_arr_init(&pduSessions, sizeof(rrc_pdu_session_param_t)); + seq_arr_init(&drbs, sizeof(drb_t)); + + /* test add 1 DRB to 1st PDU session */ + const int id1 = 1; + pdusession_t s1 = {0}; + seq_arr_init(&s1.qos, sizeof(nr_rrc_qos_t)); + s1.pdusession_id = id1; + add_pduSession(&pduSessions, &s1); // add PDU session + + nr_pdcp_configuration_t pdcp = {.drb.discard_timer = 100, .drb.sn_size = 18, .drb.t_reordering = 50}; + drb_t *in1 = nr_rrc_add_drb(&drbs, id1, &pdcp); // add DRB + AssertFatal(in1, "add_rrc_drb failed"); + LOG_A(NR_RRC, "First DRB created with ID %d\n", in1->drb_id); + + drb_t *out1 = get_drb(&drbs, 1); // fetch DRB + AssertFatal(out1 && out1 == in1, "get_drb failed"); + LOG_A(NR_RRC, "DRB retrieval test passed\n"); + + /* test add DRB to 2nd PDU session */ + const int id2 = 2; + pdusession_t s2 = {0}; + seq_arr_init(&s2.qos, sizeof(nr_rrc_qos_t)); + s2.pdusession_id = id2; + add_pduSession(&pduSessions, &s2); // add 2nd PDU session + drb_t *in2 = nr_rrc_add_drb(&drbs, id2, &pdcp); // add DRB to 2nd PDU session + AssertFatal(in2, "add_rrc_drb failed"); + LOG_A(NR_RRC, "Second DRB created with ID %d\n", in2->drb_id); + drb_t *out2 = get_drb(&drbs, 2); + AssertFatal(out2 && out2->drb_id == 2, "get_drb failed"); + LOG_A(NR_RRC, "Second DRB retrieval test passed\n"); + + seq_arr_free(&pduSessions, free_pdusession); + seq_arr_free(&drbs, free_drb); +} + +// ---------------- DRB TESTS ---------------- + +static void test_rrc_qos(void) +{ + seq_arr_t pduSessions = {0}; + seq_arr_init(&pduSessions, sizeof(rrc_pdu_session_param_t)); + + const int session_id = 70; + pdusession_t in = {0}; + in.pdusession_id = session_id; + seq_arr_init(&in.qos, sizeof(nr_rrc_qos_t)); + add_pduSession(&pduSessions, &in); + LOG_A(NR_RRC, "Created PDU Session %d for QoS test\n", session_id); + + const int qfi = 4; + const pdusession_level_qos_parameter_t param = { .fiveQI = 9, .fiveQI_type = NON_DYNAMIC, .qfi = qfi }; + LOG_A(NR_RRC, "Adding QoS flow with QFI %d\n", qfi); + nr_rrc_qos_t *added = add_qos(&in.qos, ¶m); + AssertFatal(added, "add_qos failed"); + LOG_A(NR_RRC, "QoS flow added successfully\n"); + + nr_rrc_qos_t *found = find_qos(&in.qos, qfi); + AssertFatal(found && found == added, "find_qos failed"); + LOG_A(NR_RRC, "QoS flow find test passed\n"); + + seq_arr_free(&pduSessions, free_pdusession); +} + +int main() +{ + // Initialize logging system + logInit(); + // Set logging level for NR_RRC to show INFO messages + set_log(NR_RRC, OAILOG_INFO); + // PDU Session + test_rrc_pdu_session(); + // DRB + test_rrc_drb(); + // QoS + test_rrc_qos(); + LOG_A(NR_RRC, "All RRC Bearers tests passed successfully!\n"); + return 0; +} From 2d70cec6ddef08fbb0a7e3853d8a8718af819b5c Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 25 Jul 2025 14:41:30 +0200 Subject: [PATCH 793/964] Remove autotools definitions They do not seem to be used anywhere (I grepped). --- CMakeLists.txt | 3 --- 1 file changed, 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 058bfd7a39..e996e633b4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -173,9 +173,6 @@ else () set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -march=armv8.2-a") endif() -# add autotools definitions that were maybe used! -add_definitions(-DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_FCNTL_H=1 -DHAVE_ARPA_INET_H=1 -DHAVE_SYS_TIME_H=1 -DHAVE_SYS_SOCKET_H=1 -DHAVE_STRERROR=1 -DHAVE_SOCKET=1 -DHAVE_MEMSET=1 -DHAVE_GETTIMEOFDAY=1 -DHAVE_STDLIB_H=1 -DHAVE_MALLOC=1 -DHAVE_LIBSCTP) - # we need -rdynamic to incorporate all symbols in shared objects, see man page set(commonOpts "-pipe -fPIC -Wall -fno-strict-aliasing -rdynamic") # GNU C/C++ Compiler might throw many warnings without packed-bitfield-compat, see man page From d5bf702f10fa47ebb3c6f9892cb7b750f9b2885f Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 25 Jul 2025 14:41:03 +0200 Subject: [PATCH 794/964] Remove CMakeLists.txt author information Author information can be inferred from git blame. --- CMakeLists.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e996e633b4..1bbed7918b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,8 +19,6 @@ # * contact@openairinterface.org # */ -# Author: laurent THOMAS, Lionel GAUTHIER - cmake_minimum_required (VERSION 3.16) project (OpenAirInterface LANGUAGES C CXX) set(CMAKE_CXX_STANDARD 17) From acb6f05a6d679245279d85604008a90e6c7b2ab7 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 15 Sep 2025 09:17:19 +0200 Subject: [PATCH 795/964] Remove include_directories() for non-existing directories --- CMakeLists.txt | 6 ------ 1 file changed, 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1bbed7918b..5f7c520a0c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -544,7 +544,6 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR}) include_directories("${OPENAIR_DIR}/executables") include_directories("${OPENAIR2_DIR}/COMMON") include_directories("${OPENAIR2_DIR}/UTIL") -include_directories("${OPENAIR2_DIR}/UTIL/LOG") include_directories("${OPENAIR3_DIR}/COMMON") include_directories("${OPENAIR3_DIR}/UTILS") include_directories("${NFAPI_DIR}/nfapi/public_inc") @@ -585,12 +584,7 @@ include_directories("${OPENAIR3_DIR}/ocp-gtpu") include_directories("${OPENAIR3_DIR}/M3AP") include_directories("${OPENAIR3_DIR}/MME_APP") include_directories("${OPENAIR_DIR}/radio/COMMON") -include_directories("${OPENAIR2_DIR}/UTIL/OSA") -include_directories("${OPENAIR2_DIR}/UTIL/MEM") -include_directories("${OPENAIR2_DIR}/UTIL/LISTS") -include_directories("${OPENAIR2_DIR}/UTIL/FIFO") include_directories("${OPENAIR2_DIR}/UTIL/MATH") -include_directories("${OPENAIR2_DIR}/UTIL/TIMER") include_directories("${OPENAIR2_DIR}/UTIL/OTG") include_directories("${OPENAIR2_DIR}/UTIL/OPT") include_directories("${OPENAIR_DIR}") From ada7eb8b2a6e1c6d02833a51bb4dbaf41444d587 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 19 Dec 2024 21:38:22 +0100 Subject: [PATCH 796/964] Remove unused/non-compiling test stub --- CMakeLists.txt | 4 ---- openair2/NR_PHY_INTERFACE/nfapi_5g_test.c | 21 --------------------- 2 files changed, 25 deletions(-) delete mode 100644 openair2/NR_PHY_INTERFACE/nfapi_5g_test.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 5f7c520a0c..d993a8d09a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1715,10 +1715,6 @@ add_library(minimal_lib ) target_link_libraries(minimal_lib PUBLIC pthread dl ${T_LIB} LOG) -add_executable(nfapi_test - ${OPENAIR_DIR}/openair2/NR_PHY_INTERFACE/nfapi_5g_test.c - ) - add_executable(measurement_display ${OPENAIR_DIR}/common/utils/threadPool/measurement_display.c) target_link_libraries (measurement_display minimal_lib) diff --git a/openair2/NR_PHY_INTERFACE/nfapi_5g_test.c b/openair2/NR_PHY_INTERFACE/nfapi_5g_test.c deleted file mode 100644 index 5d2cf18974..0000000000 --- a/openair2/NR_PHY_INTERFACE/nfapi_5g_test.c +++ /dev/null @@ -1,21 +0,0 @@ - - -//openair2/NR_PHY_INTERFACE/nfapi_5g_test.c -#include "nfapi_nr_interface_scf.h" - -#include // for printf - -int main ( int argc, char** argv) -{ - nfapi_nr_cell_param_t nfapi_nr_cell_param_test; - nfapi_nr_param_tlv_t tlvs_to_report_list; - - nfapi_nr_cell_param_test.config_tlvs_to_report_list = &tlvs_to_report_list; - nfapi_nr_cell_param_test.phy_state = 0; - nfapi_nr_cell_param_test.release_capability = 0; - nfapi_nr_cell_param_test.skip_blank_dl_config = 0; - nfapi_nr_cell_param_test.skip_blank_ul_config = 0; - - printf(" test nfapi \n"); - return 0; -} From b2fce659e8d6301d1b64e787a83cf1a02f03d464 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 19 Dec 2024 22:00:03 +0100 Subject: [PATCH 797/964] Fix warning for wrong printf format specifier MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit common/utils/threadPool/measurement_display.c:55:14 warning: format ‘%lu’ expects argument of type ‘long unsigned int’, but argument 3 has type ‘long long unsigned int’ [-Wformat=] --- common/utils/threadPool/measurement_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/utils/threadPool/measurement_display.c b/common/utils/threadPool/measurement_display.c index cf2febaf33..8e44beb949 100644 --- a/common/utils/threadPool/measurement_display.c +++ b/common/utils/threadPool/measurement_display.c @@ -52,7 +52,7 @@ int main(int argc, char *argv[]) { while ( 1 ) { if ( read(fd,&doneRequest, sizeof(doneRequest)) == sizeof(doneRequest)) { - printf("%lu" SEP "%lu" SEP "%lu" SEP "%lu" "\n", + printf("%lu" SEP "%llu" SEP "%llu" SEP "%llu" "\n", doneRequest.key, (doneRequest.startProcessingTime-doneRequest.creationTime)/cpuCyclesMicroSec, (doneRequest.endProcessingTime-doneRequest.startProcessingTime)/cpuCyclesMicroSec, From 252b19cddbbbb641bd08700ef295e793f4e00786 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 19 Dec 2024 22:42:38 +0100 Subject: [PATCH 798/964] Make rftest compile uniqCfg is in minimal_lib, so not necessary. Remove non-existant struct members. --- openair1/PHY/TOOLS/calibration_test.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/openair1/PHY/TOOLS/calibration_test.c b/openair1/PHY/TOOLS/calibration_test.c index f69e468e7b..1d8e64ee90 100644 --- a/openair1/PHY/TOOLS/calibration_test.c +++ b/openair1/PHY/TOOLS/calibration_test.c @@ -28,7 +28,6 @@ char *uecap_file; int read_recplayconfig(recplay_conf_t **recplay_conf, recplay_state_t **recplay_state) {return 0;} void nfapi_setmode(nfapi_mode_t nfapi_mode) {} void set_taus_seed(unsigned int seed_init){}; -configmodule_interface_t *uniqCfg = NULL; int main(int argc, char **argv) { ///static configuration for NR at the moment if ((uniqCfg = load_configmodule(argc, argv, CONFIG_ENABLECMDLINEONLY)) == NULL) { @@ -60,8 +59,6 @@ int main(int argc, char **argv) { openair0_config_t openair0_cfg= { //! Module ID for this configuration .Mod_id=0, - //! device log level - .log_level=0, //! duplexing mode .duplex_mode=0, //! number of downlink resource blocks @@ -130,8 +127,6 @@ int main(int argc, char **argv) { .recplay_conf=NULL, //! number of samples per tti .samples_per_tti=0, - //! check for threequarter sampling rate - .threequarter_fs=0, }; //----------------------- openair0_device rfdevice= { From 912463f7528e27d0659c4c5b66052972a123f92d Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Thu, 25 Sep 2025 09:29:44 +0200 Subject: [PATCH 799/964] modulation LUTs size was wrong, and remove inconsistent test of SSE2 enable --- openair1/PHY/MODULATION/nr_modulation.c | 33 +++++++---------------- openair1/PHY/NR_REFSIG/nr_gen_mod_table.c | 10 +++---- openair1/PHY/NR_REFSIG/nr_mod_table.h | 9 +++---- 3 files changed, 15 insertions(+), 37 deletions(-) diff --git a/openair1/PHY/MODULATION/nr_modulation.c b/openair1/PHY/MODULATION/nr_modulation.c index 40de9351d6..84f7e356e7 100644 --- a/openair1/PHY/MODULATION/nr_modulation.c +++ b/openair1/PHY/MODULATION/nr_modulation.c @@ -119,49 +119,33 @@ const char nr_W_4l_4p[5][4][4] = { void nr_modulation(const uint32_t *in, uint32_t length, uint16_t mod_order, int16_t *out) { - uint16_t mask = ((1 << mod_order) - 1); - int32_t *nr_mod_table32; + const uint16_t mask = ((1 << mod_order) - 1); int32_t *out32 = (int32_t *)out; const uint8_t *in_bytes = (const uint8_t *)in; const uint64_t *in64 = (const uint64_t *)in; int64_t *out64 = (int64_t *)out; uint32_t i = 0; -#if defined(__SSE2__) - simde__m128i *nr_mod_table128; - simde__m128i *out128; -#endif - LOG_D(PHY, "nr_modulation: length %d, mod_order %d\n", length, mod_order); switch (mod_order) { -#if defined(__SSE2__) - case 2: - nr_mod_table128 = (simde__m128i *)nr_qpsk_byte_mod_table; - out128 = (simde__m128i *)out; + case 2: { + simde__m128i *nr_mod_table128 = (simde__m128i *)nr_qpsk_byte_mod_table; + simde__m128i *out128 = (simde__m128i *)out; for (i = 0; i < length / 8; i++) out128[i] = nr_mod_table128[in_bytes[i]]; // the bits that are left out i = i * 8 / 2; - nr_mod_table32 = (int32_t *)nr_qpsk_mod_table; + int32_t *nr_mod_table32 = (int32_t *)nr_qpsk_mod_table; while (i < length / 2) { const int idx = ((in_bytes[(i * 2) / 8] >> ((i * 2) & 0x7)) & mask); out32[i] = nr_mod_table32[idx]; i++; } + } return; -#else - case 2: - nr_mod_table32 = (int32_t *)nr_qpsk_mod_table; - for (i = 0; i < length / mod_order; i++) { - const int idx = ((in[i * 2 / 32] >> ((i * 2) & 0x1f)) & mask); - out32[i] = nr_mod_table32[idx]; - } - return; -#endif case 4: - out64 = (int64_t *)out; for (i = 0; i < length / 8; i++) out64[i] = nr_16qam_byte_mod_table[in_bytes[i]]; // the bits that are left out @@ -234,10 +218,11 @@ void nr_modulation(const uint32_t *in, uint32_t length, uint16_t mod_order, int1 } return; - case 8: - nr_mod_table32 = (int32_t *)nr_256qam_mod_table; + case 8: { + int32_t *nr_mod_table32 = (int32_t *)nr_256qam_mod_table; for (i = 0; i < length / 8; i++) out32[i] = nr_mod_table32[in_bytes[i]]; + } return; default: diff --git a/openair1/PHY/NR_REFSIG/nr_gen_mod_table.c b/openair1/PHY/NR_REFSIG/nr_gen_mod_table.c index 76a89f670b..732d531db4 100644 --- a/openair1/PHY/NR_REFSIG/nr_gen_mod_table.c +++ b/openair1/PHY/NR_REFSIG/nr_gen_mod_table.c @@ -22,15 +22,11 @@ #include "nr_refsig.h" #include "nr_mod_table.h" c16_t nr_qpsk_mod_table[4]; - +simde__m128i nr_qpsk_byte_mod_table[256]; int32_t nr_16qam_mod_table[16]; -simde__m128i nr_qpsk_byte_mod_table[2048]; - -int64_t nr_16qam_byte_mod_table[1024]; - +int64_t nr_16qam_byte_mod_table[256]; int64_t nr_64qam_mod_table[4096]; - -int32_t nr_256qam_mod_table[512]; +int32_t nr_256qam_mod_table[256]; void nr_generate_modulation_table() { float sqrt2 = 0.70711; diff --git a/openair1/PHY/NR_REFSIG/nr_mod_table.h b/openair1/PHY/NR_REFSIG/nr_mod_table.h index 517d86b762..81969d9a40 100644 --- a/openair1/PHY/NR_REFSIG/nr_mod_table.h +++ b/openair1/PHY/NR_REFSIG/nr_mod_table.h @@ -29,15 +29,12 @@ #define NR_MOD_TABLE_QAM256_OFFSET 87 extern c16_t nr_qpsk_mod_table[4]; +extern simde__m128i nr_qpsk_byte_mod_table[256]; extern int32_t nr_16qam_mod_table[16]; -#if defined(__SSE2__) -extern simde__m128i nr_qpsk_byte_mod_table[2048]; -#endif - -extern int64_t nr_16qam_byte_mod_table[1024]; +extern int64_t nr_16qam_byte_mod_table[256]; extern int64_t nr_64qam_mod_table[4096]; -extern int32_t nr_256qam_mod_table[512]; +extern int32_t nr_256qam_mod_table[256]; #endif From 89004ef241632dc526378a3366ea313b573f9492 Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 25 Aug 2025 16:41:37 +0200 Subject: [PATCH 800/964] use common scale channel functions for DLSCH and ULSCH --- doc/SW_archi.md | 2 +- .../PHY/NR_TRANSPORT/nr_ulsch_demodulation.c | 52 +++------------- .../NR_UE_TRANSPORT/nr_dlsch_demodulation.c | 61 +------------------ .../PHY/nr_phy_common/inc/nr_phy_common.h | 1 + .../PHY/nr_phy_common/src/nr_phy_common.c | 27 ++++++++ 5 files changed, 37 insertions(+), 106 deletions(-) diff --git a/doc/SW_archi.md b/doc/SW_archi.md index 433a1ac3d1..9c3736ac2a 100644 --- a/doc/SW_archi.md +++ b/doc/SW_archi.md @@ -151,7 +151,7 @@ populates UL_INFO.uci_ind, actual uci data is in gNB->pucch {: .func4} * nr_ulsch_extract_rbs_single() {: .func4} - * nr_ulsch_scale_channel() + * nr_scale_channel() {: .func4} * nr_ulsch_channel_level() {: .func4} diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c index bd4ee92284..28f3e2cc67 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c @@ -159,42 +159,6 @@ static void nr_ulsch_extract_rbs(c16_t* const rxdataF, } } -static void nr_ulsch_scale_channel(int size_est, - int ul_ch_estimates_ext[][size_est], - NR_DL_FRAME_PARMS *frame_parms, - uint8_t symbol, - uint8_t is_dmrs_symbol, - uint32_t len, - uint8_t nrOfLayers, - unsigned short nb_rb, - int shift_ch_ext) -{ - // Determine scaling amplitude based the symbol - int b = 3; - short ch_amp = 1024 * 8; - if (shift_ch_ext > 3) { - b = 0; - ch_amp >>= (shift_ch_ext - 3); - if (ch_amp == 0) { - ch_amp = 1; - } - } else { - b -= shift_ch_ext; - } - simde__m128i ch_amp128 = simde_mm_set1_epi16(ch_amp); // Q3.13 - LOG_D(PHY, "Scaling PUSCH Chest in OFDM symbol %d by %d, pilots %d nb_rb %d NCP %d symbol %d\n", symbol, ch_amp, is_dmrs_symbol, nb_rb, frame_parms->Ncp, symbol); - - for (int aatx = 0; aatx < nrOfLayers; aatx++) { - for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { - simde__m128i *ul_ch128 = (simde__m128i *)&ul_ch_estimates_ext[aatx * frame_parms->nb_antennas_rx + aarx][symbol * len]; - for (int i = 0; i < len >> 2; i++) { - ul_ch128[i] = simde_mm_mulhi_epi16(ul_ch128[i], ch_amp128); - ul_ch128[i] = simde_mm_slli_epi16(ul_ch128[i], b); - } - } - } -} - static int get_nb_re_pusch (NR_DL_FRAME_PARMS *frame_parms, nfapi_nr_pusch_pdu_t *rel15_ul,int symbol) { uint8_t dmrs_symbol_flag = (rel15_ul->ul_dmrs_symb_pos >> symbol) & 0x01; @@ -1375,15 +1339,13 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, //---------------------------------------------------------- //--------------------- Channel Scaling -------------------- //---------------------------------------------------------- - nr_ulsch_scale_channel(size_est, - ul_ch_estimates_ext, - frame_parms, - meas_symbol, - (rel15_ul->ul_dmrs_symb_pos >> meas_symbol) & 0x01, - nb_re_pusch, - rel15_ul->nrOfLayers, - rel15_ul->rb_size, - shift_ch_ext); + nr_scale_channel(size_est, + ul_ch_estimates_ext, + meas_symbol, + nb_re_pusch, + rel15_ul->nrOfLayers, + frame_parms->nb_antennas_rx, + shift_ch_ext); int avg[frame_parms->nb_antennas_rx*rel15_ul->nrOfLayers]; nr_channel_level(meas_symbol, diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c index e281e1851d..10294bccb4 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c @@ -193,15 +193,6 @@ static void nr_dlsch_channel_compensation(uint32_t rx_size_symbol, unsigned char output_shift, PHY_NR_MEASUREMENTS *measurements); -void nr_dlsch_scale_channel(uint32_t rx_size_symbol, - int32_t dl_ch_estimates_ext[][rx_size_symbol], - NR_DL_FRAME_PARMS *frame_parms, - uint8_t n_tx, - uint8_t n_rx, - uint8_t symbol, - uint8_t pilots, - uint32_t len, - unsigned short nb_rb); static void nr_dlsch_detection_mrc(uint32_t rx_size_symbol, short nl, short n_rx, @@ -507,7 +498,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, //--------------------- Channel Scaling -------------------- //---------------------------------------------------------- start_meas_nr_ue_phy(ue, DLSCH_CHANNEL_SCALE_STATS); - nr_dlsch_scale_channel(rx_size_symbol, dl_ch_estimates_ext, frame_parms, nl, n_rx, symbol, pilots, nb_re_pdsch, nb_rb_pdsch); + nr_scale_channel(rx_size_symbol, dl_ch_estimates_ext, 0, nb_re_pdsch, nl, n_rx, 0); stop_meas_nr_ue_phy(ue, DLSCH_CHANNEL_SCALE_STATS); if (meas_enabled) { LOG_D(PHY, @@ -921,56 +912,6 @@ static void nr_dlsch_channel_compensation(uint32_t rx_size_symbol, } } -void nr_dlsch_scale_channel(uint32_t rx_size_symbol, - int32_t dl_ch_estimates_ext[][rx_size_symbol], - NR_DL_FRAME_PARMS *frame_parms, - uint8_t n_tx, - uint8_t n_rx, - uint8_t symbol, - uint8_t pilots, - uint32_t len, - unsigned short nb_rb) - -{ - - - short rb, ch_amp; - unsigned char aatx,aarx; - simde__m128i *dl_ch128, ch_amp128; - - uint32_t nb_rb_0 = len/12 + ((len%12)?1:0); - - // Determine scaling amplitude based the symbol - - ch_amp = 1024*8; //((pilots) ? (dlsch_ue[0]->sqrt_rho_b) : (dlsch_ue[0]->sqrt_rho_a)); - - LOG_D(PHY,"Scaling PDSCH Chest in OFDM symbol %d by %d, pilots %d nb_rb %d NCP %d symbol %d\n",symbol,ch_amp,pilots,nb_rb,frame_parms->Ncp,symbol); - // printf("Scaling PDSCH Chest in OFDM symbol %d by %d\n",symbol_mod,ch_amp); - - ch_amp128 = simde_mm_set1_epi16(ch_amp); // Q3.13 - - for (aatx=0; aatx 3) { + b = 0; + ch_amp >>= (shift_ch_ext - 3); + if (ch_amp == 0) { + ch_amp = 1; + } + } else { + b -= shift_ch_ext; + } + simde__m128i ch_amp128 = simde_mm_set1_epi16(ch_amp); // Q3.13 + LOG_D(PHY, "Scaling channel est in OFDM symbol %d by %d\n", symb, ch_amp); + + for (int l = 0; l < nrOfLayers; l++) { + for (int aarx = 0; aarx < nb_rx; aarx++) { + simde__m128i *ul_ch128 = (simde__m128i *)&ch_estimates_ext[l * nb_rx + aarx][symb * len]; + for (int i = 0; i < len >> 2; i++) { + ul_ch128[i] = simde_mm_mulhi_epi16(ul_ch128[i], ch_amp128); + ul_ch128[i] = simde_mm_slli_epi16(ul_ch128[i], b); + } + } + } +} void nr_fo_compensation(double fo_Hz, int samples_per_ms, int sample_offset, const c16_t *rxdata_in, c16_t *rxdata_out, int size) { From c88b7bac72955433e7a3d43c732514cc7405bb7c Mon Sep 17 00:00:00 2001 From: francescomani Date: Wed, 17 Sep 2025 09:40:50 +0200 Subject: [PATCH 801/964] process the remaining elements in scale channel --- openair1/PHY/nr_phy_common/src/nr_phy_common.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/openair1/PHY/nr_phy_common/src/nr_phy_common.c b/openair1/PHY/nr_phy_common/src/nr_phy_common.c index cdc4e6f13a..aacabeed3b 100644 --- a/openair1/PHY/nr_phy_common/src/nr_phy_common.c +++ b/openair1/PHY/nr_phy_common/src/nr_phy_common.c @@ -445,10 +445,17 @@ void nr_scale_channel(int size, int ch_estimates_ext[][size], int symb, uint32_t for (int l = 0; l < nrOfLayers; l++) { for (int aarx = 0; aarx < nb_rx; aarx++) { simde__m128i *ul_ch128 = (simde__m128i *)&ch_estimates_ext[l * nb_rx + aarx][symb * len]; - for (int i = 0; i < len >> 2; i++) { + int loop_end = len >> 2; + for (int i = 0; i < loop_end; i++) { ul_ch128[i] = simde_mm_mulhi_epi16(ul_ch128[i], ch_amp128); ul_ch128[i] = simde_mm_slli_epi16(ul_ch128[i], b); } + // loop for the remaining elements + int start_index = loop_end * 4; + for (int j = start_index; j < len; j++) { + c16_t *temp = ((c16_t *)ul_ch128) + j; + *temp = c16Shift(*temp, b); + } } } } From 2bf7c2500e387c9afd34dae0e405e6341c575543 Mon Sep 17 00:00:00 2001 From: rmagueta Date: Thu, 18 Sep 2025 16:50:41 +0100 Subject: [PATCH 802/964] Simplifying bit shift in the nr_scale_channel() function --- .../PHY/nr_phy_common/src/nr_phy_common.c | 20 ++----------------- 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/openair1/PHY/nr_phy_common/src/nr_phy_common.c b/openair1/PHY/nr_phy_common/src/nr_phy_common.c index aacabeed3b..a723780f94 100644 --- a/openair1/PHY/nr_phy_common/src/nr_phy_common.c +++ b/openair1/PHY/nr_phy_common/src/nr_phy_common.c @@ -427,34 +427,18 @@ void nr_channel_level(const int symbol, void nr_scale_channel(int size, int ch_estimates_ext[][size], int symb, uint32_t len, int nrOfLayers, int nb_rx, int shift_ch_ext) { - // Determine scaling amplitude based the symbol - int b = 3; - short ch_amp = 1024 * 8; - if (shift_ch_ext > 3) { - b = 0; - ch_amp >>= (shift_ch_ext - 3); - if (ch_amp == 0) { - ch_amp = 1; - } - } else { - b -= shift_ch_ext; - } - simde__m128i ch_amp128 = simde_mm_set1_epi16(ch_amp); // Q3.13 - LOG_D(PHY, "Scaling channel est in OFDM symbol %d by %d\n", symb, ch_amp); - for (int l = 0; l < nrOfLayers; l++) { for (int aarx = 0; aarx < nb_rx; aarx++) { simde__m128i *ul_ch128 = (simde__m128i *)&ch_estimates_ext[l * nb_rx + aarx][symb * len]; int loop_end = len >> 2; for (int i = 0; i < loop_end; i++) { - ul_ch128[i] = simde_mm_mulhi_epi16(ul_ch128[i], ch_amp128); - ul_ch128[i] = simde_mm_slli_epi16(ul_ch128[i], b); + ul_ch128[i] = simde_mm_srai_epi16(ul_ch128[i], shift_ch_ext); } // loop for the remaining elements int start_index = loop_end * 4; for (int j = start_index; j < len; j++) { c16_t *temp = ((c16_t *)ul_ch128) + j; - *temp = c16Shift(*temp, b); + *temp = c16Shift(*temp, shift_ch_ext); } } } From a7257eaff1341611356a96c7e51a8395b3463f2e Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Thu, 18 Sep 2025 22:12:37 +0200 Subject: [PATCH 803/964] E1 lib: fix inconsistent equality checking patterns in E1AP bearer context management Replace result &= pattern with consistent early return pattern: - Fix mixing of logical (&&) and binary (&) operators - Use consistent 'if (!eq_()) return false;' pattern throughout - Fix bug in eq_bearer_context_mod_response where drbModA was compared with itself - Remove unused 'bool result = true;' variables - Always return true at the end of equality functions This makes the code more consistent with the rest of the codebase and provides better error reporting through the existing _E1_EQ_CHECK macros. --- .../E1AP/lib/e1ap_bearer_context_management.c | 52 +++++++++++-------- 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/openair2/E1AP/lib/e1ap_bearer_context_management.c b/openair2/E1AP/lib/e1ap_bearer_context_management.c index 0f2e5972e2..fdccd94925 100644 --- a/openair2/E1AP/lib/e1ap_bearer_context_management.c +++ b/openair2/E1AP/lib/e1ap_bearer_context_management.c @@ -398,7 +398,6 @@ static bool eq_pdcp_info(const e1_pdcp_status_info_t *a, const e1_pdcp_status_in */ static bool eq_drb_to_setup(const DRB_nGRAN_to_setup_t *a, const DRB_nGRAN_to_setup_t *b) { - bool result = true; _E1_EQ_CHECK_LONG(a->id, b->id); _E1_EQ_CHECK_INT(a->numCellGroups, b->numCellGroups); for (int i = 0; i < a->numCellGroups; i++) { @@ -406,11 +405,14 @@ static bool eq_drb_to_setup(const DRB_nGRAN_to_setup_t *a, const DRB_nGRAN_to_se } _E1_EQ_CHECK_INT(a->numQosFlow2Setup, b->numQosFlow2Setup); for (int i = 0; i < a->numQosFlow2Setup; i++) { - result &= eq_qos_flow(&a->qosFlows[i], &b->qosFlows[i]); + if (!eq_qos_flow(&a->qosFlows[i], &b->qosFlows[i])) + return false; } - result &= eq_pdcp_config(&a->pdcp_config, &b->pdcp_config); - result &= eq_sdap_config(&a->sdap_config, &b->sdap_config); - return result; + if (!eq_pdcp_config(&a->pdcp_config, &b->pdcp_config)) + return false; + if (!eq_sdap_config(&a->sdap_config, &b->sdap_config)) + return false; + return true; } static void free_drb_to_setup_item(const DRB_nGRAN_to_setup_t *msg) @@ -1939,25 +1941,32 @@ static bool eq_security_ind(security_indication_t *a, security_indication_t *b) */ static bool eq_drb_to_mod(const DRB_nGRAN_to_mod_t *a, const DRB_nGRAN_to_mod_t *b) { - bool result = true; _E1_EQ_CHECK_LONG(a->id, b->id); _E1_EQ_CHECK_INT(a->numQosFlow2Setup, b->numQosFlow2Setup); for (int i = 0; i < a->numQosFlow2Setup; i++) { - result &= eq_qos_flow(&a->qosFlows[i], &b->qosFlows[i]); + if (!eq_qos_flow(&a->qosFlows[i], &b->qosFlows[i])) + return false; } _E1_EQ_CHECK_INT(a->numDlUpParam, b->numDlUpParam); for (int i = 0; i < a->numDlUpParam; i++) { _E1_EQ_CHECK_INT(a->DlUpParamList[i].cell_group_id, b->DlUpParamList[i].cell_group_id); - result &= eq_up_tl_info(&a->DlUpParamList[i].tl_info, &b->DlUpParamList[i].tl_info); + if (!eq_up_tl_info(&a->DlUpParamList[i].tl_info, &b->DlUpParamList[i].tl_info)) + return false; + } + if (a->pdcp_config && b->pdcp_config) { + if (!eq_pdcp_config(a->pdcp_config, b->pdcp_config)) + return false; + } + if (a->sdap_config && b->sdap_config) { + if (!eq_sdap_config(a->sdap_config, b->sdap_config)) + return false; } - if (a->pdcp_config && b->pdcp_config) - result &= eq_pdcp_config(a->pdcp_config, b->pdcp_config); - if (a->sdap_config && b->sdap_config) - result &= eq_sdap_config(a->sdap_config, b->sdap_config); _E1_EQ_CHECK_OPTIONAL_PTR(a, b, pdcp_status); - if (a->pdcp_status && b->pdcp_status) - result &= eq_pdcp_info(a->pdcp_status, b->pdcp_status); - return result; + if (a->pdcp_status && b->pdcp_status) { + if (!eq_pdcp_info(a->pdcp_status, b->pdcp_status)) + return false; + } + return true; } /** @brief Equality check for PDU session item to modify */ @@ -2423,8 +2432,6 @@ bool eq_bearer_context_mod_response(const e1ap_bearer_modif_resp_t *a, const e1a { if (!a || !b) return false; // Null-check both inputs - bool result = true; - // Basic members _E1_EQ_CHECK_INT(a->gNB_cu_cp_ue_id, b->gNB_cu_cp_ue_id); _E1_EQ_CHECK_INT(a->gNB_cu_up_ue_id, b->gNB_cu_up_ue_id); @@ -2440,8 +2447,10 @@ bool eq_bearer_context_mod_response(const e1ap_bearer_modif_resp_t *a, const e1a _E1_EQ_CHECK_OPTIONAL_IE(pduA, pduB, integrityProtectionIndication, _E1_EQ_CHECK_INT); _E1_EQ_CHECK_OPTIONAL_PTR(pduA, pduB, ng_DL_UP_TL_info); - if (pduA->ng_DL_UP_TL_info && pduB->ng_DL_UP_TL_info) - result &= eq_up_tl_info(pduA->ng_DL_UP_TL_info, pduB->ng_DL_UP_TL_info); + if (pduA->ng_DL_UP_TL_info && pduB->ng_DL_UP_TL_info) { + if (!eq_up_tl_info(pduA->ng_DL_UP_TL_info, pduB->ng_DL_UP_TL_info)) + return false; + } // DRB Modified List _E1_EQ_CHECK_INT(pduA->numDRBModified, pduB->numDRBModified); @@ -2455,7 +2464,8 @@ bool eq_bearer_context_mod_response(const e1ap_bearer_modif_resp_t *a, const e1a } _E1_EQ_CHECK_OPTIONAL_PTR(drbModA, drbModB, pdcp_status); if (drbModA->pdcp_status && drbModB->pdcp_status) { - result &= eq_pdcp_info(drbModA->pdcp_status, drbModA->pdcp_status); + if (!eq_pdcp_info(drbModA->pdcp_status, drbModB->pdcp_status)) + return false; } } @@ -2490,7 +2500,7 @@ bool eq_bearer_context_mod_response(const e1ap_bearer_modif_resp_t *a, const e1a } - return result; + return true; } /** From 8dcd253e60171bb0de622a49b55a5eb0735eb4e6 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Thu, 18 Sep 2025 22:15:30 +0200 Subject: [PATCH 804/964] E1 lib: Adopt _E1_EQ_CHECK_OPTIONAL_PTR macro in E1AP bearer context management - Add _E1_EQ_CHECK_OPTIONAL_PTR checks for pdcp_config, sdap_config, UP_TL_information, and securityIndication - Fix bug in eq_pdu_session_to_mod_item where a->UP_TL_information was compared with itself instead of b->UP_TL_information - Fix eq_security_ind call to properly handle return value with early return pattern - Improve consistency with existing macro usage patterns in the codebase - Provide better error reporting for optional pointer field mismatches --- openair2/E1AP/lib/e1ap_bearer_context_management.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/openair2/E1AP/lib/e1ap_bearer_context_management.c b/openair2/E1AP/lib/e1ap_bearer_context_management.c index fdccd94925..109b0008d3 100644 --- a/openair2/E1AP/lib/e1ap_bearer_context_management.c +++ b/openair2/E1AP/lib/e1ap_bearer_context_management.c @@ -1953,10 +1953,12 @@ static bool eq_drb_to_mod(const DRB_nGRAN_to_mod_t *a, const DRB_nGRAN_to_mod_t if (!eq_up_tl_info(&a->DlUpParamList[i].tl_info, &b->DlUpParamList[i].tl_info)) return false; } + _E1_EQ_CHECK_OPTIONAL_PTR(a, b, pdcp_config); if (a->pdcp_config && b->pdcp_config) { if (!eq_pdcp_config(a->pdcp_config, b->pdcp_config)) return false; } + _E1_EQ_CHECK_OPTIONAL_PTR(a, b, sdap_config); if (a->sdap_config && b->sdap_config) { if (!eq_sdap_config(a->sdap_config, b->sdap_config)) return false; @@ -1973,7 +1975,8 @@ static bool eq_drb_to_mod(const DRB_nGRAN_to_mod_t *a, const DRB_nGRAN_to_mod_t static bool eq_pdu_session_to_mod_item(const pdu_session_to_mod_t *a, const pdu_session_to_mod_t *b) { _E1_EQ_CHECK_LONG(a->sessionId, b->sessionId); - if (a->UP_TL_information && a->UP_TL_information) { + _E1_EQ_CHECK_OPTIONAL_PTR(a, b, UP_TL_information); + if (a->UP_TL_information && b->UP_TL_information) { if (!eq_up_tl_info(a->UP_TL_information, b->UP_TL_information)) return false; } @@ -1987,8 +1990,10 @@ static bool eq_pdu_session_to_mod_item(const pdu_session_to_mod_t *a, const pdu_ if (!eq_drb_to_mod(&a->DRBnGRanModList[i], &b->DRBnGRanModList[i])) return false; } + _E1_EQ_CHECK_OPTIONAL_PTR(a, b, securityIndication); if (a->securityIndication && b->securityIndication) { - eq_security_ind(a->securityIndication, b->securityIndication); + if (!eq_security_ind(a->securityIndication, b->securityIndication)) + return false; } return true; } From 50760c04a705862246fe4e19cd7bae02ea8467df Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Thu, 18 Sep 2025 21:43:30 +0200 Subject: [PATCH 805/964] Fix log messages in N2 handover: print both PCI and Cell ID when available - Fixed incorrect log messages that said 'PCI=%lu' when printing nr_cell_id - Now prints both NR Cell ID and PCI when DU is found - Provides better debugging information for handover requests --- openair2/RRC/NR/rrc_gNB_NGAP.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index 34666e3538..75e6742422 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -1129,11 +1129,10 @@ void rrc_gNB_send_NGAP_HANDOVER_FAILURE(gNB_RRC_INST *rrc, ngap_handover_failure /** @brief Process NG Handover Request message (8.4.2.2 3GPP TS 38.413) */ int rrc_gNB_process_Handover_Request(gNB_RRC_INST *rrc, instance_t instance, ngap_handover_request_t *msg) { - LOG_I(NR_RRC, "Received Handover Request (on PCI=%lu) \n", msg->nr_cell_id); struct nr_rrc_du_container_t *du = get_du_by_cell_id(rrc, msg->nr_cell_id); if (du == NULL) { /* Cell Not Found! Return HO Request Failure*/ - LOG_E(RRC, "Failed to process Handover Request: no DU found with PCI=%lu \n", msg->nr_cell_id); + LOG_E(RRC, "Failed to process Handover Request: no DU found with NR Cell ID=%lu \n", msg->nr_cell_id); ngap_handover_failure_t fail = { .amf_ue_ngap_id = msg->amf_ue_ngap_id, .cause.type = NGAP_CAUSE_RADIO_NETWORK, @@ -1142,6 +1141,8 @@ int rrc_gNB_process_Handover_Request(gNB_RRC_INST *rrc, instance_t instance, nga rrc_gNB_send_NGAP_HANDOVER_FAILURE(rrc, &fail); return -1; } + uint16_t pci = du->setup_req->cell[0].info.nr_pci; + LOG_I(NR_RRC, "Received Handover Request (on NR Cell ID=%lu, PCI=%u) \n", msg->nr_cell_id, pci); // Create UE context sctp_assoc_t curr_assoc_id = du->assoc_id; From e535fbe6a715808fe1fee7f691ec77984467923c Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Tue, 23 Sep 2025 10:55:45 +0200 Subject: [PATCH 806/964] Replace impossible ID mismatch checks with DevAssert in NGAP functions - Replace error handling for impossible ID mismatches with DevAssert statements - If ngap_get_ue_context() succeeds, returned context must have matching NGAP gNB UE IDs by definition - This catches potential bugs in the lookup function immediately - Affects: handover_required, handover_notify, handover_cancel, ul_ran_status_transfer These checks were logically impossible since we looked up the context using the same IDs we were then checking for mismatch. --- openair3/NGAP/ngap_gNB.c | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/openair3/NGAP/ngap_gNB.c b/openair3/NGAP/ngap_gNB.c index 8c9ac6a973..46bcf93cad 100644 --- a/openair3/NGAP/ngap_gNB.c +++ b/openair3/NGAP/ngap_gNB.c @@ -293,12 +293,7 @@ int ngap_handover_required(instance_t instance, ngap_handover_required_t *msg) return -1; } - if ((ue_context_p->gNB_ue_ngap_id != msg->gNB_ue_ngap_id)) { - NGAP_ERROR("ue_context_p->gNB_ue_ngap_id %d does not match msg->gNB_ue_ngap_id %d\n", - ue_context_p->gNB_ue_ngap_id, - msg->gNB_ue_ngap_id); - return -1; - } + DevAssert(ue_context_p->gNB_ue_ngap_id == msg->gNB_ue_ngap_id); NGAP_NGAP_PDU_t *pdu = encode_ng_handover_required(msg); if (!pdu) { @@ -434,11 +429,7 @@ static int ngap_gNB_handover_notify(instance_t instance, const ngap_handover_not NGAP_ERROR("Failed to encode Handover Notify: no ue context associated with gNB_ue_ngap_id=%d\n", msg->gNB_ue_ngap_id); return -1; } - - if (ue_context_p->gNB_ue_ngap_id != msg->gNB_ue_ngap_id) { - NGAP_ERROR("Failed to encode Handover Notify: unknown gNB_ue_ngap_id=%d\n", msg->gNB_ue_ngap_id); - return -1; - } + DevAssert(ue_context_p->gNB_ue_ngap_id == msg->gNB_ue_ngap_id); if (ue_context_p->amf_ue_ngap_id != msg->amf_ue_ngap_id) { NGAP_ERROR("Failed to encode Handover Notify: unknown amf_ue_ngap_id=%ld\n", msg->amf_ue_ngap_id); @@ -479,11 +470,7 @@ static int ngap_gNB_handover_cancel(instance_t instance, const ngap_handover_can NGAP_ERROR("Failed to encode Handover Cancel: no UE context for gNB_ue_ngap_id=%d\n", msg->gNB_ue_ngap_id); return -1; } - - if (ue_context_p->gNB_ue_ngap_id != msg->gNB_ue_ngap_id) { - NGAP_ERROR("Failed to encode Handover Cancel: mismatched gNB_ue_ngap_id=%d\n", msg->gNB_ue_ngap_id); - return -1; - } + DevAssert(ue_context_p->gNB_ue_ngap_id == msg->gNB_ue_ngap_id); if (ue_context_p->amf_ue_ngap_id != msg->amf_ue_ngap_id) { NGAP_ERROR("Failed to encode Handover Cancel: mismatched amf_ue_ngap_id=%ld\n", msg->amf_ue_ngap_id); @@ -522,11 +509,13 @@ int ngap_gNB_handle_ul_ran_status_transfer(instance_t instance, const ngap_ran_s DevAssert(ngap_gNB_instance_p != NULL); ngap_gNB_ue_context_t *ue_context_p = ngap_get_ue_context(msg->gnb_ue_ngap_id); - if (!ue_context_p || ue_context_p->gNB_ue_ngap_id != msg->gnb_ue_ngap_id) { + if (!ue_context_p) { NGAP_ERROR("Could not find UE context for gNB_ue_ngap_id %d\n", msg->gnb_ue_ngap_id); return -1; } + DevAssert(ue_context_p->gNB_ue_ngap_id == msg->gnb_ue_ngap_id); + NGAP_NGAP_PDU_t *pdu = encode_ng_ul_ran_status_transfer(msg); if (!pdu) { NGAP_ERROR("Failed to encode UL RAN Status Transfer\n"); From 41b33e912462347768d5c4d483b4251248a5b0c7 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Thu, 25 Sep 2025 15:22:10 +0200 Subject: [PATCH 807/964] CI: Update frequency in HO setup Move center frequency from 3439 MHz to 4185 MHz to avoid interference with other lab setups. --- .../gnb-du.sa.band78.51prb.usrpb210.ho-pci0.conf | 14 +++++++------- .../gnb-du.sa.band78.51prb.usrpb210.ho-pci1.conf | 14 +++++++------- ci-scripts/conf_files/neighbour-config-ho.conf | 8 ++++---- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/ci-scripts/conf_files/gnb-du.sa.band78.51prb.usrpb210.ho-pci0.conf b/ci-scripts/conf_files/gnb-du.sa.band78.51prb.usrpb210.ho-pci0.conf index 216e2c3bd2..eb52e68566 100644 --- a/ci-scripts/conf_files/gnb-du.sa.band78.51prb.usrpb210.ho-pci0.conf +++ b/ci-scripts/conf_files/gnb-du.sa.band78.51prb.usrpb210.ho-pci0.conf @@ -26,11 +26,11 @@ gNBs = # downlinkConfigCommon #frequencyInfoDL - # 4.01 GHz - absoluteFrequencySSB = 629376; - dl_frequencyBand = 78; - # 4 GHz - dl_absoluteFrequencyPointA = 628720; + # 4186.56 MHz + absoluteFrequencySSB = 679104; + dl_frequencyBand = 77; + # 4175.82 MHz + dl_absoluteFrequencyPointA = 678388; #scs-SpecificCarrierList dl_offstToCarrier = 0; # subcarrierSpacing @@ -50,7 +50,7 @@ gNBs = #uplinkConfigCommon #frequencyInfoUL - ul_frequencyBand = 78; + ul_frequencyBand = 77; #scs-SpecificCarrierList ul_offstToCarrier = 0; # subcarrierSpacing @@ -188,7 +188,7 @@ RUs = ( nb_rx = 1 att_tx = 0; att_rx = 0; - bands = [78]; + bands = [77]; max_pdschReferenceSignalPower = -27; max_rxgain = 114; eNB_instances = [0]; diff --git a/ci-scripts/conf_files/gnb-du.sa.band78.51prb.usrpb210.ho-pci1.conf b/ci-scripts/conf_files/gnb-du.sa.band78.51prb.usrpb210.ho-pci1.conf index ff154f733f..3ba7e17b46 100644 --- a/ci-scripts/conf_files/gnb-du.sa.band78.51prb.usrpb210.ho-pci1.conf +++ b/ci-scripts/conf_files/gnb-du.sa.band78.51prb.usrpb210.ho-pci1.conf @@ -26,11 +26,11 @@ gNBs = # downlinkConfigCommon #frequencyInfoDL - # 4.01 GHz - absoluteFrequencySSB = 629376; - dl_frequencyBand = 78; - # 4 GHz - dl_absoluteFrequencyPointA = 628720; + # 4186.56 MHz + absoluteFrequencySSB = 679104; + dl_frequencyBand = 77; + # 4175.82 MHz + dl_absoluteFrequencyPointA = 678388; #scs-SpecificCarrierList dl_offstToCarrier = 0; # subcarrierSpacing @@ -50,7 +50,7 @@ gNBs = #uplinkConfigCommon #frequencyInfoUL - ul_frequencyBand = 78; + ul_frequencyBand = 77; #scs-SpecificCarrierList ul_offstToCarrier = 0; # subcarrierSpacing @@ -188,7 +188,7 @@ RUs = ( nb_rx = 1 att_tx = 0; att_rx = 0; - bands = [78]; + bands = [77]; max_pdschReferenceSignalPower = -27; max_rxgain = 114; eNB_instances = [0]; diff --git a/ci-scripts/conf_files/neighbour-config-ho.conf b/ci-scripts/conf_files/neighbour-config-ho.conf index f9d1e38ee0..2490ce1883 100644 --- a/ci-scripts/conf_files/neighbour-config-ho.conf +++ b/ci-scripts/conf_files/neighbour-config-ho.conf @@ -6,9 +6,9 @@ neighbour_list = ( gNB_ID = 0xe01; nr_cellid = 11111111; physical_cellId = 1; - absoluteFrequencySSB = 629376; + absoluteFrequencySSB = 679104; subcarrierSpacing = 1; #30 KHz - band = 78; + band = 77; plmn = { mcc = 001; mnc = 03; mnc_length = 2}; tracking_area_code = 1; } @@ -21,9 +21,9 @@ neighbour_list = ( gNB_ID = 0xe00; nr_cellid = 12345678; physical_cellId = 0; - absoluteFrequencySSB = 629376; + absoluteFrequencySSB = 679104; subcarrierSpacing = 1; #30 KHz - band = 78; + band = 77; plmn = { mcc = 001; mnc = 03; mnc_length = 2}; tracking_area_code = 1; } From a64038658f66693808f6f3dde1e8747047118d53 Mon Sep 17 00:00:00 2001 From: alexjiao Date: Fri, 13 Jun 2025 15:56:05 +0800 Subject: [PATCH 808/964] Modify nr_uci_encoding for UCI on PUSCH 38.212 section 5.3.3.1 and 5.3.3.2 describe how to encode 1-bit and 2-bit information. This is needed when typically HARQ-ACK will be transmitted on PUSCH. 38.212 section 5.4.3 also describes how to do rate matching for channel coding of small block lengths. --- .../CODING/nrSmallBlock/encodeSmallBlock.c | 3 + openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c | 285 ++++++++++++------ openair1/PHY/NR_UE_TRANSPORT/pucch_nr.h | 2 + 3 files changed, 194 insertions(+), 96 deletions(-) diff --git a/openair1/PHY/CODING/nrSmallBlock/encodeSmallBlock.c b/openair1/PHY/CODING/nrSmallBlock/encodeSmallBlock.c index 3078243c8f..a3a5863542 100644 --- a/openair1/PHY/CODING/nrSmallBlock/encodeSmallBlock.c +++ b/openair1/PHY/CODING/nrSmallBlock/encodeSmallBlock.c @@ -31,11 +31,14 @@ */ #include "PHY/CODING/nrSmallBlock/nr_small_block_defs.h" +#include "common/utils/assertions.h" //input = [0 ... 0 c_K-1 ... c_2 c_1 c_0] //output = [d_31 d_30 ... d_2 d_1 d_0] uint32_t encodeSmallBlock(int in, int len) { + AssertFatal(len >= 3, "encodeSmallBlock only supports input lengths A >= 3, got A=%d", len); + uint32_t out = 0; for (int i = 0; i < len; i++) if ((in & (1 << i)) > 0) diff --git a/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c b/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c index 611572a0a3..b4c65cf28e 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c @@ -520,101 +520,143 @@ static inline void nr_pucch2_3_4_scrambling(uint16_t M_bit, uint16_t rnti, uint1 printf("\t\t [nr_pucch2_3_4_scrambling] scrambling M_bit=%d bits\n", M_bit); #endif } -static void nr_uci_encoding(uint64_t payload, - uint8_t nr_bit, - int fmt, - uint8_t is_pi_over_2_bpsk_enabled, - uint8_t nrofSymbols, - uint8_t nrofPRB, - uint8_t n_SF_PUCCH_s, - uint8_t intraSlotFrequencyHopping, - uint8_t add_dmrs, - uint64_t *b, - uint16_t *M_bit) { + +void nr_uci_encoding(uint64_t payload, uint8_t nr_bit, uint8_t nrofPRB, bool uci_on_pusch, uint16_t E, uint8_t Qm, uint64_t *b) +{ /* - * Implementing TS 38.212 Subclause 6.3.1.2 + * Implementing TS 38.212 Subclause 6.3.1.2 and 6.3.2 * */ // A is the payload size, to be provided in function call uint8_t A = nr_bit; // L is the CRC size - //uint8_t L; + // uint8_t L; // E is the rate matching output sequence length as given in TS 38.212 subclause 6.3.1.4.1 - uint16_t E=0,E_init; - - if (fmt == 2) E = 16*nrofSymbols*nrofPRB; - - if (fmt == 3) { - E_init = (is_pi_over_2_bpsk_enabled == 0) ? 24:12; - - if (nrofSymbols == 4) { - E = (intraSlotFrequencyHopping == 0)?(E_init*(nrofSymbols-1)*nrofPRB):((E_init*(nrofSymbols-1)*nrofPRB)); + // int I_seg; #ifdef DEBUG_NR_PUCCH_TX - printf("format 3 nrofSymbols =4 and E_init=%d,E=%d\n",E_init,E); + printf("\t\t [nr_uci_encoding] start function with encoding A=%d bits into M_bit=%d (where nrofPRB=%d)\n", A, E, nrofPRB); #endif - } - if (nrofSymbols > 4) { - E = E_init*(nrofSymbols-2)*nrofPRB; -#ifdef DEBUG_NR_PUCCH_TX - printf("format 3 nrofSymbols >4 and E_init=%d,E = %d\n",E_init,E); -#endif - } + // For A=1 case (single bit UCI) + if (A == 1) { + uint8_t uci_bit_val = payload & 1; // Extract the single UCI bit + uint64_t pattern_word; + uint8_t *b_bytes = (uint8_t *)b; // Access b as bytes to set individual special values - if (nrofSymbols > 9) { - E = (add_dmrs == 0)?(E_init*(nrofSymbols-2)*nrofPRB):((E_init*(nrofSymbols-4)*nrofPRB)); -#ifdef DEBUG_NR_PUCCH_TX - printf("format 3 nrofSymbols >9 and E_init=%d,E = %d\n",E_init,E); -#endif + if (Qm == 1) { + // For BPSK, just repeat the input bit + pattern_word = uci_bit_val ? 0xFFFFFFFFFFFFFFFFULL : 0x0000000000000000ULL; + for (int i = 0; i < 8; i++) { + b[i] = pattern_word; + } + } else { + // For higher order modulation (QPSK, etc.), use placeholder values + memset(b, 0, 8 * sizeof(uint64_t)); + + // Fill the entire output with the pattern + for (int i = 0; i < E; i++) { + switch (i % Qm) { + case 0: + // First bit in each group is actual UCI bit + b_bytes[i] = uci_bit_val; + LOG_D(PHY, + "[UCI_ENCODING_A1_QAM_LOOP] i=%d, i%%Qm=%d (case 0), writing uci_bit_val %d to b_bytes[%d]\n", + i, + i % Qm, + uci_bit_val, + i); + break; + case 1: + b_bytes[i] = NR_PUSCH_y; + LOG_D(PHY, + "[UCI_ENCODING_A1_QAM_LOOP] i=%d, i%%Qm=%d (case 1), writing NR_PUSCH_y (0x%02X) to b_bytes[%d]\n", + i, + i % Qm, + NR_PUSCH_y, + i); + break; + default: + b_bytes[i] = NR_PUSCH_x; + break; + } + } } } + // For A=2 case (two bits UCI) + else if (A == 2) { + uint8_t bit0 = (payload >> 0) & 1; + uint8_t bit1 = (payload >> 1) & 1; + uint8_t c2 = bit0 ^ bit1; // Parity bit (XOR of the two bits) + uint8_t *b_bytes = (uint8_t *)b; - if (fmt == 4) { - E_init = (is_pi_over_2_bpsk_enabled == 0) ? 24:12; + if (Qm == 1) { + // For BPSK, output is [bit0, bit1, c2] + uint64_t pattern = (bit0) | (bit1 << 1) | (c2 << 2); + // Repeat this 3-bit pattern to fill the output + pattern |= pattern << 3; + pattern |= pattern << 6; + pattern |= pattern << 12; + pattern |= pattern << 24; + pattern |= pattern << 48; - if (nrofSymbols == 4) { - E = (intraSlotFrequencyHopping == 0)?(E_init*(nrofSymbols-1)/n_SF_PUCCH_s):((E_init*(nrofSymbols-1)/n_SF_PUCCH_s)); -#ifdef DEBUG_NR_PUCCH_TX - printf("format 4 nrofSymbols =4 and E_init=%d,E=%d\n",E_init,E); -#endif + for (int i = 0; i < 8; i++) { + b[i] = pattern; + } + } else { + // For higher order modulation (Qm>=2), using patterns from Table 5.3.3.2-1 + // Pattern: 3 groups of Qm bits each = 3*Qm total length + memset(b, 0, 8 * sizeof(uint64_t)); + + for (int i = 0; i < E; i++) { + int pos_in_pattern = i % (3 * Qm); + int group = pos_in_pattern / Qm; + int pos_in_group = pos_in_pattern % Qm; + uint8_t val_to_write; + + if (pos_in_group == 0) { + if (group == 0) + val_to_write = bit0; + else if (group == 1) + val_to_write = c2; + else + val_to_write = bit1; + } else if (pos_in_group == 1) { + if (group == 0) + val_to_write = bit1; + else if (group == 1) + val_to_write = bit0; + else + val_to_write = c2; + } else { + // Positions 2 and beyond are x placeholders + val_to_write = NR_PUSCH_x; + } + + b_bytes[i] = val_to_write; + } } - - if (nrofSymbols > 4) { - E = E_init*(nrofSymbols-2)/n_SF_PUCCH_s; -#ifdef DEBUG_NR_PUCCH_TX - printf("format 4 nrofSymbols >4 and E_init=%d,E = %d\n",E_init,E); -#endif - } - - if (nrofSymbols > 9) { - E = (add_dmrs == 0)?(E_init*(nrofSymbols-2)/n_SF_PUCCH_s):((E_init*(nrofSymbols-4)/n_SF_PUCCH_s)); -#ifdef DEBUG_NR_PUCCH_TX - printf("format 4 nrofSymbols >9 and E_init=%d,E = %d\n",E_init,E); -#endif - } - } - - *M_bit = E; - //int I_seg; -#ifdef DEBUG_NR_PUCCH_TX - printf("\t\t [nr_uci_encoding] start function with fmt=%d, encoding A=%d bits into M_bit=%d (where nrofSymbols=%d,nrofPRB=%d)\n",fmt,A,*M_bit,nrofSymbols,nrofPRB); -#endif - - if (A<=11) { + } else if (A <= 11) { // procedure in subclause 6.3.1.2.2 (UCI encoded by channel coding of small block lengths -> subclause 6.3.1.3.2) // CRC bits are not attached, and coding small block lengths (subclause 5.3.3) uint64_t b0 = encodeSmallBlock(payload, A); - // repetition for rate-matching up to 16 PRB - b[0] = b0 | (b0<<32); - b[1] = b[0]; - b[2] = b[0]; - b[3] = b[0]; - b[4] = b[0]; - b[5] = b[0]; - b[6] = b[0]; - b[7] = b[0]; - AssertFatal(nrofPRB<=16,"Number of PRB >16\n"); - } else if (A>=12) { + if (uci_on_pusch) { + b[0] = b0; + for (int i = 1; i < 8; i++) { + b[i] = 0; + } + } else { + // repetition for rate-matching up to 16 PRB + b[0] = b0 | (b0<<32); + b[1] = b[0]; + b[2] = b[0]; + b[3] = b[0]; + b[4] = b[0]; + b[5] = b[0]; + b[6] = b[0]; + b[7] = b[0]; + AssertFatal(nrofPRB<=16,"Number of PRB >16\n"); + } + } else if (A >= 12) { // Encoder reversal payload = reverse_bits(payload, A); @@ -623,7 +665,52 @@ static void nr_uci_encoding(uint64_t payload, A, nrofPRB); } - + + if (uci_on_pusch) { + // Rate matching for HARQ ACK following 38.212 section 5.4.3 + uint64_t output[8] = {0}; // Assuming max 512 bits (8 words of 64 bits) + uint16_t N; + if (nr_bit <= 2) { + // For A=1 (BPSK), N=1. For A=2 (QPSK), N=3 + N = (nr_bit == 1) ? 1 : 3; + } else if (nr_bit <= 11) { + // For 3 <= A <= 11, the small block encoder produces a 32-bit codeword + N = 32; + } else { + // For polar-coded UCI, output depends on nrofPRB + N = 16 * nrofPRB; + } + + if ((nr_bit == 1 || nr_bit == 2) && Qm > 1) { + LOG_D(PHY, + "[UCI_ENCODING_RM] Bypassing bit-wise rate matching for A=%d, Qm=%d. 'b' (length %d bytes) is assumed to be already " + "final.\n", + nr_bit, + Qm, + E); + } else { + if (N == 0) { + LOG_W(PHY, "HARQ-ACK rate matching with encoded_length=0 but E_uci_ack=%d\n", E); + return; + } + + // Rate matching with single loop for both repetition and puncturing + for (int i = 0; i < E; i++) { + int src_bit = i % N; // Modulo for cyclic repetition + int src_word = src_bit / 64; + int src_bit_pos = src_bit % 64; + int dst_word = i / 64; + int dst_bit_pos = i % 64; + + if ((b[src_word] >> src_bit_pos) & 1ULL) + output[dst_word] |= (1ULL << dst_bit_pos); + } + + for (int i = 0; i < (E + 63) / 64; i++) { + b[i] = output[i]; + } + } + } } //#if 0 void nr_generate_pucch2(const PHY_VARS_NR_UE *ue, @@ -639,13 +726,8 @@ void nr_generate_pucch2(const PHY_VARS_NR_UE *ue, // b is the block of bits transmitted on the physical channel after payload coding uint64_t b[16] = {0}; // limit to 1024-bit encoded length // M_bit is the number of bits of block b (payload after encoding) - uint16_t M_bit = 0; - nr_uci_encoding(pucch_pdu->payload, - pucch_pdu->n_bit, - 2,0, - pucch_pdu->nr_of_symbols, - pucch_pdu->prb_size, - 1,0,0,&b[0],&M_bit); + uint16_t M_bit = 16 * pucch_pdu->nr_of_symbols * pucch_pdu->prb_size; + nr_uci_encoding(pucch_pdu->payload, pucch_pdu->n_bit, pucch_pdu->prb_size, false, M_bit, 0, &b[0]); /* * Implementing TS 38.211 * Subclauses 6.3.2.5.1 Scrambling (PUCCH format 2) @@ -829,7 +911,7 @@ void nr_generate_pucch3_4(const PHY_VARS_NR_UE *ue, // b is the block of bits transmitted on the physical channel after payload coding uint64_t b[16]; // M_bit is the number of bits of block b (payload after encoding) - uint16_t M_bit; + uint16_t M_bit = 0; // parameter PUCCH-F4-preDFT-OCC-length set of {2,4} -> to use table -1 or -2 // in format 4, n_SF_PUCCH_s = {2,4}, provided by higher layer parameter PUCCH-F4-preDFT-OCC-length (in format 3 n_SF_PUCCH_s=1) uint8_t n_SF_PUCCH_s; @@ -856,17 +938,28 @@ void nr_generate_pucch3_4(const PHY_VARS_NR_UE *ue, uint16_t startingPRB = pucch_pdu->prb_start + pucch_pdu->bwp_start; uint8_t add_dmrs = pucch_pdu->add_dmrs_flag; - nr_uci_encoding(pucch_pdu->payload, - pucch_pdu->n_bit, - pucch_pdu->format_type, - is_pi_over_2_bpsk_enabled, - nrofSymbols, - nrofPRB, - n_SF_PUCCH_s, - intraSlotFrequencyHopping, - add_dmrs, - b, - &M_bit); + uint16_t E_init = (is_pi_over_2_bpsk_enabled == 0) ? 24 : 12; + + if (pucch_pdu->format_type == 3) { + if (nrofSymbols == 4) { + M_bit = (intraSlotFrequencyHopping == 0) ? (E_init * (nrofSymbols - 1) * nrofPRB) : (E_init * (nrofSymbols - 1) * nrofPRB); + } else if (nrofSymbols > 4) { + M_bit = E_init * (nrofSymbols - 2) * nrofPRB; + } else if (nrofSymbols > 9) { + M_bit = (add_dmrs == 0) ? (E_init * (nrofSymbols - 2) * nrofPRB) : (E_init * (nrofSymbols - 4) * nrofPRB); + } + } else if (pucch_pdu->format_type == 4) { + if (nrofSymbols == 4) { + M_bit = (intraSlotFrequencyHopping == 0) ? (E_init * (nrofSymbols - 1) / n_SF_PUCCH_s) + : (E_init * (nrofSymbols - 1) / n_SF_PUCCH_s); + } else if (nrofSymbols > 4) { + M_bit = E_init * (nrofSymbols - 2) / n_SF_PUCCH_s; + } else if (nrofSymbols > 9) { + M_bit = (add_dmrs == 0) ? (E_init * (nrofSymbols - 2) / n_SF_PUCCH_s) : (E_init * (nrofSymbols - 4) / n_SF_PUCCH_s); + } + } + + nr_uci_encoding(pucch_pdu->payload, pucch_pdu->n_bit, nrofPRB, false, M_bit, 0, b); /* * Implementing TS 38.211 * Subclauses 6.3.2.6.1 Scrambling (PUCCH formats 3 and 4) diff --git a/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.h b/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.h index 97be0e274f..1f24b589f4 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.h +++ b/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.h @@ -72,6 +72,8 @@ void nr_generate_pucch3_4(const PHY_VARS_NR_UE *ue, const int nr_slot_tx, const fapi_nr_ul_config_pucch_pdu *pucch_pdu); +void nr_uci_encoding(uint64_t payload, uint8_t nr_bit, uint8_t nrofPRB, bool uci_on_pusch, uint16_t E, uint8_t Qm, uint64_t *b); + static const uint8_t list_of_prime_numbers[46] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101,103,107,109,113, From 8222fa27e5a2e358e351cb522122cc8433dfc3c2 Mon Sep 17 00:00:00 2001 From: alexjiao Date: Fri, 13 Jun 2025 16:31:45 +0800 Subject: [PATCH 809/964] Add functions to calculate rate matching information for UCI on PUSCH Use betaOffset and alpha scaling etc. to get rate matching information of UCI on PUSCH (e.g. max bit capacity of encoded UCI and encoded ULSCH) according to TS 38.212 section 6.3.2.4 and 6.2.7. --- .../PHY/NR_UE_TRANSPORT/nr_transport_ue.h | 9 + openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c | 169 ++++++++++++++++++ 2 files changed, 178 insertions(+) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h index c63754b583..7252663d41 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h @@ -135,4 +135,13 @@ typedef struct { // PTRS symbol index, to be updated every PTRS symbol within a slot. uint8_t ptrs_symbol_index; } NR_UE_DLSCH_t; + +typedef struct { + uint16_t Q_dash_ACK; // number of coded HARQ-ACK symbols + uint16_t E_uci_ACK; // number of coded HARQ-ACK bits + uint16_t Q_dash_ACK_rvd; // number of coded HARQ-ACK symbols reserved + uint16_t E_uci_ACK_rvd; // number of coded HARQ-ACK bits reserved + uint32_t G_ulsch; // bit capacity of ULSCH +} rate_match_info_uci_t; + #endif diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c index 435716919a..bd51b0641c 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c @@ -472,6 +472,175 @@ static void map_symbols(const nr_phy_pxsch_params_t p, } } +// Function to lookup beta offset value from Table 9.3-1 in TS 38.213 +static double get_beta_offset_harq_ack(uint8_t beta_offset_index) +{ + static const double beta_offset_values[21] = { + 1.000, // Index 0 + 2.000, // Index 1 + 2.500, // Index 2 + 3.125, // Index 3 + 4.000, // Index 4 + 5.000, // Index 5 + 6.250, // Index 6 + 8.000, // Index 7 + 10.000, // Index 8 + 12.625, // Index 9 + 15.875, // Index 10 + 20.000, // Index 11 + 31.000, // Index 12 + 50.000, // Index 13 + 80.000, // Index 14 + 126.000, // Index 15 + 0.6, // Index 16 + 0.4, // Index 17 + 0.2, // Index 18 + 0.1, // Index 19 + 0.05, // Index 20 + }; + + if (beta_offset_index > 20) { + LOG_E(PHY, "Invalid beta_offset_index %d, using default value\n", beta_offset_index); + return 20.000; // Default value using index 11 + } + + return beta_offset_values[beta_offset_index]; +} + +static double get_alpha_scaling_value(uint8_t alpha_scaling) +{ + switch (alpha_scaling) { + case 0: + return 0.5; + case 1: + return 0.65; + case 2: + return 0.8; + case 3: + return 1.0; + default: + AssertFatal(false, "Invalid alpha_scaling value %d, valid range is 0-3", alpha_scaling); + return 1.0; + } +} + +/* + * This function gets the CRC size of UCI + */ +static int get_crc_uci(const uint16_t ouci) +{ + int L = 0; + if (ouci > 19) { + L = 11; + } else if (ouci > 11) { + L = 6; + } else { + L = 0; // no ACK/NACK + } + + return L; +} + +static uint16_t get_Qd(const uint16_t oack, double beta, double alpha, const uint32_t sumKr, const uint32_t s1, const uint32_t s2) +{ + if (oack == 0) + return 0; + + uint16_t first_term = ceil(((double)oack + get_crc_uci(oack)) * (double)beta * s1 / sumKr); + uint16_t second_term = ceil(alpha * s2); + + return (first_term < second_term) ? first_term : second_term; +} + +/* + * This function calculates the rate matching information for UCI multiplexing with PUSCH + */ +static rate_match_info_uci_t calc_rate_match_info_uci(const nfapi_nr_ue_pusch_pdu_t *pusch_pdu, + const NR_UL_UE_HARQ_t *harq_process_ul_ue, + const uint8_t nlqm, + unsigned int *G) +{ + // get beta offset + uint8_t beta_offset_index = pusch_pdu->pusch_uci.beta_offset_harq_ack; + double beta = get_beta_offset_harq_ack(beta_offset_index); + + // get alpha scaling value + uint8_t alpha_scaling = pusch_pdu->pusch_uci.alpha_scaling; + double alpha = get_alpha_scaling_value(alpha_scaling); + + // Calculate sumKr (total bits in all code blocks) + uint32_t sumKr = 0; + if (harq_process_ul_ue->C == 0) { + sumKr = 0; + } else if (harq_process_ul_ue->C == 1) { + sumKr = harq_process_ul_ue->K; + } else { + sumKr = harq_process_ul_ue->K * harq_process_ul_ue->C; + } + + // Calculate s1: total number of non-DMRS REs in allocation + uint16_t nb_rb = pusch_pdu->rb_size; + uint8_t start_symbol = pusch_pdu->start_symbol_index; + uint8_t number_of_symbols = pusch_pdu->nr_of_symbols; + uint16_t ul_dmrs_symb_pos = pusch_pdu->ul_dmrs_symb_pos; + + uint32_t s1 = 0; + for (int l = start_symbol; l < start_symbol + number_of_symbols; l++) { + if (!((ul_dmrs_symb_pos >> l) & 0x01)) { + s1 += nb_rb * NR_NB_SC_PER_RB; + } + } + + // Calculate s2: number of non-DMRS REs after first DMRS symbol + int first_dmrs_symbol = -1; + for (int l = start_symbol; l < start_symbol + number_of_symbols; l++) { + if ((ul_dmrs_symb_pos >> l) & 0x01) { + first_dmrs_symbol = l; + break; + } + } + int l0 = -1; + if (first_dmrs_symbol >= 0 && first_dmrs_symbol < start_symbol + number_of_symbols - 1) { + l0 = first_dmrs_symbol + 1; + } + uint32_t s2 = 0; + for (int l = l0; l < start_symbol + number_of_symbols; l++) { + if (!((ul_dmrs_symb_pos >> l) & 0x01)) { + s2 += nb_rb * NR_NB_SC_PER_RB; + } + } + + uint16_t oack = pusch_pdu->pusch_uci.harq_ack_bit_length; + uint16_t oack_rvd = (oack <= 2) ? 2 : 0; // get the reserved bits when oACK <= 2 according to TS 38.212 section 6.2.7, step 1 + + rate_match_info_uci_t rminfo = {0}; + + // get the number of coded HARQ-ACK symbols and bits, TS 38.212 section 6.3.2.4.1.1 + rminfo.Q_dash_ACK = get_Qd(oack, beta, alpha, sumKr, s1, s2); + rminfo.E_uci_ACK = rminfo.Q_dash_ACK * nlqm; + + if (oack_rvd > 0) { + rminfo.Q_dash_ACK_rvd = get_Qd(oack_rvd, beta, alpha, sumKr, s1, s2); + rminfo.E_uci_ACK_rvd = rminfo.Q_dash_ACK_rvd * nlqm; + } + + if (oack_rvd == 0) { + rminfo.G_ulsch = *G - rminfo.E_uci_ACK; + } else { + rminfo.G_ulsch = *G; + } + + *G = rminfo.G_ulsch; + LOG_D(PHY, "[UCI_RATE_MATCH] sumKr=%u, s1=%u, s2=%u, Final G_ulsch (output G): %u\n", sumKr, s1, s2, *G); + LOG_D(PHY, + "[UCI_RATE_MATCH] rate matching info returned: E_uci_ACK=%u, E_uci_ACK_rvd=%u, G_ulsch=%u\n", + rminfo.E_uci_ACK, + rminfo.E_uci_ACK_rvd, + rminfo.G_ulsch); + + return rminfo; +} + void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, const uint32_t frame, const uint8_t slot, From ceda9c11412a465c47b4dc092086eca4dcac0555 Mon Sep 17 00:00:00 2001 From: alexjiao Date: Fri, 13 Jun 2025 19:58:41 +0800 Subject: [PATCH 810/964] Add functions to implement UCI and data multiplexing on PUSCH Data and control multiplexing procedure is defined in 38.212 section 6.2.7. Step 3 (CSI1 and CSI2 mapping) is not implemented, only HARQ-ACK. PUSCH frequency hopping is not supported. --- .../NR_UE_TRANSPORT/nr_transport_proto_ue.h | 13 +- openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c | 371 ++++++++++++++++++ 2 files changed, 382 insertions(+), 2 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h index 44a3611bf0..8a08b97121 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h @@ -41,6 +41,15 @@ #define NR_PUSCH_x 2 // UCI placeholder bit TS 38.212 V15.4.0 subclause 5.3.3.1 #define NR_PUSCH_y 3 // UCI placeholder bit +typedef enum { + BIT_TYPE_ULSCH = 0, // Default: UL-SCH data + BIT_TYPE_ACK = 1, // HARQ-ACK bit + BIT_TYPE_ACK_RESERVED = 2, // Reserved for HARQ-ACK (punctured) + BIT_TYPE_ACK_ULSCH = 3, + BIT_TYPE_CSI1 = 4, // CSI Part 1 bit + BIT_TYPE_CSI2 = 5 // CSI Part 2 bit +} uci_on_pusch_bit_type_t; + // Specifies the data that should be copied to the scope during PDSCH RX typedef struct pdsch_scope_req_s { bool copy_chanest_to_scope; @@ -121,8 +130,8 @@ void nr_pusch_codeword_scrambling(uint8_t *in, uint32_t Nid, uint32_t n_RNTI, bool uci_on_pusch, - uint32_t* out); - + const uci_on_pusch_bit_type_t *template, + uint32_t *out); /** \brief Alternative entry point to UE uplink shared channels procedures. It handles all the HARQ processes in only one call. diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c index bd51b0641c..6091746ef2 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c @@ -49,6 +49,12 @@ #include "PHY/NR_REFSIG/ul_ref_seq_nr.h" #include #include "PHY/log_tools.h" +#include "PHY/NR_UE_TRANSPORT/pucch_nr.h" +#include + +#define MAX_RE_PER_SYMBOL_IN_ALLOC (275 * 12) +#define MAX_NLQM (4 * 8) +#define MAX_UCI_CODED_BITS 1024 //#define DEBUG_PUSCH_MAPPING //#define DEBUG_MAC_PDU @@ -641,6 +647,371 @@ static rate_match_info_uci_t calc_rate_match_info_uci(const nfapi_nr_ue_pusch_pd return rminfo; } +static int initialize_mapping_resources(const nfapi_nr_ue_pusch_pdu_t *pusch_pdu, + uint32_t *m_ulsch_initial, + uint32_t *m_ulsch_current, + uint32_t *m_uci_current, + bool *is_dmrs_symbol_flags, + uint8_t *dmrs_symbol_set_relative, + uint8_t *num_dmrs_symbols_in_set_relative) +{ + if (!pusch_pdu || !m_ulsch_initial || !m_ulsch_current || !m_uci_current || !is_dmrs_symbol_flags || !dmrs_symbol_set_relative + || !num_dmrs_symbols_in_set_relative) + return -1; + + uint8_t n_pusch_sym_all = pusch_pdu->nr_of_symbols; + uint16_t ul_dmrs_symb_pos = pusch_pdu->ul_dmrs_symb_pos; + uint8_t dmrs_type = pusch_pdu->dmrs_config_type; + uint8_t cdm_grps_no_data = pusch_pdu->num_dmrs_cdm_grps_no_data; + uint32_t res_per_symbol_non_dmrs = pusch_pdu->rb_size * 12; + + *num_dmrs_symbols_in_set_relative = 0; + + // Initialize resources per symbol for ULSCH and UCI + for (uint8_t i = 0; i < n_pusch_sym_all; i++) { + uint8_t absolute_symbol_idx = pusch_pdu->start_symbol_index + i; + + if ((ul_dmrs_symb_pos >> absolute_symbol_idx) & 0x01) { + is_dmrs_symbol_flags[i] = true; + if (*num_dmrs_symbols_in_set_relative < 14) { + dmrs_symbol_set_relative[(*num_dmrs_symbols_in_set_relative)++] = i; + } + + // Calculate available data REs on DMRS symbols based on DMRS configuration + uint32_t data_re_on_dmrs_sym_per_prb = 0; + + if (dmrs_type == 0) { // Type 1 + if (cdm_grps_no_data == 1) { + data_re_on_dmrs_sym_per_prb = 6; + } else { + data_re_on_dmrs_sym_per_prb = 0; + } + } else { // Type 2 + if (cdm_grps_no_data == 1) { + data_re_on_dmrs_sym_per_prb = 4; + } else if (cdm_grps_no_data == 2) { + data_re_on_dmrs_sym_per_prb = 2; + } else { + data_re_on_dmrs_sym_per_prb = 0; + } + } + + m_ulsch_initial[i] = pusch_pdu->rb_size * data_re_on_dmrs_sym_per_prb; + m_ulsch_current[i] = m_ulsch_initial[i]; + m_uci_current[i] = 0; // UCI is not mapped on DMRS symbols + + } else { // Not a DMRS symbol + is_dmrs_symbol_flags[i] = false; + + m_ulsch_initial[i] = res_per_symbol_non_dmrs; + m_ulsch_current[i] = res_per_symbol_non_dmrs; + m_uci_current[i] = res_per_symbol_non_dmrs; + } + } + + return 0; +} + +static uint8_t find_first_uci_symbol(uint8_t n_pusch_sym_all, + const bool *is_dmrs_symbol_flags, + uint8_t *dmrs_symbol_set_relative, + uint32_t num_dmrs_symbols_in_set_relative) +{ + uint8_t l1_c = 0; + + // Find first non-DMRS symbol + for (uint8_t i = 0; i < n_pusch_sym_all; i++) { + if (!is_dmrs_symbol_flags[i]) { + l1_c = i; + break; + } + } + + // If there are DMRS symbols, try to find a symbol after the first DMRS + if (num_dmrs_symbols_in_set_relative > 0) { + uint8_t first_dmrs_idx = dmrs_symbol_set_relative[0]; + if (l1_c <= first_dmrs_idx) { + for (uint8_t i = first_dmrs_idx + 1; i < n_pusch_sym_all; i++) { + if (!is_dmrs_symbol_flags[i]) { + l1_c = i; + break; + } + } + } + } + + return l1_c; +} + +/* + * This function builds the initial template by reserving positions for HARQ-ACK. + */ +static void build_template_reserve_ack(uci_on_pusch_bit_type_t *template, + const nfapi_nr_ue_pusch_pdu_t *pusch_pdu, + uint32_t G_ack_rvd, + uint8_t l1_c, + const uint32_t *m_uci_current, + const uint32_t *m_ulsch_initial, + uint32_t positions_by_sym[][MAX_UCI_CODED_BITS], + uint32_t *count_by_sym) +{ + const uint8_t n_symbols = pusch_pdu->nr_of_symbols; + const uint32_t nlqm = pusch_pdu->qam_mod_order * pusch_pdu->nrOfLayers; + + memset(count_by_sym, 0, n_symbols * sizeof(uint32_t)); + + uint32_t symbol_start_bit_idx[14] = {0}; + for (uint8_t s = 1; s < n_symbols; s++) { + symbol_start_bit_idx[s] = symbol_start_bit_idx[s - 1] + (m_ulsch_initial[s - 1] * nlqm); + } + + // Reserve Positions using RE-level D-Factor Distribution + uint32_t total_reserved = 0; + + for (uint8_t sym = l1_c; sym < n_symbols && total_reserved < G_ack_rvd; sym++) { + const uint32_t uci_re_on_sym = m_uci_current[sym]; + + if (uci_re_on_sym > 0) { + const uint32_t remaining_to_reserve = G_ack_rvd - total_reserved; + uint32_t d_factor_re; + const uint32_t num_re_to_select = ceil((double)remaining_to_reserve / nlqm); + if (num_re_to_select >= uci_re_on_sym) { + d_factor_re = 1; + } else { + d_factor_re = floor((double)uci_re_on_sym / num_re_to_select); + if (d_factor_re == 0) { + d_factor_re = 1; + } + } + + for (uint32_t re_offset = 0; re_offset < uci_re_on_sym && total_reserved < G_ack_rvd; re_offset += d_factor_re) { + for (uint32_t bit_in_re = 0; bit_in_re < nlqm; bit_in_re++) { + if (total_reserved >= G_ack_rvd) { + break; + } + + uint32_t bit_offset_in_sym = (re_offset * nlqm) + bit_in_re; + uint32_t cw_idx = symbol_start_bit_idx[sym] + bit_offset_in_sym; + template[cw_idx] = BIT_TYPE_ACK_RESERVED; + positions_by_sym[sym][count_by_sym[sym]] = cw_idx; + count_by_sym[sym]++; + + total_reserved++; + } + } + } + } +} + +/* + * This function maps the HARQ-ACK bits when O_ACK > 2 + */ +static void map_non_overlapped_ack(uci_on_pusch_bit_type_t *template, + const nfapi_nr_ue_pusch_pdu_t *pusch_pdu, + uint16_t G_ack, + uint8_t l1_c, + const uint32_t *m_uci_current, + const uint32_t *m_ulsch_initial) +{ + const uint8_t n_symbols = pusch_pdu->nr_of_symbols; + const uint32_t nlqm = pusch_pdu->qam_mod_order * pusch_pdu->nrOfLayers; + + uint32_t symbol_start_bit_idx[14] = {0}; + for (uint8_t s = 1; s < n_symbols; s++) { + symbol_start_bit_idx[s] = symbol_start_bit_idx[s - 1] + (m_ulsch_initial[s - 1] * nlqm); + } + + uint32_t total_placed = 0; + for (uint8_t sym = l1_c; sym < n_symbols && total_placed < G_ack; sym++) { + const uint32_t uci_re_on_sym = m_uci_current[sym]; + + if (uci_re_on_sym > 0) { + const uint32_t remaining_to_place = G_ack - total_placed; + uint32_t d_factor_re; + const uint32_t num_re_to_select = ceil((double)remaining_to_place / nlqm); + + if (num_re_to_select >= uci_re_on_sym) { + d_factor_re = 1; + } else { + d_factor_re = floor((double)uci_re_on_sym / num_re_to_select); + if (d_factor_re == 0) { + d_factor_re = 1; + } + } + + for (uint32_t re_offset = 0; re_offset < uci_re_on_sym && total_placed < G_ack; re_offset += d_factor_re) { + for (uint32_t bit_in_re = 0; bit_in_re < nlqm; bit_in_re++) { + if (total_placed >= G_ack) { + break; + } + + uint32_t bit_offset_in_sym = (re_offset * nlqm) + bit_in_re; + uint32_t cw_idx = symbol_start_bit_idx[sym] + bit_offset_in_sym; + template[cw_idx] = BIT_TYPE_ACK; + + total_placed++; + } + } + } + } +} + +/* + * This function maps the HARQ-ACK bits when O_ACK <= 2 + */ +static void map_overlapped_ack(uci_on_pusch_bit_type_t *template, + uint16_t G_ack, + uint8_t l1_c, + uint8_t n_symbols, + uint32_t positions_by_sym[][MAX_UCI_CODED_BITS], + const uint32_t *count_by_sym) +{ + uint32_t ack_bits_marked = 0; + + for (uint8_t sym_iter = l1_c; sym_iter < n_symbols && ack_bits_marked < G_ack; sym_iter++) { + const uint32_t num_reserved_bits_on_sym = count_by_sym[sym_iter]; + + if (num_reserved_bits_on_sym > 0) { + const uint32_t num_ack_remaining = G_ack - ack_bits_marked; + uint32_t d_factor; + + // This d-factor is calculated for stepping through the list of *reserved bits*. + if (num_ack_remaining >= num_reserved_bits_on_sym) { + d_factor = 1; + } else { + d_factor = floor((double)num_reserved_bits_on_sym / num_ack_remaining); + if (d_factor == 0) { + d_factor = 1; + } + } + + const uint32_t *reserved_indices_on_this_sym = positions_by_sym[sym_iter]; + + for (uint32_t i = 0; i < num_reserved_bits_on_sym && ack_bits_marked < G_ack; i += d_factor) { + uint32_t pos_to_mark = reserved_indices_on_this_sym[i]; + template[pos_to_mark] = BIT_TYPE_ACK_ULSCH; + + ack_bits_marked++; + } + } + } +} + +/* + * Applies the template to build the final codeword + */ +static void apply_template_to_codeword(uint8_t *codeword, + const uci_on_pusch_bit_type_t *template, + uint32_t codeword_len, + const uint8_t *ulsch_bits, + const uint64_t *cack, + uint16_t G_ack, + uint32_t G_ulsch) +{ + uint32_t ulsch_idx = 0; + uint32_t ack_idx = 0; + + for (uint32_t i = 0; i < codeword_len; i++) { + switch (template[i]) { + case BIT_TYPE_ACK: + if (G_ack > 0 && ack_idx < G_ack) { + uint32_t word_idx = ack_idx / 64; + uint32_t bit_in_word_idx = ack_idx % 64; + codeword[i] = (cack[word_idx] >> bit_in_word_idx) & 1; + ack_idx++; + } + break; + + case BIT_TYPE_ACK_ULSCH: + if (G_ack > 0 && ack_idx < G_ack) { + codeword[i] = ((const uint8_t *)cack)[ack_idx++]; + if (G_ulsch > 0 && ulsch_idx < G_ulsch) { + ulsch_idx++; + } + } + break; + + case BIT_TYPE_ACK_RESERVED: + case BIT_TYPE_ULSCH: + default: + if (G_ulsch > 0 && ulsch_idx < G_ulsch) { + uint32_t byte_idx = ulsch_idx / 8; + uint32_t bit_in_byte_idx = ulsch_idx % 8; + codeword[i] = (ulsch_bits[byte_idx] >> bit_in_byte_idx) & 1; + ulsch_idx++; + } + break; + } + } +} + +/* + * This function implements the UCI multiplexing on PUSCH according to TS 38.212 section 6.2.7. + */ +static uci_on_pusch_bit_type_t *nr_data_control_mapping(const nfapi_nr_ue_pusch_pdu_t *pusch_pdu, + uci_on_pusch_bit_type_t *template, + unsigned int G_ulsch, + uint16_t G_ack, + uint32_t G_ack_rvd, + uint8_t *codeword, + uint32_t codeword_len, + const uint8_t *ulsch_bits, + const uint64_t *cack) +{ + if (!pusch_pdu || !codeword || codeword_len == 0 || !template) + return NULL; + const uint8_t n_symbols = pusch_pdu->nr_of_symbols; + if (n_symbols == 0 || n_symbols > 14) + return NULL; + + uint32_t m_ulsch_initial[14] = {0}; + uint32_t m_ulsch_current[14] = {0}; + uint32_t m_uci_current[14] = {0}; // This holds RE counts, not bit counts + bool is_dmrs_symbol_flags[14] = {0}; + uint8_t dmrs_symbol_set_relative[14] = {0}; + uint8_t num_dmrs_symbols_in_set_relative = 0; + + if (initialize_mapping_resources(pusch_pdu, + m_ulsch_initial, + m_ulsch_current, + m_uci_current, + is_dmrs_symbol_flags, + dmrs_symbol_set_relative, + &num_dmrs_symbols_in_set_relative) + != 0) { + LOG_E(PHY, "Failed to initialize mapping resources\n"); + return NULL; + } + + uint8_t l1_c = find_first_uci_symbol(n_symbols, is_dmrs_symbol_flags, dmrs_symbol_set_relative, num_dmrs_symbols_in_set_relative); + + memset(template, 0, codeword_len * sizeof(uci_on_pusch_bit_type_t)); + + uint32_t positions_by_sym[14][MAX_UCI_CODED_BITS] = {0}; + uint32_t count_by_sym[14] = {0}; + + if (G_ack_rvd > 0) { + build_template_reserve_ack(template, + pusch_pdu, + G_ack_rvd, + l1_c, + m_uci_current, + m_ulsch_initial, + positions_by_sym, + count_by_sym); + } else if (G_ack > 0) { + map_non_overlapped_ack(template, pusch_pdu, G_ack, l1_c, m_uci_current, m_ulsch_initial); + } + + if (G_ack > 0 && G_ack_rvd > 0) { + map_overlapped_ack(template, G_ack, l1_c, n_symbols, positions_by_sym, count_by_sym); + } + + apply_template_to_codeword(codeword, template, codeword_len, ulsch_bits, cack, G_ack, G_ulsch); + + return template; +} + void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, const uint32_t frame, const uint8_t slot, From 5f3a19cb7d83dd7c83c3a801ae4952a1a8a0d7e0 Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Fri, 15 Aug 2025 21:20:53 -0400 Subject: [PATCH 811/964] Separate segmentation from ULSCH encoding function Segmentation have to be called before UCI mapping to get number of segments and sumKr values. --- .../NR_UE_TRANSPORT/nr_transport_proto_ue.h | 7 + .../PHY/NR_UE_TRANSPORT/nr_transport_ue.h | 2 + .../PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c | 153 +++++++++--------- openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c | 4 +- openair1/SIMULATION/NR_PHY/ulschsim.c | 1 + 5 files changed, 92 insertions(+), 75 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h index 8a08b97121..c257726501 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h @@ -95,6 +95,13 @@ void nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, int nb_dlsch, uint8_t *DLSCH_ids); +int nr_ulsch_pre_encoding(PHY_VARS_NR_UE *ue, + const NR_UE_ULSCH_t *ulsch, + const uint32_t frame, + const uint8_t slot, + const unsigned int *G, + const int nb_ulsch, + const uint8_t *ULSCH_ids); /** \brief This is the alternative top-level entry point for ULSCH encoding in UE. It handles all the HARQ processes in only one call. The routine first computes the segmentation information, followed by LDPC encoding algorithm of the diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h index 7252663d41..26f41b1fd3 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h @@ -55,6 +55,8 @@ typedef struct { uint32_t C; /// Number of bits in code segments uint32_t K; + /// + uint32_t Kb; /// Number of "Filler" bits uint32_t F; /// Number of soft channel bits diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c index b044d06305..d68ae6e9ae 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c @@ -34,56 +34,27 @@ #include "common/utils/LOG/vcd_signal_dumper.h" #include "PHY/log_tools.h" -int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, - NR_UE_ULSCH_t *ulsch, - const uint32_t frame, - const uint8_t slot, - unsigned int *G, - int nb_ulsch, - uint8_t *ULSCH_ids, - uint16_t number_dmrs_symbols) +int nr_ulsch_pre_encoding(PHY_VARS_NR_UE *ue, + const NR_UE_ULSCH_t *ulsch, + const uint32_t frame, + const uint8_t slot, + const unsigned int *G, + const int nb_ulsch, + const uint8_t *ULSCH_ids) { - start_meas_nr_ue_phy(ue, ULSCH_ENCODING_STATS); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_UE_ULSCH_ENCODING, VCD_FUNCTION_IN); - - nrLDPC_TB_encoding_parameters_t TBs[nb_ulsch]; - memset(TBs, 0, sizeof(TBs)); - nrLDPC_slot_encoding_parameters_t slot_parameters = { - .frame = frame, - .slot = slot, - .nb_TBs = nb_ulsch, - .threadPool = &get_nrUE_params()->Tpool, - .tinput = NULL, - .tprep = NULL, - .tparity = NULL, - .toutput = NULL, - .TBs = TBs - }; - - int max_num_segments = 0; - - for (uint8_t pusch_id = 0; pusch_id < nb_ulsch; pusch_id++) { - uint8_t ULSCH_id = ULSCH_ids[pusch_id]; - uint8_t harq_pid = ulsch[ULSCH_id].pusch_pdu.pusch_data.harq_process_id; - - nrLDPC_TB_encoding_parameters_t *TB_parameters = &TBs[pusch_id]; - /* Neither harq_pid nor ULSCH_id are unique in the instance - * but their combination is. - * Since ULSCH_id < 2 - * then 2 * harq_pid + ULSCH_id is unique. - */ - TB_parameters->harq_unique_pid = 2 * harq_pid + ULSCH_id; + for (uint_fast8_t pusch_id = 0; pusch_id < nb_ulsch; pusch_id++) { + const uint8_t ULSCH_id = ULSCH_ids[pusch_id]; + const uint8_t harq_pid = ulsch[ULSCH_id].pusch_pdu.pusch_data.harq_process_id; /////////////////////////parameters and variables initialization///////////////////////// - unsigned int crc = 1; NR_UL_UE_HARQ_t *harq_process = &ue->ul_harq_processes[harq_pid]; const nfapi_nr_ue_pusch_pdu_t *pusch_pdu = &ulsch->pusch_pdu; - uint16_t nb_rb = pusch_pdu->rb_size; - uint32_t A = pusch_pdu->pusch_data.tb_size << 3; - uint8_t Qm = pusch_pdu->qam_mod_order; + const uint16_t nb_rb = pusch_pdu->rb_size; + const uint32_t A = pusch_pdu->pusch_data.tb_size << 3; + const uint8_t Qm = pusch_pdu->qam_mod_order; // target_code_rate is in 0.1 units - float Coderate = (float)pusch_pdu->target_code_rate / 10240.0f; + const float Coderate = (float)pusch_pdu->target_code_rate / 10240.0f; LOG_D(NR_PHY, "ulsch coding nb_rb %d, Nl = %d\n", nb_rb, pusch_pdu->nrOfLayers); LOG_D(NR_PHY, "ulsch coding A %d G %d mod_order %d Coderate %f\n", A, G[pusch_id], Qm, Coderate); @@ -91,11 +62,11 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, ///////////////////////// a---->| add CRC |---->b ///////////////////////// - int max_payload_bytes = MAX_NUM_NR_ULSCH_SEGMENTS_PER_LAYER * pusch_pdu->nrOfLayers * 1056; + const int max_payload_bytes = MAX_NUM_NR_ULSCH_SEGMENTS_PER_LAYER * pusch_pdu->nrOfLayers * 1056; int B; if (A > NR_MAX_PDSCH_TBS) { // Add 24-bit crc (polynomial A) to payload - crc = crc24a(harq_process->payload_AB, A) >> 8; + const unsigned int crc = crc24a(harq_process->payload_AB, A) >> 8; harq_process->payload_AB[A >> 3] = ((uint8_t *)&crc)[2]; harq_process->payload_AB[1 + (A >> 3)] = ((uint8_t *)&crc)[1]; harq_process->payload_AB[2 + (A >> 3)] = ((uint8_t *)&crc)[0]; @@ -103,7 +74,7 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, AssertFatal((A / 8) + 4 <= max_payload_bytes, "A %d is too big (A/8+4 = %d > %d)\n", A, (A / 8) + 4, max_payload_bytes); } else { // Add 16-bit crc (polynomial A) to payload - crc = crc16(harq_process->payload_AB, A) >> 16; + const unsigned int crc = crc16(harq_process->payload_AB, A) >> 16; harq_process->payload_AB[A >> 3] = ((uint8_t *)&crc)[1]; harq_process->payload_AB[1 + (A >> 3)] = ((uint8_t *)&crc)[0]; B = A + 16; @@ -151,7 +122,7 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, T_INT((int)ulsch->pusch_pdu.transform_precoding), // transformPrecoder_enabled = 0, transformPrecoder_disabled = 1 T_INT((int)ulsch->pusch_pdu.dmrs_config_type), // dmrs_resource_map_config: pusch_dmrs_type1 = 0, pusch_dmrs_type2 = 1 T_INT((int)ulsch->pusch_pdu.ul_dmrs_symb_pos), // used to derive the DMRS symbol positions - T_INT((int)number_dmrs_symbols), + T_INT((int)get_num_dmrs(ulsch->pusch_pdu.ul_dmrs_symb_pos)), // dmrs_start_ofdm_symbol // dmrs_duration_num_ofdm_symbols // dmrs_num_add_positions @@ -168,36 +139,55 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_SEGMENTATION, VCD_FUNCTION_IN); start_meas_nr_ue_phy(ue, ULSCH_SEGMENTATION_STATS); - TB_parameters->Kb = nr_segmentation(harq_process->payload_AB, - harq_process->c, - B, - &harq_process->C, - &harq_process->K, - &harq_process->Z, - &harq_process->F, - harq_process->BG); - TB_parameters->C = harq_process->C; - TB_parameters->K = harq_process->K; - TB_parameters->Z = harq_process->Z; - TB_parameters->F = harq_process->F; - TB_parameters->BG = harq_process->BG; - if (TB_parameters->C > MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER * pusch_pdu->nrOfLayers) { - LOG_E(PHY, "nr_segmentation.c: too many segments %d, B %d\n", TB_parameters->C, B); + harq_process->Kb = nr_segmentation(harq_process->payload_AB, + harq_process->c, + B, + &harq_process->C, + &harq_process->K, + &harq_process->Z, + &harq_process->F, + harq_process->BG); + if (harq_process->C > MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER * pusch_pdu->nrOfLayers) { + LOG_E(PHY, "nr_segmentation.c: too many segments %d, B %d\n", harq_process->C, B); return (-1); } stop_meas_nr_ue_phy(ue, ULSCH_SEGMENTATION_STATS); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_SEGMENTATION, VCD_FUNCTION_OUT); - max_num_segments = max(max_num_segments, TB_parameters->C); - - TB_parameters->nb_rb = nb_rb; - TB_parameters->Qm = Qm; - TB_parameters->mcs = pusch_pdu->mcs_index; - TB_parameters->nb_layers = pusch_pdu->nrOfLayers; - TB_parameters->rv_index = pusch_pdu->pusch_data.rv_index; - TB_parameters->G = G[pusch_id]; - TB_parameters->tbslbrm = pusch_pdu->tbslbrm; - TB_parameters->A = A; } // pusch_id + return 0; +} + +int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, + NR_UE_ULSCH_t *ulsch, + const uint32_t frame, + const uint8_t slot, + unsigned int *G, + int nb_ulsch, + uint8_t *ULSCH_ids, + uint16_t number_dmrs_symbols) +{ + start_meas_nr_ue_phy(ue, ULSCH_ENCODING_STATS); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_UE_ULSCH_ENCODING, VCD_FUNCTION_IN); + + nrLDPC_TB_encoding_parameters_t TBs[nb_ulsch]; + memset(TBs, 0, sizeof(TBs)); + nrLDPC_slot_encoding_parameters_t slot_parameters = {.frame = frame, + .slot = slot, + .nb_TBs = nb_ulsch, + .threadPool = &get_nrUE_params()->Tpool, + .tinput = NULL, + .tprep = NULL, + .tparity = NULL, + .toutput = NULL, + .TBs = TBs}; + + int max_num_segments = 0; + for (uint_fast8_t pusch_id = 0; pusch_id < nb_ulsch; pusch_id++) { + const uint8_t ULSCH_id = ULSCH_ids[pusch_id]; + const uint8_t harq_pid = ulsch[ULSCH_id].pusch_pdu.pusch_data.harq_process_id; + NR_UL_UE_HARQ_t *harq_process = &ue->ul_harq_processes[harq_pid]; + max_num_segments = max(max_num_segments, harq_process->C); + } nrLDPC_segment_encoding_parameters_t segments[nb_ulsch][max_num_segments]; memset(segments, 0, sizeof(segments)); @@ -208,10 +198,25 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, nrLDPC_TB_encoding_parameters_t *TB_parameters = &TBs[pusch_id]; NR_UL_UE_HARQ_t *harq_process = &ue->ul_harq_processes[harq_pid]; + const nfapi_nr_ue_pusch_pdu_t *pusch_pdu = &ulsch[ULSCH_id].pusch_pdu; + const uint16_t nb_rb = pusch_pdu->rb_size; + TB_parameters->harq_unique_pid = 2 * harq_pid + ULSCH_id; + TB_parameters->C = harq_process->C; + TB_parameters->K = harq_process->K; + TB_parameters->Z = harq_process->Z; + TB_parameters->F = harq_process->F; + TB_parameters->BG = harq_process->BG; + TB_parameters->Kb = harq_process->Kb; + TB_parameters->nb_rb = nb_rb; + TB_parameters->Qm = pusch_pdu->qam_mod_order; + TB_parameters->mcs = pusch_pdu->mcs_index; + TB_parameters->nb_layers = pusch_pdu->nrOfLayers; + TB_parameters->rv_index = pusch_pdu->pusch_data.rv_index; + TB_parameters->G = G[pusch_id]; + TB_parameters->tbslbrm = pusch_pdu->tbslbrm; + TB_parameters->A = pusch_pdu->pusch_data.tb_size / 8; TB_parameters->segments = segments[pusch_id]; - const nfapi_nr_ue_pusch_pdu_t *pusch_pdu = &ulsch->pusch_pdu; - uint16_t nb_rb = pusch_pdu->rb_size; memset(harq_process->f, 0, 14 * nb_rb * 12 * 16); TB_parameters->output = harq_process->f; diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c index 6091746ef2..561d357363 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c @@ -1092,7 +1092,9 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, /////////////////////////ULSCH coding///////////////////////// - if (nr_ulsch_encoding(UE, &phy_data->ulsch, frame, slot, G, 1, ULSCH_ids, number_dmrs_symbols) == -1) { + int enc_ret = nr_ulsch_pre_encoding(UE, &phy_data->ulsch, frame, slot, G, 1, ULSCH_ids); + enc_ret += nr_ulsch_encoding(UE, &phy_data->ulsch, frame, slot, G, 1, ULSCH_ids, number_dmrs_symbols); + if (enc_ret != 0) { stop_meas_nr_ue_phy(UE, PUSCH_PROC_STATS); return; } diff --git a/openair1/SIMULATION/NR_PHY/ulschsim.c b/openair1/SIMULATION/NR_PHY/ulschsim.c index 058a59feb5..64c04b900e 100644 --- a/openair1/SIMULATION/NR_PHY/ulschsim.c +++ b/openair1/SIMULATION/NR_PHY/ulschsim.c @@ -513,6 +513,7 @@ int main(int argc, char **argv) if (input_fd == NULL) { uint8_t ULSCH_ids[] = {0}; + nr_ulsch_pre_encoding(UE, ulsch_ue, 0, 0, &G, 1, ULSCH_ids); nr_ulsch_encoding(UE, ulsch_ue, 0, 0, &G, 1, ULSCH_ids, 0); } From b43dee14995c274d3f617db0039073c464d45445 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Fri, 26 Sep 2025 14:58:47 +0200 Subject: [PATCH 812/964] CI: adjust Amarisoft UE RX gain Lower the RX gain used by the Amarisoft UE in CI tests to prevent DL signal saturation. This resolves an issue with low DL throughput observed in CI. RX/TX signal levels on the Amarisoft UE can be checked with "t spl" command in lteue; MAX values should not approach 0. --- ci-scripts/as_ue/config.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci-scripts/as_ue/config.cfg b/ci-scripts/as_ue/config.cfg index 1c71b752c1..42d8eba369 100644 --- a/ci-scripts/as_ue/config.cfg +++ b/ci-scripts/as_ue/config.cfg @@ -44,4 +44,4 @@ rf_driver: { #endif tx_gain: 75.0, /* TX gain (in dB) */ -rx_gain: 55.0, /* RX gain (in dB) */ +rx_gain: 52.0, /* RX gain (in dB) */ From 03d4ce2e1e96fee1d1b2ccec8e4b1a8b669af2d1 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Fri, 26 Sep 2025 15:07:16 +0200 Subject: [PATCH 813/964] CI: Attach multiple UEs at once in AW2S test --- .../xml_files/container_sa_aw2s_asue.xml | 88 +------------------ 1 file changed, 2 insertions(+), 86 deletions(-) diff --git a/ci-scripts/xml_files/container_sa_aw2s_asue.xml b/ci-scripts/xml_files/container_sa_aw2s_asue.xml index 2367dc7e5c..e5d32c181f 100644 --- a/ci-scripts/xml_files/container_sa_aw2s_asue.xml +++ b/ci-scripts/xml_files/container_sa_aw2s_asue.xml @@ -36,18 +36,6 @@ 102002 302002 102003 - 102004 - 102005 - 102006 - 102007 - 102008 - 102009 - 102010 - 102011 - 102012 - 102013 - 102014 - 102015 100100 100010 100020 @@ -118,80 +106,8 @@ Attach_UE - Attach UE 3 - amarisoft_ue_3 - - - - Attach_UE - Attach UE 4 - amarisoft_ue_4 - - - - Attach_UE - Attach (RedCap) UE 5 - amarisoft_ue_5 - - - - Attach_UE - Attach (RedCap) UE 6 - amarisoft_ue_6 - - - - Attach_UE - Attach UE 7 - amarisoft_ue_7 - - - - Attach_UE - Attach UE 8 - amarisoft_ue_8 - - - - Attach_UE - Attach UE 9 - amarisoft_ue_9 - - - - Attach_UE - Attach (RedCap) UE 10 - amarisoft_ue_10 - - - - Attach_UE - Attach (RedCap) UE 11 - amarisoft_ue_11 - - - - Attach_UE - Attach (RedCap) UE 12 - amarisoft_ue_12 - - - - Attach_UE - Attach UE 13 - amarisoft_ue_13 - - - - Attach_UE - Attach UE 14 - amarisoft_ue_14 - - - - Attach_UE - Attach (RedCap) UE 15 - amarisoft_ue_15 + Attach UE 3 - 15 + 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 From 124debc2c77cb3ad74d2630e4ed76abb59daba81 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 19 Dec 2024 23:51:37 +0100 Subject: [PATCH 814/964] Fix warnings in rftest executable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit warning: ‘genericPowerPerAntena’ defined but not used [-Wunused-function] warning: ‘graph.text’ is used uninitialized [-Wuninitialized] warning: ignoring return value of ‘read’ declared with attribute ‘warn_unused_result’ [-Wunused-result] --- openair1/PHY/TOOLS/calibration_scope.c | 14 ++++++++++---- openair1/PHY/TOOLS/calibration_test.c | 9 +++++++-- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/openair1/PHY/TOOLS/calibration_scope.c b/openair1/PHY/TOOLS/calibration_scope.c index 6d7723d6d4..c7a305ab27 100644 --- a/openair1/PHY/TOOLS/calibration_scope.c +++ b/openair1/PHY/TOOLS/calibration_scope.c @@ -99,8 +99,9 @@ static void commonGraph(OAIgraph_t *graph, int type, FL_Coord x, FL_Coord y, FL_ } static OAIgraph_t calibrationCommonGraph( void (*funct) (OAIgraph_t *graph, calibData_t *context), - int type, FL_Coord x, FL_Coord y, FL_Coord w, FL_Coord h, const char *label, FL_COLOR pointColor) { - OAIgraph_t graph; + int type, FL_Coord x, FL_Coord y, FL_Coord w, FL_Coord h, const char *label, FL_COLOR pointColor) +{ + OAIgraph_t graph = {0}; commonGraph(&graph, type, x, y, w, h, label, pointColor); graph.funct=funct; return graph; @@ -236,7 +237,9 @@ static void genericWaterFall (OAIgraph_t *graph, scopeSample_t *values, const in graph->iteration++; } -static void genericPowerPerAntena(OAIgraph_t *graph, const int nb_ant, const scopeSample_t **data, const int len) { +__attribute__((unused)) +static void genericPowerPerAntena(OAIgraph_t *graph, const int nb_ant, const scopeSample_t **data, const int len) +{ float *values, *time; oai_xygraph_getbuff(graph, &time, &values, len, 0); @@ -263,7 +266,10 @@ static void gNBfreqWaterFall (OAIgraph_t *graph, calibData_t *context) { 0, 0, "X axis:one frame in time"); } -static void timeResponse (OAIgraph_t *graph, calibData_t *context) { + +__attribute__((unused)) +static void timeResponse (OAIgraph_t *graph, calibData_t *context) +{ #if 0 const int len=2*phy_vars_gnb->frame_parms.ofdm_symbol_size; float *values, *time; diff --git a/openair1/PHY/TOOLS/calibration_test.c b/openair1/PHY/TOOLS/calibration_test.c index 1d8e64ee90..4d88ab542a 100644 --- a/openair1/PHY/TOOLS/calibration_test.c +++ b/openair1/PHY/TOOLS/calibration_test.c @@ -314,8 +314,13 @@ int main(int argc, char **argv) { rfdevice.trx_start_func(&rfdevice); while(!oai_exit) { - for (int i=0; i Date: Thu, 19 Dec 2024 22:45:50 +0100 Subject: [PATCH 815/964] CMakeLists.txt: comment out sims that don't compile --- CMakeLists.txt | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d993a8d09a..9aeb1851d7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1930,14 +1930,14 @@ target_link_libraries(nr-uesoftmodem PRIVATE ##################################### #special case for dlim TM4, which uses its own version of phy_scope code -add_executable(dlsim_tm4 - ${OPENAIR1_DIR}/SIMULATION/LTE_PHY/dlsim_tm4.c - ${OPENAIR1_DIR}/PHY/TOOLS/lte_phy_scope_tm4.c - ) -target_link_libraries (dlsim_tm4 - -Wl,--start-group SIMU UTIL SCHED_LIB SCHED_RU_LIB PHY ITTI -Wl,--end-group - pthread m rt CONFIG_LIB ${T_LIB} - ) +#add_executable(dlsim_tm4 +# ${OPENAIR1_DIR}/SIMULATION/LTE_PHY/dlsim_tm4.c +# ${OPENAIR1_DIR}/PHY/TOOLS/lte_phy_scope_tm4.c +# ) +#target_link_libraries (dlsim_tm4 +# -Wl,--start-group SIMU UTIL SCHED_LIB SCHED_RU_LIB PHY ITTI -Wl,--end-group +# pthread m rt CONFIG_LIB ${T_LIB} +# ) add_executable(rftest ${OPENAIR_DIR}/openair1/PHY/TOOLS/calibration_test.c @@ -2062,7 +2062,9 @@ target_link_libraries(nr_ulsim PRIVATE ) target_link_libraries(nr_ulsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) -foreach(myExe dlsim dlsim_tm7 ulsim pbchsim scansim mbmssim pdcchsim pucchsim prachsim syncsim) +# these simulators do not compile: +# dlsim_tm7 pbchsim scansim mbmssim pdcchsim pucchsim prachsim syncsim +foreach(myExe dlsim ulsim) add_executable(${myExe} ${OPENAIR1_DIR}/SIMULATION/LTE_PHY/${myExe}.c From a31838acd72150f1684b6931b87704f456269d2b Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 19 Dec 2024 22:45:59 +0100 Subject: [PATCH 816/964] CMakeLists.txt: comment out tests that don't compile --- CMakeLists.txt | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9aeb1851d7..66c6fe20b1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2084,22 +2084,23 @@ endforeach(myExe) #unitary tests for Core NEtwork pieces ################################# -foreach(myExe s1ap - secu_knas_encrypt_eia1 - secu_kenb - aes128_ctr - secu_knas_encrypt_eea2 - secu_knas secu_knas_encrypt_eea1 - kdf - aes128_cmac_encrypt - secu_knas_encrypt_eia2) - add_executable(test_${myExe} - ${OPENAIR3_DIR}/TEST/test_${myExe}.c - ) - target_link_libraries (test_${myExe} - -Wl,--start-group SECURITY UTIL -Wl,--end-group m rt CONFIG_LIB - ) -endforeach(myExe) +#foreach(myExe +# s1ap +# secu_knas_encrypt_eia1 +# secu_kenb +# aes128_ctr +# secu_knas_encrypt_eea2 +# secu_knas secu_knas_encrypt_eea1 +# kdf +# aes128_cmac_encrypt +# secu_knas_encrypt_eia2) +# add_executable(test_${myExe} +# ${OPENAIR3_DIR}/TEST/test_${myExe}.c +# ) +# target_link_libraries (test_${myExe} +# -Wl,--start-group SECURITY UTIL -Wl,--end-group m rt CONFIG_LIB +# ) +#endforeach(myExe) #ensure that the T header files are generated before targets depending on them if (${T_TRACER}) From d6c29b2d2c4a17f22a082df56b78de026c67ec9a Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 16 Sep 2025 08:12:23 +0200 Subject: [PATCH 817/964] Fix E2_AGENT linking w.r.t. simulators Link E2_AGENT libraries directly into nr-softmodem/lte-softmodem instead of L2/L2_NR/F1AP. Doing that ensures that simulators, e.g., nr_dlsim/nr_ulsim do still compile. It also simplifies the code. Prior to this, compiling nr_ulsim with E2_AGENT, for instance, resulted in the following errors, fixed in this commit: FAILED: nr_ulsim /usr/bin/ld: openair2/E2AP/RAN_FUNCTION/libe2_ran_func_du_cucp_cuup.a(ran_func_rc.c.o): in function `send_aper_ric_ind': /home/oai/robert/cleanup-t-dependency-cmake/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.c:643: (.text+0xee6): undefined reference to `async_event_agent_api' /usr/bin/ld: /home/oai/robert/cleanup-t-dependency-cmake/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.c:643:(.text+0x11ca): undefined reference to `async_event_agent_api' /usr/bin/ld: /home/oai/robert/cleanup-t-dependency-cmake/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.c:643:(.text+0x1485): undefined reference to `async_event_agent_api' /usr/bin/ld: /home/oai/robert/cleanup-t-dependency-cmake/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.c:643:(.text+0x159c): undefined reference to `async_event_agent_api' /usr/bin/ld: /home/oai/robert/cleanup-t-dependency-cmake/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.c:643:(.text+0x16b1): undefined reference to `async_event_agent_api' [...] --- CMakeLists.txt | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 66c6fe20b1..9a865728a9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -464,9 +464,6 @@ target_include_directories(f1ap PUBLIC F1AP_DIR) target_link_libraries(f1ap PUBLIC asn1_f1ap GTPV1U) target_link_libraries(f1ap PRIVATE ngap nr_rrc HASHTABLE f1ap_lib) target_include_directories(f1ap PRIVATE ${F1AP_DIR}/lib) -if(E2_AGENT) - target_compile_definitions(f1ap PRIVATE E2_AGENT) -endif() # LPP ############## @@ -1306,12 +1303,6 @@ add_library(L2 target_link_libraries(L2 PRIVATE x2ap s1ap lte_rrc m2ap) target_link_libraries(L2 PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs) -if(E2_AGENT) - target_link_libraries(L2 PUBLIC e2_agent e2_agent_arg e2_ran_func_du_cucp_cuup) - target_compile_definitions(L2 PRIVATE ${E2AP_VERSION} ${KPM_VERSION} E2_AGENT) -endif() - - add_library(MAC_UE_NR ${MAC_NR_SRC_UE}) target_link_libraries(MAC_UE_NR PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs PUBLIC nr_ue_power_procedures nr_ue_ra_procedures) @@ -1338,10 +1329,6 @@ target_link_libraries(L2_NR PRIVATE f1ap x2ap s1ap ngap nr_rrc e1ap nr_rlc nr_co if(OAI_AERIAL) target_compile_definitions(L2_NR PRIVATE ENABLE_AERIAL) endif() -if(E2_AGENT) - target_link_libraries(L2_NR PUBLIC e2_agent e2_agent_arg e2_ran_func_du_cucp_cuup) - target_compile_definitions(L2_NR PRIVATE ${E2AP_VERSION} ${KPM_VERSION} E2_AGENT) -endif() add_library(L2_LTE_NR # temporary solution until 4G/5G code completely untangled (as evidenced by deletion of the following file) @@ -1754,6 +1741,7 @@ target_link_libraries(lte-softmodem PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) target_link_libraries(lte-softmodem PRIVATE ${blas_LIBRARIES} ${cblas_LIBRARIES} ${lapacke_LIBRARIES} ${lapack_LIBRARIES}) if(E2_AGENT) + target_link_libraries(lte-softmodem PUBLIC e2_agent e2_agent_arg e2_ran_func_du_cucp_cuup) target_compile_definitions(lte-softmodem PRIVATE ${E2AP_VERSION} ${KPM_VERSION} E2_AGENT) endif() @@ -1857,6 +1845,7 @@ if (OAI_AERIAL) target_link_libraries(nr-softmodem PUBLIC aerial_lib) endif() if(E2_AGENT) + target_link_libraries(nr-softmodem PUBLIC e2_agent e2_agent_arg e2_ran_func_du_cucp_cuup) target_compile_definitions(nr-softmodem PRIVATE ${E2AP_VERSION} ${KPM_VERSION} E2_AGENT) endif() From 1a5e2598a3e76beda7bfe5c274cf24e2e693bfa4 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 12 Sep 2025 12:10:17 +0200 Subject: [PATCH 818/964] Move LTTng check to subdirectory where used --- CMakeLists.txt | 5 ----- common/utils/LOG/CMakeLists.txt | 3 +++ 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9a865728a9..a72cc93823 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -609,11 +609,6 @@ add_library(UTIL ${OPENAIR_DIR}/common/utils/LOG/vcd_signal_dumper.c ${OPENAIR2_DIR}/UTIL/OPT/probe.c ) -if (ENABLE_LTTNG) - find_package(LTTngUST 2.3.8 EXACT REQUIRED) -else() - message(STATUS "LTTNG support disabled") -endif() pkg_check_modules(cap libcap) if (cap_FOUND) diff --git a/common/utils/LOG/CMakeLists.txt b/common/utils/LOG/CMakeLists.txt index ff224329de..6c4527f760 100644 --- a/common/utils/LOG/CMakeLists.txt +++ b/common/utils/LOG/CMakeLists.txt @@ -4,7 +4,10 @@ target_link_libraries(log_headers INTERFACE T_headers) set(log_sources log.c) if (ENABLE_LTTNG) + find_package(LTTngUST 2.3.8 EXACT REQUIRED) set(log_sources ${log_sources} lttng-tp.c) +else() + message(STATUS "LTTNG support disabled") endif() add_library(LOG ${log_sources}) target_include_directories(LOG PUBLIC .) From a68168805b3837346bd6f7d60d13961233a073d8 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 19 Dec 2024 23:11:44 +0100 Subject: [PATCH 819/964] Remove NB-IoT configuration Remove, because 1) it does not compile (the asn1c generated code should be prepend with LTE_ etc, nobody did that) 2) a shared module makes no sense 3) the configuration is trivial to recreate --- CMakeLists.txt | 5 - openair2/ENB_APP/NB_IoT_config.c | 252 ------------------ openair2/ENB_APP/NB_IoT_config.h | 37 --- openair2/ENB_APP/NB_IoT_paramdef.h | 405 ----------------------------- 4 files changed, 699 deletions(-) delete mode 100644 openair2/ENB_APP/NB_IoT_config.c delete mode 100644 openair2/ENB_APP/NB_IoT_config.h delete mode 100644 openair2/ENB_APP/NB_IoT_paramdef.h diff --git a/CMakeLists.txt b/CMakeLists.txt index a72cc93823..350b66afa9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1653,12 +1653,7 @@ include_directories(${NAS_SRC}UE/EMM/SAP) include_directories(${NAS_SRC}UE/ESM) include_directories(${NAS_SRC}UE/ESM/SAP) -# nbiot add_definitions("-DNUMBER_OF_UE_MAX_NB_IoT=16") -set (NBIOT_SOURCES - ${OPENAIR2_DIR}/ENB_APP/NB_IoT_config.c - ) -add_library(NB_IoT MODULE ${NBIOT_SOURCES} ) # Simulation library ########################## diff --git a/openair2/ENB_APP/NB_IoT_config.c b/openair2/ENB_APP/NB_IoT_config.c deleted file mode 100644 index e6fe6e5d71..0000000000 --- a/openair2/ENB_APP/NB_IoT_config.c +++ /dev/null @@ -1,252 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.openairinterface.org/?page_id=698 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -/* - nbiot_config.c - ------------------- - AUTHOR : Francois Taburet - COMPANY : NOKIA - EMAIL : francois.taburet@nokia-bell-labs.com -*/ - -#include -#include - -#include "log.h" -#include "assertions.h" -#include "intertask_interface.h" -#include "s1ap_eNB.h" -#include "sctp_eNB_task.h" -#include "SystemInformationBlockType2.h" - -#include "PHY/phy_extern.h" -#include "radio/ETHERNET/ethernet_lib.h" -#include "common/config/config_userapi.h" -#include "RRC_config_tools.h" -#include "RRC_paramsvalues.h" -#include "NB_IoT_paramdef.h" -#include "L1_paramdef.h" -#include "MACRLC_paramdef.h" -#include "LAYER2/MAC/proto_NB_IoT.h" - - -void RCconfig_NbIoTL1(void) { - paramdef_t NbIoT_L1_Params[] = L1PARAMS_DESC; - paramlist_def_t NbIoT_L1_ParamList = {NBIOT_L1LIST_CONFIG_STRING,NULL,0}; - /* No component carrier for NbIoT, ignore number of CC */ - // NbIoT_L1_Params[L1_CC_IDX ].paramflags = PARAMFLAG_DONOTREAD; - config_getlist(&NbIoT_L1_ParamList, NbIoT_L1_Params, sizeofArray(NbIoT_L1_Params), NULL); - - if (NbIoT_L1_ParamList.numelt > 0) { - if (RC.L1_NB_IoT == NULL) { - RC.L1_NB_IoT = (PHY_VARS_eNB_NB_IoT **)malloc(RC.nb_nb_iot_L1_inst*sizeof(PHY_VARS_eNB_NB_IoT *)); - LOG_I(PHY,"RC.L1_NB_IoT = %p\n",RC.L1_NB_IoT); - memset(RC.L1_NB_IoT,0,RC.nb_nb_iot_L1_inst*sizeof(PHY_VARS_eNB_NB_IoT *)); - } - - for(int j = 0; j eth_params_n.local_if_name = strdup(*(NbIoT_L1_ParamList.paramarray[j][L1_LOCAL_N_IF_NAME_IDX].strptr)); - RC.L1_NB_IoT[j]->eth_params_n.my_addr = strdup(*(NbIoT_L1_ParamList.paramarray[j][L1_LOCAL_N_ADDRESS_IDX].strptr)); - RC.L1_NB_IoT[j]->eth_params_n.remote_addr = strdup(*(NbIoT_L1_ParamList.paramarray[j][L1_REMOTE_N_ADDRESS_IDX].strptr)); - RC.L1_NB_IoT[j]->eth_params_n.my_portc = *(NbIoT_L1_ParamList.paramarray[j][L1_LOCAL_N_PORTC_IDX].iptr); - RC.L1_NB_IoT[j]->eth_params_n.remote_portc = *(NbIoT_L1_ParamList.paramarray[j][L1_REMOTE_N_PORTC_IDX].iptr); - RC.L1_NB_IoT[j]->eth_params_n.my_portd = *(NbIoT_L1_ParamList.paramarray[j][L1_LOCAL_N_PORTD_IDX].iptr); - RC.L1_NB_IoT[j]->eth_params_n.remote_portd = *(NbIoT_L1_ParamList.paramarray[j][L1_REMOTE_N_PORTD_IDX].iptr); - RC.L1_NB_IoT[j]->eth_params_n.transp_preference = ETH_UDP_MODE; - } else { // other midhaul - } - }// j=0..num_inst - - printf("Initializing northbound interface for NB-IoT L1\n"); - l1_north_init_NB_IoT(); - } else { - LOG_I(PHY,"No " NBIOT_L1LIST_CONFIG_STRING " configuration found"); - } -} - -void RCconfig_NbIoTmacrlc(void) { - paramdef_t NbIoT_MacRLC_Params[] = MACRLCPARAMS_DESC; - paramlist_def_t NbIoT_MacRLC_ParamList = {NBIOT_MACRLCLIST_CONFIG_STRING,NULL,0}; - /* No component carrier for NbIoT, ignore number of CC */ - // NbIoT_MacRLC_Params[MACRLC_CC_IDX ].paramflags = PARAMFLAG_DONOTREAD; - config_getlist(&NbIoT_MacRLC_ParamList, NbIoT_MacRLC_Params, sizeofArray(NbIoT_MacRLC_Params), NULL); - - if ( NbIoT_MacRLC_ParamList.numelt > 0) { - mac_top_init_eNB_NB_IoT(); - - for (int j=0; jeth_params_n.local_if_name = strdup(*(NbIoT_MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_N_IF_NAME_IDX].strptr)); - RC.nb_iot_mac[j]->eth_params_n.my_addr = strdup(*(NbIoT_MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_N_ADDRESS_IDX].strptr)); - RC.nb_iot_mac[j]->eth_params_n.remote_addr = strdup(*(NbIoT_MacRLC_ParamList.paramarray[j][MACRLC_REMOTE_N_ADDRESS_IDX].strptr)); - RC.nb_iot_mac[j]->eth_params_n.my_portc = *(NbIoT_MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_N_PORTC_IDX].iptr); - RC.nb_iot_mac[j]->eth_params_n.remote_portc = *(NbIoT_MacRLC_ParamList.paramarray[j][MACRLC_REMOTE_N_PORTC_IDX].iptr); - RC.nb_iot_mac[j]->eth_params_n.my_portd = *(NbIoT_MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_N_PORTD_IDX].iptr); - RC.nb_iot_mac[j]->eth_params_n.remote_portd = *(NbIoT_MacRLC_ParamList.paramarray[j][MACRLC_REMOTE_N_PORTD_IDX].iptr);; - RC.nb_iot_mac[j]->eth_params_n.transp_preference = ETH_UDP_MODE; - } else { // other midhaul - AssertFatal(1==0,"MACRLC %d: %s unknown northbound midhaul\n",j, *(NbIoT_MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_N_PREFERENCE_IDX].strptr)); - } - - if (strcmp(*(NbIoT_MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_S_PREFERENCE_IDX].strptr), "local_L1") == 0) { - } else if (strcmp(*(NbIoT_MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_S_PREFERENCE_IDX].strptr), "nfapi") == 0) { - RC.nb_iot_mac[j]->eth_params_s.local_if_name = strdup(*(NbIoT_MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_S_IF_NAME_IDX].strptr)); - RC.nb_iot_mac[j]->eth_params_s.my_addr = strdup(*(NbIoT_MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_S_ADDRESS_IDX].strptr)); - RC.nb_iot_mac[j]->eth_params_s.remote_addr = strdup(*(NbIoT_MacRLC_ParamList.paramarray[j][MACRLC_REMOTE_S_ADDRESS_IDX].strptr)); - RC.nb_iot_mac[j]->eth_params_s.my_portc = *(NbIoT_MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_S_PORTC_IDX].iptr); - RC.nb_iot_mac[j]->eth_params_s.remote_portc = *(NbIoT_MacRLC_ParamList.paramarray[j][MACRLC_REMOTE_S_PORTC_IDX].iptr); - RC.nb_iot_mac[j]->eth_params_s.my_portd = *(NbIoT_MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_S_PORTD_IDX].iptr); - RC.nb_iot_mac[j]->eth_params_s.remote_portd = *(NbIoT_MacRLC_ParamList.paramarray[j][MACRLC_REMOTE_S_PORTD_IDX].iptr); - RC.nb_iot_mac[j]->eth_params_s.transp_preference = ETH_UDP_MODE; - } else { // other midhaul - AssertFatal(1==0,"MACRLC %d: %s unknown southbound midhaul\n",j,*(NbIoT_MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_S_PREFERENCE_IDX].strptr)); - } - }// j=0..num_inst */ - } else {// MacRLC_ParamList.numelt > 0 - AssertFatal (0, - "No " NBIOT_MACRLCLIST_CONFIG_STRING " configuration found"); - } -} - - - - -int RCconfig_NbIoTRRC(MessageDef *msg_p, int nbiotrrc_id,eNB_RRC_INST_NB_IoT *nbiotrrc) { - char instprefix[MAX_OPTNAME_SIZE*3 + 32]; - checkedparam_t NBIoTCheckParams[] = NBIOT_RRCPARAMS_CHECK_DESC_0_14; - checkedparam_t NBIoTCheckParamsB[] = NBIOT_RRCPARAMS_CHECK_DESC_15_end; - paramdef_t NBIoTParams[] = NBIOTRRCPARAMS_DESC; - paramdef_t NBIoTPrachParams[] = NBIOTRRC_NPRACH_PARAMS_DESC; - checkedparam_t NBIoTPrachCheckParams[] = NBIOT_RRCLIST_NPRACHPARAMSCHECK_DESC; - paramdef_t NBIoTRRCRefParams[] = NBIOTRRCPARAMS_RRCREF_DESC; - paramdef_t NBIoTLteCCParams[] = NBIOT_LTECCPARAMS_DESC; - checkedparam_t NBIoTLteCCCheckParams[] = NBIOT_LTECCPARAMS_CHECK_DESC; - - /* map parameter checking array instances to parameter definition array instances */ - for (int i = 0; i < sizeofArray(NBIoTParams) && i < sizeofArray(NBIoTCheckParams); i++) { - NBIoTParams[i].chkPptr = &(NBIoTCheckParams[i]); - } - - for (int i = 0; i < sizeofArray(NBIoTParams) && i < sizeofArray(NBIoTCheckParamsB); i++) { - NBIoTParams[i + 15].chkPptr = &(NBIoTCheckParamsB[i]); - } - - for (int i = 0; i < sizeofArray(NBIoTPrachParams) && i < sizeofArray(NBIoTPrachCheckParams); i++) { - NBIoTPrachParams[i].chkPptr = &(NBIoTPrachCheckParams[i]); - } - - /* brut force itti message fields assignment, to be redesigned with itti replacement */ - NBIoTParams[NBIOT_RACH_RARESPONSEWINDOWSIZE_NB_IDX].uptr = (uint32_t *)&(NBIOTRRC_CONFIGURATION_REQ (msg_p).rach_raResponseWindowSize_NB); - NBIoTParams[NBIOT_RACH_MACCONTENTIONRESOLUTIONTIMER_NB_IDX].uptr = (uint32_t *)&(NBIOTRRC_CONFIGURATION_REQ (msg_p).rach_macContentionResolutionTimer_NB); - NBIoTParams[NBIOT_RACH_POWERRAMPINGSTEP_NB_IDX].uptr = (uint32_t *)&(NBIOTRRC_CONFIGURATION_REQ (msg_p).rach_powerRampingStep_NB); - NBIoTParams[NBIOT_RACH_PREAMBLEINITIALRECEIVEDTARGETPOWER_NB_IDX].uptr = (uint32_t *)&(NBIOTRRC_CONFIGURATION_REQ (msg_p).rach_preambleInitialReceivedTargetPower_NB); - NBIoTParams[NBIOT_RACH_PREAMBLETRANSMAX_CE_NB_IDX].uptr = (uint32_t *)&(NBIOTRRC_CONFIGURATION_REQ (msg_p).rach_preambleTransMax_CE_NB); - NBIoTParams[NBIOT_BCCH_MODIFICATIONPERIODCOEFF_NB_IDX].uptr = (uint32_t *)&(NBIOTRRC_CONFIGURATION_REQ (msg_p).bcch_modificationPeriodCoeff_NB); - NBIoTParams[NBIOT_PCCH_DEFAULTPAGINGCYCLE_NB_IDX].uptr = (uint32_t *)&(NBIOTRRC_CONFIGURATION_REQ (msg_p).pcch_defaultPagingCycle_NB); - NBIoTParams[NBIOT_NPRACH_CP_LENGTH_IDX].uptr = (uint32_t *)&(NBIOTRRC_CONFIGURATION_REQ (msg_p).nprach_CP_Length); - NBIoTParams[NBIOT_NPRACH_RSRP_RANGE_IDX].uptr = (uint32_t *)&(NBIOTRRC_CONFIGURATION_REQ (msg_p).nprach_rsrp_range); - NBIoTParams[NBIOT_MAXNUMPREAMBLEATTEMPTCE_NB_IDX].uptr = (uint32_t *)&(NBIOTRRC_CONFIGURATION_REQ (msg_p).maxNumPreambleAttemptCE_NB); - NBIoTParams[NBIOT_NPDSCH_NRS_POWER_IDX].uptr = (uint32_t *)&(NBIOTRRC_CONFIGURATION_REQ (msg_p).npdsch_nrs_Power); - NBIoTParams[NBIOT_NPUSCH_ACK_NACK_NUMREPETITIONS_NB_IDX].uptr = (uint32_t *)&(NBIOTRRC_CONFIGURATION_REQ (msg_p). npusch_ack_nack_numRepetitions_NB); - NBIoTParams[NBIOT_NPUSCH_SRS_SUBFRAMECONFIG_NB_IDX].uptr = (uint32_t *)&(NBIOTRRC_CONFIGURATION_REQ (msg_p). npusch_srs_SubframeConfig_NB); - NBIoTParams[NBIOT_NPUSCH_THREETONE_CYCLICSHIFT_R13_IDX].uptr = (uint32_t *)&(NBIOTRRC_CONFIGURATION_REQ (msg_p).npusch_threeTone_CyclicShift_r13); - NBIoTParams[NBIOT_NPUSCH_SIXTONE_CYCLICSHIFT_R13_IDX].uptr = (uint32_t *)&(NBIOTRRC_CONFIGURATION_REQ (msg_p).npusch_sixTone_CyclicShift_r13); - NBIoTParams[NBIOT_NPUSCH_GROUPASSIGNMENTNPUSCH_R13_IDX].uptr = (uint32_t *)&(NBIOTRRC_CONFIGURATION_REQ (msg_p).npusch_groupAssignmentNPUSCH_r13); - NBIoTParams[NBIOT_DL_GAPTHRESHOLD_NB_IDX].uptr = (uint32_t *)&(NBIOTRRC_CONFIGURATION_REQ (msg_p).dl_GapThreshold_NB); - NBIoTParams[NBIOT_DL_GAPPERIODICITY_NB_IDX].uptr = (uint32_t *)&(NBIOTRRC_CONFIGURATION_REQ (msg_p).dl_GapPeriodicity_NB); - NBIoTParams[NBIOT_NPUSCH_P0_NOMINALNPUSCH_IDX].uptr = (uint32_t *)&(NBIOTRRC_CONFIGURATION_REQ (msg_p).npusch_p0_NominalNPUSCH); - NBIoTParams[NBIOT_DELTAPREAMBLEMSG3_IDX].uptr = (uint32_t *)&(NBIOTRRC_CONFIGURATION_REQ (msg_p).deltaPreambleMsg3); - NBIoTParams[NBIOT_UE_TIMERSANDCONSTANTS_T300_NB_IDX].uptr = (uint32_t *)&(NBIOTRRC_CONFIGURATION_REQ (msg_p).ue_TimersAndConstants_t300_NB); - NBIoTParams[NBIOT_UE_TIMERSANDCONSTANTS_T301_NB_IDX].uptr = (uint32_t *)&(NBIOTRRC_CONFIGURATION_REQ (msg_p).ue_TimersAndConstants_t301_NB); - NBIoTParams[NBIOT_UE_TIMERSANDCONSTANTS_T310_NB_IDX].uptr = (uint32_t *)&(NBIOTRRC_CONFIGURATION_REQ (msg_p).ue_TimersAndConstants_t310_NB); - NBIoTParams[NBIOT_UE_TIMERSANDCONSTANTS_T311_NB_IDX].uptr = (uint32_t *)&(NBIOTRRC_CONFIGURATION_REQ (msg_p).ue_TimersAndConstants_t311_NB); - NBIoTParams[NBIOT_UE_TIMERSANDCONSTANTS_N310_NB_IDX].uptr = (uint32_t *)&(NBIOTRRC_CONFIGURATION_REQ (msg_p).ue_TimersAndConstants_n310_NB); - NBIoTParams[NBIOT_UE_TIMERSANDCONSTANTS_N311_NB_IDX].uptr = (uint32_t *)&(NBIOTRRC_CONFIGURATION_REQ (msg_p).ue_TimersAndConstants_n311_NB); - sprintf(instprefix, NBIOT_RRCLIST_CONFIG_STRING ".[%i]",nbiotrrc_id); - config_get( NBIoTParams,sizeofArray(NBIoTParams),instprefix); - NBIOTRRC_CONFIGURATION_REQ (msg_p).nprach_SubcarrierMSG3_RangeStart = config_get_processedint(config_get_if(), &(NBIoTParams[NBIOT_NPRACH_SUBCARRIERMSG3_RANGESTART_IDX]) ); - NBIOTRRC_CONFIGURATION_REQ (msg_p).npusch_groupHoppingEnabled = config_get_processedint(config_get_if(), &(NBIoTParams[NBIOT_NPUSCH_GROUPHOPPINGENABLED_IDX] ) ); - NBIOTRRC_CONFIGURATION_REQ (msg_p).dl_GapDurationCoeff_NB = config_get_processedint(config_get_if(), &(NBIoTParams[NBIOT_DL_GAPDURATIONCOEFF_NB_IDX] ) ); - NBIOTRRC_CONFIGURATION_REQ (msg_p).npusch_alpha = config_get_processedint(config_get_if(), &(NBIoTParams[NBIOT_NPUSCH_ALPHA_IDX] ) ); - - for (int i=0; inb_nb_iot_rrc_inst = NbIoT_ParamList.numelt; - config_getlist( &NbIoT_MACRLCParamList,NULL,0, NULL); - RC->nb_nb_iot_macrlc_inst = NbIoT_MACRLCParamList.numelt; - // Get num L1 instances - config_getlist( &NbIoT_L1ParamList,NULL,0, NULL); - RC->nb_nb_iot_L1_inst = NbIoT_L1ParamList.numelt; -} diff --git a/openair2/ENB_APP/NB_IoT_config.h b/openair2/ENB_APP/NB_IoT_config.h deleted file mode 100644 index 314fca8180..0000000000 --- a/openair2/ENB_APP/NB_IoT_config.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.openairinterface.org/?page_id=698 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -/* - nbiot_config.h - ------------------- - AUTHOR : Francois Taburet - COMPANY : NOKIA - EMAIL : francois.taburet@nokia-bell-labs.com -*/ -#ifndef INCLUDE_NBIOT_CONFIG_H -#define INCLUDE_NBIOT_CONFIG_H - - -extern void RCconfig_NbIoTL1(void) ; -extern void RCconfig_NbIoTmacrlc(void); -extern int RCconfig_NbIoTRRC(MessageDef *msg_p, int nbiotrrc_id,eNB_RRC_INST_NB_IoT *nbiotrrc); -extern void RCConfig_NbIoT(RAN_CONTEXT_t *RC); -#endif diff --git a/openair2/ENB_APP/NB_IoT_paramdef.h b/openair2/ENB_APP/NB_IoT_paramdef.h deleted file mode 100644 index 8778f6d2e4..0000000000 --- a/openair2/ENB_APP/NB_IoT_paramdef.h +++ /dev/null @@ -1,405 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.openairinterface.org/?page_id=698 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -/*! \file openair2/ENB_APP/enb_paramdef.f - * \brief definition of configuration parameters for all eNodeB modules - * \author Francois TABURET - * \date 2017 - * \version 0.1 - * \company NOKIA BellLabs France - * \email: francois.taburet@nokia-bell-labs.com - * \note - * \warning - */ - -#ifndef __ENB_APP_NB_IOT_PARAMDEF__H__ -#define __ENB_APP_NB_IOT_PARAMDEF__H__ - -#include "common/config/config_paramdesc.h" -#include "SystemInformationBlockType2.h" -#include "DL-GapConfig-NB-r13.h" -#include "NPRACH-Parameters-NB-r13.h" -#include "PowerRampingParameters.h" -#include "BCCH-Config-NB-r13.h" -#include "PCCH-Config-NB-r13.h" -#include "ACK-NACK-NumRepetitions-NB-r13.h" -#include "TDD-Config.h" - - - - - -/* - int16_t eutra_band; - uint32_t downlink_frequency; - int32_t uplink_frequency_offset; - int16_t Nid_cell;// for testing, change later - int16_t N_RB_DL;// for testing, change later -*/ -/*-------------------------------------------------------------------------------------------------------------------*/ -/* SIB1 parameters possibly coming from LTE RRC (in band deployment) */ -/*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ -/* component carriers configuration parameters */ -/* optname helpstr paramflags XXXptr defXXXval type numelt checked_param */ -/*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ -#define NBIOT_LTECCPARAMS_CHECK_DESC { \ - { .s3a= { config_checkstr_assign_integer, FRAMETYPE_OKVALUES, FRAMETYPE_MODVALUES,2}} , \ - { .s2= { config_check_intrange, TDDCONFIG_OKRANGE}}, \ - { .s2= { config_check_intrange, TDDCONFIGS_OKRANGE}}, \ - { .s3a= { config_checkstr_assign_integer, PREFIX_OKVALUES, PREFIX_MODVALUES,2}} , \ - { .s3a= { config_checkstr_assign_integer, PREFIXUL_OKVALUES, PREFIXUL_MODVALUES,2}} , \ - { .s5= {NULL }} , \ - { .s5= {NULL }} , \ - { .s5= {NULL }} , \ - { .s5= {NULL }} , \ - { .s1= { config_check_intval, NRBDL_OKVALUES,6}} , \ -} - - -#define NBIOT_LTECCPARAMS_DESC { \ -{ENB_CONFIG_STRING_FRAME_TYPE, NULL, 0, strptr:NULL, defstrval:"FDD", TYPE_STRING, 0}, \ -{ENB_CONFIG_STRING_TDD_CONFIG, NULL, 0, iptr:NULL, defintval:3, TYPE_UINT, 0}, \ -{ENB_CONFIG_STRING_TDD_CONFIG_S, NULL, 0, iptr:NULL, defintval:0, TYPE_UINT, 0}, \ -{ENB_CONFIG_STRING_PREFIX_TYPE, NULL, 0, strptr:NULL, defstrval:"NORMAL", TYPE_STRING, 0}, \ -{ENB_CONFIG_STRING_PREFIX_TYPE_UL, NULL, 0, strptr:NULL, defstrval:"NORMAL", TYPE_STRING, 0}, \ -{ENB_CONFIG_STRING_EUTRA_BAND, NULL, 0, iptr:NULL, defintval:7, TYPE_UINT, 0}, \ -{ENB_CONFIG_STRING_DOWNLINK_FREQUENCY, NULL, 0, i64ptr:NULL, defint64val:2680000000, TYPE_UINT64, 0}, \ -{ENB_CONFIG_STRING_UPLINK_FREQUENCY_OFFSET, NULL, 0, iptr:NULL, defintval:-120000000, TYPE_INT, 0}, \ -{ENB_CONFIG_STRING_NID_CELL, NULL, 0, iptr:NULL, defintval:0, TYPE_UINT, 0}, \ -{ENB_CONFIG_STRING_N_RB_DL, NULL, 0, iptr:NULL, defintval:25, TYPE_UINT, 0}, \ -} -#define LTECCPARAMS_FRAME_TYPE_IDX 0 -#define LTECCPARAMS_TDD_CONFIG_IDX 1 -#define LTECCPARAMS_TDD_CONFIG_S_IDX 2 -#define LTECCPARAMS_PREFIX_TYPE_IDX 3 -#define LTECCPARAMS_PREFIX_TYPE_UL_IDX 4 -#define LTECCPARAMS_EUTRA_BAND_IDX 5 -#define LTECCPARAMS_DOWNLINK_FREQUENCY_IDX 6 -#define LTECCPARAMS_UPLINK_FREQUENCY_OFFSET_IDX 7 -#define LTECCPARAMS_NID_CELL_IDX 8 -#define LTECCPARAMS_N_RB_DL_IDX 9 - - -/*-------------------------------------------------------------------------------------------------------------------*/ - -/* NB-Iot RRC list section name */ -#define NBIOT_RRCLIST_CONFIG_STRING "NB-IoT_RRCs" - - -#define RACH_RARESPONSEWINDOWSIZE_NB_OKVALUES {20,50,80,120,180,240,320,400} -#define PREF1(A) RACH_CE_LevelInfo_r13__ra_ResponseWindowSize_r13_ ## A -#define RACH_RARESPONSEWINDOWSIZE_NB_MODVALUES { PREF1(sf20),PREF1(sf50),PREF1(sf80),PREF1(sf120), \ - PREF1(sf180),PREF1(sf240),PREF1(sf320),PREF1(sf400) } - - -#define RACH_MACCONTENTIONRESOLUTIONTIMER_NB_OKVALUES {80,100,120,160,200,240,480,960} -#define PREF2(A) RACH_CE_LevelInfo_r13__mac_ContentionResolutionTimer_r13_ ## A -#define RACH_MACCONTENTIONRESOLUTIONTIMER_NB_MODVALUES { PREF2(sf80),PREF2(sf100),PREF2(sf120),PREF2(sf160), \ - PREF2(sf200),PREF2(sf240),PREF2(sf480),PREF2(sf960) } - - -#define RACH_POWERRAMPINGSTEP_NB_OKVALUES {0,2,4,6} -#define PREF3(A) PowerRampingParameters__powerRampingStep_ ## A -#define RACH_POWERRAMPINGSTEP_NB_MODVALUES { PREF3(dB0),PREF3(dB2),PREF3(dB4),PREF3(dB6) } - - -#define RACH_PREAMBLEINITIALRECEIVEDTARGETPOWER_NB_OKRANGE {-120, -90} - -#define RACH_PREAMBLETRANSMAX_CE_NB_OKVALUES {3,4,5,6,7,8,10,20,50,100,200} -#define PREF4(A) PreambleTransMax_ ## A -#define RACH_PREAMBLETRANSMAX_CE_NB_MODVALUES { PREF4(n3), PREF4(n4), PREF4(n5), PREF4(n6), PREF4(n7), PREF4(n8), \ - PREF4(n10),PREF4(n20),PREF4(n50),PREF4(n100),PREF4(n200) } - -#define BCCH_MODIFICATIONPERIODCOEFF_NB_OKVALUES {16,32,64,128} -#define PREF5(A) BCCH_Config_NB_r13__modificationPeriodCoeff_r13_ ## A -#define BCCH_MODIFICATIONPERIODCOEFF_NB_MODVALUES { PREF5(n16), PREF5(n32), PREF5(n64),PREF5(n128) } - -#define PCCH_DEFAULTPAGINGCYCLE_NB_OKVALUES {128,256,512,1024} -#define PREF6(A) PCCH_Config_NB_r13__defaultPagingCycle_r13_ ## A -#define PCCH_DEFAULTPAGINGCYCLE_NB_MODVALUES { PREF6(rf128), PREF6(rf256), PREF6(rf512), PREF6(rf1024) } - -#define NPRACH_CP_LENGTH_OKVALUES {0,1} -#define NPRACH_RSRP_RANGE_OKVALUES {0,96} - -#define MSG3RANGESTART_OKVALUES {"zero","oneThird","twoThird","one"} -#define MSG3RANGESTART_MODVALUES {NPRACH_Parameters_NB_r13__nprach_SubcarrierMSG3_RangeStart_r13_zero, NPRACH_Parameters_NB_r13__nprach_SubcarrierMSG3_RangeStart_r13_oneThird, \ - NPRACH_Parameters_NB_r13__nprach_SubcarrierMSG3_RangeStart_r13_twoThird, NPRACH_Parameters_NB_r13__nprach_SubcarrierMSG3_RangeStart_r13_one} - - -#define MAXNUMPREAMBLEATTEMPTCE_OKVALUES {3,4,5,6,7,8,10} -#define MAXNUMPREAMBLEATTEMPTCE_MODVALUES { NPRACH_Parameters_NB_r13__maxNumPreambleAttemptCE_r13_n3, NPRACH_Parameters_NB_r13__maxNumPreambleAttemptCE_r13_n4, \ - NPRACH_Parameters_NB_r13__maxNumPreambleAttemptCE_r13_n5, NPRACH_Parameters_NB_r13__maxNumPreambleAttemptCE_r13_n6, \ - NPRACH_Parameters_NB_r13__maxNumPreambleAttemptCE_r13_n7, NPRACH_Parameters_NB_r13__maxNumPreambleAttemptCE_r13_n8, \ - NPRACH_Parameters_NB_r13__maxNumPreambleAttemptCE_r13_n10 } - -#define NPDSCH_NRS_POWER_OKRANGE {-60,50} - -#define NPUSCH_ACK_NACK_NUMREPETITIONS_NB_OKVALUES {1,2,4,8,16,32,64,128} -#define PREF9(A) ACK_NACK_NumRepetitions_NB_r13_ ## A -#define NPUSCH_ACK_NACK_NUMREPETITIONS_NB_MODVALUES { PREF9(r1), PREF9(r2), PREF9(r4), PREF9(r8), \ - PREF9(r16), PREF9(r32), PREF9(r64), PREF9(r128) } - -#define NPUSCH_SRS_SUBFRAMECONFIG_NB_OKRANGE {0,15} -#define NPUSCH_THREETONE_CYCLICSHIFT_R13_OKRANGE {0,2} -#define NPUSCH_SIXTONE_CYCLICSHIFT_R13_OKRANGE {0,3} - -#define NPUSCH_GROUPHOPPINGENABLED_OKVALUES {"enable","disable"} -#define NPUSCH_GROUPHOPPINGENABLED_MODVALUES {1,0} - -#define NPUSCH_GROUPASSIGNMENTNPUSCH_R13_OKRANGE {0,29} - -#define DLGAPTHRESHOLD_OKVALUES {32,64,128,256} -#define DLGAPTHRESHOLD_MODVALUES { DL_GapConfig_NB_r13__dl_GapThreshold_r13_n32, DL_GapConfig_NB_r13__dl_GapThreshold_r13_n64, \ - DL_GapConfig_NB_r13__dl_GapThreshold_r13_n128, DL_GapConfig_NB_r13__dl_GapThreshold_r13_n256} \ - -#define DLGAPPERIODICITY_OKVALUES {64,128,256,512} -#define DLGAPPERIODICITY_MODVALUES { DL_GapConfig_NB_r13__dl_GapPeriodicity_r13_sf64, DL_GapConfig_NB_r13__dl_GapPeriodicity_r13_sf128, \ - DL_GapConfig_NB_r13__dl_GapPeriodicity_r13_sf256,DL_GapConfig_NB_r13__dl_GapPeriodicity_r13_sf512} - -#define DLGAPDURATION_OKVALUES {"oneEighth","oneFourth","threeEighth","oneHalf"} -#define DLGAPDURATION_MODVALUES {DL_GapConfig_NB_r13__dl_GapDurationCoeff_r13_oneEighth, DL_GapConfig_NB_r13__dl_GapDurationCoeff_r13_oneFourth, \ - DL_GapConfig_NB_r13__dl_GapDurationCoeff_r13_threeEighth, DL_GapConfig_NB_r13__dl_GapDurationCoeff_r13_oneHalf} - -#define NPUSCH_P0_NOMINALNPUSCH_OKRANGE {-126,24} - -#define NPUSCH_ALPHA_OKVALUES {"AL0","AL04","AL05","AL06","AL07","AL08","AL09","AL1"} -#define NPUSCH_ALPHA_MODVALUES { Alpha_r12_al0, Alpha_r12_al04, Alpha_r12_al05, Alpha_r12_al06, \ - Alpha_r12_al07, Alpha_r12_al08, Alpha_r12_al09, Alpha_r12_al1} - -#define DELTAPREAMBLEMSG3_OKRANGE {-1,6} - - - - - -#define NBIOT_RRCPARAMS_CHECK_DESC { \ - { .s1a= { config_check_modify_integer, RACH_RARESPONSEWINDOWSIZE_NB_OKVALUES, RACH_RARESPONSEWINDOWSIZE_NB_MODVALUES, 8}}, \ - { .s1a= { config_check_modify_integer, RACH_MACCONTENTIONRESOLUTIONTIMER_NB_OKVALUES, RACH_MACCONTENTIONRESOLUTIONTIMER_NB_MODVALUES, 8}}, \ - { .s1a= { config_check_modify_integer, RACH_POWERRAMPINGSTEP_NB_OKVALUES, RACH_POWERRAMPINGSTEP_NB_MODVALUES, 4}} , \ - { .s2= { config_check_intrange, RACH_PREAMBLEINITIALRECEIVEDTARGETPOWER_NB_OKRANGE}}, \ - { .s1a= { config_check_modify_integer, RACH_PREAMBLETRANSMAX_CE_NB_OKVALUES, RACH_PREAMBLETRANSMAX_CE_NB_MODVALUES, 11}} , \ - { .s1a= { config_check_modify_integer, BCCH_MODIFICATIONPERIODCOEFF_NB_OKVALUES, BCCH_MODIFICATIONPERIODCOEFF_NB_MODVALUES, 4}} , \ - { .s1a= { config_check_modify_integer, PCCH_DEFAULTPAGINGCYCLE_NB_OKVALUES, PCCH_DEFAULTPAGINGCYCLE_NB_MODVALUES, 4}} , \ - { .s1= { NULL, NPRACH_CP_LENGTH_OKVALUES ,4}} , \ - { .s2= { config_check_intrange, NPRACH_RSRP_RANGE_OKVALUES}} , \ - { .s3a= { config_checkstr_assign_integer, MSG3RANGESTART_OKVALUES, MSG3RANGESTART_MODVALUES, 4}} , \ - { .s1a= { config_check_modify_integer, MAXNUMPREAMBLEATTEMPTCE_OKVALUES, MAXNUMPREAMBLEATTEMPTCE_MODVALUES, 7}} , \ - { .s1= { config_check_intval, NPDSCH_NRS_POWER_OKRANGE,4}} , \ - { .s1a= { config_check_modify_integer, NPUSCH_ACK_NACK_NUMREPETITIONS_NB_OKVALUES, NPUSCH_ACK_NACK_NUMREPETITIONS_NB_MODVALUES, 8}} , \ - { .s2= { config_check_intrange, NPUSCH_SRS_SUBFRAMECONFIG_NB_OKRANGE}} , \ - { .s2= { config_check_intrange, NPUSCH_THREETONE_CYCLICSHIFT_R13_OKRANGE}} , \ - { .s2= { config_check_intrange, NPUSCH_SIXTONE_CYCLICSHIFT_R13_OKRANGE}} , \ - { .s3a= { config_checkstr_assign_integer, NPUSCH_GROUPHOPPINGENABLED_OKVALUES, NPUSCH_GROUPHOPPINGENABLED_MODVALUES, 2}} , \ - { .s2= { config_check_intrange, NPUSCH_GROUPASSIGNMENTNPUSCH_R13_OKRANGE}} , \ - { .s1a= { config_check_modify_integer, DLGAPTHRESHOLD_OKVALUES, DLGAPTHRESHOLD_MODVALUES, 4}} , \ - { .s1a= { config_check_modify_integer, DLGAPPERIODICITY_OKVALUES, DLGAPPERIODICITY_MODVALUES, 4}} , \ - { .s3a= { config_checkstr_assign_integer, DLGAPDURATION_OKVALUES, DLGAPDURATION_MODVALUES , 4}} , \ - { .s2= { config_check_intrange, NPUSCH_P0_NOMINALNPUSCH_OKRANGE}} , \ - { .s3a= { config_checkstr_assign_integer, NPUSCH_ALPHA_OKVALUES, NPUSCH_ALPHA_MODVALUES, 8}} , \ - { .s2= { config_check_intrange, DELTAPREAMBLEMSG3_OKRANGE}} , \ - { .s1a= { config_check_modify_integer, UETIMER_T300_OKVALUES, UETIMER_T300_MODVALUES,8}} , \ - { .s1a= { config_check_modify_integer, UETIMER_T301_OKVALUES, UETIMER_T301_MODVALUES,8}} , \ - { .s1a= { config_check_modify_integer, UETIMER_T310_OKVALUES, UETIMER_T310_MODVALUES,7}} , \ - { .s1a= { config_check_modify_integer, UETIMER_T311_OKVALUES, UETIMER_T311_MODVALUES,7}} , \ - { .s1a= { config_check_modify_integer, UETIMER_N310_OKVALUES, UETIMER_N310_MODVALUES,8}} , \ - { .s1a= { config_check_modify_integer, UETIMER_N311_OKVALUES, UETIMER_N311_MODVALUES,8}} , \ -} -/*-----------------------------------------------------------------------------------------------------------------------------------------*/ -/* NB-IoT RRC configuration parameters */ -/* optname helpstr paramflags XXXptr defXXXval type numelt */ -/*-----------------------------------------------------------------------------------------------------------------------------------------*/ -#define NBIOTRRCPARAMS_DESC { \ -{"rach_raResponseWindowSize_NB", NULL, 0, uptr:NULL, defintval:20, TYPE_UINT, 0}, \ -{"rach_macContentionResolutionTimer_NB", NULL, 0, uptr:NULL, defintval:80, TYPE_UINT, 0}, \ -{"rach_powerRampingStep_NB", NULL, 0, uptr:NULL, defintval:0, TYPE_UINT, 0}, \ -{"rach_preambleInitialReceivedTargetPower_NB", NULL, 0, iptr:NULL, defintval:-112, TYPE_INT32, 0}, \ -{"rach_preambleTransMax_CE_NB", NULL, 0, uptr:NULL, defintval:3, TYPE_UINT, 0}, \ -{"bcch_modificationPeriodCoeff_NB", NULL, 0, uptr:NULL, defintval:16, TYPE_UINT, 0}, \ -{"pcch_defaultPagingCycle_NB", NULL, 0, uptr:NULL, defintval:256, TYPE_UINT, 0}, \ -{"nprach_CP_Length", NULL, 0, uptr:NULL, defintval:0, TYPE_UINT, 0}, \ -{"nprach_rsrp_range", NULL, 0, uptr:NULL, defintval:0, TYPE_UINT, 0}, \ -{"nprach_SubcarrierMSG3_RangeStart", NULL, 0, strptr:NULL, defstrval:"one", TYPE_STRING, 0}, \ -{"maxNumPreambleAttemptCE_NB", NULL, 0, uptr:NULL, defintval:10, TYPE_UINT, 0}, \ -{"npdsch_nrs_Power", NULL, 0, iptr:NULL, defintval:0, TYPE_INT, 0}, \ -{"npusch_ack_nack_numRepetitions_NB", NULL, 0, uptr:NULL, defintval:1, TYPE_UINT, 0}, \ -{"npusch_srs_SubframeConfig_NB", NULL, 0, uptr:NULL, defintval:0, TYPE_UINT, 0}, \ -{"npusch_threeTone_CyclicShift_r13", NULL, 0, uptr:NULL, defintval:0, TYPE_UINT, 0}, \ -{"npusch_sixTone_CyclicShift_r13", NULL, 0, uptr:NULL, defintval:0, TYPE_UINT, 0}, \ -{"npusch_groupHoppingEnabled", NULL, 0, strptr:NULL, defstrval:"disable", TYPE_STRING, 0}, \ -{"npusch_groupAssignmentNPUSCH_r13", NULL, 0, uptr:NULL, defintval:0, TYPE_UINT, 0}, \ -{"dl_GapThreshold_NB", NULL, 0, uptr:NULL, defintval:32, TYPE_UINT, 0}, \ -{"dl_GapPeriodicity_NB", NULL, 0, uptr:NULL, defintval:64, TYPE_UINT, 0}, \ -{"dl_GapDurationCoeff_NB", NULL, 0, strptr:NULL, defstrval:"oneEighth", TYPE_STRING, 0}, \ -{"npusch_p0_NominalNPUSCH", NULL, 0, iptr:NULL, defintval:0, TYPE_INT32, 0}, \ -{"npusch_alpha", NULL, 0, strptr:NULL, defstrval:"AL0", TYPE_STRING, 0}, \ -{"deltaPreambleMsg3", NULL, 0, iptr:NULL, defintval:0, TYPE_INT32, 0}, \ -{"ue_TimersAndConstants_t300_NB", NULL, 0, uptr:NULL, defintval:1000, TYPE_UINT, 0}, \ -{"ue_TimersAndConstants_t301_NB", NULL, 0, uptr:NULL, defintval:1000, TYPE_UINT, 0}, \ -{"ue_TimersAndConstants_t310_NB", NULL, 0, uptr:NULL, defintval:1000, TYPE_UINT, 0}, \ -{"ue_TimersAndConstants_t311_NB", NULL, 0, uptr:NULL, defintval:10000, TYPE_UINT, 0}, \ -{"ue_TimersAndConstants_n310_NB", NULL, 0, uptr:NULL, defintval:20, TYPE_UINT, 0}, \ -{"ue_TimersAndConstants_n311_NB", NULL, 0, uptr:NULL, defintval:1, TYPE_UINT, 0}, \ -} - -#define NBIOT_RACH_RARESPONSEWINDOWSIZE_NB_IDX 0 -#define NBIOT_RACH_MACCONTENTIONRESOLUTIONTIMER_NB_IDX 1 -#define NBIOT_RACH_POWERRAMPINGSTEP_NB_IDX 2 -#define NBIOT_RACH_PREAMBLEINITIALRECEIVEDTARGETPOWER_NB_IDX 3 -#define NBIOT_RACH_PREAMBLETRANSMAX_CE_NB_IDX 4 -#define NBIOT_BCCH_MODIFICATIONPERIODCOEFF_NB_IDX 5 -#define NBIOT_PCCH_DEFAULTPAGINGCYCLE_NB_IDX 6 -#define NBIOT_NPRACH_CP_LENGTH_IDX 7 -#define NBIOT_NPRACH_RSRP_RANGE_IDX 8 -#define NBIOT_NPRACH_SUBCARRIERMSG3_RANGESTART_IDX 9 -#define NBIOT_MAXNUMPREAMBLEATTEMPTCE_NB_IDX 10 -#define NBIOT_NPDSCH_NRS_POWER_IDX 11 -#define NBIOT_NPUSCH_ACK_NACK_NUMREPETITIONS_NB_IDX 12 -#define NBIOT_NPUSCH_SRS_SUBFRAMECONFIG_NB_IDX 13 -#define NBIOT_NPUSCH_THREETONE_CYCLICSHIFT_R13_IDX 14 -#define NBIOT_NPUSCH_SIXTONE_CYCLICSHIFT_R13_IDX 15 -#define NBIOT_NPUSCH_GROUPHOPPINGENABLED_IDX 16 -#define NBIOT_NPUSCH_GROUPASSIGNMENTNPUSCH_R13_IDX 17 -#define NBIOT_DL_GAPTHRESHOLD_NB_IDX 18 -#define NBIOT_DL_GAPPERIODICITY_NB_IDX 19 -#define NBIOT_DL_GAPDURATIONCOEFF_NB_IDX 20 -#define NBIOT_NPUSCH_P0_NOMINALNPUSCH_IDX 21 -#define NBIOT_NPUSCH_ALPHA_IDX 22 -#define NBIOT_DELTAPREAMBLEMSG3_IDX 23 -#define NBIOT_UE_TIMERSANDCONSTANTS_T300_NB_IDX 24 -#define NBIOT_UE_TIMERSANDCONSTANTS_T301_NB_IDX 25 -#define NBIOT_UE_TIMERSANDCONSTANTS_T310_NB_IDX 26 -#define NBIOT_UE_TIMERSANDCONSTANTS_T311_NB_IDX 27 -#define NBIOT_UE_TIMERSANDCONSTANTS_N310_NB_IDX 28 -#define NBIOT_UE_TIMERSANDCONSTANTS_N311_NB_IDX 29 - -/* NB-Iot RRC: link to LTE RRC section name */ -#define NBIOT_LTERRCREF_CONFIG_STRING "LTERRC_Ref" -/*---------------------------------------------------------------------------------------------------------------*/ -/* NB-IoT RRC configuration parameters to link to a LTE RRC instance (in-guard, in-band) */ -/* optname helpstr paramflags XXXptr defXXXval type numelt */ -/*---------------------------------------------------------------------------------------------------------------*/ -#define NBIOTRRCPARAMS_RRCREF_DESC { \ -{"RRC_inst", NULL, 0, uptr:NULL, defintval:0, TYPE_UINT, 0}, \ -{"CC_inst", NULL, 0, uptr:NULL, defintval:0, TYPE_UINT, 0}, \ -} -/*--------------------------------------------------------------------------------------------------------------*/ -#define NBIOT_RRCINST_IDX 0 -#define NBIOT_CCINST_IDX 1 - -#define NBIOT_RRCLIST_NPRACHPARAMS_CONFIG_STRING "NPRACH-NB-r13" - - -#define NPRACH_PERIODICITY_OKVALUES {40,80,160,240,320,640,1280,2560} -#define NPRACH_PERIODICITY_MODVALUES { NPRACH_Parameters_NB_r13__nprach_Periodicity_r13_ms40, NPRACH_Parameters_NB_r13__nprach_Periodicity_r13_ms80, \ - NPRACH_Parameters_NB_r13__nprach_Periodicity_r13_ms160, NPRACH_Parameters_NB_r13__nprach_Periodicity_r13_ms240, \ - NPRACH_Parameters_NB_r13__nprach_Periodicity_r13_ms320, NPRACH_Parameters_NB_r13__nprach_Periodicity_r13_ms640, \ - NPRACH_Parameters_NB_r13__nprach_Periodicity_r13_ms1280, NPRACH_Parameters_NB_r13__nprach_Periodicity_r13_ms2560 } - -#define NPRACH_STARTTIME_OKVALUES {8,16,32,64,128,256,512,1024} -#define NPRACH_STARTTIME_MODVALUES { NPRACH_Parameters_NB_r13__nprach_StartTime_r13_ms8, NPRACH_Parameters_NB_r13__nprach_StartTime_r13_ms16, \ - NPRACH_Parameters_NB_r13__nprach_StartTime_r13_ms32, NPRACH_Parameters_NB_r13__nprach_StartTime_r13_ms64, \ - NPRACH_Parameters_NB_r13__nprach_StartTime_r13_ms128, NPRACH_Parameters_NB_r13__nprach_StartTime_r13_ms256, \ - NPRACH_Parameters_NB_r13__nprach_StartTime_r13_ms512, NPRACH_Parameters_NB_r13__nprach_StartTime_r13_ms1024 } - -#define NPRACH_SUBCARRIEROFFSET_OKVALUES {0,12,24,36,2,18,34} -#define NPRACH_SUBCARRIEROFFSET_MODVALUES { NPRACH_Parameters_NB_r13__nprach_SubcarrierOffset_r13_n0, NPRACH_Parameters_NB_r13__nprach_SubcarrierOffset_r13_n12, \ - NPRACH_Parameters_NB_r13__nprach_SubcarrierOffset_r13_n24, NPRACH_Parameters_NB_r13__nprach_SubcarrierOffset_r13_n36, \ - NPRACH_Parameters_NB_r13__nprach_SubcarrierOffset_r13_n2, NPRACH_Parameters_NB_r13__nprach_SubcarrierOffset_r13_n18, \ - NPRACH_Parameters_NB_r13__nprach_SubcarrierOffset_r13_n34 } - -#define NPRACH_NUMSUBCARRIERS_OKVALUES {12,24,36,48} -#define NPRACH_NUMSUBCARRIERS_MODVALUES { NPRACH_Parameters_NB_r13__nprach_NumSubcarriers_r13_n12, NPRACH_Parameters_NB_r13__nprach_NumSubcarriers_r13_n24, \ - NPRACH_Parameters_NB_r13__nprach_NumSubcarriers_r13_n36, NPRACH_Parameters_NB_r13__nprach_NumSubcarriers_r13_n48 } - - -#define NUMREPETITIONSPERPREAMBLEATTEMPT_OKVALUES {1,2,4,8,16,32,64,128} -#define NUMREPETITIONSPERPREAMBLEATTEMPT_MODVALUES { NPRACH_Parameters_NB_r13__numRepetitionsPerPreambleAttempt_r13_n1, NPRACH_Parameters_NB_r13__numRepetitionsPerPreambleAttempt_r13_n2, \ - NPRACH_Parameters_NB_r13__numRepetitionsPerPreambleAttempt_r13_n4, NPRACH_Parameters_NB_r13__numRepetitionsPerPreambleAttempt_r13_n8, \ - NPRACH_Parameters_NB_r13__numRepetitionsPerPreambleAttempt_r13_n16, NPRACH_Parameters_NB_r13__numRepetitionsPerPreambleAttempt_r13_n32, \ - NPRACH_Parameters_NB_r13__numRepetitionsPerPreambleAttempt_r13_n64, NPRACH_Parameters_NB_r13__numRepetitionsPerPreambleAttempt_r13_n128} - -#define NPDCCHNUMREPETITIONSRA_OKVALUES {1,2,4,8,16,32,64,128,256,512,1024,2048} -#define NPDCCHNUMREPETITIONSRA_MODVALUES { NPRACH_Parameters_NB_r13__npdcch_NumRepetitions_RA_r13_r1, NPRACH_Parameters_NB_r13__npdcch_NumRepetitions_RA_r13_r2, \ - NPRACH_Parameters_NB_r13__npdcch_NumRepetitions_RA_r13_r4, NPRACH_Parameters_NB_r13__npdcch_NumRepetitions_RA_r13_r8, \ - NPRACH_Parameters_NB_r13__npdcch_NumRepetitions_RA_r13_r16, NPRACH_Parameters_NB_r13__npdcch_NumRepetitions_RA_r13_r32, \ - NPRACH_Parameters_NB_r13__npdcch_NumRepetitions_RA_r13_r64, NPRACH_Parameters_NB_r13__npdcch_NumRepetitions_RA_r13_r128, \ - NPRACH_Parameters_NB_r13__npdcch_NumRepetitions_RA_r13_r256, NPRACH_Parameters_NB_r13__npdcch_NumRepetitions_RA_r13_r512, \ - NPRACH_Parameters_NB_r13__npdcch_NumRepetitions_RA_r13_r1024,NPRACH_Parameters_NB_r13__npdcch_NumRepetitions_RA_r13_r2048} - -#define NPDCCHSTARTSFCSSRA_OKVALUES {1,2,4,8,16,32,48,64} -#define NPDCCHSTARTSFCSSRA_MODVALUES { NPRACH_Parameters_NB_r13__npdcch_StartSF_CSS_RA_r13_v1dot5, NPRACH_Parameters_NB_r13__npdcch_StartSF_CSS_RA_r13_v2, \ - NPRACH_Parameters_NB_r13__npdcch_StartSF_CSS_RA_r13_v4, NPRACH_Parameters_NB_r13__npdcch_StartSF_CSS_RA_r13_v8, \ - NPRACH_Parameters_NB_r13__npdcch_StartSF_CSS_RA_r13_v16, NPRACH_Parameters_NB_r13__npdcch_StartSF_CSS_RA_r13_v32, \ - NPRACH_Parameters_NB_r13__npdcch_StartSF_CSS_RA_r13_v48, NPRACH_Parameters_NB_r13__npdcch_StartSF_CSS_RA_r13_v64} - -#define NPDCCHOFFSETRA_OKVALUES {"zero","oneEighth","oneFourth","threeEighth"} -#define NPDCCHOFFSETRA_MODVALUES { NPRACH_Parameters_NB_r13__npdcch_Offset_RA_r13_zero, NPRACH_Parameters_NB_r13__npdcch_Offset_RA_r13_oneEighth, \ - NPRACH_Parameters_NB_r13__npdcch_Offset_RA_r13_oneFourth, NPRACH_Parameters_NB_r13__npdcch_Offset_RA_r13_threeEighth} - - - -#define NBIOT_RRCLIST_NPRACHPARAMSCHECK_DESC { \ - { .s1a= { config_check_modify_integer, NPRACH_PERIODICITY_OKVALUES, NPRACH_PERIODICITY_MODVALUES, 8 }}, \ - { .s1a= { config_check_modify_integer, NPRACH_STARTTIME_OKVALUES, NPRACH_STARTTIME_MODVALUES, 8 }}, \ - { .s1a= { config_check_modify_integer, NPRACH_SUBCARRIEROFFSET_OKVALUES, NPRACH_SUBCARRIEROFFSET_MODVALUES, 7 }}, \ - { .s1a= { config_check_modify_integer, NPRACH_NUMSUBCARRIERS_OKVALUES, NPRACH_NUMSUBCARRIERS_MODVALUES, 4 }}, \ - { .s1a= { config_check_modify_integer, NUMREPETITIONSPERPREAMBLEATTEMPT_OKVALUES, NUMREPETITIONSPERPREAMBLEATTEMPT_MODVALUES,8 }}, \ - { .s1a= { config_check_modify_integer, NPDCCHNUMREPETITIONSRA_OKVALUES, NPDCCHNUMREPETITIONSRA_MODVALUES, 12}}, \ - { .s1a= { config_check_modify_integer, NPDCCHSTARTSFCSSRA_OKVALUES, NPDCCHSTARTSFCSSRA_MODVALUES, 8 }}, \ - { .s3a= { config_checkstr_assign_integer, NPDCCHOFFSETRA_OKVALUES, NPDCCHOFFSETRA_MODVALUES, 4 }}, \ -} - - - -/*------------------------------------------------------------------------------------------------------------------------------*/ -/* NB-IoT NPrach parameters, there will be three ocuurences of these parameters in each RRC instance */ - /* optname helpstr paramflags XXXptr defXXXval type numelt */ -/*------------------------------------------------------------------------------------------------------------------------------*/ -#define NBIOTRRC_NPRACH_PARAMS_DESC { \ -{"nprach_Periodicity", NULL, 0, uptr:NULL, defintval:320, TYPE_UINT, 0}, \ -{"nprach_StartTime", NULL, 0, uptr:NULL, defintval:8, TYPE_UINT, 0}, \ -{"nprach_SubcarrierOffset", NULL, 0, uptr:NULL, defintval:0, TYPE_UINT, 0}, \ -{"nprach_NumSubcarriers", NULL, 0, uptr:NULL, defintval:12, TYPE_UINT, 0}, \ -{"numRepetitionsPerPreambleAttempt", NULL, 0, uptr:NULL, defintval:2, TYPE_UINT, 0}, \ -{"npdcch_NumRepetitions_RA", NULL, 0, uptr:NULL, defintval:16, TYPE_UINT, 0}, \ -{"npdcch_StartSF_CSS_RA", NULL, 0, uptr:NULL, defintval:2, TYPE_UINT, 0}, \ -{"npdcch_Offset_RA", NULL, 0, strptr:NULL, defstrval:"zero", TYPE_STRING, 0}, \ -} - -#define NBIOT_NPRACH_PERIODICITY_IDX 0 -#define NBIOT_NPRACH_STARTTIME_IDX 1 -#define NBIOT_NPRACH_SUBCARRIEROFFSET_IDX 2 -#define NBIOT_NPRACH_NUMSUBCARRIERS_IDX 3 -#define NBIOT_NUMREPETITIONSPERPREAMBLEATTEMPT_NB_IDX 4 -#define NBIOT_NPDCCH_NUMREPETITIONS_RA_IDX 5 -#define NBIOT_NPDCCH_STARTSF_CSS_RA_IDX 6 -#define NBIOT_NPDCCH_OFFSET_RA_IDX 7 - -/*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ -/* NB IoT MACRLC configuration list section name */ -#define NBIOT_MACRLCLIST_CONFIG_STRING "NB-IoT_MACRLCs" - - -/*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ -/* NB IoT L1 configuration list section name */ -#define NBIOT_L1LIST_CONFIG_STRING "NB-IoT_L1s" - -#endif From cede4499071097c04e83071661b3835379051d44 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 25 Jul 2025 09:30:00 +0200 Subject: [PATCH 820/964] Remove NUMBER_OF_UE_MAX_NB_IoT and make NB_IoT compile This constant seems to be an analogon to NUMBER_OF_UE_MAX; replace with the latter, as it does the same. (NBIoT does not work, anyway) Fix dependencies of the NB_IoT target so it compiles. --- CMakeLists.txt | 2 - openair1/PHY/defs_L1_NB_IoT.h | 73 ++++++++++++++--------------- openair1/PHY/impl_defs_top_NB_IoT.h | 24 +++++----- 3 files changed, 48 insertions(+), 51 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 350b66afa9..fa7510a9f1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1653,8 +1653,6 @@ include_directories(${NAS_SRC}UE/EMM/SAP) include_directories(${NAS_SRC}UE/ESM) include_directories(${NAS_SRC}UE/ESM/SAP) -add_definitions("-DNUMBER_OF_UE_MAX_NB_IoT=16") - # Simulation library ########################## set (SIMUSRC diff --git a/openair1/PHY/defs_L1_NB_IoT.h b/openair1/PHY/defs_L1_NB_IoT.h index aba1ffb255..97f243fae8 100644 --- a/openair1/PHY/defs_L1_NB_IoT.h +++ b/openair1/PHY/defs_L1_NB_IoT.h @@ -512,20 +512,20 @@ typedef struct PHY_VARS_eNB_NB_IoT_s { NB_IoT_DL_FRAME_PARMS frame_parms; PHY_MEASUREMENTS_eNB_NB_IoT measurements[NUMBER_OF_eNB_SECTORS_MAX_NB_IoT]; /// Measurement variables NB_IoT_eNB_COMMON common_vars; - NB_IoT_eNB_SRS srs_vars[NUMBER_OF_UE_MAX_NB_IoT]; + NB_IoT_eNB_SRS srs_vars[NUMBER_OF_UE_MAX]; NB_IoT_eNB_PBCH pbch; - NB_IoT_eNB_PUSCH *pusch_vars[NUMBER_OF_UE_MAX_NB_IoT]; + NB_IoT_eNB_PUSCH *pusch_vars[NUMBER_OF_UE_MAX]; NB_IoT_eNB_PRACH prach_vars; - //LTE_eNB_DLSCH_t *dlsch[NUMBER_OF_UE_MAX_NB_IoT][2]; // Nusers times two spatial streams - NB_IoT_eNB_NULSCH_t *ulsch[NUMBER_OF_UE_MAX_NB_IoT+1]; // Nusers + number of RA (the ulsch[0] contains RAR) + //LTE_eNB_DLSCH_t *dlsch[NUMBER_OF_UE_MAX][2]; // Nusers times two spatial streams + NB_IoT_eNB_NULSCH_t *ulsch[NUMBER_OF_UE_MAX+1]; // Nusers + number of RA (the ulsch[0] contains RAR) //LTE_eNB_DLSCH_t *dlsch_SI,*dlsch_ra; //LTE_eNB_DLSCH_t *dlsch_MCH; - NB_IoT_eNB_UE_stats UE_stats[NUMBER_OF_UE_MAX_NB_IoT]; - //LTE_eNB_UE_stats *UE_stats_ptr[NUMBER_OF_UE_MAX_NB_IoT]; + NB_IoT_eNB_UE_stats UE_stats[NUMBER_OF_UE_MAX]; + //LTE_eNB_UE_stats *UE_stats_ptr[NUMBER_OF_UE_MAX]; /// cell-specific reference symbols uint32_t lte_gold_table_NB_IoT[20][2][14]; /// UE-specific reference symbols (p=5), TM 7 - uint32_t lte_gold_uespec_port5_table[NUMBER_OF_UE_MAX_NB_IoT][20][38]; + uint32_t lte_gold_uespec_port5_table[NUMBER_OF_UE_MAX][20][38]; /// UE-specific reference symbols (p=7...14), TM 8/9/10 uint32_t lte_gold_uespec_table[2][20][2][21]; /// mbsfn reference symbols @@ -539,7 +539,7 @@ typedef struct PHY_VARS_eNB_NB_IoT_s { /// char eNB_generate_rar; /// Indicator set to 0 after first SR - uint8_t first_sr[NUMBER_OF_UE_MAX_NB_IoT]; + uint8_t first_sr[NUMBER_OF_UE_MAX]; uint32_t max_peak_val; /// @@ -549,7 +549,7 @@ typedef struct PHY_VARS_eNB_NB_IoT_s { /// N0 (used for abstraction) double N0; /// - unsigned char first_run_timing_advance[NUMBER_OF_UE_MAX_NB_IoT]; + unsigned char first_run_timing_advance[NUMBER_OF_UE_MAX]; unsigned char first_run_I0_measurements; unsigned char cooperation_flag; // for cooperative communication @@ -575,37 +575,37 @@ typedef struct PHY_VARS_eNB_NB_IoT_s { DCI_ALLOC_NB_IoT_t dci_alloc[2][NUM_DCI_MAX_NB_IoT]; // dci_alloc from even/odd subframes ///////////// // PDSCH Variables - PDSCH_CONFIG_DEDICATED_NB_IoT pdsch_config_dedicated[NUMBER_OF_UE_MAX_NB_IoT]; + PDSCH_CONFIG_DEDICATED_NB_IoT pdsch_config_dedicated[NUMBER_OF_UE_MAX]; // PUSCH Variables - PUSCH_CONFIG_DEDICATED_NB_IoT pusch_config_dedicated[NUMBER_OF_UE_MAX_NB_IoT]; + PUSCH_CONFIG_DEDICATED_NB_IoT pusch_config_dedicated[NUMBER_OF_UE_MAX]; // PUCCH variables - PUCCH_CONFIG_DEDICATED_NB_IoT pucch_config_dedicated[NUMBER_OF_UE_MAX_NB_IoT]; + PUCCH_CONFIG_DEDICATED_NB_IoT pucch_config_dedicated[NUMBER_OF_UE_MAX]; // UL-POWER-Control - UL_POWER_CONTROL_DEDICATED_NB_IoT ul_power_control_dedicated[NUMBER_OF_UE_MAX_NB_IoT]; + UL_POWER_CONTROL_DEDICATED_NB_IoT ul_power_control_dedicated[NUMBER_OF_UE_MAX]; // TPC - TPC_PDCCH_CONFIG_NB_IoT tpc_pdcch_config_pucch[NUMBER_OF_UE_MAX_NB_IoT]; + TPC_PDCCH_CONFIG_NB_IoT tpc_pdcch_config_pucch[NUMBER_OF_UE_MAX]; /// - TPC_PDCCH_CONFIG_NB_IoT tpc_pdcch_config_pusch[NUMBER_OF_UE_MAX_NB_IoT]; + TPC_PDCCH_CONFIG_NB_IoT tpc_pdcch_config_pusch[NUMBER_OF_UE_MAX]; // CQI reporting - CQI_REPORT_CONFIG_NB_IoT cqi_report_config[NUMBER_OF_UE_MAX_NB_IoT]; + CQI_REPORT_CONFIG_NB_IoT cqi_report_config[NUMBER_OF_UE_MAX]; // SRS Variables - SOUNDINGRS_UL_CONFIG_DEDICATED_NB_IoT soundingrs_ul_config_dedicated[NUMBER_OF_UE_MAX_NB_IoT]; + SOUNDINGRS_UL_CONFIG_DEDICATED_NB_IoT soundingrs_ul_config_dedicated[NUMBER_OF_UE_MAX]; /// uint8_t ncs_cell[20][7]; // Scheduling Request Config - SCHEDULING_REQUEST_CONFIG_NB_IoT scheduling_request_config[NUMBER_OF_UE_MAX_NB_IoT]; + SCHEDULING_REQUEST_CONFIG_NB_IoT scheduling_request_config[NUMBER_OF_UE_MAX]; // Transmission mode per UE - uint8_t transmission_mode[NUMBER_OF_UE_MAX_NB_IoT]; + uint8_t transmission_mode[NUMBER_OF_UE_MAX]; /// cba_last successful reception for each group, used for collision detection uint8_t cba_last_reception[4]; // Pointers for active physicalConfigDedicated to be applied in current subframe - struct PhysicalConfigDedicated *physicalConfigDedicated[NUMBER_OF_UE_MAX_NB_IoT]; + struct PhysicalConfigDedicated *physicalConfigDedicated[NUMBER_OF_UE_MAX]; //Pointers for actve physicalConfigDedicated for NB-IoT to be applied in current subframe - struct PhysicalConfigDedicated_NB_r13 *phy_config_dedicated_NB_IoT[NUMBER_OF_UE_MAX_NB_IoT]; + struct PhysicalConfigDedicated_NB_r13 *phy_config_dedicated_NB_IoT[NUMBER_OF_UE_MAX]; /// uint32_t rb_mask_ul[4]; /// Information regarding TM5 - MU_MIMO_mode_NB_IoT mu_mimo_mode[NUMBER_OF_UE_MAX_NB_IoT]; + MU_MIMO_mode_NB_IoT mu_mimo_mode[NUMBER_OF_UE_MAX]; /// target_ue_dl_mcs : only for debug purposes uint32_t target_ue_dl_mcs; /// target_ue_ul_mcs : only for debug purposes @@ -660,16 +660,16 @@ typedef struct PHY_VARS_eNB_NB_IoT_s { time_stats_t ulsch_tc_ext_stats; time_stats_t ulsch_tc_intl1_stats; time_stats_t ulsch_tc_intl2_stats; - int32_t pucch1_stats_cnt[NUMBER_OF_UE_MAX_NB_IoT][10]; - int32_t pucch1_stats[NUMBER_OF_UE_MAX_NB_IoT][10*1024]; - int32_t pucch1_stats_thres[NUMBER_OF_UE_MAX_NB_IoT][10*1024]; - int32_t pucch1ab_stats_cnt[NUMBER_OF_UE_MAX_NB_IoT][10]; - int32_t pucch1ab_stats[NUMBER_OF_UE_MAX_NB_IoT][2*10*1024]; - int32_t pusch_stats_rb[NUMBER_OF_UE_MAX_NB_IoT][10240]; - int32_t pusch_stats_round[NUMBER_OF_UE_MAX_NB_IoT][10240]; - int32_t pusch_stats_mcs[NUMBER_OF_UE_MAX_NB_IoT][10240]; - int32_t pusch_stats_bsr[NUMBER_OF_UE_MAX_NB_IoT][10240]; - int32_t pusch_stats_BO[NUMBER_OF_UE_MAX_NB_IoT][10240]; + int32_t pucch1_stats_cnt[NUMBER_OF_UE_MAX][10]; + int32_t pucch1_stats[NUMBER_OF_UE_MAX][10*1024]; + int32_t pucch1_stats_thres[NUMBER_OF_UE_MAX][10*1024]; + int32_t pucch1ab_stats_cnt[NUMBER_OF_UE_MAX][10]; + int32_t pucch1ab_stats[NUMBER_OF_UE_MAX][2*10*1024]; + int32_t pusch_stats_rb[NUMBER_OF_UE_MAX][10240]; + int32_t pusch_stats_round[NUMBER_OF_UE_MAX][10240]; + int32_t pusch_stats_mcs[NUMBER_OF_UE_MAX][10240]; + int32_t pusch_stats_bsr[NUMBER_OF_UE_MAX][10240]; + int32_t pusch_stats_BO[NUMBER_OF_UE_MAX][10240]; /// RF and Interface devices per CC openair0_device rfdevice; @@ -682,7 +682,7 @@ typedef struct PHY_VARS_eNB_NB_IoT_s { //------------------------ /* - * NUMBER_OF_UE_MAX_NB_IoT maybe in the future should be dynamic because could be very large and the memory may explode + * NUMBER_OF_UE_MAX maybe in the future should be dynamic because could be very large and the memory may explode * (is almost the indication of the number of UE context that we are storing at PHY layer) * * reasoning: the following data structure (ndlsch, nulsch ecc..) are used to store the context that should be transmitted in at least n+4 subframe later @@ -710,11 +710,10 @@ typedef struct PHY_VARS_eNB_NB_IoT_s { * */ - //TODO: check what should be NUMBER_OF_UE_MAX_NB_IoT value NB_IoT_eNB_NPBCH_t *npbch; - NB_IoT_eNB_NPDCCH_t *npdcch[NUMBER_OF_UE_MAX_NB_IoT]; - NB_IoT_eNB_NDLSCH_t *ndlsch[NUMBER_OF_UE_MAX_NB_IoT][2]; - NB_IoT_eNB_NULSCH_t *nulsch[NUMBER_OF_UE_MAX_NB_IoT+1]; //nulsch[0] contains the RAR + NB_IoT_eNB_NPDCCH_t *npdcch[NUMBER_OF_UE_MAX]; + NB_IoT_eNB_NDLSCH_t *ndlsch[NUMBER_OF_UE_MAX][2]; + NB_IoT_eNB_NULSCH_t *nulsch[NUMBER_OF_UE_MAX+1]; //nulsch[0] contains the RAR NB_IoT_eNB_NDLSCH_t *ndlsch_SI,*ndlsch_ra, *ndlsch_SIB1; NB_IoT_DL_FRAME_PARMS frame_parms_NB_IoT; diff --git a/openair1/PHY/impl_defs_top_NB_IoT.h b/openair1/PHY/impl_defs_top_NB_IoT.h index f9560cb228..8b3360c087 100644 --- a/openair1/PHY/impl_defs_top_NB_IoT.h +++ b/openair1/PHY/impl_defs_top_NB_IoT.h @@ -158,30 +158,30 @@ typedef struct { short n0_subband_power_tot_dBm[100]; // eNB measurements (per user) //! estimated received spatial signal power (linear) - unsigned int rx_spatial_power[NUMBER_OF_UE_MAX_NB_IoT][2][2]; + unsigned int rx_spatial_power[NUMBER_OF_UE_MAX][2][2]; //! estimated received spatial signal power (dB) - unsigned short rx_spatial_power_dB[NUMBER_OF_UE_MAX_NB_IoT][2][2]; + unsigned short rx_spatial_power_dB[NUMBER_OF_UE_MAX][2][2]; //! estimated rssi (dBm) - short rx_rssi_dBm[NUMBER_OF_UE_MAX_NB_IoT]; + short rx_rssi_dBm[NUMBER_OF_UE_MAX]; //! estimated correlation (wideband linear) between spatial channels (computed in dlsch_demodulation) - int rx_correlation[NUMBER_OF_UE_MAX_NB_IoT][2]; + int rx_correlation[NUMBER_OF_UE_MAX][2]; //! estimated correlation (wideband dB) between spatial channels (computed in dlsch_demodulation) - int rx_correlation_dB[NUMBER_OF_UE_MAX_NB_IoT][2]; + int rx_correlation_dB[NUMBER_OF_UE_MAX][2]; /// Wideband CQI (= SINR) - int wideband_cqi[NUMBER_OF_UE_MAX_NB_IoT][NB_ANTENNAS_RX]; + int wideband_cqi[NUMBER_OF_UE_MAX][NB_ANTENNAS_RX]; /// Wideband CQI in dB (= SINR dB) - int wideband_cqi_dB[NUMBER_OF_UE_MAX_NB_IoT][NB_ANTENNAS_RX]; + int wideband_cqi_dB[NUMBER_OF_UE_MAX][NB_ANTENNAS_RX]; /// Wideband CQI (sum of all RX antennas, in dB) - char wideband_cqi_tot[NUMBER_OF_UE_MAX_NB_IoT]; + char wideband_cqi_tot[NUMBER_OF_UE_MAX]; /// Subband CQI per RX antenna and RB (= SINR) - int subband_cqi[NUMBER_OF_UE_MAX_NB_IoT][NB_ANTENNAS_RX][100]; + int subband_cqi[NUMBER_OF_UE_MAX][NB_ANTENNAS_RX][100]; /// Total Subband CQI and RB (= SINR) - int subband_cqi_tot[NUMBER_OF_UE_MAX_NB_IoT][100]; + int subband_cqi_tot[NUMBER_OF_UE_MAX][100]; /// Subband CQI in dB and RB (= SINR dB) - int subband_cqi_dB[NUMBER_OF_UE_MAX_NB_IoT][NB_ANTENNAS_RX][100]; + int subband_cqi_dB[NUMBER_OF_UE_MAX][NB_ANTENNAS_RX][100]; /// Total Subband CQI and RB - int subband_cqi_tot_dB[NUMBER_OF_UE_MAX_NB_IoT][100]; + int subband_cqi_tot_dB[NUMBER_OF_UE_MAX][100]; } PHY_MEASUREMENTS_eNB_NB_IoT; From cc094ac73789fd9340bddb190db85b24c85b850f Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 20 Dec 2024 00:03:20 +0100 Subject: [PATCH 821/964] XNAP asn.1 cmake: ber_decoder.h is not created XNAP is asn1c compiled with -no-gen-BER. Correspondingly, no ber_decoder.h file is created. However, when running cmake followed by ninja, it notices the absence of this file: ninja explain: output openair2/XNAP/MESSAGES/ber_decoder.h doesn't exist which triggers a complete rebuild of XNAP ASN.1. Without this file, the targets are not marked as dirty. --- openair2/XNAP/MESSAGES/ASN1/xnap_R16.2.0.cmake | 1 - 1 file changed, 1 deletion(-) diff --git a/openair2/XNAP/MESSAGES/ASN1/xnap_R16.2.0.cmake b/openair2/XNAP/MESSAGES/ASN1/xnap_R16.2.0.cmake index 3cc71e8415..cb0c762983 100644 --- a/openair2/XNAP/MESSAGES/ASN1/xnap_R16.2.0.cmake +++ b/openair2/XNAP/MESSAGES/ASN1/xnap_R16.2.0.cmake @@ -833,7 +833,6 @@ set(xnap_headers asn_SEQUENCE_OF.h asn_SET_OF.h asn_system.h - ber_decoder.h ber_tlv_length.h ber_tlv_tag.h BIT_STRING.h From 4177c6d182692c913525ab227cbabeaa6a5686db Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 25 Jul 2025 14:36:25 +0200 Subject: [PATCH 822/964] Include CMakeLists.txt using add_subdirectory(), simplify --- CMakeLists.txt | 2 -- openair1/PHY/CODING/CMakeLists.txt | 1 + openair1/PHY/CODING/nrLDPC_decoder/CMakeLists.txt | 1 + .../PHY/CODING/nrLDPC_decoder/nrLDPC_tools/CMakeLists.txt | 8 ++++---- 4 files changed, 6 insertions(+), 6 deletions(-) create mode 100644 openair1/PHY/CODING/nrLDPC_decoder/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index fa7510a9f1..6d16902308 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2105,8 +2105,6 @@ if (${T_TRACER}) endforeach(i) endif (${T_TRACER}) -include(${OPENAIR1_DIR}/PHY/CODING/nrLDPC_decoder/nrLDPC_tools/CMakeLists.txt) - set(ENABLE_TESTS OFF CACHE STRING "Activate build of tests") set_property(CACHE ENABLE_TESTS PROPERTY TYPE BOOL) set(ENABLE_PHYSIM_TESTS OFF CACHE STRING "Activate build of physim tests") diff --git a/openair1/PHY/CODING/CMakeLists.txt b/openair1/PHY/CODING/CMakeLists.txt index 7e07f8f2dc..4681487c85 100644 --- a/openair1/PHY/CODING/CMakeLists.txt +++ b/openair1/PHY/CODING/CMakeLists.txt @@ -68,3 +68,4 @@ if (ENABLE_LDPC_CUDA) endif() add_subdirectory(nrLDPC_coding) +add_subdirectory(nrLDPC_decoder) diff --git a/openair1/PHY/CODING/nrLDPC_decoder/CMakeLists.txt b/openair1/PHY/CODING/nrLDPC_decoder/CMakeLists.txt new file mode 100644 index 0000000000..1734260e68 --- /dev/null +++ b/openair1/PHY/CODING/nrLDPC_decoder/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(nrLDPC_tools) diff --git a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_tools/CMakeLists.txt b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_tools/CMakeLists.txt index 26ef39408f..4b8dfcb446 100644 --- a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_tools/CMakeLists.txt +++ b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_tools/CMakeLists.txt @@ -1,7 +1,7 @@ -add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/generator_bnProc ldpc/generator_bnProc) -add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/generator_bnProc_avx512 ldpc/generator_bnProc_avx512) -add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/generator_cnProc ldpc/generator_cnProc) -add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/generator_cnProc_avx512 ldpc/generator_cnProc_avx512) +add_subdirectory(generator_bnProc ldpc/generator_bnProc) +add_subdirectory(generator_bnProc_avx512 ldpc/generator_bnProc_avx512) +add_subdirectory(generator_cnProc ldpc/generator_cnProc) +add_subdirectory(generator_cnProc_avx512 ldpc/generator_cnProc_avx512) # custom target to build all generators add_custom_target(ldpc_generators) From 46ed4ac36d300eb8d1d9c337192431c88d97afbc Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 11 Sep 2025 06:49:45 +0200 Subject: [PATCH 823/964] Update comment to reference right target --- common/utils/T/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/utils/T/CMakeLists.txt b/common/utils/T/CMakeLists.txt index 5425a564b1..8f58871adc 100644 --- a/common/utils/T/CMakeLists.txt +++ b/common/utils/T/CMakeLists.txt @@ -47,7 +47,7 @@ add_custom_target(generate_T DEPENDS T_IDs.h check_vcd) # even if T is off, we need the headers as many targets depend on it # for this, create an INTERFACE (header-only) library T_headers. To ensure the # headers have really been created, we make this headers library explicitly -# depend on the generated headers. +# depend on the generate_T target. add_library(T_headers INTERFACE) add_dependencies(T_headers T_IDs.h generate_T) target_include_directories(T_headers INTERFACE ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) From 72371ba10b53013dd5f38fbe59ece9dbbaec6758 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 11 Sep 2025 06:50:09 +0200 Subject: [PATCH 824/964] Remove unnecessary comment --- openair1/PHY/CODING/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/openair1/PHY/CODING/CMakeLists.txt b/openair1/PHY/CODING/CMakeLists.txt index 4681487c85..f696c71213 100644 --- a/openair1/PHY/CODING/CMakeLists.txt +++ b/openair1/PHY/CODING/CMakeLists.txt @@ -7,7 +7,6 @@ add_library(coding MODULE 3gpplte_turbo_decoder.c ) set_target_properties(coding PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) -#ensure that the T header files are generated before targets depending on them target_link_libraries(coding PRIVATE log_headers) add_library(ldpc_orig MODULE From eef092c3188fa457416564015da525cf571417f2 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 11 Sep 2025 10:10:14 +0200 Subject: [PATCH 825/964] Omit JER compilation for NRPPA ASN.1 We don't use JER. This avoids compilation problems, such as: /usr/bin/ld: openair3/NRPPA/MESSAGES/libasn1_nrppa.a(INTEGER_jer.c.o): in function `INTEGER_decode_jer': tmp.MtrwVDhQqY/openair3/NRPPA/MESSAGES/INTEGER_jer.c:186:(.text+0x5b8): undefined reference to `jer_decode_primitive --- openair3/NRPPA/MESSAGES/ASN1/38455.cmake | 14 -------------- openair3/NRPPA/MESSAGES/CMakeLists.txt | 2 +- 2 files changed, 1 insertion(+), 15 deletions(-) diff --git a/openair3/NRPPA/MESSAGES/ASN1/38455.cmake b/openair3/NRPPA/MESSAGES/ASN1/38455.cmake index d81f3db96c..7421d09e06 100644 --- a/openair3/NRPPA/MESSAGES/ASN1/38455.cmake +++ b/openair3/NRPPA/MESSAGES/ASN1/38455.cmake @@ -4,7 +4,6 @@ set(nrppa_source ANY_aper.c ANY_ber.c ANY.c -ANY_jer.c ANY_uper.c ANY_xer.c aper_decoder.c @@ -24,7 +23,6 @@ ber_decoder.c ber_tlv_length.c ber_tlv_tag.c BIT_STRING.c -BIT_STRING_jer.c BIT_STRING_print.c BIT_STRING_rfill.c BIT_STRING_uper.c @@ -33,7 +31,6 @@ constraints.c constr_CHOICE_aper.c constr_CHOICE_ber.c constr_CHOICE.c -constr_CHOICE_jer.c constr_CHOICE_print.c constr_CHOICE_rfill.c constr_CHOICE_uper.c @@ -41,11 +38,9 @@ constr_CHOICE_xer.c constr_SEQUENCE_aper.c constr_SEQUENCE_ber.c constr_SEQUENCE.c -constr_SEQUENCE_jer.c constr_SEQUENCE_OF_aper.c constr_SEQUENCE_OF_ber.c constr_SEQUENCE_OF.c -constr_SEQUENCE_OF_jer.c constr_SEQUENCE_OF_uper.c constr_SEQUENCE_OF_xer.c constr_SEQUENCE_print.c @@ -55,7 +50,6 @@ constr_SEQUENCE_xer.c constr_SET_OF_aper.c constr_SET_OF_ber.c constr_SET_OF.c -constr_SET_OF_jer.c constr_SET_OF_print.c constr_SET_OF_rfill.c constr_SET_OF_uper.c @@ -66,21 +60,17 @@ GraphicString.c INTEGER_aper.c INTEGER_ber.c INTEGER.c -INTEGER_jer.c INTEGER_print.c INTEGER_rfill.c INTEGER_uper.c INTEGER_xer.c -jer_encoder.c NativeEnumerated_aper.c NativeEnumerated.c -NativeEnumerated_jer.c NativeEnumerated_uper.c NativeEnumerated_xer.c NativeInteger_aper.c NativeInteger_ber.c NativeInteger.c -NativeInteger_jer.c NativeInteger_print.c NativeInteger_rfill.c NativeInteger_uper.c @@ -406,21 +396,18 @@ NRPPA_WLAN-RSSI.c NULL_aper.c NULL_ber.c NULL.c -NULL_jer.c NULL_print.c NULL_rfill.c NULL_uper.c NULL_xer.c ObjectDescriptor.c OBJECT_IDENTIFIER.c -OBJECT_IDENTIFIER_jer.c OBJECT_IDENTIFIER_print.c OBJECT_IDENTIFIER_rfill.c OBJECT_IDENTIFIER_xer.c OCTET_STRING_aper.c OCTET_STRING_ber.c OCTET_STRING.c -OCTET_STRING_jer.c OCTET_STRING_print.c OCTET_STRING_rfill.c OCTET_STRING_uper.c @@ -473,7 +460,6 @@ constr_TYPE.h der_encoder.h GraphicString.h INTEGER.h -jer_encoder.h NativeEnumerated.h NativeInteger.h NRPPA_AbortTransmission.h diff --git a/openair3/NRPPA/MESSAGES/CMakeLists.txt b/openair3/NRPPA/MESSAGES/CMakeLists.txt index 997fb70a9c..6581932024 100644 --- a/openair3/NRPPA/MESSAGES/CMakeLists.txt +++ b/openair3/NRPPA/MESSAGES/CMakeLists.txt @@ -12,7 +12,7 @@ include(ASN1/38455.cmake) run_asn1c(${CMAKE_CURRENT_SOURCE_DIR}/${NRPPA_GRAMMAR} "NRPPA_" OUTPUT ${nrppa_source} ${nrppa_headers} - OPTIONS -gen-APER -gen-UPER -no-gen-OER -fcompound-names -no-gen-example -findirect-choice -fno-include-deps + OPTIONS -gen-APER -gen-UPER -no-gen-OER -no-gen-JER -fcompound-names -no-gen-example -findirect-choice -fno-include-deps COMMENT "NRPPA source files" ) From 66c3b7d192d307b18326bf92208d6e42b0682700 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 12 Sep 2025 19:59:28 +0200 Subject: [PATCH 826/964] Break coding_defs.h dependency on logging module coding_defs.h included defs_common.h, which pulls in many dependencies, e.g., the logging module, which pulls in T. However, it does not use anything of this. So remove, and include stdbool.h instead (because bool is used in coding_defs.h. nr_polar_defs.h relied on some includes done in coding_defs. Use includes for pthreads and SIMD to define types that are used in nr_polar_defs.h. --- openair1/PHY/CODING/3gpplte.c | 1 + openair1/PHY/CODING/coding_defs.h | 5 +---- openair1/PHY/CODING/nrPolar_tools/nr_crc_byte.c | 1 + openair1/PHY/CODING/nrPolar_tools/nr_polar_defs.h | 2 ++ 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/openair1/PHY/CODING/3gpplte.c b/openair1/PHY/CODING/3gpplte.c index 3502a1ad56..d3aec284da 100644 --- a/openair1/PHY/CODING/3gpplte.c +++ b/openair1/PHY/CODING/3gpplte.c @@ -30,6 +30,7 @@ #include #include #include "PHY/CODING/coding_defs.h" +#include "common/utils/utils.h" //#define DEBUG_TURBO_ENCODER 1 diff --git a/openair1/PHY/CODING/coding_defs.h b/openair1/PHY/CODING/coding_defs.h index 3c91892d8c..d6e1b780f7 100644 --- a/openair1/PHY/CODING/coding_defs.h +++ b/openair1/PHY/CODING/coding_defs.h @@ -28,7 +28,7 @@ #define __CODING_DEFS__H__ #include -#include +#include #define CRC24_A 0 #define CRC24_B 1 @@ -455,8 +455,5 @@ int32_t nr_segmentation(unsigned char *input_buffer, */ int nr_get_R_ldpc_decoder(int rvidx, int E, int BG, int Z, int *llrLen, int round); -decoder_if_t phy_threegpplte_turbo_decoder; -decoder_if_t phy_threegpplte_turbo_decoder8; -decoder_if_t phy_threegpplte_turbo_decoder16; /** @} */ #endif diff --git a/openair1/PHY/CODING/nrPolar_tools/nr_crc_byte.c b/openair1/PHY/CODING/nrPolar_tools/nr_crc_byte.c index 58764151c4..2bc3c8b517 100644 --- a/openair1/PHY/CODING/nrPolar_tools/nr_crc_byte.c +++ b/openair1/PHY/CODING/nrPolar_tools/nr_crc_byte.c @@ -20,6 +20,7 @@ */ #include "PHY/CODING/nrPolar_tools/nr_polar_defs.h" +#include "common/utils/utils.h" // ----- Old implementation ---- const uint8_t **crc24c_generator_matrix(uint16_t payloadSizeBits) diff --git a/openair1/PHY/CODING/nrPolar_tools/nr_polar_defs.h b/openair1/PHY/CODING/nrPolar_tools/nr_polar_defs.h index 803854c23b..519f23175c 100644 --- a/openair1/PHY/CODING/nrPolar_tools/nr_polar_defs.h +++ b/openair1/PHY/CODING/nrPolar_tools/nr_polar_defs.h @@ -38,11 +38,13 @@ #include #include #include +#include #include "PHY/CODING/nrPolar_tools/nr_polar_dci_defs.h" #include "PHY/CODING/nrPolar_tools/nr_polar_uci_defs.h" #include "PHY/CODING/nrPolar_tools/nr_polar_pbch_defs.h" #include "PHY/CODING/coding_defs.h" +#include "PHY/sse_intrin.h" // #include "SIMULATION/TOOLS/sim.h" #define NR_POLAR_DECODER_LISTSIZE 8 // uint8_t From fd37fba9b735c6c68ff367817b56fdcd03df34b3 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Tue, 8 Oct 2024 10:14:32 +0200 Subject: [PATCH 827/964] Cleanup of libraries/executables from T loop These libraries/executables are not defined in OAI. --- CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6d16902308..2f576a1919 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2087,17 +2087,17 @@ if (${T_TRACER}) nr-uesoftmodem dlsim dlsim_tm4 dlsim_tm7 ulsim pbchsim scansim mbmssim pdcchsim pucchsim prachsim syncsim nr_ulsim nr_dlsim nr_dlschsim nr_pbchsim nr_pucchsim - nr_ulschsim ldpctest polartest smallblocktest cu_test du_test + nr_ulschsim ldpctest polartest smallblocktest #all "add_library" definitions ITTI lte_rrc nr_rrc s1ap x2ap m2ap m3ap f1ap params_libconfig oai_usrpdevif oai_bladerfdevif oai_lmssdrdevif oai_iqplayer - oai_eth_transpro oai_mobipass HASHTABLE UTIL OMG_SUMO - SECURITY SCHED_LIB SCHED_NR_LIB SCHED_RU_LIB SCHED_UE_LIB SCHED_NR_UE_LIB default_sched remote_sched RAL + oai_eth_transpro HASHTABLE UTIL + SECURITY SCHED_LIB SCHED_NR_LIB SCHED_RU_LIB SCHED_UE_LIB SCHED_NR_UE_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_VNF_LIB NFAPI_USER_LIB MISC_NFAPI_LTE_LIB MISC_NFAPI_NR_LIB PHY_COMMON PHY PHY_UE PHY_NR PHY_NR_COMMON PHY_NR_UE PHY_RU L2 L2_LTE L2_NR L2_LTE_NR L2_UE NR_L2_UE MAC_NR_COMMON MAC_UE_NR ngap - CN_UTILS GTPV1U SCTP_CLIENT MME_APP LIB_NAS_UE NB_IoT SIMU OPENAIR0_LIB + GTPV1U SCTP_CLIENT MME_APP LIB_NAS_UE SIMU dfts config_internals nr_common crc_byte) if (TARGET ${i}) add_dependencies(${i} generate_T) From 197705f232e587b97ad959224e8703457fd80063 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 16 Sep 2025 08:59:31 +0200 Subject: [PATCH 828/964] Provide T headers via log.h It seems that many compilation units include T.h through the config module (as evidenced when taking out T.h from config_load_configmodule.h). This is strange, because T.h is only used in the logging headers. Hence, move it to there, where it is used. --- common/config/config_load_configmodule.h | 1 - common/utils/LOG/log.h | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/common/config/config_load_configmodule.h b/common/config/config_load_configmodule.h index 3ec27d456f..d5f87d0f8b 100644 --- a/common/config/config_load_configmodule.h +++ b/common/config/config_load_configmodule.h @@ -39,7 +39,6 @@ #include #include #include "common/config/config_paramdesc.h" -#include "common/utils/T/T.h" #define CONFIG_MAX_OOPT_PARAMS 10 // maximum number of parameters in the -O option (-O :P1:P2... #define CONFIG_MAX_ALLOCATEDPTRS 32768 // maximum number of parameters that can be dynamicaly allocated in the config module diff --git a/common/utils/LOG/log.h b/common/utils/LOG/log.h index 7b9b570a06..1f7474253c 100644 --- a/common/utils/LOG/log.h +++ b/common/utils/LOG/log.h @@ -52,6 +52,7 @@ #endif #include #include +#include "common/utils/T/T.h" #if ENABLE_LTTNG #include "lttng-log.h" #endif From 2889e55cd8d4671017e689adf3036bcde27bc087 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 11 Sep 2025 06:49:31 +0200 Subject: [PATCH 829/964] Remove redundant target_include_directories() from LOG The same is achieved by including log_headers. --- common/utils/LOG/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/common/utils/LOG/CMakeLists.txt b/common/utils/LOG/CMakeLists.txt index 6c4527f760..ade7f76dea 100644 --- a/common/utils/LOG/CMakeLists.txt +++ b/common/utils/LOG/CMakeLists.txt @@ -10,7 +10,6 @@ else() message(STATUS "LTTNG support disabled") endif() add_library(LOG ${log_sources}) -target_include_directories(LOG PUBLIC .) target_link_libraries(LOG PRIVATE CONFIG_LIB) target_link_libraries(LOG PUBLIC log_headers) if (ENABLE_LTTNG) From 1ecb03f5f81dc8ed4ee831e862ebf45bf88996ac Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 15 Sep 2025 09:02:41 +0200 Subject: [PATCH 830/964] Make BladeRF compile Fix variable name. See also: 74662975683d ("move command line sample offset [...] at top level [...]") --- radio/BLADERF/bladerf_lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radio/BLADERF/bladerf_lib.c b/radio/BLADERF/bladerf_lib.c index e834f8377e..178fc2fff2 100644 --- a/radio/BLADERF/bladerf_lib.c +++ b/radio/BLADERF/bladerf_lib.c @@ -138,7 +138,7 @@ static int trx_brf_write(openair0_device *device, brf_state_t *brf = (brf_state_t*)device->priv; /* BRF has only 1 rx/tx chaine : is it correct? */ int16_t *samples = (int16_t*)buff[0]; - timestamp -= device->openair0_cfg->command_line_sample_advance - device->openair0_cfg->tx_sample_advance; + ptimestamp -= device->openair0_cfg->command_line_sample_advance - device->openair0_cfg->tx_sample_advance; //memset(&brf->meta_tx, 0, sizeof(brf->meta_tx)); // When BLADERF_META_FLAG_TX_NOW is used the timestamp is not used, so one can't schedule a tx if (brf->meta_tx.flags == 0 ) From 2a5ed87589299dca7e9ca93cb86d068a10419672 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 25 Apr 2024 09:50:11 +0200 Subject: [PATCH 831/964] E2 Agent uses CONFIG_LIB for configuration Since E2 agent uses the config library, include it directly. This also makes the dependency on T obsolete, because - it is the logging headers that are needed, and - the T dependency is fulfilled through the log_headers. --- openair2/E2AP/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair2/E2AP/CMakeLists.txt b/openair2/E2AP/CMakeLists.txt index d86dafb0b9..8cbaae73db 100644 --- a/openair2/E2AP/CMakeLists.txt +++ b/openair2/E2AP/CMakeLists.txt @@ -129,4 +129,4 @@ add_subdirectory(flexric/src/util) add_subdirectory(RAN_FUNCTION) add_library(e2_agent_arg STATIC e2_agent_arg.c) -add_dependencies(e2_agent_arg generate_T) +target_link_libraries(e2_agent_arg PRIVATE CONFIG_LIB log_headers) From 19813283fbb4dc507d005ce3b6fb8bb628252f0c Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 11 Sep 2025 09:30:08 +0200 Subject: [PATCH 832/964] Avoid T error on radio libraries These libraries have an (indirect) dependency on T, either by using the logging module (which in turn depends on T), or through other includes. The easiest is to depend on the logging module, which will fulfil also the T dependency. It would equally be feasible to use the utils target (which in turn depends on log_headers), but this would necessitate to compile, and does not seem to be necessary. --- CMakeLists.txt | 7 +++---- radio/AW2SORI/CMakeLists.txt | 2 +- radio/BLADERF/CMakeLists.txt | 2 +- radio/ETHERNET/CMakeLists.txt | 2 +- radio/LMSSDR/CMakeLists.txt | 2 +- radio/USRP/CMakeLists.txt | 2 +- radio/emulator/CMakeLists.txt | 3 +-- radio/fhi_72/CMakeLists.txt | 3 ++- radio/fhi_72/mplane/CMakeLists.txt | 2 +- radio/rfsimulator/CMakeLists.txt | 2 +- radio/vrtsim/CMakeLists.txt | 4 ++-- 11 files changed, 15 insertions(+), 16 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2f576a1919..30c8ee06a5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1678,9 +1678,8 @@ include_directories("${NFAPI_DIR}/nfapi/inc") include_directories("${NFAPI_DIR}/sim_common/inc") include_directories("${NFAPI_DIR}/pnf_sim/inc") -add_library(oai_iqplayer MODULE - ${OPENAIR_DIR}/radio/iqplayer/iqplayer_lib.c - ) +add_library(oai_iqplayer MODULE ${OPENAIR_DIR}/radio/iqplayer/iqplayer_lib.c) +target_link_libraries(oai_iqplayer PRIVATE log_headers) ################################# # add executables for operation @@ -2090,7 +2089,7 @@ if (${T_TRACER}) nr_ulschsim ldpctest polartest smallblocktest #all "add_library" definitions ITTI lte_rrc nr_rrc s1ap x2ap m2ap m3ap f1ap - params_libconfig oai_usrpdevif oai_bladerfdevif oai_lmssdrdevif oai_iqplayer + params_libconfig oai_eth_transpro HASHTABLE UTIL SECURITY SCHED_LIB SCHED_NR_LIB SCHED_RU_LIB SCHED_UE_LIB SCHED_NR_UE_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_VNF_LIB NFAPI_USER_LIB diff --git a/radio/AW2SORI/CMakeLists.txt b/radio/AW2SORI/CMakeLists.txt index e02d8a2721..134ab27b81 100644 --- a/radio/AW2SORI/CMakeLists.txt +++ b/radio/AW2SORI/CMakeLists.txt @@ -9,7 +9,7 @@ endif() add_library(aw2sori_transpro MODULE oaiori.c) target_compile_options(aw2sori_transpro PRIVATE -shared -fPIC -msse4 -g -ggdb -DLITE_COMPILATION) -target_link_libraries(aw2sori_transpro PRIVATE ori oai_eth_transpro) +target_link_libraries(aw2sori_transpro PRIVATE ori oai_eth_transpro log_headers) set_target_properties(aw2sori_transpro PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) add_custom_command(TARGET aw2sori_transpro POST_BUILD COMMAND ${CMAKE_COMMAND} -E create_symlink libaw2sori_transpro.so libthirdparty_transpro.so diff --git a/radio/BLADERF/CMakeLists.txt b/radio/BLADERF/CMakeLists.txt index 5504eb4051..063c8cb21e 100644 --- a/radio/BLADERF/CMakeLists.txt +++ b/radio/BLADERF/CMakeLists.txt @@ -1,7 +1,7 @@ pkg_check_modules(bladeRF REQUIRED libbladeRF) add_library(oai_bladerfdevif MODULE bladerf_lib.c) target_link_libraries(oai_bladerfdevif PRIVATE bladeRF) -target_link_libraries(oai_bladerfdevif PRIVATE UTIL) +target_link_libraries(oai_bladerfdevif PRIVATE log_headers) set_target_properties(oai_bladerfdevif PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) add_custom_command(TARGET oai_bladerfdevif POST_BUILD COMMAND ${CMAKE_COMMAND} -E create_symlink liboai_bladerfdevif.so liboai_device.so diff --git a/radio/ETHERNET/CMakeLists.txt b/radio/ETHERNET/CMakeLists.txt index 8c6590c6e9..3a9b9dc5cb 100644 --- a/radio/ETHERNET/CMakeLists.txt +++ b/radio/ETHERNET/CMakeLists.txt @@ -3,7 +3,7 @@ add_library(oai_eth_transpro MODULE eth_udp.c eth_raw.c ) -target_link_libraries(oai_eth_transpro PRIVATE ${T_LIB}) +target_link_libraries(oai_eth_transpro PRIVATE log_headers) target_include_directories(oai_eth_transpro PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) set_target_properties(oai_eth_transpro PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) add_custom_command(TARGET oai_eth_transpro POST_BUILD diff --git a/radio/LMSSDR/CMakeLists.txt b/radio/LMSSDR/CMakeLists.txt index 2df5c9a01f..bfe2a7f99f 100644 --- a/radio/LMSSDR/CMakeLists.txt +++ b/radio/LMSSDR/CMakeLists.txt @@ -1,7 +1,7 @@ find_package(LimeSuite REQUIRED) add_library(oai_lmssdrdevif MODULE lms_lib.cpp) -target_link_libraries(oai_lmssdrdevif LimeSuite ) +target_link_libraries(oai_lmssdrdevif LimeSuite log_headers) set_target_properties(oai_lmssdrdevif PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) add_custom_command(TARGET oai_lmssdrdevif POST_BUILD COMMAND ${CMAKE_COMMAND} -E create_symlink liboai_lmssdrdevif.so liboai_device.so diff --git a/radio/USRP/CMakeLists.txt b/radio/USRP/CMakeLists.txt index 4e72d140f4..50d95ee7e5 100644 --- a/radio/USRP/CMakeLists.txt +++ b/radio/USRP/CMakeLists.txt @@ -5,7 +5,7 @@ add_library(oai_usrpdevif MODULE usrp_lib.cpp) #target_include_directories(oai_usrpdevif PRIVATE Boost::boost) target_link_libraries(oai_usrpdevif PRIVATE ${UHD_LIBRARIES}) target_include_directories(oai_usrpdevif PRIVATE ${UHD_INCLUDE_DIRS}) -target_link_libraries(oai_usrpdevif PRIVATE UTIL) +target_link_libraries(oai_usrpdevif PRIVATE log_headers) set_target_properties(oai_usrpdevif PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) add_custom_command(TARGET oai_usrpdevif POST_BUILD COMMAND ${CMAKE_COMMAND} -E create_symlink liboai_usrpdevif.so liboai_device.so diff --git a/radio/emulator/CMakeLists.txt b/radio/emulator/CMakeLists.txt index 42b196ee95..983d95986a 100644 --- a/radio/emulator/CMakeLists.txt +++ b/radio/emulator/CMakeLists.txt @@ -1,4 +1,3 @@ add_library(rf_emulator MODULE rf_emulator.c) set_target_properties(rf_emulator PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) -target_link_libraries(rf_emulator PRIVATE noise_device) -add_dependencies(rf_emulator generate_T) +target_link_libraries(rf_emulator PRIVATE noise_device log_headers) diff --git a/radio/fhi_72/CMakeLists.txt b/radio/fhi_72/CMakeLists.txt index 3b0f16d2a4..f2161d06a8 100644 --- a/radio/fhi_72/CMakeLists.txt +++ b/radio/fhi_72/CMakeLists.txt @@ -33,7 +33,8 @@ endif() add_compile_options(-Wno-packed-not-aligned) set_target_properties(oran_fhlib_5g PROPERTIES COMPILE_FLAGS "-fvisibility=hidden -march=native") -target_link_libraries(oran_fhlib_5g PRIVATE xran::xran ${dpdk_LINK_LIBRARIES} ${T_LIB} pthread dl rt m numa) +target_link_libraries(oran_fhlib_5g PRIVATE xran::xran ${dpdk_LINK_LIBRARIES} pthread dl rt m numa) +target_link_libraries(oran_fhlib_5g PRIVATE log_headers) target_include_directories(oran_fhlib_5g PRIVATE ${dpdk_INCLUDE_DIRS}) if (CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64") find_package(armral REQUIRED) diff --git a/radio/fhi_72/mplane/CMakeLists.txt b/radio/fhi_72/mplane/CMakeLists.txt index 65faa6dfbd..26bbb7939e 100644 --- a/radio/fhi_72/mplane/CMakeLists.txt +++ b/radio/fhi_72/mplane/CMakeLists.txt @@ -17,7 +17,7 @@ endif() add_compile_options(-Wno-packed-not-aligned) set_target_properties(oran_fhlib_5g_mplane PROPERTIES COMPILE_FLAGS "-fvisibility=hidden -march=native") -target_link_libraries(oran_fhlib_5g_mplane PRIVATE xran::xran ${dpdk_LINK_LIBRARIES} ${T_LIB} pthread dl rt m numa) +target_link_libraries(oran_fhlib_5g_mplane PRIVATE xran::xran ${dpdk_LINK_LIBRARIES} log_headers pthread dl rt m numa) target_include_directories(oran_fhlib_5g_mplane PRIVATE ${dpdk_INCLUDE_DIRS}) target_compile_definitions(oran_fhlib_5g_mplane PRIVATE OAI_MPLANE) diff --git a/radio/rfsimulator/CMakeLists.txt b/radio/rfsimulator/CMakeLists.txt index efba710bad..ad4d92f108 100644 --- a/radio/rfsimulator/CMakeLists.txt +++ b/radio/rfsimulator/CMakeLists.txt @@ -3,7 +3,7 @@ add_library(rfsimulator MODULE apply_channelmod.c ../../openair1/PHY/TOOLS/signal_energy.c ) -target_link_libraries(rfsimulator PRIVATE SIMU) +target_link_libraries(rfsimulator PRIVATE SIMU log_headers) set_target_properties(rfsimulator PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) add_executable(replay_node stored_node.c) diff --git a/radio/vrtsim/CMakeLists.txt b/radio/vrtsim/CMakeLists.txt index c5ee458666..998b791653 100644 --- a/radio/vrtsim/CMakeLists.txt +++ b/radio/vrtsim/CMakeLists.txt @@ -1,9 +1,9 @@ add_library(noise_device STATIC noise_device.c) +target_link_libraries(noise_device PRIVATE log_headers) add_library(vrtsim MODULE vrtsim.c) set_target_properties(vrtsim PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) -target_link_libraries(vrtsim PRIVATE SIMU shm_td_iq_channel actor noise_device) -add_dependencies(vrtsim generate_T) +target_link_libraries(vrtsim PRIVATE SIMU shm_td_iq_channel actor noise_device log_headers) add_boolean_option(OAI_VRTSIM_TAPS_CLIENT OFF "Enable taps client" ON) if (OAI_VRTSIM_TAPS_CLIENT) From eea7be3977ffa10adf4a58c3d5c0d9903a743432 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 11 Sep 2025 06:51:32 +0200 Subject: [PATCH 833/964] ldpc_segment: avoid T error, use log_headers for logging As parent. --- .../nrLDPC_coding/nrLDPC_coding_segment/CMakeLists.txt | 6 +----- .../CODING/nrLDPC_coding/nrLDPC_coding_xdma/CMakeLists.txt | 7 +------ 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/CMakeLists.txt b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/CMakeLists.txt index f96a2cfaca..8c2811e3a1 100644 --- a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/CMakeLists.txt +++ b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/CMakeLists.txt @@ -3,8 +3,4 @@ add_library(ldpc_segment OBJECT nrLDPC_coding_segment_decoder.c nrLDPC_coding_segment_encoder.c ) - -#ensure that the T header files are generated before targets depending on them -if (${T_TRACER}) - add_dependencies(ldpc_segment generate_T) -endif (${T_TRACER}) +target_link_libraries(ldpc_segment PUBLIC log_headers) diff --git a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_xdma/CMakeLists.txt b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_xdma/CMakeLists.txt index 0325858389..0d8f5571cd 100644 --- a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_xdma/CMakeLists.txt +++ b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_xdma/CMakeLists.txt @@ -16,12 +16,7 @@ if (ENABLE_LDPC_XDMA) ) target_include_directories(ldpc_xdma PRIVATE ../nrLDPC_coding_segment) - #ensure that the T header files are generated before targets depending on them - if (${T_TRACER}) - add_dependencies(ldpc_xdma generate_T) - endif (${T_TRACER}) - - target_link_libraries(ldpc_xdma PRIVATE ldpc_gen_HEADERS) + target_link_libraries(ldpc_xdma PRIVATE ldpc_gen_HEADERS log_headers) set_target_properties(ldpc_xdma PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) add_dependencies(nr-softmodem ldpc_xdma) From 5716d95e978d78dbc2803068c3c6ceabdea9dc71 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 15 Sep 2025 07:46:56 +0000 Subject: [PATCH 834/964] nr_prachsim: remove unused include --- openair1/SIMULATION/NR_PHY/prachsim.c | 1 - 1 file changed, 1 deletion(-) diff --git a/openair1/SIMULATION/NR_PHY/prachsim.c b/openair1/SIMULATION/NR_PHY/prachsim.c index a13918a606..35e242cad3 100644 --- a/openair1/SIMULATION/NR_PHY/prachsim.c +++ b/openair1/SIMULATION/NR_PHY/prachsim.c @@ -64,7 +64,6 @@ #include "nfapi/oai_integration/vendor_ext.h" #include "nfapi_interface.h" #include "nfapi_nr_interface_scf.h" -#include "nr_common.h" #include "time_meas.h" #define NR_PRACH_DEBUG 1 From 1b81c4b09ca98b3b7216a9f603a47376252ce1af Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sat, 13 Sep 2025 06:26:03 +0000 Subject: [PATCH 835/964] RLC only needs headers for logging --- openair2/LAYER2/nr_rlc/CMakeLists.txt | 4 ++-- openair2/LAYER2/nr_rlc/tests/CMakeLists.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/openair2/LAYER2/nr_rlc/CMakeLists.txt b/openair2/LAYER2/nr_rlc/CMakeLists.txt index 953822df10..7473b1d493 100644 --- a/openair2/LAYER2/nr_rlc/CMakeLists.txt +++ b/openair2/LAYER2/nr_rlc/CMakeLists.txt @@ -7,14 +7,14 @@ add_library(nr_rlc_core OBJECT nr_rlc_sdu.c nr_rlc_rx_manager.c) target_include_directories(nr_rlc_core PRIVATE ../../..) -target_link_libraries(nr_rlc_core PRIVATE ${T_LIB}) +target_link_libraries(nr_rlc_core PRIVATE log_headers) add_library(nr_rlc STATIC asn1_utils.c nr_rlc_oai_api.c nr_rlc_ue_manager.c ) # L2_NR: for PDCP -target_link_libraries(nr_rlc PUBLIC pthread f1ap nr_rlc_core UTIL ${T_LIB}) +target_link_libraries(nr_rlc PUBLIC pthread f1ap nr_rlc_core log_headers) target_include_directories(nr_rlc PRIVATE ../../..) target_link_libraries(nr_rlc PRIVATE asn1_lte_rrc asn1_nr_rrc) diff --git a/openair2/LAYER2/nr_rlc/tests/CMakeLists.txt b/openair2/LAYER2/nr_rlc/tests/CMakeLists.txt index c8d365ddf9..68d001ab94 100644 --- a/openair2/LAYER2/nr_rlc/tests/CMakeLists.txt +++ b/openair2/LAYER2/nr_rlc/tests/CMakeLists.txt @@ -1,7 +1,7 @@ foreach(TESTNUM RANGE 1 17) add_executable(nr_rlc_test_${TESTNUM} test.c) - target_link_libraries(nr_rlc_test_${TESTNUM} PRIVATE nr_rlc_core pthread UTIL ${T_LIB} minimal_lib) + target_link_libraries(nr_rlc_test_${TESTNUM} PRIVATE nr_rlc_core pthread utils minimal_lib) target_compile_definitions(nr_rlc_test_${TESTNUM} PRIVATE TEST="test${TESTNUM}.h") #target_include_directories(nr_rlc_test_${TESTNUM} PRIVATE LOG) #target_compile_options(nr_rlc_test_${TESTNUM} PRIVATE -g --coverage -Wall) From 1e476735eac1d5220413634fc9f10b5f9ff8356f Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 12 Sep 2025 18:19:10 +0000 Subject: [PATCH 836/964] xforms uses logging --- openair1/PHY/TOOLS/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/openair1/PHY/TOOLS/CMakeLists.txt b/openair1/PHY/TOOLS/CMakeLists.txt index 8a3d912caa..dad31d0ede 100644 --- a/openair1/PHY/TOOLS/CMakeLists.txt +++ b/openair1/PHY/TOOLS/CMakeLists.txt @@ -45,6 +45,7 @@ if(ENABLE_UESCOPE OR ENABLE_ENBSCOPE OR ENABLE_NRSCOPE) lte_phy_scope.c ../../../executables/stats.c) target_link_libraries(xforms_common PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) + target_link_libraries(xforms_common PRIVATE log_headers) add_library(enbscope MODULE lte_enb_scope.c $) target_link_libraries(enbscope PUBLIC forms PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs UTIL) From cdbfaf835e2747c401f5cd140461db6a021664fb Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sat, 13 Sep 2025 06:28:03 +0000 Subject: [PATCH 837/964] params_yaml has no dependency on UTIL These libraries have no dependencies on UTIL, so it's better to omit it. However, then the test is missing symbols for the config (which likely, indirectly came through UTIL -> LOG -> CONFIG_LIB, so add it now onto the test. --- common/config/yaml/CMakeLists.txt | 4 ++-- common/config/yaml/tests/CMakeLists.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/common/config/yaml/CMakeLists.txt b/common/config/yaml/CMakeLists.txt index 635887e37e..cfcc57e2ab 100644 --- a/common/config/yaml/CMakeLists.txt +++ b/common/config/yaml/CMakeLists.txt @@ -8,11 +8,11 @@ else() endif() add_library(params_yaml_static config_yaml.cpp) -target_link_libraries(params_yaml_static PUBLIC UTIL yaml-cpp::yaml-cpp) +target_link_libraries(params_yaml_static PUBLIC yaml-cpp::yaml-cpp) if (ENABLE_TESTS) add_subdirectory(tests) endif() add_library(params_yaml MODULE config_yaml.cpp) -target_link_libraries(params_yaml PUBLIC UTIL yaml-cpp::yaml-cpp) +target_link_libraries(params_yaml PUBLIC yaml-cpp::yaml-cpp) set_target_properties(params_yaml PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) diff --git a/common/config/yaml/tests/CMakeLists.txt b/common/config/yaml/tests/CMakeLists.txt index e3f1002d79..a460ccfdd4 100644 --- a/common/config/yaml/tests/CMakeLists.txt +++ b/common/config/yaml/tests/CMakeLists.txt @@ -1,5 +1,5 @@ add_executable(test_yaml_config test_yaml_config.cpp) -target_link_libraries(test_yaml_config PRIVATE params_yaml_static GTest::gtest) +target_link_libraries(test_yaml_config PRIVATE params_yaml_static GTest::gtest CONFIG_LIB) add_dependencies(tests test_yaml_config) add_test(NAME test_yaml_config COMMAND ./test_yaml_config) From 4876533e9ca9114ac0b3f3b5a714bdfc5eff030e Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sat, 13 Sep 2025 06:31:48 +0000 Subject: [PATCH 838/964] F1AP IDs: Remove unnecessary dependency --- openair2/F1AP/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair2/F1AP/CMakeLists.txt b/openair2/F1AP/CMakeLists.txt index 78bc9435a2..53ab2823ed 100644 --- a/openair2/F1AP/CMakeLists.txt +++ b/openair2/F1AP/CMakeLists.txt @@ -3,7 +3,7 @@ add_subdirectory(MESSAGES) if(ENABLE_TESTS) add_executable(f1ap_ids_test f1ap_ids_test.c f1ap_ids.c) - target_link_libraries(f1ap_ids_test UTIL HASHTABLE minimal_lib) + target_link_libraries(f1ap_ids_test HASHTABLE minimal_lib) add_dependencies(tests f1ap_ids_test) add_test(NAME F1AP_ID_test COMMAND f1ap_ids_test) From 2ff949a16fe803fcffd2ea1fe720ec2c472b16f3 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 15 Sep 2025 13:14:46 +0000 Subject: [PATCH 839/964] Correct dependencies onto logging module These libraries depend on the logging module, so add the right dependency log_headers. Indirectly, this will fulfill the condition of T. I consider the prior usage of generate_T or {T_LIB} incorrect, because basically none of these libraries actually, actively use T, but rather only the logging module, which pulls in T. The dependency of log_headers will also take care of generating and including T headers, which is a dependency of the logging module. For conf2uedata and related, fulfill the dependency through conf2uedata_lib (on which the rest depends). --- common/utils/telnetsrv/CMakeLists.txt | 2 +- common/utils/time_manager/CMakeLists.txt | 2 +- nfapi/oai_integration/socket/CMakeLists.txt | 3 +-- openair2/LAYER2/NR_MAC_UE/CMakeLists.txt | 4 ++-- openair3/NAS/TOOLS/CMakeLists.txt | 7 +------ 5 files changed, 6 insertions(+), 12 deletions(-) diff --git a/common/utils/telnetsrv/CMakeLists.txt b/common/utils/telnetsrv/CMakeLists.txt index 1a740adbe2..a249596d97 100644 --- a/common/utils/telnetsrv/CMakeLists.txt +++ b/common/utils/telnetsrv/CMakeLists.txt @@ -44,7 +44,7 @@ add_library(telnetsrv_enb MODULE telnetsrv_enb_phycmd.c ) add_dependencies(telnetsrv telnetsrv_enb) -target_link_libraries(telnetsrv_enb PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) +target_link_libraries(telnetsrv_enb PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs log_headers) message(STATUS "No specific telnet functions for gnb") diff --git a/common/utils/time_manager/CMakeLists.txt b/common/utils/time_manager/CMakeLists.txt index 3a197ae556..37cae023b0 100644 --- a/common/utils/time_manager/CMakeLists.txt +++ b/common/utils/time_manager/CMakeLists.txt @@ -7,7 +7,7 @@ add_library(time_management_core OBJECT time_client.c) target_link_libraries(time_management PUBLIC time_management_core) -target_link_libraries(time_management_core PRIVATE ${T_LIB}) +target_link_libraries(time_management_core PRIVATE log_headers) if(ENABLE_TESTS) add_subdirectory(tests) diff --git a/nfapi/oai_integration/socket/CMakeLists.txt b/nfapi/oai_integration/socket/CMakeLists.txt index 57cad36362..a909372d37 100644 --- a/nfapi/oai_integration/socket/CMakeLists.txt +++ b/nfapi/oai_integration/socket/CMakeLists.txt @@ -8,7 +8,6 @@ target_include_directories(nfapi_socket_lib PRIVATE include/) target_compile_definitions(nfapi_socket_lib PUBLIC ENABLE_SOCKET) target_link_libraries(nfapi_socket_lib PRIVATE NFAPI_LIB NFAPI_USER_LIB) -target_link_libraries(nfapi_socket_lib PRIVATE LOG) -add_dependencies(nfapi_socket_lib generate_T) +target_link_libraries(nfapi_socket_lib PRIVATE log_headers) target_link_libraries(nfapi_socket_lib PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs) target_link_libraries(nfapi_socket_lib PRIVATE nr_fapi_p5 nr_fapi_p7) diff --git a/openair2/LAYER2/NR_MAC_UE/CMakeLists.txt b/openair2/LAYER2/NR_MAC_UE/CMakeLists.txt index aa583c8598..8a7fec829e 100644 --- a/openair2/LAYER2/NR_MAC_UE/CMakeLists.txt +++ b/openair2/LAYER2/NR_MAC_UE/CMakeLists.txt @@ -1,7 +1,7 @@ add_library(nr_ue_power_procedures nr_ue_power_procedures.c) -target_link_libraries(nr_ue_power_procedures PUBLIC asn1_nr_rrc ${T_LIB} MAC_NR_COMMON nr_common) +target_link_libraries(nr_ue_power_procedures PUBLIC asn1_nr_rrc log_headers MAC_NR_COMMON nr_common) add_library(nr_ue_ra_procedures nr_ra_procedures.c) -target_link_libraries(nr_ue_ra_procedures PUBLIC asn1_nr_rrc asn1_lte_rrc_hdrs ${T_LIB} MAC_NR_COMMON nr_common) +target_link_libraries(nr_ue_ra_procedures PUBLIC asn1_nr_rrc asn1_lte_rrc_hdrs log_headers MAC_NR_COMMON nr_common) if (ENABLE_TESTS) add_subdirectory(tests) endif() diff --git a/openair3/NAS/TOOLS/CMakeLists.txt b/openair3/NAS/TOOLS/CMakeLists.txt index e57db8255f..50058ad5bc 100755 --- a/openair3/NAS/TOOLS/CMakeLists.txt +++ b/openair3/NAS/TOOLS/CMakeLists.txt @@ -13,6 +13,7 @@ add_library(conf2uedata_lib OBJECT ${OPENAIR_DIR}/common/utils/mem/memory.c ${OPENAIR_DIR}/common/utils/utils.c ) +target_link_libraries(conf2uedata_lib PUBLIC log_headers) add_executable(conf2uedata conf2uedata.c) target_link_libraries(conf2uedata PRIVATE conf2uedata_lib) @@ -28,9 +29,3 @@ add_executable(nvram nvram.c) target_link_libraries(nvram PRIVATE conf2uedata_lib) set_target_properties(nvram PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) target_link_libraries(nvram PRIVATE LOG minimal_lib ${libconfig_LIBRARIES}) - -if (${T_TRACER}) - add_dependencies(conf2uedata generate_T) - add_dependencies(usim generate_T) - add_dependencies(nvram generate_T) -endif (${T_TRACER}) From 60ab0a89a2d1b1024efa7a6627dbfc682c88065e Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 16 Sep 2025 09:07:41 +0200 Subject: [PATCH 840/964] Build all targets in Cluster PhySim build --- docker/Dockerfile.phySim.rhel9 | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/docker/Dockerfile.phySim.rhel9 b/docker/Dockerfile.phySim.rhel9 index c5faab2ec7..abb85f9586 100644 --- a/docker/Dockerfile.phySim.rhel9 +++ b/docker/Dockerfile.phySim.rhel9 @@ -36,9 +36,14 @@ RUN dnf install -y libasan libubsan #run build_oai to build the target image RUN /bin/sh oaienv && \ - cd cmake_targets && \ - mkdir -p log && \ - ./build_oai --phy_simulators --ninja --sanitize --build-tool-opt -k10 --noavx512 -c --cmake-opt -DCMAKE_C_FLAGS=-Werror --cmake-opt -DCMAKE_CXX_FLAGS=-Werror --cmake-opt -DCMAKE_RUNTIME_OUTPUT_DIRECTORY=/opt/oai-physim/bin + mkdir -p cmake_targets/ran_build/build && \ + cd cmake_targets/ran_build/build && \ + cmake3 -GNinja ../../.. \ + -DAVX512=OFF -DCMAKE_C_FLAGS=-Werror -DCMAKE_CXX_FLAGS=-Werror \ + -DENABLE_PHYSIM_TESTS=ON \ + -DSANITIZE_ADDRESS=ON -DSANITIZE_UNDEFINED=ON \ + -DCMAKE_RUNTIME_OUTPUT_DIRECTORY=/opt/oai-physim/bin && \ + ninja -k10 -j36 #start from scratch for target executable FROM registry.access.redhat.com/ubi9/ubi:latest AS oai-physim From 4b6c18b1dd8f8d63866c1a3b9c18929b9a04a593 Mon Sep 17 00:00:00 2001 From: Shubhika Garg Date: Mon, 29 Sep 2025 10:51:32 +0200 Subject: [PATCH 841/964] [ci] Fix MissingPropertyException - COTS-UE by binding `OAI_Registry` globally `def` creates a variable local to the script object, not automatically visible inside helper functions. This fixes the following exception in Jenkins: Found unhandled groovy.lang.MissingPropertyException exception: No such property: OAI_Registry for class: groovy.lang.Binding --- ci-scripts/Jenkinsfile-GitLab-Container | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci-scripts/Jenkinsfile-GitLab-Container b/ci-scripts/Jenkinsfile-GitLab-Container index c3f3037c78..44d857f1dc 100644 --- a/ci-scripts/Jenkinsfile-GitLab-Container +++ b/ci-scripts/Jenkinsfile-GitLab-Container @@ -35,7 +35,7 @@ def gitCommitAuthorEmailAddr // list of failing stages def failingStages = "" -def OAI_Registry = "gracehopper3-oai.sboai.cs.eurecom.fr" +OAI_Registry = "gracehopper3-oai.sboai.cs.eurecom.fr" pipeline { agent { From 0fb8a09b86019d0b6d482ecbcaa438cfebefb1a2 Mon Sep 17 00:00:00 2001 From: alexjiao Date: Mon, 29 Sep 2025 17:08:16 +0800 Subject: [PATCH 842/964] Remove function get_nr_RSRP() and get_nr_rx_total_gain_dB() for cleanup The function get_nr_RSRP() and get_nr_rx_total_gain_dB() is not used anywhere in the code. --- openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h | 2 -- .../PHY/NR_UE_ESTIMATION/nr_ue_measurements.c | 28 ------------------- 2 files changed, 30 deletions(-) diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h index b327327113..b1bc3ca8e1 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h @@ -147,8 +147,6 @@ void nr_pdsch_ptrs_processing(PHY_VARS_NR_UE *ue, uint16_t rnti, NR_UE_DLSCH_t dlsch[2]); -float_t get_nr_RSRP(module_id_t Mod_id,uint8_t CC_id,uint8_t gNB_index); - int nr_sl_psbch_rsrp_measurements(sl_nr_ue_phy_params_t *sl_phy_params, NR_DL_FRAME_PARMS *fp, c16_t rxdataF[][fp->samples_per_slot_wCP], diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c b/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c index 747a000c4d..ff706af688 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c @@ -46,34 +46,6 @@ //#define DEBUG_MEAS_UE //#define DEBUG_RANK_EST -uint32_t get_nr_rx_total_gain_dB (module_id_t Mod_id,uint8_t CC_id) -{ - - PHY_VARS_NR_UE *ue = PHY_vars_UE_g[Mod_id][CC_id]; - - if (ue) - return ue->rx_total_gain_dB; - - return 0xFFFFFFFF; -} - - -float_t get_nr_RSRP(module_id_t Mod_id,uint8_t CC_id,uint8_t gNB_index) -{ - - AssertFatal(PHY_vars_UE_g!=NULL,"PHY_vars_UE_g is null\n"); - AssertFatal(PHY_vars_UE_g[Mod_id]!=NULL,"PHY_vars_UE_g[%d] is null\n",Mod_id); - AssertFatal(PHY_vars_UE_g[Mod_id][CC_id]!=NULL,"PHY_vars_UE_g[%d][%d] is null\n",Mod_id,CC_id); - - PHY_VARS_NR_UE *ue = PHY_vars_UE_g[Mod_id][CC_id]; - - if (ue) - return (10*log10(ue->measurements.rsrp[gNB_index])- - get_nr_rx_total_gain_dB(Mod_id,0) - - 10*log10(20*12)); - return -140.0; -} - void nr_ue_measurements(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, NR_UE_DLSCH_t *dlsch, From 7d70617a019eecfee636c55c73d53a4da2dc5e82 Mon Sep 17 00:00:00 2001 From: calvin_peyron Date: Tue, 2 Sep 2025 11:46:54 +0200 Subject: [PATCH 843/964] Fix documentation broken links --- doc/FEATURE_SET.md | 2 +- doc/environment-variables.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/FEATURE_SET.md b/doc/FEATURE_SET.md index 9faf2c3d3b..f759ddf145 100644 --- a/doc/FEATURE_SET.md +++ b/doc/FEATURE_SET.md @@ -25,7 +25,7 @@ The following features are valid for the gNB and the 5G-NR UE. * Static TDD - - Multi TDD pattern supported refer [TDD Configuration](NR_SA_Multi_TDD_Pattern.md) + - Multi TDD pattern supported refer [TDD Configuration](MAC/mac-usage.md) * Static FDD * Normal CP * Subcarrier spacings: 15 and 30kHz (FR1), 120kHz (FR2) diff --git a/doc/environment-variables.md b/doc/environment-variables.md index 9778665afe..76730294fa 100644 --- a/doc/environment-variables.md +++ b/doc/environment-variables.md @@ -9,7 +9,7 @@ OAI uses/supports a number of environment variables, documented in the following - `OAI_CONFIGMODULE`: can be used to pass the configuration file instead of `-O` - `OAI_GDBSTACKS`: if defined when hitting an assertion (`DevAssert()`, `AssertFatal()`, ...), OAI will load `gdb` and provide a backtrace for every thread - `OAI_RNGSEED`: overwrites any seed for random number generators (RNG) in simulators -- `OAI_THREADPOOLMEASUREMENTS`: path to a file to store thread pool debugging information, see the [thread pool documentation](..common/utils/threadPool/thread-pool.md) +- `OAI_THREADPOOLMEASUREMENTS`: path to a file to store thread pool debugging information, see the [thread pool documentation](../common/utils/threadPool/thread-pool.md) - `OPENAIR_DIR`: should point to the root directory of OpenAirInterface; some code relies on this to get a filename, e.g., BLER curves for L2sim channel emulation - `USIM_DIR`: directory to read/write USIM data in (4G) `usim` tool; if not defined, will use `PWD` (working directory) From 3f9dcee5fa8735c94e05ad013e17a116cbf19bb7 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Tue, 2 Sep 2025 17:02:05 +0200 Subject: [PATCH 844/964] remove a dead function --- common/utils/mem/memory.c | 46 ----------------------------------- common/utils/mem/oai_memory.h | 2 -- 2 files changed, 48 deletions(-) diff --git a/common/utils/mem/memory.c b/common/utils/mem/memory.c index d4f09279aa..44b806dbe9 100644 --- a/common/utils/mem/memory.c +++ b/common/utils/mem/memory.c @@ -25,52 +25,6 @@ #include "common/utils/mem/oai_memory.h" #include "common/utils/LOG/log.h" -/**************************************************************************** - ** ** - ** Name: memory_get_path() ** - ** ** - ** Description: Gets the absolute path of the file where non-volatile ** - ** data are located ** - ** ** - ** Inputs: dirname: The directory where data file is located ** - ** filename: The name of the data file ** - ** Others: None ** - ** ** - ** Outputs: None ** - ** Return: The absolute path of the non-volatile data ** - ** file. The returned value is a dynamically ** - ** allocated octet string that needs to be ** - ** freed after usage. ** - ** Others: None ** - ** ** - ***************************************************************************/ -char* memory_get_path(const char* dirname, const char* filename) -{ - /* Get non-volatile data directory */ - const char* path = getenv(dirname); - - if (path == NULL) { - path = getenv(DEFAULT_NAS_PATH); - } - - if (path == NULL) { - path = "."; - } - - /* Append non-volatile data file name */ - size_t size = strlen(path) + strlen(filename) + 1; - char* data_filename = (char*)malloc(size + 1); - - if (data_filename != NULL) { - if (size != sprintf(data_filename, "%s/%s", path, filename)) { - free(data_filename); - return NULL; - } - } - - return data_filename; -} - char* memory_get_path_from_ueid(const char* dirname, const char* filename, int ueid) { /* Get non-volatile data directory */ diff --git a/common/utils/mem/oai_memory.h b/common/utils/mem/oai_memory.h index 311ad6f4d0..c09fe0b072 100644 --- a/common/utils/mem/oai_memory.h +++ b/common/utils/mem/oai_memory.h @@ -35,8 +35,6 @@ typedef unsigned char uint8_t; //----------------------------------------------------------------------------- -char* memory_get_path(const char* dirname, const char* filename); - char* memory_get_path_from_ueid(const char* dirname, const char* filename, int ueid); int memory_read(const char* datafile, void* data, size_t size); From 63397ac592d8b552d7e868f8bd37adaac084cd8e Mon Sep 17 00:00:00 2001 From: calvin_peyron Date: Wed, 17 Sep 2025 11:23:21 +0200 Subject: [PATCH 845/964] Remove RFSIMULATOR environment variable --- radio/rfsimulator/simulator.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/radio/rfsimulator/simulator.c b/radio/rfsimulator/simulator.c index 1a5c94f698..13a414fed6 100644 --- a/radio/rfsimulator/simulator.c +++ b/radio/rfsimulator/simulator.c @@ -358,14 +358,6 @@ static void rfsimulator_readconfig(rfsimulator_state_t *rfsimulator) { } } - /* for compatibility keep environment variable usage */ - if (getenv("RFSIMULATOR") != NULL) { - rfsimulator->ip = getenv("RFSIMULATOR"); - LOG_W(HW, "The RFSIMULATOR environment variable is deprecated and support will be removed in the future. Instead, add parameter --rfsimulator.serveraddr %s to set the server address. Note: the default is \"server\"; for the gNB/eNB, you don't have to set any configuration.\n", rfsimulator->ip); - LOG_I(HW, "Remove RFSIMULATOR environment variable to get rid of this message and the sleep.\n"); - sleep(10); - } - if ( strncasecmp(rfsimulator->ip,"enb",3) == 0 || strncasecmp(rfsimulator->ip,"server",3) == 0 ) rfsimulator->role = SIMU_ROLE_SERVER; From 1c5af6065c83bb25bdbe553e6fe456f41b9c4e29 Mon Sep 17 00:00:00 2001 From: alexjiao Date: Fri, 13 Jun 2025 20:39:08 +0800 Subject: [PATCH 846/964] Handle UCI on PUSCH procedures at PHY Get beta offset, alpha scaling and other parameters to calculate rate matching information for UCI on PUSCH, then use the rate matching info to encode UCI and re-encode PUSCH, call nr_uci_on_pusch to get final multiplexed codeword for scrambling. --- openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c | 71 ++++++++++++++++++++-- 1 file changed, 65 insertions(+), 6 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c index 561d357363..41b935221b 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c @@ -1034,8 +1034,11 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, LOG_D(PHY, "nr_ue_ulsch_procedures_slot hard_id %d %d.%d prepare for coding\n", harq_pid, frame, slot); NR_UE_ULSCH_t *ulsch_ue = &phy_data->ulsch; + NR_UE_PUCCH *pucch_ue = &phy_data->pucch_vars; NR_UL_UE_HARQ_t *harq_process_ul_ue = &UE->ul_harq_processes[harq_pid]; const nfapi_nr_ue_pusch_pdu_t *pusch_pdu = &ulsch_ue->pusch_pdu; + const fapi_nr_ul_config_pucch_pdu *pucch_pdu = &pucch_ue->pucch_pdu[0]; + uci_on_pusch_bit_type_t *uci_mapping_template = NULL; uint16_t number_dmrs_symbols = 0; @@ -1076,6 +1079,11 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, G[pusch_id] = nr_get_G(nb_rb, number_of_symbols, nb_dmrs_re_per_rb, number_dmrs_symbols, unav_res, mod_order, Nl); + // Capture the initial total PUSCH bits. This is the total_codeword_length for mapping. + unsigned int G_initial_total_pusch_bits = G[pusch_id]; + + uci_on_pusch_bit_type_t template_buffer[G_initial_total_pusch_bits]; + ws_trace_t tmp = {.nr = true, .direction = DIRECTION_UPLINK, .pdu_buffer = harq_process_ul_ue->payload_AB, @@ -1092,9 +1100,18 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, /////////////////////////ULSCH coding///////////////////////// - int enc_ret = nr_ulsch_pre_encoding(UE, &phy_data->ulsch, frame, slot, G, 1, ULSCH_ids); - enc_ret += nr_ulsch_encoding(UE, &phy_data->ulsch, frame, slot, G, 1, ULSCH_ids, number_dmrs_symbols); - if (enc_ret != 0) { + rate_match_info_uci_t rm_info = {0}; + const uint8_t nl_qm = Nl * mod_order; // product of number of layers and modulation order + if(nr_ulsch_pre_encoding(UE, &phy_data->ulsch, frame, slot, G, 1, ULSCH_ids) != 0) { + LOG_E(PHY, "Error pre-encoding\n"); + return; + } + + if (pusch_pdu->pusch_uci.harq_ack_bit_length != 0) { + rm_info = calc_rate_match_info_uci(pusch_pdu, harq_process_ul_ue, nl_qm, &G[pusch_id]); + } + + if (nr_ulsch_encoding(UE, &phy_data->ulsch, frame, slot, G, 1, ULSCH_ids, number_dmrs_symbols) == -1) { stop_meas_nr_ue_phy(UE, PUSCH_PROC_STATS); return; } @@ -1107,9 +1124,51 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, int N_PRB_oh = 0; // higher layer (RRC) parameter xOverhead in PUSCH-ServingCellConfig - AssertFatal(pusch_pdu->pusch_uci.harq_ack_bit_length == 0 && pusch_pdu->pusch_uci.csi_part1_bit_length == 0 - && pusch_pdu->pusch_uci.csi_part2_bit_length == 0, - "UCI on PUSCH not supported at PHY\n"); + if (pusch_pdu->pusch_uci.harq_ack_bit_length != 0) { + LOG_D(PHY, "[UCI_ON_PUSCH] Original HARQ-ACK bit length: %u\n", pusch_pdu->pusch_uci.harq_ack_bit_length); + LOG_D(PHY, "[UCI_ON_PUSCH] Initial G: %u\n", G_initial_total_pusch_bits); + // b is the block of bits transmitted on the physical channel after payload coding + uint64_t b[16] = {0}; // limit to 1024-bit encoded length + + if (pucch_pdu == NULL) { + LOG_E(PHY, "nr_ue_ulsch_procedures: pucch_pdu is NULL but HARQ-ACK is present. Cannot proceed with UCI encoding.\n"); + stop_meas_nr_ue_phy(UE, PUSCH_PROC_STATS); + return; + } + + nr_uci_encoding(pusch_pdu->pusch_uci.harq_payload, + pusch_pdu->pusch_uci.harq_ack_bit_length, + pucch_pdu->prb_size, + true, + rm_info.E_uci_ACK, + mod_order, + &b[0]); + + LOG_D(PHY, + "[UCI_ON_PUSCH] G_ulsch=%u (updated G[pusch_id]), G_ack=%u (M_bit), G_ack_rvd=%u, total_len=%u " + "(G_initial_total_pusch_bits).\n", + G[pusch_id], + rm_info.E_uci_ACK, + rm_info.E_uci_ACK_rvd, + G_initial_total_pusch_bits); + + uint8_t temp_codeword[G_initial_total_pusch_bits]; + nr_data_control_mapping(pusch_pdu, + template_buffer, + G[pusch_id], + rm_info.E_uci_ACK, + rm_info.E_uci_ACK_rvd, + temp_codeword, + G_initial_total_pusch_bits, + harq_process_ul_ue->f, + b); + + memcpy(harq_process_ul_ue->f, temp_codeword, G_initial_total_pusch_bits); + uci_mapping_template = template_buffer; + } + + AssertFatal(pusch_pdu->pusch_uci.csi_part1_bit_length == 0 && pusch_pdu->pusch_uci.csi_part2_bit_length == 0, + "UCI (CSI) on PUSCH not supported at PHY\n"); uint16_t start_rb = pusch_pdu->rb_start; uint16_t start_sc = frame_parms->first_carrier_offset + (start_rb + pusch_pdu->bwp_start) * NR_NB_SC_PER_RB; From b69b65ba6676d9fa84f4aa564322033724b1fc46 Mon Sep 17 00:00:00 2001 From: alexjiao Date: Fri, 13 Jun 2025 20:46:00 +0800 Subject: [PATCH 847/964] Handle UCI on PUSCH scrambling When the codeword has UCI multiplexed with data, we need to handle UCI scrambling according to 38.211 section 6.3.1.1. Especially when O_ACK <= 2 there are x and y placeholder bits for UCI. --- openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c | 106 +++++++++++++++++---- 1 file changed, 85 insertions(+), 21 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c index 41b935221b..08cc881180 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c @@ -62,32 +62,84 @@ //extern int32_t uplink_counter; -void nr_pusch_codeword_scrambling_uci(uint8_t *in, uint32_t size, uint32_t Nid, uint32_t n_RNTI, uint32_t* out) +static void nr_pusch_codeword_scrambling_uci(uint8_t *in, + uint32_t size, + uint32_t Nid, + uint32_t n_RNTI, + const uci_on_pusch_bit_type_t *template, + uint32_t *out) { uint32_t *seq = gold_cache((n_RNTI << 15) + Nid, (size + 31) / 32); - for (int i=0; i> 31; + uint32_t num_words = (size + 31) / 32; + + // Step 1: Initial general scrambling + // First convert unpacked input to bit-packed words + uint32_t in_words[num_words]; + memset(in_words, 0, num_words * sizeof(uint32_t)); + + for (uint32_t i = 0; i < size; i++) { + uint32_t word_idx = i / 32; + uint32_t bit_idx = i % 32; + if (in[i] & 1) { + in_words[word_idx] |= (1U << bit_idx); + } + } + + for (uint32_t i = 0; i < num_words; i++) { + out[i] = in_words[i] ^ seq[i]; + } + + for (uint32_t i = 0; i < size; i++) { + if (template[i] == BIT_TYPE_ACK) { + // Step 2: Overwrite/Correct positions for ACK-only bits when O_ACK > 2 + uint32_t pos = i; + uint32_t idx = pos / 32; + uint32_t b_idx = pos % 32; + + // Clear the bit that was set by the initial general scrambling + out[idx] &= ~(1U << b_idx); + + uint32_t ack_bit_value = in[pos] & 1; + uint32_t scrambling_bit_for_ack = (seq[idx] >> b_idx) & 1; + out[idx] |= ((ack_bit_value ^ scrambling_bit_for_ack) << b_idx); + } else if (template[i] == BIT_TYPE_ACK_ULSCH) { + // Step 3: Overwrite/Correct positions for UCI bits including placeholders X, Y when O_ACK <= 2 + uint32_t pos = i; + uint32_t idx = pos / 32; + uint32_t b_idx = pos % 32; + + out[idx] &= ~(1U << b_idx); + + if (in[pos] == NR_PUSCH_y) { + if (b_idx > 0) { + // Y depends on the final value of the previous bit in the same word. + // This previous bit could be an ACK (already corrected) or ULSCH (from initial scramble). + out[idx] |= ((out[idx] >> (b_idx - 1)) & 1) << b_idx; + } else if (idx > 0) { + // Y depends on the last bit of the previous word. + out[idx] |= ((out[idx - 1] >> 31) & 1); + } + } else if (in[pos] == NR_PUSCH_x) { + out[idx] |= (1U << b_idx); + } else { + uint32_t ack_bit_value = in[pos] & 1; + uint32_t scrambling_bit_for_ack = (seq[idx] >> b_idx) & 1; + out[idx] |= ((ack_bit_value ^ scrambling_bit_for_ack) << b_idx); } } - else - out[idx] ^= (((in[i]) & 1) ^ ((seq[idx] >> b_idx) & 1)) << b_idx; - //printf("i %d b_idx %d in %d s 0x%08x out 0x%08x\n", i, b_idx, in[i], s, *out); } } -void nr_pusch_codeword_scrambling(uint8_t *in, uint32_t size, uint32_t Nid, uint32_t n_RNTI, bool uci_on_pusch, uint32_t* out) +void nr_pusch_codeword_scrambling(uint8_t *in, + uint32_t size, + uint32_t Nid, + uint32_t n_RNTI, + bool uci_on_pusch, + const uci_on_pusch_bit_type_t *template, + uint32_t *out) { if (uci_on_pusch) - nr_pusch_codeword_scrambling_uci(in, size, Nid, n_RNTI, out); + nr_pusch_codeword_scrambling_uci(in, size, Nid, n_RNTI, template, out); else nr_codeword_scrambling(in, size, 0, Nid, n_RNTI, out); } @@ -1201,16 +1253,28 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, /////////////////////////ULSCH scrambling///////////////////////// - uint32_t available_bits = G[pusch_id]; - // +1 because size can be not modulo 4 - uint32_t scrambled_output[available_bits / (8 * sizeof(uint32_t)) + 1]; + uint32_t available_bits; + bool is_uci_on_pusch = (pusch_pdu->pusch_uci.harq_ack_bit_length != 0); + + if (is_uci_on_pusch) { + // UCI on PUSCH is present, so available bits are the total codeword length + available_bits = G_initial_total_pusch_bits; + } else { + // No UCI on PUSCH, so available bits are the initial G value + available_bits = G[pusch_id]; + } + + // +1 because size can be not modulo 4 for the uint32_t array + uint32_t scrambled_output_len_u32 = (available_bits + 31) / 32; // Round up to nearest uint32_t count + uint32_t scrambled_output[scrambled_output_len_u32]; memset(scrambled_output, 0, sizeof(scrambled_output)); nr_pusch_codeword_scrambling(harq_process_ul_ue->f, available_bits, pusch_pdu->data_scrambling_id, rnti, - false, + is_uci_on_pusch, + uci_mapping_template, scrambled_output); #if T_TRACER if (T_ACTIVE(T_UE_PHY_UL_SCRAMBLED_TX_BITS)) { From ac76c6e27a533ff4289044a97843805e643a5f2c Mon Sep 17 00:00:00 2001 From: alexjiao Date: Sun, 27 Jul 2025 19:40:09 +0800 Subject: [PATCH 848/964] Add functions to calculate M_bit for PUCCH format 2/3/4 Add functions to calculate PUCCH format 2/3/4 rate matching output sequence length (M_bit), according to 3GPP TS 38.212 Table 6.3.1.4-1. --- openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c | 67 +++++++++++++++++-------- 1 file changed, 46 insertions(+), 21 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c b/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c index b4c65cf28e..b6b20cefaf 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c @@ -485,6 +485,45 @@ void nr_generate_pucch1(const PHY_VARS_NR_UE *ue, } } +// Calculate number of DMRS symbols for PUCCH formats 3 and 4 +static uint8_t nr_pucch_get_dmrs_symbols(uint8_t nrofSymbols, uint8_t add_dmrs) +{ + if (nrofSymbols == 4) { + return 1; + } else if (nrofSymbols > 4 && nrofSymbols <= 9) { + return 2; + } else if (nrofSymbols > 9) { + return (add_dmrs == 0) ? 2 : 4; + } + return 0; +} + +// Calculate PUCCH format 2/3/4 rate matching output sequence length according to TS 38.212 Table 6.3.1.4-1 +static uint16_t nr_pucch_output_sequence_length(uint8_t format_type, + uint8_t nrofSymbols, + uint16_t nrofPRB, + uint8_t n_SF_PUCCH_s, + uint8_t is_pi_over_2_bpsk_enabled, + uint8_t add_dmrs) +{ + uint16_t M_bit = 0; + + if (format_type == 2) { + M_bit = 16 * nrofSymbols * nrofPRB; + } else if (format_type == 3) { + uint16_t E_init = (is_pi_over_2_bpsk_enabled == 0) ? 24 : 12; + uint8_t num_dmrs_symbols = nr_pucch_get_dmrs_symbols(nrofSymbols, add_dmrs); + M_bit = E_init * (nrofSymbols - num_dmrs_symbols) * nrofPRB / n_SF_PUCCH_s; + } else if (format_type == 4) { + nrofPRB = 1; + uint16_t E_init = (is_pi_over_2_bpsk_enabled == 0) ? 24 : 12; + uint8_t num_dmrs_symbols = nr_pucch_get_dmrs_symbols(nrofSymbols, add_dmrs); + M_bit = E_init * (nrofSymbols - num_dmrs_symbols) * nrofPRB / n_SF_PUCCH_s; + } + + return M_bit; +} + static inline void nr_pucch2_3_4_scrambling(uint16_t M_bit, uint16_t rnti, uint16_t n_id, uint64_t *B64, uint8_t *btilde) { // c_init=nRNTI*2^15+n_id according to TS 38.211 Subclause 6.3.2.6.1 @@ -726,7 +765,7 @@ void nr_generate_pucch2(const PHY_VARS_NR_UE *ue, // b is the block of bits transmitted on the physical channel after payload coding uint64_t b[16] = {0}; // limit to 1024-bit encoded length // M_bit is the number of bits of block b (payload after encoding) - uint16_t M_bit = 16 * pucch_pdu->nr_of_symbols * pucch_pdu->prb_size; + uint16_t M_bit = nr_pucch_output_sequence_length(pucch_pdu->format_type, pucch_pdu->nr_of_symbols, pucch_pdu->prb_size, 0, 0, 0); nr_uci_encoding(pucch_pdu->payload, pucch_pdu->n_bit, pucch_pdu->prb_size, false, M_bit, 0, &b[0]); /* * Implementing TS 38.211 @@ -938,26 +977,12 @@ void nr_generate_pucch3_4(const PHY_VARS_NR_UE *ue, uint16_t startingPRB = pucch_pdu->prb_start + pucch_pdu->bwp_start; uint8_t add_dmrs = pucch_pdu->add_dmrs_flag; - uint16_t E_init = (is_pi_over_2_bpsk_enabled == 0) ? 24 : 12; - - if (pucch_pdu->format_type == 3) { - if (nrofSymbols == 4) { - M_bit = (intraSlotFrequencyHopping == 0) ? (E_init * (nrofSymbols - 1) * nrofPRB) : (E_init * (nrofSymbols - 1) * nrofPRB); - } else if (nrofSymbols > 4) { - M_bit = E_init * (nrofSymbols - 2) * nrofPRB; - } else if (nrofSymbols > 9) { - M_bit = (add_dmrs == 0) ? (E_init * (nrofSymbols - 2) * nrofPRB) : (E_init * (nrofSymbols - 4) * nrofPRB); - } - } else if (pucch_pdu->format_type == 4) { - if (nrofSymbols == 4) { - M_bit = (intraSlotFrequencyHopping == 0) ? (E_init * (nrofSymbols - 1) / n_SF_PUCCH_s) - : (E_init * (nrofSymbols - 1) / n_SF_PUCCH_s); - } else if (nrofSymbols > 4) { - M_bit = E_init * (nrofSymbols - 2) / n_SF_PUCCH_s; - } else if (nrofSymbols > 9) { - M_bit = (add_dmrs == 0) ? (E_init * (nrofSymbols - 2) / n_SF_PUCCH_s) : (E_init * (nrofSymbols - 4) / n_SF_PUCCH_s); - } - } + M_bit = nr_pucch_output_sequence_length(pucch_pdu->format_type, + nrofSymbols, + nrofPRB, + n_SF_PUCCH_s, + is_pi_over_2_bpsk_enabled, + add_dmrs); nr_uci_encoding(pucch_pdu->payload, pucch_pdu->n_bit, nrofPRB, false, M_bit, 0, b); /* From 8de13fab97e7c2132ddb22451e3d026377f40e7e Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Fri, 15 Aug 2025 23:56:39 -0400 Subject: [PATCH 849/964] Simplify code --- openair1/PHY/NR_REFSIG/dmrs_nr.c | 4 + openair1/PHY/NR_REFSIG/dmrs_nr.h | 2 + openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c | 145 +++++++------------- openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 8 +- 4 files changed, 53 insertions(+), 106 deletions(-) diff --git a/openair1/PHY/NR_REFSIG/dmrs_nr.c b/openair1/PHY/NR_REFSIG/dmrs_nr.c index a5a55d685a..7dba224cdb 100644 --- a/openair1/PHY/NR_REFSIG/dmrs_nr.c +++ b/openair1/PHY/NR_REFSIG/dmrs_nr.c @@ -306,6 +306,10 @@ int8_t get_next_dmrs_symbol_in_slot(uint16_t ul_dmrs_symb_pos, uint8_t counter, return -1; } +int8_t get_num_dmrs_re_per_rb(const uint8_t dmrs_type, const uint8_t num_cdm_grp_no_data) +{ + return (dmrs_type == NFAPI_NR_DMRS_TYPE1 ? 6 * num_cdm_grp_no_data : 4 * num_cdm_grp_no_data); +} /* return the position of valid dmrs symbol in a slot for channel compensation */ int8_t get_valid_dmrs_idx_for_channel_est(uint16_t dmrs_symb_pos, uint8_t counter) diff --git a/openair1/PHY/NR_REFSIG/dmrs_nr.h b/openair1/PHY/NR_REFSIG/dmrs_nr.h index 97d61993ce..5f17478874 100644 --- a/openair1/PHY/NR_REFSIG/dmrs_nr.h +++ b/openair1/PHY/NR_REFSIG/dmrs_nr.h @@ -71,6 +71,8 @@ void nr_chest_time_domain_avg(NR_DL_FRAME_PARMS *frame_parms, uint16_t dmrs_bitmap, uint16_t num_rbs); +int8_t get_num_dmrs_re_per_rb(const uint8_t dmrs_type, const uint8_t num_cdm_grp_no_data); + static inline uint8_t is_dmrs_symbol(uint8_t l, uint16_t dmrsSymbMask) { DevAssert(l < 32); diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c index 08cc881180..d48109440d 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c @@ -89,28 +89,17 @@ static void nr_pusch_codeword_scrambling_uci(uint8_t *in, out[i] = in_words[i] ^ seq[i]; } + // According to 38.211 6.3.1.1 for (uint32_t i = 0; i < size; i++) { - if (template[i] == BIT_TYPE_ACK) { - // Step 2: Overwrite/Correct positions for ACK-only bits when O_ACK > 2 + if (template[i] == BIT_TYPE_ACK_ULSCH) { + // Step 2: Overwrite/Correct positions for UCI bits including placeholders X, Y when O_ACK <= 2 uint32_t pos = i; uint32_t idx = pos / 32; uint32_t b_idx = pos % 32; - // Clear the bit that was set by the initial general scrambling - out[idx] &= ~(1U << b_idx); - - uint32_t ack_bit_value = in[pos] & 1; - uint32_t scrambling_bit_for_ack = (seq[idx] >> b_idx) & 1; - out[idx] |= ((ack_bit_value ^ scrambling_bit_for_ack) << b_idx); - } else if (template[i] == BIT_TYPE_ACK_ULSCH) { - // Step 3: Overwrite/Correct positions for UCI bits including placeholders X, Y when O_ACK <= 2 - uint32_t pos = i; - uint32_t idx = pos / 32; - uint32_t b_idx = pos % 32; - - out[idx] &= ~(1U << b_idx); - if (in[pos] == NR_PUSCH_y) { + // Clear bit + out[idx] &= ~(1U << b_idx); if (b_idx > 0) { // Y depends on the final value of the previous bit in the same word. // This previous bit could be an ACK (already corrected) or ULSCH (from initial scramble). @@ -121,10 +110,6 @@ static void nr_pusch_codeword_scrambling_uci(uint8_t *in, } } else if (in[pos] == NR_PUSCH_x) { out[idx] |= (1U << b_idx); - } else { - uint32_t ack_bit_value = in[pos] & 1; - uint32_t scrambling_bit_for_ack = (seq[idx] >> b_idx) & 1; - out[idx] |= ((ack_bit_value ^ scrambling_bit_for_ack) << b_idx); } } } @@ -139,8 +124,10 @@ void nr_pusch_codeword_scrambling(uint8_t *in, uint32_t *out) { if (uci_on_pusch) + // in buffer is in byte-packed format nr_pusch_codeword_scrambling_uci(in, size, Nid, n_RNTI, template, out); else + // in buffer is in bit-packed format nr_codeword_scrambling(in, size, 0, Nid, n_RNTI, out); } @@ -701,62 +688,31 @@ static rate_match_info_uci_t calc_rate_match_info_uci(const nfapi_nr_ue_pusch_pd static int initialize_mapping_resources(const nfapi_nr_ue_pusch_pdu_t *pusch_pdu, uint32_t *m_ulsch_initial, - uint32_t *m_ulsch_current, - uint32_t *m_uci_current, - bool *is_dmrs_symbol_flags, - uint8_t *dmrs_symbol_set_relative, - uint8_t *num_dmrs_symbols_in_set_relative) + uint32_t *m_uci_current) { - if (!pusch_pdu || !m_ulsch_initial || !m_ulsch_current || !m_uci_current || !is_dmrs_symbol_flags || !dmrs_symbol_set_relative - || !num_dmrs_symbols_in_set_relative) + if (!pusch_pdu || !m_ulsch_initial || !m_uci_current) return -1; - uint8_t n_pusch_sym_all = pusch_pdu->nr_of_symbols; - uint16_t ul_dmrs_symb_pos = pusch_pdu->ul_dmrs_symb_pos; - uint8_t dmrs_type = pusch_pdu->dmrs_config_type; - uint8_t cdm_grps_no_data = pusch_pdu->num_dmrs_cdm_grps_no_data; - uint32_t res_per_symbol_non_dmrs = pusch_pdu->rb_size * 12; - - *num_dmrs_symbols_in_set_relative = 0; + const uint8_t n_pusch_sym_all = pusch_pdu->nr_of_symbols; + const uint16_t ul_dmrs_symb_pos = pusch_pdu->ul_dmrs_symb_pos; + const uint8_t dmrs_type = pusch_pdu->dmrs_config_type; + const uint8_t cdm_grps_no_data = pusch_pdu->num_dmrs_cdm_grps_no_data; + const uint32_t res_per_symbol_non_dmrs = pusch_pdu->rb_size * NR_NB_SC_PER_RB; + const uint32_t data_re_on_dmrs_sym_per_prb = NR_NB_SC_PER_RB - get_num_dmrs_re_per_rb(dmrs_type, cdm_grps_no_data); // Initialize resources per symbol for ULSCH and UCI for (uint8_t i = 0; i < n_pusch_sym_all; i++) { uint8_t absolute_symbol_idx = pusch_pdu->start_symbol_index + i; if ((ul_dmrs_symb_pos >> absolute_symbol_idx) & 0x01) { - is_dmrs_symbol_flags[i] = true; - if (*num_dmrs_symbols_in_set_relative < 14) { - dmrs_symbol_set_relative[(*num_dmrs_symbols_in_set_relative)++] = i; - } - // Calculate available data REs on DMRS symbols based on DMRS configuration - uint32_t data_re_on_dmrs_sym_per_prb = 0; - - if (dmrs_type == 0) { // Type 1 - if (cdm_grps_no_data == 1) { - data_re_on_dmrs_sym_per_prb = 6; - } else { - data_re_on_dmrs_sym_per_prb = 0; - } - } else { // Type 2 - if (cdm_grps_no_data == 1) { - data_re_on_dmrs_sym_per_prb = 4; - } else if (cdm_grps_no_data == 2) { - data_re_on_dmrs_sym_per_prb = 2; - } else { - data_re_on_dmrs_sym_per_prb = 0; - } - } m_ulsch_initial[i] = pusch_pdu->rb_size * data_re_on_dmrs_sym_per_prb; - m_ulsch_current[i] = m_ulsch_initial[i]; m_uci_current[i] = 0; // UCI is not mapped on DMRS symbols } else { // Not a DMRS symbol - is_dmrs_symbol_flags[i] = false; m_ulsch_initial[i] = res_per_symbol_non_dmrs; - m_ulsch_current[i] = res_per_symbol_non_dmrs; m_uci_current[i] = res_per_symbol_non_dmrs; } } @@ -764,35 +720,31 @@ static int initialize_mapping_resources(const nfapi_nr_ue_pusch_pdu_t *pusch_pdu return 0; } -static uint8_t find_first_uci_symbol(uint8_t n_pusch_sym_all, - const bool *is_dmrs_symbol_flags, - uint8_t *dmrs_symbol_set_relative, - uint32_t num_dmrs_symbols_in_set_relative) +static void get_first_uci_symbol(const uint8_t start_symbol, + const uint8_t num_symbols, + const uint16_t dmrs_map, + uint8_t *first_non_dmrs_sym, + uint8_t *dmrs_p1) { - uint8_t l1_c = 0; - - // Find first non-DMRS symbol - for (uint8_t i = 0; i < n_pusch_sym_all; i++) { - if (!is_dmrs_symbol_flags[i]) { - l1_c = i; + // First non-DMRS symbol + const uint16_t last_sym = start_symbol + num_symbols; + for (uint_fast8_t s = start_symbol; s < last_sym; s++) { + if (!is_dmrs_symbol(s, dmrs_map)) { + *first_non_dmrs_sym = s; break; } } - // If there are DMRS symbols, try to find a symbol after the first DMRS - if (num_dmrs_symbols_in_set_relative > 0) { - uint8_t first_dmrs_idx = dmrs_symbol_set_relative[0]; - if (l1_c <= first_dmrs_idx) { - for (uint8_t i = first_dmrs_idx + 1; i < n_pusch_sym_all; i++) { - if (!is_dmrs_symbol_flags[i]) { - l1_c = i; - break; - } - } - } + // Symbol after first consequtive DMRS symbol + const uint8_t first_dmrs_sym = get_next_dmrs_symbol_in_slot(dmrs_map, start_symbol, last_sym); + *dmrs_p1 = first_dmrs_sym + 1; + while (is_dmrs_symbol(*dmrs_p1, dmrs_map) && *dmrs_p1 < last_sym) { + (*dmrs_p1)++; } - return l1_c; + // Return relative symbol idx + *first_non_dmrs_sym -= start_symbol; + *dmrs_p1 -= start_symbol; } /* @@ -1013,34 +965,29 @@ static uci_on_pusch_bit_type_t *nr_data_control_mapping(const nfapi_nr_ue_pusch_ if (!pusch_pdu || !codeword || codeword_len == 0 || !template) return NULL; const uint8_t n_symbols = pusch_pdu->nr_of_symbols; - if (n_symbols == 0 || n_symbols > 14) + if (n_symbols == 0 || n_symbols > NR_NUMBER_OF_SYMBOLS_PER_SLOT) return NULL; - uint32_t m_ulsch_initial[14] = {0}; - uint32_t m_ulsch_current[14] = {0}; - uint32_t m_uci_current[14] = {0}; // This holds RE counts, not bit counts - bool is_dmrs_symbol_flags[14] = {0}; - uint8_t dmrs_symbol_set_relative[14] = {0}; - uint8_t num_dmrs_symbols_in_set_relative = 0; + uint32_t m_ulsch_initial[NR_NUMBER_OF_SYMBOLS_PER_SLOT] = {0}; + uint32_t m_uci_current[NR_NUMBER_OF_SYMBOLS_PER_SLOT] = {0}; // This holds RE counts, not bit counts - if (initialize_mapping_resources(pusch_pdu, - m_ulsch_initial, - m_ulsch_current, - m_uci_current, - is_dmrs_symbol_flags, - dmrs_symbol_set_relative, - &num_dmrs_symbols_in_set_relative) - != 0) { + if (initialize_mapping_resources(pusch_pdu, m_ulsch_initial, m_uci_current) != 0) { LOG_E(PHY, "Failed to initialize mapping resources\n"); return NULL; } - uint8_t l1_c = find_first_uci_symbol(n_symbols, is_dmrs_symbol_flags, dmrs_symbol_set_relative, num_dmrs_symbols_in_set_relative); + uint8_t first_non_dmrs_sym = 0; + uint8_t l1_c = 0; + get_first_uci_symbol(pusch_pdu->start_symbol_index, + pusch_pdu->nr_of_symbols, + pusch_pdu->ul_dmrs_symb_pos, + &first_non_dmrs_sym, + &l1_c); memset(template, 0, codeword_len * sizeof(uci_on_pusch_bit_type_t)); - uint32_t positions_by_sym[14][MAX_UCI_CODED_BITS] = {0}; - uint32_t count_by_sym[14] = {0}; + uint32_t positions_by_sym[NR_NUMBER_OF_SYMBOLS_PER_SLOT][MAX_UCI_CODED_BITS] = {0}; + uint32_t count_by_sym[NR_NUMBER_OF_SYMBOLS_PER_SLOT] = {0}; if (G_ack_rvd > 0) { build_template_reserve_ack(template, diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index ce398d9a7a..75f73b0e8c 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -1214,13 +1214,7 @@ void pdsch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_ } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PDSCH, VCD_FUNCTION_OUT); - uint8_t nb_re_dmrs; - if (dlsch_config->dmrsConfigType == NFAPI_NR_DMRS_TYPE1) { - nb_re_dmrs = 6 * dlsch_config->n_dmrs_cdm_groups; - } - else { - nb_re_dmrs = 4 * dlsch_config->n_dmrs_cdm_groups; - } + const uint8_t nb_re_dmrs = get_num_dmrs_re_per_rb(dlsch_config->dmrsConfigType, dlsch_config->n_dmrs_cdm_groups); uint16_t dmrs_len = get_num_dmrs(dlsch_config->dlDmrsSymbPos); uint32_t unav_res = 0; if(dlsch_config->pduBitmap & 0x1) { From b2174cb8e127da301650f16b0e404852d0bf2c77 Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Sat, 16 Aug 2025 12:46:11 -0400 Subject: [PATCH 850/964] Add processing stats for UCI mapping on PUSCH --- openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c | 3 ++- openair1/PHY/nr_phy_common/inc/nr_ue_phy_meas.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c index d48109440d..7fca035a27 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c @@ -1152,6 +1152,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, G_initial_total_pusch_bits); uint8_t temp_codeword[G_initial_total_pusch_bits]; + start_meas_nr_ue_phy(UE, UCI_ON_PUSCH_MAPPING); nr_data_control_mapping(pusch_pdu, template_buffer, G[pusch_id], @@ -1161,7 +1162,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, G_initial_total_pusch_bits, harq_process_ul_ue->f, b); - + stop_meas_nr_ue_phy(UE, UCI_ON_PUSCH_MAPPING); memcpy(harq_process_ul_ue->f, temp_codeword, G_initial_total_pusch_bits); uci_mapping_template = template_buffer; } diff --git a/openair1/PHY/nr_phy_common/inc/nr_ue_phy_meas.h b/openair1/PHY/nr_phy_common/inc/nr_ue_phy_meas.h index 9f91274bae..79b0b378e8 100644 --- a/openair1/PHY/nr_phy_common/inc/nr_ue_phy_meas.h +++ b/openair1/PHY/nr_phy_common/inc/nr_ue_phy_meas.h @@ -47,6 +47,7 @@ FN(DLSCH_PROCEDURES_STATS),\ FN(PHY_PROC_TX),\ FN(PUSCH_PROC_STATS),\ + FN(UCI_ON_PUSCH_MAPPING),\ FN(ULSCH_SEGMENTATION_STATS),\ FN(ULSCH_LDPC_ENCODING_STATS),\ FN(ULSCH_RATE_MATCHING_STATS),\ From 83bf140bc3bd7e0416f09706b9681abd67a5edca Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Sat, 16 Aug 2025 19:20:44 -0400 Subject: [PATCH 851/964] Add flag for Tx phase pre compensation Used in ulsim to verify waveform in MATLAB --- .../PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h | 3 ++- openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c | 16 +++++++++------- openair1/PHY/defs_nr_UE.h | 3 +++ openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 3 ++- openair1/SCHED_NR_UE/phy_procedures_nr_ue_sl.c | 10 +++++++++- 5 files changed, 25 insertions(+), 10 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h index c257726501..0c519451a5 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h @@ -170,7 +170,8 @@ uint8_t nr_ue_pusch_common_procedures(PHY_VARS_NR_UE *UE, c16_t **txdataF, c16_t **txdata, uint32_t linktype, - bool was_symbol_used[NR_NUMBER_OF_SYMBOLS_PER_SLOT]); + bool was_symbol_used[NR_NUMBER_OF_SYMBOLS_PER_SLOT], + bool no_phase_pre_comp); void clean_UE_harq(PHY_VARS_NR_UE *UE); diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c index 7fca035a27..ff2d67e793 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c @@ -1506,19 +1506,21 @@ uint8_t nr_ue_pusch_common_procedures(PHY_VARS_NR_UE *UE, c16_t **txdataF, c16_t **txdata, uint32_t linktype, - bool was_symbol_used[NR_NUMBER_OF_SYMBOLS_PER_SLOT]) + bool was_symbol_used[NR_NUMBER_OF_SYMBOLS_PER_SLOT], + bool no_phase_pre_comp) { int N_RB = (linktype == link_type_sl) ? frame_parms->N_RB_SL : frame_parms->N_RB_UL; - for (int i = 0; i < NR_NUMBER_OF_SYMBOLS_PER_SLOT; i++) { - if (was_symbol_used[i] == false) - continue; - for (int ap = 0; ap < n_antenna_ports; ap++) { - apply_nr_rotation_TX(frame_parms, txdataF[ap], frame_parms->symbol_rotation[linktype], slot, N_RB, i, 1); + if (!no_phase_pre_comp) { + for (int i = 0; i < NR_NUMBER_OF_SYMBOLS_PER_SLOT; i++) { + if (was_symbol_used[i] == false) + continue; + for (int ap = 0; ap < n_antenna_ports; ap++) { + apply_nr_rotation_TX(frame_parms, txdataF[ap], frame_parms->symbol_rotation[linktype], slot, N_RB, i, 1); + } } } - for (int ap = 0; ap < n_antenna_ports; ap++) { if (frame_parms->Ncp == 1) { // extended cyclic prefix for (int i = 0; i < NR_NUMBER_OF_SYMBOLS_PER_SLOT_EXTENDED_CP; i++) { diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h index 6ae3ddc37a..d56355298b 100644 --- a/openair1/PHY/defs_nr_UE.h +++ b/openair1/PHY/defs_nr_UE.h @@ -499,6 +499,9 @@ typedef struct PHY_VARS_NR_UE_s { /// RF and Interface devices per CC openair0_device rfdevice; + /// Phase precompensation flag + bool no_phase_pre_comp; + void* scopeData; // Pointers to hold PDSCH data only for phy simulators void *phy_sim_rxdataF; diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index 75f73b0e8c..89b8ed91a7 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -404,7 +404,8 @@ void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, n (c16_t **)txdataF, txp, link_type_ul, - was_symbol_used); + was_symbol_used, + ue->no_phase_pre_comp); stop_meas_nr_ue_phy(ue, OFDM_MOD_STATS); } diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue_sl.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue_sl.c index bd2ac08b81..e03c0a1fae 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue_sl.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue_sl.c @@ -313,7 +313,15 @@ void phy_procedures_nrUE_SL_TX(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc was_symbol_used[i] = true; if (tx_action) { LOG_D(NR_PHY, "Sending Uplink data \n"); - nr_ue_pusch_common_procedures(ue, proc->nr_slot_tx, fp, fp->nb_antennas_tx, txdataF, txp, link_type_sl, was_symbol_used); + nr_ue_pusch_common_procedures(ue, + proc->nr_slot_tx, + fp, + fp->nb_antennas_tx, + txdataF, + txp, + link_type_sl, + was_symbol_used, + ue->no_phase_pre_comp); } LOG_D(NR_PHY, "****** end Sidelink TX-Chain for AbsSubframe %d.%d ******\n", frame_tx, slot_tx); From 59ff9ae04e8d8826cc91df0e2989bc7ffd24f46c Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Sat, 16 Aug 2025 21:04:56 -0400 Subject: [PATCH 852/964] ulsim: test UCI on PUSCH with matlab Since there is no UCI on PUSCH implementation in gNB, it is good to test UE's implementation with matlab. This commit allows to test with matlab in two ways: 1. generate OFDM waveform from ulsim and decode it in matlab using uci_on_pusch_decode.m 2. generate codeword in matlab using uci_on_pusch_encode.m read it in ulsim and compare the bits. ulsim option -o is used --- openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c | 3 + openair1/PHY/defs_nr_UE.h | 1 + openair1/SIMULATION/NR_PHY/ulsim.c | 176 +++++++++++++++++- .../SIMULATION/TOOLS/uci_on_pusch_decode.m | 79 ++++++++ .../SIMULATION/TOOLS/uci_on_pusch_encode.m | 85 +++++++++ 5 files changed, 335 insertions(+), 9 deletions(-) create mode 100644 openair1/SIMULATION/TOOLS/uci_on_pusch_decode.m create mode 100644 openair1/SIMULATION/TOOLS/uci_on_pusch_encode.m diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c index ff2d67e793..310fa7dc5f 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c @@ -1224,6 +1224,9 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, is_uci_on_pusch, uci_mapping_template, scrambled_output); + if (UE->phy_sim_test_buf) { + memcpy(UE->phy_sim_test_buf, scrambled_output, (available_bits + 7) / 8); + } #if T_TRACER if (T_ACTIVE(T_UE_PHY_UL_SCRAMBLED_TX_BITS)) { // Get Time Stamp for T-tracer messages diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h index d56355298b..935226b238 100644 --- a/openair1/PHY/defs_nr_UE.h +++ b/openair1/PHY/defs_nr_UE.h @@ -511,6 +511,7 @@ typedef struct PHY_VARS_NR_UE_s { void *phy_sim_pdsch_dl_ch_estimates; void *phy_sim_pdsch_dl_ch_estimates_ext; uint8_t *phy_sim_dlsch_b; + uint8_t *phy_sim_test_buf; dynamic_barrier_t process_slot_tx_barriers[NUM_PROCESS_SLOT_TX_BARRIERS]; diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index ec4a7190fa..edab935e15 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -160,6 +160,108 @@ openair0_config_t openair0_cfg[MAX_CARDS]; channel_desc_t *UE2gNB[MAX_MOBILES_PER_GNB][NUMBER_OF_gNB_MAX]; +static void copy_bytes_to_packed_bits(const uint8_t *in, const uint32_t num_bits, const bool is_ulsch, uint8_t *out) +{ + if (is_ulsch) { // MATLAB computes CRC for input of MSB first + for (uint_fast32_t b = 0; b < num_bits; b++) { + out[b / 8] |= ((in[b] & 1) << (7 - (b % 8))); + } + } else { + for (uint_fast32_t b = 0; b < num_bits; b++) { + out[b / 8] |= (in[b] << (b % 8)); + } + } +} + +static void prepare_ue_pusch_pdu_from_matlab_vector(const bool uci_on_pusch, + FILE *vect_file, + nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu, + uint8_t *cw_buf) +{ + if (!uci_on_pusch) + return; + + if (vect_file == NULL) + return; + + struct vect_vars { + uint32_t A; + uint32_t oack; + uint32_t ocsi1; + uint32_t ocsi2; + uint32_t cwlen; + uint32_t cwlen_scr; + } __attribute__((packed)); + + struct vect_vars var = {0}; + if (1 != fread(&var, sizeof(var), 1, vect_file)) { + printf("Error reading from matlab vector file\n"); + exit(-1); + } + + const uint16_t buff_len = var.A + var.oack + var.ocsi1 + var.ocsi2; + uint8_t vec_bits[buff_len]; + memset(vec_bits, 0, sizeof(vect_file)); + + uint8_t *p_vec_bits = vec_bits; + if (var.A != fread(p_vec_bits, sizeof(uint8_t), var.A, vect_file)) { + printf("Error reading ULSCH bits from file\n"); + exit(-1); + } + p_vec_bits += var.A; + if (var.oack != fread(p_vec_bits, sizeof(uint8_t), var.oack, vect_file)) { + printf("Error reading ACK bits from file\n"); + exit(-1); + } + p_vec_bits += var.oack; + if (var.ocsi1 != fread(p_vec_bits, sizeof(uint8_t), var.ocsi1, vect_file)) { + printf("Error reading CSI1 bits from file\n"); + exit(-1); + } + p_vec_bits += var.ocsi1; + if (var.ocsi2 != fread(p_vec_bits, sizeof(uint8_t), var.ocsi2, vect_file)) { + printf("Error reading CSI2 bits from file\n"); + exit(-1); + } + + if (var.cwlen != fread(cw_buf, sizeof(uint8_t), var.cwlen, vect_file)) { + printf("Error reading cw bits from file\n"); + exit(-1); + } + + memset(cw_buf, 0, var.cwlen_scr); + if (var.cwlen_scr != fread(cw_buf, sizeof(uint8_t), var.cwlen_scr, vect_file)) { + printf("Error reading cw bits from file\n"); + exit(-1); + } + + uint16_t tb_buf_size = (var.A + 7) / 8; + pusch_config_pdu->pusch_data.tb_size = tb_buf_size; + pusch_config_pdu->tx_request_body.pdu_length = tb_buf_size; + uint8_t *pb = pusch_config_pdu->tx_request_body.fapiTxPdu; + memset(pb, 0, tb_buf_size); + p_vec_bits = vec_bits; + copy_bytes_to_packed_bits(p_vec_bits, var.A, true, pb); + + pusch_config_pdu->pusch_uci.harq_ack_bit_length = var.oack; + pb = (uint8_t *)&pusch_config_pdu->pusch_uci.harq_payload; + memset(pb, 0, sizeof(pusch_config_pdu->pusch_uci.harq_payload)); + p_vec_bits += var.A; + copy_bytes_to_packed_bits(p_vec_bits, var.oack, false, pb); + + pusch_config_pdu->pusch_uci.csi_part1_bit_length = var.ocsi1; + pb = (uint8_t *)&pusch_config_pdu->pusch_uci.csi_part1_payload; + memset(pb, 0, sizeof(pusch_config_pdu->pusch_uci.csi_part1_payload)); + p_vec_bits += var.oack; + copy_bytes_to_packed_bits(p_vec_bits, var.ocsi1, false, pb); + + pusch_config_pdu->pusch_uci.csi_part2_bit_length = var.ocsi2; + pb = (uint8_t *)&pusch_config_pdu->pusch_uci.csi_part2_payload; + memset(pb, 0, sizeof(pusch_config_pdu->pusch_uci.csi_part2_payload)); + p_vec_bits += var.ocsi1; + copy_bytes_to_packed_bits(p_vec_bits, var.ocsi2, false, pb); +} + configmodule_interface_t *uniqCfg = NULL; int main(int argc, char *argv[]) { @@ -204,6 +306,8 @@ int main(int argc, char *argv[]) int print_perf = 0; cpuf = get_cpu_freq_GHz(); int msg3_flag = 0; + bool uci_on_pusch = false; + bool no_phase_pre_comp = false; int rv_index = 0; float roundStats; double effRate; @@ -227,6 +331,7 @@ int main(int argc, char *argv[]) UE_nr_rxtx_proc_t UE_proc; FILE *scg_fd=NULL; + FILE *uci_ulsch_matlab_vec = NULL; int file_offset = 0; double DS_TDL = .03; @@ -252,7 +357,8 @@ int main(int argc, char *argv[]) int c; bool setAffinity=false; char gNBthreads[128]="n"; - while ((c = getopt(argc, argv, "--:O:a:b:c:d:ef:g:h:i:jk:m:n:p:q:r:s:t:u:v:w:y:z:A:C:F:G:H:I:M:N:PR:S:T:U:L:ZW:E:X:Y:")) != -1) { + while ((c = getopt(argc, argv, "--:O:a:b:c:d:ef:g:h:i:jk:m:n:o::p:q:r:s:t:u:v:w:y:z:A:C:F:G:H:I:M:N:PR:S:T:U:L:ZW:E:X:Y:")) + != -1) { /* ignore long options starting with '--', option '-O' and their arguments that are handled by configmodule */ /* with this opstring getopt returns 1 for non-option arguments, refer to 'man 3 getopt' */ if (c == 1 || c == '-' || c == 'O') @@ -360,6 +466,20 @@ int main(int argc, char *argv[]) Imcs = atoi(optarg); break; + case 'o': + uci_on_pusch = true; + // UCI on PUSCH is not implemented in OAI gNB yet. + // So this flag is needed to verify in MATLAB + no_phase_pre_comp = true; + if (optarg) { // -o with file input: use matlab vector + uci_ulsch_matlab_vec = fopen(optarg, "rb"); + if (uci_ulsch_matlab_vec == NULL) { + printf("Error opening %s\n", optarg); + exit(-1); + } + } + break; + case 'W': precod_nbr_layers = atoi(optarg); break; @@ -539,6 +659,7 @@ int main(int argc, char *argv[]) printf("-k 3/4 sampling\n"); printf("-m MCS value\n"); printf("-n Number of trials to simulate\n"); + printf("-o Enable UCI on PUSCH. Optionally accepts input file (without space). This feature is not yet available in gNB so only used to verify with MATLAB generated vector\n"); printf("-p Use extended prefix mode\n"); printf("-q MCS table\n"); printf("-r Number of allocated resource blocks for PUSCH\n"); @@ -786,7 +907,8 @@ int main(int argc, char *argv[]) UE->if_inst->phy_config_request = nr_ue_phy_config_request; UE->if_inst->dl_indication = nr_ue_dl_indication; UE->if_inst->ul_indication = nr_ue_ul_indication; - + UE->no_phase_pre_comp = no_phase_pre_comp; + UE_mac->if_module = nr_ue_if_module_init(0); initFloatingCoresTpool(threadCnt, &nrUE_params.Tpool, false, "UE-tpool"); @@ -924,6 +1046,9 @@ int main(int argc, char *argv[]) } unsigned int available_bits = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, number_dmrs_symbols, unav_res, mod_order, precod_nbr_layers); + uint8_t cw_buf[available_bits]; + memset(cw_buf, 0, available_bits); + UE->phy_sim_test_buf = calloc(1, (available_bits + 7) / 8); printf("[ULSIM]: VALUE OF G: %u, TBS: %u\n", available_bits, TBS); int frame_length_complex_samples = gNB->frame_parms.samples_per_subframe * NR_NUMBER_OF_SUBFRAMES_PER_FRAME; @@ -1222,6 +1347,20 @@ int main(int argc, char *argv[]) // pusch_config_pdu->pdu_bit_map |= PUSCH_PDU_BITMAP_DFTS_OFDM; pusch_config_pdu->num_dmrs_cdm_grps_no_data = num_dmrs_cdm_grps_no_data; } + if (uci_on_pusch) { + const nfapi_nr_ue_pusch_uci_t pusch_uci = { + .alpha_scaling = 3, + .beta_offset_csi1 = 13, + .beta_offset_csi2 = 13, + .beta_offset_harq_ack = 11, + .harq_ack_bit_length = 3, + .harq_payload = 3, + //.csi_part1_bit_length = 4, + //.csi_part1_payload = 15 + }; + pusch_config_pdu->pusch_uci = pusch_uci; + prepare_ue_pusch_pdu_from_matlab_vector(uci_on_pusch, uci_ulsch_matlab_vec, pusch_config_pdu, cw_buf); + } if (do_SRS == 1) { fapi_nr_ul_config_request_pdu_t *ul_config1 = &ul_config.ul_config_list[1]; @@ -1457,7 +1596,7 @@ int main(int argc, char *argv[]) } if ((ulsch_gNB->last_iteration_cnt >= ulsch_gNB->max_ldpc_iterations) || ul_proc_error == 1) { - error_flag = 1; + error_flag = uci_on_pusch ? 0 : 1; n_errors[round]++; crc_status = 1; } else @@ -1474,15 +1613,29 @@ int main(int argc, char *argv[]) available_bits, (ptrsSymbPerSlot * ptrsRePerSymb * mod_order * precod_nbr_layers)); } - for (i = 0; i < available_bits; i++) { - const uint8_t current_bit = (UE->ul_harq_processes[harq_pid].f[i / 8] >> (i & 7)) & 1; - if (((current_bit == 0) && (pusch_vars->llr[i] <= 0)) || ((current_bit == 1) && (pusch_vars->llr[i] >= 0))) { - /*if(errors_scrambling == 0) - printf("\x1B[34m" "[frame %d][trial %d]\t1st bit in error in unscrambling = %d\n" "\x1B[0m", frame, trial, i);*/ - errors_scrambling[round]++; + if (uci_on_pusch) { + for (i = 0; i < available_bits; i++) { + const uint8_t current_bit = (UE->phy_sim_test_buf[i / 8] >> (i & 7)) & 1; + const uint8_t test_vector_bit = cw_buf[i] & 1; + if (current_bit != test_vector_bit) + errors_scrambling[round]++; + } + } else { + for (i = 0; i < available_bits; i++) { + const uint8_t current_bit = (UE->ul_harq_processes[harq_pid].f[i / 8] >> (i & 7)) & 1; + if (((current_bit == 0) && (pusch_vars->llr[i] <= 0)) || ((current_bit == 1) && (pusch_vars->llr[i] >= 0))) { + errors_scrambling[round]++; + } } } round++; + if (uci_on_pusch && uci_ulsch_matlab_vec && (errors_scrambling[round] == 0)) { + ret = 0; + printf("*************\n"); + printf("UCI on PUSCH test OK against MATLAB generated codeword\n"); + printf("*************\n"); + break; + } } // round if (n_trials == 1 && errors_scrambling[0] > 0) { @@ -1655,5 +1808,10 @@ int main(int argc, char *argv[]) free(filename_csv); } + if (uci_ulsch_matlab_vec) + fclose(uci_ulsch_matlab_vec); + + free_and_zero(UE->phy_sim_test_buf); + return ret; } diff --git a/openair1/SIMULATION/TOOLS/uci_on_pusch_decode.m b/openair1/SIMULATION/TOOLS/uci_on_pusch_decode.m new file mode 100644 index 0000000000..122b4912fb --- /dev/null +++ b/openair1/SIMULATION/TOOLS/uci_on_pusch_decode.m @@ -0,0 +1,79 @@ +% ULSIM command line +% ./nr_ulsim -m 27 -u 1 -R 51 -r 51 -s 300 -L 4 -o + +carrier = nrCarrierConfig; +carrier.NSizeGrid = 51; +carrier.NSlot = 8; +carrier.SubcarrierSpacing = 30; +carrier.CyclicPrefix = "normal"; + +pusch = nrPUSCHConfig; +pusch.PRBSet = 0:carrier.NSizeGrid-1; +pusch.SymbolAllocation = [0,12]; +pusch.MappingType = "B"; +pusch.NID = 0; +pusch.RNTI = 4660; +pusch.NumLayers = 1; +pusch.TransformPrecoding = false; +pusch.TransmissionScheme = "nonCodebook"; +pusch.NumAntennaPorts = 1; +pusch.TPMI = 0; +pusch.Modulation = "64QAM"; + +pusch.DMRS.DMRSConfigurationType = 1; +pusch.DMRS.DMRSTypeAPosition = 2; +pusch.DMRS.NumCDMGroupsWithoutData = 1; +pusch.DMRS.DMRSAdditionalPosition = 0; +pusch.DMRS.NIDNSCID = 0; +pusch.DMRS.NRSID = 0; +pusch.DMRS.NSCID = 0; +pusch.DMRS.GroupHopping = 0; +pusch.DMRS.SequenceHopping = 0; + +pusch.BetaOffsetACK = 20; +pusch.BetaOffsetCSI1 = 6.25; +pusch.BetaOffsetCSI2 = 1; +pusch.UCIScaling = 1; + +[puschIndices,puschIndicesInfo] = nrPUSCHIndices(carrier,pusch); + +dmrsLayerSymbols = nrPUSCHDMRS(carrier,pusch); +dmrsLayerIndices = nrPUSCHDMRSIndices(carrier,pusch); + +run("../../../cmake_targets/ran_build/build/txsig0.m"); +rxGrid = nrOFDMDemodulate(carrier,txs0); +[estChannelGrid,noiseEst] = nrChannelEstimate(carrier,rxGrid,dmrsLayerIndices,dmrsLayerSymbols); +[puschRx,puschHest] = nrExtractResources(puschIndices,rxGrid,estChannelGrid); +[puschEq,csi] = nrEqualizeMMSE(puschRx,puschHest,noiseEst); + +decodeULSCH = nrULSCHDecoder; +decodeULSCH.MultipleHARQProcesses = false; +decodeULSCH.CBGTransmission = false; +decodeULSCH.TargetCodeRate = 910 / 1024; +decodeULSCH.LDPCDecodingAlgorithm = 'Normalized min-sum'; +decodeULSCH.MaximumLDPCIterationCount = 6; +decodeULSCH.TransportBlockLength = 37896; + +oack = 3; +ocsi1 = 0; +ocsi2 = 0; +[ulschLLRs,rxSymbols] = nrPUSCHDecode(carrier,pusch,decodeULSCH.TargetCodeRate,... + decodeULSCH.TransportBlockLength,oack,ocsi1,ocsi2,puschEq,noiseEst); +rmInfo = nrULSCHInfo(pusch,decodeULSCH.TargetCodeRate,... + decodeULSCH.TransportBlockLength,oack,ocsi1,ocsi2); +[culsch,cack,ccsi1,ccsi2] = nrULSCHDemultiplex(pusch,decodeULSCH.TargetCodeRate,... + decodeULSCH.TransportBlockLength,oack,ocsi1,ocsi2,ulschLLRs); + +plot(rxSymbols,'*'); + +decodeULSCH.reset(); +rv = 0; % Redundancy version for decoding +[decodedBits,blkerr] = decodeULSCH(culsch,pusch.Modulation,pusch.NumLayers,rv); +% Display the decoded bits +disp('Block error:'); +disp(blkerr); + +ucibits = nrUCIDecode(cack,oack); +% Display the decoded UCI bits +disp('Decoded UCI bits:'); +disp(ucibits); diff --git a/openair1/SIMULATION/TOOLS/uci_on_pusch_encode.m b/openair1/SIMULATION/TOOLS/uci_on_pusch_encode.m new file mode 100644 index 0000000000..0b83d211d2 --- /dev/null +++ b/openair1/SIMULATION/TOOLS/uci_on_pusch_encode.m @@ -0,0 +1,85 @@ +% ulsim command for same pusch config +% ./nr_ulsim -m 27 -u 1 -R 51 -r 51 -s 300 -o uci_on_pusch_7.bin + +carrier = nrCarrierConfig; +carrier.NSizeGrid = 51; +carrier.NSlot = 8; +carrier.SubcarrierSpacing = 30; +carrier.CyclicPrefix = "normal"; + +pusch = nrPUSCHConfig; +pusch.PRBSet = 0:carrier.NSizeGrid-1; +pusch.SymbolAllocation = [0,12]; +pusch.MappingType = "B"; +pusch.NID = 0; +pusch.RNTI = 4660; +pusch.NumLayers = 1; +pusch.TransformPrecoding = false; +pusch.TransmissionScheme = "nonCodebook"; +pusch.NumAntennaPorts = 1; +pusch.TPMI = 0; +pusch.Modulation = "64QAM"; + +pusch.DMRS.DMRSConfigurationType = 1; +pusch.DMRS.DMRSTypeAPosition = 2; +pusch.DMRS.NumCDMGroupsWithoutData = 1; +pusch.DMRS.DMRSAdditionalPosition = 0; +pusch.DMRS.NIDNSCID = 0; +pusch.DMRS.NRSID = 0; +pusch.DMRS.NSCID = 0; +pusch.DMRS.GroupHopping = 0; +pusch.DMRS.SequenceHopping = 0; + +pusch.BetaOffsetACK = 20; +pusch.BetaOffsetCSI1 = 6.25; +pusch.BetaOffsetCSI2 = 1; +pusch.UCIScaling = 1; + +A = 37896; +rate = 910 / 1024; +rv = 0; +modulation = pusch.Modulation; +nlayers = pusch.NumLayers; % Number of layers for decoding + +oack = 7; +ocsi1 = 0; +ocsi2 = 0; +cbsInfo = nrULSCHInfo(pusch, rate, A, oack, ocsi1, ocsi2); % Get ULSCH information + +ack = randi([0 1],oack,1); +csi1 = randi([0 1],ocsi1,1); +csi2 = randi([0 1],ocsi2,1); +cack = nrUCIEncode(ack,cbsInfo.GACK,pusch.Modulation); +ccsi1 = []; +ccsi2 = []; + +tb_data = randi([0 1],A,1); +% Transport block CRC attachment +tbIn = nrCRCEncode(tb_data,cbsInfo.CRC); + +% Code block segmentation and CRC attachment +cbsIn = nrCodeBlockSegmentLDPC(tbIn,cbsInfo.BGN); + +% LDPC encoding +enc = nrLDPCEncode(cbsIn,cbsInfo.BGN); + +% Rate matching and code block concatenation +chIn = nrRateMatchLDPC(enc,cbsInfo.GULSCH,rv,modulation,nlayers); +culsch = chIn; + + +% Get the codeword and locations of each type (data and UCI) +[cw,indInfo] = nrULSCHMultiplex(pusch,rate,A,culsch,cack,ccsi1,ccsi2); +cw_scr = nrPUSCHScramble(cw,pusch.NID,pusch.RNTI); + +% Write to bin file +fid = fopen('uci_on_pusch_7.bin', 'wb'); +to_write = [A,oack,ocsi1,ocsi2,length(cw),length(cw_scr)]; +fwrite(fid, to_write, 'uint32'); % Write the data to the binary file +fwrite(fid, tb_data, "uint8"); +fwrite(fid, ack, "uint8"); +fwrite(fid, csi1, "uint8"); +fwrite(fid, csi2, "uint8"); +fwrite(fid, cw, "uint8"); +fwrite(fid, cw_scr, "uint8"); +fclose(fid); % Close the file after writing From fd50ff43ccb20bb3a7ede13f80d6ee5f1f1daf0e Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Tue, 29 Jul 2025 10:54:11 +0200 Subject: [PATCH 853/964] Handle gracefully encoding failure in build_RRCReconfiguration_IEs closes #979 --- openair2/RRC/NR/MESSAGES/asn1_msg.c | 34 ++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.c b/openair2/RRC/NR/MESSAGES/asn1_msg.c index 0ed1750d6b..5420348a16 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.c +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.c @@ -545,15 +545,35 @@ static NR_RRCReconfiguration_IEs_t *build_RRCReconfiguration_IEs(const nr_rrc_re /* masterCellGroup */ if (params->cell_group_config) { - // Encode in extension IE (Master cell group) - uint8_t *buf = NULL; - ssize_t len = uper_encode_to_new_buffer(&asn_DEF_NR_CellGroupConfig, NULL, params->cell_group_config, (void **)&buf); - AssertFatal(len > 0, "ASN1 message encoding failed (%lu)!\n", len); + uint8_t temp[4096]; + asn_enc_rval_t enc = uper_encode_to_buffer(&asn_DEF_NR_CellGroupConfig, NULL, params->cell_group_config, temp, sizeof(temp)); + + if (enc.encoded <= 0) { + LOG_E(NR_RRC, "ASN.1 encoding failed for NR_CellGroupConfig (encoded=%ld)\n", enc.encoded); + if (enc.failed_type) { + LOG_E(NR_RRC, "Failed at ASN.1 type: %s\n", enc.failed_type->name); + } + if (enc.structure_ptr) { + LOG_E(NR_RRC, "Failed at structure element: %p\n", enc.structure_ptr); + } + // Print diagnostic information to help debug the issue + LOG_E(NR_RRC, "CellGroupConfig structure that failed to encode:\n"); + xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void *)params->cell_group_config); + ASN_STRUCT_FREE(asn_DEF_NR_RRCReconfiguration_IEs, ie); + return NULL; + } + DevAssert(enc.encoded <= sizeof(temp) * 8); // Encoded data must fit in temp buffer + // Allocate buffer for the encoded data and copy it + // enc.encoded is in bits, convert to bytes + size_t encoded_bytes = (enc.encoded + 7) / 8; + uint8_t *buf = calloc_or_fail(1, encoded_bytes); + memcpy(buf, temp, encoded_bytes); + if (LOG_DEBUGFLAG(DEBUG_ASN1)) { xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void *)params->cell_group_config); } ie->nonCriticalExtension->masterCellGroup = calloc_or_fail(1, sizeof(*ie->nonCriticalExtension->masterCellGroup)); - *ie->nonCriticalExtension->masterCellGroup = (OCTET_STRING_t){.buf = buf, .size = len}; + *ie->nonCriticalExtension->masterCellGroup = (OCTET_STRING_t){.buf = buf, .size = encoded_bytes}; } /* masterKeyUpdate */ @@ -608,6 +628,10 @@ byte_array_t do_RRCReconfiguration(const nr_rrc_reconfig_param_t *params) { byte_array_t msg = {.buf = NULL, .len = 0}; NR_RRCReconfiguration_IEs_t *ie = build_RRCReconfiguration_IEs(params); + if (!ie) { + LOG_E(NR_RRC, "%s: failed to encode RRCReconfiguration\n", __func__); + return msg; + } NR_DL_DCCH_Message_t dl_dcch_msg = {0}; dl_dcch_msg.message.present = NR_DL_DCCH_MessageType_PR_c1; From b4485ecea2ff0fed61242c449ae61009d910b9df Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Thu, 18 Sep 2025 21:58:52 +0200 Subject: [PATCH 854/964] Fix UE context leak in handover failure - Add UE context cleanup before sending handover failure message - Prevents memory/resource leak when PDU session establishment fails during handover - UE context was created but never cleaned up on failure path This fixes a bug where UE contexts would accumulate over time when handovers failed after context creation. --- openair2/RRC/NR/rrc_gNB_NGAP.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index 75e6742422..a7ed703f7d 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -1196,12 +1196,15 @@ int rrc_gNB_process_Handover_Request(gNB_RRC_INST *rrc, instance_t instance, nga if (!trigger_bearer_setup(rrc, UE, msg->nb_of_pdusessions, to_setup, msg->ue_ambr.br_dl)) { LOG_E(NR_RRC, "Failed to establish PDU session: handover failed\n"); + ngap_handover_failure_t fail = { .amf_ue_ngap_id = msg->amf_ue_ngap_id, .cause.type = NGAP_CAUSE_RADIO_NETWORK, .cause.value = NGAP_CAUSE_RADIO_NETWORK_HO_FAILURE_IN_TARGET_5GC_NGRAN_NODE_OR_TARGET_SYSTEM, }; rrc_gNB_send_NGAP_HANDOVER_FAILURE(rrc, &fail); + rrc_remove_ue(rrc, ue_context_p); + return -1; } return 0; From a38aa1bab8cfab44942dbc324cea220201e31c74 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Thu, 18 Sep 2025 22:02:47 +0200 Subject: [PATCH 855/964] Fix memory leaks in fill_removal_lists_from_source_measConfig - Add proper cleanup of allocated ASN.1 structures in all return paths - Fix early returns that were leaking NR_HandoverPreparationInformation - Fix early returns that were leaking NR_RRCReconfiguration - Add cleanup at end of successful function execution This prevents memory leaks when processing handover preparation information during N2 handover procedures. --- openair2/RRC/NR/MESSAGES/asn1_msg.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.c b/openair2/RRC/NR/MESSAGES/asn1_msg.c index 0ed1750d6b..f76f3ee1d1 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.c +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.c @@ -1231,6 +1231,7 @@ void fill_removal_lists_from_source_measConfig(NR_MeasConfig_t *currentMC, byte_ and extract the measConfig provided by the source gNB */ if (!hpi->criticalExtensions.choice.c1->choice.handoverPreparationInformation->sourceConfig) { LOG_W(NR_RRC, "Missing sourceConfig: in source gNB rrcReconfiguration\n"); + ASN_STRUCT_FREE(asn_DEF_NR_HandoverPreparationInformation, hpi); return; } NR_RRCReconfiguration_t *rrcReconf = NULL; @@ -1242,11 +1243,15 @@ void fill_removal_lists_from_source_measConfig(NR_MeasConfig_t *currentMC, byte_ sourceConfig->rrcReconfiguration.size); if (rrcReconf_dec_rval.code != RC_OK || rrcReconf_dec_rval.consumed < 0) { LOG_E(NR_RRC, "Failed to decode source gNB rrcReconfiguration!\n"); + ASN_STRUCT_FREE(asn_DEF_NR_HandoverPreparationInformation, hpi); return; } - if (rrcReconf->criticalExtensions.choice.rrcReconfiguration->measConfig == NULL) + if (rrcReconf->criticalExtensions.choice.rrcReconfiguration->measConfig == NULL) { + ASN_STRUCT_FREE(asn_DEF_NR_HandoverPreparationInformation, hpi); + ASN_STRUCT_FREE(asn_DEF_NR_RRCReconfiguration, rrcReconf); return; + } NR_MeasConfig_t *sourceMC = rrcReconf->criticalExtensions.choice.rrcReconfiguration->measConfig; @@ -1278,6 +1283,10 @@ void fill_removal_lists_from_source_measConfig(NR_MeasConfig_t *currentMC, byte_ asn1cSeqAdd(¤tMC->measIdToRemoveList->list, measId); } } + + // Clean up allocated memory + ASN_STRUCT_FREE(asn_DEF_NR_HandoverPreparationInformation, hpi); + ASN_STRUCT_FREE(asn_DEF_NR_RRCReconfiguration, rrcReconf); } int doRRCReconfiguration_from_HandoverCommand(byte_array_t *ba, const byte_array_t handoverCommand) From 12d92bc836a65b2f09f50d591564845a385b67e7 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 19 Sep 2025 10:33:25 +0200 Subject: [PATCH 856/964] Fix crash in get_du_for_ue when F1 UE data does not exist Add check for cu_exists_f1_ue_data() before calling cu_get_f1_ue_data() to prevent assertion failure when telnet command 'ci fetch_du_by_ue_id' is used for UEs that have been handed over via N2 (and no longer have F1 UE data). This fixes the crash: Assertion (ret == HASH_TABLE_OK && data != ((void *)0)) failed! In get_hashtable_data() /oai-ran/openair2/F1AP/f1ap_ids.c:36 element for ue_id 1 not found The function now returns NULL gracefully when F1 UE data is not available. Co-authored-by: Guido Casati --- openair2/RRC/NR/rrc_gNB_du.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openair2/RRC/NR/rrc_gNB_du.c b/openair2/RRC/NR/rrc_gNB_du.c index db1a9cd459..e104641edc 100644 --- a/openair2/RRC/NR/rrc_gNB_du.c +++ b/openair2/RRC/NR/rrc_gNB_du.c @@ -619,6 +619,8 @@ void rrc_CU_process_f1_lost_connection(gNB_RRC_INST *rrc, f1ap_lost_connection_t nr_rrc_du_container_t *get_du_for_ue(gNB_RRC_INST *rrc, uint32_t ue_id) { + if (!cu_exists_f1_ue_data(ue_id)) + return NULL; f1_ue_data_t ue_data = cu_get_f1_ue_data(ue_id); return get_du_by_assoc_id(rrc, ue_data.du_assoc_id); } From 524a3ddf85412d3750db6db08e9c0f8806cd094a Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Fri, 19 Sep 2025 15:48:09 +0200 Subject: [PATCH 857/964] Fix xer_fprint parameter in ngap_handover_required Fix incorrect xer_fprint parameter - should pass pdu instead of &pdu to properly print ASN.1 structure for debugging. --- openair3/NGAP/ngap_gNB.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair3/NGAP/ngap_gNB.c b/openair3/NGAP/ngap_gNB.c index 46bcf93cad..4331f130a9 100644 --- a/openair3/NGAP/ngap_gNB.c +++ b/openair3/NGAP/ngap_gNB.c @@ -303,7 +303,7 @@ int ngap_handover_required(instance_t instance, ngap_handover_required_t *msg) } if (LOG_DEBUGFLAG(DEBUG_ASN1)) - xer_fprint(stdout, &asn_DEF_NGAP_NGAP_PDU, &pdu); + xer_fprint(stdout, &asn_DEF_NGAP_NGAP_PDU, pdu); byte_array_t out = { .buf = NULL, .len = 0 }; if (ngap_gNB_encode_pdu(pdu, &out.buf, (uint32_t *)&out.len) < 0) { From 235493aa07f87cdfb58c9580e55bb5cf86d5fa4d Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Fri, 19 Sep 2025 15:40:22 +0200 Subject: [PATCH 858/964] Fix ASN.1 memory management ownership in NGAP functions In the current memory management the caller wasn't responsible for freeing memory they allocate. The ngap_gNB_encode_pdu function was taking ownership of PDU contents by calling ASN_STRUCT_FREE_CONTENTS_ONLY, while callers also expected to manage the same memory. This created unclear ownership semantics and potential double-free bugs. - Remove ASN_STRUCT_FREE_CONTENTS_ONLY from ngap_gNB_encode_pdu to prevent double-free - Remove unnecessary ASN_STRUCT_FREE when encode function returns NULL - Add proper ASN_STRUCT_FREE cleanup for heap-allocated PDUs in ngap_gNB.c functions - Add ASN_STRUCT_FREE_CONTENTS_ONLY cleanup for stack-allocated PDUs in NAS and context management functions - Ensure consistent memory cleanup patterns across all NGAP encoder callers - Fix potential memory leaks in all ngap_gNB_encode_pdu call sites This prevents double-free bugs and ensures proper cleanup of ASN.1 structures in both heap and stack allocation scenarios. --- openair3/NGAP/ngap_gNB.c | 16 ++++++++------ .../ngap_gNB_context_management_procedures.c | 4 ++++ openair3/NGAP/ngap_gNB_encoder.c | 1 - openair3/NGAP/ngap_gNB_nas_procedures.c | 22 ++++++++++++++++++- 4 files changed, 34 insertions(+), 9 deletions(-) diff --git a/openair3/NGAP/ngap_gNB.c b/openair3/NGAP/ngap_gNB.c index 4331f130a9..b2ba38de52 100644 --- a/openair3/NGAP/ngap_gNB.c +++ b/openair3/NGAP/ngap_gNB.c @@ -298,7 +298,6 @@ int ngap_handover_required(instance_t instance, ngap_handover_required_t *msg) NGAP_NGAP_PDU_t *pdu = encode_ng_handover_required(msg); if (!pdu) { NGAP_ERROR("Failed to encode Handover Required\n"); - ASN_STRUCT_FREE(asn_DEF_NGAP_NGAP_PDU, pdu); return -1; } @@ -307,11 +306,10 @@ int ngap_handover_required(instance_t instance, ngap_handover_required_t *msg) byte_array_t out = { .buf = NULL, .len = 0 }; if (ngap_gNB_encode_pdu(pdu, &out.buf, (uint32_t *)&out.len) < 0) { - ASN_STRUCT_FREE(asn_DEF_NGAP_NGAP_PDU, pdu); NGAP_ERROR("Failed to encode Handover Required message\n"); + ASN_STRUCT_FREE(asn_DEF_NGAP_NGAP_PDU, pdu); return -1; } - free(pdu); /* UE associated signalling -> use the allocated stream */ ngap_gNB_itti_send_sctp_data_req(ngap_gNB_instance_p->instance, @@ -320,6 +318,7 @@ int ngap_handover_required(instance_t instance, ngap_handover_required_t *msg) out.len, ue_context_p->tx_stream); + ASN_STRUCT_FREE(asn_DEF_NGAP_NGAP_PDU, pdu); return 0; } @@ -342,7 +341,6 @@ static int ngap_gNB_handover_failure(instance_t instance, const ngap_handover_fa NGAP_NGAP_PDU_t *pdu = encode_ng_handover_failure(msg); if (!pdu) { NGAP_ERROR("Failed to encode NG Handover Failure\n"); - ASN_STRUCT_FREE(asn_DEF_NGAP_NGAP_PDU, pdu); return -1; } @@ -364,7 +362,7 @@ static int ngap_gNB_handover_failure(instance_t instance, const ngap_handover_fa } ngap_gNB_itti_send_sctp_data_req(ngap_gNB_instance_p->instance, amf->assoc_id, buffer, length, amf->nextstream); - ASN_STRUCT_FREE(asn_DEF_NGAP_NGAP_PDU, &pdu); + ASN_STRUCT_FREE(asn_DEF_NGAP_NGAP_PDU, pdu); return 0; } @@ -410,7 +408,7 @@ static int ngap_gNB_handover_request_acknowledge(instance_t instance, ngap_hando /* UE associated signalling -> use the allocated stream */ ngap_gNB_itti_send_sctp_data_req(ngap->instance, ue_context_p.amf_ref->assoc_id, ba.buf, ba.len, ue_context_p.tx_stream); NGAP_INFO("Sent Handover Request Acknowledge to AMF\n"); - + ASN_STRUCT_FREE(asn_DEF_NGAP_NGAP_PDU, pdu); return 0; } @@ -450,6 +448,7 @@ static int ngap_gNB_handover_notify(instance_t instance, const ngap_handover_not ba.buf, ba.len, ue_context_p->tx_stream); + ASN_STRUCT_FREE(asn_DEF_NGAP_NGAP_PDU, pdu); return 0; } @@ -489,7 +488,6 @@ static int ngap_gNB_handover_cancel(instance_t instance, const ngap_handover_can ASN_STRUCT_FREE(asn_DEF_NGAP_NGAP_PDU, pdu); return -1; } - ASN_STRUCT_FREE(asn_DEF_NGAP_NGAP_PDU, pdu); /* UE-associated signalling -> use the UE's allocated SCTP stream */ ngap_gNB_itti_send_sctp_data_req(ngap_gNB_instance_p->instance, @@ -498,6 +496,7 @@ static int ngap_gNB_handover_cancel(instance_t instance, const ngap_handover_can ba.len, ue_context_p->tx_stream); + ASN_STRUCT_FREE(asn_DEF_NGAP_NGAP_PDU, pdu); return 0; } @@ -530,6 +529,7 @@ int ngap_gNB_handle_ul_ran_status_transfer(instance_t instance, const ngap_ran_s } ngap_gNB_itti_send_sctp_data_req(instance, ue_context_p->amf_ref->assoc_id, out.buf, out.len, ue_context_p->tx_stream); + ASN_STRUCT_FREE(asn_DEF_NGAP_NGAP_PDU, pdu); return 0; } @@ -769,11 +769,13 @@ static int ngap_gNB_generate_ng_setup_request( if (ngap_gNB_encode_pdu(&pdu, &buffer, &len) < 0) { NGAP_ERROR("Failed to encode NG setup request\n"); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu); return -1; } /* Non UE-Associated signalling -> stream = 0 */ ngap_gNB_itti_send_sctp_data_req(instance_p->instance, ngap_amf_data_p->assoc_id, buffer, len, 0); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu); return ret; } diff --git a/openair3/NGAP/ngap_gNB_context_management_procedures.c b/openair3/NGAP/ngap_gNB_context_management_procedures.c index 7abbec2592..7f114d5bf6 100644 --- a/openair3/NGAP/ngap_gNB_context_management_procedures.c +++ b/openair3/NGAP/ngap_gNB_context_management_procedures.c @@ -111,6 +111,7 @@ int ngap_ue_context_release_complete(instance_t instance, if (ngap_gNB_encode_pdu(&pdu, &buffer, &length) < 0) { /* Encode procedure has failed... */ NGAP_ERROR("Failed to encode UE context release complete\n"); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu); return -1; } @@ -125,6 +126,7 @@ int ngap_ue_context_release_complete(instance_t instance, ngap_gNB_ue_context_t *tmp = ngap_detach_ue_context(ue_release_complete_p->gNB_ue_ngap_id); if (tmp) free(tmp); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu); return 0; } @@ -207,6 +209,7 @@ int ngap_ue_context_release_req(instance_t instance, if (ngap_gNB_encode_pdu(&pdu, &buffer, &length) < 0) { /* Encode procedure has failed... */ NGAP_ERROR("Failed to encode UE context release complete\n"); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu); return -1; } @@ -215,6 +218,7 @@ int ngap_ue_context_release_req(instance_t instance, ue_context_p->amf_ref->assoc_id, buffer, length, ue_context_p->tx_stream); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu); return 0; } diff --git a/openair3/NGAP/ngap_gNB_encoder.c b/openair3/NGAP/ngap_gNB_encoder.c index 7a7ce758e1..be3945c2f0 100644 --- a/openair3/NGAP/ngap_gNB_encoder.c +++ b/openair3/NGAP/ngap_gNB_encoder.c @@ -148,6 +148,5 @@ int ngap_gNB_encode_pdu(NGAP_NGAP_PDU_t *pdu, uint8_t **buffer, uint32_t *len) NGAP_DEBUG("Unknown message outcome (%d) or not implemented", (int)pdu->present); return -1; } - ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, pdu); return ret; } diff --git a/openair3/NGAP/ngap_gNB_nas_procedures.c b/openair3/NGAP/ngap_gNB_nas_procedures.c index fe86d7c5e0..cff9cd0b72 100644 --- a/openair3/NGAP/ngap_gNB_nas_procedures.c +++ b/openair3/NGAP/ngap_gNB_nas_procedures.c @@ -259,8 +259,11 @@ int ngap_gNB_handle_nas_first_req(instance_t instance, ngap_nas_first_req_t *UEf ie->value.choice.UEContextRequest = NGAP_UEContextRequest_requested; } - if (ngap_gNB_encode_pdu(&pdu, &buffer, &length) < 0) + if (ngap_gNB_encode_pdu(&pdu, &buffer, &length) < 0) { + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu); DevMessage("Failed to encode initial UE message\n"); + return -1; + } /* Update the current NGAP UE state */ ue_desc_p.ue_state = NGAP_UE_WAITING_CSR; @@ -288,6 +291,7 @@ int ngap_gNB_handle_nas_first_req(instance_t instance, ngap_nas_first_req_t *UEf /* Send encoded message over sctp */ ngap_gNB_itti_send_sctp_data_req(instance_p->instance, amf->assoc_id, buffer, length, ue_desc_p.tx_stream); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu); return 0; } @@ -454,6 +458,7 @@ int ngap_gNB_nas_uplink(instance_t instance, ngap_uplink_nas_t *ngap_uplink_nas_ if (ngap_gNB_encode_pdu(&pdu, &buffer, &length) < 0) { NGAP_ERROR("Failed to encode uplink NAS transport\n"); /* Encode procedure has failed... */ + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu); return -1; } @@ -462,6 +467,7 @@ int ngap_gNB_nas_uplink(instance_t instance, ngap_uplink_nas_t *ngap_uplink_nas_ ue_context_p->amf_ref->assoc_id, buffer, length, ue_context_p->tx_stream); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu); return 0; } @@ -535,6 +541,7 @@ int ngap_gNB_nas_non_delivery_ind(instance_t instance, if (ngap_gNB_encode_pdu(&pdu, &buffer, &length) < 0) { NGAP_ERROR("Failed to encode NAS NON delivery indication\n"); /* Encode procedure has failed... */ + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu); return -1; } @@ -543,6 +550,7 @@ int ngap_gNB_nas_non_delivery_ind(instance_t instance, ue_context_p->amf_ref->assoc_id, buffer, length, ue_context_p->tx_stream); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu); return 0; } @@ -704,6 +712,7 @@ int ngap_gNB_initial_ctxt_resp(instance_t instance, ngap_initial_context_setup_r if (ngap_gNB_encode_pdu(&pdu, &buffer, &length) < 0) { NGAP_ERROR("Failed to encode InitialContextSetupResponse\n"); /* Encode procedure has failed... */ + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu); return -1; } @@ -711,6 +720,7 @@ int ngap_gNB_initial_ctxt_resp(instance_t instance, ngap_initial_context_setup_r LOG_I(NR_RRC,"Send message to sctp: NGAP_InitialContextSetupResponse\n"); ngap_gNB_itti_send_sctp_data_req(ngap_gNB_instance_p->instance, ue_context_p->amf_ref->assoc_id, buffer, length, ue_context_p->tx_stream); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu); return 0; } @@ -785,6 +795,7 @@ int ngap_gNB_initial_ctxt_fail(instance_t instance, ngap_initial_context_setup_f if (ngap_gNB_encode_pdu(&pdu, &buffer, &length) < 0) { NGAP_ERROR("Failed to encode InitialContextSetupFailure\n"); /* Encode procedure has failed... */ + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu); return -1; } /* UE associated signalling -> use the allocated stream */ @@ -794,6 +805,7 @@ int ngap_gNB_initial_ctxt_fail(instance_t instance, ngap_initial_context_setup_f buffer, length, ue_context_p->tx_stream); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu); return 0; } @@ -866,11 +878,13 @@ int ngap_gNB_ue_capabilities(instance_t instance, ngap_ue_cap_info_ind_t *ue_cap if (ngap_gNB_encode_pdu(&pdu, &buffer, &length) < 0) { /* Encode procedure has failed... */ NGAP_ERROR("Failed to encode UE radio capabilities indication\n"); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu); return -1; } /* UE associated signalling -> use the allocated stream */ ngap_gNB_itti_send_sctp_data_req(ngap_gNB_instance_p->instance, ue_context_p->amf_ref->assoc_id, buffer, length, ue_context_p->tx_stream); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu); return 0; } @@ -990,11 +1004,13 @@ int ngap_gNB_pdusession_setup_resp(instance_t instance, ngap_pdusession_setup_re if (ngap_gNB_encode_pdu(&pdu, &buffer, &length) < 0) { NGAP_ERROR("Failed to encode uplink transport\n"); /* Encode procedure has failed... */ + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu); return -1; } /* UE associated signalling -> use the allocated stream */ ngap_gNB_itti_send_sctp_data_req(ngap_gNB_instance_p->instance, ue_context_p->amf_ref->assoc_id, buffer, length, ue_context_p->tx_stream); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu); return 0; } @@ -1128,12 +1144,14 @@ int ngap_gNB_pdusession_modify_resp(instance_t instance, ngap_pdusession_modify_ if (ngap_gNB_encode_pdu(&pdu, &buffer, &length) < 0) { NGAP_ERROR("Failed to encode uplink transport\n"); /* Encode procedure has failed... */ + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu); return -1; } /* UE associated signalling -> use the allocated stream */ ngap_gNB_itti_send_sctp_data_req(ngap_gNB_instance_p->instance, ue_context_p->amf_ref->assoc_id, buffer, length, ue_context_p->tx_stream); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu); return 0; } //------------------------------------------------------------------------------ @@ -1201,6 +1219,7 @@ int ngap_gNB_pdusession_release_resp(instance_t instance, ngap_pdusession_releas if (ngap_gNB_encode_pdu(&pdu, &buffer, &length) < 0) { NGAP_ERROR("Failed to encode release response\n"); /* Encode procedure has failed... */ + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu); return -1; } @@ -1211,6 +1230,7 @@ int ngap_gNB_pdusession_release_resp(instance_t instance, ngap_pdusession_releas (uint64_t)ue_context_p->amf_ue_ngap_id, pdusession_release_resp_p->nb_of_pdusessions_released); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu); return 0; } From de07668b0bb07ac2f542fdced61e6153de7f4bfc Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Fri, 19 Sep 2025 15:58:40 +0200 Subject: [PATCH 859/964] Fix potential memory leak in ngap_gNB_handover_request_acknowledge Move UE context creation and storage to after successful PDU encoding to prevent memory leaks if encoding fails. Also add proper PDU cleanup when AMF fetch fails and use consistent NULL check style. This ensures UE context is only stored when the operation is guaranteed to succeed, improving error handling and memory management. --- openair3/NGAP/ngap_gNB.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/openair3/NGAP/ngap_gNB.c b/openair3/NGAP/ngap_gNB.c index b2ba38de52..68e77d369c 100644 --- a/openair3/NGAP/ngap_gNB.c +++ b/openair3/NGAP/ngap_gNB.c @@ -376,20 +376,6 @@ static int ngap_gNB_handover_request_acknowledge(instance_t instance, ngap_hando DevAssert(msg != NULL); DevAssert(ngap != NULL); - // First, create and store NGAP UE context - ngap_gNB_ue_context_t ue_context_p = { - .amf_ref = ngap_gNB_get_AMF_from_instance(ngap), - .gNB_ue_ngap_id = msg->gNB_ue_ngap_id, - .amf_ue_ngap_id = msg->amf_ue_ngap_id, - .gNB_instance = ngap, - .ue_state = NGAP_UE_CONNECTED, - }; - if (ue_context_p.amf_ref == NULL) { - NGAP_ERROR("Failed to fetch AMF for current NGAP instance\n"); - return -1; - } - ngap_store_ue_context(&ue_context_p); - NGAP_NGAP_PDU_t *pdu = encode_ng_handover_request_ack(msg); if (!pdu) { NGAP_ERROR("Failed to encode NG Handover Request Acknowledge\n"); @@ -405,6 +391,21 @@ static int ngap_gNB_handover_request_acknowledge(instance_t instance, ngap_hando return -1; } + // Create and store NGAP UE context + ngap_gNB_ue_context_t ue_context_p = { + .amf_ref = ngap_gNB_get_AMF_from_instance(ngap), + .gNB_ue_ngap_id = msg->gNB_ue_ngap_id, + .amf_ue_ngap_id = msg->amf_ue_ngap_id, + .gNB_instance = ngap, + .ue_state = NGAP_UE_CONNECTED, + }; + if (!ue_context_p.amf_ref) { + NGAP_ERROR("Failed to fetch AMF for current NGAP instance\n"); + ASN_STRUCT_FREE(asn_DEF_NGAP_NGAP_PDU, pdu); + return -1; + } + ngap_store_ue_context(&ue_context_p); + /* UE associated signalling -> use the allocated stream */ ngap_gNB_itti_send_sctp_data_req(ngap->instance, ue_context_p.amf_ref->assoc_id, ba.buf, ba.len, ue_context_p.tx_stream); NGAP_INFO("Sent Handover Request Acknowledge to AMF\n"); From 13571587224ab11a191fc9751d02a868cfbce345 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Fri, 19 Sep 2025 16:51:34 +0200 Subject: [PATCH 860/964] Fix hardcoded instance 0 bug in UE context release command Use the instance parameter instead of hardcoded 0 to access the correct RRC instance. Also clean up redundant variable initialization. --- openair2/RRC/NR/rrc_gNB_NGAP.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index a7ed703f7d..95fbf72d5d 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -1306,9 +1306,8 @@ void rrc_gNB_free_Handover_Command(ngap_handover_command_t *msg) */ int rrc_gNB_process_NGAP_UE_CONTEXT_RELEASE_COMMAND(MessageDef *msg_p, instance_t instance) { - gNB_RRC_INST *rrc = RC.nrrrc[0]; - uint32_t gNB_ue_ngap_id = 0; - gNB_ue_ngap_id = NGAP_UE_CONTEXT_RELEASE_COMMAND(msg_p).gNB_ue_ngap_id; + gNB_RRC_INST *rrc = RC.nrrrc[instance]; + uint32_t gNB_ue_ngap_id = NGAP_UE_CONTEXT_RELEASE_COMMAND(msg_p).gNB_ue_ngap_id; rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(RC.nrrrc[instance], gNB_ue_ngap_id); if (ue_context_p == NULL) { From 59803e221f7a5cdb9fdca6bbbe154d8049c8d019 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Mon, 22 Sep 2025 10:31:18 +0200 Subject: [PATCH 861/964] Fix duplicate handover request handling - Add early check for existing UE context by AMF UE NGAP ID at beginning of rrc_gNB_process_Handover_Request - Add dedicated function to get UE context by AMF UE NGAP ID: rrc_gNB_get_ue_context_by_amf_ue_ngap_id() - Send handover failure with appropriate cause if UE context already exists - Remove redundant ho_context NULL check that could never be true for newly created UE contexts - Prevents duplicate handover processing and resource leaks --- openair2/RRC/NR/rrc_gNB_NGAP.c | 17 +++++++++++++---- openair2/RRC/NR/rrc_gNB_UE_context.c | 12 ++++++++++++ openair2/RRC/NR/rrc_gNB_UE_context.h | 1 + 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index 95fbf72d5d..4c5b504f2d 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -1129,6 +1129,19 @@ void rrc_gNB_send_NGAP_HANDOVER_FAILURE(gNB_RRC_INST *rrc, ngap_handover_failure /** @brief Process NG Handover Request message (8.4.2.2 3GPP TS 38.413) */ int rrc_gNB_process_Handover_Request(gNB_RRC_INST *rrc, instance_t instance, ngap_handover_request_t *msg) { + // Check if UE context already exists for this AMF UE NGAP ID + rrc_gNB_ue_context_t *existing_ue_context = rrc_gNB_get_ue_context_by_amf_ue_ngap_id(rrc, msg->amf_ue_ngap_id); + if (existing_ue_context != NULL) { + LOG_E(RRC, "UE context already exists for AMF UE NGAP ID %ld, cannot process handover request\n", msg->amf_ue_ngap_id); + ngap_handover_failure_t fail = { + .amf_ue_ngap_id = msg->amf_ue_ngap_id, + .cause.type = NGAP_CAUSE_RADIO_NETWORK, + .cause.value = NGAP_CAUSE_RADIO_NETWORK_HO_FAILURE_IN_TARGET_5GC_NGRAN_NODE_OR_TARGET_SYSTEM, + }; + rrc_gNB_send_NGAP_HANDOVER_FAILURE(rrc, &fail); + return -1; + } + struct nr_rrc_du_container_t *du = get_du_by_cell_id(rrc, msg->nr_cell_id); if (du == NULL) { /* Cell Not Found! Return HO Request Failure*/ @@ -1150,10 +1163,6 @@ int rrc_gNB_process_Handover_Request(gNB_RRC_INST *rrc, instance_t instance, nga gNB_RRC_UE_t *UE = &ue_context_p->ue_context; // allocate context for target - if (UE->ho_context != NULL) { - LOG_E(NR_RRC, "Ongoing handover for UE %d, cannot trigger new\n", UE->rrc_ue_id); - return -1; - } UE->ho_context = alloc_ho_ctx(HO_CTX_TARGET); UE->ho_context->target->ho_trigger = nr_rrc_trigger_n2_ho_target; diff --git a/openair2/RRC/NR/rrc_gNB_UE_context.c b/openair2/RRC/NR/rrc_gNB_UE_context.c index 412c5231cc..9a2c3fb6f6 100644 --- a/openair2/RRC/NR/rrc_gNB_UE_context.c +++ b/openair2/RRC/NR/rrc_gNB_UE_context.c @@ -122,6 +122,18 @@ rrc_gNB_ue_context_t *rrc_gNB_get_ue_context_by_rnti_any_du(gNB_RRC_INST *rrc_in return NULL; } +/** @brief Fetch UE Context by the unique AMF UE NGAP ID */ +rrc_gNB_ue_context_t *rrc_gNB_get_ue_context_by_amf_ue_ngap_id(gNB_RRC_INST *rrc_instance_pP, uint64_t amf_ue_ngap_id) +{ + rrc_gNB_ue_context_t *ue_context_p; + RB_FOREACH (ue_context_p, rrc_nr_ue_tree_s, &(rrc_instance_pP->rrc_ue_head)) { + if (ue_context_p->ue_context.amf_ue_ngap_id == amf_ue_ngap_id) { + return ue_context_p; + } + } + return NULL; +} + void rrc_gNB_free_mem_ue_context(rrc_gNB_ue_context_t *const ue_context_pP) //----------------------------------------------------------------------------- { diff --git a/openair2/RRC/NR/rrc_gNB_UE_context.h b/openair2/RRC/NR/rrc_gNB_UE_context.h index 9485672463..b8edd159c4 100644 --- a/openair2/RRC/NR/rrc_gNB_UE_context.h +++ b/openair2/RRC/NR/rrc_gNB_UE_context.h @@ -46,6 +46,7 @@ rrc_gNB_ue_context_t* rrc_gNB_allocate_new_ue_context(gNB_RRC_INST* rrc_instance rrc_gNB_ue_context_t* rrc_gNB_get_ue_context(gNB_RRC_INST* rrc_instance_pP, ue_id_t ue); rrc_gNB_ue_context_t* rrc_gNB_get_ue_context_by_rnti(gNB_RRC_INST* rrc_instance_pP, sctp_assoc_t assoc_id, rnti_t rntiP); rrc_gNB_ue_context_t* rrc_gNB_get_ue_context_by_rnti_any_du(gNB_RRC_INST* rrc_instance_pP, rnti_t rntiP); +rrc_gNB_ue_context_t* rrc_gNB_get_ue_context_by_amf_ue_ngap_id(gNB_RRC_INST* rrc_instance_pP, uint64_t amf_ue_ngap_id); void rrc_gNB_free_mem_ue_context(rrc_gNB_ue_context_t* const ue_context_pP); From 487de67ff8eb3b4f32ee03b6fc95e2c8b5fc984c Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Tue, 23 Sep 2025 14:52:37 +0200 Subject: [PATCH 862/964] Fix measurement configuration memory leak with stack allocation - Replace heap allocation with stack allocation for seq_arr_t structures - Use proper seq_arr_free() with free functions for ASN.1 structures - Remove unnecessary malloc/free calls for sequence containers - Improve memory safety and performance with automatic cleanup Fixes 128-byte memory leak: Direct leak of 128 byte(s) in 2 object(s) allocated from: /#0 0x7e7f39ab4a57 in __interceptor_calloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:154 /#1 0x56df8b07312d in SEQUENCE_decode_uper /home/guido/repo/openairinterface5g/develop/cmake_targets/ran_build/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE_uper.c:37 /#2 0x56df8b056551 in uper_decode /home/guido/repo/openairinterface5g/develop/cmake_targets/ran_build/build/openair2/RRC/LTE/MESSAGES/uper_decoder.c:83 /#3 0x56df8a896b1b in get_nr_mtc /home/guido/repo/openairinterface5g/develop/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c:4216 /#4 0x56df8a82feb8 in ue_context_setup_request /home/guido/repo/openairinterface5g/develop/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c:635 /#5 0x56df8a66a298 in nr_initiate_handover /home/guido/repo/openairinterface5g/develop/openair2/RRC/NR/rrc_gNB_mobility.c:218 /#6 0x56df8a6720af in nr_rrc_trigger_n2_ho_target /home/guido/repo/openairinterface5g/develop/openair2/RRC/NR/rrc_gNB_mobility.c:526 /#7 0x56df8a5cf338 in rrc_gNB_process_e1_bearer_context_setup_resp /home/guido/repo/openairinterface5g/develop/openair2/RRC/NR/rrc_gNB.c:2633 /#8 0x56df8a5d28ab in rrc_gnb_task /home/guido/repo/openairinterface5g/develop/openair2/RRC/NR/rrc_gNB.c:3012 /#9 0x7e7f38494ac2 in start_thread nptl/pthread_create.c:442 --- openair2/RRC/NR/MESSAGES/asn1_msg.c | 6 +++++- openair2/RRC/NR/rrc_gNB.c | 28 +++++++++++++++++----------- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.c b/openair2/RRC/NR/MESSAGES/asn1_msg.c index f76f3ee1d1..d711217fbb 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.c +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.c @@ -1121,7 +1121,11 @@ NR_MeasConfig_t *get_MeasConfig(const NR_MeasTiming_t *mt, if (rc_A3_seq) { for (int i = 0; i < rc_A3_seq->size; i++) { NR_ReportConfigToAddMod_t *rc_A3 = (NR_ReportConfigToAddMod_t *)seq_arr_at(rc_A3_seq, i); - asn1cSeqAdd(&mc->reportConfigToAddModList->list, rc_A3); + // Create a deep copy of the report config + NR_ReportConfigToAddMod_t *rc_A3_copy = NULL; + int result = asn_copy(&asn_DEF_NR_ReportConfigToAddMod, (void **)&rc_A3_copy, rc_A3); + AssertFatal(result >= 0, "error during asn_copy() of ReportConfigToAddMod\n"); + asn1cSeqAdd(&mc->reportConfigToAddModList->list, rc_A3_copy); } } diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index cc766b9d81..2661531c27 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -638,11 +638,14 @@ NR_MeasConfig_t *nr_rrc_get_measconfig(const gNB_RRC_INST *rrc, uint64_t nr_cell nr_rrc_du_container_t *du = get_du_by_cell_id((gNB_RRC_INST *)rrc, nr_cellid); DevAssert(du != NULL); f1ap_served_cell_info_t *cell_info = &du->setup_req->cell[0].info; - NR_ReportConfigToAddMod_t *rc_PER = NULL; - NR_ReportConfigToAddMod_t *rc_A2 = NULL; - seq_arr_t *rc_A3_seq = NULL; - seq_arr_t *neigh_seq = NULL; + if (du->mtc != NULL) { + NR_ReportConfigToAddMod_t *rc_PER = NULL; + NR_ReportConfigToAddMod_t *rc_A2 = NULL; + seq_arr_t rc_A3_seq = {0}; + seq_arr_t neigh_seq = {0}; + seq_arr_init(&rc_A3_seq, sizeof(NR_ReportConfigToAddMod_t)); + seq_arr_init(&neigh_seq, sizeof(nr_neighbour_cell_t)); int scs = get_ssb_scs(cell_info); int band = get_dl_band(cell_info); const NR_MeasTimingList_t *mtlist = du->mtc->criticalExtensions.choice.c1->choice.measTimingConf->measTiming; @@ -657,21 +660,17 @@ NR_MeasConfig_t *nr_rrc_get_measconfig(const gNB_RRC_INST *rrc, uint64_t nr_cell If no related A3 but there is default add the default one. If default one added once as a report, no need to add it again && duplication. */ - rc_A3_seq = malloc(sizeof(seq_arr_t)); - neigh_seq = malloc(sizeof(seq_arr_t)); - seq_arr_init(rc_A3_seq, sizeof(NR_ReportConfigToAddMod_t)); - seq_arr_init(neigh_seq, sizeof(nr_neighbour_cell_t)); LOG_D(NR_RRC, "Preparing A3 Event Measurement Configuration!\n"); bool default_a3_added = false; // To ensure that the default configuration is only added once for (int i = 0; i < neighbour_cells->size; i++) { nr_neighbour_cell_t *neighbourCell = (nr_neighbour_cell_t *)seq_arr_at(neighbour_cells, i); if (default_a3_added && neighbourCell->physicalCellId == -1) continue; - seq_arr_push_back(neigh_seq, neighbourCell, sizeof(nr_neighbour_cell_t)); + seq_arr_push_back(&neigh_seq, neighbourCell, sizeof(nr_neighbour_cell_t)); const nr_a3_event_t *a3Event = get_a3_configuration((gNB_RRC_INST *)rrc, neighbourCell->physicalCellId); if (a3Event) { NR_ReportConfigId_t reportConfigId = neighbourCell->physicalCellId == -1 ? 3 : i + 4; - seq_arr_push_back(rc_A3_seq, prepare_a3_event_report(a3Event, reportConfigId), sizeof(NR_ReportConfigToAddMod_t)); + seq_arr_push_back(&rc_A3_seq, prepare_a3_event_report(a3Event, reportConfigId), sizeof(NR_ReportConfigToAddMod_t)); if (neighbourCell->physicalCellId == -1) default_a3_added = true; } @@ -681,7 +680,14 @@ NR_MeasConfig_t *nr_rrc_get_measconfig(const gNB_RRC_INST *rrc, uint64_t nr_cell rc_PER = prepare_periodic_event_report(rrc->measurementConfiguration.per_event); if (rrc->measurementConfiguration.a2_event) rc_A2 = prepare_a2_event_report(rrc->measurementConfiguration.a2_event); - return get_MeasConfig(mt, band, scs, cell_info->nr_pci, rc_PER, rc_A2, rc_A3_seq, neigh_seq); + + NR_MeasConfig_t *result = get_MeasConfig(mt, band, scs, cell_info->nr_pci, rc_PER, rc_A2, &rc_A3_seq, &neigh_seq); + + // Clean up sequence arrays + seq_arr_free(&rc_A3_seq, NULL); + seq_arr_free(&neigh_seq, NULL); + + return result; } return NULL; } From 915c41c127e48bd09c5905a5bc52246a60d7270c Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Tue, 23 Sep 2025 16:10:48 +0200 Subject: [PATCH 863/964] Fix MTC sequence memory leak in UE context setup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add missing ASN_STRUCT_FREE for NR_MeasurementTimingConfiguration in ue_context_setup_request - Fix 64-byte MTC sequence leak in get_nr_mtc → SEQUENCE_decode_uper AddressSanitizer backtrace: Direct leak of 64 byte(s) in 1 object(s) allocated from: /#0 0x7dcfcb8b4a57 in __interceptor_calloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:154 /#1 0x591fcc59b67d in SEQUENCE_decode_uper /home/guido/repo/openairinterface5g/develop/cmake_targets/ran_build/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE_uper.c:37 /#2 0x591fcc57eaa1 in uper_decode /home/guido/repo/openairinterface5g/develop/openair2/RRC/LTE/MESSAGES/uper_decoder.c:83 /#3 0x591fcbdbedeb in get_nr_mtc /home/guido/repo/openairinterface5g/develop/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c:4216 /#4 0x591fcbd58188 in ue_context_setup_request /home/guido/repo/openairinterface5g/develop/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c:635 /#5 0x591fcbb92568 in nr_initiate_handover /home/guido/repo/openairinterface5g/develop/openair2/RRC/NR/rrc_gNB_mobility.c:218 /#6 0x591fcbb9a37f in nr_rrc_trigger_n2_ho_target /home/guido/repo/openairinterface5g/develop/openair2/RRC/NR/rrc_gNB_mobility.c:526 /#7 0x591fcbaf7608 in rrc_gNB_process_e1_bearer_context_setup_resp /home/guido/repo/openairinterface5g/develop/openair2/RRC/NR/rrc_gNB.c:2640 /#8 0x591fcbafab7b in rrc_gnb_task /home/guido/repo/openairinterface5g/develop/openair2/RRC/NR/rrc_gNB.c:3019 /#9 0x7dcfca294ac2 in start_thread nptl/pthread_create.c:442 Root cause: ue_context_setup_request allocated NR_MeasurementTimingConfiguration via get_nr_mtc() but never freed it after creating the measurement gap configuration. The create_measgap_config function only reads from the structure and doesn't take ownership, so the caller must free it. --- openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c | 1 + 1 file changed, 1 insertion(+) diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c index b3d596b524..debc0d5530 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -721,6 +721,7 @@ void ue_context_setup_request(const f1ap_ue_context_setup_req_t *req) /* free the memory we allocated above */ free_ue_context_setup_resp(&resp); ASN_STRUCT_FREE(asn_DEF_NR_CG_ConfigInfo, cg_configinfo); + ASN_STRUCT_FREE(asn_DEF_NR_MeasurementTimingConfiguration, mtc); } void ue_context_modification_request(const f1ap_ue_context_mod_req_t *req) From ff3245ea90a04ad071180f68de74f675ae19313c Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Wed, 17 Sep 2025 12:47:12 +0200 Subject: [PATCH 864/964] Enable ULSCH performance logging in nr_ulsim --- openair1/SIMULATION/tests/CMakeLists.txt | 106 +++++++++++------------ 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/openair1/SIMULATION/tests/CMakeLists.txt b/openair1/SIMULATION/tests/CMakeLists.txt index 9602d6d1f4..1d41b1fba9 100644 --- a/openair1/SIMULATION/tests/CMakeLists.txt +++ b/openair1/SIMULATION/tests/CMakeLists.txt @@ -274,59 +274,59 @@ add_physim_test(physim.5g.nr_pucchsim.test29 "Format 2 64-bit 16/273 PRB Delay 2 ###### nr_ulsim unit test ###### #################################################################################### -add_physim_test(physim.5g.nr_ulsim.misc.test1 "MCS 9 106 PRBs" nr_ulsim -n300 -m9 -r106 -s5) -add_physim_test(physim.5g.nr_ulsim.misc.test2 "MCS 16 50 PRBs" nr_ulsim -n300 -m16 -s10) -add_physim_test(physim.5g.nr_ulsim.misc.test3 "MCS 28 50 PRBs" nr_ulsim -n300 -m28 -s20) -add_physim_test(physim.5g.nr_ulsim.misc.test4 "MCS 27 50 PRBs 256QAM" nr_ulsim -n300 -m27 -s25 -q1) -add_physim_test(physim.5g.nr_ulsim.misc.test5 "MCS 9 217 PRBs" nr_ulsim -n300 -m9 -R217 -r217 -s5) -add_physim_test(physim.5g.nr_ulsim.misc.test6 "MCS 9 273 PRBs" nr_ulsim -n300 -m9 -R273 -r273 -s5) -add_physim_test(physim.5g.nr_ulsim.misc.test7 "PUSCH Type A, 2 DMRS Symbols" nr_ulsim -n300 -s5 -U 0,1,1,1) -add_physim_test(physim.5g.nr_ulsim.misc.test8 "PUSCH Type A, 3 DMRS, 4 PTRS, 5 Interpolated Symbols" nr_ulsim -n300 -s5 -T 1,2 -U 0,2,1,1) -add_physim_test(physim.5g.nr_ulsim.misc.test9 "PUSCH Type B, 3 DMRS, 2 PTRS, 7 Interpolated Symbols" nr_ulsim -n300 -s5 -T 2,2 -U 1,2,1,1) -add_physim_test(physim.5g.nr_ulsim.misc.test10 "PUSCH Type B, 3 DMRS, 2 PTRS, 3 Interpolated Symbols" nr_ulsim -n300 -s5 -a4 -b8 -T 1,2 -U 1,3,1,1) -add_physim_test(physim.5g.nr_ulsim.misc.test11 "25 PRBs, 15 kHz SCS" nr_ulsim -n300 -u0 -m0 -R25 -r25 -i 1,0) -add_physim_test(physim.5g.nr_ulsim.misc.test12 "32 PRBs, 120 kHz SCS" nr_ulsim -n300 -s5 -r32 -R32 -u3) -add_physim_test(physim.5g.nr_ulsim.misc.test13 "MCS 0, low SNR performance" nr_ulsim -n300 -m0 -S -0.6 -i 1,0) -add_physim_test(physim.5g.nr_ulsim.misc.test14 "MCS 28, 106 PRBs, Time shift 8" nr_ulsim -n300 -m28 -R106 -r106 -t90 -s24 -S24 -d 8) -add_physim_test(physim.5g.nr_ulsim.misc.test15 "SRS, SNR 40 dB" nr_ulsim -n300 -s40 -E 1) -add_physim_test(physim.5g.nr_ulsim.sc-fdma.test1 "SC-FDMA, 50 PRBs" nr_ulsim -n300 -s5 -Z) -add_physim_test(physim.5g.nr_ulsim.sc-fdma.test2 "SC-FDMA, 75 PRBs" nr_ulsim -n300 -s5 -Z -r75) -add_physim_test(physim.5g.nr_ulsim.sc-fdma.test3 "SC-FDMA, 216 PRBs" nr_ulsim -n150 -s5 -Z -r216 -R217) -add_physim_test(physim.5g.nr_ulsim.sc-fdma.test4 "SC-FDMA, 273 PRBs" nr_ulsim -n150 -s5 -Z -r270 -R273) -add_physim_test(physim.5g.nr_ulsim.sc-fdma.test5 "SC-FDMA, 3 DMRS" nr_ulsim -n300 -s5 -Z -U 0,2,1,2) -add_physim_test(physim.5g.nr_ulsim.mimo.test1 "MCS 19 50 PRBs 2 RX_Antenna" nr_ulsim -n300 -m19 -s10 -S15 -z2) -add_physim_test(physim.5g.nr_ulsim.mimo.test2 "MCS 9 106 PRBs MIMO 2 layers" nr_ulsim -n300 -m9 -r106 -s8 -W2 -y2 -z2) -add_physim_test(physim.5g.nr_ulsim.mimo.test3 "MCS 10 106 PRBs MIMO 2 layers" nr_ulsim -n300 -m10 -r106 -s12 -W2 -y2 -z2) -add_physim_test(physim.5g.nr_ulsim.mimo.test4 "MCS 19 106 PRBs MIMO 2 layers" nr_ulsim -n300 -m19 -r106 -s22 -W2 -y2 -z2) -add_physim_test(physim.5g.nr_ulsim.mimo.test5 "MCS 9 106 PRBs MIMO 4 layers" nr_ulsim -n300 -m9 -r106 -s10 -W4 -y4 -z4) -add_physim_test(physim.5g.nr_ulsim.3gpp.test1 "3GPP G-FR1-A5-13, PUSCH Type A, 40 MHz BW, 30 kHz SCS, 2 RX Antennas Requirements Test" nr_ulsim -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R106 -r106 -U 0,1,1,2 -z2 -s12.4 -S12.4) -add_physim_test(physim.5g.nr_ulsim.3gpp.test2 "3GPP G-FR1-A5-13, PUSCH Type A, 40 MHz BW, 30 kHz SCS, 4 RX Antennas Requirements Test" nr_ulsim -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R106 -r106 -U 0,1,1,2 -z4 -s8.5 -S8.5) -add_physim_test(physim.5g.nr_ulsim.3gpp.test3 "3GPP G-FR1-A5-13, PUSCH Type A, 40 MHz BW, 30 kHz SCS, 8 RX Antennas Requirements Test" nr_ulsim -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R106 -r106 -U 0,1,1,2 -z8 -s5.4 -S5.4) -add_physim_test(physim.5g.nr_ulsim.3gpp.test4 "3GPP G-FR1-A5-8, PUSCH Type B, 5 MHz BW, 15 kHz SCS, 2 RX Antennas Requirements Test" nr_ulsim -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 0 -m20 -R25 -r25 -U 1,1,1,2 -z2 -s12.5 -S12.5) -add_physim_test(physim.5g.nr_ulsim.3gpp.test5 "3GPP G-FR1-A5-8, PUSCH Type B, 5 MHz BW, 15 kHz SCS, 4 RX Antennas Requirements Test" nr_ulsim -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 0 -m20 -R25 -r25 -U 1,1,1,2 -z4 -s8.9 -S8.9) -add_physim_test(physim.5g.nr_ulsim.3gpp.test6 "3GPP G-FR1-A5-8, PUSCH Type B, 5 MHz BW, 15 kHz SCS, 8 RX Antennas Requirements Test" nr_ulsim -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 0 -m20 -R25 -r25 -U 1,1,1,2 -z8 -s5.7 -S5.7) -add_physim_test(physim.5g.nr_ulsim.3gpp.test7 "3GPP G-FR1-A5-9, PUSCH Type B, 10 MHz BW, 15 kHz SCS, 2 RX Antennas Requirements Test" nr_ulsim -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 0 -m20 -R52 -r52 -U 1,1,1,2 -z2 -s12.6 -S12.6) -add_physim_test(physim.5g.nr_ulsim.3gpp.test8 "3GPP G-FR1-A5-9, PUSCH Type B, 10 MHz BW, 15 kHz SCS, 4 RX Antennas Requirements Test" nr_ulsim -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 0 -m20 -R52 -r52 -U 1,1,1,2 -z4 -s8.9 -S8.9) -add_physim_test(physim.5g.nr_ulsim.3gpp.test9 "3GPP G-FR1-A5-9, PUSCH Type B, 10 MHz BW, 15 kHz SCS, 8 RX Antennas Requirements Test" nr_ulsim -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 0 -m20 -R52 -r52 -U 1,1,1,2 -z8 -s5.8 -S5.8) -add_physim_test(physim.5g.nr_ulsim.3gpp.test10 "3GPP G-FR1-A5-10, PUSCH Type B, 20 MHz BW, 15 kHz SCS, 2 RX Antennas Requirements Test" nr_ulsim -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 0 -m20 -R106 -r106 -U 1,1,1,2 -z2 -s12.3 -S12.3) -add_physim_test(physim.5g.nr_ulsim.3gpp.test11 "3GPP G-FR1-A5-10, PUSCH Type B, 20 MHz BW, 15 kHz SCS, 4 RX Antennas Requirements Test" nr_ulsim -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 0 -m20 -R106 -r106 -U 1,1,1,2 -z4 -s8.8 -S8.8) -add_physim_test(physim.5g.nr_ulsim.3gpp.test12 "3GPP G-FR1-A5-10, PUSCH Type B, 20 MHz BW, 15 kHz SCS, 8 RX Antennas Requirements Test" nr_ulsim -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 0 -m20 -R106 -r106 -U 1,1,1,2 -z8 -s5.7 -S5.7) -add_physim_test(physim.5g.nr_ulsim.3gpp.test13 "3GPP G-FR1-A5-11, PUSCH Type B, 10 MHz BW, 30 kHz SCS, 2 RX Antennas Requirements Test" nr_ulsim -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R24 -r24 -U 1,1,1,2 -z2 -s12.5 -S12.5) -add_physim_test(physim.5g.nr_ulsim.3gpp.test14 "3GPP G-FR1-A5-11, PUSCH Type B, 10 MHz BW, 30 kHz SCS, 4 RX Antennas Requirements Test" nr_ulsim -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R24 -r24 -U 1,1,1,2 -z4 -s8.6 -S8.6) -add_physim_test(physim.5g.nr_ulsim.3gpp.test15 "3GPP G-FR1-A5-11, PUSCH Type B, 10 MHz BW, 30 kHz SCS, 8 RX Antennas Requirements Test" nr_ulsim -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R24 -r24 -U 1,1,1,2 -z8 -s5.6 -S5.6) -add_physim_test(physim.5g.nr_ulsim.3gpp.test16 "3GPP G-FR1-A5-12, PUSCH Type B, 20 MHz BW, 30 kHz SCS, 2 RX Antennas Requirements Test" nr_ulsim -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R51 -r51 -U 1,1,1,2 -z2 -s12.5 -S12.5) -add_physim_test(physim.5g.nr_ulsim.3gpp.test17 "3GPP G-FR1-A5-12, PUSCH Type B, 20 MHz BW, 30 kHz SCS, 4 RX Antennas Requirements Test" nr_ulsim -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R51 -r51 -U 1,1,1,2 -z4 -s8.6 -S8.6) -add_physim_test(physim.5g.nr_ulsim.3gpp.test18 "3GPP G-FR1-A5-12, PUSCH Type B, 20 MHz BW, 30 kHz SCS, 8 RX Antennas Requirements Test" nr_ulsim -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R51 -r51 -U 1,1,1,2 -z8 -s5.6 -S5.6) -add_physim_test(physim.5g.nr_ulsim.3gpp.test19 "3GPP G-FR1-A5-13, PUSCH Type B, 40 MHz BW, 30 kHz SCS, 2 RX Antennas Requirements Test" nr_ulsim -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R106 -r106 -U 1,1,1,2 -z2 -s12.5 -S12.5) -add_physim_test(physim.5g.nr_ulsim.3gpp.test20 "3GPP G-FR1-A5-13, PUSCH Type B, 40 MHz BW, 30 kHz SCS, 4 RX Antennas Requirements Test" nr_ulsim -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R106 -r106 -U 1,1,1,2 -z4 -s8.7 -S8.7) -add_physim_test(physim.5g.nr_ulsim.3gpp.test21 "3GPP G-FR1-A5-13, PUSCH Type B, 40 MHz BW, 30 kHz SCS, 8 RX Antennas Requirements Test" nr_ulsim -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R106 -r106 -U 1,1,1,2 -z8 -s5.5 -S5.5) -add_physim_test(physim.5g.nr_ulsim.3gpp.test22 "3GPP G-FR1-A5-14, PUSCH Type B, 100 MHz BW, 30 kHz SCS, 2 RX Antennas Requirements Test" nr_ulsim -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R273 -r273 -U 1,1,1,2 -z2 -s13.1 -S13.1) -add_physim_test(physim.5g.nr_ulsim.3gpp.test23 "3GPP G-FR1-A5-14, PUSCH Type B, 100 MHz BW, 30 kHz SCS, 4 RX Antennas Requirements Test" nr_ulsim -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R273 -r273 -U 1,1,1,2 -z4 -s9.2 -S9.2) -add_physim_test(physim.5g.nr_ulsim.3gpp.test24 "3GPP G-FR1-A5-14, PUSCH Type B, 100 MHz BW, 30 kHz SCS, 8 RX Antennas Requirements Test" nr_ulsim -n300 -b14 -I8 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R273 -r273 -U 1,1,1,2 -z8 -s5.9 -S5.9) -add_physim_test(physim.5g.nr_ulsim.3gpp.test25 "3GPP G-FR1-A3-27, PUSCH Type B, 40 MHz BW, 30 kHz SCS, 2 RX Antennas Requirements Test, 2 layers" nr_ulsim -n300 -b14 -I15 -i 0,1 -g B,l -t70 -u 1 -m2 -R106 -r106 -U 1,1,1,2 -W2 -y2 -z2 -s1.7 -S1.7) -add_physim_test(physim.5g.nr_ulsim.3gpp.test26 "3GPP G-FR1-A3-27, PUSCH Type B, 40 MHz BW, 30 kHz SCS, 4 RX Antennas Requirements Test, 2 layers" nr_ulsim -n300 -b14 -I15 -i 0,1 -g B,l -t70 -u 1 -m2 -R106 -r106 -U 1,1,1,2 -W2 -y2 -z4 -s-2.1 -S-2.1) -add_physim_test(physim.5g.nr_ulsim.3gpp.test27 "3GPP G-FR1-A4-27, PUSCH Type B, 40 MHz BW, 30 kHz SCS, 2 RX Antennas Requirements Test, 2 layers" nr_ulsim -n300 -b14 -I15 -i 0,1 -g C,l -t70 -u 1 -m16 -R106 -r106 -U 1,1,1,2 -W2 -y2 -z2 -s18.7 -S18.7) -add_physim_test(physim.5g.nr_ulsim.3gpp.test28 "3GPP G-FR1-A4-27, PUSCH Type B, 40 MHz BW, 30 kHz SCS, 4 RX Antennas Requirements Test, 2 layers" nr_ulsim -n300 -b14 -I15 -i 0,1 -g C,l -t70 -u 1 -m16 -R106 -r106 -U 1,1,1,2 -W2 -y2 -z4 -s11.2 -S11.2) +add_physim_test(physim.5g.nr_ulsim.misc.test1 "MCS 9 106 PRBs" nr_ulsim -P -n300 -m9 -r106 -s5) +add_physim_test(physim.5g.nr_ulsim.misc.test2 "MCS 16 50 PRBs" nr_ulsim -P -n300 -m16 -s10) +add_physim_test(physim.5g.nr_ulsim.misc.test3 "MCS 28 50 PRBs" nr_ulsim -P -n300 -m28 -s20) +add_physim_test(physim.5g.nr_ulsim.misc.test4 "MCS 27 50 PRBs 256QAM" nr_ulsim -P -n300 -m27 -s25 -q1) +add_physim_test(physim.5g.nr_ulsim.misc.test5 "MCS 9 217 PRBs" nr_ulsim -P -n300 -m9 -R217 -r217 -s5) +add_physim_test(physim.5g.nr_ulsim.misc.test6 "MCS 9 273 PRBs" nr_ulsim -P -n300 -m9 -R273 -r273 -s5) +add_physim_test(physim.5g.nr_ulsim.misc.test7 "PUSCH Type A, 2 DMRS Symbols" nr_ulsim -P -n300 -s5 -U 0,1,1,1) +add_physim_test(physim.5g.nr_ulsim.misc.test8 "PUSCH Type A, 3 DMRS, 4 PTRS, 5 Interpolated Symbols" nr_ulsim -P -n300 -s5 -T 1,2 -U 0,2,1,1) +add_physim_test(physim.5g.nr_ulsim.misc.test9 "PUSCH Type B, 3 DMRS, 2 PTRS, 7 Interpolated Symbols" nr_ulsim -P -n300 -s5 -T 2,2 -U 1,2,1,1) +add_physim_test(physim.5g.nr_ulsim.misc.test10 "PUSCH Type B, 3 DMRS, 2 PTRS, 3 Interpolated Symbols" nr_ulsim -P -n300 -s5 -a4 -b8 -T 1,2 -U 1,3,1,1) +add_physim_test(physim.5g.nr_ulsim.misc.test11 "25 PRBs, 15 kHz SCS" nr_ulsim -P -n300 -u0 -m0 -R25 -r25 -i 1,0) +add_physim_test(physim.5g.nr_ulsim.misc.test12 "32 PRBs, 120 kHz SCS" nr_ulsim -P -n300 -s5 -r32 -R32 -u3) +add_physim_test(physim.5g.nr_ulsim.misc.test13 "MCS 0, low SNR performance" nr_ulsim -P -n300 -m0 -S -0.6 -i 1,0) +add_physim_test(physim.5g.nr_ulsim.misc.test14 "MCS 28, 106 PRBs, Time shift 8" nr_ulsim -P -n300 -m28 -R106 -r106 -t90 -s24 -S24 -d 8) +add_physim_test(physim.5g.nr_ulsim.misc.test15 "SRS, SNR 40 dB" nr_ulsim -P -n300 -s40 -E 1) +add_physim_test(physim.5g.nr_ulsim.sc-fdma.test1 "SC-FDMA, 50 PRBs" nr_ulsim -P -n300 -s5 -Z) +add_physim_test(physim.5g.nr_ulsim.sc-fdma.test2 "SC-FDMA, 75 PRBs" nr_ulsim -P -n300 -s5 -Z -r75) +add_physim_test(physim.5g.nr_ulsim.sc-fdma.test3 "SC-FDMA, 216 PRBs" nr_ulsim -P -n150 -s5 -Z -r216 -R217) +add_physim_test(physim.5g.nr_ulsim.sc-fdma.test4 "SC-FDMA, 273 PRBs" nr_ulsim -P -n150 -s5 -Z -r270 -R273) +add_physim_test(physim.5g.nr_ulsim.sc-fdma.test5 "SC-FDMA, 3 DMRS" nr_ulsim -P -n300 -s5 -Z -U 0,2,1,2) +add_physim_test(physim.5g.nr_ulsim.mimo.test1 "MCS 19 50 PRBs 2 RX_Antenna" nr_ulsim -P -n300 -m19 -s10 -S15 -z2) +add_physim_test(physim.5g.nr_ulsim.mimo.test2 "MCS 9 106 PRBs MIMO 2 layers" nr_ulsim -P -n300 -m9 -r106 -s8 -W2 -y2 -z2) +add_physim_test(physim.5g.nr_ulsim.mimo.test3 "MCS 10 106 PRBs MIMO 2 layers" nr_ulsim -P -n300 -m10 -r106 -s12 -W2 -y2 -z2) +add_physim_test(physim.5g.nr_ulsim.mimo.test4 "MCS 19 106 PRBs MIMO 2 layers" nr_ulsim -P -n300 -m19 -r106 -s22 -W2 -y2 -z2) +add_physim_test(physim.5g.nr_ulsim.mimo.test5 "MCS 9 106 PRBs MIMO 4 layers" nr_ulsim -P -n300 -m9 -r106 -s10 -W4 -y4 -z4) +add_physim_test(physim.5g.nr_ulsim.3gpp.test1 "3GPP G-FR1-A5-13, PUSCH Type A, 40 MHz BW, 30 kHz SCS, 2 RX Antennas Requirements Test" nr_ulsim -P -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R106 -r106 -U 0,1,1,2 -z2 -s12.4 -S12.4) +add_physim_test(physim.5g.nr_ulsim.3gpp.test2 "3GPP G-FR1-A5-13, PUSCH Type A, 40 MHz BW, 30 kHz SCS, 4 RX Antennas Requirements Test" nr_ulsim -P -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R106 -r106 -U 0,1,1,2 -z4 -s8.5 -S8.5) +add_physim_test(physim.5g.nr_ulsim.3gpp.test3 "3GPP G-FR1-A5-13, PUSCH Type A, 40 MHz BW, 30 kHz SCS, 8 RX Antennas Requirements Test" nr_ulsim -P -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R106 -r106 -U 0,1,1,2 -z8 -s5.4 -S5.4) +add_physim_test(physim.5g.nr_ulsim.3gpp.test4 "3GPP G-FR1-A5-8, PUSCH Type B, 5 MHz BW, 15 kHz SCS, 2 RX Antennas Requirements Test" nr_ulsim -P -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 0 -m20 -R25 -r25 -U 1,1,1,2 -z2 -s12.5 -S12.5) +add_physim_test(physim.5g.nr_ulsim.3gpp.test5 "3GPP G-FR1-A5-8, PUSCH Type B, 5 MHz BW, 15 kHz SCS, 4 RX Antennas Requirements Test" nr_ulsim -P -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 0 -m20 -R25 -r25 -U 1,1,1,2 -z4 -s8.9 -S8.9) +add_physim_test(physim.5g.nr_ulsim.3gpp.test6 "3GPP G-FR1-A5-8, PUSCH Type B, 5 MHz BW, 15 kHz SCS, 8 RX Antennas Requirements Test" nr_ulsim -P -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 0 -m20 -R25 -r25 -U 1,1,1,2 -z8 -s5.7 -S5.7) +add_physim_test(physim.5g.nr_ulsim.3gpp.test7 "3GPP G-FR1-A5-9, PUSCH Type B, 10 MHz BW, 15 kHz SCS, 2 RX Antennas Requirements Test" nr_ulsim -P -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 0 -m20 -R52 -r52 -U 1,1,1,2 -z2 -s12.6 -S12.6) +add_physim_test(physim.5g.nr_ulsim.3gpp.test8 "3GPP G-FR1-A5-9, PUSCH Type B, 10 MHz BW, 15 kHz SCS, 4 RX Antennas Requirements Test" nr_ulsim -P -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 0 -m20 -R52 -r52 -U 1,1,1,2 -z4 -s8.9 -S8.9) +add_physim_test(physim.5g.nr_ulsim.3gpp.test9 "3GPP G-FR1-A5-9, PUSCH Type B, 10 MHz BW, 15 kHz SCS, 8 RX Antennas Requirements Test" nr_ulsim -P -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 0 -m20 -R52 -r52 -U 1,1,1,2 -z8 -s5.8 -S5.8) +add_physim_test(physim.5g.nr_ulsim.3gpp.test10 "3GPP G-FR1-A5-10, PUSCH Type B, 20 MHz BW, 15 kHz SCS, 2 RX Antennas Requirements Test" nr_ulsim -P -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 0 -m20 -R106 -r106 -U 1,1,1,2 -z2 -s12.3 -S12.3) +add_physim_test(physim.5g.nr_ulsim.3gpp.test11 "3GPP G-FR1-A5-10, PUSCH Type B, 20 MHz BW, 15 kHz SCS, 4 RX Antennas Requirements Test" nr_ulsim -P -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 0 -m20 -R106 -r106 -U 1,1,1,2 -z4 -s8.8 -S8.8) +add_physim_test(physim.5g.nr_ulsim.3gpp.test12 "3GPP G-FR1-A5-10, PUSCH Type B, 20 MHz BW, 15 kHz SCS, 8 RX Antennas Requirements Test" nr_ulsim -P -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 0 -m20 -R106 -r106 -U 1,1,1,2 -z8 -s5.7 -S5.7) +add_physim_test(physim.5g.nr_ulsim.3gpp.test13 "3GPP G-FR1-A5-11, PUSCH Type B, 10 MHz BW, 30 kHz SCS, 2 RX Antennas Requirements Test" nr_ulsim -P -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R24 -r24 -U 1,1,1,2 -z2 -s12.5 -S12.5) +add_physim_test(physim.5g.nr_ulsim.3gpp.test14 "3GPP G-FR1-A5-11, PUSCH Type B, 10 MHz BW, 30 kHz SCS, 4 RX Antennas Requirements Test" nr_ulsim -P -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R24 -r24 -U 1,1,1,2 -z4 -s8.6 -S8.6) +add_physim_test(physim.5g.nr_ulsim.3gpp.test15 "3GPP G-FR1-A5-11, PUSCH Type B, 10 MHz BW, 30 kHz SCS, 8 RX Antennas Requirements Test" nr_ulsim -P -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R24 -r24 -U 1,1,1,2 -z8 -s5.6 -S5.6) +add_physim_test(physim.5g.nr_ulsim.3gpp.test16 "3GPP G-FR1-A5-12, PUSCH Type B, 20 MHz BW, 30 kHz SCS, 2 RX Antennas Requirements Test" nr_ulsim -P -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R51 -r51 -U 1,1,1,2 -z2 -s12.5 -S12.5) +add_physim_test(physim.5g.nr_ulsim.3gpp.test17 "3GPP G-FR1-A5-12, PUSCH Type B, 20 MHz BW, 30 kHz SCS, 4 RX Antennas Requirements Test" nr_ulsim -P -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R51 -r51 -U 1,1,1,2 -z4 -s8.6 -S8.6) +add_physim_test(physim.5g.nr_ulsim.3gpp.test18 "3GPP G-FR1-A5-12, PUSCH Type B, 20 MHz BW, 30 kHz SCS, 8 RX Antennas Requirements Test" nr_ulsim -P -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R51 -r51 -U 1,1,1,2 -z8 -s5.6 -S5.6) +add_physim_test(physim.5g.nr_ulsim.3gpp.test19 "3GPP G-FR1-A5-13, PUSCH Type B, 40 MHz BW, 30 kHz SCS, 2 RX Antennas Requirements Test" nr_ulsim -P -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R106 -r106 -U 1,1,1,2 -z2 -s12.5 -S12.5) +add_physim_test(physim.5g.nr_ulsim.3gpp.test20 "3GPP G-FR1-A5-13, PUSCH Type B, 40 MHz BW, 30 kHz SCS, 4 RX Antennas Requirements Test" nr_ulsim -P -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R106 -r106 -U 1,1,1,2 -z4 -s8.7 -S8.7) +add_physim_test(physim.5g.nr_ulsim.3gpp.test21 "3GPP G-FR1-A5-13, PUSCH Type B, 40 MHz BW, 30 kHz SCS, 8 RX Antennas Requirements Test" nr_ulsim -P -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R106 -r106 -U 1,1,1,2 -z8 -s5.5 -S5.5) +add_physim_test(physim.5g.nr_ulsim.3gpp.test22 "3GPP G-FR1-A5-14, PUSCH Type B, 100 MHz BW, 30 kHz SCS, 2 RX Antennas Requirements Test" nr_ulsim -P -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R273 -r273 -U 1,1,1,2 -z2 -s13.1 -S13.1) +add_physim_test(physim.5g.nr_ulsim.3gpp.test23 "3GPP G-FR1-A5-14, PUSCH Type B, 100 MHz BW, 30 kHz SCS, 4 RX Antennas Requirements Test" nr_ulsim -P -n300 -b14 -I7 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R273 -r273 -U 1,1,1,2 -z4 -s9.2 -S9.2) +add_physim_test(physim.5g.nr_ulsim.3gpp.test24 "3GPP G-FR1-A5-14, PUSCH Type B, 100 MHz BW, 30 kHz SCS, 8 RX Antennas Requirements Test" nr_ulsim -P -n300 -b14 -I8 -i 0,1 -g A,l,10 -t70 -u 1 -m20 -R273 -r273 -U 1,1,1,2 -z8 -s5.9 -S5.9) +add_physim_test(physim.5g.nr_ulsim.3gpp.test25 "3GPP G-FR1-A3-27, PUSCH Type B, 40 MHz BW, 30 kHz SCS, 2 RX Antennas Requirements Test, 2 layers" nr_ulsim -P -n300 -b14 -I15 -i 0,1 -g B,l -t70 -u 1 -m2 -R106 -r106 -U 1,1,1,2 -W2 -y2 -z2 -s1.7 -S1.7) +add_physim_test(physim.5g.nr_ulsim.3gpp.test26 "3GPP G-FR1-A3-27, PUSCH Type B, 40 MHz BW, 30 kHz SCS, 4 RX Antennas Requirements Test, 2 layers" nr_ulsim -P -n300 -b14 -I15 -i 0,1 -g B,l -t70 -u 1 -m2 -R106 -r106 -U 1,1,1,2 -W2 -y2 -z4 -s-2.1 -S-2.1) +add_physim_test(physim.5g.nr_ulsim.3gpp.test27 "3GPP G-FR1-A4-27, PUSCH Type B, 40 MHz BW, 30 kHz SCS, 2 RX Antennas Requirements Test, 2 layers" nr_ulsim -P -n300 -b14 -I15 -i 0,1 -g C,l -t70 -u 1 -m16 -R106 -r106 -U 1,1,1,2 -W2 -y2 -z2 -s18.7 -S18.7) +add_physim_test(physim.5g.nr_ulsim.3gpp.test28 "3GPP G-FR1-A4-27, PUSCH Type B, 40 MHz BW, 30 kHz SCS, 4 RX Antennas Requirements Test, 2 layers" nr_ulsim -P -n300 -b14 -I15 -i 0,1 -g C,l -t70 -u 1 -m16 -R106 -r106 -U 1,1,1,2 -W2 -y2 -z4 -s11.2 -S11.2) #################################################################################### ###### nr_prachsim unit test ###### From 3e7977438673e26f8443ae3fef8aca5f034ef22f Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Mon, 22 Sep 2025 10:37:05 +0200 Subject: [PATCH 865/964] Enable DLSCH performance logging in nr_dlsim --- openair1/SIMULATION/tests/CMakeLists.txt | 56 ++++++++++++------------ 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/openair1/SIMULATION/tests/CMakeLists.txt b/openair1/SIMULATION/tests/CMakeLists.txt index 1d41b1fba9..443db31c95 100644 --- a/openair1/SIMULATION/tests/CMakeLists.txt +++ b/openair1/SIMULATION/tests/CMakeLists.txt @@ -181,34 +181,34 @@ add_physim_test(physim.5g.nr_pbchsim.otherSCS.test2 "PBCH-only, 120Khz, 50Mhz" n ###### nr_dlsim unit test ###### #################################################################################### -add_physim_test(physim.5g.nr_dlsim.basic.test1 "106 PRB" nr_dlsim -n300 -R106 -b106 -s5) -add_physim_test(physim.5g.nr_dlsim.basic.test2 "217 PRB" nr_dlsim -n300 -R217 -b217 -s5) -add_physim_test(physim.5g.nr_dlsim.basic.test3 "273 PRB" nr_dlsim -n300 -R273 -b273 -s5) -add_physim_test(physim.5g.nr_dlsim.basic.test4 "HARQ test 25% TP 4 rounds" nr_dlsim -n300 -s1 -S2 -t25) -add_physim_test(physim.5g.nr_dlsim.basic.test5 "HARQ test 33% TP 3 rounds" nr_dlsim -n300 -s1 -S2 -t33) -add_physim_test(physim.5g.nr_dlsim.basic.test6 "HARQ test 50% TP 2 rounds" nr_dlsim -n300 -s5 -S7 -t50) -add_physim_test(physim.5g.nr_dlsim.basic.test7 "25 PRBs, 15 kHz SCS" nr_dlsim -n300 -m0 -e0 -R25 -b25 -i 2 1 0) -add_physim_test(physim.5g.nr_dlsim.basic.test8 "32 PRBs, 120 kHz SCS" nr_dlsim -n300 -s5 -m3 -R32 -b32) -add_physim_test(physim.5g.nr_dlsim.offset.test1 "106 PRB 25 PDSCH-Offset" nr_dlsim -n300 -R106 -a25 -s5) -add_physim_test(physim.5g.nr_dlsim.offset.test2 "106 PRB 51 PDSCH-Offset" nr_dlsim -n300 -R106 -a51 -s5) -add_physim_test(physim.5g.nr_dlsim.offset.test3 "217 PRB 100 PDSCH-PRBs" nr_dlsim -n300 -R217 -b100 -s5) -add_physim_test(physim.5g.nr_dlsim.offset.test4 "217 PRB 80 PDSCH-Offset" nr_dlsim -n300 -R217 -a80 -s5) -add_physim_test(physim.5g.nr_dlsim.offset.test5 "217 PRB 100 PDSCH-PRBs 110 PDSCH-Offset" nr_dlsim -n300 -R217 -a110 -s5 -b100) -add_physim_test(physim.5g.nr_dlsim.mcs.mimo.test1 "106 PRBs 50 PDSCH-PRBs MCS Index 27" nr_dlsim -n300 -e27 -s30) -add_physim_test(physim.5g.nr_dlsim.mcs.mimo.test2 "106 PRBs 50 PDSCH-PRBs MCS Index 16" nr_dlsim -n300 -e16 -s11 -S13) -add_physim_test(physim.5g.nr_dlsim.mcs.mimo.test3 "106 MCS-TABLE 256 QAM MCS Index 26" nr_dlsim -n300 -q1 -e26 -s30) -add_physim_test(physim.5g.nr_dlsim.mcs.mimo.test4 "106 MCS-TABLE 256 QAM Fading Channel" nr_dlsim -n300 -q1 -e24 -s30 -gA) -add_physim_test(physim.5g.nr_dlsim.mcs.mimo.test5 "MCS 0, low SNR performance" nr_dlsim -n300 -e0 -t95 -S-1.0 -i 2 1 0) -add_physim_test(physim.5g.nr_dlsim.mcs.mimo.test6 "4x4 MIMO, 1 Layer" nr_dlsim -n30 -s20 -U 3 0 0 2 -gA -x1 -y4 -z4) -add_physim_test(physim.5g.nr_dlsim.mcs.mimo.test7 "4x4 MIMO, 2 Layers" nr_dlsim -n30 -s20 -U 3 0 0 2 -gA -x2 -y4 -z4) -add_physim_test(physim.5g.nr_dlsim.mcs.mimo.test8 "4x4 MIMO, 2 Layers 256 QAM" nr_dlsim -n30 -s25 -e22 -q1 -U 3 0 0 2 -gA -x2 -y4 -z4) -add_physim_test(physim.5g.nr_dlsim.mcs.mimo.test9 "4x4 MIMO, 4 Layers" nr_dlsim -n30 -s20 -U 3 0 0 2 -x4 -y4 -z4) -add_physim_test(physim.5g.nr_dlsim.dmrs.ptrs.test1 "3 PTRS, 8 Interpolated Symbols" nr_dlsim -n300 -s5 -T 2 2 2) -add_physim_test(physim.5g.nr_dlsim.dmrs.ptrs.test2 "6 PTRS, 5 Interpolated Symbols" nr_dlsim -n300 -s5 -T 2 1 2) -add_physim_test(physim.5g.nr_dlsim.dmrs.ptrs.test3 "11 PTRS, 0 Interpolated Symbols" nr_dlsim -n300 -s5 -T 2 0 4) -add_physim_test(physim.5g.nr_dlsim.dmrs.ptrs.test4 "Mapping type A, 2 DMRS Symbols" nr_dlsim -n300 -s5 -S7 -U 2 0 1) -add_physim_test(physim.5g.nr_dlsim.dmrs.ptrs.test5 "Mapping type A, 3 DMRS Symbols" nr_dlsim -n300 -s5 -S7 -U 2 0 2) -add_physim_test(physim.5g.nr_dlsim.dmrs.ptrs.test6 "Mapping type B, 4 DMRS Symbols" nr_dlsim -n300 -s5 -S7 -U 2 1 3) +add_physim_test(physim.5g.nr_dlsim.basic.test1 "106 PRB" nr_dlsim -P -n300 -R106 -b106 -s5) +add_physim_test(physim.5g.nr_dlsim.basic.test2 "217 PRB" nr_dlsim -P -n300 -R217 -b217 -s5) +add_physim_test(physim.5g.nr_dlsim.basic.test3 "273 PRB" nr_dlsim -P -n300 -R273 -b273 -s5) +add_physim_test(physim.5g.nr_dlsim.basic.test4 "HARQ test 25% TP 4 rounds" nr_dlsim -P -n300 -s1 -S2 -t25) +add_physim_test(physim.5g.nr_dlsim.basic.test5 "HARQ test 33% TP 3 rounds" nr_dlsim -P -n300 -s1 -S2 -t33) +add_physim_test(physim.5g.nr_dlsim.basic.test6 "HARQ test 50% TP 2 rounds" nr_dlsim -P -n300 -s5 -S7 -t50) +add_physim_test(physim.5g.nr_dlsim.basic.test7 "25 PRBs, 15 kHz SCS" nr_dlsim -P -n300 -m0 -e0 -R25 -b25 -i 2 1 0) +add_physim_test(physim.5g.nr_dlsim.basic.test8 "32 PRBs, 120 kHz SCS" nr_dlsim -P -n300 -s5 -m3 -R32 -b32) +add_physim_test(physim.5g.nr_dlsim.offset.test1 "106 PRB 25 PDSCH-Offset" nr_dlsim -P -n300 -R106 -a25 -s5) +add_physim_test(physim.5g.nr_dlsim.offset.test2 "106 PRB 51 PDSCH-Offset" nr_dlsim -P -n300 -R106 -a51 -s5) +add_physim_test(physim.5g.nr_dlsim.offset.test3 "217 PRB 100 PDSCH-PRBs" nr_dlsim -P -n300 -R217 -b100 -s5) +add_physim_test(physim.5g.nr_dlsim.offset.test4 "217 PRB 80 PDSCH-Offset" nr_dlsim -P -n300 -R217 -a80 -s5) +add_physim_test(physim.5g.nr_dlsim.offset.test5 "217 PRB 100 PDSCH-PRBs 110 PDSCH-Offset" nr_dlsim -P -n300 -R217 -a110 -s5 -b100) +add_physim_test(physim.5g.nr_dlsim.mcs.mimo.test1 "106 PRBs 50 PDSCH-PRBs MCS Index 27" nr_dlsim -P -n300 -e27 -s30) +add_physim_test(physim.5g.nr_dlsim.mcs.mimo.test2 "106 PRBs 50 PDSCH-PRBs MCS Index 16" nr_dlsim -P -n300 -e16 -s11 -S13) +add_physim_test(physim.5g.nr_dlsim.mcs.mimo.test3 "106 MCS-TABLE 256 QAM MCS Index 26" nr_dlsim -P -n300 -q1 -e26 -s30) +add_physim_test(physim.5g.nr_dlsim.mcs.mimo.test4 "106 MCS-TABLE 256 QAM Fading Channel" nr_dlsim -P -n300 -q1 -e24 -s30 -gA) +add_physim_test(physim.5g.nr_dlsim.mcs.mimo.test5 "MCS 0, low SNR performance" nr_dlsim -P -n300 -e0 -t95 -S-1.0 -i 2 1 0) +add_physim_test(physim.5g.nr_dlsim.mcs.mimo.test6 "4x4 MIMO, 1 Layer" nr_dlsim -P -n30 -s20 -U 3 0 0 2 -gA -x1 -y4 -z4) +add_physim_test(physim.5g.nr_dlsim.mcs.mimo.test7 "4x4 MIMO, 2 Layers" nr_dlsim -P -n30 -s20 -U 3 0 0 2 -gA -x2 -y4 -z4) +add_physim_test(physim.5g.nr_dlsim.mcs.mimo.test8 "4x4 MIMO, 2 Layers 256 QAM" nr_dlsim -P -n30 -s25 -e22 -q1 -U 3 0 0 2 -gA -x2 -y4 -z4) +add_physim_test(physim.5g.nr_dlsim.mcs.mimo.test9 "4x4 MIMO, 4 Layers" nr_dlsim -P -n30 -s20 -U 3 0 0 2 -x4 -y4 -z4) +add_physim_test(physim.5g.nr_dlsim.dmrs.ptrs.test1 "3 PTRS, 8 Interpolated Symbols" nr_dlsim -P -n300 -s5 -T 2 2 2) +add_physim_test(physim.5g.nr_dlsim.dmrs.ptrs.test2 "6 PTRS, 5 Interpolated Symbols" nr_dlsim -P -n300 -s5 -T 2 1 2) +add_physim_test(physim.5g.nr_dlsim.dmrs.ptrs.test3 "11 PTRS, 0 Interpolated Symbols" nr_dlsim -P -n300 -s5 -T 2 0 4) +add_physim_test(physim.5g.nr_dlsim.dmrs.ptrs.test4 "Mapping type A, 2 DMRS Symbols" nr_dlsim -P -n300 -s5 -S7 -U 2 0 1) +add_physim_test(physim.5g.nr_dlsim.dmrs.ptrs.test5 "Mapping type A, 3 DMRS Symbols" nr_dlsim -P -n300 -s5 -S7 -U 2 0 2) +add_physim_test(physim.5g.nr_dlsim.dmrs.ptrs.test6 "Mapping type B, 4 DMRS Symbols" nr_dlsim -P -n300 -s5 -S7 -U 2 1 3) #################################################################################### ###### nr_dlschsim unit test ###### From 5e3b4c497c54e9d31517b1873cca745ad8b86bfd Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Tue, 23 Sep 2025 16:46:41 +0200 Subject: [PATCH 866/964] Refactor handover context cleanup and fix memory leak in N2 handover source gNB path - Add missing handover context cleanup in rrc_CU_process_ue_context_release_complete - Fix 16-byte handover context leak in N2 handover source gNB trigger path AddressSanitizer backtrace: Direct leak of 16 byte(s) in 1 object(s) allocated from: /#0 0x7fee67cb4a57 in __interceptor_calloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:154 /#1 0x58059e33454b in calloc_or_fail /home/guido/repo/openairinterface5g/develop/common/utils/utils.h:74 /#2 0x58059e33454b in alloc_ho_ctx /home/guido/repo/openairinterface5g/develop/openair2/RRC/NR/rrc_gNB_mobility.c:47 /#3 0x58059e339e4d in nr_rrc_trigger_n2_ho /home/guido/repo/openairinterface5g/develop/openair2/RRC/NR/rrc_gNB_mobility.c:556 /#4 0x58059e33ae93 in nr_HO_N2_trigger_telnet /home/guido/repo/openairinterface5g/develop/openair2/RRC/NR/rrc_gNB_mobility.c:611 Root cause: Handover context allocated in N2 handover source gNB trigger path (nr_rrc_trigger_n2_ho) for any successful N2 handover but not properly freed in all handover completion scenarios. The UE context release complete handler was missing cleanup for handover context. Solution: refactor handover context cleanup - Move nr_rrc_finalize_ho() call to rrc_delete_ue_data() for centralized cleanup - Remove redundant nr_rrc_finalize_ho() calls from handover failure paths: * rrc_CU_process_ue_context_release_request() - UE not deleted yet * invalidate_du_connections() - UE will be deleted later - Keep nr_rrc_finalize_ho() calls in handover success paths where UE continues operating - Ensures handover context is cleaned up exactly once when UE is actually deleted - Prevents potential double-free and use-after-free issues in handover cleanup This centralizes all UE data cleanup in rrc_delete_ue_data() and ensures handover context is properly managed throughout the UE lifecycle and cleaned up when UE delete happens. --- openair2/RRC/NR/rrc_gNB.c | 3 +++ openair2/RRC/NR/rrc_gNB_du.c | 4 +--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 2661531c27..aea6fb9259 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -2338,6 +2338,9 @@ static void rrc_CU_process_ue_context_release_request(MessageDef *msg_p, sctp_as static void rrc_delete_ue_data(gNB_RRC_UE_t *UE) { + /* Clean up handover context if it exists */ + if (UE->ho_context) + nr_rrc_finalize_ho(UE); ASN_STRUCT_FREE(asn_DEF_NR_UE_NR_Capability, UE->UE_Capability_nr); ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->masterCellGroup); ASN_STRUCT_FREE(asn_DEF_NR_MeasResults, UE->measResults); diff --git a/openair2/RRC/NR/rrc_gNB_du.c b/openair2/RRC/NR/rrc_gNB_du.c index e104641edc..edf6f19164 100644 --- a/openair2/RRC/NR/rrc_gNB_du.c +++ b/openair2/RRC/NR/rrc_gNB_du.c @@ -453,10 +453,8 @@ static int invalidate_du_connections(gNB_RRC_INST *rrc, sctp_assoc_t assoc_id) RB_FOREACH(ue_context_p, rrc_nr_ue_tree_s, &rrc->rrc_ue_head) { gNB_RRC_UE_t *UE = &ue_context_p->ue_context; uint32_t ue_id = UE->rrc_ue_id; - if (UE->ho_context != NULL) { + if (UE->ho_context != NULL) LOG_W(NR_RRC, "DU disconnected while handover for UE %d active\n", ue_id); - nr_rrc_finalize_ho(UE); - } f1_ue_data_t ue_data = cu_get_f1_ue_data(ue_id); if (ue_data.du_assoc_id != assoc_id) continue; /* this UE is on another DU */ From feea066c3f1922e41c23859544d287fb7a11cf5e Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Tue, 23 Sep 2025 16:15:15 +0200 Subject: [PATCH 867/964] Fix measurement gap config memory leak in create_measgap_config - Add missing ASN_STRUCT_FREE for NR_MeasGapConfig in create_measgap_config - Fix 48-byte measurement gap config leak in get_gap_config_from_smtc AddressSanitizer backtrace: Direct leak of 48 byte(s) in 1 object(s) allocated from: /#0 0x7d32adab4a57 in __interceptor_calloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:154 /#1 0x5751f99cbb79 in calloc_or_fail /home/guido/repo/openairinterface5g/develop/common/utils/utils.h:74 /#2 0x5751f99cbb79 in get_gap_config_from_smtc /home/guido/repo/openairinterface5g/develop/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c:4164 /#3 0x5751f99cbb79 in create_measgap_config /home/guido/repo/openairinterface5g/develop/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c:4310 /#4 0x5751f9964abe in ue_context_setup_request /home/guido/repo/openairinterface5g/develop/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c:709 /#5 0x5751f979e568 in nr_initiate_handover /home/guido/repo/openairinterface5g/develop/openair2/RRC/NR/rrc_gNB_mobility.c:218 /#6 0x5751f97a637f in nr_rrc_trigger_n2_ho_target /home/guido/repo/openairinterface5g/develop/openair2/RRC/NR/rrc_gNB_mobility.c:526 /#7 0x5751f9703608 in rrc_gNB_process_e1_bearer_context_setup_resp /home/guido/repo/openairinterface5g/develop/openair2/RRC/NR/rrc_gNB.c:2641 /#8 0x5751f9706b7b in rrc_gnb_task /home/guido/repo/openairinterface5g/develop/openair2/RRC/NR/rrc_gNB.c:3020 /#9 0x7d32ac494ac2 in start_thread nptl/pthread_create.c:442 Root cause: create_measgap_config allocated NR_MeasGapConfig via get_gap_config_from_smtc() but never freed it after extracting the needed values to populate the measgap_config_t return structure. --- openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c index 44cb211b1d..8d6731dbbd 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c @@ -4361,8 +4361,10 @@ measgap_config_t create_measgap_config(const NR_MeasurementTimingConfiguration_t const NR_SSB_MTC_t *ssb_mtc = &ft->ssb_MeasurementTimingConfiguration; NR_MeasGapConfig_t *measGapConfig = get_gap_config_from_smtc(ssb_mtc); const NR_GapConfig_t *gap_config = get_gap_config(measGapConfig); - if (!gap_config) + if (!gap_config) { + ASN_STRUCT_FREE(asn_DEF_NR_MeasGapConfig, measGapConfig); return mgc; + } mgc.mgrp_ms = get_mgrp(gap_config->mgrp); DevAssert(mgc.mgrp_ms != -1); @@ -4385,6 +4387,10 @@ measgap_config_t create_measgap_config(const NR_MeasurementTimingConfiguration_t mgc.mgl_slots = ((int)(10 * (mgc.mgl_ms + max_k2)) << scs) / 10; mgc.enable = true; + + // Free the allocated measGapConfig structure after we're done using gap_config + ASN_STRUCT_FREE(asn_DEF_NR_MeasGapConfig, measGapConfig); + return mgc; } From c2e8743a7b7ce7a0590f8db7ac1aa3f8686370b4 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Mon, 29 Sep 2025 17:34:15 +0200 Subject: [PATCH 868/964] Optimize create_measgap_config to eliminate unnecessary allocation - Replace inefficient 'allocate, extract, free' pattern with direct value extraction - Remove unused functions get_gap_config_from_smtc() and get_gap_config() - Add extract_gap_config_from_smtc() that extracts values directly without allocation - Eliminates use-after-free risk and improves performance - No allocation overhead, no memory leaks --- openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c | 126 ++++++++----------- 1 file changed, 49 insertions(+), 77 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c index 8d6731dbbd..a2b7c26678 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c @@ -50,6 +50,11 @@ #define NR_MAX_SUPPORTED_DL_LAYERS 4 +/* Default values for measurement gap configuration */ +#define DEFAULT_MGRP NR_GapConfig__mgrp_ms160 +#define DEFAULT_MGTA NR_GapConfig__mgta_ms0dot5 +#define DEFAULT_MGL NR_GapConfig__mgl_ms6 + #define PUCCH2_SIZE 8 const uint8_t slotsperframe[5] = {10, 20, 40, 80, 160}; @@ -4211,53 +4216,6 @@ NR_ReconfigurationWithSync_t *get_reconfiguration_with_sync(rnti_t rnti, uid_t u return reconfigurationWithSync; } -static NR_MeasGapConfig_t *get_gap_config_from_smtc(const NR_SSB_MTC_t *ssb_mtc) -{ - NR_MeasGapConfig_t *measGapConfig = calloc_or_fail(1, sizeof(*measGapConfig)); - measGapConfig->ext1 = calloc_or_fail(1, sizeof(*measGapConfig->ext1)); - measGapConfig->ext1->gapUE = calloc_or_fail(1, sizeof(*measGapConfig->ext1->gapUE)); - measGapConfig->ext1->gapUE->present = NR_SetupRelease_GapConfig_PR_setup; - NR_GapConfig_t *gap_config = calloc_or_fail(1, sizeof(*gap_config)); - measGapConfig->ext1->gapUE->choice.setup = gap_config; - - // mgta = Measurement Gap Timing Advance, to provide sufficient time for the UE to re-tune its transceiver - // This allows the Measurement Gap to extend mgta ms either side of the SS/PBCH Measurement Window. - gap_config->mgta = NR_GapConfig__mgta_ms0dot5; - - // mgrp = Measurement Gap Repetition Period - // gapOffset = It defines the start of the Measurement Gaps relative to the start of the radio frame with SFN = 0 - // The Measurement Gaps need to be synchronized with the SS/PBCH transmissions which are to be measured - gap_config->mgrp = NR_GapConfig__mgrp_ms160; - switch (ssb_mtc->periodicityAndOffset.present) { - case NR_SSB_MTC__periodicityAndOffset_PR_sf20: - gap_config->gapOffset = ssb_mtc->periodicityAndOffset.choice.sf20; - break; - case NR_SSB_MTC__periodicityAndOffset_PR_sf40: - gap_config->gapOffset = ssb_mtc->periodicityAndOffset.choice.sf40; - break; - case NR_SSB_MTC__periodicityAndOffset_PR_sf80: - gap_config->gapOffset = ssb_mtc->periodicityAndOffset.choice.sf80; - break; - case NR_SSB_MTC__periodicityAndOffset_PR_sf160: - gap_config->gapOffset = ssb_mtc->periodicityAndOffset.choice.sf160; - break; - default: - LOG_W(NR_RRC, "SMTC periodicity higher than MGRP\n"); - // With this configuration, not all SSBs belong to the Measurement Gap. - if (ssb_mtc->periodicityAndOffset.present == NR_SSB_MTC__periodicityAndOffset_PR_sf5) { - gap_config->gapOffset = ssb_mtc->periodicityAndOffset.choice.sf5; - } else if (ssb_mtc->periodicityAndOffset.present == NR_SSB_MTC__periodicityAndOffset_PR_sf10) { - gap_config->gapOffset = ssb_mtc->periodicityAndOffset.choice.sf10; - } - } - - // mgl = Measurement Gap Length - // FIXME: At least the duration of the SMTC plus 2 times the mgta should be enough, - // however, at the moment it only works by setting the maximum value - gap_config->mgl = NR_GapConfig__mgl_ms6; - - return measGapConfig; -} NR_MeasurementTimingConfiguration_t *get_nr_mtc(uint8_t *buf, uint32_t len) { @@ -4330,25 +4288,37 @@ static float get_mgta(long mgta) } } -/** @brief Return Measurement Gap Configuration, from ASN.1 config */ -const NR_GapConfig_t *get_gap_config(const NR_MeasGapConfig_t *mgc) +/** @brief Extract gapOffset from SSB MTC periodicity */ +static bool extract_gap_offset_from_smtc(const NR_SSB_MTC_t *ssb_mtc, long *gapOffset) { - if (mgc->gapFR2 && mgc->gapFR2->present == NR_SetupRelease_GapConfig_PR_setup) - return mgc->gapFR2->choice.setup; + if (!ssb_mtc) + return false; - // FR1 case - if (!mgc->ext1) - return NULL; + // Extract gapOffset based on periodicity + switch (ssb_mtc->periodicityAndOffset.present) { + case NR_SSB_MTC__periodicityAndOffset_PR_sf20: + *gapOffset = ssb_mtc->periodicityAndOffset.choice.sf20; + break; + case NR_SSB_MTC__periodicityAndOffset_PR_sf40: + *gapOffset = ssb_mtc->periodicityAndOffset.choice.sf40; + break; + case NR_SSB_MTC__periodicityAndOffset_PR_sf80: + *gapOffset = ssb_mtc->periodicityAndOffset.choice.sf80; + break; + case NR_SSB_MTC__periodicityAndOffset_PR_sf160: + *gapOffset = ssb_mtc->periodicityAndOffset.choice.sf160; + break; + default: + LOG_W(NR_RRC, "SMTC periodicity higher than MGRP\n"); + if (ssb_mtc->periodicityAndOffset.present == NR_SSB_MTC__periodicityAndOffset_PR_sf5) { + *gapOffset = ssb_mtc->periodicityAndOffset.choice.sf5; + } else if (ssb_mtc->periodicityAndOffset.present == NR_SSB_MTC__periodicityAndOffset_PR_sf10) { + *gapOffset = ssb_mtc->periodicityAndOffset.choice.sf10; + } + break; + } - const NR_SetupRelease_GapConfig_t *gapUE = mgc->ext1->gapUE; - if (gapUE && gapUE->present == NR_SetupRelease_GapConfig_PR_setup) - return gapUE->choice.setup; - - const NR_SetupRelease_GapConfig_t *gapFR1 = mgc->ext1->gapFR1; - if (gapFR1 && gapFR1->present == NR_SetupRelease_GapConfig_PR_setup) - return gapFR1->choice.setup; - - return NULL; + return true; } measgap_config_t create_measgap_config(const NR_MeasurementTimingConfiguration_t *mtc, int scs, int min_rxtxtime) @@ -4359,20 +4329,25 @@ measgap_config_t create_measgap_config(const NR_MeasurementTimingConfiguration_t DevAssert(mt != NULL && mt->frequencyAndTiming != NULL); const struct NR_MeasTiming__frequencyAndTiming *ft = mt->frequencyAndTiming; const NR_SSB_MTC_t *ssb_mtc = &ft->ssb_MeasurementTimingConfiguration; - NR_MeasGapConfig_t *measGapConfig = get_gap_config_from_smtc(ssb_mtc); - const NR_GapConfig_t *gap_config = get_gap_config(measGapConfig); - if (!gap_config) { - ASN_STRUCT_FREE(asn_DEF_NR_MeasGapConfig, measGapConfig); + + // Initialize with defaults + long mgrp = DEFAULT_MGRP; + long gapOffset = 0; + long mgta = DEFAULT_MGTA; + long mgl = DEFAULT_MGL; + + // Extract gapOffset from SSB MTC periodicity + if (!extract_gap_offset_from_smtc(ssb_mtc, &gapOffset)) { return mgc; } - mgc.mgrp_ms = get_mgrp(gap_config->mgrp); + mgc.mgrp_ms = get_mgrp(mgrp); DevAssert(mgc.mgrp_ms != -1); - mgc.mgrp = gap_config->mgrp; + mgc.mgrp = mgrp; - mgc.gapOffset = gap_config->gapOffset; - mgc.mgta = gap_config->mgta; - mgc.n_slots_mgta = ((int)(10 * get_mgta(gap_config->mgta)) << scs) / 10; + mgc.gapOffset = gapOffset; + mgc.mgta = mgta; + mgc.n_slots_mgta = ((int)(10 * get_mgta(mgta)) << scs) / 10; // We start the timer K2 slots earlier to avoid scheduling feedback PUCCHs inside measGap // or depending on the current min_rxtxtime earlier @@ -4381,16 +4356,13 @@ measgap_config_t create_measgap_config(const NR_MeasurementTimingConfiguration_t mgc.n_slots_advance = mgc.n_slots_mgta + max_k2; - mgc.mgl_ms = get_mgl(gap_config->mgl); + mgc.mgl_ms = get_mgl(mgl); DevAssert(mgc.mgl_ms != -1); - mgc.mgl = gap_config->mgl; + mgc.mgl = mgl; mgc.mgl_slots = ((int)(10 * (mgc.mgl_ms + max_k2)) << scs) / 10; mgc.enable = true; - // Free the allocated measGapConfig structure after we're done using gap_config - ASN_STRUCT_FREE(asn_DEF_NR_MeasGapConfig, measGapConfig); - return mgc; } From 3e8354727e03c3d8fce493732899943ca6630c3c Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Tue, 23 Sep 2025 14:15:44 +0200 Subject: [PATCH 869/964] Remove redundant NULL checks for handover encoder functions Handoer encoder functions never return NULL - they either return a valid pointer or terminate the program. Remove dead code paths. --- openair3/NGAP/ngap_gNB.c | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/openair3/NGAP/ngap_gNB.c b/openair3/NGAP/ngap_gNB.c index 68e77d369c..7cc8041ad5 100644 --- a/openair3/NGAP/ngap_gNB.c +++ b/openair3/NGAP/ngap_gNB.c @@ -296,10 +296,7 @@ int ngap_handover_required(instance_t instance, ngap_handover_required_t *msg) DevAssert(ue_context_p->gNB_ue_ngap_id == msg->gNB_ue_ngap_id); NGAP_NGAP_PDU_t *pdu = encode_ng_handover_required(msg); - if (!pdu) { - NGAP_ERROR("Failed to encode Handover Required\n"); - return -1; - } + DevAssert(pdu != NULL); if (LOG_DEBUGFLAG(DEBUG_ASN1)) xer_fprint(stdout, &asn_DEF_NGAP_NGAP_PDU, pdu); @@ -339,10 +336,7 @@ static int ngap_gNB_handover_failure(instance_t instance, const ngap_handover_fa DevAssert(ngap_gNB_instance_p != NULL); NGAP_NGAP_PDU_t *pdu = encode_ng_handover_failure(msg); - if (!pdu) { - NGAP_ERROR("Failed to encode NG Handover Failure\n"); - return -1; - } + DevAssert(pdu != NULL); if (ngap_gNB_encode_pdu(pdu, &buffer, &length) < 0) { NGAP_ERROR("Failed to encode HANDOVER FAILURE MESSAGE\n"); @@ -377,10 +371,7 @@ static int ngap_gNB_handover_request_acknowledge(instance_t instance, ngap_hando DevAssert(ngap != NULL); NGAP_NGAP_PDU_t *pdu = encode_ng_handover_request_ack(msg); - if (!pdu) { - NGAP_ERROR("Failed to encode NG Handover Request Acknowledge\n"); - return -1; - } + DevAssert(pdu != NULL); if (LOG_DEBUGFLAG(DEBUG_ASN1)) xer_fprint(stdout, &asn_DEF_NGAP_NGAP_PDU, pdu); @@ -436,6 +427,10 @@ static int ngap_gNB_handover_notify(instance_t instance, const ngap_handover_not } NGAP_NGAP_PDU_t *pdu = encode_ng_handover_notify(msg); + if (!pdu) { + NGAP_ERROR("Failed to encode NG Handover Notify\n"); + return -1; + } if (ngap_gNB_encode_pdu(pdu, &ba.buf, (uint32_t *)&ba.len) < 0) { NGAP_ERROR("Failed to encode NG Handover Notify message\n"); @@ -479,10 +474,7 @@ static int ngap_gNB_handover_cancel(instance_t instance, const ngap_handover_can /* Encode NGAP PDU */ NGAP_NGAP_PDU_t *pdu = encode_ng_handover_cancel(msg); - if (pdu == NULL) { - NGAP_ERROR("Failed to encode NG Handover Cancel\n"); - return -1; - } + DevAssert(pdu != NULL); if (ngap_gNB_encode_pdu(pdu, &ba.buf, (uint32_t *)&ba.len) < 0) { NGAP_ERROR("Failed to encode NG Handover Cancel message PDU\n"); @@ -517,10 +509,7 @@ int ngap_gNB_handle_ul_ran_status_transfer(instance_t instance, const ngap_ran_s DevAssert(ue_context_p->gNB_ue_ngap_id == msg->gnb_ue_ngap_id); NGAP_NGAP_PDU_t *pdu = encode_ng_ul_ran_status_transfer(msg); - if (!pdu) { - NGAP_ERROR("Failed to encode UL RAN Status Transfer\n"); - return -1; - } + DevAssert(pdu != NULL); byte_array_t out = {.buf = NULL, .len = 0}; if (ngap_gNB_encode_pdu(pdu, &out.buf, (uint32_t *)&out.len) < 0) { From 0cbed89b03c5201ae95184d0bf9519cada2d0569 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Tue, 23 Sep 2025 14:20:39 +0200 Subject: [PATCH 870/964] Replace malloc_or_fail with calloc_or_fail for safer memory allocation - Update encoder functions in ngap_gNB_mobility_management.c to use calloc_or_fail - Provides zero-initialized memory and consistent error handling - Prevents uninitialized fields and improves memory safety Also: - Update NG Setup Request to use calloc_or_fail --- openair3/NGAP/ngap_gNB.c | 18 +++++++++--------- openair3/NGAP/ngap_gNB_mobility_management.c | 14 +++++++------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/openair3/NGAP/ngap_gNB.c b/openair3/NGAP/ngap_gNB.c index 7cc8041ad5..fb4d6c135b 100644 --- a/openair3/NGAP/ngap_gNB.c +++ b/openair3/NGAP/ngap_gNB.c @@ -677,7 +677,7 @@ static int ngap_gNB_generate_ng_setup_request( pdu.choice.initiatingMessage->value.present = NGAP_InitiatingMessage__value_PR_NGSetupRequest; out = &pdu.choice.initiatingMessage->value.choice.NGSetupRequest; /* mandatory */ - ie = (NGAP_NGSetupRequestIEs_t *)calloc(1, sizeof(NGAP_NGSetupRequestIEs_t)); + ie = calloc_or_fail(1, sizeof(NGAP_NGSetupRequestIEs_t)); ie->id = NGAP_ProtocolIE_ID_id_GlobalRANNodeID; ie->criticality = NGAP_Criticality_reject; ie->value.present = NGAP_NGSetupRequestIEs__value_PR_GlobalRANNodeID; @@ -700,7 +700,7 @@ static int ngap_gNB_generate_ng_setup_request( /* optional */ if (instance_p->gNB_name) { - ie = (NGAP_NGSetupRequestIEs_t *)calloc(1, sizeof(NGAP_NGSetupRequestIEs_t)); + ie = calloc_or_fail(1, sizeof(NGAP_NGSetupRequestIEs_t)); ie->id = NGAP_ProtocolIE_ID_id_RANNodeName; ie->criticality = NGAP_Criticality_ignore; ie->value.present = NGAP_NGSetupRequestIEs__value_PR_RANNodeName; @@ -710,28 +710,28 @@ static int ngap_gNB_generate_ng_setup_request( } /* mandatory */ - ie = (NGAP_NGSetupRequestIEs_t *)calloc(1, sizeof(NGAP_NGSetupRequestIEs_t)); + ie = calloc_or_fail(1, sizeof(NGAP_NGSetupRequestIEs_t)); ie->id = NGAP_ProtocolIE_ID_id_SupportedTAList; ie->criticality = NGAP_Criticality_reject; ie->value.present = NGAP_NGSetupRequestIEs__value_PR_SupportedTAList; { - ta = (NGAP_SupportedTAItem_t *)calloc(1, sizeof(NGAP_SupportedTAItem_t)); + ta = (NGAP_SupportedTAItem_t *)calloc_or_fail(1, sizeof(NGAP_SupportedTAItem_t)); INT24_TO_OCTET_STRING(instance_p->tac, &ta->tAC); { for (int i = 0; i < ngap_amf_data_p->broadcast_plmn_num; ++i) { - plmn = (NGAP_BroadcastPLMNItem_t *)calloc(1, sizeof(NGAP_BroadcastPLMNItem_t)); + plmn = (NGAP_BroadcastPLMNItem_t *)calloc_or_fail(1, sizeof(NGAP_BroadcastPLMNItem_t)); ngap_plmn_t *plmn_req = &instance_p->plmn[ngap_amf_data_p->broadcast_plmn_index[i]]; plmn_id_t *plmn_id = &instance_p->plmn[ngap_amf_data_p->broadcast_plmn_index[i]].plmn; MCC_MNC_TO_TBCD(plmn_id->mcc, plmn_id->mnc, plmn_id->mnc_digit_length, &plmn->pLMNIdentity); for (int si = 0; si < plmn_req->num_nssai; si++) { - ssi = (NGAP_SliceSupportItem_t *)calloc(1, sizeof(NGAP_SliceSupportItem_t)); + ssi = (NGAP_SliceSupportItem_t *)calloc_or_fail(1, sizeof(NGAP_SliceSupportItem_t)); INT8_TO_OCTET_STRING(plmn_req->s_nssai[si].sst, &ssi->s_NSSAI.sST); const uint32_t sd = plmn_req->s_nssai[si].sd; if (sd != 0xffffff) { - ssi->s_NSSAI.sD = calloc(1, sizeof(NGAP_SD_t)); - ssi->s_NSSAI.sD->buf = calloc(3, sizeof(uint8_t)); + ssi->s_NSSAI.sD = calloc_or_fail(1, sizeof(NGAP_SD_t)); + ssi->s_NSSAI.sD->buf = calloc_or_fail(3, sizeof(uint8_t)); ssi->s_NSSAI.sD->size = 3; ssi->s_NSSAI.sD->buf[0] = (sd & 0xff0000) >> 16; ssi->s_NSSAI.sD->buf[1] = (sd & 0x00ff00) >> 8; @@ -749,7 +749,7 @@ static int ngap_gNB_generate_ng_setup_request( asn1cSeqAdd(&out->protocolIEs.list, ie); /* mandatory */ - ie = (NGAP_NGSetupRequestIEs_t *)calloc(1, sizeof(NGAP_NGSetupRequestIEs_t)); + ie = calloc_or_fail(1, sizeof(NGAP_NGSetupRequestIEs_t)); ie->id = NGAP_ProtocolIE_ID_id_DefaultPagingDRX; ie->criticality = NGAP_Criticality_ignore; ie->value.present = NGAP_NGSetupRequestIEs__value_PR_PagingDRX; diff --git a/openair3/NGAP/ngap_gNB_mobility_management.c b/openair3/NGAP/ngap_gNB_mobility_management.c index a6ff4b39a1..95290f7bc3 100644 --- a/openair3/NGAP/ngap_gNB_mobility_management.c +++ b/openair3/NGAP/ngap_gNB_mobility_management.c @@ -37,7 +37,7 @@ * (9.2.3.1 of 3GPP TS 38.413) NG-RAN node → AMF */ NGAP_NGAP_PDU_t *encode_ng_handover_required(const ngap_handover_required_t *msg) { - NGAP_NGAP_PDU_t *pdu = malloc_or_fail(sizeof(*pdu)); + NGAP_NGAP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); /* Prepare the NGAP message to encode */ pdu->present = NGAP_NGAP_PDU_PR_initiatingMessage; @@ -198,7 +198,7 @@ NGAP_NGAP_PDU_t *encode_ng_handover_required(const ngap_handover_required_t *msg NGAP_NGAP_PDU_t *encode_ng_handover_failure(const ngap_handover_failure_t *msg) { - NGAP_NGAP_PDU_t *pdu = malloc_or_fail(sizeof(*pdu)); + NGAP_NGAP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); /* Prepare the NGAP message to encode */ pdu->present = NGAP_NGAP_PDU_PR_unsuccessfulOutcome; @@ -283,7 +283,7 @@ int decode_ng_handover_request(ngap_handover_request_t *out, const NGAP_NGAP_PDU // Mobility Restriction List (O) NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_HandoverRequestIEs_t, ie, container, NGAP_ProtocolIE_ID_id_MobilityRestrictionList, false); if (ie != NULL) { - out->mobility_restriction = malloc_or_fail(sizeof(*out->mobility_restriction)); + out->mobility_restriction = calloc_or_fail(1, sizeof(*out->mobility_restriction)); *out->mobility_restriction = decode_ngap_mobility_restriction(&ie->value.choice.MobilityRestrictionList); } @@ -385,7 +385,7 @@ int decode_ng_handover_request(ngap_handover_request_t *out, const NGAP_NGAP_PDU NGAP_NGAP_PDU_t *encode_ng_handover_request_ack(ngap_handover_request_ack_t *msg) { - NGAP_NGAP_PDU_t *pdu = malloc_or_fail(sizeof(*pdu)); + NGAP_NGAP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); pdu->present = NGAP_NGAP_PDU_PR_successfulOutcome; asn1cCalloc(pdu->choice.successfulOutcome, head); @@ -453,7 +453,7 @@ NGAP_NGAP_PDU_t *encode_ng_handover_request_ack(ngap_handover_request_ack_t *msg for (int j = 0; j < msg->pdusessions[pduSesIdx].ack_transfer.nb_of_qos_flow; j++) { asn1cSequenceAdd(transfer.qosFlowSetupResponseList.list, NGAP_QosFlowItemWithDataForwarding_t, qosItem); qosItem->qosFlowIdentifier = msg->pdusessions[pduSesIdx].ack_transfer.qos_setup_list[j].qfi; - qosItem->dataForwardingAccepted = malloc_or_fail(sizeof(*qosItem->dataForwardingAccepted)); + qosItem->dataForwardingAccepted = calloc_or_fail(1, sizeof(*qosItem->dataForwardingAccepted)); *qosItem->dataForwardingAccepted = NGAP_DataForwardingAccepted_data_forwarding_accepted; } @@ -565,7 +565,7 @@ void free_ng_handover_command(ngap_handover_command_t *msg) NGAP_NGAP_PDU_t *encode_ng_handover_notify(const ngap_handover_notify_t *msg) { - NGAP_NGAP_PDU_t *pdu = malloc_or_fail(sizeof(*pdu)); + NGAP_NGAP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); // Message Type (M) pdu->present = NGAP_NGAP_PDU_PR_initiatingMessage; @@ -682,7 +682,7 @@ int decode_ng_handover_cancel_ack(ngap_handover_cancel_ack_t *out, const NGAP_NG /** @brief Encode NGAP UL RAN Status Transfer (9.2.3.14 of 3GPP TS 38.413) */ NGAP_NGAP_PDU_t *encode_ng_ul_ran_status_transfer(const ngap_ran_status_transfer_t *msg) { - NGAP_NGAP_PDU_t *pdu = malloc_or_fail(sizeof(*pdu)); + NGAP_NGAP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); pdu->present = NGAP_NGAP_PDU_PR_initiatingMessage; asn1cCalloc(pdu->choice.initiatingMessage, head); head->procedureCode = NGAP_ProcedureCode_id_UplinkRANStatusTransfer; From c6a06dc81faeb866488cc51774337fc682ac7c5d Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Fri, 19 Sep 2025 15:48:22 +0200 Subject: [PATCH 871/964] Improve error message consistency in NGAP handover functions - ngap_gNB_handover_notify: Fix misleading error message from 'Failed to encode' to 'Failed to find UE context' for better clarity - ngap_gNB_handle_ul_ran_status_transfer: Standardize error message format from 'Could not find' to 'Failed to find' for consistency across functions This ensures consistent and accurate error reporting across all NGAP handover functions. --- openair3/NGAP/ngap_gNB.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openair3/NGAP/ngap_gNB.c b/openair3/NGAP/ngap_gNB.c index fb4d6c135b..b03e153486 100644 --- a/openair3/NGAP/ngap_gNB.c +++ b/openair3/NGAP/ngap_gNB.c @@ -416,7 +416,7 @@ static int ngap_gNB_handover_notify(instance_t instance, const ngap_handover_not DevAssert(ngap_gNB_instance_p != NULL); if ((ue_context_p = ngap_get_ue_context(msg->gNB_ue_ngap_id)) == NULL) { - NGAP_ERROR("Failed to encode Handover Notify: no ue context associated with gNB_ue_ngap_id=%d\n", msg->gNB_ue_ngap_id); + NGAP_ERROR("Failed to find UE context for Handover Notify: gNB_ue_ngap_id=%d\n", msg->gNB_ue_ngap_id); return -1; } DevAssert(ue_context_p->gNB_ue_ngap_id == msg->gNB_ue_ngap_id); @@ -502,7 +502,7 @@ int ngap_gNB_handle_ul_ran_status_transfer(instance_t instance, const ngap_ran_s ngap_gNB_ue_context_t *ue_context_p = ngap_get_ue_context(msg->gnb_ue_ngap_id); if (!ue_context_p) { - NGAP_ERROR("Could not find UE context for gNB_ue_ngap_id %d\n", msg->gnb_ue_ngap_id); + NGAP_ERROR("Failed to find UE context for gNB_ue_ngap_id %d\n", msg->gnb_ue_ngap_id); return -1; } From 1fc057cb08c141674040d73b9773a5a904abf9c9 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Thu, 18 Sep 2025 22:09:51 +0200 Subject: [PATCH 872/964] Optimize PLMN identity assignment in handover procedures Replace field-by-field assignment with struct copy for plmn_identity. Both source and destination use identical plmn_id_t type, making this change safe and more maintainable. - Reduces lines of code - More readable and less error-prone - Single memory copy operation instead of multiple field assignments --- openair2/RRC/NR/rrc_gNB_NGAP.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index 4c5b504f2d..b5915db574 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -1466,11 +1466,11 @@ void rrc_gNB_send_NGAP_HANDOVER_NOTIFY(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE) ho_notify->gNB_ue_ngap_id = UE->rrc_ue_id; ho_notify->amf_ue_ngap_id = UE->amf_ue_ngap_id; ho_notify->user_info.nrCellIdentity = rrc->nr_cellid; - ho_notify->user_info.target_ng_ran.tac = *du->setup_req->cell->info.tac; - ho_notify->user_info.target_ng_ran.targetgNBId = rrc->node_id; - ho_notify->user_info.target_ng_ran.plmn_identity.mcc = du->setup_req->cell->info.plmn.mcc; - ho_notify->user_info.target_ng_ran.plmn_identity.mnc = du->setup_req->cell->info.plmn.mnc; - ho_notify->user_info.target_ng_ran.plmn_identity.mnc_digit_length = du->setup_req->cell->info.plmn.mnc_digit_length; + + target_ran_node_id_t *target_ng_ran = &ho_notify->user_info.target_ng_ran; + target_ng_ran->tac = *du->setup_req->cell->info.tac; + target_ng_ran->targetgNBId = rrc->node_id; + target_ng_ran->plmn_identity = du->setup_req->cell->info.plmn; itti_send_msg_to_task(TASK_NGAP, rrc->module_id, msg_p); } @@ -1626,10 +1626,7 @@ void rrc_gNB_send_NGAP_HANDOVER_REQUIRED(gNB_RRC_INST *rrc, { LOG_I(NR_RRC, "Handover Preparation: send Handover Required (target gNB ID=%d, PCI=%d)\n", neighbour->gNB_ID, neighbour->physicalCellId); - const plmn_id_t plmn = {.mcc = neighbour->plmn.mnc, - .mnc = neighbour->plmn.mnc, - .mnc_digit_length = neighbour->plmn.mnc_digit_length}; - + const plmn_id_t plmn = neighbour->plmn; const target_ran_node_id_t target = { .plmn_identity = plmn, .tac = neighbour->tac, From 205bf7c993e59b91cea2eb4f81a5cd7289df46e9 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Fri, 19 Sep 2025 16:44:54 +0200 Subject: [PATCH 873/964] Add NULL check for DU lookup in handover notify Add early return if get_du_by_cell_id returns NULL to prevent segmentation fault when accessing DU structure members. --- openair2/RRC/NR/rrc_gNB_NGAP.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index b5915db574..8c839304c8 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -1457,11 +1457,15 @@ void rrc_gNB_send_NGAP_HANDOVER_REQUEST_ACKNOWLEDGE(gNB_RRC_INST *rrc, gNB_RRC_U void rrc_gNB_send_NGAP_HANDOVER_NOTIFY(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE) { LOG_I(NR_RRC, "Triggering NGAP Handover Notify\n"); + nr_rrc_du_container_t *du = get_du_by_cell_id(rrc, rrc->nr_cellid); + if (du == NULL) { + LOG_E(NR_RRC, "Failed to send Handover Notify: no DU found with NR Cell ID=%lu\n", rrc->nr_cellid); + return; + } MessageDef *msg_p = itti_alloc_new_message(TASK_RRC_GNB, 0, NGAP_HANDOVER_NOTIFY); ngap_handover_notify_t *ho_notify = &NGAP_HANDOVER_NOTIFY(msg_p); memset(ho_notify, 0, sizeof(*ho_notify)); - nr_rrc_du_container_t *du = get_du_by_cell_id(rrc, rrc->nr_cellid); ho_notify->gNB_ue_ngap_id = UE->rrc_ue_id; ho_notify->amf_ue_ngap_id = UE->amf_ue_ngap_id; From 9d9f272e74beba0dfa40c5056019610b90893b7c Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Fri, 19 Sep 2025 11:33:18 +0200 Subject: [PATCH 874/964] Refactor: split e1_send_bearer_updates into specialized functions Split monolithic e1_send_bearer_updates into three focused functions: - e1_send_bearer_updates(): DRB setup from F1 UE Context Modification Response - e1_request_pdcp_status(): Request PDCP status during inter-CU handover - e1_notify_pdcp_status(): Notify CU-UP with PDCP status during handover Extract common helpers: - append_e1_drb_mod_req(): Common DRB-to-mod for bearer request logic - e1_send_bearer_modification_request(): Common sending step Bug fixes: - Fix loop bounds (i < n instead of i == n) - Fix array access bounds checking - Fix DRB ID consistency Memory management: - Add missing free_e1ap_context_mod_request calls - Improve error handling with early returns In the process: - Simplify cuup_notify_reestablishment with FOR_EACH_SEQ_ARR loop - Adopted all callers to use new consolidated functions Improves maintainability and eliminates complex conditional logic. --- openair2/RRC/NR/nr_rrc_proto.h | 2 +- openair2/RRC/NR/rrc_gNB.c | 283 +++++++++++++++++++-------------- openair2/RRC/NR/rrc_gNB_NGAP.c | 2 +- 3 files changed, 166 insertions(+), 121 deletions(-) diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h index fbd09d20a1..777ea9a8d1 100644 --- a/openair2/RRC/NR/nr_rrc_proto.h +++ b/openair2/RRC/NR/nr_rrc_proto.h @@ -127,6 +127,6 @@ void openair_rrc_gNB_configuration(gNB_RRC_INST *rrc, gNB_RrcConfigurationReq *c NR_SRB_ToAddModList_t *createSRBlist(gNB_RRC_UE_t *ue, uint8_t reestablish); NR_DRB_ToAddModList_t *createDRBlist(gNB_RRC_UE_t *ue, bool reestablish, bool do_integrity, bool do_ciphering); void activate_srb(gNB_RRC_UE_t *UE, int srb_id); -void e1_send_bearer_updates(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, f1ap_drb_setup_t *drbs, const ngap_drb_status_t *drb_status); +void e1_notify_pdcp_status(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const ngap_drb_status_t *drb_status); #endif diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index aea6fb9259..c2734c755a 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -879,22 +879,65 @@ static void fill_security_info(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, security_inf nr_derive_key(UP_INT_ALG, secInfo->integrityProtectionAlgorithm, UE->kgnb, (uint8_t *)secInfo->integrityProtectionKey); } -/* \brief find existing PDU session inside E1AP Bearer Modif message, or - * point to new one. - * \param bearer_modif E1AP Bearer Modification Message - * \param pdu_id PDU session ID - * \return pointer to existing PDU session, or to new/unused one. */ -static pdu_session_to_mod_t *find_or_next_pdu_session(e1ap_bearer_mod_req_t *bearer_modif, int pdu_id) +/** @brief Add DRB modification to E1AP bearer modification request + * Finds PDU session by DRB ID, creates/updates PDU session modification entry + * and appends DRB modification + * @param req E1AP bearer modification request + * @param ue UE context + * @param drb_id DRB ID to find PDU session for + * @param drb_to_mod DRB modification data to append + * @return true if successful, false if PDU session not found */ +static bool append_e1_drb_mod_req(e1ap_bearer_mod_req_t *req, + gNB_RRC_UE_t *ue, + const int drb_id, + const DRB_nGRAN_to_mod_t *drb_to_mod) { - for (int i = 0; i < bearer_modif->numPDUSessionsMod; ++i) { - if (bearer_modif->pduSessionMod[i].sessionId == pdu_id) - return &bearer_modif->pduSessionMod[i]; + // Find PDU session by DRB ID + rrc_pdu_session_param_t *pdu = find_pduSession_from_drbId(ue, drb_id); + if (!pdu) { + LOG_E(NR_RRC, "UE %d: Failed to append E1 DRB mod, no PDU session found (DRB=%d)\n", ue->rrc_ue_id, drb_id); + return false; } - /* E1AP Bearer Modification has no PDU session to modify with that ID, create - * new entry */ - DevAssert(bearer_modif->numPDUSessionsMod < E1AP_MAX_NUM_PDU_SESSIONS - 1); - bearer_modif->numPDUSessionsMod += 1; - return &bearer_modif->pduSessionMod[bearer_modif->numPDUSessionsMod - 1]; + + int pdu_id = pdu->param.pdusession_id; + + // Find existing PDU session modification entry or create new one + pdu_session_to_mod_t *pdu_mod = NULL; + for (int i = 0; i < req->numPDUSessionsMod; ++i) { + if (req->pduSessionMod[i].sessionId == pdu_id) { + pdu_mod = &req->pduSessionMod[i]; + break; + } + } + + // Create new PDU session modification entry if not found + if (!pdu_mod) { + DevAssert(req->numPDUSessionsMod < E1AP_MAX_NUM_PDU_SESSIONS); + int new_index = req->numPDUSessionsMod++; + req->pduSessionMod[new_index].sessionId = pdu_id; + pdu_mod = &req->pduSessionMod[new_index]; + } + + // Append DRB modification + DevAssert(pdu_mod->numDRB2Modify < E1AP_MAX_NUM_DRBS); + pdu_mod->DRBnGRanModList[pdu_mod->numDRB2Modify++] = *drb_to_mod; + + return true; +} + +/** @brief Create DRB modification for reestablishment from existing DRB */ +static DRB_nGRAN_to_mod_t get_e1_drb_mod_reestablishment(const drb_t *drb, const bearer_context_pdcp_config_t *pdcp_config) +{ + DRB_nGRAN_to_mod_t drb_e1 = {0}; + drb_e1.id = drb->drb_id; + drb_e1.numDlUpParam = 1; + memcpy(&drb_e1.DlUpParamList[0].tl_info.tlAddress, &drb->du_tunnel_config.addr.buffer, sizeof(uint8_t) * 4); + drb_e1.DlUpParamList[0].tl_info.teId = drb->du_tunnel_config.teid; + /* PDCP configuration */ + drb_e1.pdcp_config = malloc_or_fail(sizeof(*drb_e1.pdcp_config)); + *drb_e1.pdcp_config = *pdcp_config; + drb_e1.pdcp_config->pDCP_Reestablishment = true; + return drb_e1; } /** @@ -907,44 +950,18 @@ static void cuup_notify_reestablishment(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue_p) .gNB_cu_up_ue_id = ue_p->rrc_ue_id, }; // Quit re-establishment notification if no CU-UP is associated - if (!is_cuup_associated(rrc)) { + if (!is_cuup_associated(rrc) || !ue_associated_to_cuup(rrc, ue_p)) { return; } - if (!ue_associated_to_cuup(rrc, ue_p)) - return; + + bool um_on_default_drb = rrc->configuration.um_on_default_drb; /* loop through active DRBs */ - for (int drb_id = 1; drb_id <= MAX_DRBS_PER_UE; drb_id++) { - drb_t *drb = get_drb(&ue_p->drbs, drb_id); - if (!drb) - continue; - /* fetch an existing PDU session for this DRB */ - rrc_pdu_session_param_t *pdu = find_pduSession_from_drbId(ue_p, drb_id); - if (pdu == NULL) { - LOG_E(RRC, "UE %d: E1 Bearer Context Modification: no PDU session for DRB ID %d\n", ue_p->rrc_ue_id, drb_id); - continue; + FOR_EACH_SEQ_ARR(drb_t *, drb, &ue_p->drbs) { + bearer_context_pdcp_config_t pdcp = set_bearer_context_pdcp_config(drb->pdcp_config, um_on_default_drb, ue_p->redcap_cap); + DRB_nGRAN_to_mod_t drb_e1 = get_e1_drb_mod_reestablishment(drb, &pdcp); + if (!append_e1_drb_mod_req(&req, ue_p, drb->drb_id, &drb_e1)) { + LOG_W(NR_RRC, "UE %d: Failed to append E1 DRB mod for reestablishment (DRB=%d)\n", ue_p->rrc_ue_id, drb->drb_id); } - /* Get pointer to existing (or new one) PDU session to modify in E1 */ - pdu_session_to_mod_t *pdu_e1 = find_or_next_pdu_session(&req, pdu->param.pdusession_id); - AssertError(pdu != NULL, - continue, - "UE %u: E1 Bearer Context Modification: PDU session %d to setup is null\n", - ue_p->rrc_ue_id, - pdu->param.pdusession_id); - /* Prepare PDU for E1 Bearear Context Modification Request */ - pdu_e1->sessionId = pdu->param.pdusession_id; - /* Fill DRB to setup with ID, DL TL and DL TEID */ - DRB_nGRAN_to_mod_t *drb_e1 = &pdu_e1->DRBnGRanModList[pdu_e1->numDRB2Modify]; - drb_e1->id = drb_id; - drb_e1->numDlUpParam = 1; - memcpy(&drb_e1->DlUpParamList[0].tl_info.tlAddress, &drb->du_tunnel_config.addr.buffer, sizeof(uint8_t) * 4); - drb_e1->DlUpParamList[0].tl_info.teId = drb->du_tunnel_config.teid; - /* PDCP configuration */ - if (!drb_e1->pdcp_config) - drb_e1->pdcp_config = malloc_or_fail(sizeof(*drb_e1->pdcp_config)); - *drb_e1->pdcp_config = set_bearer_context_pdcp_config(drb->pdcp_config, rrc->configuration.um_on_default_drb, ue_p->redcap_cap); - drb_e1->pdcp_config->pDCP_Reestablishment = true; - /* increase DRB to modify counter */ - pdu_e1->numDRB2Modify += 1; } #if 0 @@ -2094,12 +2111,14 @@ void rrc_gNB_process_dc_overall_timeout(const module_id_t gnb_mod_idP, x2ap_ENDC /* \brief fill E1 bearer modification's DRB from F1 DRB * \param drb_e1 pointer to a DRB inside an E1 bearer modification message * \param drb_f1 pointer to a DRB inside an F1 UE Ctxt modification Response */ -static void fill_e1_bearer_modif(DRB_nGRAN_to_mod_t *drb_e1, const f1ap_drb_setup_t *drb_f1) +static DRB_nGRAN_to_mod_t fill_e1_bearer_modif_from_f1(const f1ap_drb_setup_t *drb_f1) { - drb_e1->id = drb_f1->id; - drb_e1->numDlUpParam = drb_f1->up_dl_tnl_len; - drb_e1->DlUpParamList[0].tl_info.tlAddress = drb_f1->up_dl_tnl[0].tl_address; - drb_e1->DlUpParamList[0].tl_info.teId = drb_f1->up_dl_tnl[0].teid; + DRB_nGRAN_to_mod_t drb_e1 = {0}; + drb_e1.id = drb_f1->id; + drb_e1.numDlUpParam = drb_f1->up_dl_tnl_len; + drb_e1.DlUpParamList[0].tl_info.tlAddress = drb_f1->up_dl_tnl[0].tl_address; + drb_e1.DlUpParamList[0].tl_info.teId = drb_f1->up_dl_tnl[0].teid; + return drb_e1; } static gtpu_tunnel_t f1u_gtp_update(uint32_t teid, const in_addr_t addr) @@ -2126,89 +2145,113 @@ static void store_du_f1u_tunnel(const f1ap_drb_setup_t *drbs, int n, gNB_RRC_UE_ } } -static void fill_e1_bearer_modif_pdcp_status(gNB_RRC_UE_t *UE, - DRB_nGRAN_to_mod_t *drb_to_mod, - const int drb_id, - const bool um_on_default_drb, - const ngap_drb_status_t *drb_status) +static DRB_nGRAN_to_mod_t get_e1_drb_mod_pdcp_status(const drb_t *drb, + bearer_context_pdcp_config_t *pdcp_config, + const ngap_drb_status_t *drb_status) { DevAssert(drb_status); - drb_to_mod->id = drb_id; - drb_to_mod->pdcp_sn_status_requested = false; + DevAssert(pdcp_config); + DevAssert(drb); + DRB_nGRAN_to_mod_t drb_to_mod = {0}; + drb_to_mod.id = drb->drb_id; + drb_to_mod.pdcp_sn_status_requested = false; // PDCP SN Status Information - drb_to_mod->pdcp_config = calloc_or_fail(1, sizeof(*drb_to_mod->pdcp_config)); - drb_t *drb = get_drb(&UE->drbs, drb_id); - *drb_to_mod->pdcp_config = set_bearer_context_pdcp_config(drb->pdcp_config, um_on_default_drb, UE->redcap_cap); - drb_to_mod->pdcp_status = calloc_or_fail(1, sizeof(*drb_to_mod->pdcp_status)); - drb_to_mod->pdcp_status->dl_count.hfn = drb_status->dl_count.hfn; - drb_to_mod->pdcp_status->dl_count.sn = drb_status->dl_count.pdcp_sn; - drb_to_mod->pdcp_status->ul_count.hfn = drb_status->ul_count.hfn; - drb_to_mod->pdcp_status->ul_count.sn = drb_status->ul_count.pdcp_sn; + drb_to_mod.pdcp_config = calloc_or_fail(1, sizeof(*drb_to_mod.pdcp_config)); + *drb_to_mod.pdcp_config = *pdcp_config; + drb_to_mod.pdcp_status = calloc_or_fail(1, sizeof(*drb_to_mod.pdcp_status)); + drb_to_mod.pdcp_status->dl_count.hfn = drb_status->dl_count.hfn; + drb_to_mod.pdcp_status->dl_count.sn = drb_status->dl_count.pdcp_sn; + drb_to_mod.pdcp_status->ul_count.hfn = drb_status->ul_count.hfn; + drb_to_mod.pdcp_status->ul_count.sn = drb_status->ul_count.pdcp_sn; + return drb_to_mod; } -/** @brief Fill and send Bearer Context Modification Request with: - * (1) from F1 UE Context DRB to setup list, or (2) with PDCP Status Request */ -void e1_send_bearer_updates(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, f1ap_drb_setup_t *drbs, const ngap_drb_status_t *drb_status) +/** @brief Send E1 bearer context modification request to CU-UP */ +static void e1_send_bearer_modification_request(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, e1ap_bearer_mod_req_t *req) { - // Quit bearer updates if no CU-UP is associated - if (!is_cuup_associated(rrc)) { + if (req->numPDUSessionsMod == 0) { + LOG_W(NR_RRC, "UE %d: No PDU sessions to modify in E1 bearer update\n", UE->rrc_ue_id); return; } - // we assume the same UE ID in CU-UP and CU-CP + DevAssert(req->numPDUSessions == 0); + req->secInfo = malloc_or_fail(sizeof(*req->secInfo)); + fill_security_info(rrc, UE, req->secInfo); + + sctp_assoc_t assoc_id = get_existing_cuup_for_ue(rrc, UE); + rrc->cucp_cuup.bearer_context_mod(assoc_id, req); +} + +/** @brief Send E1 bearer updates for DRBs to setup from F1 UE Context Modification Response */ +static void e1_send_bearer_updates(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, f1ap_drb_setup_t *drbs) +{ + if (!is_cuup_associated(rrc) || n <= 0) + return; + e1ap_bearer_mod_req_t req = { .gNB_cu_cp_ue_id = UE->rrc_ue_id, .gNB_cu_up_ue_id = UE->rrc_ue_id, }; - bool is_inter_cu_ho = UE->ho_context && UE->ho_context->source && !UE->ho_context->target; - int drb_index = 0; - FOR_EACH_SEQ_ARR(drb_t *, drb, &UE->drbs) { - int drb_id = drb->drb_id; - DRB_nGRAN_to_mod_t drb_to_mod = {0}; - if (n > 0) { - /* DRBs to Setup in F1 UE Context Modifcation Response */ - if (drb_index == n) - break; - const f1ap_drb_setup_t *drb_f1 = &drbs[drb_index]; - drb_id = drb_f1->id; - fill_e1_bearer_modif(&drb_to_mod, drb_f1); - } else if (is_inter_cu_ho) { - /* On-going handover: send PDCP Status Request */ - drb_t *drb = get_drb(&UE->drbs, drb_id); - if (!drb) { - LOG_E(NR_RRC, "Failed to send PDCP Status Request: DRB %d not found\n", drb_id); - continue; - } - drb_to_mod.id = drb_id; - // PDCP SN Status Request - drb_to_mod.pdcp_sn_status_requested = true; - LOG_I(NR_RRC, "PDCP Status requested (drb_id=%d)\n", drb_id); - } else if (drb_status) { - /* On-going handover: send PDCP Status */ - fill_e1_bearer_modif_pdcp_status(UE, &drb_to_mod, drb_id, rrc->configuration.um_on_default_drb, drb_status); - } + for (int i = 0; i < n; i++) { + const f1ap_drb_setup_t *drb_f1 = &drbs[i]; + int drb_id = drb_f1->id; rrc_pdu_session_param_t *pdu = find_pduSession_from_drbId(UE, drb_id); if (!pdu) continue; - pdu_session_to_mod_t *to_mod = find_or_next_pdu_session(&req, pdu->param.pdusession_id); - DevAssert(to_mod); - to_mod->sessionId = pdu->param.pdusession_id; - // Fill E1 DRB to Modify item - to_mod->DRBnGRanModList[to_mod->numDRB2Modify++] = drb_to_mod; - - drb_index++; + DRB_nGRAN_to_mod_t drb_to_mod = fill_e1_bearer_modif_from_f1(drb_f1); + if (!append_e1_drb_mod_req(&req, UE, drb_id, &drb_to_mod)) { + LOG_W(NR_RRC, "UE %d: Failed to append E1 DRB mod from F1 (DRB=%d)\n", UE->rrc_ue_id, drb_id); + } } - DevAssert(req.numPDUSessionsMod > 0); - DevAssert(req.numPDUSessions == 0); - // Always send security information - req.secInfo = malloc_or_fail(sizeof(*req.secInfo)); - fill_security_info(rrc, UE, req.secInfo); + e1_send_bearer_modification_request(rrc, UE, &req); + free_e1ap_context_mod_request(&req); +} - // send the E1 bearer modification request message to update F1-U tunnel info - sctp_assoc_t assoc_id = get_existing_cuup_for_ue(rrc, UE); - rrc->cucp_cuup.bearer_context_mod(assoc_id, &req); +/** @brief Request PDCP status from CU-UP during inter-CU handover */ +static void e1_request_pdcp_status(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE) +{ + if (!is_cuup_associated(rrc)) + return; + + e1ap_bearer_mod_req_t req = { + .gNB_cu_cp_ue_id = UE->rrc_ue_id, + .gNB_cu_up_ue_id = UE->rrc_ue_id, + }; + + FOR_EACH_SEQ_ARR(drb_t *, drb, &UE->drbs) { + DRB_nGRAN_to_mod_t drb_to_mod = {.id = drb->drb_id, .pdcp_sn_status_requested = true}; + LOG_D(NR_RRC, "PDCP Status requested (drb_id=%d)\n", drb->drb_id); + if (!append_e1_drb_mod_req(&req, UE, drb->drb_id, &drb_to_mod)) { + LOG_W(NR_RRC, "UE %d: Failed to append E1 DRB mod for PDCP status request (DRB=%d)\n", UE->rrc_ue_id, drb->drb_id); + } + } + + e1_send_bearer_modification_request(rrc, UE, &req); + free_e1ap_context_mod_request(&req); +} + +/** @brief Notify CU-UP with PDCP status during handover */ +void e1_notify_pdcp_status(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const ngap_drb_status_t *drb_status) +{ + if (!is_cuup_associated(rrc) || !drb_status) + return; + + e1ap_bearer_mod_req_t req = { + .gNB_cu_cp_ue_id = UE->rrc_ue_id, + .gNB_cu_up_ue_id = UE->rrc_ue_id, + }; + + FOR_EACH_SEQ_ARR(drb_t *, drb, &UE->drbs) { + LOG_I(NR_RRC, "Forward PDCP Status to CU-UP (drb_id=%d)\n", drb->drb_id); + bearer_context_pdcp_config_t pdcp_config = set_bearer_context_pdcp_config(drb->pdcp_config, rrc->configuration.um_on_default_drb, UE->redcap_cap); + DRB_nGRAN_to_mod_t drb_to_mod = get_e1_drb_mod_pdcp_status(drb, &pdcp_config, drb_status); + append_e1_drb_mod_req(&req, UE, drb->drb_id, &drb_to_mod); + } + + e1_send_bearer_modification_request(rrc, UE, &req); + free_e1ap_context_mod_request(&req); } static void rrc_CU_process_ue_context_setup_response(MessageDef *msg_p, instance_t instance) @@ -2262,7 +2305,7 @@ static void rrc_CU_process_ue_context_setup_response(MessageDef *msg_p, instance AssertFatal(UE->Srb[1].Active && UE->Srb[2].Active, "SRBs 1 and 2 must be active during DRB Establishment"); store_du_f1u_tunnel(resp->drbs, resp->drbs_len, UE); if (num_drb == 0) - e1_send_bearer_updates(rrc, UE, resp->drbs_len, resp->drbs, NULL); + e1_send_bearer_updates(rrc, UE, resp->drbs_len, resp->drbs); else cuup_notify_reestablishment(rrc, UE); } @@ -2397,9 +2440,11 @@ static void rrc_CU_process_ue_context_modification_response(MessageDef *msg_p, i gNB_RRC_UE_t *UE = &ue_context_p->ue_context; bool is_inter_cu_ho = UE->ho_context && UE->ho_context->source && !UE->ho_context->target; - if (resp->drbs_len > 0 || is_inter_cu_ho) { + if (resp->drbs_len > 0) { // DRB to setup store_du_f1u_tunnel(resp->drbs, resp->drbs_len, UE); - e1_send_bearer_updates(rrc, UE, resp->drbs_len, resp->drbs, NULL); + e1_send_bearer_updates(rrc, UE, resp->drbs_len, resp->drbs); + } else if (is_inter_cu_ho) { // PDCP status request + e1_request_pdcp_status(rrc, UE); } if (resp->du_to_cu_rrc_info) { diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index 8c839304c8..7d75384a9b 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -1725,7 +1725,7 @@ int rrc_gNB_process_NGAP_DL_RAN_STATUS_TRANSFER(MessageDef *msg_p, instance_t in s->dl_count.sn_len == NGAP_SN_LENGTH_18 ? "18-bit" : "12-bit"); // Send to PDCP layer - e1_send_bearer_updates(rrc, UE, 0, NULL, s); + e1_notify_pdcp_status(rrc, UE, s); } return 0; From 4aafd1e369f3ba1c95e24244c9d2ee997c66c3ee Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Thu, 25 Sep 2025 11:28:17 +0200 Subject: [PATCH 875/964] Simplify N2 handover test to focus on N2 handover only - Remove extensive traffic testing before HO (iperf tests 030001, 030002) - Do 1 ping test after attachment - Reduce ping packet count from 100 to 50 packets for remaining connectivity test Time savings: ~2-3 minutes by removing traffic validation overhead --- ci-scripts/xml_files/container_5g_rfsim_n2_ho.xml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/ci-scripts/xml_files/container_5g_rfsim_n2_ho.xml b/ci-scripts/xml_files/container_5g_rfsim_n2_ho.xml index 1b2e84046c..feffaedf05 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_n2_ho.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_n2_ho.xml @@ -31,9 +31,6 @@ 000002 000003 020001 - 020002 - 030001 - 030002 000004 040001 050001 @@ -110,7 +107,7 @@ acamas rfsim5g_ue acamas - -c 100 -i 0.25 + -c 50 -i 0.25 5 @@ -121,7 +118,7 @@ acamas rfsim5g_ext_dn acamas - -c 100 -i 0.25 + -c 50 -i 0.25 10 From dcd7ee711bbb9029803267727db41835f8bbc0ec Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Thu, 18 Sep 2025 22:25:35 +0200 Subject: [PATCH 876/964] Improve RRC neighbor configuration documentation - Move 'What is a gNB neighbor?' explanation from rrc-usage.md to handover-tutorial.md where it belongs - Replace generic parameter names with actual configuration parameter names and specific descriptions (e.g. gNB_ID, nr_cellid) - Add example configuration structure showing proper syntax - Add missing 'band' parameter that was not listed before - Provide concrete examples and exact constraints for each parameter - Cross-reference between documents for better organization This addresses documentation issues where generic parameter descriptions were not useful for developers configuring neighbor cells. --- doc/RRC/rrc-usage.md | 55 ++++++++++++++++++++++++++-------------- doc/handover-tutorial.md | 17 +++++++++++++ 2 files changed, 53 insertions(+), 19 deletions(-) diff --git a/doc/RRC/rrc-usage.md b/doc/RRC/rrc-usage.md index 0eb7bc7195..0e8c94c61a 100644 --- a/doc/RRC/rrc-usage.md +++ b/doc/RRC/rrc-usage.md @@ -99,26 +99,43 @@ the [MAC configuration](../MAC/mac-usage.md) as well for SIB configuration. ### Neighbor-gNB configuration -#### What is a gNB neighbor? - -Network continuity is a key aspect of 5G. In the 5G architecture, gNB neighbors play a central role in maintaining service continuity through mechanisms such as handover and load balancing. By definition, a gNB neighbor is another gNB that can be measured and linked by the UE. If the current serving gNB is no longer optimal, the UE may connect to a neighbor gNB. - -To support this behavior, the network configuration specifies additional frequencies and cells that the UE should measure. The UE reports these measurements to the network, which then decides whether or not to initiate a handover. - -Neighbor types include: -- **Intra-gNB neighbors** - cells belonging to the same gNB -- **Inter-gNB neighbors** - cells belonging to different gNBs -- **Inter-RAT neighbors** - cells belonging to another RAT (e.g., LTE) +Refer to the [handover tutorial](../handover-tutorial.md) for detailed information about gNB neighbors and handover procedures. #### Required configuration parameters -To define a neighbor cell in the configuration file, the following parameters are typically needed: -- **gNB ID** - unique identifier of the gNB -- **Cell ID** - identifier of the cell within the gNB -- **Physical Cell ID** - identifier of the cell’s synchronization signal (PCI) -- **Absolute Frequency** - frequency used by the SSB (absoluteFrequencySSB) -- **Subcarrier Spacing** - numerology (e.g., 15 kHz, 30 kHz) -- **PLMN configuration** - MCC, MNC, and MNC length -- **Tracking Area Code (TAC)** - identifier of the tracking area +To define a neighbor cell in the configuration file, the following parameters are required: -Refer to the [handover tutorial](../handover-tutorial.md) for more information. +- `gNB_ID` - identifier of the neighbor gNB (e.g., `0xe01`) +- `nr_cellid` - cell identifier of the neighbor cell (e.g., `11111111`) +- `physical_cellId` - physical cell ID for radio identification (e.g., `1`) +- `absoluteFrequencySSB` - SSB frequency in ARFCN notation (e.g., `643296`) +- `subcarrierSpacing` - numerology index: 0=15kHz, 1=30kHz, 2=60kHz, 3=120kHz +- `band` - 3GPP frequency band number (e.g., `78` for 3.5GHz) +- `plmn` - PLMN configuration object with: + - `mcc` - mobile country code (3 digits, e.g., `001`) + - `mnc` - mobile network code (2-3 digits, e.g., `01`) + - `mnc_length` - number of digits in MNC (must be `2` or `3`) +- `tracking_area_code` - tracking area identifier (e.g., `1`) + +Example configuration structure: +``` +neighbour_list = ( + { + nr_cellid = 12345678; + neighbour_cell_configuration = ( + { + gNB_ID = 0xe01; + nr_cellid = 11111111; + physical_cellId = 1; + absoluteFrequencySSB = 643296; + subcarrierSpacing = 1; # 30 kHz + band = 78; + plmn = { mcc = 001; mnc = 01; mnc_length = 2 }; + tracking_area_code = 1; + } + ); + } +); +``` + +Refer to the [handover tutorial](../handover-tutorial.md) for complete examples and detailed setup instructions. diff --git a/doc/handover-tutorial.md b/doc/handover-tutorial.md index 67bf99b3c2..eeb4ce09fa 100644 --- a/doc/handover-tutorial.md +++ b/doc/handover-tutorial.md @@ -13,6 +13,23 @@ same. ![F1 Handover setup](./RRC/ho.png) +# What is a gNB neighbor? + +Network continuity is a key aspect of 5G. In the 5G architecture, gNB neighbors +play a central role in maintaining service continuity through mechanisms such +as handover and load balancing. By definition, a gNB neighbor is another gNB +that can be measured and linked by the UE. If the current serving gNB is no +longer optimal, the UE may connect to a neighbor gNB. + +To support this behavior, the network configuration specifies additional frequencies +and cells that the UE should measure. The UE reports these measurements to the +network, which then decides whether or not to initiate a handover. + +Neighbor types include: +- **Intra-gNB neighbors** - cells belonging to the same gNB +- **Inter-gNB neighbors** - cells belonging to different gNBs +- **Inter-RAT neighbors** - cells belonging to another RAT (e.g., LTE) + # Steps to run F1 handover with OAI UE Measurement reporting and processing of RRC Reconfiguration for Mobility are From dcb10ffc944c82dded1b54a8a6323c80f74e34e5 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 15 Jan 2025 10:30:00 +0100 Subject: [PATCH 877/964] Handover tutorial: fix minor issues and add same-machine setup guidance - Update opening statement to reflect both F1 (intra-gNB) and N2 (inter-gNB) handover support - Fix grammar error: 'either by by decision' -> 'either a decision' - Standardize naming: 'gNB PCI1' -> 'gNB-PCI1' - Fix typo: 'neighbor call' -> 'neighbor cell' - Remove --sa flag from N2 handover target gNB command for consistency - Add network configuration notes for same-machine setups: * IP address assignment instructions to avoid network conflicts * Target gNB command options for proper network interface configuration --- doc/handover-tutorial.md | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/doc/handover-tutorial.md b/doc/handover-tutorial.md index eeb4ce09fa..b6e60746aa 100644 --- a/doc/handover-tutorial.md +++ b/doc/handover-tutorial.md @@ -1,5 +1,5 @@ -This tutorial explains how to perform handovers. For the moment, only F1 -handovers are supported. +This tutorial explains how to perform handovers. It covers both F1 handovers +(intra-gNB, within a single gNB between DUs) and N2 handovers (inter-gNB). [[_TOC_]] @@ -370,10 +370,16 @@ We assume: * Two independent gNBs connected to the same 5GC via N2 interface. * A UE initially connected to gNB-PCI0, which will be handed over to gNB-PCI1. -* Handover is triggered by either by decision based measurement event (e.g. A3) or telnet command. +* Handover is triggered by either a decision based measurement event (e.g. A3) or telnet command. ## Steps to run N2 handover with OAI UE +**Note for same-machine setup:** When running both gNBs on the same machine, you need to assign a unique IP address to the second gNB to avoid network conflicts. For example: + +```sh +sudo ip addr add 192.168.71.180/24 dev rfsim5g-public +``` + 1. Similarly to F1 handover, UE does not support any measurement reporting and handover is triggered by telnet command. Therefore, ensure that both gNBs and UE are built with telnet support: @@ -397,10 +403,17 @@ sudo ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --rfsim --ui Ensure the UE successfully registers with the network. -4. Start the target gNB (gNB PCI1) e.g. +4. Start the target gNB (gNB-PCI1) e.g. ```sh -sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.pci1.rfsim.conf --sa --rfsim --telnetsrv --telnetsrv.shrmod ci --gNBs.[0].min_rxtxtime 6 --rfsimulator.serveraddr 127.0.0.1 +sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.pci1.rfsim.conf --rfsim --telnetsrv --telnetsrv.shrmod ci --gNBs.[0].min_rxtxtime 6 --rfsimulator.serveraddr 127.0.0.1 +``` + +**Note for same-machine setup:** When running both gNBs on the same machine, add the following network interface options to the target gNB command, e.g.: + +```sh +--gNBs.[0].NETWORK_INTERFACES.GNB_IPV4_ADDRESS_FOR_NG_AMF 192.168.71.180 +--gNBs.[0].NETWORK_INTERFACES.GNB_IPV4_ADDRESS_FOR_NGU 192.168.71.180 ``` 5. Trigger the N2 handover, e.g. @@ -410,7 +423,7 @@ From gNB-PCI0, trigger handover on target gNB with PCI 1 for UE ID 1: ```sh echo ci trigger_n2_ho 1,1 | nc 127.0.0.1 9090 && echo ``` -where the input parameters correspond to the PCI of the neighbor call and the RRC ID of the UE. +where the input parameters correspond to the PCI of the neighbor cell and the RRC ID of the UE. This will initiate the N2 handover on the source gNB. From 6193d7c7f452835bab2b0a268aaae2b10968bd69 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Mon, 29 Sep 2025 17:21:45 +0200 Subject: [PATCH 878/964] Create XML for OAIUE longrun pipeline Test duration: 1 hour Test scenario: 3x DL 10 min test (20 Mbps) + 3x UL 10 min test (5 Mbps) --- .../container_sa_n310_nrue_longrun.xml | 179 ++++++++++++++++++ 1 file changed, 179 insertions(+) create mode 100644 ci-scripts/xml_files/container_sa_n310_nrue_longrun.xml diff --git a/ci-scripts/xml_files/container_sa_n310_nrue_longrun.xml b/ci-scripts/xml_files/container_sa_n310_nrue_longrun.xml new file mode 100644 index 0000000000..f0d8f4f3b6 --- /dev/null +++ b/ci-scripts/xml_files/container_sa_n310_nrue_longrun.xml @@ -0,0 +1,179 @@ + + + LONGRUN-5G-NRUE + Longrun 40 MHz TDD SA + tasks + + 060000 + 010000 010001 + 800813 + 020000 + 800814 + 020001 + 000001 + 001000 + 000100 + 001000 + 000100 + 001000 + 000100 + 001000 + 000200 + 001000 + 000200 + 001000 + 000200 + 040001 040000 + 333333 + 444444 + 060001 + + + + + DeployCoreNetwork + Initialize 5G Core + oc-cn5g + + + + Pull_Cluster_Image + Pull Images from Cluster + oai-gnb + avra + + + + Pull_Cluster_Image + Pull Images from Cluster + oai-nr-ue + caracal + + + + Create_Workspace + Create new Workspace + avra + + + + Deploy_Object + Deploy gNB (TDD/Band78/40MHz/N310) in a container + avra + ci-scripts/yaml_files/5g_sa_n310_gnb + 3 + + + + Create_Workspace + Create new Workspace + caracal + + + + Deploy_Object + Deploy nrUE (TDD/Band78/40MHz/N310) in a container + ci-scripts/yaml_files/5g_sa_n310_nrue + caracal + 3 + + + + Attach_UE + Attach OAIUE + oai_ue_caracal + + + + Iperf + iperf (DL/10Mbps/UDP)(10 min) + -u -b 10M -t 600 -i 1 -R + oai_ue_caracal + oc-cn5g + 25 + 80 + + + + Iperf + iperf (UL/2Mbps/UDP)(10 min) + -u -b 2M -t 600 -i 1 + oai_ue_caracal + oc-cn5g + 25 + 80 + + + + Ping + Ping: 20pings in 20sec + oai_ue_caracal + oc-cn5g + -c 20 + 1 + 25 + + + + Undeploy_Object + true + Undeploy gNB + avra + ci-scripts/yaml_files/5g_sa_n310_gnb + 20,100,100,100 + 20,100,100,100 + + + + Undeploy_Object + true + Undeploy nr UE + caracal + ci-scripts/yaml_files/5g_sa_n310_nrue + + + + Clean_Test_Server_Images + true + Clean Test Images on Test Server + avra + oai-gnb + + + + Clean_Test_Server_Images + true + Clean Test Images on Test Server + caracal + oai-nr-ue + + + + UndeployCoreNetwork + Terminate 5G Core + true + oc-cn5g + + + From 7935c19d21f9ef848256204b81a78360b02a1da3 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Mon, 28 Jul 2025 22:31:11 +0200 Subject: [PATCH 879/964] Fix in CreateWorkspace Previously, the script attempted to directly merge ${merge}, which could f ail if the branch was not already available locally. This update explicitly fetches the branch from origin and then merges FETCH_HEAD with --ff, ensuring the merge works even when the branch is missing locally. --- ci-scripts/scripts/create_workspace.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci-scripts/scripts/create_workspace.sh b/ci-scripts/scripts/create_workspace.sh index c8410802db..a8359a9ae4 100755 --- a/ci-scripts/scripts/create_workspace.sh +++ b/ci-scripts/scripts/create_workspace.sh @@ -22,5 +22,5 @@ git config user.name "OAI Jenkins" git config advice.detachedHead false mkdir -p cmake_targets/log git checkout -f ${ref} -[ -n "${merge}" ] && git merge --ff ${merge} -m "Temporary merge for CI" +[ -n "${merge}" ] && git fetch origin ${merge} && git merge --ff FETCH_HEAD -m "Temporary merge for CI" exit 0 From 2dde472cfd78e4f7aca2e7b4a8d1e3ce59e55483 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Wed, 1 Oct 2025 10:58:39 +0200 Subject: [PATCH 880/964] Adjust gNB conf file in OAIUE test Increase prach_dtx_threshold to avoid fake PRACH detection. --- ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf b/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf index 2f994ab25e..ed1c79911e 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf @@ -184,7 +184,7 @@ L1s = ( { num_cc = 1; tr_n_preference = "local_mac"; - prach_dtx_threshold = 130; + prach_dtx_threshold = 150; #pucch0_dtx_threshold = 150; } ); From 2ea4cbbd930639f46c5e85ab436e186f60bbadbb Mon Sep 17 00:00:00 2001 From: calvin_peyron Date: Wed, 17 Sep 2025 11:23:35 +0200 Subject: [PATCH 881/964] update env variable usage documentation --- doc/environment-variables.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/doc/environment-variables.md b/doc/environment-variables.md index 76730294fa..767afa6db4 100644 --- a/doc/environment-variables.md +++ b/doc/environment-variables.md @@ -3,14 +3,13 @@ OAI uses/supports a number of environment variables, documented in the following: - `NFAPI_TRACE_LEVEL`: set the nfapi custom logging framework's log level; can be one of `error`, `warn`, `note`, `info`, `debug`. Default is `warn`. -- `NR_AWGN_RESULTS_DIR`: directory containing BLER curves for L2simulator channel modelling in SISO case -- `NR_MIMO2x2_AWGN_RESULTS_DIR`: directory containing BLER curves for L2simulator channel modelling in 2x2 MIMO case +- `NR_AWGN_RESULTS_DIR`: directory containing BLER curves for NR L2simulator channel modelling in SISO case +- `NR_MIMO2x2_AWGN_RESULTS_DIR`: directory containing BLER curves for NR L2simulator channel modelling in 2x2 MIMO case +- `OPENAIR_DIR`: should point to the root directory of OpenAirInterface; BLER curves for LTE L2sim channel emulation - `NVRAM_DIR`: directory to read/write NVRAM data in (5G) `nvram` tool; if not defined, will use `PWD` (working directory) - `OAI_CONFIGMODULE`: can be used to pass the configuration file instead of `-O` - `OAI_GDBSTACKS`: if defined when hitting an assertion (`DevAssert()`, `AssertFatal()`, ...), OAI will load `gdb` and provide a backtrace for every thread - `OAI_RNGSEED`: overwrites any seed for random number generators (RNG) in simulators -- `OAI_THREADPOOLMEASUREMENTS`: path to a file to store thread pool debugging information, see the [thread pool documentation](../common/utils/threadPool/thread-pool.md) -- `OPENAIR_DIR`: should point to the root directory of OpenAirInterface; some code relies on this to get a filename, e.g., BLER curves for L2sim channel emulation - `USIM_DIR`: directory to read/write USIM data in (4G) `usim` tool; if not defined, will use `PWD` (working directory) Furthermore, these variables appear in code that is not maintained and maybe not even compiled anywhere: @@ -19,3 +18,5 @@ Furthermore, these variables appear in code that is not maintained and maybe not - `SSH_CLIENT`: alternative host to connect to, for CLI, if `REMADDR` is not defined - `USER`: user name in the command-line interface - `rftestInputFile`: input file for the `calibration_test` tool +- `OPENAIR2_DIR` : OMV and OMG modules, obsolete +- `TITLE`: OTG module, obsolete From a0d8baf323b169d4255c0d8f5a3998e8ff30ee52 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Tue, 2 Sep 2025 17:07:28 +0200 Subject: [PATCH 882/964] update and rename TESTING_GNB_W_COTS_UE.md to describe actual content --- doc/README.md | 2 +- ..._COTS_UE.md => TESTING_OAI_NSA_COTS_UE.md} | 61 +++++++++--------- .../attach_signaling_scheme.jpg | Bin .../oai_fr1_lab.jpg | Bin .../oai_fr1_setup.jpg | Bin .../enb.conf | 0 .../gnb.conf | 0 .../oai_enb.log | 0 .../oai_fr1_setup.vsdx | Bin .../oai_gnb.log | 0 10 files changed, 33 insertions(+), 30 deletions(-) rename doc/{TESTING_GNB_W_COTS_UE.md => TESTING_OAI_NSA_COTS_UE.md} (85%) rename doc/{testing_gnb_w_cots_ue_resources => images}/attach_signaling_scheme.jpg (100%) rename doc/{testing_gnb_w_cots_ue_resources => images}/oai_fr1_lab.jpg (100%) rename doc/{testing_gnb_w_cots_ue_resources => images}/oai_fr1_setup.jpg (100%) rename doc/{testing_gnb_w_cots_ue_resources => testing_oai_nsa_w_cots_ue_resources}/enb.conf (100%) rename doc/{testing_gnb_w_cots_ue_resources => testing_oai_nsa_w_cots_ue_resources}/gnb.conf (100%) rename doc/{testing_gnb_w_cots_ue_resources => testing_oai_nsa_w_cots_ue_resources}/oai_enb.log (100%) rename doc/{testing_gnb_w_cots_ue_resources => testing_oai_nsa_w_cots_ue_resources}/oai_fr1_setup.vsdx (100%) rename doc/{testing_gnb_w_cots_ue_resources => testing_oai_nsa_w_cots_ue_resources}/oai_gnb.log (100%) diff --git a/doc/README.md b/doc/README.md index 9bd89480af..139418d817 100644 --- a/doc/README.md +++ b/doc/README.md @@ -52,7 +52,7 @@ There is some general information in the [OpenAirInterface Gitlab Wiki](https:// * IF setups and arbitrary frequencies * MIMO - [How to run OAI with O-RAN 7.2 FHI](./ORAN_FHI7.2_Tutorial.md) -- [How to run a 5G-NSA setup](./TESTING_GNB_W_COTS_UE.md) +- [How to run a 5G-NSA setup](./TESTING_OAI_NSA_COTS_UE.md) - [How to run a 4G setup using L1 simulator](./L1SIM.md) _Note: we recommend the RFsimulator_ - [How to use the L2 simulator](./L2NFAPI.md) - [How to use the OAI channel simulator](../openair1/SIMULATION/TOOLS/DOC/channel_simulation.md) diff --git a/doc/TESTING_GNB_W_COTS_UE.md b/doc/TESTING_OAI_NSA_COTS_UE.md similarity index 85% rename from doc/TESTING_GNB_W_COTS_UE.md rename to doc/TESTING_OAI_NSA_COTS_UE.md index f44e140e22..f53e7fe9a1 100644 --- a/doc/TESTING_GNB_W_COTS_UE.md +++ b/doc/TESTING_OAI_NSA_COTS_UE.md @@ -7,12 +7,12 @@ STATUS 2020/10/15 : added External Resources section and links ## External Resources Additional Resources to this page can be found here (special mention to Walter Maguire ) : -https://docs.google.com/document/d/1pL8Szm0ocGxdl5ESVp12Ff71a4PbhCb9SpvbLZzwYbo/edit?usp=sharing +[Additional Notes Supporting the OAI COTS NSA](https://docs.google.com/document/d/1pL8Szm0ocGxdl5ESVp12Ff71a4PbhCb9SpvbLZzwYbo/edit?usp=sharing) At time of writing, the openairinterface5G Commit Tag is 2020.w39 Faraday Cages can be found here : -http://www.saelig.com/MFR00066/ste2300.htm +[Faraday Cage](http://www.saelig.com/MFR00066/ste2300.htm) ## Configuration Overview @@ -37,32 +37,32 @@ Our code might not work with all 5G phones yet, but we are constantly improving * Simcom SIMCOM8200EA * Quectel RM500Q-GL -Note1: In the version we have at Eurecom, you need to set the PLMN to 50501, and you also need to change the firmware to "11.0.0 (RD1A.201105.003.B1, Nov 2020, EU carriers)" (see https://developers.google.com/android/images) +Note1: In the version we have at Eurecom, you need to set the PLMN to 50501, and you also need to change the firmware to "11.0.0 (RD1A.201105.003.B1, Nov 2020, EU carriers)" (see [Factory Images for Nexus and Pixel Devices](https://developers.google.com/android/images)) ## Repository -https://gitlab.eurecom.fr/oai/openairinterface5g/tree/develop +[OAI](https://gitlab.eurecom.fr/oai/openairinterface5g/tree/develop) ## Architecture Setup The scheme below depicts our typical setup: -![image info](./testing_gnb_w_cots_ue_resources/oai_fr1_setup.jpg) +![image info](./images/oai_fr1_setup.jpg) The photo depicts the FR1 setup part of the scheme above: -![image info](./testing_gnb_w_cots_ue_resources/oai_fr1_lab.jpg) +![image info](./images/oai_fr1_lab.jpg) ## Build and Install General guidelines to build eNB and gNB : -See https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/doc/BUILD.md#building-ues-enodeb-and-gnodeb-executables +See [Building UE, eNB and gNb executables](https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/doc/BUILD.md#building-ues-enodeb-and-gnodeb-executables) - **eNB** -``` +```bash cd /openairinterface5g/ source oaienv cd cmake_targets/ @@ -72,7 +72,7 @@ cd cmake_targets/ - **gNB** -``` +```bash cd /openairinterface5g/ source oaienv cd cmake_targets/ @@ -83,8 +83,7 @@ cd cmake_targets/ - **EPC** for reference: -https://github.com/OPENAIRINTERFACE/openair-epc-fed/blob/master/docs/DEPLOY_HOME.md - +[DEPLOY_HOME_MAGMA_MME](https://github.com/OPENAIRINTERFACE/openair-epc-fed/blob/master/docs/DEPLOY_HOME_MAGMA_MME.md) ## Configuration Files @@ -93,15 +92,17 @@ Each component (EPC, eNB, gNB) has its own configuration file. These config files are passed as arguments of the run command line, using the option -O \ The **REFERENCE** files for eNB and gNB, **used by the CI**, can be found here: -[enb conf file](../ci-scripts/conf_files/enb.band7.tm1.fr1.25PRB.usrpb210.conf) -[gnb conf file](../ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf) +* [enb conf file](../ci-scripts/conf_files/enb.band7.25prb.usrpb200.tm1.conf) +* [gnb conf file](../ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf) These files have to be updated manually to set the IP addresses and frequency. - -**ATTENTION** : an **EXTERNAL** clock is used to sync the eNB and gNB, -whether the clock is internal or external is defined in the configuration files (!! details needed !!) - +--- +>**⚠️ ATTENTION ⚠️** +> +>An **EXTERNAL** clock is used to sync the eNB and gNB, whether the clock is internal or external is defined in the configuration files (!! details needed !!) +> +--- 1- In the **eNB configuration file** : - look for MME IP address, and update the **ipv4 field** with the IP address of the **EPC** server @@ -198,14 +199,13 @@ The test takes typically a few seconds, max 10-15 seconds. If it takes more than - **EPC** (on EPC host): for reference: -https://github.com/OPENAIRINTERFACE/openair-epc-fed/blob/master/docs/DEPLOY_HOME.md - +[DEPLOY_HOME_MAGMA_MME](https://github.com/OPENAIRINTERFACE/openair-epc-fed/blob/master/docs/DEPLOY_HOME_MAGMA_MME.md) - **eNB** (on the eNB host): Execute: -``` +```bash ~/openairinterface5g/cmake_targets/ran_build/build$ sudo ./lte-softmodem -O **YOUR_ENB_CONF_FILE** | tee **YOUR_LOG_FILE** ``` @@ -213,13 +213,16 @@ Execute: - **gNB** (on the gNB host) - -**ATTENTION** : for the gNB execution, -The **-E** option is required to enable the tri-quarter sampling rate when using a B2xx serie USRP -The **-E** option is **NOT supported** when using a a N300 USRP +--- +>**⚠️ ATTENTION ⚠️** +> +> For the gNB execution: +> - The **-E** option is required to enable the tri-quarter sampling rate when using a B2xx serie USRP +> - The **-E** option is **NOT supported** when using a a N300 USRP +--- Execute: -``` +```bash ~/openairinterface5g/cmake_targets/ran_build/build$ sudo ./nr-softmodem -O **YOUR_GNB_CONF_FILE** -E --nsa | tee **YOUR_LOG_FILE** ``` @@ -229,9 +232,9 @@ Execute: The test case corresponds to the UE attachement, that is the UE connection and its initial access in 5G, as depicted below: -**Source** : https://www.sharetechnote.com/html/5G/5G_LTE_Interworking.html +**Source** : [5G/LTE interworking](https://www.sharetechnote.com/html/5G/5G_LTE_Interworking.html ) -![image info](./testing_gnb_w_cots_ue_resources/attach_signaling_scheme.jpg) +![image info](./images/attach_signaling_scheme.jpg) The test reaches step **12. E-RAB modifcation confirmation** , eventhough not all the messages will appear in the log file. @@ -239,8 +242,8 @@ The test reaches step **12. E-RAB modifcation confirmation** , eventhough not al From the log file that is generated, we can monitor several important steps, to assess that the test was successful. Log files examples can be found here: -[enb log file](https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/rh_doc_update_3/doc/testing_gnb_w_cots_ue_resources/oai_enb.log) -[gnb log file](https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/rh_doc_update_3/doc/testing_gnb_w_cots_ue_resources/oai_gnb.log) +* [enb log file](./testing_oai_nsa_w_cots_ue_resources/oai_enb.log) +* [gnb log file](./testing_oai_nsa_w_cots_ue_resources/oai_gnb.log) - eNB receives UE capabilities information, including its NR capabilites, and triggers sGNB Addition Request message: diff --git a/doc/testing_gnb_w_cots_ue_resources/attach_signaling_scheme.jpg b/doc/images/attach_signaling_scheme.jpg similarity index 100% rename from doc/testing_gnb_w_cots_ue_resources/attach_signaling_scheme.jpg rename to doc/images/attach_signaling_scheme.jpg diff --git a/doc/testing_gnb_w_cots_ue_resources/oai_fr1_lab.jpg b/doc/images/oai_fr1_lab.jpg similarity index 100% rename from doc/testing_gnb_w_cots_ue_resources/oai_fr1_lab.jpg rename to doc/images/oai_fr1_lab.jpg diff --git a/doc/testing_gnb_w_cots_ue_resources/oai_fr1_setup.jpg b/doc/images/oai_fr1_setup.jpg similarity index 100% rename from doc/testing_gnb_w_cots_ue_resources/oai_fr1_setup.jpg rename to doc/images/oai_fr1_setup.jpg diff --git a/doc/testing_gnb_w_cots_ue_resources/enb.conf b/doc/testing_oai_nsa_w_cots_ue_resources/enb.conf similarity index 100% rename from doc/testing_gnb_w_cots_ue_resources/enb.conf rename to doc/testing_oai_nsa_w_cots_ue_resources/enb.conf diff --git a/doc/testing_gnb_w_cots_ue_resources/gnb.conf b/doc/testing_oai_nsa_w_cots_ue_resources/gnb.conf similarity index 100% rename from doc/testing_gnb_w_cots_ue_resources/gnb.conf rename to doc/testing_oai_nsa_w_cots_ue_resources/gnb.conf diff --git a/doc/testing_gnb_w_cots_ue_resources/oai_enb.log b/doc/testing_oai_nsa_w_cots_ue_resources/oai_enb.log similarity index 100% rename from doc/testing_gnb_w_cots_ue_resources/oai_enb.log rename to doc/testing_oai_nsa_w_cots_ue_resources/oai_enb.log diff --git a/doc/testing_gnb_w_cots_ue_resources/oai_fr1_setup.vsdx b/doc/testing_oai_nsa_w_cots_ue_resources/oai_fr1_setup.vsdx similarity index 100% rename from doc/testing_gnb_w_cots_ue_resources/oai_fr1_setup.vsdx rename to doc/testing_oai_nsa_w_cots_ue_resources/oai_fr1_setup.vsdx diff --git a/doc/testing_gnb_w_cots_ue_resources/oai_gnb.log b/doc/testing_oai_nsa_w_cots_ue_resources/oai_gnb.log similarity index 100% rename from doc/testing_gnb_w_cots_ue_resources/oai_gnb.log rename to doc/testing_oai_nsa_w_cots_ue_resources/oai_gnb.log From acd3634d27667e8f968900a0a33d2fadad55952d Mon Sep 17 00:00:00 2001 From: calvin_peyron Date: Wed, 3 Sep 2025 11:20:21 +0200 Subject: [PATCH 883/964] Update E1-design.md --- doc/E1AP/E1-design.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/doc/E1AP/E1-design.md b/doc/E1AP/E1-design.md index 8fafd09f66..d9a7131393 100644 --- a/doc/E1AP/E1-design.md +++ b/doc/E1AP/E1-design.md @@ -1,6 +1,6 @@ [[_TOC_]] -# 1. Introduction +## 1. Introduction E1 is the interface that lies between the nodes CU Control Plane (CUCP) and CU User Plane (CUUP). Once the nodes are configured, all user plane traffic flows through CUUP. @@ -77,11 +77,11 @@ sequenceDiagram ``` More details about the E1AP procedures in OAI are available in this document: [E1 Procedures](./e1ap_procedures.md). -# 2. Running the E1 Split +## 2. Running the E1 Split The setup is assuming that all modules are running on the same machine. The user can refer to the [F1 design document](./../F1AP/F1-design.md) for local deployment of the DU. -## 2.1 Configuration File +### 2.1 Configuration File The gNB is started based on the node type that is specified in the configuration file. The following parameters must be configured accordingly. @@ -130,9 +130,9 @@ The CUUP uses the IP address specified in `gNBs.[0].local_s_address` for F1-U an Alternatively, you can use the config files `ci-scripts/conf_files/gnb-cucp.sa.f1.conf` and `ci-scripts/conf_files/gnb-cuup.sa.f1.conf`. -## 2.2 Steps to Run the Split in rfsimulator with OAI UE +### 2.2 Steps to Run the Split in rfsimulator with OAI UE -Note: A 5G core must be running at this point. Steps to start the OAI 5G core can be found [in the oai-cn5g-fed repository](https://gitlab.eurecom.fr/oai/cn5g/oai-cn5g-fed/-/blob/master/docs/DEPLOY_HOME.md) or [here](NR_SA_CN5G_gNB_USRP_COTS_UE_Tutorial.md). +Note: A 5G core must be running at this point. Steps to start the OAI 5G core can be found [in the oai-cn5g-fed repository](https://gitlab.eurecom.fr/oai/cn5g/oai-cn5g-fed/-/blob/master/docs/DEPLOY_HOME.md) or [here](../NR_SA_Tutorial_OAI_CN5G.md). 0. Open wireshark to capture the E1AP messages. You might set the capture filter to `sctp` to limit the number of captured packages. @@ -165,7 +165,7 @@ OAI UE: sudo ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --rfsim --rfsimulator.serveraddr 127.0.0.1 ``` -# 3. Configuration file IP addresses of network functions +## 3. Configuration file IP addresses of network functions You can also run the nodes on different machines. If you do so please change the interface parameters accordingly and make sure the interfaces are reachable. Please refer to the following figure for an overview of all parameters. @@ -173,7 +173,7 @@ You can also run the nodes on different machines. If you do so please change the [PDF version](./images/e1-archi.pdf) | [LaTeX/TikZ version](./images/e1-archi.tex) if you want to modify to reflect your setup -# 4. Multiple CU-UP +## 4. Multiple CU-UP It is possible to connect multiple CU-UP to the same CU-CP. In the handler of the E1 Setup Request, the CU-CP verifies that the PLMN(s) (MCC, MNC) between @@ -195,6 +195,6 @@ that you have to restart the CU-CP if you want to connect the CU-UP again (e.g., after a crash). The CU-CP might also misfunction during attach if a CU-UP was connected, but disconnected in the meantime. -# 5. Abnormal conditions +## 5. Abnormal conditions * The CU-UP goes offline during normal operation (e.g. UEs have a valid PDU Session and are exchanging data on the UP): after restarting the CU-UP, the UP is not restored and the user will notice GTP errors. In this case the UEs have to reconnect. From 25918898a74984773aa8b79d941c2e628c8d78f4 Mon Sep 17 00:00:00 2001 From: calvin_peyron Date: Wed, 3 Sep 2025 11:35:32 +0200 Subject: [PATCH 884/964] Update F1-design.md --- doc/F1AP/F1-design.md | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/doc/F1AP/F1-design.md b/doc/F1AP/F1-design.md index 34c48a640c..5290426ea3 100644 --- a/doc/F1AP/F1-design.md +++ b/doc/F1AP/F1-design.md @@ -2,7 +2,7 @@ - + @@ -14,7 +14,7 @@ [[_TOC_]] -# Introduction +## Introduction The F1 interface is the functional split of 3GPP between the CU (centralized unit: PDCP, RRC, SDAP) and the DU (distributed unit: RLC, MAC, PHY). It is @@ -33,17 +33,17 @@ F1-U: No equivalent for 4G exists. -## Control plane (F1-C) +### Control plane (F1-C) The interface F1-C is designed for the exchange of signalling messages between the Radio Network Layer (RNL) and the Transport Network Layer (TNL). It consists of F1 Application Protocol messages (F1-AP) exchanged over SCTP. -## Data plane (F1-U) +### Data plane (F1-U) F1-U uses GTP-U for information exchange. -# OAI Implementation Status +## OAI Implementation Status The implementation of F1AP messages is seamlessly integrated into OAI, supporting both Monolithic SA and CU/DU functional split modes. The F1 code is therefore always compiled with nr-softmodem. @@ -63,13 +63,13 @@ This is the current status: - Not supported: * NSA -## F1-C +### F1-C -### F1AP messages +#### F1AP messages -Refer to [FEATURE_SET.md](FEATURE_SET.md#gNB-F1AP) to learn about the current F1AP implementation status. +Refer to [FEATURE_SET.md](../FEATURE_SET.md#gnb-f1ap) to learn about the current F1AP implementation status. -### High-level F1-C code structure +#### High-level F1-C code structure The F1 interface is used internally between CU (mostly RRC) and DU (mostly MAC) to exchange information. In DL, the CU sends messages as defined by the @@ -170,7 +170,7 @@ sequenceDiagram TASK_MAC_GNB->>+TASK_RRC_GNB: raw F1AP message (ITTI) ``` -## F1-U +### F1-U Current status: @@ -178,7 +178,7 @@ Current status: * Each packet is acknowledged individually * Support of multiple DUs per CU -# How to run +## How to run As mentioned earlier, OAI uses F1 internally. It is always compiled in. To start CU/DU, you use `./nr-softmodem` with the appropriate configuration @@ -190,7 +190,7 @@ sudo cmake_targets/ran_build/build/nr-softmodem -O ci-scripts/conf_files/gnb-du. ``` These files are tested in the CI, and are configured for use in docker, -see [this `docker-compose` file](../ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml). +see [this `docker-compose` file](../../ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml). The rules to decide if a config triggers a start of a DU, CU, or monolithic gNB, are, in order: @@ -200,7 +200,7 @@ gNB, are, in order: (`tr_s_preference`), it is a CU. 3. It is a (monolithic) gNB. -## F1 IP configuration for Local network deployment of F1 +### F1 IP configuration for Local network deployment of F1 The following paragraphs explain the IP configuration for F1 in the OAI config files on the example of a a local deployment. We assume that the CU will bind @@ -242,7 +242,7 @@ the options `MACRLCs.[0].local_n_address` and `MACRLCs.[0].local_n_address_f1u`, respectively. Note that this is not foreseen for the CU; in the case of the CU, please use separate CU-UP and CU-CP. -## Configuration of multiple DUs +### Configuration of multiple DUs Upon F1 Setup Request of a new DU, the CU cross-checks that @@ -260,9 +260,9 @@ You have to of course make sure that the local interface of the DU Assuming you use RFsim, you should make the RFsimulator server side (typically the gNB) bind on different hosts (`rfsimulator.serverport`). -# Code documentation +## Code documentation -## Common multi-threading architecture +### Common multi-threading architecture The CU and DU interfaces are based on ITTI threads (see `common/utils/ocp_itti/itti.md`) adopted by all OAI upper layers to run isolated threads dedicated to one feature. @@ -301,7 +301,7 @@ All GTP-U tunnels are managed in a Linux Thread, that have partially ITTI design 3. incoming packets are sent to the tunnel creator using a C callback (the callback function is given in tunnel creation order). The callback should not block -## F1-C messages towards the CU +### F1-C messages towards the CU The CU thread starts when the CU starts. It opens listening socket on the configuration-specified IP/port by sending the appropriate message to @@ -332,7 +332,7 @@ You might also want to consult TS 38.401 regarding the message exchange. | UE Context Release Request | `F1AP_UE_CONTEXT_RELEASE_REQ` | `rrc_CU_process_ue_context_release_request()` | RRC will trigger UE release | | UE Context Release Complete | `F1AP_UE_CONTEXT_RELEASE_COMPLETE` | `rrc_CU_process_ue_context_release_complete()` | frees UE Context, signals to NGAP | -## F1-C Messages towards the DU +### F1-C Messages towards the DU The task "gNB app", after reading the configuration file, sends a message `F1AP_DU_REGISTER_REQ` to the DU task. This message contains network @@ -371,9 +371,9 @@ You might also want to consult TS 38.401 regarding the message exchange. a reconfiguration has to be triggered if the CU receives a CellGroupConfig, originating at the DU. See also flag `expect_reconfiguration`. -## F1-U messages +### F1-U messages -### General +#### General In the DU in UL, RLC checks in `deliver_sdu()` if we are operating in split mode, and either (direct) calls `pdcp_data_ind` (DRB) or (f1ap) sends a GTP @@ -390,7 +390,7 @@ In the DU in DL, assuming the GTP-U tunnel exists, GTP decapsulates the packet and calls the reception call back `nr_rlc_data_req()`, which enqueues the packet into the UE's RLC buffer. -## Tunnel Setup +### Tunnel Setup In GTP-U, TS 29.281 specifies a optional header (NR RAN Container). This extension header may be transmitted in a G-PDU over the X2-U, Xn-U and F1-U user From 0721c0fad0ca1b99afe9eefb5d3c2dfdcfc7a885 Mon Sep 17 00:00:00 2001 From: calvin_peyron Date: Wed, 3 Sep 2025 11:38:16 +0200 Subject: [PATCH 885/964] Fix image link inside F1AP-lib.md --- doc/F1AP/F1AP-lib.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/F1AP/F1AP-lib.md b/doc/F1AP/F1AP-lib.md index 46712914ed..86db97ec8b 100644 --- a/doc/F1AP/F1AP-lib.md +++ b/doc/F1AP/F1AP-lib.md @@ -2,7 +2,7 @@ - + From aa323b02f28554630c77502486328794b49b8647 Mon Sep 17 00:00:00 2001 From: calvin_peyron Date: Wed, 3 Sep 2025 13:16:25 +0200 Subject: [PATCH 886/964] Fix link in mac-usage.md --- doc/MAC/mac-usage.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/MAC/mac-usage.md b/doc/MAC/mac-usage.md index e412d4b329..f4583b7a23 100644 --- a/doc/MAC/mac-usage.md +++ b/doc/MAC/mac-usage.md @@ -183,7 +183,7 @@ See [nFAPI documentation](../nfapi.md) or [Aerial tutorial](../Aerial_FAPI_Split_Tutorial.md) for information about the (n)FAPI split. -See [F1 documentation](../F1-design.md) for information about the F1 split. +See [F1 documentation](../F1AP/F1-design.md) for information about the F1 split. ## MAC scheduler-related configuration options From 2d2f61f2530b04b85e587a966f8e76c0037ba520 Mon Sep 17 00:00:00 2001 From: calvin_peyron Date: Wed, 3 Sep 2025 13:16:54 +0200 Subject: [PATCH 887/964] Fix link in rrc-usage.md --- doc/RRC/rrc-usage.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/RRC/rrc-usage.md b/doc/RRC/rrc-usage.md index 0eb7bc7195..332c69a0eb 100644 --- a/doc/RRC/rrc-usage.md +++ b/doc/RRC/rrc-usage.md @@ -12,7 +12,7 @@ The RRC layer controls the basic connection setup of UEs as well as additional procedures. It is the fundamental building block of OAI's CU-CP, and interacts with lower layers (DU, basically MAC and RLC) through F1AP messages, and with the CU-UP through E1AP messages. More information can be found in the -respective [F1AP page](../F1-design.md) and [E1AP page](../E1AP/E1-design.md). +respective [F1AP page](../F1AP/F1-design.md) and [E1AP page](../E1AP/E1-design.md). # Periodic output and interpretation @@ -57,7 +57,7 @@ As of now, it does not print information about connected CU-UPs or AMFs. ## Split-related options (when running in a CU or CU-CP) -See [F1 documentation](../F1-design.md) for information about the F1 split. +See [F1 documentation](../F1AP/F1-design.md) for information about the F1 split. See [E1 documentation](../E1AP/E1-design.md) for information about the E1 split. ## RRC-specific configuration options From e7a45a304b3196c8afb60e9ffab8a02013aabb73 Mon Sep 17 00:00:00 2001 From: calvin_peyron Date: Wed, 3 Sep 2025 13:54:20 +0200 Subject: [PATCH 888/964] Remove unused and outdated documentation --- doc/README.md | 2 - doc/SystemX-tutorial-design.md | 143 --------------------------------- 2 files changed, 145 deletions(-) delete mode 100644 doc/SystemX-tutorial-design.md diff --git a/doc/README.md b/doc/README.md index 139418d817..e19c71268b 100644 --- a/doc/README.md +++ b/doc/README.md @@ -71,8 +71,6 @@ There is some general information in the [OpenAirInterface Gitlab Wiki](https:// Legacy unmaintained files: - [`L2NFAPI_NOS1.md`](./L2NFAPI_NOS1.md), [`L2NFAPI_S1.md`](./L2NFAPI_S1.md): old L2simulator, not valid anymore -- [`SystemX-tutorial-design.md`](./SystemX-tutorial-design.md): old, high-level - documentation - [`UL_MIMO.txt`](./UL_MIMO.txt): UL-MIMO specific notes # Designs diff --git a/doc/SystemX-tutorial-design.md b/doc/SystemX-tutorial-design.md deleted file mode 100644 index 1e099abafd..0000000000 --- a/doc/SystemX-tutorial-design.md +++ /dev/null @@ -1,143 +0,0 @@ -# OpenAirInterface for SystemX - -# Terminology - -****This document use the 5G terminology**** - -**Central Unit (CU):** It is a logical node that includes the gNB -functions like Transfer of user data, Mobility control, Radio access -network sharing, Positioning, Session Management etc., except those -functions allocated exclusively to the DU. CU controls the operation of -DUs over front-haul (Fs) interface. A central unit (CU) may also be -known as BBU/REC/RCC/C-RAN/V-RAN/VNF - -**Distributed Unit (DU):** This logical node includes a subset of the -gNB functions, depending on the functional split option. Its operation -is controlled by the CU. Distributed Unit (DU) also known with other -names like RRH/RRU/RE/RU/PNF. - -In OpenAir code, the terminology is often RU and BBU. - -# OpenAirUsage - -## EPC and general environment - -### OAI EPC - -Use the stable OAI EPC, that can run in one machine (VM or standalone) - -Draft description: - - -## Standalone 4G - -EPC+eNB on one machine, the UE can be commercial or OAI UE. - -### USRP B210 - -Main current issue: traffic is good only on coaxial link between UE and -eNB (probably power management issue). - -### Simulated RF - -Running eNB+UE both OAI can be done over a virtual RF link. - -The UE current status is that threads synchronization is implicit in -some cases. As the RF simulator is very quick, a “sleep()” is required -in the UE main loop - -(line 1744, targets/RT/USER/lte-ue.c). - -Running also the UE in the same machine is possible with simulated RF. - -Running in same machine is simpler, offers about infinite speed for -virtual RF samples transmission. - -A specific configuration is required because the EPC Sgi interface has -the same IP tunnel end point as the UE. - -So, we have to create a network namespace for the UE and to route data -in/out of the namespace. - -```bash -ip netns delete aNameSpace 2> /dev/null - -ip link delete v-eth1 2> /dev/null - -ip netns add aNameSpace - -ip link add v-eth1 type veth peer name v-peer1 - -ip link set v-peer1 netns aNameSpace - -ip addr add 10.200.1.1/24 dev v-eth1 - -ip link set v-eth1 up - -iptables -t nat -A POSTROUTING -s 10.200.1.0/255.255.255.0 -o enp0s31f6 \ --j MASQUERADE - -iptables -A FORWARD -i enp0s31f6 -o v-eth1 -j ACCEPT - -iptables -A FORWARD -o enp0s31f6 -i v-eth1 -j ACCEPT - -ip netns exec aNameSpace ip link set dev lo up - -ip netns exec aNameSpace ip addr add 10.200.1.2/24 dev v-peer1 - -ip netns exec aNameSpace ip link set v-peer1 up - -ip netns exec aNameSpace bash -``` - -After the last command, the Linux shell is in the new namespace, ready -to run the UE. - -To make user plan traffic, the traffic generator has to run in the same -namespace - -```bash -ip netns exec aNameSpace bash -``` - -The traffic genenrator has to specify the interface: - -```bash -route add default oaitun_ue1 -``` - -or specify the outgoing route in the traffic generator (like option “-I” -in ping command). - -## 5G and F1 - -Today 5G achievement is limited to physical layer. - -The available modulation is 40MHz, that require one X310 or N300 for the -gNB and a X310 or N300 for the nrUE. - -### Usage with X310 - -Linux configuration: - - -We included most of this configuration included in OAI source code. - -Remain to set the NIC (network interface card) MTU to 9000 (jumbo -frames). - -### Running 5G - -Usage with RFsimulator: - -**gNB** - -```bash -sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf -``` - -**nrUE** - -```bash -sudo ./nr-uesoftmodem --numerology 1 -r 106 -C 3510000000 -d --rfsimulator.serveraddr 127.0.0.1 -``` From 2dd72d40cbf422c7cdb7f4f04f55cb834e81e1c0 Mon Sep 17 00:00:00 2001 From: calvin_peyron Date: Thu, 4 Sep 2025 10:13:44 +0200 Subject: [PATCH 889/964] Put documentation images in right folder --- doc/Doxyfile | 2 +- doc/FEATURE_SET.md | 4 ++-- doc/{ => images}/nr-ue-threads.svg | 0 doc/{ => images}/oai_enb_func_split_arch.png | Bin doc/{ => images}/oai_logo.png | Bin doc/nr-ue-design.md | 2 +- doc/oai_enb_block_diagram.png | Bin 277532 -> 0 bytes 7 files changed, 4 insertions(+), 4 deletions(-) rename doc/{ => images}/nr-ue-threads.svg (100%) rename doc/{ => images}/oai_enb_func_split_arch.png (100%) rename doc/{ => images}/oai_logo.png (100%) delete mode 100644 doc/oai_enb_block_diagram.png diff --git a/doc/Doxyfile b/doc/Doxyfile index e67078a043..e91e63386f 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -51,7 +51,7 @@ PROJECT_BRIEF = "Full experimental OpenSource LTE and NR implementation # pixels and the maximum width should not exceed 200 pixels. Doxygen will copy # the logo to the output directory. -PROJECT_LOGO = @CMAKE_SOURCE_DIR@/doc/oai_logo.png +PROJECT_LOGO = @CMAKE_SOURCE_DIR@/doc/images/oai_logo.png # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path # into which the generated documentation will be written. If a relative path is diff --git a/doc/FEATURE_SET.md b/doc/FEATURE_SET.md index f759ddf145..4429cad56b 100644 --- a/doc/FEATURE_SET.md +++ b/doc/FEATURE_SET.md @@ -11,12 +11,12 @@ - FAPI (IF2) : specified by Small Cell Forum (open-nFAPI implementation) - IF1 : F1 in 3GPP Release 15 -![Functional Split Architecture](./oai_enb_func_split_arch.png) +![Functional Split Architecture](./images/oai_enb_func_split_arch.png) # OpenAirInterface Block Diagram # -![Block Diagram](./oai_enb_block_diagram.png) +![Block Diagram](./images/oai_enb_block_diagram.png) # OpenAirInterface 5G-NR Feature Set # diff --git a/doc/nr-ue-threads.svg b/doc/images/nr-ue-threads.svg similarity index 100% rename from doc/nr-ue-threads.svg rename to doc/images/nr-ue-threads.svg diff --git a/doc/oai_enb_func_split_arch.png b/doc/images/oai_enb_func_split_arch.png similarity index 100% rename from doc/oai_enb_func_split_arch.png rename to doc/images/oai_enb_func_split_arch.png diff --git a/doc/oai_logo.png b/doc/images/oai_logo.png similarity index 100% rename from doc/oai_logo.png rename to doc/images/oai_logo.png diff --git a/doc/nr-ue-design.md b/doc/nr-ue-design.md index 9ca95c1a00..1648e6b7c5 100644 --- a/doc/nr-ue-design.md +++ b/doc/nr-ue-design.md @@ -15,7 +15,7 @@ The UE exits when at any point in operation it gets out of synchronization. When UE uses actors which are threads dedicated to particular activity. Sync Actor handles initial sync. DL Actors handle DLSCH PHY procedures. UL procedures are are run on the UL Actor -![design](nr-ue-threads.svg) +![design](images/nr-ue-threads.svg) ## Initial Synchronization Block ```mermaid diff --git a/doc/oai_enb_block_diagram.png b/doc/oai_enb_block_diagram.png deleted file mode 100644 index 58c8eb9e959fae8616de03cc9f56fcfe2cc0f0e7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 277532 zcmeFYhgVbE7d09$Dqd+KDAGhhK~S1VFHxz|mENT&AiYT^Sdbg-_9wfgq@=2)sVNNRHXa>rt{UZk^+ONVdxFF!Hlw*eQJtMcPRAqK zQ2JcVv`!4OiDb(KDQZf~pc{|Q5Xof7SB;iPK5ib}A`7qm>0B5V#)fBMYJ;7DxqT)kT$guN zWTk*aY>OJ=qeTcyR0n4_>y?s9#r(cfH&A-7G!PMNn=Tu}~BP{gI`_QuJ z&kkNR10MN<;Cq8r3kLi3DF)@2dWnYnIRUL|D#^lfcuceDb>j5m6!iI`?q}k*=j58t ziIsnmPhWzief!hx5(RsMKf`x_1J$#)?P27SWP_4ar4L1u{A?>PjQnDq^gHIcsPgE- zz!u%rUqts*yBZO;E+hZR@#}fZ zhq|9qKaqUrpBK3QQA~z4TzFn(o-ZivK~x~eXS(b&KOR+O6Vv(HO3n3>KA_-~!lr9j zuz1jIJVvIu_B~Y(K*`YXHe_ETQES`dAz$=$H#OG2*VbNc+NynfIH1h5ZWML^qcYhY zWn(zg-caP=A#^wCF4v{@<`=)p=j0vuE7dBw^x>E@wwEh>kAt%27PhP16l&=u&NBJ; zG}6r6-R?S6#*^Xi_|OsFJiPJkLc&?6w|8$weUclMzjK@6w)3UJ%OCz!doRr#en)cf zwk}m&V7Szoq5y3rF{Rqa3^$dj;1SukZb$HT#8b=2-@fvR<4M8S&aagHq?YmbWHj0I zBI-K&<~ir@J5p7}dWDH88D<8kJzyV>g2^+#pveg8SFU;#|G75(Sq_IfNiH}4o9aki zX>rLq>Ey3IU!L?jTacI9>t3~iZ`|78*x=n@OjaKGJki&@{Kt`x2g!-ZiSSAK1xYER z7NuLdX8v*oaq#%#fCMXUMkfXj53l`r>Q_Pfk>t589am*)dV^P5J~^_LHLZFw@|&t|d? zgv5WpXMFmd!GudrUM@lI{F6obVR^#{>SCUl^PM5lKRHa3UxXA%D6q>pWSD$Ccv7Yi zBFFip^U1`Mb~zdaSGh2GM2vB#P{*wfhNzVoch=y@q453au5fWyPs!JYq3q_j+avGB zh~C9YU5_3K$3~(#5RZLSeV#sg+9-X~AWe6sx~Y~~p--9jY0=~D;@PCjk{vSak8&Qb z1ohu7zm?dj{8Fpvc#P!7&X2+$IzPyMNdD;LNZ@$GagKwLqeq=RmtjbI=;DyX&^i9w z{M=<;Wddbvt7a~t9<@i5`)BrVlPQHf52>S@qAN-0Pq0mJPq0a#(skz4DzufsAWxV>LdZe^xFF3x67M(w3-L2mx)>PZ=mDD_cXfH2Zac}GD!Bx?F zT)JMx4@#)DQ_Aqo@;w|KxkImBCofjVxhSn==4<4$6wv4U30NmyNSqURtoLFaYO432C<#;dve&^&op7u2HMDGNCc9b~koEX{Q z#h(|~NiLIJqxN9<_;UBl zl1aYl57U<>1*V;*=5zUT=*#aYi^P{EFeFWeKb8-a ztNO$do)9&jni&_9D3DZ`Xc)!y^V?6Mq@o7wFF|wWczQn1vx<+ZpYtf(wNe>2D_44L zbI_jjImxMNwkoIUot|^~`o#Unr6g>#=A`EIFv@EIZ-9%OsGOiHXPHPZ$8M-jJ*_nL z$m;A?tGQDX@%rT1b8S__Eg#n{%=BZwrer@gPyK_^D}mJ8!EIRGjRFEW)}YB%@^~1N zH;pY5syG=B1;L!KSE*Nv4yYkAjK!(S6r<8{W0h~5+B5Vw(!Ul-HhGEC8uaQVKb zs&%gBOXcjzOqai%R)YF4QyN2u2y^~U{%Ve9o`h=MGb$rKT`QxBr))+QNZS>Qy}oeM z*X`qLS5_5P;Y=z*r`e4eX?ai6i+0Y=NF4;mDm_vng4_F8SjO0JS)MxH-~YN5h0Zy> zx*HRti5o5!DCNwv!8jkT9K%IUM+XW=rh6M#?+6o_7kAelvCn1|m0UMJ?sn)dOVxrK zjdU#E!#u7ocjk0%cO~(B?D>Ja(r9_DY;^;#Ls*KWiRK zj)idB6KrEDF{zlO1{G>Jm8T|7|I~dBIbQ$zLf89PRz@~rqr-YPk=8_y6TL;dy90jQ zE8KU@qh9L13^C{K7Veosl+6t7t?i9;?n>7O6AZC3Yh5__`sp?O3p#N=orszv^A*u} zS2lEF?WW$Ij@RkUh31`S+p_UtSrQHsWM1T_VkJo>kM(nozMN!W^V&xOhoXjt2(ZWZ zKA}YEqz!?0I&Y#ND+MD!|3BAdMS@rUw3pLy0{)5$`Z)tjNCKt@M(q4VNt$@};#tzW z>~_zHP%zjH*b}Ko>TcufQwXogeQ&nI3R1DlBu~Vo)(3CMa}_ICbDgDmlT7wwStl_*q%RWHkP7i-B9pk#&Y3op%>>V#l z#=t=T`RDs*LI%k{Pr&1y56?yZ=czQMBJqDuKi_$~^4~KUwKNaoe@}hCT*xH)@2M(v zqw{~yU_s1rN3HtwU3bOJ4!t{233|C}LFDv8s@bGXx|MPi{I>+Te zsaugxlK-3D$gj5&yI#5w@jWsyFt~L&FuR~2q_B{S(J^LiWhK5>={!F_|5F{E93t~? zi;IgEHZ~yv7u0V2iw?!mU6;nOg1S2Kgv3M^W|QNCji&|%;>)M@H5ZyDNu>hb`>v!UEpFaBU&r*0zZ8C5D>ur=WgEr)EE!$?0|XYj~_q0E(n=8zHMmQP?WM= z9~v21%1g<5#vZ-+-vo94v9$Kbt5>gf>a(8Z@Y)PaPBH{aF()J>d_kckM1BXsAJJjv zlYDe^WMO4RU-sCABRUA&UGCQ9aQO`8XnAQD7Z-IcEm<`+HSmz?IAL}_-p*A?NeP6u z_^!(|T0UcE0}19mGc)t)L;`?Jb+w1;KCWpb9{gTa<=%V1$jJEaC@U@P=IYwoZWvXd zluxogd~k43N=3 z5@z=H_U3!^Y-_-0c|$Vdy*U5)2QCd#e`fNfeSUF2{wHDnaUNUeIZ;8|Ng-?Bva&K4 zIXBT+sn&gvi_uDlxo?m9&F<5JTu8p%0~v(S0|Ekeew53UR0O%h7;U1|Q zZp?G{qUFixRGLGM!F7M%6v;05IyWybJuAz+xAOZ&$=0|9$OR~an`_R_&Qe-hBcH77 zaADEuL4hjO) z8Y3vKB0Dr{6y@zHVV{tvE0&~h&#$FZ2apbMe_rFZt+h47<%?XTBwCu9i_MLkoSg68 zPWvIP9)yI1;J(@D=}ml+{|Rbsb#;|FUQy=7ix<|DmAvJ4=FDToI>D89+B^KFNh&5P?2LSpi!_VidJ7y@ONIz#<5mo)em+NokFH4zZSuBa z3%Q$1Z7y8SsdBdf8fKulO-)VJH8sh{WoPyWMn|s|6cj+AKtpSq&QX6gYJa#gN{~Ws zJO&jlcdV502>S=m@W`L23740&^gl z(jz`HIOzPt2{`1G$Px{Z*MPaN#l?=_h3VHu8F~b==;llr&G+~B(?k6t+b26rJ@1WZ z&bZN9CO5rKnmovvM(~atXpd{T)d3=)7(;<7Y$<0HbF=R~p6VExRII=HFDrb$#*x_r z@i{ax$ivCr-cQJ7F-=fUeM3XhNE7|+Z%6y~8UuQ|x-$8_hT2tC-KpB<~NkTfY~N^x=V ztO6w}T61t$#Hp2)mB0ElHv=}^fJQhvI=VS@uIVK7!7vH3F8s)b0}Btg@~k|tnXGj9 zUStKXY9odl?J&DvpP!RsDM#;!#Hpi6dDW2rfg4zxBhr3AZlFMMslnVRA*QbdIXSe{ zag2FjqA7`f`OOSqo-#vnO8k>3yt-(Wu95lCjiy}#g+2Zv=~4Z ze%_y++pja|&y&bb*E!=1)YSOa%QUWq78VpRzD{m>!NO>oi#5sz zq)Pejm*0qDT2nhqas{C0r>TiKBh3E-i+at=fX9iH=0=yF8QW!fc=YyrEvG9*Dp%II zynMb41xI$wf99BC@#|Nyb!85}MlEsOwl47O06iTYkQ)AHIqIe588@o|yc z-s(C!v_SA7L0w*12?WHLr-clKD(cm%A6g?4G*>j&nF@+s3ymT==HK@mODWB}&Hb66 zBF*D1a%XWoC4cQl*@b`ek`)Ff?-?NLg-3gl3y)Wt&)Lz_)2D+;VrFKF=sCB@!VE4g zGv&$=ouGR7fZ1fOEyQ7?Y(xeq)li;R`@zP93N1OrstZ1B<0)VsMggm!ho4v@<1aW@biQA*LPxL zz!K@@hj>4|1P z_AElWi2Mi%1G!jUU8UQH#1}!XENi3)FyfM^-yk7)zK5TxuAEJBCWOUr<66)0uww0h z4DtN_g-o?5pt)W{+mAuX0=Z)`xiKj|4a3N#^#gVC`d(L8=RN9cS*VnLPR$9TSYsed z!;g%Q0=^S}VKMpcWEyR?sXgwr^O{X70j_lmXmS;O=ja`M^Dj%rVyySO+lrNJlNJhN zo3{DYK4L|#g%y2_1On<1mga=}-+5q;Q|<#!Wp>;O83L36$bTR3YEYp+w*_>Roz@K` z`cYV9huPrJP)MZ@msbM7KX9Sr6B8`qa#EmT0HVG0l*v28%m8$72mC;YFH-;3vu5B; zaNkZkpz5lqprEhr(&$$P2BUoOh=chHa4(}AKY`p6=#&eE5L_SQBYTzr#$WAt+l#zi zp<*LZ|wnI7mp>dsKM!J ziP_`6|0CJONl21AGRDgQN<)$K)^)rXN3k`@3JwmR4550LNap z=O@>Yz!8JN8;2#XrOq7XfFXjvKNPYqWkBTttF<`sK)(ifCx5a65L_Er zFYF$J6fQ3Qu?{qg1p{*Cp(>4adStx665iHs@7TB(@aEMh%enVXCmuUwe^Bv;I}G>s zUIL@Q3vXBE$Z(5C-qjz8yOXUvGYy0PVJsMr&e?(ZPaPNk zcd2e(uT%Z+8(=VBlmBZWAM^~Y&p@N&pMTFk+y#9Eov8*lAc%6Tkx%vX=s^xd{$)lO z>?P0tx&FVeK=aS1!J{ha|M}PdZ+8bWr;F5E66+bl?*)zuBYyGntemc)QCGC^t?942;)S#%>XTUso{n~%)P*%pdjs1i$0wp z+eYWiHjA`9h8gEOpl`Kyc6{Rw;)kYROAjVZW9xN?>Yv>D06dgaQM zBD0PN?P_OBh)$%XTT5;7o{L1<-2)f-aTKr`azx7d9C`wcW)=)<$ny7y>=X754rH{n zv_S2S)_GzB);M!?7_Kb5cLaz?aX{wu8-aY04_|BX#8D*-)fE^EcvtR#`W=ty~c9qG2e&(-^Rh&n1 za&q6;nDDKShEENzmI-nN`=ur@#Twk_zG_%>gX2f1Gt}$j$#*tFtmA6xwlOLP?I}!~ z!7UUOQq^|$GCVZT>ItXES<;E;2IBSE{QGSkkuSl zheq7O;HJp77tsVspD~SkM@xMy+=uzJS%JV`zfOVJEk8UOAXxU6H~rOleje z0UwPo&QOSL^TtlmD8zD!v)G8BEsdXjq?YF{2$W;{P-vvfx8-FlBwkTxFG6Zns(K{- zqQrlSmF6KgY1Wbtjq>l-qi^8a#zqLg)iCMBuiRkf!%hyGp{Zwt0#?iccMg!Que*V% z@zlu2!ADxl=R=noqoz+aG+cBiZpA5Y%aCM*$p|sFSu_7eFt`8=7N-wp zyXf`CxLno%CGVF1FIhTF@NNEJwi9g>j2^t}Da`e=^LM9)z+A7QH| z@!6+G9NWSYCU*I*R-u^929;u#P+b=lNygGgYGru+{V%!FgeC_HqCzSdA2h?5~Z;N=Zq(>v(0%ptNzV3(}i{iCr>gEX59D0V&4@Tu_ho zd&g40LMXu%|Mba|dmsr4udd22rPg02pu8o&4y z3#w_RX~pmOT+qdgB~lt?^p4>1-<{Xzr2Q+-`35xt08cC?pXHCL0qg*@S<9Qfw#4Xx z8Wn@u2otp%zQ+cQHo!DqQHp^gD>jPssP606Tk>CSY5L5>WY;<9h~bgf!=?}wg2PB7 zrWI$A>+bX6+1c4~{Rgz!{+8?jXwtju@cnC*z zF@pxP1YsR|MSuTpY#WX3VQKd{=)S&cU|zO+B`FppSMJtVdYPo{t%F{fA}dw<{dQ)j zb!~=DvsrCcs(5SGm(fwA_@5ksyDz(b5TMUWNu8Fw)hT(o0GGYP&K{`9>V$XtVCt~0 z&H6)LVGa$)9T)8cS4c@onVXx7?e$6mw#q8?21+~}ThCk89~e-N6x}}5s%GYRwNIj0 zJWS}l^1CY9p{f{Rhi(B={W?|SN^#V@;q5v_8}?vQ5OZQyGWPvtsFrNl8$yUG88m%y z`tA4QA88DZoS=K!TvO51l$3xEw+rmN?_TB9eQ>+|fc@__djk(NEjlHv;6Xhqwsiz? zJmcWs?{uY~ul;^_2ScZpjMiV5yy$mjh%a7IY_CClyT-`#4w$?1-ow0Cy!!tZ1D=nd zXj(8+H7v|u76=wW(MI|b2O%UxEA64g{eFGmUA_a$wR30oCr;gM#HNly0m}O?ZYEX0obvi*2X47mf zz$D+J@dUb2oGt3KUYuH?uu6oP`E*_db*011vHxIW;L=}L@SOuzkU3ddcIfu5$rKZu zH`Av0T-qLRUh)vV@f3LPZp)^xMi>R1o=R>X&V{vmZr0JnD`qaA97+9cZf-Dxib=1i z5M*Z7MfFhwAD<@WJ1E6~!0qW*ICYLa83{vGkej+T6#+q?>QAm9io+^aS5ncVgRo$p!b zLax*9Y+xPoGCIT~$6K4-AG5q7kEp6)E61#d5GGGFYZ1%Y zR3r_;8?kW1>lIuDp?a~JscMg0c7>m;+Wd0dVWXN1-mg?Ef=r;dG2w?*L_!R4EEls0Hj79ZT) zf&(-fS5)aOuIeoo^C_#&t|dL!gV1X-gu%DM=g%~dVoTon&owkQzgr9|5cQnvSgL5v zf(x@@j__X&`5Fm=G6aytIV*pR=AjO-NI84*#$DDSn9M6J#kp20Uu&NQ;vYmI7=h1V^7gp zoEDZ;*T;QG8YevEMc&Xs&LAdc!6gQ+Gm0C29I9t>Uz%s`SltlKi9ggZcmGma`%mxs;P2*m@2!Jt=B#|Ztb%@7{ zdyl@fcWD%nbq-_8L;WR`fYgfPf6|g=5RL?mLX+(n0|Kbdl&{6=W2FAzF@?qe4Sv-& ziOB#yNdx_CGKtWIiPZ_0`=A7e#q66)Uu|~mxyqiEsN zo;RTS@T|uBym-VTJEXwk7(hnG-5nQq!1B*-&QCcY zs$lsnC3P>S%45)lI5)$b+4IAA^=<*t_8QttcpC2ffSDN@S_L-^7tA-Q$=8)D3X9M4 zoJ~$WXdOq_vj4_+ZHOpZ=L}h1fDj|xOWC`jsM#uj$Ys>M~eZEl}Sdga!Er>CcfqwNw`;m2b=Uyw*{uG+08UJa$x z4En#s$2Z;rxPKfv7U+e0tF;tsV&M0eJ#uAx`WZD?3dWHBF`5=4S0k1vau~~Zza7Ub z-$C^|ft?O$NA0pO zHbVnzQ92fVy&ez{5azvZ+BY&n4gBZP0}D)+=TTZ%!)Wcko1vir@G z*N07hlo`9bVW4yDd~u*3S~Gn4!VJWidSPLq$fEBH{yxO6z5_WmHKNSSz+o3>-{Gcr zsIvy-x*nesEupI8;`9}SB1{w8W;f}rB%u$3eOxaTEez_+;|f|b^x}Jsa=CHc-NVTX z>sm^!LYhLt(Nc<+Tb8H-M^Om$ln4q-S(1rG+U{KV@`mY^#!>AyXovlK=JkC}n31XK+A3x@=e*Bv4>K#bMfgDWsaB(V5i%bC;r~ zrUrDiTKc8Ew+oQTZl@a+=+FR1#&bN98`E{7%*yyiwk)tjis3S#1AUIit5B#7mf>=@ zn3+wUblpM3!3{aZJoi;v(I4a5md3D&2u=aDxn|Ykd(`g`r*WNjeBb zNUw#vl$20eF0ZWx14vaaf9WGIvcz?NT?UrFu&@x?#%q|7D>TrgPem=Hu04n|gX0rj z(>+I2cEXqr3+$GuGnbOK4^Tpm*>Df^Gz}%Crz^omiWGn54v0U2-^!%#i!{`o0Ik5M z8VgL#zayPr0}BKI3`$A`tE*v^h6kj6{VdF<*iGxe-*q2Aj6ul&{bl`ibUU{F%{%|} zHUDFXPFplmljx0(@J$1+@qnjdQhS^7b~JW;pVu9Y&)Kv}c7oDE&2d*CCBO(G0V{uD`sDqIjc<` zsTd44`MmR4z5T@!_GY1#l3 zsP7lhYXp4Z?miZjftGJ+wjU5ulN+X0&~&YP8Y+WALMd}NDe{Z;uaXD=;YXeD z!(Z=&Joc8eC%XH+KaK#0H&;Gk+vDGF9vjojh!wk5kF~3(cb(k*^;uN}_HhKnNB;o% zlZ)}tzx!x^4SI7}nbpYZEok_kEjCfdwo;_(icC)d@qBM{FHzo1)ksCSsMPKby!lmo zi5{jH3fOes?%>t&G(E2BHOJB}a4NtqF48ZFo`EGfjBrp`8$CH0f5 zjt4@2r2~#}+k6ATP)G1Kf|B!kbDA+s{2&hV`xq9hmH;#Tn2_D@%E{$b2oWYX?(r?IljW|u95}hI=mO)$@j?b52QTVR3%|NBLbVXsWuzRsP*d>itwA9i=pui6cvR;z!ky-r8(G3~cc#o^)`=*=3)kpV->Y;xlcXikMpl08>@%6@OQj+G?^VC? zV1%EgX_jCk`*~@_*+aE*Gt~3?M^TKseUfK~j6fnt_x*5j!)*aJ8aZO$Z6Qi^?m)$t z&qH%+PB7Zr+;l9nElL`7b*GJ_P@bsGKkIt5xM$()bgNc#W3>#ZA;D&bJrA1yW6tm9 z4%pQ`gd8mJ=W^ymJe&)*{R!*tpW<%<%enZ~+CJ2o=iU6{6<{-80+J%C-w)AtZ0?#H zZ4P{R1eUGD)0U?mlCW;?s!txQks(&69ZPd*i!pHq9>$>g1opauoJ9&Ep@H}^zvvka zhqD4-r!X1Ws{t2hbpjO3<|gz=Pi?r$O0|F^0@nzOXgodR?}AE-24wJ=3M92lLISP) z`kG25g>T8D8M3}e@5rl5s4AzWHg2EoU?C6Z<$BLs{(%7j;7|k9;tL3Xkk_d-E!xIe zf>Q-Kq?9B6^|5+8Ms&9NMH%R=WFd~SwwDm6OCrCUUe_wtX>($I-d@ZDIc*q|dm9HC zBKYAueo9K<2yjJS3*x5ZT#4e8zdIkkd>e~buq_#}T42}-rO7!{`U%zay;H2R@c`*PESt<1XOOvL}%&4BRgb3 zNmvW0D-i$6-%+tcfddH#n`kDmuL?FH!P&Uha28qTf0NK~E1V}K4eGfvn*b?GE!I7H z7`>-xR-yw|Io%?=G(N0_dYbf~pl)peqH50PwZ8+4L?`P&LJHMUgj*tyaGv+MSxN^E4%#o@^I| zdEW#5#l8LgmA_{Ax$fB3VD%{Y(Z))3e(TwsDq}kuFdsn+b+-u+DY_n`H$v)a4wf(M zmI>3xX?BmC<5K}UGEzW`ID>OlelkJ#%6kUpp-zDt8495Bj6rNGtms8&OyzF3=-hH& zI2^JMd&Ev8UwE@Y&9!N|P3wlf#}VafC~n#7;MX|qtg zXeP&{4?RLNGBQQ&>Vunp8dd^cA=;eK&~QL&F$KBDYJ^n#tfhywo=#6!z8DJ9M!oXG z9oS-02n=^4giM9ZL5W7^xm^|LMPPUK^O>IY09h#=YxkkR`?`Wc!D#;nq0{ ziTf+<;zRleKQd##?Dw@pKdc!?dn7$#^hPzur(PCb-^EUC?P|dopo!Ubn`3zwTJ`IP zAF$;qqu|OCc<)@(jj1wo#od>-btZY%iO3$jmreJ1*5IHOK1Gq_P$_2Kt*}t(R9Xl_ z^zk2Gt-zA#7rF6@wW!;a(5fD|>N|Ju1_K)c^a-3o`chh|&i1>_z_Sshp-zoAyneER z8tva-jmwK)`ooa2{hcMt`;W>a4$7L=(tCaD0L)C~J!41jy3}6R4$O3Oqv<_eHv)^n zo~Hdm6W?@7QzDJbtDfK4aK|@N-CP%~_p*af!HZn&A4MNiY`0lW%tkA5E6MYC-E-1G zRC6C-uE%)_i0@ka*e1D-Wz3ykjd;A4ViBly@sEX0t%3j?fHRo)*0<6myX{_cWh1+3 z7*2ykVhwI1O;@$rXO~W|=UhDMc(dgVY9ODk%EoU^#o347NF@w6oUpI#bqfn^BWm)*@%X`1cDzmIf zbqv%>Q9dS9%{DUcqsV4)u6FHSHSf7Ll@W(b-9jajLj7wbS2;gw3Di;RRSUE?hY6;Z znSPFYo-RPNl+e_R120fqG+A0q*V8NrsH;)wNmAE*Dsd^((8J(fUJd){0*%&U{iFF9 zjk_|W@4{X-tE~Zp1r>27+X(5H3MLN9f<_G{#0AlN-weKs)W23_`3nm{Ylm`t2PE{o zxWrIxydGlug$5P*{X}FLy-VKaY8EToxX+X5bnRkpY7425<)UdBdVKOU^N{BSH zh&dYVQnn;i3YR^qD~Nx+N8EE$VPxME2g%``dR_)<2*R&)7p311jvvJ57MynH-5~H7 zx-E|3*W6|&tW;=ijR0g0D-h*Ay+y=}OH|(9?4lCe9R*_+LI+YY^!qPM^jr5#auXAg zXSzAT2}&NYA|ko!{j$XcbW_Y-uELg*a3pXlQNmF@`Nhno+)O43FQFfuoi2ZEzYmP> zXxyEJDlz+3f^9ePcmI+MD<=tUm(JWPxFBG*gw$RDTJ*Xy^};1J3<6knP|UIlwsn}P zR^*kO1DFOAS?pTTYA3d>xH{1Uymxf(XUV&_?wzZ)LH&M*5@k7?y)flmfz%tFoh-%H}?IQq7R0gq z+U9%3zccB%#F?i#k6v>+x!+$64#z|#BHJa5RQ8j^r*R&+OV+#mKN;QvYB@SQ`+7Uc zou!cPk|M=WKeP)XwlqgXFfXV_^zHyQ@uy%4WswbSSsyELq5fSr1H+u{L~}rUtv%Q= z_?d}G;191M)lqIAlAoQEI5L zXYKC3de7LRRh%&RlEEji0h$`8E|VXZ(xs)y&CcFu2}@F2XDMT;(=opd`{5 z7+7(J7WIE`BPd$!a^?Nd5<5A)^JZJWl8t%xC=m{~3FEtRvDs^c=6ylo>ADMU0Z>zF zG4s;hL_@l4DUaHVD^Q$(egznjx9UNJho_mbCXLZuYQ-mRSI$p@x-|u}!b|w!2dTYx z``vjIfHtJLUX@%l_IiMOAz|N1YXFhO*b%DPbWOJVZ{vKydf`Htpu}ZLqBCu4b`pIf zySZG9yHy_eM%kS!S~T2sTt@5%zyP!YBd}|l4|3lQEQsvnNGN8+bd#?~Mn~HHo>3Vy z7Su&IRdFkyUM9_fMa5s)WUD|nqw1do!dY5-*_ehpicgjzk$9)LuNnktQ z{L|hw)MeI0#_TvqDwcBpR*4Vy;2wJx41iy_s+XC6pAUgGl)eT`QskR)l=cKOP20Cuzq0t<2%hq(6%Z@qGIH4uv_mpp7Sbv22IKycArc~0%*GNQndarF&dximdf3ADpx2 zCI=G6Q&&&fsUF}jKfE7wyqFiV*o2F$J8`4dEHpAyH7M(SdzYq-%I4jK6QIWHyj$AZ zw-M+&f|nH43!5A;`XSU}wVQbqsmpmZGMGHzZ7n<;yFQ&7f(gT;u-F3+qBlf++0->w24PNxcp_KN#flW}YhSiyj_ zG#}!65QV=x1hBYaP^G(X3V`#7LRQABRj$XVsnaHtx6^JPE-cJVzXWR<+%I+GxO-Xl zz{F_DPK^M?@F&ZWZi&lnrl|q>IDZLwx<2;QxRhs5XtIif!N2PB`1BNu|HjpOxPkTab7M;<<~pg-y$QFTv(6G^ya&UZFYp8tKaKpx_tgIZHo~dhNXO*pCiMXAu{pyLm)m!CH-tnqBX0!rC-xcqV z_25o;<8QuMKfZ;`3X^-en8e4I%IAbKzrVRFj4CWOS9Vs4?XPAuNc1E-T-BI$T-*E8 z+~4*3`Ciel+$hPF;7wH@%u8|XU=R3PUdzI;lgf$ypL0~vJU5?aC9~15U&S~bz2E&o zK6OywvDLB3FQOtj;b8O-yQ6y4cp|O4o4Ay~K%>WO{P>F@fu~~Ht#|;Xp;G8o*@1ic zGkJqzeDkQXxBg`R+!z(>tzo^zuWQdr!8?etG(!`oM@>UEjLpZZZe4L?pSf?ug^JWp z^}l;-@s$F$oJiWNs-Y1Lj%N=djo=sm`Igsm(dzl~Qyn%QAA3YNTqs&#bJ4ddHT0Qk zmZXhZvWQBm{ZXopjHf)da&DEE zS#Jr@O>;WbAeSW!?dY}W=L;srYHfXM3)`x_1aChO`zb1e;qF&H)|}Gwtg}AK+x>YXth5WeN)PYR`J9&Sw#pwAJHGt?x6o@ zW!2k7^UTWXS8m;|U}npLt%LSF^Goun+pOBG+pJ;xmlS2iGud^%XAr@T zz9l5kX=rG$3kk)U{L`}WD5Z6>8%{uru|44!E!6?@aPlStyhL7kY{_k;ZTPI@OyfIp zyKCHV?35<)rQ1Vm>f!i{ zGOGab6|dt^`U>TJ&B)Nc`IP|(f*_9*L%ev$$U=oaw4sl5grM1V-7FR_N#aDM6bYrx zBzq3HYsq!59nbOoZB4?y4Q=x^ByGu=J=?PbGv*$8;9z!d7VU?|xPQL;a^V8Xb^-P6 z*;K<6wN4Wxor%O*H`}X2|!FXqn{goinvR$C+TT zBY|cfbqx*aoBw3~%uSo=jL-#CL+{6`646@87g|#)dW@4sU%~WGw~xQQp+04KQNYI5 zJ^{P{m5YAgiweLK)#G&UKlt<0)xO%q7w`f=5~|(Ir|3_0AMCl25C2)guQjlEh$+eF zwB9g{`Rc+==rC&5!_>YL6o=Iti5*GR{n}cX*1>*297myqw#u0R6KxUug8E(UAii!p za8N#D^G#4aCH1%v5g+1Wh7?u4GH-ieht#{A{jwHAYx>#~!WOJRy4_hW!Yjo1-CH5e zzm7Egj_i+C5YE2-Vb7XhjtI+zK^^RX{zDFc+u-WvtAl^CcE@=-l?<>c$_;MinL=fS zt4iGe6^XX8uf|Vyi7emguM6Y)!=LV-vjF*;7H*aD`dkHh8!Z>d96^xE>-)lh7W$WR1?bxa1+B7=(ZcN4U{tU@5?yYS| z-E|-|Qx?}KAEK`lye4Yv>+nGc@EsHjx40CKn|WhJ0N~ajKI^A6n}ze9c!=u}p2ywQ zf~$VL+=3wDmy&2QoAktSTNP0EK$&n9s#a?fusIj($FU7YsOC%0H|`mJx2;f!xJW{B z`w6+fWP~&R(BVlxM&;tX*z4sWoZ>)~*~(UXq}b8dXP8=NTT?laiMChA0OV@;_fi{2Zh1RaHT@qx__G^(ed%B9Ds)YS z=uwUP1V@lU9J;#Vfn*pKtCbO+X)cGUL?$9EQB z132$BtGK{F2_3Xo82LH1JNKgg!644wMoe0~z}lQa)D%L%5(l?bpZ4;tN-EJQZ2An5J3>xo!XUe#R#f(G0H+MNEA~J;O(Ys^+{oOmoorFi`bh(yq2h z9AEiipeeB6OVlY`Jov>Fi~JBz5W3*k`o)Ho zjg8Oe=*@LJys6gg803|Hq${g{zzg8-o}QkBstMeF`ISxT&!5Q-P~0ug)1cP@-5clE zaBY8CaN#IuGEwDo3%jNi(qOoTjov}K2eZE^;t1=VJC-yF54}98#f&776veix`^b_H zWsQdZsb}3!TpQo*0$&v44;?S$y`lbv0w&%X^m08cz!+G&(9spJ{GYgWL(qY+_s-nj zq$4QZ2;FlX)PCK8zzj@gio?Ug8@(y1D5xjPck2tb65IwrMd?AGO8x2~QTV4%pI$>} zYnnMcZOiX=t7-3zYwJ7Yy_hpLFrbSqQN9+8XA?K!wft3tB~_fg)DI7Rr@(AtLEh5h zDwX~A2StUHAmrP{cR2^1gl)L}qD3>Ei}YEdetH-WpTehVWvbL7l?gpWc5uoXR`Iv_ zj;T=f-4FN5K(76NUAf%6#A7~Ly1T?b;lAn__kwOk-7h;O92 zcp|sIrT4gkBgE`~z#bqDYS=czRnVm!H3hkCeWMutYI=IQf5?~~I?LEMOY5ua6=sQu zmwF3P1p~AeRSO1Te^rURs3XX=wt#66S3tVpJNb6$HWeYg3 zexGDX=hVBLyzA^_+Y)Zo>FNA(_rT3v_jIy0l*$HH!N#kwiH|HnN_C;P@W>Tl_m`Y0 z;O~pd%MJyIYf)9o^35>=7>nEZnq)3r>U>u-Nb<(* z23U+w6y?)FMkce-J%t$!@Tt_RT2CaJ-ggUHJNSd78sd&-<23Q33OMB9@+RLGmr>GF zc4BBhq|vvfUk|pYO?SZ{6f<1H_vXEHX7Ssy;KSrOqwyD~3!Bs_0Uh7|MOJ8NsPNlA zA(^U7&o2#t5?t(weW9!zRjig%E#$ItTlc@V{1ICmxcBYwuDl)^|2Z1nbT_52F>(&4 z{k=9s{NRi_j3up@oh%Zn1^Z1{YY@b~chJ}9I=25wkNw5Vj#FU>)sC^rP)df0Kj`EMet zCAr%(gdP%!VeFF`SS*#>lKu8uBi=_je!tsBi-P63eqDnE#4Hh%WrXGZeo}WbyluHY zJbV$WN+nT=Mb$eWH6qk9Vmjocbf|?~;^M zR5+lvZa32j6Bk(;_s+mSmgks|2hM91_nTiZ5?FwJ{a4<4DNr6ov%it&!= zDfw1@;KW0N?CLmmw&$0O1WFND(4dZ0CiddU59@yMAk#E@9oSk}S!q4W4ZaPwJ?3s? zifn&mVEiuYzUJ&Zu%D=-@fso->y|roWt2*cEZ=EE?Iujl(y|zU6$6X!=+o~}ADl*g zifvB1*09@c5H?Gx?+`72W>5BA(uCdq@GPGqp$4!$4Sn_~m9?x))e>s|)3+Dmb9@PR z8_aZM!(HVBRN$DJA2V$07neChGNo?(c*3l#z5h?A&tM@AcAyw{s_}tN!a zU~zk_((q~GQy1gNl~xi(f!FDDprdHb{q15rALg)V=5*4|`S1BN|BH=*ll4E|6Eza8 z_t%WTjp|kzGeQSA6kv9qFh@h)3ZnsD6|LenJj#>cwR859B3@yP57xZ`sx9w_U3f&Y zpVz{^n|*vvrq52Ml1fsOBf1}Ve$p@E<)oDdLUrklAnJ5~m`zkPlkTbmuW&!+Tu2oh zdKRGCXgLov1|a((=;laGG5~6O;u-Tn6*` zpq7s_edo`f{OGD8B!HUUVQ4cwUf3`mwTrji>-jggyh4bB$}1M!JcnVEvSW%NZJw?e zYHf@^e9RY*0vs(<+FkllL#s8`iejD%9o!}%B_(zKuN;6GAcl*QA35DdnAN?LfK%|5 zm+kr$H_imPEnM?ho17W$18E0n#``%Aw+1aCq{=n+jzloU^S72_K$_Gek& z8mU`67YdcC`ROt6<3}O`2=}#JnuVIg@g-fZ9$uAga&)7FTksmr$Ymx9%y-m7a1&mv z&WWT9P52Ve5HfP_xVuC{!<2%QR90#v zPyU-Ltw}8l-BSaQ=LJOCZPK6KN&wAPj~*#2WNmJzcT{kjkY;OoDsuL7+cFbfjp_Qm z6rW!-p5W3HiZjUDrWDPR(98oQH>J*|~-J_K0Ff zz{_3FSbY3g4WNb#r#ks;{@~7b5=AHKJjuQW@k)f5-$RUzK9KKmz0-==+D;Z{6DycT z`kFrO;=b|Z3gl{cl~M<-g0NSqyc{u&y8Z{l?7Jz-@La(g_c>FPDs*e&FYTGP&FQe) zR?NBCHF2NssR|MI2J$1*CNb7W3(H%VK_u`^C!e!Z(nB zfJEUQOwppv>Jy<@Dh(ZrP*FxsokUM&BCoc}N_LP@6~-cT9soCkV`D#2W0A1PFo^wf zry~U7JFl{@>AE;)6JI!G?5$GMaZ-LOxPJW#M-mC8e$7C6O$MkmtXr?)MY{cZRadBl z7wA?D`;89zY96%;32;P%f$t^i*u0Ui)#XfmCN;t$|HCz~txZ%x^GE7C#;Ba1OAW=y z%?6wF$AOPQ<}IJ)JF5>S3JoLHu&`+9?^o0|8l*8CaRG}4W+o=Ncvp}M6%|w*M}5Nd zJC*)bEITlCU}!q`6XST)hRKBiICqaelc+%&!CAr8-jo#tu!E>4ll*Ma#y~S_MJ;wC z9^-4T5b;$eXqlyA%*o`_J+Obe7clSTt@L*7_Zil>CwD8gRRdS@m| zyzIi#@u+^bnzbKkJmuwdQPq3)rm(Yrbc5Q5Ipw)q}Kl52jx2SOgeI)YjqbN*(U%GwS$u6_(T7dtTd?SgnSfg! zKbZeDyfT>4=!7TBL^o zzqAH^De&4lQ8sEX`+V#3yhA)-x@gNQnO}J7-@Gmz`^UKjyQ)(d1MWwnGyA=YMRwDV z5|8w<>=G<2f_8^@zg8b|S;F-<$V5d0=M01qOdV*;I1(>@O!V_MVLULi>dTH!Fff zg^7)wJ&^%;>G+Z>P6hDe&*G@9vY#|(r6dqEQ1u6GD9!<(#AfdO4`#~!T&jM6)y*$!o9~{!|WLu85Mhb z&e$7pgl7DKaBvGU==qxb^!Pa@LE{D$X@_qUfy7lmT|4sU) z<6yHCxXTl;$$M${o$L9jr>7`&#I*)>-~>sY7s?7LUvc%hrU7a_`F;h0^2AQ#Dz0PhNfSEc%{&O90kjv%Kibxvnec~>6aN!=#b)5zb=wr(*=Z5yul;~ zg8Nn)Zb|cH$&p+2SUGAcea zz}~WwDYEicHClK?WE-Eqm_^4tsI*IvTbo(B6A@Lb!3?CdHvo?#h{)`KX;{VmkpVqP z1dnZ&gA^zp-kme=*$2ZHYj0Ag+zfa7;i&;;;%xD_IYb_O&<}iE2yY*-A(gi(HmKeI z3NfnbCoy0vV`@F_mL96i(2l@YUgYoJKb&84a8&|H(vn{G`}$6xnDAz$|4B=Fx~-0` zb}xlyL2j-e2|nWM?>D{6&I<94nNuhvr7y<5_@~ol0h23MT=dxHVoRofcz8;NSga8A z%k?ii_t`eG($NK7y~431LhAj+xFp-yu(Vw+0y|Owo|DlH;K#JDaW*ytm=4#1 z>qjtPh5W1|2B~W(UjR=n7Fc_oXCw^CC8u~z;IMP@AC9@{B;n%TQmP~oPE>gq=FKSpkb3nY-bUHXIR zyaeHQJGquWQu6>;j0C;FIPgICozPu|34#VA_NtM2`tLA31F4SyNxy>p7afED0^|zZ za2!1Q`|V}Br*(`h=ewt7HlZ;&ZrE@;^)Y`1ULY$MdQVm^Rt5|dEO!CRx3q)ngmzOZ z*?$blg_Z-v-g_F0tM70=5T;QO5%HApQ)sW5Df_dj?ULie2~Ev}jLb=H!ozsty1NC=e@}4} zrs0Bgj=hA(8pc7+LBdPic791IjMbWUX&V@n1D635=jDaNe3#$ovn_$c5?R6<;D%~E zQ4|x}!1Jaq(^pX;AA$qHtCD8sPl$beKn%7V>B^^PP&ht5KHnhhdi1}&4>;UGNJKYD z8Ym=8tj5QCLCuc?%S1S)6h3Y($|y!Zl7;~V8(bs1>+UM(T{jiYI%w{0V0OsMtp&LLS{WMfCGdmxE{9s{j^-Tjb9 zpHU?^R09BY07@ZUPinlGR+HF@dBA#HS^qWiQ;)8WQC0dn>-B?;8nEBfZTc)GQoM3p zKZSGqXw8U9aQ^`pS#Geedw;2i=e}W$MxrCHnRX`bv^4LhLlfSi(z1^>_eriAbz=)P zx-g<%8XU?YCCdLnLAu)gb9rpoQRa2WgAsDn*H0aWH6RvXPrUc*Nik#7U6^ z6{Ds&Dc?UzfKUgt-7o+kt-VCA;OQbp3v3QO+!klBNeFu`XKi2`53qLJPNFmB1EoI3 zr$!s-xnOnizq2AFA+)LU((bKBLPA2HW(jI;6!b)Wcp?4g8L0gjDmb1!F>j-al(;x` zQP4cnk*R)}%aRt)ZglhzSW(}*hD>P+v0s~eRUzXvWtF|nFd>T9SX&a$+issfi?!L6 zKWLd)OhLmdK&yusOX7Cnx!YaD#Jc4jMR8_|Y;0RgtZ~t%a~}&A4H}h#B8U0@2od0; zu&TqrK*E5Izdr}7ur!NJAI#D$2>cVDFsDIqRcf?l@xNXGkm?oo+-q|H!4Css7SMqzeMQ8_ z%4Vw9XQB3!ha4GvjBZUUa~;}11|T7_z77_^;DjG$5s}vU1Hexw^0G*=l=XoH=VE6E z*dsw58~*jO0P>2ud9U4H=A{2%YHi5E#TB)q;DGpKg7Ki49PMJ#G0-eVyFhI>5Or}pu%c3zOnC#nhSBl3Hv3%yq zfV(E0kQ46xH_)6XZ|Siy!GPT7AxBAV@%zTLs$jjY`CJBktFynIT6X+E05wB#i;`a% zoPG%My84?p++5f*=D_s`a$DIcK;Ty*R#d`r>`5KgX_}Tp1%iaN`Y{##w_YUSLcR5` zxoTWv=k)xcK|&^3Bf#*~K#RVBkIy0IpQf^>y~UyfqI#yuq8>ZjTAEf`%(+*93j@X- zXak8$goO*dT+gAFKi2P2Enfa&-=5kvTA0i9!@*&Bc=y5e^MI2J^s0)N1p3}t&nM6H zUx}Ge`3)Vp!tAj?wWYO+ei?NqU{M+ zk@iZL#y}LEFT~l?>LOa~V=M==%Kh6u)(|^Gfn`zgq2fh5(kFIYi7C$FjfR*3Vgz6PaHQgR;IdcTQ zSkMMFhM!Z>Ac3cPEw?BGHdBHRAohVwj{C7x$dt0;2w-g@B4Vr;WRBx&Ma&I`TTNnfIJWZvd5iKCctM^8MG?`Uiy+O0tCC4 zhIy1JHDSLA=wcH@zhZ#x9*nm>M^z&S7%hyG9&ApHR1 zEzWejw76K7k1q`9lD1mE;=j{HZZq}LDXDKWpMg1P&6hbTyrO1nf6>`s?dQaN*2k9Y z`Dvx1O(am(e)_!Z{L}8D?y$${xR96$Q(}xG#XAnbqF*#Wid2T9!X^m|+(n=8G9FlR zc<+RRWrqd`8h<}dEdap9@7G)acido`B#=lAKp%LC15puX=+UC@f&$Q^xK$Rm(u3AF zYxHmYE9PL&0W06pNefg+o7AVb;26)Q!-el2!;@lcP6-UYek*O+#}Zt28_DhM`9vL$ zB`<*l0=X)aLsV?_PZEnK;dyKvYbjon`ee82WyCh|=l|5N$*?h%2|MVt(q_3=xyo-; zw=}Y~Jo``9&6k$n^C@3b@{ahoH2y|~Nh8a&I-WsM*}RXYZdPE3+@BI^)tPk24!n@a zyHoIoK>>>h^TrrF{4jBPCZ-<$+oqse!m3UPUaq2vfhQ_je6rEDQ54%LGh_?i!}*U0 ze!E}?D*39EQddBw9{8>G%3l_*z14*{j@NNOW<+7Z;cTwzUj+tUnX+F01qB#U5C`({ z0F2>h3+GONs;|-u65w4U%=h*OrUcR_3CTFRe`e;5aGqWgbRKUC8Lr zu}=OAVf}tP#}Ms4@mleSwYB$A zu1MAph})VqsqY;lkDj`}Gbb*`$#vSCJh+QjVLS;v-Xy-9r1dZ{%az)tITQgTuZq4Ti#R7NLUz zXYMjYGRl9^&Db(N@clj+244U(nuw=!k0Hotf zZDx3bSn!U#leWxn)Y190iZR%H-|*7zE0QpDj475zhFMG<@9#{&$sg~|B2b|+D%70v zYk^J~phLQWRtBud*J9*|9S@ZvI%}}FyA<^KOOh&$KAFLbzv%jj45@&_9r1@fs=OZnOn`3 z`=iTwC=L3sbvx)?MPk>cIBvvYqmwnzMwcy$PBtzuNr2iX!ENtHcc8_v>rq=BW<(-# zJI*l`_n!vJlZ-I@BxWxf>i8D}ZLbhKX5g zlsL}X)v5_?!7O#*5kJCEIHfdm zy9c&b9W<`hj&Hyu_)ITgTFcqkm~UN8M>xK~DqP5>=k>1ewnVbQRf+m&o8G&xO>_RO zJPibXq~%ktD1T&FK3g;=CHt%6=0^B`^TKlS%(e%#3?PJ^dTk~-9w?>>)m(Q0RHRdH zAMec~=tOmSiEDYWUwalG^o}B)u)ND}S7~Is;Y{W%pXn!$GjhKpwWQ`wbsY;J^L+-8 zoXCJxdObMQoJK`KE|Ee0t+}+po1*1~HkHMMMFxe8^N#0RT#7mxtM>mpdwN9U1RcuM zVmV0Bg5U(<4|;M&gM?s~K^^Jw1Tcs|PVvRkd zUxZV^Z=$Ww_7*MToA$R7cx{i=_3;SDn}6ORDM%7sP7?N8&m8jA$agVm#`uVJ_rxYH zj`Vp=g@zlD3V5aR`!_&`r&b5d<$5itN;SH|4`HkPSREOZr!5_VHN*@0C6r_2Yz)d2 z+;47E;^QO&6&CA)V-64M4gLua^;02Z9yD*tzG)T6^oX@R!rC}DC4$C6tF$WTaSXxs z80Ku9s?7PXP-RyR^^|u;(|Xvn7U?*b{54#ZRS~3p{2xn`2io@{MsZeG84o%H&o(f4 z+O@Iie2g3{vVd^L@*__Is8;}0b4bmCWtXT#Hp)E=0a*hWC_Cr5pVks{>ljh5?qx(w zdbFC$X{BLJ=Y}=h1+b5mfQaNf&NP{;tr+ApY|GF8^bXqUppV6=BN^a8)SRwiAb^K; z6sI{QuX;jH>}YcxJ+J5Kef+T-pc-)(j#>X~RRU_3#Gsd3pNLO6)zZX&8ay*%SoU2) zY~5;S)t-u>Dd=15L8Zr?fJPmxQVw#k?&y{puh25Cg62=1vxyoS6Lz{cM~73`9tyk1 zjJ#N(^$Lw5*Y3DA`bvsB%^RD67y{PaH>{UuUahf7JDeqYZQfRSNM8M6@hhqA##9+v zKwL-_xa`tT7d=DqxxAW}DTRJ#K_u=v?@!R%J@{9=ZknXp6`a+^uMNZrtXgk}b zT_3$=0&xYrE!HahpKs*4P)TeYhR0>#qg2nvN}RG1D!YyfPDt>E2Ij>&V7X2jivz zhjq&R&M|QMhsj}_tkcC8n!ROCJHxfJg#2N*gSg+(^XD0zo8wJtYE3q`z_|~TOB-(- z=JVX!b;n8=j{Ru_Kj-^Njpa&_5k7q6>sR*->n!{aV>=dshn<^B{E_&XUxgPD;Jcaq z&EwbDDe^54u)Dom$aj6W@Dtr;H}2VW#A!Wy?HUOKJk{tQby!K8=ElCb#(9&!$y>ws zMY86>{iJ4PqqUEM)=Rft%ySh7{Z4+|FVw8h0Z}>gX;I5zdbg~>Sh4+3$>0r~WEz*S zP%ob7p-|Bv%{DxczNEU@;q~iO*=J!kuU|KRwIAR3d#p)ng0hzW%WW(OUbs(v)>PGt z`EoQz&e)H!&e;>6VFHkSjyA~6sQ*06*FL9J?khsT$9G`qIcLJm;PXBx=*aAjn2D}# za;M=*Rb={hvSa#u@QrJHiGIb+(i{7#c3NMO0Ha@djhEH3)_(E|Aoh2GXaXoN<9wi- zWPf6%0ta^jWtuUY!hx0f(4Rjug{&+}sEd?p+7l6*?7y#j_Uku$7Uq;-6LH|gsB-cN zTfO+{yl0mp)4h8;*C)$ts>5*n7x|9Xy>`>qw*^SY=);y%k(5O%gck@$EHe(sSvw#E z4!Yyvj=Tl*^TD4mBf{(l=0|bdgfw@HLq4WZxP6a(uU%HM+q6>86b;Y4;(+N8^LtkK zxW~IEBW!E&5ZPB=&Oh7mH%{tH#E1JcYv!H8W~E!1ALmwtjS=5I-7}Y6n-?IhX+bNsZjsqfyO(!<~KcLG|pK2pZ-uAFmwcIi_J0!8{=md0k^uBgnS#K+SA z=Ic5~E9w*fc}-iZiT~LMrPqb2d`E|{m@ZJwOy|~v0hhcHN+{BJh+v}>3!4r)SRR$> zdqkUiII2e4>h|fU_p49alFL9&0o8&mR!?ul`*?VW-do<7ByS@I&Q%eN1SA_+R>v3W zBOeU9E1^R((+P^a``HeLPsREd+;fdRP>JW9(S)p8ivHxLt_?p|yCq3=!#8-k%D>uf zBMqT{kF>#(Fv)8(g%@*DC{C%44ttOGx`uJXjiD_0W;>Uf2Yahn`PJS>UUC5MFB(cU z+64OX-c;&=e6#G^peFKAj&JpZp~x6h6yWQK?XFB0HU!O|Hp5KEit?Gv3hPr&0hM{C zpY(#>UCHfnZh2{tQm+~h#Zt=8;21mnId!iOCEYagTnE~inofSt5FndOHullqD8SZF zk~Hc*^94Y|*Kw`Y6FGdB@%Bi1{eeq3oB7a=Dl%7`-Rr$$D$jG86^E%=AsS}>bKC0& z^`#2|e)xp-pUeUv4TlK2_F7Y`_N}!=SvgzVKk^7czGQA;;lV)j?=!ltn%hny`PX_P z&hX^zff#X(;4#*xNN%n%^bErezA0Ullgkq~5{*aQtV<^m(B!FpFk8I*IO?GRSMU5s z>8fjP+nF^ubDtO+*--OY1KDo}fAV*d!S)-+(gr%j-&UUc=Ie{s%%3svd z{Qg`n{tepce5_CAn0dFNCW=M@_vV$s&9V_NuP5K$f&od;K}){Uyavfe6*vl#k7^wA z$NTtfQ;y;#6tqkAxA|MfzJ#_5ry7G<1O>K=>c)1P4KJ1ALdOM9JIpjvB90mWO7u0( zwaF{r@$1HGlVmCg3ChQ-uC>dR&s!bB7b@ru{3dQEO@>)w9RO`Hm;1Jk{zTh|zYS{S zNwc|cLjB-DaS>E`Jm|qGErA1%qif+s><&{T!fP|9wUM?{9=lF9Ip3{o0&iy{L*(YY z2*q96SITHtpKY?&1xr3}z`boaDZfbTsmk>`a znvgb4f17j3C#iKl^t5(b*AtD*>F+8kJ>bZ2gK%9Ih-)%*^!5?T52_jxN3k6nSVea~ ziw+224dUnqX9Dr5PqQ_XZ4EKRiN##X@NmyrofVd;4lz7FzGaG*4rZNB(A{{`406RB zNKRtAW1S7?-Xhgf0!s#4B*#6zr%$7<=E09UT=a#V@>R)N8-JTT_i}(c`oB6n@Sp;- zT^w&FBzSdA9(Y9KPWZ-|Rd4D;0Zphf)s)SZ*SP`;_l3085H695{j81Eub}hO?z!`U zI%(+Pzl}zrzr}L*K^{8aEa3`%cAu&}v}SZ8TFdMJ(F#YMAJSu|)9sgDU1#LUzuf~Q z^8;7b_S`U&oe>RHYlT=1U=uD|EEz_oNt_#1qzsLg{+7A6B{Z>_eva(e z1pU)fI_t39y>rG-IM-R;-8M=c&UJ^)|MMY8ANKXV!PNXE%S|3UjxhloVc~)5)P7h-UWp4qB2o-AM zwK{lpbH-g#VBx7zH7JPx9G03~JR-ccQqMX9C;jWT{@Y3b)A_y=z?80~GCj}@d7eI1 zX5%Tg`SRnLzg8|*ogE(LX9X<{H;=DSS=VxCPX=DIpb}J%v|?cMT^9rmP4P7Y=YJYL z7`&)8^dDF#09gjMYDI|^YgRJs8Pqz*5nVW?LFZQpe2`rH#8~wK? z`^=!mbG1rX#DHV0aF+Dx-f;=EJEEysbb*qKPIaRkH+&&!YMOU}PIglgumEM}{`#!p zX&$Oh%EGJruxyLsU6{JCa41*qdDNyBKGo)vBQyDK!0cN^Uifa)H}H)*1VLEig*39W|PHsF8%vOXz33vme`UY(krMp zb_*P1*iAN(MWkR{8`v>Q9Cr_bG1DKVUj=d2qGyoj?boCMUYIW^iO1aWYVBJY#o6zV zA_w7eTMS_Bod71nztgkzuB;d36gFZ}0EzPj+rI%E6+8WF=^y6?ki7kT+~3-wn-}yt z@U%_0ww_M6Mjv)z4F{Cy474+sK2&K{C2>jY{aJR7L#2mh znG_5FRCIWIP>2Mt-PO7$xBeow&~DCpn}zXWFE;kt(@gQp{-FrKQNf(T8T!cFlR!U< zj=siFglz2MMlv-iRbJh$ipL-zhh%xIph%nS<3&>k)}1YsNrtF2F+#%VF{Lv4dKTEvWA6-Gkw#+SNd_rE)SQclM^&OE48vj+F_CaJ zCEm-pCBhP?cTV0l-r2*Q$t5l(iOfI9UOI8(zyMQs?AC?Ei^;@qUcDp0sSuCaZck~t zr$f5T%H}q}eZO<09_(FEh}Rs$)~7gnQx`Ahooxq*wttFw=(cT{2#0cBc98{;)#>A{ zZ9M1$*kcTMfdD1o>@#_24X7QAfsp!cd4B|Jk~b@$LD;UWnPS^5zRV9?Bom^ZVKK2n zZp>{lQ4jQHviX?ag;cq$SLP9r-z>V8#WF6ej)naTWgIYFe{#zqXyBxKcs!ln9_bPd zH&GVA`Nq{c-nz8cQy!q+2yZVZ>x201yf~M>fcgF@@^{0)HUW*_ir|FKdcy*XMT#?? zs>l>i@6hP)L(dE|@DJtp!p2_URr zh~uo;nl}CN@*f#CzQ_Y>_`B-EreBvpvmH4X$;O}S+e7;DN4K4(PS~eUNpX-_)$oB|T~6{-0|NMisY}1Bf^v(E(x@(ItN)c?dm(o}=dakt ze6<6f_R4Oy%`mTurzj~a*J4ziq#AeWQUEixNo>-;J=p_i3r2>9&I>4m=1f3+M5|6|Ls5SS9IL=%594|HOQY0E3SP|boqx1-{qf3Ij6N;tk~Olf z4@G{UNclyGYOg&kC89#R_B#7g!5N(djrQDCYRW5hJs%js1GB$PA=yFlpqX-qUb`Av zL#wW~K8J@B1hULb+h)iR8R!gy&9u98h#>c=0(HARfZ&msHKI;#H7=ZDEEmuBCCkA>;&9A|9+XX_G0$ zEXDdO$i%t zR)jnq$GBNx;l$G$9Li25+OuD|3kvG#D~T&ys{Xu!B4%}q-9GYi$B>}jW9bQ3Etx7*w(^~T>}sbS6>ugvw`T}=G#_M*Cz0r#Nh69r zhc~ZapX_R<7-5DV#lSTca2h7KWDemCCAZ5p75zPk$e(2TEpts3qDkNu&7SocI`9vo z->PE=itynV!xG}*agsump=~kuRq;aleY5ZT(C#s;#BiSOn8cW#U0~$K1^fqbX(=qu zwa#jNCnA4#oLm>Zc#T8(ji4sy3hh2^7|(~^(XgT?n!7*GuCIz!?=wpb1gFI3)`>K| zFz7B$NK(UvXQYQv)|ZdS8L86a!m~m%qX-AN`EQVpT?}mtzb3AQv3n9tUxV&?_)T4b z=#ZZW%_zNScQ=WUsE}P1K*XtK{7@J6%(PZ{kBWr-QZvcjr`-0uFW{2QP2!?d-?w#U zD27-=o`>nc`wFV3s6Dm$N;mk_P!?6!O(qQ>H%K>&RkFVQ-^}nktTUYMJdf^L$d)0! z4;p%p3^xc{(XFjsJA(qZitk19xyYsP+IuPn;f|)?=EwJ}63Pp7*Lk4Nm(|;7M3d4r zH+ub|%iFEQ_}dz>Zrf>nnynagk?qT+Se2$&j=m1oBr z5dn>@;W?r-wQn>jsng!vgQ&keNqVs*17<{%bUiUdsB%w=nq@PTsc^sXsNS|_dW%KN z0utclI77V2u7&d};JD82f4udW8feY_ zL1!c6kNARVaNLxV_wSprw>oZn#F;g7 z?Y)I9@ML57&!th!kw-%4j^Soeg|R*#qR9Yu|D17;mp0J3ET|`E_$+oxTZK5MAjvp` zlVa1)y`qEwJaYNZ7sl8YV{hhW@SxbNR%t;5!RhhK4DC9{-3zZoyfkoVEx5w6j?gOy zlbo6CHdK3i#eK!Xz9tWT#Tr5#3rfNZw(dleVr-EvdbBYnd-9 zV~F37du(65_gHYt&tlL5BHf7UVRC=BByPO9Cb@h-rfux>Wx^fZRJZ3v0Lg7BxaQ^{ z;By}A)>v?Da*JB8)jP9E!^m(UX@`J<({$F#;^(1$T90lTR7|cS%6}JT?ph7SCw3~0 z7kC+RMS21y%(ag5)FS-{5(6HnAT=eB)$ENXBIb-fKA`voGdn@FN;4y-57L?L${?Fa zvCqoDUSSEFH;n!)SfPa`GZIV)^ThG~C$o%7WLt>!g08I`dN#ct-f%$T#IyT~q zJuU_<Un3^z?3dJ8JQBjZBwJUDl;m*ntrfkho`J6^`apSs# z@|P{Ed$mGd;?l3BbN7|a?>XDqiMh{y-)~qC^0*GKd5NJgS-9OKw%kgQ9kR4bZc31I zH;k{k{jb;;RGj{AaO83DnMW!B;aRBHn~IVQyp(Qbt%RK(@UXV>mnJp8Ie$GzzdQF) zT|*rvx<4l7zH@m+-&b+6TKf%7rufV|O#=BmIOO!uZxS&PYzWok%d%#FPrO*bN6Wq? zBmVs`jUX8L>@cFA;?>sLRS3hgusW&tqVJ2czPPGcZmq>jr!1sVeg!D}X!m4pZZvdV zsp^y+^Q(@uhEFa5c*lkNuUq6=%|t~R)qc@KP9eGTK~DNU`W7RRpSEVrJ}S3~r5uI+;a#B^<7odDOLWK6&om&gq}0f_Y41c|e^NUTzPl9pZGVP8MCn;v(5reG z>W~X<3H}=&@sL|Bk^M8BpJ+uB9g?hOZ$G}%!o;8+18{hZPZ&6bIlBn1+I^>J4sc5H zW92t<2mSN5$XMm(58;n%t?xOPxd+?r4atDCv2h!EBPskp z#J%`1c|#{lq!TH-$+%sbPJR3S(w>!v-jl4hUtWV5ag57+O!c3_?J?7 z%|IGqaEqX>E=N|+t+zyHQ{%!v$Ywa`r3`EIl0UcGa%+Ay;Yx?u_J_Q;YILQGO(+rg zwLL%7a~`yBe~b8aGkBDj$UQSCd@v6lY(%+Fi zofE%ZFuuigH#3IU-+or#+^N47W^0eByp=R%2!Vj8u5I0WI2NJ$sA>&|KWCyK_shWt z&(G@72RYg9FnbLEm4&2PpHI}(X4{=Mx4r-r{OO|`%LDvE^rtGl0 zJ6B#9gwP4@e-$#o{aAuLl3nBNCDO_EJ!22!`e6O*+pU~;Vo#HEEMgw=w|&d)Y$>qQ zma9zXrl!PHN8)E@34k_Sug~c6-pR(sJOFX7-NNBH6HSQEY2A;tn;LR+f8U+-_oBE? zm@+aq8n_ZegvCSby&HKBAwSv8I_6ey;@ZwSHov@>n75cf2t?00#WxVmzG}W$}8hr_Ui<^DP@E z=S&PAjrsgn`;4A-Jznjl2?V z$sN?2Fdb%O6~6O8_+!aOm9!rVhSbXV#oqA-*=M9@|@)oPmLk73)k~a!OtB$0A!+#ei ztEj2<@=f2g>oniw19cKV?tf6$T-NUI-{cWv|LP@3a3auc)bY#E_hC6lxq9M*vC&fE zPV8(??|R;S@^@V#Y2oZyw)|i2uOG!l(U^NXRc67@%%y(pMn7kI=$9;){PV39@5MQV z)fZQ^V>YfBw|KA@aB2YBRIn7|Z(a^0`BpdwxZ|B{Dq16NY<^Br(k0L`iYm|G&X#YP zsf#^(EVG^|R4_wrML}6KRq)_F4YQM&$+XtTwymqmD~41oTXQX4!HU$reeUG*=n-!+ zw&Hu2cQMLbOI5cqU@-8$dSfW7wRvJN0{P6Gc8OLzifQ2>tA&;S>PNySe}%mt=j7e< z%>M;3PVqcJGrck)O?{8cNvFLQVlEO-0O03KCv>s3?E6#OjfXG3xaO7i7%8WYpdDkU zB9P9V3O^5BE4ABSo{Zg0<-FdLAtGyOJ#sL^%yOD#Xh>k^5o;9cK3l#{KRAO3cF0M} ztA?6+DZaZe{rYLFnB%-x$4UJdp63IT4du7!Eu*;(w@AEX(f!j94_!0!@2;2l3jU(t zeAtl*BCwZ-J5}}BGhXfmvwLyObdNq;Kn!n%Mw)JZtd*h+9ke>Abw|JQSSByE2Tv0u zm|%T2e1oFyU`s$-#@L&Sfg|j9D1TZE7+m&4;J5`#)#{vCmy!Mcz3AsnL+IO$|C>B8 zgCD)SjkwRYjD7{;z56Am0dj3&NO&HIyCGhD8R_1$$EGeQEqa)-m8o~j0t5KjlSI{L z9T?0Ge??J()rM0D<^P6{{b~|-GWXI)0}Y+0 zY|9KV@(MSJ6DEI4^bxxNKei5ar=wGQgXUDy{AbmF4tgiLQD4gWG$*G$WU@)b{ucH( z?0MZPPLMkeRsoM*!d8en_X2OH*?*gCQLi$){lEMC?{@!vvA*%R_GYgZK#ss6Jv@j! z{F(grcC~0vH!b$_{=e7Wt6RnJ+B$cS)>C~KZ@JF>$SbJ#0Z6@?==iTlfYs`6Oc>q% zzi+zy|GkIcopFOV!4ug^?OFq2O_W3u3r3zqRuma0FT1bE@TH4{?3~~_kU$=}4LuC$ zeLXf@g%Gp1|Ns3kViX5|phtz5@>SrMtwD?uK`d`g_*9p7;Cjn}ur_x#x~^_P(xb@3YT27Z9kfJ0-af zf{-$AQmi9Czx8OUSNOk%<=*9&*ND+%FzIu|(#joS_y=*ae8&83);gSzvNcOnw1P^c zP)!(28Gtlg^Gh9D>>w1|8~fAxGMe%Ib>{(10Cibok;**DU})jkDP~U9Wf|_NPG68$%&h9po{&NgM>uLeuAc2 zoazVjeIv^g*27({fkVFd^d+;8%E7lHBC?nB=jZ@-z+|A2Amk9jf1CW+1}GwS%0hI} z=@4~jOIDT%@GJ07<#XiRUbS_|``wU0Fc@r=(p^xy>%9Vo!CG^H03B(uMPm5o{!}zu9f$&rR z6bOIu@)GUu?@!U#B2+{@EY)-YzX0Qt&iL#?UQ}}mB zH7&@XgEy8XXck@mwEkgAv`>ArC5J4ZRzaE0=3eSeuk|pj@3@4NLl$~@kG$O6B&=Uz zyp4^69b+6=n3m)jxvtT5#(mtQX0WrlIeWTdpg!ZqV6v9_efbq3;ku0BSv$f{@gC{a z_#v8VHgDP4q9)r7Zhu{}7irVUo1eV(wohDnn4exCya`}KeMNa+8lg>(wm~hw8DxHT&thdW{P zZ@yj%Xo9ry@-EL6JS=?tAg$b0S2|aFeVCZgY<~03Hf&GJ#K@T1ju^<`mXjurv|AaUH%1cp=W&b!&LDZiw$ZOm$psKYWLoOH;t4#8nv79 zEzpWSCkRL1gx;GVR~`Rr%c=tXJ=zC0L7{C*Ye-xn17~dCQYZW;Jauh4uwt~GwAq_e z*SD?K@{irI!Q7vge8!@uKT?hBJlNO}NA(G()-8k(XD+wQ`(Xq3L;Aa&wl+8K#Po`F zg@o)knU)(rGri2jf8WqOsk)TVbSb3m8j1DGLBpEDZcf!+rY+t!R4_NuH2qFi*6h2D z05b;%F3iO5E8^@i<`J4e++b(_z5f&WEr!EH09O!Qz-}V+;J_^~I2hV9H6!DaaH7i5 z?LXKtIbc^j*PCQxGu`0Y(K%M{TS!XOFf3(}%I+l&uL^0|daKiq zn(Ay`lfRw5w0@Dv{}9ynk%KLtO=_xGUnh?|Yg<6z{l;F6y^_?t|CMjG7w?BU7#|&vLgm~P)sTxN{ZPJ&LPQ^f#^Qde8VdIC@gNwJHB+p;{b_jlzK+hwdeob> zBHBmlxr5SK1F1ztMLmq{w)QVUXplU9{McojjUep07SmsnfL;%J5^*n^J=gC{gZDBy z3&C-*%SxZM@^+Ih4$6r?CXn{b z{Bv^Q#wZT);fLB2{p)Yf!UbK74_|8_Euo5Wj{J++;cK#NUM-RDdS-cTFZd;*K6>+; z;cjg?PU3tZw3tF$pXZ&e5m6@zQj8#XKdcgZs2^xlTO7dJc*Px#qxOd$=JCHLDa+^5 zKQNFv3{{0KCEsB&I)o(bQ#CgqG&S?6^r6S}d)SCvu~0@vCQ*fiib|NX$^8%58kN|r zvLkm>#m-&73~e`WvGgy8^S3eHxa*s91wqunMy%R~t=T_*LkoG@^ts`}u~m=iAJUlb zd@5lyTS~^X#UF8Rzdrp3V|PRPj~q2l6=esvhBh{*?1z=Yv|!9%kbDJr7E}Jh5A`o0 zbQ0cO)x1-w)75{BIt!lwglVBxctOFzOgC=e3nvm>dxH&CA0wZi&8Ng^>*%m)E-9+0 z$Xi*lRoG49l#afHjX0-HP+rVbty&ijTPY+DA&WNlP_H{X8^X#cH6zWM`@QWa`Cm=U*_GJeSUHts+w>${$LwSh8yZf9qvIk+qp9LFJ6g@Wi`zn7 z!g-W;R}}G+Ug|MuWUkLoSXJuw*%dSCkUcjp$3dO0NY_Hp8|V(MFkNYowYs++w0L)A zY$S0N1BFAgG^++$MY`y|K@*D=;j7;H#gyEfM$g@gd4U<`zVvwk&|r0{1u^(MV=~mQ z2sFBcYQP2O;O#@4l%dw*m4UKY&GoL`y4m8o4(F5{kVc(q;o?p_YtFddTaF{bxITm8rIoXLv%gK?kkWA{mQ7B@48j za*yS(Imt`QXn#kk<>}R>PMa}w8=2+Bj@?vGm(y3SCEcO_B@VYJZRo?r#6RYfn-v!u zmr|DYrC^c_Cv);>-PQN_$Ccbnn7&wUO-{~wZP$Gzw8Il<6tJm!<&p<%t#qk$6fa+^ zvyGX`3=+M>5ydcd8~Jgm-upNzHWnjO{dTrR%v&tqr;p2ZkuTeQ;=Sa~hZQa{qzB?28%28l zd;XULejs?}>m_$26S&Ewzm_uds}~8I+-Cxg2myS!$yp#X3j*uM@Res^65E+%LOy)c zCMbIYmJznCOzobI3;!d)QgZT|A2-(2w}n>r8^uZ=rhx^Z_=6(uh7?#?+*FT<+ZRT2 zf*mavZjuVI?KqJY>7QWb>c7TaJjSgz;Lb9J+J;>R`QCL_E{HU=av|@=p8<+ zRl0s6y0J^(Gv&{AgQC8Mng6~z!V@S4z$mk~T4X#rE;)Q(VuS^~)YJDC;;>oRCSayw zyY{p@-esL%;JunIS709Dir59oY&vectW_tl734WHziy3jwNRuk8GBHz?NT{@UPE$S zr-^T%MH~aS1jYL5Nuz~i1MuN)yw+spbhEgxn;U&B_nlVmsS(~8Z-7Qz|Lv{IaZOI) zgD-(I9dx)DPR@b<811A)L4NqljE`5Snw5UtefC)`0tJoW8+Js6nfMqNcRa)plAkoB za|fBk#i#P0*u41~2-6Kfl7S)3rALZWZMmT49xyYLk&^CE3k)ys>Qp(fAQ*1la#WO) z3bXokMVXa}%FI*~wfGY9IXC>j8bvq&l^@TK3^s9bLyv}{A|fCTf^EBr&&040%A4R! z*cDq*Rn@g-nDGzCRX(oN$xJC}kbVW+@X9y_2NdrsI#Etd$sQD8o`$4*bKTARkmR}% zN~*G+d$enu&_N1{%e>dyJaej*TiB-LtSZ$@lLG8%9 zsZ;R_U}5@CY??s_zN0k8I{{P3yX`^8s#vY?TOe|Ys!sN>*PJUUSvyM`$~_9yUw@dbM|!3 zC_hC`=F^=mmQSGx)ac=@FKbUC`$o*00j<~;lxqAOBZ_r#WWr;r26G--*;LP|-SGlb z{lO^hS?KE?Q${y#tCjoc_GHDIRyix1n^KJ0ricAMrktrWkgaM*b6>80xe*#S^g#Fi z^IEg2BAqU`<3vH?N`|RBpN|dM4B+TzrmxG^AuPI1)Zq2_chp|fV6k4qV=~ZJ{k$Z( zWpP?>6^{*c4WENazLq`%ARSI`)45Tus;?{xN*bBa)7cX<796U7>k3{+M~B~6bBE9J zL(99MU)k8%rKP0&J1t=SImO{G2%1>_U+W(6rebp?n76ozBk&;?87eCI=+QM;`!{p; z+JgrVFumqWVCJ!htw^4^gG0$=)SGU*qzjEOUpW(YzM_R6lz7X?xJuwCgCYiT*5%!N zb+tq7>S;xPQ-sd862=?_%Utrn85#&!phTYrlU4pgb497y+5m-(<`Nc{PNz8AT^Gsh zw>~>F#7J+;nBvJy2~EyA6`h@gu4P$sjwv}Xrq^#yF$X{ne1G-B__)5#W&HJFC#}`A zv6QC0+@{47?c25isofH4z;btE`YYGRm({|&A9k_RjJ>g~ELeP^&FFJKt)&dKGs6S6 z3=6H8n7g#-5dMWctt{Q2h^ad@5v2)e`+1h3dBC2ERj0^BpLGvN{PS%S=7hRx3 z;j;bOkt^TBBbp?#PA?)-=P#l(9U1rMff+ zWpT3BX-{VYnEQ*v;E>Pg*gC~OF%cNz>XN=CKKra}C#=Tn5-eMtL0)a3+%tRk+ajom z>FFbTd)3}4UxOV>C9?*q@Pgu%uh~piYvz=w$eKU75bp;Gri`qtyM_C!83)+p7{8o9Q8u;lzg589r$_bh1x5oTsOFjal=H?qd1-!ubYGz zS4bCp*<#^9>}Xj^#4hs`<{FvZ@&y;(8U?Or{WsjoLd z`v?{7hstE`rd}4o3vKV#Z1>j|w2d|lC)-G*t=V_+nJJ2h{=oLQ>Xi1}zu(uHQqBVZ z#FR1Fgj#sI%8?c35oJD^3ks8I&B3f&8^W!Aj-N<85JEWwf#;|aMi{O1+T-;)ZMWx3h zN`F~jOH+%h&gZ6`e<$(_(LwpgN0qV1fY|+_?U6r4G$iPAWIRhU+1D;Q=NI3>5gre2 zkgHfnswS>EK5WV%iqjlV)LfxkJH&L!iAEndu-vey->o)v># zi4|QFY;jT!d&4xYL=UNfQ!Z|ZKG4z8JG#4r)vuq-qB1wm%UW9d45)@HwA5QX@_KxmVD+oZ zkt*IY!Bwn!n@MX_&@_5+s$%tcKP@Fk<0#H^kF;Wa+LPN$-%NHWRuHpRf4r!wbfeOi zZ1?qp)&M)b@y0{r=5Cq9bDv?`R|Z8&{MiSutMYaGq^diu_C7Q$_Z?1~9;1}^+j z4%}D1|DnvZO>+nsQSG;yqx^GZsPeyB0Fc`#^<_vlQ;r`mf-5+#b$^}v-4w-muVcjK zlFh#}I|maHXzy&h;MyX*$s>1gyG~Q;@6=o$2NMG%55_ zk(G%{NO%eRaWdVy^`LroUBaD}d+uuwb|+R1{SZw-{;@}|R^y~Up?HJ>Ktqub zFLt5rK9itI8_Hcc=gmOm8hV8hL&ugl|hI>W7_cC;arYd zg`5Ik*zZPge=80$4U&Q{e0(ubsN4VIGGr7}ioXU{PP>ypYiwAz#S+_xqdq|@qkr$q z4Mjic0?7>d1F=PwaS(wa-qc-YNV^gJ{12^!oPAi331EiNNK6R*A*I0}-;e3_$>OmwVPn*Wq>%$;}2hy1E z8Smz)-Lx7ijF(0hKC)?oLjrVFx`KWaPj=VuXroV>A{$O2K5bi3V{S|G{0HJ z|1$H&6dwx;?u-~qDbu!e9}E;>4xky2jtxQ-OAmo2!Rlc{i~3jHJP!h6$?-f1XWb83 z4LF;i^q3*F0`Z5m=EI-?hW+x7KgEZfxdSCyBAk`&KbF2_Ij2mr-~2*jC%VF0A# z7$DbdOUrTZh`ID*_pkwki`hVo&oDXyrwS&$wcZGA_pb|y-boKa`1QYdO^ojqt~rl} zC-jz%f+P~M*3>bpG%MAu1n3Cx{V*dUS!TA|w<%LoQ%9$l542P3JQ6Z1_$RSvAD)n9ys*7XYNCavBTr^ zUX9YEAJJ>^G3t+d+8qWMnIXdGk|1)Ub3*AQKCGAZ*M1hOXgWU|E0dTLo;3JrTtSUM zg^}g+xSequ|FxpXzgE1bZX-lczb9j!A$rTE)5~`GTFuklQ&b@Dw+$f`-LyP_8=nC7 z^yFG#jBVDlK>`TYQCyWH20yg@8#t zerlQvz;mG}A$2W4WEsN`nm6uMm|#M@?37CGAP5$zH?W(~)HvfT&_2ju zt4f`jLbcDD<+O;{e1o8s)pbCgR#aRAA8lRfViP#qHmACA0Hh}jxlm6TUAVmdC+8Q< z+W#F#_Q`mniQW_h#efwkK57lS6B*lr=UVEcsW(U@Hbf3ad-v#giD4(UUUwQgYo>7|#(leQ4EN+lyhA|;dtx^Lk zU&znbG#&!k5rJkVRD8 zzxf4uoD)pfAawu3kc&4;D2YgNVa&BYtW@-OgQ9Iv65X=%OZ*V^W9AfteEsvadfq-4oeg3(40@ z6rb7Hh2Sb<{_qU5M$Ivm3Mc3?dH6$Jg^X+8EEabl7FHa1p*g?Kx?*%vv>tH91?nl+ zE!Q2~R}!4BF{DMKWa+|!c}<@`2>4(YK0AT<#8*~VVcX{xhe^>VL!5MqX}oP9tNPd; zu*awviIhH@m)GGWM?U(fV|x(+(bV@xsl(3JIma?OEG#T{I&%R-K+vKn6f!5IWMoao zJc=@RFEmGt!sm?4%-x#0KaDrlY{aP0)^I{IdcMa6nzX;+7(G`rw1NBGDtDZS_v-hp z^4wmNVnwMX)_HOv0Q<_M5YZx)Va5TlfRWQb{ zli$2|>KVOzq*cRHeNc*mB?^NCZl=_WO$0PzZn7WjTr%1gi(SemQ7JqaePCe?zptrf zqV4T#Xrr9G6ezOF^5$do_FdG-QK;zD)4$O&6}Qi38vzX8pb~5_9N@yZ2ucoe?X4n@^glZuU!G?ic3tyhr!}EU(H<;MM$x+vAr=SY-Nxy#MhpPFdNQKH_$LqQ3ERILFHN5 zzLQz1ZUj_&*bt>L_F9*J_Bt#XAAn_cAOIRbqK_YLFQFMr3i6lh-snyeTYkzL3snGt zmr}L&pYBTk8H?I72lqUPSrY_6NL$e0h2f@)MAFq~IJY6`CY=8kXeQu!j(X*A>Cc## z;v9ac!6a$TxuW%H$YU)eiLtB>NRBNI`wHP8ytN*}cqv(Ip#lG|Rq9_SfEoVED_1nA zFG_bDgQ(Ewnm?;J-lg}6%qeluU%`)+p!yUoebmHG218GN#+r)L?aue-qPp>)=}qL9 ztl4?u5A*)HN2+@*n}3pHR-%wr;?^vIVf`wD$D+_J^_)+x>rf`Pnct*n~z@8F`S5oe{&T}ZfI2p_~ljV$FHmk9BGntqH*#gE&n zJFVbBl(`~3H@7vIqxNSk*TI0_4dT~0w2h{) z6+&Y$_s57y3cQNTE=K-4o8YUilwA9R+d(M%wi2CzK}xE~3H(gYoF=UXy0B9hO%^ZC zu`ilx6C@Rpp|#UbG5RsT3A{5@SAQNsEx32v8zwY5-Ln&cOl$|Su{@<_Zxaerc zpsGX=eGu>>{L0G8?oW$ns$b97E*yqY_RhsJC>#&^YJLHck>&X15|e5p)TjOLmsv(y z1tsCv27H);097r7d?E`{%I{AQ)X%--f!I()6cZB!koTp%{UT9LhPJjgEX0KAM?~aG zz9#^IHrb%9(ekbb(%H)DSBe6;(!G0f@IBx#P_d|Ll@A}-BmB&7zE{)GxSFq;JNW8O zXi_K*?>li7O(>{@VwWEk<*9Wwn72+X-jVRoescUNxh9B>Py>B-j6dkIomkZ$I95U3 zf1VW>VlwO9;;C2Tsn+`xJLblXA{W=YorKX}qjJI|LzRb?D#Esh%gdX_1}-8{r|OfE z3QZzj*b~>S@r=^b3x~6W65vRGxb_?~3DqsoF`*}9FL)D^|9*m$?FzS0BuvR*p50W4 zI-Fle6;1aR4xJ;SBY7Vw)HDCz(c@M~WX|!I*d8s7x5j~4;sx}+%NDPA1Ed;ak+0Wj&CD=JPq}DBXvgZ zb?CxowCc?*P?KJ-cU+ZUrab1Oz0Ca2WcDF~ytqm667m|iu5JHU=61;Bs6c^8IejEZ z9S|BS-wJvB=(leJVRRdYrr-x@shdxJ=gu9FIB#;^M3TYdKtcuz7VeB&-_6_WRzk`q z1vTwF`&h6VOsZs*tp!Duc+iWV$EFxH)hKRgyIqZ~DVqUwKGf;SUQ!MzufcS-wS^fMfzN~QLfH-! ze(i|wJGw63zW%lzitpih-8TN@R6;|8ja@P@007MdBvAVF-wQtyl9pGmVximIyY@!L zVyFIRjo0B;wrv)49AxE+ft%^dh<6GV_Ghr)5Far6B}c4PC!;^5^n0v}xb}g3Ha32V z$(;*hp#41*arH0TsHLn5 zka2b}+&!2mf#&!9{WCm-i^Q=(hy_f-Y4nldfAr1Vdu<+SiP@|^Uy{V?zXf%T|IcfI z?XA?zGus!2ks}}1M))EwzVX_XWPMEn%TmUxFL8!fDEHF~TLj#tCcgJ#V3|5fjp&0Q%ivsvmqo+`Gj z@I9F}aHQ&%g7axa{^~)CCB^;AS6%pSJTqwr=AR_#hi{lCyK%|~AwBh5;MNgzWs z>>U}dyz^vSPJGmEB@^8x`ex&55?WVQ>AgnVp>_I@Efz7gnZhd32_56nf4d{*D+EsX4Te zG0dzQY?l9%qWyD6Y4=T5S4^2vqx$ZlqIGCt22!Ds>czZ(Fh{)p_hx==C0-Y=^Cd`w0E9oy+c*bE?{5`*j~bbMNfU} z<^{R-1n-eBqPKzFBm4k~zAfJf(47L{hIYDu$QzcQZQSlLsT06~N;+^1hnnZ^272Qu zL-b5S||pON+qV`d$D4ldytmlJMrb>%llq&#ezeq=@zok;2b2KF`( z^c=bJ*Ae*U?6%fbnUV!K6y08#E_Rgi5wKajfhQD5Mu(9}(KiR9q=f^}s@e8ZJh#qTjY5?|VBdTDlUP)h(K8nbHXQH=b}qB<2+Uk=x| zUi+*-LiZfb-g|gYklpS&OoWW@S)B*$K@|xz84K4BPzzwLp?_WUc~hj8@AA$*RhQ*n zDX{d84+`G%eI-Qkz&R0&2qQoaD9wi_Q{0xnr0n`|)2mKE=|cr{sGV3EbYlO}(dEDP z|E~%f^+q6ip3p*r{Mmu zjxfugn2o+;vSqGQZMR!Azi?w&q@#d^n7A)AJHLTK!;~kn!)M7e6I28mCOS6j*$Td!%LgLYH-b@b>~=g z_kbB?u*b&>XJIBgP(R*Fxt!q()BGSeHgdY+nyEBj0kbGfKzsl$an(`4b~a9U~bMh&E9&XN9Nx_@=&BEBZtqC&V(m1G=ZcA(dMCb^KVIH zS~T<7!pKh}UW4Ipw4-Nu*J@=N!EMyrCU z0PD8|MK2wF6Mj3bZaiyCNtZk_`{1||>e+*=`NbQip6Ali0@TZ_Erp<1-Q=ky+~uhX z3Dl9pJQ7(DEWgJBUu>fu+l%ogWm>>QJ zHnG0RtdVK{Uq=^NpX#wHeY@8`ohrLf^ToKjycG91Qq#Dl|B3+4Vc>;2;;wuxgfv!M z=!*B2{oQAq-|k(yE;J_;&6;g(C9i4EV^Av&=AU-P`_3mhi-}&!*pDXPR*Td{BCtKn z9 z)_ayMi_+%{I-3a?^vMEgl1AZW6iLSZ^jjX%3gNJ`4M);|u@+H4rEGWox#gvU^s_Bn zlot!-2qK8&4~_q#>pf!e859!xefiv8=VA2m-ewEj(?ta7 zuLyOlcUF1ehDGi@&k)kizNiVAuBTSfz3$(Cn9Hy6UZf5L5`kCn%A0xlcOSkZ{4^!Z z8J=5-jz(=|Xz+WF7pgk$Jls+m>gHNGi@dBOQj-D?5d4;Pluh>Zoe&xpj(I|eRi63j zn(F7FN9c{#sQ5IXiQ^#!-z?(+bn`_7TSI1}eT`+&eXH-M6`mO1?6G5Xe7DpSw6*V2 zWO}V%{~mwLgD^fX#?hdPcTaiz-FC{61}>)zU0*KY5ep+?9k#09?;8&i21YdkihfFi zWe8EPKI4R=!f>|huFX`>BFv50OJcmN?3!*hn+}!Mq=2O4KWRk7vUu%N%l6!Xo!}`IBrI4LZ9mZ(#phcLBW#%>mKe!4K|MBqf?)8&a7I zwX68YOE0X7t|+g!Py3!z26mH5hhf%8KP}=2jF3+6-kXRgJ7Iu3O;BA;w$-!-{}^i6 z#>Uyn=L3*D|nc7MP?bcj8YL>bMW zoCr(_*!%h{eW!8(Y};g!@P`d)8qAS&q_Rgk64^lUD*SviQoUVr%geM~ki6+Cm1yy; zPpg(Mtk|w7yS8xT8Z|zMjzkdUXsuTtVu6R6xAcZCe-C}14$363aDj>&j0C6|2rrf^|MEzT@;mw(vJ3vkJR$bNzk1XHS^Xlu;RHk(q6M=Q- zhQZzOVm4R);-AB(?MH-X2K(qLr^9jxX|_`%LAgd>s^mLF5w3b#oKell@{d}1zDp#* z_8rWFA9Rbs&#q6DFfQI%IY7FO^2i3feP4}G8Z|GQUXdSKKMNEU!<{9H2n-`Z?0yf! zQoE_NWSe1pWaMV6%%=ka-~!@1&g)WME1iwXPt+(!mN;``ByWF$h5$O6-R*8y8|j*2 zQD^Lqmkm zU)=1x;Yg{(%Jems3^&8i9`w%g^x-9F*dh;M_em%Z;7ED$fz=$c_?6| zpojweEy(hxgaFr`FMxDy1sC@DH2vMpCCBrCpIRJe`$-Z^x+KpVd}r^-K9P2N-5UkK zm?E;tg0oZJkADmXW40QZ6eBE8M2sJ|Lq^E#6^nN)eugV-zsIou4lV0!naSrM4P(3f z*62S!p4Yea=5UCl>^-VfLDp$XsF@(sj0FgYZ=)Czd|KyJh4?$IL2n}Inse6G?^0v9 zs*>WiH>tzqC(q2tTzd51mV6aDk$+8^!IG9rEb-ucYuy7@Hb}`yrPRdlQgk~Z&T~H# zfn`OUAEfz%8VEjr`}JMA4-wioY`2YZ5}xQxgSw%+#U^gs)92KFL@GuH8ds=;tPmgc z^3~hbF$Nxg=6NSB2?*93*z+aq^2MDP=YwTh37Qq0CIDoHpL*n?;>EPM^%f>FeSV;+ zW^%{RvOi}^woiHv+9$m~zmnuDj6V zLoQAh9Mos>j^tbX!v%4Gm2R(R*kH*O%hyG0U(ln@ayj|c7Lph{)XL_@D;URjMD-~@ zERZ3$JT1JrUd_z|(~4oWk-$eT3^Kp}BIJAr0R5F^y=UD|$snd&IrGs!^5S`P>86g7 zY(dzd<32?~JIG>nNdwodyPRI^c(544b68D;H$#QFZSWRFrp-+)(X1xmsnoZdC(KkT z;DRfsS+aTAL&n4Hi`n%*a89-3QqOORXD8j07kLPS2x&&B_5cTKW@tYyZUD)wq z$+fTx=|$vzWeW(6?CK4QlcnVP#$my+z6t9XyMk|7_vB@N1z=%oNQy`Jn>rK>{dlq0 zZTHDFIe#hHC&Ax|iHiT$1y*M7))pPob0XAQMH1EdTiyGoS%GacUFF57VaMwGwN z#U{eSyG(;cBq?rphp<#-1*6*TAmLiXSect*+AcceMM)+FMH2C;In}xJpHD^_--=sDG;(fLhS|ohH5SiRJ3pcD?xN zwxzD_nZ*rVp=9~6fte6ys>6ex-=_ly?m3H#K}SFF!^>)Gqk=CGk&V}iPS)AQ2xt`c z2GEKO7S}1Lvt`e;PI`O%iW83+59gEcJ&Hs-{-jxV4Cs4URzo6cF*IDX4Cc-!zwCA!-|p@h$meQ*8|nUSInsSxFrRby%h^gp?n5xt7_VAOF7Xe)HD-B3_=DtrEwb!NP>}@VKP7Z8W5r zLD`Nd>fbKCXqw<&UG7wUz;6jR*%s#XROR2olFW?khnC+5zi-kpu1 zNY3Zr7LUh6B1|8}$7LO_e^!DH$+R>=zA5yStY1SzkBro9YN_$~9Ql0VsZqTwbkn4l zJ0%)Y@;mn*+~t_l-x8vE0SYqbb`2&~KF4h$9;hCm7c|^UyyLt7 zz1#3~e7mrAPSvBsj0XF&$mzD)RqmuSbnjtrWJZJU zhJ@jdjrMe2+v9*#v!lMFC#BrzQLBfBaf`y2Ewq>v{azA+N0N zSLCvg(_1oR?h-l6f{+v3a*TzX1H5J8V(WKT^vIU#SZ)t#J5Rf653os+j`@^ow=kzZ zdt$aL$A@(}xN+wa8+7)Q1cLl$!hBm_vC#?etf$ZR`H#M~Qwh=hNEjGMe=i|;e)xPR zh;(f~T!tQ*CsF^{`@By(4%riAxp?yILG{7i*BOOAi!?DwrGALf>@gdEB?@k}-SYnE z$XB1vPnl7D$()?f3m+G~j=eT!qr~y(D(ktqMM468nj491zZ8w(I=gIpfgzuh{oBA8 zHTjcO{BUQRgqLr%_-^or=^ZI>R7_a|PvdV=~X{>=33ZeBm7M&Jb1 zYb8M?UGZ+mmWkzRYjt-`r}irCK1*ievihzqYiVbnZ#-3AEm=F-&a#QCw$F6@+Z_U~z3=iW@$+rL#W_ke$L8t9}@a~Y9tKht?g zj$`Gj6{}-*rDVA6cevBKS;Ihh&2d@olAo3q=>S_JX|RI)AQE4*b40D~Il71<+l2uV z&hwX5IXdcjFIZZIJ$7X7^w(Y(|3WBEc{PbW+4sy{$Jpby%gN%fVSkJsRsOnB&Y{uK zOh3nM9iljN%dX+)r9YR`GMDH;GkjwKuTr15zn!Lf<{_z9N&EKdjoS|ou@O=+MY0?yc?k&qWs7@z+l0wA%1a zouh3fv-={$M#KwE_gbQ$`R`|;-%IVBgT^Y?A3%2t*n4XdPCLKB*?RaAq5NojXqZp* zCi{48ZAOGahe1}~pEZn8@bUM>@BjtwS3e2zWQX`5)200G*i0Se2-k_dmJZL!X7iV2 z=Ar%X*uU@QoR$`0WC>?;YvQ(3N9++7UT(s#<+kG-*EJsd*&r1$F8tk(@PEE0DL<}O zCk>XM_6_xSw*H=ZzJMp<3@_-AjD|2f|8r7Jw^C$P@fW$w$lS`1uK zo$$rMNS|T@fXtGv&H-p6i}*N&7KZCs%Kx_0`|s-yXTv-vPyq4z2XeJ9k?=$pzQc#- z(7n--O?Lz-j>>xW>u;~04xfLHO>w$P=Kpth=l{NrVBi4%K`!}vCj#X~UERgN(A<_d zlYy@(`3XA&KYZJVT#de3#chaF5oB{ zw&Q!hfirXJo>di8WhkQ`nn%d*xj%DFMgdlxztplNbnGwqjulPDrT^!amh%9cxeRobql9mc!4tad()2z#Cin%{BGyC$M(dkg){17K zy)I|`ZyS^UZnQ%Q<+`4e?1OoRIYZroKmIU#=?=Km4xF34qh~;S6;~rFIctvTxm)y9 zu!733#+j%odYU2srrBo=;EG^~IJY_OT5)F3{6Dvx8^gufd+Ms6Su>p9Us|~Hb$Z`F z$vacEX+B+R=rO|sXh0?~Bya_D#r8a=KUOB`qCer~WX*Cgu}^TZ4Z2FaH=ayQGUI{5~c9@!!%6$xx!8ujv@TWE zgX7yxX1ZmEk2NQ@1i!8O#KU3;9iu%*8dV-m#Z&kVK(Se<4oefhXVZXy1=6rAP} z=HHgTsbYA}XmGGff4%U$w=A-2-AB)2+BZs4h(RXsXhk*scPVvl3#6II{U%>|N1VY1wbh`ro+`9X9`(n+@)OePgw_ zp5CQEt*4M~C^@{l#7CecPkC}&k6*XC<7gC`LLtV4wsGb9?~#vi;{5fxhDf6m z&E1pVv!Rm1X|HTG1e}HaS1}v7H;jOn2*kvPJQg|1K)&^4B9JKMD_=vvyHZ zCG|~zKV1my7JVk2<-6(Bl_+xNbl~`be>L$mujlCK*0>k?*=8Zr^U1cewPySCj-!Y7 z+wJ*uPb|Ep`dN*xf8_P&BdPy&^+(9^HLnRPBoq2sv5Lj?`KPOoRW{ze5Uz;m{DH?% zg<~{E(#MT?wzqfZc%^ZA%FaSNnMCxXTzvA!o(rYF;3`K9|89|C_78AL$_r;58tpC) zou@E5O!UTZFqNc5@~`NpMt|GRw_Gj;RxR4~LN;)>YM}>9ooQKK#sfrq1%7XcB3-^Hey>ME))X zawc&)Vec7Sv{y&+!_H_bhjy>!pWT8`Pv$UzI)uY3J>l7&Ff*PQ@aAj=+2&^ z>91DBj%wTuQMw<0kOS^p!3^$}A)oji0R!{yUR|L?{dWD;PvaUudONnOB<`MXxr8ju2Dse0;n3KW^AX|js$vhMxJH1A@>msoluedb6 z&42#=w(xXP;o@R~D;mP@hX^!Keh>W*0VDH99VwrrdTXN;2TwM(^pjeq3lW!R6rakT z|8$p8c+Py}GT3^Qa7Mw$VkmfJjIS2ug{hG$=@ylr+)} z(jg@xC`wBsh)9RDG@_(*HzM8ANba$`?`QA#dH4VC*S8MT!^K)xj5)?R&T)=8=XD_w z?{_ge+M(02EDSy|fP|HS5vtRfVV=h6LPk28GQY~wjK}eu93Kj3Gn~6`niJ19eyLR{ z-V{zZ5JeN>x>ta#@{xbo?lhlUfq=$eE1LZ{ygt1k6jJ>PV?-y5St`C3sszyWg=gmVoBC_{P zy?+kR`YsjrDspbAfLJhS8TEN5K`gmWtQHEwFtUY3#iq5AsNV8}KS2{GQ@}AX{&>|a zMROa}lzUDch+nnrUL^0smMbmIxcBRn+~X+sXj-x!?gI<+!7yTNYkh>$GHS&CT)(Fp z)$up_WHcq3XfTBO*!sSqg@M{_I=A*0;x^D~tS=DMh z-to}Z3*!w?)YR8Vr}O)fYpWf%D$_Vt1bhu?=&inb&z$dHUTpmE zHl3{<>CH1B1=cM1btUu%Uwo`i%uebIZN<4oF`(J{r_tE~-b9H!Hnyz%pjkQYpZl|7iU8=vm+VX`vWZCz)q%o&mZc zeQknQK7s9>u!O3KC8{BXV*kvy>l-z@zsjs{A)+$@?bo+y_jD7}!@_VieCC~7WingF zkV;x_!$3Ch3T};jJbLy({G!DjDv-Z%{QEcuDw6c4 z2znH7@WMSirdDe_WsaotXFtD)(W!6Z?0oRX9Uw;fY9}ZWt43)vA1;Dq3h>t9(ioix zakMw{`oM&#>|Ue!b5UyN>mxLI7b{l{F3F8P1|q(9nYldc5y&xROq0jO=zWpr_o7tL znGrp4qv_{o_XGTu3SX>!sPyDM{QR=~jBW*UIo@q@w9J3kG%uK?MH)jWJ11aI+e{;k zmiBr@=Vv-f>fw>)`#P_X{(MrLme1G2aKavG;p?v58>rrP)FD<2UW*)z9bf(_{@HY0 z;hBn_+A+oSeIcltp)8I+I+pM)X^TF&)k-FoauAWD%BPY7xI8_PwDqg3uE4k1r5E*h!vf!#Jf_aqOOEni~U(PO<`=G)1( zfDt%(LP^!BjO#3;|C{!u$KVRXMLNp!^tRW?Npp@Dx?AU>`a`7+_0oiMkeP(e&r(jy z!amh%?$xzUqSj^-v!I!#bi=9PYy(lOf;H?ynr)l)JuDao1#V6SHea&p5lcdXa9!U@ zhg5?fKk#@?4l3O1Y&mY-t|DJ`Y*;iS#&Pa>SrMOm*t)3Igv8R7z9=<&eVG<5AaF`o3EYclyPRWX4j1V}@eY0Plz^ z1mSB9GBX3MZijF1Oj0{%W^RbWlTt&2S z2_5d>Y>xX&%m|#iZp@RcZBc1}t^@MUAgEsD4t%ekMCn3FmEeYy92>>zzv0UJ9~ULJ z2L#9R;4vU24nWBI{S!S_gE|Rq!)G_%q8aO|i1DNs_R_>k@yje^{mOW*T9KT8|9Z(w znfsCjRlfC7wvLZec8Vi{S=tZ$>LKJNhFv6ld_wlC#HZsAHHj<5JXGNj#;MC?q3G2^ zmc<4-SwY_&EUbXcIRn`N4e!C%K37U z;rf{4YyGx@PauE1inksRsO-Z%J%a>}zu$4f0L8I{^&12dQqah&= z`%b+dul;EOj(m1613CC|_)3{0D7i=t|YA{&z0NVR)S zc-w4wf!}}T0wAvbFmsE|wB@{Q`b_HK_~%1z+YO}J1N>0sSnPz5Foa|3mZbxkpbrPd z%qRq<^)&>xaN0%dtbN7vfjhd73eu+hK2l!n>Q*-#l0F}Za#IXAxwBQHiS)H-q^3Jb zw^G`Z9B2ljUQ@x^*`@nc>=eo z_>;={{q6X=QigJ&%MMFSZe|LH0tll*v7Tm_dI28WEw9o@+x>(Xv2Ci+r5JTcUcQg(D@w9yjTTwJ_=4g6&M5!%= zc6)I0obmbrCB#Q$Fl_E;n$J+~jy{m(DE_BQLMp93VqmlBi&*m3{LaWS;Tn)Xq>Un0 zzcs}!Ph>?3#XxBle zXBTUdSX=IgXw_C1i7p2*laA$Nmag@sXFsG38n7|Gm>9r3aZKKD3=OsWH)?AqPk?H6BSy34OHRNJ zvCao5u534eD_GvIv_^H*){5Hn7N>5m6c|U3C-eR zr258<^a_;!UQmaD7{oUEQc~q13xI4<-8^KH)0mNrx;b600XT6L>kbgI^!n1Hf zQ&}9-qNz(SijSsU3~J^=1WJqqMtfEXvYYqRQi-q^+jn)qgp&MT$9@Q?4H5He=eu)RUxA=@#0zkzt3#Yr_iT4Gx3{^X z%Hvi>@6`e{MSox0la0Y%8u{d9WQVhG&z3}lkp84(ETt@|0i9kLd|;N6PHrp6j;6Nj zDJ>g`E7kiOlufy~sB>Wg2zqUiu@ZHFfF%DVeZI5B3Nv{u=KkODqifH9VMJ$cpYQEK z3oslC`rD(EM-30f1c{$M!O!I3`7nM8EnJBrDynjM1T|4AlrzIcI2hUD%cu1AX_g8y zP2LSt$5iswO!+GV8yq|~k-o8Ah2BP}=sHm|f&B@_Gysl&wqBR+= zd-!rxRdee1YXgZ4Wbw0j;mQ4_YRXWGOx_G#eRm6l2;DGN!~!!(-2((Qm&=^a;Nacl zc|aX4W9ng|fE7qLmCtb>=@370+>RW!^grexcSPq360_A5@?;j}UQTSVE2>B7db27F z-t!k>(c4jxB776)JY%WaAFpgwi=Z|c(;4N{$FU>d~Ye&9J$DSn7_K67R?8dC9q zM7H+cvQ`a}fH-Bv&(Essfuc3xC$>-{JKFA-vhr;U&OXFCae>#lbq0aBuJ!%gn6bkq z%)H6SPLvFJuq@B((>$swg6C+1&6n7hx_zmH?aVXnHmYSnN8*B$8Srm5UF!&Tc_3a%0Jg^p@Alu7Gvkt2f&;IMdqShrc?havK=SXa1D`%f z(=ey=rfzKF95|xt2PWbbzcfF2RGQc%OeTWHQw8C;R#ryy-P>l)vV=4R-FT_NhVUJW zxa$jqC_NSW6&K&vQ`c*|c4+ZPo>?pgne|h;eHT84Y!!fxTiQ!ik=Hp zlVGfaBsms(5}^A7*b?D9lEP4to8_aLn4KuIma)n(p8X+O!2Lejs7}0a0*c4G#l*YU zWiQ332%ZlF9w(sFml4x)WN7*|1>IiB>3s*?+)DlJY?p< zOhpr!esTWP`Sb{?3^)qPK*?*QPKZ1L33H@72H;3nGr9Xd9c`8*k-)#LPr+_8M;0m? zqBPfnP=xV`7~VhMFsu1v=@fw#T78+~m6zxG^EVN}^Dh9ae}5bBLN5C?_CFs)1Z86&0F(jYfvW+Rli_4L@1yZIMqt12owmiKi0@5ph+ zv*k6ayf{2`U-#11)YK6_@)XG{E>7Fu-f;K%zMj%~a`oApt?|hYvS$i@(k9$PRq@xx2Nsb^DT&2>TWhcKiHJ4t$4zfFK5QAR+x! zf}Xx{R{Uc?vf}8#Kn8rPdU`9xdm2tV&N|bQyHqzezw<^foi&&&Kuc3Ix3rYoWX|e~ zozbxzT$}L#$`F3sKbP2~m_WtW-^0-otqB83PrE)^T=l$jeQgaa1ougbjlQt=XJ}-E z|4Co9;OO1)c6G4vQNwe!d3tm=k4}dtCRiidOfhIx%HL{i+SZ)jpJT@3Y`r}vxvZq5L_FTQ z>0YbP8E*s63q3kz5!w0{G*D$Xe)VaC>4g~SGqJRaUaKG-JN{(&4E(IEtqqNhHu?Bmv&@fc#oR&R+mgtzRcF3BwiLv;m(A20mV@_dy%jIenI zXJ;LKMaQXsnhhH@2We*2V#OpB)M`EY-HczD>n-l(LG zkU4#7dG9s_J}U*juHR=qa?`iKhrf<&os7YuiOB%A4 zmMp+t!$U*ui_RSovEau5AMmhvc>1kFm2gHXi?^bZQg``i?p$xbhSleBI}$CA->2tV z80o+HvA5Is`1s~0e3?%Z@@RB*bs>lfvsh^ip^IH$pnyyS~_ubr1;HD!uwPS)~~vFlu2ZatWF`?RKG|4G?+xoKNCj<}2n zt%?+;0*NtKCHkT(T-?yijDvxT!$i6DL}Ox+|M192=c;Qf%^MW6*Pf-P$LD^U+S+;% z_EuJ(QGH+*Kx;`(UY@+Yy}cH~lXv;e(zD^ZIIHI^>h*WNXMg_8^-DDLkW!Qg`|)2GYc~XEI0&#V&J}}_r%aHPd4Cl_aI)Og%dHXwhy1C8Ihwfx~du6LE$HlHq zUG-_6KqRcxDB+q5M|kxAbj1_rp#h+Y%wlC@D^$dqo}Rutt)J#V1vfg9`5H$o?M=6Z z!ehi$1Y*vj%p3dNgUHQ+>VleaE!NIdbuF6eJTM9e2gj~=y^Xzn>VCqJcm2rQ^ODiG zF&GpH4Z{EehlhvP&CjhI9ji{v$_2)<*Nu=yJRsrjxIz9sd0Gbd<}KKU?xP*Q-uJhp z2t=tpyL0XIuBXVzlrry;Uf02_;&ykYvr(vufk7(Y>=UvNGBJfBB98^*yzaaBf>W4l zUXQ$X7i)ZM4AzSCExIW|IJ{SYz`Z~5ebrTW^yQqd2x)N#`wM=QUFB?bv9w-qvF`5f zkwe9ot|Z^>PxM_}_Ff!u2YpTF!?G(I9~v4m^A)S8tkeyYTU%c*44!~Axcq7IJ`fvDaD%U9O-eTp|aSY1qQ2%SyUGZ{@V-Pzt>?b)6M`lM%*N>J8Wsvt~VNt4=zATrdpDwoX90u8tfz0ysF z75f_dHwN7ph$g$Fw`(^vu1HoYESIij^}h5^E%+xu02x0!*i@C5KNi?(g8{2JX&dvK zgD5o>KimF>hOYQ(&*~&rhnK7mI2BD7*<;g2_VPvvYGhlIVED43O#6y_TiEjg0p5rqex0r&$*l zezrI2{s?Ce=GN5IJoOhJKQ!Qshn+Zvr>5*~UQ4hM8|qR|5POF`H)_t)F_jiNYL+(z z$+cyTXXy{@0s@>Mr?Aj|%CzfHgf^ni(DA#E@zCg~9?CrM3gR?TU<%+oc|}E)hfnhG z!t0e&S1flnAXK#5hl;6o3%N!W>+r|6+s)zpT=b}|ZuZ062X!Mt4AToev&P5d*)P+m+8*)UCP&gj zYu2-ezQ?Z%rR={=HN{_5|8++jIk{BGzgGC>sjib&U{T%ieM%aM9(nfzBGwT4N%KcK zZi9sCYFjC#Ywdh7r_AYy(DLArpliJN__)OCEW8d~!LcTr0c$yH9 znn+nozqyuQT**qQNcMuzEbMXFX+pyTO`yv~Z>0f!N1EkHo{3Bg+IqGwxK5M*N(=iu zxoKl(S6*}gkOU+nBQKBDe(KB9&Y#94R@6QEu)~I7MOBsUk2sF`=dmp6+S--|rb+^I zlztmsht&oQhB1l$G^e`Fr-NhZuHQ6RBb70}P%+cb=!WP&ThlLDWjQ^^D%P! zVvruO;R*0e-^E3oir=3M=LSbq%{=;OuE6HzP-5^SPHU~(ciMYfLINB+m^&}+?6R* zdBycFUSdVYL>q{{=)BSHo~WTUof4CkF(qg|9Ayh=RuFs>@Cm#~t521SqP+BzN}Tz# z8U$L50TZD6_*}-SibIv2d+oHY6v^iOsE!2gWoF~A5C_*0=w>xA96%28O{1nAs-EAU zoSbA4)y79h9XXGAyq$_fv9xbi#u(MF=NQ%6+ zcD&|vZb`}AIh;GqY-%^x$K>2T*M6Hza7vp?yUiJI+uZiz($4O;&+)nH9<9=MCI*Vy zK6=VmQz5xOaS#%9ewC||Y`1)Mq(9NxcuOtENx`b!lFr*5xq6Pd{mG)!Cm~pr^E2D7 zI=y&!b|ZeH`pa=Xn|zd%SJrk|bluiD)>}no==*`83XT8y3GAQc+?P{JhZ&~+4am|H zMZ%EV+UD~e^YQX_SuqGq*t>e9u_k`YJKZ1l|NVdxMM60uY=lYrc|I~lCrsGIYQ{g( z{>RhdUPs>U0-)HUmRD2^3pJQ_Ja%YRE8AQ}9qi5^+7mQo_O~omHDd*aJu>>>L9DU# zVc5-DB+81ACFVV0rhk^v6!81C&Q3}ivyYLw=5A+2K!{Y29H2|*{LbSxH{fZerXSyJ zdKdKc^gI>!sMd$FL*31-;>@qH&an8*@A8HJ_JKFh1cqolsgF=zJi0|M93|N`=aO5} zgVS=7^y}{MT{=JUq2)bkv)Ys#m6ods@7sM<$FUKS*p7#;>wp+Iay{US{W9-U_>G@| znT0Mk6Jy1Cn^BV;4D?JzNA2&pt_oK$ojY0-=POp#o4kaS-4Ue1$34;a8i`ZK0SZ3>O!% zXKIf%HQ&M88M?Qwc3YB1Dnv(3V<7_UXv4sPhX6`B-lVKhkEJlSQEen|`0@z|sGQX5 zceTc^%x6NrMwVqQ+3;K^oU->SZUm)3ScgYP6$ZXE?F0YI_ts#K)*R=EOW%;H&(h#> zkxXm=`)BP9ji?{V_^bLKl}oOcS?fqYE{%E;{g%E0Vo`_~u36OQP)eUpF*x~fdQmnxTY(zJ2C_-#RXH9*OzG{Sc-y&=X4mqm1U!iv-gkt0!dpcX*Y}K zAD^b8q+~$FY7VlowXxy0Fe2Hc+LcFYV0On3Vw< zvYyiCBqbx$b%`CsD1KA85hpvB*pRAhIpj~iZ7cuo6&X2G&1I$u9gt6Rt9v=wex$gH zMt>9hr=$9}u2+&|wh|nk+8m$1>?loh2`7IAnp=W7vr90J_ucEfie$l7s6R-MV{U;r z{J^<4`|{NOfbOh}*8ili+*8c|Vk2_t*%LLbO1G?c$Z*k3MJ5J|r}8c?E>aR+P#ARK zX*ILOD3W74FuSxFeuPx4lco;uKYcr%l~Vt`nP=g>l=)GjjeasG4;vz&L`2htf%FqvL2? zSRxS?AD7v(=e2~fif5D%|IR+u+I+a%MOoU~tuv3291fCOUq6lep6lyc33hLQL)my1 z!7YKWB!GqbKi_sRtsZ!1cip=;?1FQdf~=C)*N7xa+xl}$ProCpA5AIds|vHJipMFW zNXzukM+wpqKmkTt4yfQJmYDNeCwGcGno)#)8aqt}r?~UpIA0{w`WJlvXY43bS*(V2 zE(|fLw%{+46BJZt>1Cx`Jp}4p4rK3#&$!4gpuPOO$ihz!L+T&{dqT6V= zZI~!8v6iJy|L~4iB0w1^373h1xGj0^q=Zo@rLmN>>HEY2nD8QSIbT9R9R{+-mqvra z)K@^&sHmv0hAolj!|Q(s*YR}Ni5VE}c#6m+=3Cj?LZKaYaB|g4iEr|V9tz{a1r%`C zy9a_KDZJyha^J-e2-$b>9w)BLM~=z+M-dliat0-xiTlfUd8vnx1Y%|bhr_w{ATB8u zs|AfD(dud5wVH@0ThhSz^2^F%PJPvpz2bmxqyFL0hxsezCZqjsN9F;Y*J}}#|1SaIY zoa(`RCPRkNMONmdAXFj2AkrkPi>zDHz3lBb%LS&pO_kCp*+jy;f&FNt@iFtfO2n=l zw}V_`%1uGx;$YW$D&1EW}lXQXH-US>-a4?JBz)@b#y3 zYIKQY0W;XqZy8&^6*Kh_GRLn9hw;*zOM4}c4b@A7wU42g(n4H3&T>?C-Lerg>N>Rz zkNLgc?|B5?n|F;&S+pm_QeP!A&E94NNLcsDa?OPao8C$3Yx(n^J|25Z^sCKmK1%Ll z!u`KA_UZ-i0HM)s^b=inQ>Ql-LS*JnOz8eiR*NQy=_w9W%nx9LK@dy!GGk!%eC8w8 ze;}TH`p5s9;;y=&83<__)_?lca^h9~js&9c9Zt`jlaw2c_495et*@`{QD0$0n|3wl zLOPDbE7+=7kUBh}v;l40fj@@m#nF?rUV+U&b%HF3au3xI2vfBJ#VqHDwvV7_gwjt* zX?MvlHgNHPdxC7IPEVwY6n(yaXIAyu(0}=3@e$OLZiGGP?h!z`uRSe%q^@qd3Hq51 z)W4wj5aW?C*E%E>T^)Aqa+}g{VFKF1BSs#!%=bzD!Gj>T^qrjF|CtL=I6gI1P*hYD zdeox9i;Wos9zZpUIj7msJi88KVJp0|1+WQoI@NA(?-l2N{yF5e>Z&tD@)dZl_G9D0 zLR;JYpp)7*(L>8*W^oU%{biNihYZj*Y|{ox<(AuEZ-NQphgP5}Ro+hp)CJ)Lg zh+qJTd4+}V23Oz6;*LyD)09}bWDVaeL-||GH?ugKaGdf_^CM**f*0U4tQ;Jv`wyQ$ zZOmNAZ$I%JghSapB+IC*1b}>q9>#1#mE|l8jF&YeGLg8NITeHzmvN0);p_q-=irVv zv|=A@$XKf?D}iFzOqBGQ)#70W0b^C;u)?`~^NL^35Xyj9fz@dTfxwk^FW?x!p<}|; z)y_XK9|Mz zfcn%gM11zu^9x{IV5Cgosq5SDP0&VQFH5Tlm>X-wo_~)|to|%d1&Wh!A4QlNl{e+B z@b+C{{pWPmAFR|QVghoMl(=h)sWFxg{*LtNE(%v&IDH-DZeuB3d1VO@V zqa;^(Zf`q~c}wm6F(wO3T-Qd#gbCC}tU5kC9-SLj0j0l7(go^AzzSTPvY8Ulp7ruISN12zzs1hH$UIkN`^x2hB5HTv0E`5`h%-2I08`nXozbPI~* zaBnInaNZbsFY1%!>o+LcI_H#AR;CWF4q0QQSvI+w8GfoJMa`WWawQT9e5D4V@gc=1 z!gb#Lem|G8eo5#kGjPQea)_Y0)_#fPYA^=RkB6eX&(`YBrcB7fmZCk$vy)tEv$B{W z>XD5F2r{8Sx|GUflF?Xt6_YfDo+q>DYb^TYL5mM!qhCO3&q4ead;p`I_?pa+AJC_itdjO9%2 zTq9R{c>w&{Rx&Zy7-4L(V|KLTU9YZn2m3O$+aipW$ciCrHo2Fuc$A9R>Rvz00DmL> ziaIRAi(ttsxhc@BQk&t(yl01Hu&<9u9iv%4t}}oLIyu(qds2Zv=HBIWF+{rZ436^Z zDaIWu&O$FJMzHF85u29a!LD+e;mqnF6n?~C*Af{f=-uUXwVv8c`IfbbZ_YN158C_M zmwsXN_+ER@Z9~uq5DxlJsDVvydQh@;j}r-$=T*@HhS)ebDlltuF~0!ZuRk?a=)Gw| zH5Y*#Wl;N>@i`&eL4*y2(+DTXq98IAkCkd(X;HS-5~vG)w}NyAB^V?+QeIPT|HQNy zYuv=lh6b^WuD!>rhFS)Xq^#%7;{Ng9K42>x_Y-r3+Q&+q3gAhqoVP?L*6%mYI=-zZ zdB>WTcPGg%0Kq&mG?dAqR|!o9cl|V80jYr}v~6=vR&C)lpmHVruGRp(I5$@ggrO8$ zG)NEwiu|oFw09G1o|INsUG3&G;XcxYrw$z1KD6L|mt)6IMG9LQHIPZ5)RvspsWxeuFh#<7RN*)L!+?!#DU7GQXJC#L~Mh7~ebKb7!G7u_wr_)^(Ih zgGo%W^vWoIpx?R+dzM(}{o^O&?1O)EUm=utW^6I_kCN)X*Zry1iPVI=Bg!dq%K%rC z>aI=%3%C0&pU4-Hq)wK9BzM3`P=T8zyb<%K#jD%>;cWnW+jV=&o$s@u17Ki4qoaqU z6`xGicuzs-Q8PD9bD&ljZm@7R!X9s7q7D6&!31@YC{l$%7Nv`+V)X(LZv>$jQcB*E#sS*R(g0DzW(Fe!3sjcrPN(L$J1neb7FbvCdZeqG91hG9g3EulSLcSykl4*Yl}d978w$ z>WI4DWMLy4`>n3_QJ?h*Rj!LZC)Eh?{yYJnGvvqDD;hlLjWO0027u~Jd*k7B1eo3U zXMJPmC%wNy9Th}y$EJIJe!i`~Q|`C9&t&?U3L{&&ovF#vjIVALzVA9$)uLHNN<&|l z+}zyM!)>pGeADgvb##j4_|Db8gp}(Iiz~)#nMtvy9I7g0Giz%naTO!nCI2q!GovEg zKt%*3va)|(1vz1;m)1*F<(&1J=fzO*L}4+Dv%@O`+aedsg>?g{HD&0$9(nj}^AiwY zA%mLqh1j?$3KJoue0UMP3~)7zaplaX-SoTqkFY51UhDht{0l?@$l>#?-ye(PLBnY{ z+v4iaEvI|X7rC;|*Vl;rGQ5nJaPjO;PJOnjN?$qpd{EdXKxd$Jf%9wYFAag3U1Rdj zWx}2_-%0AspB0)3x|1SRnY^pT9-x2JR5s*fS613i;u(0CWefj0TH=eoO(QGzZZQINr%Wq+Q2v6VyT13r115cLk& z1%#9#4~N-yD#9*?e-HTYG2oxl$4>&4ez4l{!c#+ppc?q!ukZi8ChPC7CG?@=^#A){ zFcj?n-z)MiOd*fX96coH`@2{%^5K7f=lVDPI}r~N%uivRQuN;yJMdllMfeaGTlm|Q zbmB-gn6b|L?*hL8Skrv#EyC;rTF?VtREpXx)tb)|SC1S6Ue)yao@=Uz{jQbKJV5G7CElcqbO zCAP9FmUoApzgO_=+k~aheK}2XS>g#TRLE<~1NoMIQJy@cG)vutERmsZ!N6CwqTB z!BmLSK%DYT0(@>U2HUnG1JMsnI_fv*XD&>*rO@_^)k)FYd#JBW$|NB1a;!#Lr`^cO;Eot zkF~$jp^NFg(_KYY#-)P(y>&ko)&aRLwpb3*OOQFiCI~v2IF-`;5eBe^8`ior71<{? zio>#_N_!t`{e`;9*^P=5atL5&Ns(b~gp`mcuPdRzOv}drDdcQdryW>y^qYN1LWoDw zX3>1Pk3!-KPvSDH9jDLdCi?i>E@ydikR|zJZYb9?ZV5sOJH^&ov!iX~QY1T=s#C+V zY-Ul*9f_0a`xH(h!EQL|L7#C4rTvP4ks(=sTc90v?Nwr4J#a?kqJLbB1#ZVMeRpu_ z)EPs$ftq1bbX(MRoH>+o$BpHw>!Beyip$if|4i1>a~gRDi|QJf9E2FoX(*^GOFd%! zA%^JV6E_M5a+`z^Jf^Kf($ZcdCK0a2+%3_su7nyKk0oqu{8-ux+US%xGc9G}xScAH z-`ldk3ace50th5rVPlBG3z13R>k=l30n@P3iP$QvfU36Zz%-*&(6OKaxeW#-jB=?o zT6H^n&u7?S;N==AFLpqR8r(#*>xOAGAxa6icl2Ej8k{-eaIjrsvSKHCUZ|QN-CC??jTS!GE|dI!}w*! z8kB03B)+bR4P6|&b(bIs24f4ww8S)jq3eTz?DGZeC8a}m#TX`AIZ5u>vZ8%w6Zw0} zb*Y6+SpET<8$>bL=NL+6sUrki8n}3k&JIsg&=4iuq*!))yZ0g_?nBHPYv~`6zv~n? zEdmo%c&*#=Vh=pZSuluj>p~6aNK&q3rLTNCJVl|eW*Di}%OMgZOzImjmS9(yi~Smp z&@cNnPUM9zKP4>FVV7ImKO~Yx@A`RGW3PAX@d2h~f59DYl*q?mJFRs4$;x^SQpu4w z2LBmj90Jd~fnQ+ng_E5-l{_9{DeHRTCoS%BAMmqb)>WjfA}QH6EOfjZK(RTVHkS7g z0q$xceR18zZLx)19(UT+>=Egz6>RMSyP@ zQK_yrKMxfngt_JBrJq=YoJL?B0<2((vo|!9isX#kY$i8F?gDWkT$G`PSfD16_4&Q> z`N9=|5%v2|0+=gijC2A%&(U*e7wa+d$rhQ#w59+tiRa#=2BF)S!StBFAqVu7|(5HuXt=yL= z{~%fRLrjU`r>~Rd{Rg%6Y*=wms}AJ^J;$;uh6#o=w`*|&%M_^iZkkAS+FRz}O5PwQ zVUuEJ7I7WBm&iq-yxMR{Q51%QzMInZ?X)892Tr1*g&XT)(CBdF1W0$D{`*&weJQU@y=<{ zhO1tqwnC$84@HF0YToEaTf>iEurnTojTX11O+I-)TgaNC9ITGG%ds7fFE^0PM_|!J zCUI1!Gf02?F^4ZbStJ8LF=XdVhtzw9F57j|kA9&suRtuTMw-Bm@Ozu1}S zUrPDp&D2*Wn4Fww#@UX`!WM6lkV=j`rf!|z3@`l)@xCIuhA#?mqO0uR_J>|4U%y6= zS$8J&zJPIF*bXfK_JulMx2S?E(2;3f|FeDNj4xg@c(B{aJE$#RX0)!=@=GWy-vI~B zMNyjHLJ^9=ZxlpSy49hS+`!JD-+52>0Zn?Xn8<*MJLRpE)RutsSt7XAh28DMJUy21 z_-h4Oa_NW%EjgS&3Cn+Qizr`i(rw3?ds3sJ{p7}QX(LKNsku>(CWf?v2|c(Ek8 z#NQVzuYKOq`GXMOPqS#Mi^-+Op6rAHgxgaq5sI=*3Uun(Y+acb^>~Sv+T+8JSXq$Np$+FhXyL*&he##SXIW7a~lO$ zo*c_-*S~JK)Uz)b`%%rv@EXSbEvb*@{<*&ZUY&XNn<~DGdf9qXj93;Oj^4eS%ouQCwRb#yS9Vb;+;J zawg>`symn%BlL$q1zu;}LXZb*xhQ_tr&1fHmYMuj;cV?4QcaM~_)-32iMW0>uc_>^ z-O9z-$^hbL24;k|O8pnM1q%0PW8%w+>JL{#*c=|gV1oboZdVIv7 zkN%@Vx0;u6Lzozaf&xNv|HpPu6pX9aO!o!xT+V=|<5n$r@xeZ$2Z4_C@`h`&`(;5N zJ`!SBi^XzaYXUhqnZhDSsSiADc22t2p6TssU`r<%_Y^0pFrhJ52=kYi+NiBIcTrep~p{LDR6xNci$B3I=W;j1jxtrLp5% zEnohfM|MRUVr1fM38idT7l6r^XZs54C$yDHxJB!o=Nk39-evCFjzf2gjl|DJ>^_ZM zy-xj|{bOlviK=P;^P$lErG(_fp(hT-lN%$QA=Gu%0nf=F-f@5MU~P{`0EtGj?wgYf6#%pO}i0-2i?q+DN9&nc1A_Q>qH^+edb$E#HY!Yfu=ukF%FtSk~$nKXlwxf~|*tcc-DO{XgMZ-1JIC3>%cwHP@@ZN80swE69c z^xgfBj@?Tp^d^r!nl zas~4DvDYTPF;iE0O6K*TUs&|$_@^7N(K&Nj67MZHs2Dt!Wsn2&Ta|N^E`5jW!Ijc* zkaPIVNtb}OxZ!AuDk<(=28M^Z^~jLxjFr^lMdev{&_sP>|5?>kS7xa0V^m{fWN1#P z;O(ax)p2+jl!0q$sLy8Ts1IsBGb-ZV)aYyJ+peV^&$S4?bb3N_y%?~$BG0KNZ$_8_ zK0f1Ftk%G@3C=zI>mdIjN8Jasx$Uo)6&O9%lSL7k#av9&QSQDOI$wEV#4*tkHLHs( zyZcRz8ab<(Mzj9rA%2G|sBf=JtKF5reL2v0*?EOVd{cltx^#sAEfC6p&%7?3N;Pi3 zJnPSwg*MOjWOlJ8Djdr6*7si zMLKcS^g0uwp1=3WAcbDaNd2{`)@Kmq5IBz@a5nOZNGL@N0kLd3Pvk%252~{{ygs%G zzZpD#Q*PLy7#U{AF2eiA53X?TGBU&9z^PB0sT;KbCA(9&S?!kDQx%(1Ht$(#b1G>& zSUi$yAp1CQ`t_yO`9&d#&{&@h=I^TRIJ?e^vS+$6z8i_J5aRI#(;98{zC>OpO`FVmP3HxB}OUT8@ZzT;=s;mMxL zM1pf9Vn6I3Kw$nC5b|7y^9MAGe|c4RHnN4OQvandy8?uH1Ddl>IHlD2+M=6xI%TO~ zv!44qb^4^U@e0QTcU?qiChWnz4Z+J_Y&ORzEZg-TU8V|#CA=>q8DM9H2whqgh>uEqqY=nEu%9q5u(HBVue0|M*auL zeC>O@qsI5lU6J5zo9kK_za01EI*LJuB3*v6BSrpgk~X$KHRzb=5{=1`7X6p{d}`o? ztnRdgyYFL`5L`i|9?d6i9GW%D6lb2Ox7X`<4<&TH!Z z)DLNV^36)G4tFX1)rn1bb)wu!+NJNWU@w{i2}^d7M2ODBd3y-b)Gh4L<7&T8!7M-U zHaoi&U*`y(I;t${Kkb>}zbidh`Y5q1v{O*{Mt4RFVdlf3l+CyOm7b6lThC6M)FmuY z{Raav#TY5EKVJNN^lVQ~ZXi+5G43+l4)YV8Vvi!s=mqLFP^2;h^hY;NTqk;=$ad?u zzkbo5V*8VCX@to}{^vb7^5?9<_C-v>)67uL7JJWmR|ghIyEfsn6~e|2pNV;FcC)B%VT4QFZu-FZu~3T3Zs zbVCyLo#k>h{7!@{#a%^`4YIe&;iFc1cK%jTPzM1h>6RO(T;VTYGk%bdw2^(_o<&pD zLv|raGfD`&uG=3oZ02xW$oko}$ix1sjR=Hj3A=wOphzOh0g_UD%#swgq1uUx=y^XlXKDx)Xf|O)xhwWZ1!UMk zS({hBzDgVRRr;Tskr#)*4k5m1%sR0kKF$Kf=i zAK*OY6E3;NB9nw_gLkGB?RqZ$-MULVgy+_Ig;6QikwOd)$wxo9es?EoJ1ag%%S@eE z&qt8Yh0G! z#>D-yTkGl<0yW6y|1~2voAoG*jn0J`$B#7j*+lpH9m9_{RF`>xEMCf$d8OQ7xmgOaj_eO<9M`g5uO=qvNy z`nTl9mUP73Uz9JA7x`bWKJx#45csw4{lCNT-ydZ8zaRY9ApfV#Gs=yQwrqELskYZ~ zhxeIO`kwGvc4jgDFOvUNB|_y6xa-sFAGdA(luecji5-q&^A*!Clm-DkgDR^Q1R zY;I54tS^Wqx6S+3>+Zis4i-h64EUW!ssulwKD*wj|5-(ZTKib{Ugx1$?3`gUOE10A zN6b$ae8!%Q`&8!r`Nxj%IO7gYn`Q7X-qXiEO?Y5Q&G5gs*|_XJ=d9qG zaQ~LKaQ9(=u>7xPYZ5}_O^R2&uCbwDQnc&gLkK4fo4&82ZWW*}RlgAG8=zeHyKKB( z&&Gc`vTS=n*h9G!38H-C>cREPrU`(cP!s<9Irk{Q0SC`9Faewxye`??0GD*;yA_(b zNj`UI5RjZE{u`PDbGN5QK32OiTt6kf!n9&kdCj)Z@aS_p|Gs0=NRmo-7r4g;B?luwE1a!D4a%8>Sf`TU=$F)VHe-|!@dT0^Q zs=lllLY*%BL=g?bB>G*!IC|kDs(M|wDL@;*%z)mF;L{`5fl8f!UiYF>xBY);^r!QT zngp##3*g;ADy-%eytCf_7Qt_;^s{OF7=7)5ZEA(>gA!0bG~^^F+~o8ac4G+&IfGM-R8k~!m~K3T!-SIb62p$Plq^dBct%DFiD`ELbh16%y$p^a2N3zn z^cZ(A4qivrATDMzWG@SKc-&{-5{ci!3eiXPd1X96y&*7rvziUcCsO|1@0TInbVM=h zWH5ayv-zRm!V{Z{SC_i6W=n*smNk&#K=5mj?wB^56TOs9*gtp5#XAh|7O= zhnDy*fn*o%oC&dekx*cTd~Mi<2e?G20XYl)Clm zOyJRzx>pFEq3$$}>3%H^{ug54Q^5Z~c_)<#+z5(pdwC3*Wd;6@+24%iKTj*$EZJ## zR^FrEoJCxK^Kgl;;33wV_~^4MgnwqETM!gFy2fug4}Tfi^N2?O*`MfsRI`XOUD{R;(%+hHwEss*H? zwB^WW<>4+#dwAZADD1P7ZYCbW*>P7O6b|3Z6CavDxh&5^;`#vUaD(p!D`NMQkmz2- z*-={%s>pSLze0n0ppExq5v=|~rbF>U#B`=f$O;K26*<)i0OC^R%LS@tf<@0(nzp`DuUx06=vWEUM7%f{0Ob zX22$(a|*HzaSUOjCo>~t^LNP{TTbi)V6lAa2V@#$lB<1j*~l0`VJ$%QdTsWDT-MAf zu(qq}072@zAsatHd=!_qBD639dHLzTZZoO!7K?45zBOPZ-ZmFg&>+TTXJ1RfVuhMb z^OQ5yLz!1YP#WC|VmL>7B&@ISC8}tcK_Vimy7&^Jt$m)i>ym_(^G3LT?AF4YqLIZ* zTWx4Bh>tC$*P;lgW~Tc&wsY>Hq#d^ z8HW&`Ws#OuP%OIQz&`&R>K{cGcF4K{S%>`9mn4kf+LkFgTF66K8s96b-Nes&mx7 zGS=CYxSkS48mES8sCbM>CrDa?wzi#0^-_B71L=o3Ovck3*6{Mm zZyr>b!Sj2<)xcAJXz%UGEKWVb#S)F2N3z54RXD2qqQ*UTOt>A^%O(0krJK&&&(D^)+Q>*M*ANO1;hz%5+^{b);5t>#cO-AY z6~7SQ4o{~Rq$=yUa2dQa*s{pXU*Mz1b!+Rno380Q2b)$C z{>}T5hhsi=8%tk`VSgtLv|C3>sDGFu?e1f|9Ai}_AD7MVc&bGM8Gu>??sj487`ioa zng6^Us6%?8qj#_ZOvmx&#w=!L4~@dh<`B1w*1D3pX3`RUC^7vb@DJJ)(*Q6@1#O9j z1t<)6H-hP!rU@(x%GWdfD4#*(%l#GSo-a84C9bMTXxQeB!EWB2rgMIka36ruCnLdx zqAP+xK+|-=4xOW?5h9=JRH0==y`N;yT?2nge(Q~KXhWfo5q2K5l2lx|@Ub*AT$={5 zsUaN0w&iPmJ?|X37JWVN?qZXj{+xd4qX3a2F~H=oZ5*Q^o9|xnXKPof*PgOr|2@rD zzB4pJh zdi^fu_33$k1wbTRHukm9Z@`pPXInbk=`=*IUO-MMp>vBBDiI})=98p8oebLSV0O0> z#S<uN@~pHl+enar*S z%-lgPKMRbdLy;91L)s!)oc#bM|LWfDAgU^}E83$FG{( zIhkBL;b+1{;^I4STR;2qx*dvhmY;pi(cV~4c}I@(F_(!kKSb1A`k*vsPBaazxO{g* zzO}Gs@hm_9%P8D~@SiQ|NE=+b<)Qa64*kc8CyCMS+YdZMl(*ET5@p@f1!TA1up=6< zy7R6j-gP=}jS_dcH-8TgG2VAkzJ!z)fxOaW+rL^ig(Yc>LqtiqeT=Amsf(6V`}5Ss z478E&`Cyz{JfoV4%$U~+Y%X=1bpxuc7O2oaJH3O0=dSI*48ENFuSGs4)d_%_+3{e^ z#xUkUbU9#KsG}NSRPOwUm6k7Z{1(B^DXX8yK=r(=p*>_>7Go_Ni}?6VDdsrBAV)oZ zEZ$)rK5PA8$4IDwoI6*4{MiVI4$a;7J(>3qhm}UHqeha%(3y4+C{iHKwdoYraS$~T~LG9$DLJ~|mB z0j5hrgna+~`X`t=&;6r=`cm-iyI02eb~ z#c%yn1Q%hKj}Ylrk2+rxb^>{}^lbnvJxDUQ1@W&YAIx+_zeOx~OVp<}Sl#DBce*_v zJNU4DG=>a0A)B%15?v`AgFQC;Ol>5H|BStN%ul)pu2{YUsDId?*PkhHEQLNpzZzo;jHAb zxNU%-TMOsg)Xd^O5hA~Q?ou&l?bOKtpeel?ZNx)mJtM%~n$6~x#+^A{^2eXi7ws?y zb^hh>p>Kk=6j^E_9s;Dl+HLlU(Rqi9EfD9JM_T<>^=vBgYknM?fFk;3lh|AdM3_B~3Oiv=oYYntg6L-3U?u5YfOE zk8CgT!OM6#%OFE4@BNMEMBAz9k9oDlTdXyiP_gEpqqqvtIzCLDQ?29(z<-_H^RVQA zl@&&~0-bEwa7sRKUXlTO64uZ^UN(D7bOl^G#ZArZ$wrT`wzKZI|}n&P-@Q@TEKE(mtTaM!s;Mt{bwcv8a8Qi6celx^%+pQu6c0pddd1FTF-4LXNP3NAv zcj_E+YRS)d4t+dx=NWU&TBb1n!@Hb9_aLmMx1P|N&5)Wc$0pfQ86Xkkel^(e-P33rp}tbp{MgXo+i+BMz9D*N?f=__HR8$OdYWu!}M#~E_L?TWm3mjI#- zH(@$vIj#$$*UyVc$$eppsYV=F@;PI39-o^fcAwLbzKI}=B}T{x2nhq-DY|hsG`~4> z8Y=iPkq{tnkDp~%Xdw>unG?S%q;u~)h0beDl*>UDy?Tf7J9xwi8S)3&Ktt(8>3Xui z!gVv$ebdD>r!UaZCaOivN0^!v4+4p1tU6fT-BNU)6OEne@FctCS4SttlK*8Y1I669 z7;IdrNP~mPc#a1UKo0olQ*j)A+9jQH#G=pFqh9ENJ)JGmz4y+I#%)%_HsmWzwD%`* zzlBPN*P-YiAaC|Hx!M^If^p1~NTUiB# zh9*x;JX6W&b8!~>&n^G_MJS>mO;Dq*p)sNe&ABu)ySn6pLqeJ`>zg|mA-aG<^RZ0m zT*aoE{}8h2HH4v8fa){`1D(bfb03$i9u%1L&o7s*R4lGSuN=4`miU6!e?I|BM$!G6 zFxRO23e-vOItinVZ6;R@YrRhDe}fEklg;^Fjl(j=buOsCDbQ=CgqcI>Gt`2TZkIws zq0TS&eOo%db6dHZNP;v!|C;1sH#Yeii*OqhgmTQcCJFhw|~DFwt!17 zedsm5US5-Sq;8&G|I^Z`i#}$kqMb8BNL}F1jCX5L3Ju7B6r? z%g^%#&|J0LVUvQYh6bhs-K1>mmO1O)%TLnYMmuR;pv%h2B0!!EU|Or&$S38NqFq+j zXOiedW)j{FNJ>6eBSt=tI*(;orWi$=nP=rYn{5^u%PHOV0G7VA78STIiB67C_83sq zpg>hoT|FJ`q(!8(pSl{VKLu;IQpn#K^+ZnJRHM@7AQPHzg(cOZ!!qp)@sx1KZ%; zbuS5(fe0Svb|=3Fm3iMuXg0q4&5<6=hh{wtOdZSYYRaWhE?cP~@V%*9BDOv=wK{|Q zR+Xc??2d@*xQawq-&onG-p~D!?Gc9!0beGGfMDPCD0&z+0z*0V&qIL-m?nM}e&!=X|kJpmTCWi9Z5F+_lXOvJb zhc$T)Hgyy1E-tTK%4QmyagWt+yTY4ItYL{_n=i{S3xqEu** zVf_;6d#Oj=nAS%Q(93%0TA@0n_Dv_KLixSUog{D*miUU^^i`I|)b>arbWVlkCHFI2 zVqr1mdROf14h1Xno~~4^EI+Ph?+JECDzVe75nLmml`3Vug)_S`Y|totO`Q84AA4_R zgQW7RIG!jE&5)w*kmKwm|Ao}7-a_S~h@s7zZ7Q2@TFL=+x1qeGjb(2k$_m&S6O7L6 zlox2*Csl-gQWw(RZ+q2_bBZZKUC2x&?Q3=kkZ#|we$e1G@~*Z{EF2u6?HGA``(jvl z{_An^lf;NkfTg8Ypv&*?-Ksmco~W$UL` z%b8DQ>ne>;D_oIy*GG)gsGYW1=B`3D*l3PkaEraSjg}NC|GCu$cL2s_(~$c@pJgvM zqV-ntdDhIT~@^9s#SOXm4*HTA7yC041i~TT4UsXJ2!Qab9?<4YNy3Oq{uM$I^1u z4L|c0a9v#GhFt>{9%y^*-==Bbenww9uNEQOL^NkSo}30YH8fEwB)nI=2pB7t$MGl7 z&h4u}@>Ce8=zFCdW*x$@S^Xj=glsN@G*BqLG*kp8MH42kz|40E73s+-V`BE<% zm1>AxM(+x@T8?Z}6KS*Uj7EVW0kYw;SCSp~kfZ$kzS9aEV#u~Q?&9{BZeDwT=?1|x z*sFEb%+93}Xd40T;XXn;z~?iRam%)s^n4>-WgM$^<{#*S{_xshm5Ag3& zHb-|AXz69|{lKiJq^Dm`<*&Hcy?}G7G=!a{Q;Ne}0TlIoQQF4jEm`BaKs^mFTtC}| zKz`FkI#SYJEx~P)3@ZX;wv?twphX)CBL7!~-k5J=;nN3xo26GuQ-oe)@E>S8Wfhfh z5HBVPSWvXFK#AhL-dE=(B1Bv(mMiwmz(k`qS@PokZKzScXBGKNP%Ao35-B< zn_|`Uts?%+Ol5KnnLOk$@ZL(o_&}=^DVYPNiuW>NwGpNgT5*~9?W;~AkGL{M1|HNn% zmX+~9#O`nfv$SdUy|0ykuk`dU7u;ZT%6>>pe_amrmOiU( zyxed?dQ^7071bc_=m$`5HSU*$lq6q)xvRmnQc=Cr%y76mWQZWV$t2s>lK$xFjb5mQ z@R$P&A#}Lgu~7B7w;PA#0t}H+0{nm(nNi~cW6%eoBMpYJ&xS?V*d76|uWYP>x7e4d z!7AY}?ny-*C!L&Dyp$gU_-Eqc#`e5?9^XOvd=Kv0+50ODHSH(uba}&d!$Fw$H=0q5-Ffm=( zoIM09Zttk>Q!ZP%H&RYjO4a&pq#8B9_W;&IjRNwq?vIvfX(@x1ZZ<38<`kudNap*g zc=z34-e{Q&&2nsNT7zF)@oAZ?j0{C1BctT)f}y2r*RDPLg@aVNp&~<)2~H}uY@qvM z2QLe&8gNqq)|r39GFtUOn2D(?8W+LuPJEr2S)<@R&*4?==Mz`1ry%@DGXKm32y>J? z{ECy!>^pE+8Y~#h*74XaXr8`djsXSZkU?G50pod7oS%O)Pfx;J>1AS~M)?JE@cyl= ztP~U!dX{Xj)Ya8NbF#r)JztgAH-oz8K>Re5d%O0~7)12NXBgp|fIcOyJ*n;xIXt>`OaO1TP4?zV?yocDt zTC$A=^!_tx<>T_Dmv4r-+yZjxkLUbV;bC=8aQ+B4HoY{s51OvL_@e`3z`~%SP@gz> z3uvZ4y!;_STVNAgLONb6<>3d>3QD^LP=i6_>2YfCO|VW}YT2{_c^Q|U9$)EVz(wNB zA#g~+E`gs5NAXOb9a%PGnbf@xv!2)6c+;_JWB@yq0Ubfh^D)6nz9A~tghmQO zdOM|=nQdjJ3Y;sx;I~8u-2Z+4E$QD(qwnYWD-h8KBCjTlQ1t>dwfS1nm;Q$JIG!JB zPjv2dDzZ+ngF56kvqOzx>owcY5d0jYPxfuH{gi9Pzkg&5%wPmVu&0GkF(DnI%Ei7y zA2zB&%*zWEBIw#k+o``4815~!fyfE`ctf2#PeNbY{8dJLye$Qk3>j)OHnIjx1;bJxlY)5qcIJ8rnQ< zWduSFaq-LKZ8la`ZjUJ@CMIWWIjkb|?J3_qpSdA`bC2#{xXElB501Ok<`qG7Z6Oj2 zw1%kHty)n*ApwZpj9E82z-~gX8O0}0KBo6+H_(DB1~vKs8c0-MTL4Da5H^FRNP0&z zwxv+<-m(HdgXv&?Q85vS@+*9}efrtKc`S-67hLx|k383z(qGGRJZyTmPmczTYQ!jA?8icaD z%7WJN@$o4kNk~piY@D-^3|zDoFh6tZ;{W?zoIo;IE0f)|>2eo8@FLl37sOVdBKYmM zNPr9f_Z0^~?;n8czu(5bfu?@Q2vk*Z|0gBs&ll8jsyAeMdWtv+5jWCv{th&-M*scF zbklYqZ2rv)2jWLb2biB?E(;G%k7IeE$|wX_Zd6VMMCI zI~Ji`#QCSR{qLPl)uJ^xLk&Ncw*)4!PP4pZHvwnAqMz_E5J~{3Nuc#xQpJ5pCSqja zcD@ck`_;?$nlFjRnfo~#^Fq?7AI~x5RNhZA+|J1zqc-{1h8srBEHJwcW>bT9E|?v| zCEi?lCW(`D93GtkcN;$W%!xgpXXANDgwF)^3eQCmIDpTYo<}MW63PCifWNhjwYYR_ z!;aN$iK5%v2MVil*%cm*ZF5y0LqtF1Je})%H%UXn;Du&@ z%Vj^~SL}X0x+4GHXO70`viJV3U%q;CBrfun<#X?vICBHp?mE|2ox+>r*m}bAp0)00 z5oZGh&dbt(uBOQb*b6MG0Xb`epKu9nINZRR**)T153zetA9tt;+fiX*Tp=PBe<)c; z5~rUOpd;!=eH-$MAYW+xDb&l*5W87(e+ts3p`=_N6z#QvgMkT0#%LM}#Tp44&X(a} zz4(sZql$N@A%@=O&YiYfQN_IWoN2nK@)0+*h!7M%GK4CWUnkfVZn__Ncxq#rqPlPB z(VS+6nCEZ0$xy`k zyIU<)>a-_&+d0X4u4*VXtg#d2@NA=>jG_>I&dp9qFS2AXegcW>SNC@B=K=;I5PA!Y z-a#wQJ95?5tAY#nP|Q;BA?LxFka0^Znbsi2U}gH7X;Zk!Gugzn(P6Tda7$u5+$xga zkfwE>8CQsW(33F=m%HBD(s_f%{0zb{PqSBQF+deiSQpvwb6M>A;W6xuEHTVkw;v(V zX7YoZ@1oLh5$yM?-&YF+x?tAA6{4GhcwPIsIVi7WD}d&D=VrN;?|>mF2LCPJA6qtSXK z0rdyrtFG&De~UZQ7?1ky9333%7SN%gOLi|Vk|4^g_-fP3eHA&S3)PR2iW->F@K!g3 zlcMFqWtOK0;ff`q+iz?y?lw3+@b0ySq6jXJHTB;F$h|xslXHy6)2?}UU*fvVcm(2B zGbc)hmJVSandzUw!@YNU@~+ct%?;Q${UM;KVBWu^koBhMP@eaZ*RMX05lD-BX1g84N`~6CS3Zq1&b?=%!j*xas zcxT~GcH|I(y#l!}>ou$9w#&L8_T~IC*Q27DAk!aeqmX+fkn;%1T!9J6n!`-4anX0? zF6s`W`PbK7*FFdmxX&rCK0cHlXt)w-uH@0s9EXSor9oLu89#MQB&=v_`8p;3@hUw( zpLVnu@M%sc4o>E!eByVVmJGw>Ef?aCHFHWFn?R6GmYZeg{P!m7$c{nY?5hON)HzWe z$VaJDw>Xp8Fo0m|4GWf_4tgs9aWmU%ZFAONJ*le&lGYJiSj8tnxeVD0sG_1Azg=&6^^|la5vX^eAQAbH)0Q*ze8JG9+X1-0r=->FPuaBdx(PQm zITDSg;|qGX4%m^~G*>nKOH-FS!UgyMulBn!;q`5WKXy_V#A+udgi8T5jHdisW*>0z2r@q_$DG8puJYi4!IR=Oyei2$% zUK$u2JM3IMmTP4s{#2wNO0TRh4nam#UK72WzdF5hk}1_S=636!Eyuf&FP|<8^rl-B zwkoprKZxbJinz&mvTLftJfW-uvTnlo^g~eF$4xED(c4oLR#clZ*#yOIGklg%COPJ~ z{GRlp!!fi(PcyPzrf4p7ESh_&{hhW056$>Sx*xej7bv`I*uzT571KQYiNk;k6)0$d zKX%mGJWSCaGivW!v0Fg%rVGbL4eETA*jpd}DfitX9iei23I%!tb$hGy z4Y3U2*eusKEr1x)x*Cp=w0`$ChW4kp5RX(Z{p6O=tz5DyRP)oM%I}({`<|*qJg)0+A)(j<$-CfFQ*S$ zgBKjvv1Ma6k>Q zdB1tfCTst|H-to>KTEwx_Q7X4n-65<$+Z<&Y^2T2OzoU0M-%S47_D{1(VSyl_F&DR&&16Szr$FF00zy)R}sf9vpt zORiApfo6v1Grwyi?Tc-XOjbC&-up+ZMo6)TDMejF{MfnESgqEXsix(%j&yFD8npvU z>sb%^I~i6>jMC$Xhc8{wD0Z1HnfNkwKUuo{X#e5Jhq(_YvMbBCgXXVSCbNv03vB-B*zj$>C?d zz{9kz?-#XD+?ugu^uoBg{JmP&@L)x|Grfi&GyE7lT*f0x+Lo{To_jq#I@q%yuWPh3 zI4OjA-B3!+A!a0+x$r=+edAE_BSIPnTq_G-l;(GGGWO@Y1}l(swJJ{asoKX~X6Y86 zf+1@=F~<@IO+o5w()}snw^@QI&RQwlSGmU8ME?F_Rz^9iY@yv|M%a;kzp&0mg1Jt; zJ@FMx88>sl*Ok)jpHp7bvQs&Q7mDX+O6BbKxpq6;Ki#nZ($9{F)k@)=@Z8S!EU0yS zG9{IKrdMSD72OM?=7DwNHG+b??{EWgrD4bffzlGkHoKX9X<6KQ$0>=lNy1-8q1k}Bh(Km#eSBxZe<<-tb4vH&W zrNEb0b5zbbvHo~DpmVXfCbVd}VuS<=T<@U5XItC`hPf|$)TIx+_?UTjGT6G*cy0nWN zIjwS$4F-_y4{c{P?;ouM_|j+Xb&1Sim|M5;@bF$tZ}%B21<`$|D$dS9@J$IVB zSUfw-!e?GRmHxC;h&I9&WyJ}b=-^G`?>{USd%9Xgbe^@PA1s}w{h$KN(@3Ff-E3E= z2jA)e%FWZe2!b>>M$HAM2pm$25W+E%n;=`>s)Ji682$3inmkkPO~Uzx%U-d`r3Q8t z8kJmWw2|vTX>L0Qy-`)ZMl!t1^;`a#=-rl$U$nuWRGI|3R{ExO+0kwYNg2?gc=wYp z%9d@wo~Rxf%Nz^CdegV7tQ(`NODT`%#~Dzt^sx4_+Lp>U-p#kU>N!(WIuw`isIM1r zCnwm>1l@cw7_wlN*1i%Ckm zNdy{X*jhhQFokPyU$i!EvU*-OOMOzHRR8YbHpSW8q|ZXEeP-?QOXVmZ^}cT{J{+r0 zTE5U5&Ru?El8iR8xclWeqW$ZoNS;7|&_E2x^T2T7<;{Q>EMBJrr+)YZMiptVWv>Jt z8gFTC6i+NK)v>?kVG0+_x&E?&zI$8K$?#nqe{GYlsX*7k3v)VSqh=2_Q~Pw&2H|av z^o$<_?Lw-dHoqt|V7^W^t5MHHok8J`?M)8ut@kxagbS2+?Om?o+yvzXnqOmB_WE^I zY3$vnz_g#G_^YJQYk-(ai%9u5Gp{dICWdCF9JW%Gz@|X~v=#l%21?4$^*4Pn^|ZH5 zhcNBqSfStmR+dA)VHDu0a@le2eS*@#V8bF&LCu`Z9syd<-E z4*X~%l2=MCN8oml!CC%%#ku8UYWA%4_`XlNNbmPp^JDV0%u+4(-jXH>kgt-9*!+iR!m4ry{q$!!Uin8Z_zErxrO@jDLOZ+C>t5_eM^D41c4%<8$E&eNcz2-kzuivmw zE$1P-Wv3^$-uA+9G<-Qm$Oo?~?wppxLsUC0Mw|$Dt@-|B;QlT!hPusi5c>0Cbg;YV zX?g)OZG;^bN9Sh*Fk*w!CfiLuTjLaW#QbN^5`;7s1vjfT%q0 zWa;MKe0$?K&dy186+xb{a&swuyG>8C%AM6bc_m{mva+6+MYj@)3xp(m8Ui^#{6UF- zJ>t#%!br?2nVY>;=T941wDnxM-P#8)YrM->M5D~PZ>4wI+4WV@mnw74OdG%Kc~)Lq z<2m7%sC5m=C?&67S<=zP_E^SSy*|PDO_RT-%v#wTjGJ;8mD6O%(0Z$@N;o5*PFu@< zR=ax2)v6EirOZ{4FwR`myVyOb)ciQpx8;O2*`6{NKGgJlT|WG6g1OkvSxdeoO~fkV zfE3>oMG_H`Q=jkbw8l8=5IqQ#7Th@YiO~&5e)ej>*bq|o)k*zbT(#!%^#jG#@(i1H z@&X)$T1Q_=d1^i&Dn!=#z#FxC$(6RU>_?&*ZF3(g9%FNF(FQW2>YT}-CfD8RUU1grsKqlfV@Ae(nC*6H>XqHa}ciVQ$qE$gMv$Bg-yFjo(WRF#f+@;yy5lA8#ym z*ZZ}yWWj(tO*D_SmeB<7R;gIuFc(k6<@y3Hk{)Qj+}w(konoMjs$~R1a^-&ppkmXs zp>TogqSn*HNmOZq3cPu{K+kf-FUm$;4?F?YkJL{h)P}6hCquwR_`FjLF2poSB5;Vw z-yZyT)iSjuN; zZ};BahX-|)%1Ww%MaqxlvT@cHm)p+s7ph;x|M_W2WA9DJ_U*iqODOH*eK85J;Lmc# zP?7xC>+&cN_jw}?_a7?*ynpVtX>;nHs?Rof?nyZ*k3Qo+T(RCxdfqZe#PtIvhssOd zY|vb|!@Y2K3(^0+SG+hVlxGhQR@Pz|C1CzU+*QJM%}MGnJ1==sGlCmubKl?xG*9@~ zvk~zEl!7{L!2ujkl&SSdmHr!s#zNZ4zrTsNx%~HqNSxN+&6qPu-to>_KH>_24mxX0=2 zmM>g<`4O9`k<-p9{3&)v(-^x?WzHiKJjHVB^_{}42V|@@QY}Jes;FantM`Fk*Z3sG zf3_F!-)cLEWIP=T+YAtl0cRz2-cWEB5`XDJjB|pWW_skL00dK_Bc%x?|ks5g|vfexAn;##U=794`C8 zNBK|25<)VBc3U{J#!w$dUOr^t*4Z0JZ{FR$_RnxW+~YhrY2s}4z)Y=}JwtZ+s*4$D zhwH)_S0D}}I>vb{I5=bq9Ut~xZ}C1}L9yLI$na`y5~z_x`{qwZqifG+=y=#%H%9Fe zH#%~N@JYf>whH8dW3)gw`>J@zB2P|uC1CP0l4Q=#qq)gtZ*f`~h;46X_1fMSR6vvK=quuHj zhuvn9PWSEmaL_=t;FY<;F`=hT4Z+X#3tFy;1!!YwvkyNuSPxZZNVRj9e)^-G0%Eq? z6qJHkNUJ#I2vc}&7fhE7&36OTKtS(&Nr1m({eiDcV^8DVFQP}_{6%K5n>(v$Pr~Ho zxic;SIbbT+fhiKfUT)tuldv{%EOFd={z%Lb0(1i%)B9~|oO}>L`uV7W(f))wGS(&m z7L;Xo9>nZdPb?9{%Fx|>hgY?-^u)}z_04%T#R!Ox&TkS6zdjtwPZUa9Hfc;^TdJYY zii@|mUfrry8?;`F93(1#J%%UAxA-K;e(R@s(&MQw=NCutv1=UlPGA8G4>(>p| zGdf4JiR>jC5T3;$v0m3#nAvJS&Y@M%1K5b+PhRBbYk6z>Zk6gZ-yQ(5V3dbnV} z(uT?{>F<)4+l!3`m22JT5;3NvUv2g@Xl**ym>%Ys|a9SiMjray-i3Ig;1VXZ-T$d=Rm zf=J6rR{9nuUkuULJTQSr_@G|cyt=6RTYo%g7m&DmLHk$)Py7w7{hfi`3Dc8CW~S{t zm3#EzH!Yo#WNd5bc3N+nFa4p4&Gw>1SJAKOcucvx4)rZ|bzTAA1!Jp8pS`@?3Kq~c zGkIFOM(oAfs(@qgr&kuKE&mKDr5)@ZSyvCN@ZB?LO_LZ|ZFs)+{RS;P;>MG4iac7N z{06DsT3Oe+(9X|4tmWDzOH%rTJ^Jy z+vyi8Dbzyk%WX${q4Wuufe|9SvLrNmfJwBYQ&lmN5Jtr%ksA)t3z=FY>zRR{D=gQ4 z?zB&kzaCEl`8b>>4$!X~8A7L6Pk;M1roXkRU)aT^Eh}>Rk_dv}nXP@#jnd*_)xzdk zTf2;;`-!}GQQ{cW>{D8V;pRARhikJu--_Z5?eAIXB|(c#tQwEoc~2@r=0IoK@{X?6 zz{KwEU_(2HS098~%_~QnJ^=1Wy#C2?tXu0o1auWn>lzYRcc0jUZf^49+T>SR*&3-t zTxl}!RZEncQ& zt7R9>vp0dcxr(Tg^v0s22h0v5Ml6&28a!niGL=Dl znf-7-HN7N@NkZ#ESdFGz(uZ#FiQP(ViPCKA3*cdF42c=1hrsK6x#I%27%>=M|bQC3(e<0WtmkI%Vc1 zRcFNx`Ka!0j0m;s?d#~SCyEFZ{rn7h@}xm|nBFOCs@ULF@At4gF;rVB+gC~aE=89* zpb9<_^c>1qv86lL8_=}6GIoyg<>LLAE79FF3hr}RzY1OVo&+Z3e!1?upnsLH>gvl~ zg84v30hfUc6aMUgTPK$WI?C2P$0!OYZ`7ncRp+@(#U6E#+u!=Q2T0oQ9M1%v0hWDD z%f>dx8t#AI&^lRp#+oX+95$4wg|<#4!Y4B_SqkLv;pm5EO5nt9bM@WF5D6z-B_XQb z2sH!`0bII3Myi-wYIhLvoN}tG8T+FS$8mg6`@zU}@ZFf0W}Ihd)_&zW`{+(+Y3#Y& z_Vqpi7o{k7i-DD1BB<2loGL4@k`vC?e)Wh67rXKg=qVeB!kzxgI0*8p81DsD@gvSezCkGRNI?HGhwLG0SO9OhGDkd&Td6W$ko(yl^ICul#iNLz#6Nz{oMURa}{VH<4wg!l#FmN`31!1w3(gHGr!SKP& zs)ewuZo6BpBG2@PP^H@PtfLIjmr@KizBm<}VQ%39&a=x}czBrlU^0pTW#Y4E;lXht z=$Zq|#xjBtRJOcxlZ3o_qa1Z;0VR@2TH3qQ417FPW35fxJN|1E zjRFH1(a;>Al8ftQ;DAsiGkp6&hE!Rs5^!AqI$Tze%zHpUt%8CXUXO;h>|r+)sS*tn zD9`1+kM#;ByGDp7$?41i&a(uzWU@~|@hTxA5!fx8E)%%8qi0uWHujl;(}zMlA=c$t zf!W+|{MN`PDo!IW3Y|)rN(zSd5Jl4aL-i=HlZ|(|)U-Bg&e) zTVykWK@e&)A}TTv^b0rkepXc({>5)1*VL)A&}ub2BUI@MWnGa#JqehLILt+;edG9< zruyKk_{bi$7XNLDwU)ecADs9eubF5RonQ>-(e-h!inQpmbk2%yRde)t{TuI~L?#dn zZ{yUvBnDWpGU=G7N>Nx)jsfmfgk9N2YJpQ3!Jp1&LEyn@*yeCCtinjj(em}pjZm1C zYV7bw#=6XJ$m7Sa%zu^~P@zu~Yt^V5BM7EoC#;F&G8fltlH8-jCG-3x{W)#w{N+wi zuSv#ZT=_|7aPV}&1==gC2iDi-Tr6iOvA9ljz!Y{!8l{#*Gtr;z{9>QyQT9`FrbF~m@YbswkxvNS(n@ABSjN-gWgef7a*ln6l1ubZdu^@(J)(w$`F^c|K<~ z@!#Nf)GfE`%zd}h+Kzi>_hD@JuD($w+nA8m)<$vJ?_W?6*a}$nF6X^fu{jq_bhq+P zxXn2)SP-9uH`L~q=$>1ayHp&12d zyH-q$4V1hzfg=y)wX}}B1ft=HGcI2$j<#TB&E4F`4&#R=S>?A^T((QKHdk>F(wk@h zUEes$d!bwBP041T8l3qU3J3hYfJ@i4E9hTk#?Ie8q3k9x=PFTz~* z(B}8EfTYP3I4Z1*YO!Q7x7iBnH}v7a%VJ1Dv<51X{Fqd?pAN2jj7<#Hj7XFUUA8_- zSIM(N2{_l4m_;Luhlq#vbFWUf39Pg%6^+F#WK|wgP!&>KsbF;WogRJ2>5SfPt%+6Z zWkhrRd)hph#;`^0$zqr!Tl&8!`ijDRjkeg8QzG%8sKI0< zm6Zt=jXI>A#6imZU{~|_*Fv@aAJX1BF3R?a z8(jlYP_Yn10fUqjP)be6zv7U4tfpjGgAYHA=tnAoWMHq8>d zzcD(GM{HaL&AX2rlTkL(%GsJ~n$J|eY;nnI3oMU!X;?KOuMMOfEeJEqE@dDST9bWs z^bBe#A=aWVB3diDr>8Rxs&wHMnEvNZuhqm7OL>fL|UHt+SycT)3 zeCzRs;IPfCgG%62Tu%@GbshJaj6Oi=qtg+S^SZwV-$l%HQMr z*!|fwu$UUJCH`7ljuvB0GKd~O)8dNm+N(5x$SbRM+9Z64H8%7D{smgC-X-Kr<; z-gUgDjTBOjcu{8oCY=!-^*FC@q+-O5UD0z)GEoQ|+uPI%NK92^2CyHBa~OHrZuehI zM|^0)w4F?#xb8iO^u$J=RSWQD?_v%=-06j}IY`;`+#IW&Au-ByJ);lSPM6}du-wq!a8qr2G9 zusY(+QNI$o@cS*7cRxa^*CPn2UMK1a_;68ZzI<4<(+OUHa+bQ%>5$Dj`Y=uT)1P3} z9jijBv}>p39NemQX=fd;W95lL<<$SAKv7<4b{`@N=Zs(6w-f1kTcP(W6NFp+9b6oB zA_@^~Vn0x3T(F*qGIMox1=2RNYL)T8|Kx1h>tuKu!*9z&@M9b_d_Ab*aJtfsUbB4D z&U8)ddivS`6(b`f7>XHe&={JWpP%1dN{t%kMc#cCiX{vAmJP07?urJTSi2vH=x zUlE|A`c}*nb`+w=cHjM<2N8j?LveVDz%gW<+LI-8mKVtdBC&yRzEP~-8&OrD z2{r9{405)tGSbtnzY|e(pMy}u3*hyCj_Ou~$A5REDInH>E~l4BXqxnMj(Xv3F)q*` zVXnUT#MV>$$vVZ^+3dwbZqB*KrU#LAH*UK*(0;^&_a~6tC-nGR8th8iu4i$&QMdl2=l%7@;of-{r9dO2miE)`1j-g&xpIuLlv2vo2YO8 zMH|td{=FpplOw{pPrg@x@jCodtUWWLW&b%UU`ti02mpWtm}+OD6xcBD1+oVW}mS!k25bBdFT z6o751rgZPVLAI#(gH`tXmx+#C7qccLx>BH!&~UPspVB$XWRe@bu|;LWWL8~+3eV2k)~(%QTqnZC zUI2$p_ee-Gn zq9|QM2MXi6*<8P;ag!fs(jK!iTg;0+X|?8xY4Tpocyxo)25=zP)Y^(iu@F|XxDLXR z{9d%E!kloKauC1~%GaW`9ehCtRqLj?k96mMlcm~`08XA8xVsN%H@R~ja$f<|8l32i`2}BUJSV56!j6GoA`mQ z07zxh)zijqE(FsED9d>yKn~>-#UAN%jp5FDp?70{dOuxLyJIVDjG$|lxA$!JpI#+J zc|1@4Muq@IUbWG4a{bB7X0nsAuK<-)t?TeDIje+n2V&U@=T7+O?wIjeeXoex^3w}k zdw1y_?#R=sSxd9um9xckVwVXEACXwSoJSZyd#Xr1E#|eh*YFE+=N!nLWo{s-#(2$j>4v-6px5Vh#ydo5G_K;Gl370uYFFRn?NvY@Hg>~aDT^7LuCm{*$!#i6o zy{=tVz;q5+2J9 zlh476uaL>K0L1QnzfBZ?67tO$=)^45ow3j*qB;N%%j#N|OtE3~`ZEHoa4k!*N9Sw6 z_;C~^0xHrrcal}5Jag;`=RPl!kgd6}+p=2i%N<`9w?KG#SxS%dNg1iUNVa|VZ98GA z5;E??ci8~)0jt`;+LsQW1jF+KK<~xDCr(8PDUMxb|p-!sS2_{!;*invD-hxuo|bik8-+P zx_o5-AQICv(^Av%daF7u&i0q1oGM09RtVxv`}9!+{TF-CD+J$AqI{YRz=ge@NvuND z^=|;Wp}oI3^?bRXL%?2qB9`-xm`-;pq8MaBF$7mq$er~fimR^Pni}O-v;O5nR}YAr z%M__Vzv`=)d9-T|-^WD+6R=%!;mPxAU%5BD6BR_O*8OXV)+&%CEG$UQO=EN4*j@xE z&CS%7jAjUyrKP3IGI`wi3V+!|m$7YT4+TP2X>@WDG$Sh?#*l$pSo^aFuQ}+C?ID$G zVOK-ZpCQPJ*sHyQLZLACICjWw-9DH2t6?VvNz*I~Z2($uGQq|R-(4&bD%l8ttR9Gf zP+g^ft<3@eg}kE!{ULE-e%a&bvA;zA?Xr($=?gnY{V_mfq-#beEbVRv;xL?5(3dk=uZ=Ct#z+>{1}JKM$`$id7EO@W!& zwG|(7=At-#;`^E#-!gR_;P|fvAvtlzUORnw&(z997SKGqwxdM4Q(puekDGQm7h8=9NGq2_60d|&><0suw|Fm;eX3qf)bR#^p$z;*`+6c_Z2 zdu~wY-bIFqKziKU_UFO3-{J_+Vn+?5BLR7$$y~<1)p#OCg9TeDn1YOQC`Ev}aIycS z3)Y@AnHw?_#1C%7xedN?G=T^=6#yW`+S|*7#H@dRiISE1XDdp4VgP}3foeqZ zW*Lnds{k;BWkz&dMEa)}#OpzRkqNq|NfF1*EkQ_2s2tZ_FmFKm$_UV4?)8mv4fl?1JNzfZ7ir3F}At39ad zT`NWOEaio#<*@YI)j1vY0jdBhlw}231EB2 zZ^>--m7M3xbO9w~4R~J#;q1qsk+jrU#rIs~vg!uho$hG1uq|WQXbhBn=J%bDwf>vSE zus3ktT_`Xg2tk05u&KY=i)EE$Kmd-wH765~S%FmvJVazh-MK}uQPBbbmjr;XkbDUw z_5c>A{RB2ul&=990QfI4_~&FIxBg)qxB9B$$uvgk1yn@@n$VhRGeoMOBApf;gyqE$ zp>$gj6suj`F^@L=KUPZQRyxbe5;je#=rjmE5m)~&@DB*^|A`BOKKbwXe}|O0o}T*W zPr3wS6B98BiALerNM0*#2I;7;e8^u;n;pik;kQ;YHa52HdI&Gpp{vl58uwEFQc(9S zwI16Z=Wq|FON+3R^otQ-10Z+<;UM7AS@GG6{;BI9>l8K@a5hU1iN}{}$XeF){F}ZL zQwJAU&UaU=CIxX>4c@OswvoEOk)0KCc;Mp`6L0zY`j#%%q3c`v?De5UeS2gR8>V39 z&M2xP)!314qP9m&F|ieH!xg``#JkT&X63>pXut8U*Ikj|*-se0RXX0)m!EyG>$thN zXDJ=U%fX0UO^R~u5{ZT$4X^}U|6$gKm7ua*f14KzLEJv@nu>v3D5@ zvAcu)Oa4PtOLh0%x}rws;R%dlcWDN?SF~f#KGyAE zd#-17_L^<$!z(twzjKrmv{Ea$FEUF1c|%0H=YfP~PG9)%8J<>#hKBC#t62TU6Bh9+ zerh%=+1rcF=>9bs{xZ|v0JlMex@}50>#hWw)sM+4>&MkYoF|?i1A1)F$TUe`doI z9+aWe2@e;_Qic7^U6^POg3wLPItN_&lQFUt*kXHoCue5`dHK-}{$n{Gb?BJW zq;hbO;i$X66SX~Pv)Z(nNxkxX4R38azc|*>J51`MV%M|!G57(;;n(XBMZ3@K7aN_Xgj@OUzvt)|%g=bRfs8gFqN1bb zDs2N{=MTA9pw9k`%Jj^PcpZlT*94oD7#!lis_2Pntv^s85##Es|MjY@26Sxq7wldJ z%Sy)NhW?0iOVeFWeOz8ZA@UhC-a_fe@?Cv{qOObmL zWZj^c18^p63Rm^5hN&fzrS-k%>7_;&s`#?LCw3F zdUdI@`$1|qYwvwa*JzxYrK-t!6#9y>SCfykKl zgf2a@oFLmgCF@1w$lEU%xrJB_yxRPFG8x-}tX$5(-u(SNW1AFeh3HQEtSbd|I}^oK zA?Smp*s-M=#)%Y-(DCkwzxg}6=z62A0ZK&91uy5rMr? z&_<>CEY2Hq%Lz#6s@vNS2|mE#V@%lYp4h98-7|4p@6TB+)ToO7Yt(e5bDgiuRQ+IL zCub62^l^906Nt`UT}j54vg1-^7B}$=z(0fv7&|{{MNsgI(7b zS?c}rssD0E&$|1$m%--3!1UHQ2S}k;lC7qR_%FY85k&r;3Q_+%q=_>3U}c46r8!8t zL2NO-kx;3`+sdf-u zzFJF&t#tPHPH!gg9nd_HJ$@pPZI$b$a^NSXFIv|*lC|hqG}z?win=7!EFvv}2MSpm z*fq4zH4Yi3gf7g41~8~!2@Z)kdAo>Z>Z@XT0jCGkhvr59S1DK6N%)wKh4#Nx?~K-;a^4tRmCRr{62DESqFhSFeuE|4pp%YFwKokSN)WowP#25+JY% z{{skqkiXiqvraNilYR_(h?$px$T3y$B&+Fx-tSnN%V$7^aVzTD}>#4;!7 zB!#l7W&0n5r-)vNv9x=>*1NS;p!C2)uBxgkohe85dk*%3>_3))EtKM4j)I#$u;H@T z4h+1^+KS_-NM}hTRtOL{$$4UCy>!vEHm`PuhAMqMHVbbMc7|{KK4E85yUFEws4&6B zlSa(pDc--Nw6-fp>Z(E4G zpq8PWMSe~hz_q_K>42$LaxqQA!J`Q!AL(Hy{U4$n)2C0s;P#l z?>kd}d72`_l0*qBUmEpj-PS(utowJw#~vj53rpi}osv=bMpa-onc;y-Y+$*qsH&Ru zx6WSyNxZ=&=l*9|JnEcRvr5&!=^lx<<(+;plVU%plNMd>-a*SKt@!+T{L_JZ>Q(?z zX{q4TXlZit6^MOWxG-&CEAtQOo38$6MBu^>1-wHM8TNx}&zJ_9j{3ZIvS=3U-J9Pe zIdewIi&VgDWS0eFu%`P-fy{4VdYt@r-lf^Mo#IF+1(q#;?8(0_2Yeb%8;lW*mE92| zZra5RS65NdlAb)NxVZG;1luOiVaCJJ-E*?eY5+$@%PuGP{PR)Iqn!=9aS$(sBTnsq zI|2Li06Sb}Rc*Z~GF=;bbN)|r2k&&GqB(Q>!&Nu2_SeUDuVL|CHuzQTk@GXuG|(FM zW=CyDR&T+PUk}#Lre3TREU;Pxe9_^hc{KiKX@*}3?@isJr@z}Gy93ukuH2j{Ip5G= z{&H(iv8sM6@7EB$hH<5e!`rfmvNZ3sNQn>BM$I(R9IUMJ=SFM~uh{DIKOy{Te*59- zBh-8^t6vEU32D7o&NAREunup|z_3KyYX?j;$+Z8dZDI_rVqe#D4LV5fN_NY9A<@P^ z5NgF$m3dhi>-Mv$jLYy_Htj2${6%T^d)+nDp*OwXy!py_cr#;~lPSD!qWWFPFNMww z%MjWKpBfeAOe`++859!gu17ajk!Cge&s4l#_Uj`w9>n?)SbTX&h7Ae(I=PMWj*VMU zn3HQkRvK2A`R<3*Z}vJ0^@sSB~B6nOo!MHNUA@dg@rc%jJ@nOjK<3>z<< zUcLHw^ynTlVp;*f;cy%`5I1N1u4ukLb)a;+x5$i^C{4_30lOcg^GwJiUsq;O=2AS# zP|@Iwy$SF7=~CH!_W7p|4^KvUJhg*I3ZZ4g=QijGD8G`-s;uZJQ)0QIUKm*E+dOb_ zQRVSiwdrbT=%rcvN&8?cXRM)85ciqHx}QIP>vPo`^EALueJ-)U#>K*1Rn~@vhV%_* zW#!PkygdC})tS9(C)3KkZbfO!C!pMa{9|9L^Uq77j}g72R}cG~yq1MlcFs&?R&}cy zoG~Fukwv}q3l3Id!p5nhBixn5)Jhxtl&5BC50Z1-x58Y|>s?Cw99@Mf8=ryPpNNJt zx0B;Ev3u&-l@nYcH2e$a`>u`QB!q=5hRhmWn^i{Yyc}-KKA*&jU&9jChO8?Wi6}oc8YLf_TQz!hKbn)N6dJ^TkPrdu*tZ>=&?o>6Q z;+4d40lT>`kc>4jHjs_HHwY@81&u|8O{*8@VMMI(*{R##FWh#>~`t+K?Q`hNOFm+aI*&3^B=;!g0mLa^T-1BIj;dW`N3q4u~ zRl<-$iwM|zbHO#2O-93xw!JILC4@RlwwG6MeVvTZ4rFfo#^S6%hw?RCe9h&$|0urd zAYK-GDcE`N;!^1|lFF&#zFGH)Cl+ypgB;C_h===5w(Ffr`<@-VtPh0Bc2>eqpgMM_ zZw`;yf2fhq-$JOmOXAJ|JC-|?>wk?u;nOD)>I^=HoO>1>DZa&f$9zl&B1ko6 zFFqq9Bg0Ga4kUGVcjN5PR;M?zXLECN{dQR|d&|qquK^{Q>FJZZ9KG3|IPp%iWvLc@ z@o+i@YAGl1g?EK#C8$2*R<68NlHeVSY_2>qX2Bc}aCOv!Jz6uaVHXc#3wDDfKOIFG z%RSYkNuLsq#{3;0Fff;KBcD9`ea%UHXeUwGqB|k)7I|Qj^!EcQC{gqEIhDwVYJH0# z*}#{~?wIytT$SXNvy*4-rh?XlZZoss8Dp(*c=X;^bpO3)T7q_Qs;K^neSfk}D$PRw zZ^s-y#gd2z>*&rNRBb*8-=JX%5*AJ(edEewsw%2QLEWE##!+Bqu49X?4TDekU|?TU zH6fN%3#*r-PRM6JxzUDEAu{V&@{>B?SCvu4l+1l=@DI&^7Gf(K8);qSmGl{A*9T~x zVy9Cgo5d*iZI2#1cGqps!Iu`TecAg7WdG%yoXPD!;IrhH}=g5IUoaZIy>&jdA2_OuysvrdOb}0E^o6${FtOcy zZ?xUc_*I+WwR*d-2LihY&==L37fh2TyOVw2U}D0|*|JL9Uy)B_Mla_SF8K3)$GQu< z>aU(hoRw!m#~Ca2UQV{!mkZ1)A2)L^d;LHF z-g%)B11yKLu{lVt5<0dvB^1B1y1pmdFnG*BT)k+hi~1nxYJ$_u=A9ASNN~kH`ZPPz zJlSVD9@?L|8i$Y*qp@i`-zDVd{QwJkVAJ>R^qXNDcj-}toGvAj({0R z#A(DG7nfV^a&pQpFE4-c_s6T~xF$QUPIOYqx?7g9 zeI)>GZDr7B&}cL{g~k}JC`ATW4!)SV^m4Te#&#u1>+}C%$#=Hf9BXDK%ylByC z*BLn>%p*k^vG(39=e5l>RzzrEB??^h{22UwTJ`jZVVDG_r(UK%Ve+zN2aU~Z;cb^lziVvx-|?R>5kH8Y?^ej{@wQe{x6=%~MBXLl z@8^Fbz|WAtySDuiZ)_%AC9E2jmc_r_o13cY?uaR-sbo|Hwdb^DBp{P)5E7X5W$;Fs zSvTq^V)={}ivo6(c3dS(CfrsEizW{?sCRpa+4+rzaaM}h%A>O}5g#lEc-(uqz=rHSHNVDV9B|?cRZ>pXj=0TabJm@>suw*k<{O$j@;Rzf z21m|Un3%SuE15yN{igw{l*%LvjG(@M3-e zI|$jddoPF3q_w`0;WFUY%&z-&HaJ)4On6(#$&}b%#Aa1?Z`&FD%OwA1&q~OFGMKqE zmxDjB^)z%3i03F8XP%FYp6Si?+|law9YyhFwQ!LH7r0>Q>cQZ&$W%N9qr-Gs-RJ8! z=}#oHNiyv=JiDH!_vK}?CnxtL6n;h6DiN;xA4u*Nt}6fd5r5!);%CPkou7)Ikedg78HX|fHq@tptBOPOw z)zF<0E>UGamm^)ttPTo@38L1(mJuLDw^LN?E5nMOm=!Oyt@!dcG_$mhGCn;gEt+`q ziyO(bhP&cU7cIRQLQxp56v6MVLn|a8td1rRHuf)lKp=QCdUoI6 zqK09UhsdmV%XpoKNP)88*)6>vwjY^Q|5XhUl}wva$BmkQ?$Xk>!x<8Jn2abV1)iEX zkmcd1kJHo%pwc7C86FXu37xNwjQ4E$SqMGv{CrDPUn#j6%c*M7>#+K!V|e{%IM~xH z*j$9JMR%qzFj_G_i%?Wc`$^8i^I||iD*B$(UqvqA$;@VORJFco5I8irO)R{p1SX*+e5aS|u*t{XjMr`-*tPmM20vIL>e))~ypbGE{%| zfY-4D*&M2)fOwS~saMAqXA|=h$#*!R*~`&5Wxl4iW!J3{ubIALr`1$U8tp8wt;4O(@Al4a zZL8kAf(KF#dhJbf2reCknlZPPEV=OObO?|~?QEFY4~eu(M85BJo!FFf*V$`aqKC6z{-bWwo^3l@;5eCf?bPr!FdL zYO;EMf7$GYsILxcLEFFFEldr48vZIh6YoEL_|Pg!>zcH+wPosmUK(9_jKJI$J7I1+ zm(yIadSU~q9zmhjFXIFsgDtu)hKN(pqT3U>Rwlj(RZrNujgL)81kzB`KB_*6Qjd#C z(FJP=L&NrKu!?pCZxT>1nb-uglMHs1)RmbLS>s)%s^UJX#OE)vBJr@)kfXt(J=R3S zp{o7-*2p0vL{MSv2K}0qL60NGaev5Hf^7EZ^2L?a&9E?)tDm&Jk+ znXatJzg5c@8E0^dRY5J$_UT?>VHYy~a6fJD`b2_}l)(9Z{v5ISgLHCl+c%a^F4BIk zwN1lPj*NqYzWjOk(?mJY>FI$%LFAN_Q!Cw{47}H2FEFTDxP^;4b6Z%`@~T_3H%y*_ z!)W;Z*BC15i|k_RRd+;5h3k`;UJAaMzWdEy!XFeY=vk<f{{pb zlB3nryQ3|B&9;b2j(!7}30Y5|lN60X`HWj#%nR30xmJBN4!nDb3-QPrRrl&Gij-&bB}2#DZeu6 zxGI@(a}_vNqt=&Jy0 zEuOxgu%Au<2|1Il(m6ipvf3mrolS#r|JS+aRV63I>zhsr_f^?~o$!-GiVVQ6el350 zMpkn1oLKum=1W>`SoxY-=8L{;S1!U@2A#>?`gw#PoUrb`KGVz}0cGW;05*M=`+!A^ z%3e!{UH`bWp1$OlzczWd=O-C9`Wo~W5 z+FU(9Spie~)(Rc>3Y&sYY){xXha4xP5h6$nx`WgQ7a00#YnLeo9X-mEB6XGDpN;&s z37jU*&fb+-A9UAlN_KuohtRwgdCx+=KSX7w)+n}9#SDLMYg?W5GMno@W}dKZbS5X$ zR)d-tL`FnG`q$O5+z{3t z{mE$e9~NM9eB30kGhMjm{oSv6JAq^R1Dr48dfm3-HN>#I$ z!`M9RYbS5raF(2wy?8z+=9=L@fhhYWv&ng5mv7+uo!v`)n^0|WGDRiVVp3SFz4hzD zrDLe;zyoJK7VJy$Ev@EUI&M4yD$uOcsqYlw^Btk_#o0%49s*O~-F&|DJTM6ig*jK> zI_QVL+^*nZ0#znzK_PpHz7%#W5l$RFU6!IjFQ#p=#qJ^iA-O_u#lm)P-n?1xa^%Me z4x1S;jeVJ{Awy0X2^Ezgn&ZpI#hh7KIyY*_Fpfi2PVV2|sE4hO>Kr6o-PyzwnV9sd z%f;UbEZW-5&?vTC?}d_)dnR+_D#r6ZSJa>9P8ofcC;2v11W#~)cw!gr$j`@bv;DyAV+v#QAN}Gqnmn>q=|t6`@@wp^z<|M9G&Q*nisiD zz$5;?&=zZDrJyQLUQW7Cj>#l1>CV$cOP39`tj0ebEHGCoceMrol7nNsOTHMFwONSQ z#>GAKOz$i+HQEWCz%8!0&4xA~97f*b&hzmKZ>{y+CplVtiD!nW&LNc7WoS)+-qCocYO#SAW-fLfK61@milu`;Ws#GUXkfKpmD`z^ zJ$d)O^IKDCpoqvLnbK^8A;NTAa_u-&WwZLq=#uL%KO@*xqq2r7)MT1swDi2TPAQ~J z?M4eKxy@$HjEpCb-R`q4o4oI^qc`r`8=)6b14l( z?<;~MAvk{zUHUS<%W5!lJWMlTL|Z$(WqJ;Tymj0zH~A~vGW5l~y(72;3oBO+(+zRC zp!RQlIcpD0{S%m2;U%gT#D2<_>xd22UqL-&GV8RQ3R7YpzHOg1)tW(TS@Igf+o5mVxS?KRmt|Q- za61#G`C~d&foXc?j-F)Z;^snUz>P;U zl}#*F2kL(Z9Uf`;{Gt-f#IJGd{|+$K!r2=d6#d@R+z{?-oj#0x*$uj!Jalt>8-&&I zuL;4jr%Q;wuTg2fn0WwLFLp|)W7Q*h;$lV6MD=~XzsL)+_pvP4OWj>ov=K<{=#nD1 zEm|8IGPS0K;wLth$Bu@eaAzB-%;XD?>AX(Z8bwhJ*KA=}O=JmNCk~Vnswm zt`$=-(wjV399&VW(gZafB5Sat-*a?&Jn^YXW44ylQjbxKai5i+H*V8;^Y+b~3C*kh z){SiJ#n}4pj)Wm+3a#J&Sm6hMZ7jz^qE#L|eEF+_=^@6p`Z!9l)|d+A#{M<#q{r1Y z*uIcT3dRSJhz z$!wkXA~W+&igRkl#wR_7<=9zi@Jm4$rR!dtcdbkwyKB^fn|_>G#$vcrc-!zzxg)Bi2^!` z<99wCrecQYzS&E){1$$E=jAV`nuLeyIF>kzJSr+8u*^=WNSq5=`nYyn`m_K>A~Dl! zsLD0so?Ygr&3OfDM3Zo7sfYAw7?6gmM5kD(e%V={O(jHfi*m=f$iKVneQPX+$>d>Q zQJKMm!d!giloKuFrGXn+6BA$RKknnRI2{=co9;!5+?la-I- zT7u)xmo;NU0^*Ex_X!mVbnjyJUfs)_c_Sg7p2Z^7uFt`-J_{}~Y!bA;Lj!N*D7f}NnZ^k23?~P7>DAClrGIT5Tg2jrVV2dd{Xz$&SP<2>7)>$%Vv|I+ zswyX&1{y)iI)J)tRffRflg^o)+_F%ik)Zm_(gn>cf!lVYh5V$iJ zg`B1u$Mj+RrA#6?Zocc9G9Zs)^%lKTEt^9*_J)7>SXy#QO1|)3`RC%qpqvkXgCDI? z(SJEH5{MS6u6|I=I=L+tv{w86j8kczyk7c!ZKmm0Vza(ag*MwI$}oElb$X82gY@U? zsw#O&kFBiEToF+03kn*@+s8lx_{iWPYznNC&#S9PqPPw7)eQ5)MgF_heG!Q4pFZ&@ z+Pw@jn}R+~o4vogi8m9TjGZLx8J(H#l)!2fOFNsLOlB0PYR!(`TPPLPF*Gnybg7u- zx_x_Q{n|x(O!=C;Q1Q!naO$Wk2F`46FW1pJ1|4b-lmq9RX%DaZhK6?VxGr6|kN}~i z+js8dK5YB~!Cv6wOXttaO&a`(MeBH;ID>qN2Q$-g!h!%*ZsfGIIROFZ>hk7V3=a0T z^HfWldwQe0!hogf%XS@9|V$=2Fp_x+Nq0Fv6&~B+vl^ z^|Xy)(Z{gfFj=&IFe>sZ?_^cN6%Mr69aJ0&xrl3A412NhBx- zK4cB=Q2BPc6?^@e{Xug(ENN+JNuVVxBt(hrZAe6f`XuI8U7g_3$vb!Mh(CMQ8b~j( zR?iq~ywG1t#cLTwry*OF-3Z~knAhi_IQ?sR%e|!Z#qoH|PS2j!38G`D4r(pjKtd95 zZ`HP8q%rIC#RZNbBIr> zqd&8>p*%!P(;7xND1LvI+NoiEfpFmbr1K@#rg;4nyxGVbQe;O|Dvf&^(?0+-XR%{kr<_6>8V93`oD?mZ;okbXz3>@1fT}UMcYSv7o=9~9G`nq0UUQ$vr8gCHG zasPh*`I|Yj0;w{w3n$HCc%`d)p8iJ|Gb~*D^C#2&`^pNOdEo zn1ylIXF>-!*Q(id+$ZeV%qi4YEhvmpA*VNSHAr6Q&KI>Oqs{iJ^Z8u+qHSoRNnyyF zT|SabxOK2WTq>PQCohR6OC!U2&DdakVy1=LsLNy@Z9b%}SG+FvH1VL!G~}{X|JOdt za;eCTh0bAO+71*gtq{A$$wA96NkFkOy%rjTfGtwtH@$1ynFiXSgi~Zt7lue(d-L~P z2ZT!;I61^o4%z2#J!PV&uWd8vr%^b)=cGp&k(FGB!Ig&z$U`fkaGk&evW zs_N#*_Wt-$&epczM@@|Z50wFAx<7v&*^&+hcFJi3f%xh@Ry>3!2jhOXCDKOc)!raW zCfSqwk2)?suz3NSsMAK7P~qFq(t^)#5$=m?p0*33^JV5x8SO2cX;1ck@91bEVUR5G zK{F3?PiAeU{UeRg+Opu{S1>v2>MdkmXPL!|;v5r_^npUwg#8_CICqBB?qoRkx|a!V z?N<$1MqRp+)ArV@FpoVtF}>R?AzR;xNpwo(xefoc(o*pWgy(M#I=8g3RjTA@?@Xu0 zI>2P$>Q^WI9?1g8dpI7P69>M@h4GDHMGHtqUmM9RDJc=isd4N9?)c>Ei#h&BUO_>I zKc^B`mL%ZS0?FLf+7BGSeW;fk=bzcf?k<$e1g=5x{M3jSZMJ=#tq~F;n@@PXt|T)3 zE|5VYLZ4@5q10x*zR2Q}k58rwg|&BW!h%IFlUh40J2kD4dQWMo)7U!-(`ZH}rf1xP z&N8ts+sVRnJqk6I6~W3i_pF#X@aR|<`Qpcqr@T3;j9;d%!8^$)$h`0S`}gnkzb0vT z1RMyOW`5l&+v#=%X)`jT+F!o_)zRrledWrPK=XL^U6&2np0uOOm%VG-+BzJyL7iFq zQr<~urYPwt)%zJXHDz448H9U>yUI06N`WM}iro0pKY=`t9>gUZcIl$5Hej=P(SIWk2SxB;6< z)4;=R^Z2}o0Vz&quv~>~z$t@fXMYjKaw+D_H~#t4@z)>CE=EF1ire2DYPotEAv3DF z#!>EQb$+-c!#gi878Vu>sJ6GUHA`zSzbAN9`PNgPud6F;;1ez_+}8n4{d*7`d`Xl- z-e_aJ(?0rvf*tIfOa}7`o@$9ce17WPiPlW0(3gh6Wh!6?44WdxPp0FOWl6Kt!*+%H0@Ahk)%^Mrt$cA9d{>o~+fsm< z_hpXOiA4*FRQu_ECA^lPNTQX{`UkUG`pa3Gg_4ojme%Zno*8Ivdi1DI*=U}zFAaGr ziZJ6oITW?~=`0PG*;>}CvKP7qm)WG-Cl#W=Lx(djg?AJ-S`!mIX8 z`#Bwb5TsvtLDoKKcM+=tlUHFJT49XKiWm_Q(KP5ayIBDef9jwl0gQHzl)gR!FiZd~ zll8stRbRCIOvL9~>%BM`v+DL_Dx0wn+ICJZK1p{%LY!RY)wNvf>8bA8Wg1rPZBgTS5LdH+V0+L8E z@)ylFu5iiqnR_$+avhFU-QB8TFIA+zug%Sw*Da2Wj8w=PUvBUVHbbyXM^Vj7<&9vL z>3hn8@OICmSM4e7eYf%u_B}Cr1zKYaf3zFdH(9m6!oEp;U%%`7Bg49R?dKzfG1Z!- zPT__XYx;%TyzWMVjyr!Ya&+Ylnm0L^l))*214iYX=5U^RsZ*(8OGKjfb63;;LH1~= z9rH)&%GufzdD^@6L+Lo0KfJLa^Y?K;Sp@@5O8r9htJkdGvpAZDLu~0Wh>+1GaeM9NKgB~`LjLy?j2L8;{hJ~Srhb3E%WehEJLnW8@a6>U7c%*6Cce7vZse(FRpf%GP1N0> zayktP{+bt1HwHSjw4VO?>lZj;ZRaoKFn_UJwA7B3EnCz0%EG{qqR!b!vmh=b6V_wS zP(sA>=Im>?OGh5$*C4v71dqY{$%aW6xvq$j4Kk-WF=nwxmv`|k0webB!Q|gPUn-&7 z(v?4U_yoep!&D2b*SWOp=TFw1QZFC9;LRZPGWC-LE6Eb?OgN*qVpuZ+1~?mG^9H3x zTi|$qY4-{-d)*InNNF~xziXS z198IBcJw&-4^yv+X=MKy!f8v`-(-QlHK3_qHs*QKu>}-#zG(Z4OEv3!Llm)nusbt^ zCGa~}#mC31=ebqhv+V!+)_I`~aifVsLP!eHZq|`F*2_Y|&)*z%buft5ns9ZP(JNc%Jx}F~ZxV3$of(o5*2(v?a9{uBO4Mcs zhC4&s+Z?&j82_T+`|_$6y0(etli}bKMBFb+DG$M7u@lYF8H_OwB15j5(b}%-N)~-Z zQZ^HRZ^i4~ej82;d=1Dhlt7EmJ8L4NhBMo#ub;k&ZAIjxQ+!+fx=r&1E1Yz;Ub zq2lKW6hT#Ad4aUBkX~#m&FR=tUFlmaA3tv3fz9nb^;~R*yh{{Oz73s?n(zI9=>q2; zN&3@}t5|67?g2j=1M`8FR{sm%b(;7{A>+)|?I<|U=-IMichrM%YhhOMN#%CfiKcRk zzI&AiD|!ZhK6)jCz^0k{5EUF*nKG&5#Bl;rjtzs39XK=a+Vq`;9fK| zhCtvffuro%rgV6M2}hNKbnI@T3_8o1*5N@8dM&^yQ$0D1h2?Jj^fJW%m6c6LK9Q@J zyO#fbu{2WSHT#hjm%^|bQ>Lq1(Q7x=j5dYsi~Y5P z8+F$YIds?&%zD#Xn`bV_MkT=E5R+-Hau46JzNZMp0~UJM8z!gZ;860%FkeroIr>St z-M$51nvahU)iEPLF&G@uvsvXd@-VftVh!`U>t_p2~9r8E^IK3Y6p%!op6RrMy0yt>q`X1Ci~d z^2I6*M(L+0%a?P5AQ6vK4ORu>D2`k)N1@z6PoiYPBjD34tIh;JG)GG5)hQYdL8cv)7V zn7iI}WarnQG^FBZAm)Y#|9|ZVDaRBzr#P0JiiEhh>rzpCa{l*MKEOsfV&2Bz$4AlB zFy)}iA(sKY^R>)&CP~8cO~Jw}^wrcVvu#68lHjNe2ACJ>n%6KNC>C%Lxu1e*e2Tc+ zU%oI+7X#zZDIKbAO38K;!Du4`1K59p=lsZ)NtHUIe5xvJN2eD)%+17o{-s|tv) z4IaS@!6R`WPtKC38>I^C)TLQ`AI7?WlbfiBy>y;D<#pRgXNrK+*q6P%zVv9TzNbAC zA+(u6{ELjf6&9IgU&@r6_nxVRA3fF*BvW2AnUqqVXFs(bX4GL8gJ{N`nG6^+90udA zl79RULHZ!6m%NNeO5jXzDR*Z*b{w_JZ?EMw28V`Dlq|-8?xj6gBHrHJ#R~?z{r#=6 zzAHF-)x!B=th-1c&$_>T+GK5fcI<@=B?w-fxYBHThOjezWPFTvf)=_+{KL$j5oZ2S z$>IdQS17yI%!Q-=-rgDbyt#p=K!rm6`alKg$S+^MZm&+3+nN@8`}%f*S~kd44Tk?z z%QsvW0qzJ}WI`M>k4bU2-F=)iuA90(0%v!$I{f6xHT-xR1>VtV_T$Bd?*E6f?|^D* zYyOR*VnNX>2v?dYf`}ABq=Tq{p$dpd2WirgDjnqtiV7Nf7wKK8(m@5J1_-?cq<2lI zp}jdM_xt|qt@qaYpS2J}l5_T+J$v?)-^_$3eR-x5akJzSA$O*F>1&b<^^@4RO)_^n z<0!uC*6Ie5X|BsBx-W*UWUo9iLx1vg_LNyKTqS<)9!2H~h0U_TW>klW*rSzw%b+xx zugvvwJzctLSUWZ3wx~AQ665&e+si|avWp$PiI9mQ(C4(Vu_1@ydNr5Qc>aPmqlkeR zGmM0nRx_qkv!Zfc^(B&JxqH0-yo*RilW#9h1>9ZV)q%c@um+{IG=6Vr!1P)=UCH5^ z&ClWB=kL52E^gdFCDXkEReRDQFD$@1RV|{~M5b=F*nX1ma6hVb|E}E{%XzLU6%?Hw zML=pI?nBzdyn!Pn<6AKltrtK;fdg;`jNnc`CeH_)?-~F8I}N|Hy~?=0NgxoGkVf$w z>e(HT1j4Y2_uQB#jWX?|w#0~tlmtNRI6raA4bl0$Ltled(ga$GIcaGcd_4ghGyR-m zFiK;Wl+%oiTtW3LdA*sSfQMyIu?C^@Oq$yvDG+2-MoMzBc|$OJz}v8zhssV)g$a42 z&yPo+Fz-V>Vx|RM4~0EF%rv~VHOy=uB-S>=-hTwV+RNXL)a$>kzHway7EbNYtry>Op(Q0H&x*O`XP2+^u`;RbfB}|oH!f?{^RfEkYc90&z+*pznYnaI zzMB`!e0zDiYz@R=%^cpI9)iDB$SlI3NgZJ@ZIs}2T<3J=m__3doDE8o98>eW?b&~+%Tn6iL&Gz_!MKB5R0D5um|k!eJ6| zUfad7t~2b*U@nr8pXdO2^y6^S>NHL!P;4b!d}q_XIa)|nr_^cu`5}}yqFaKD0%fxr zF?@L@13t8X0#C0au0%~ZarmRor&)RuD3#6*S~*HL+!5|rhUu ziJt4G;6gfk_2B^|{P5^0vV7i=F$*k4IdU5tSOWVV7T{79ez~WLI!wx9oH_5hS6DnK zGih>cL4TA>|EF!%z1b+Q1Zn))6nJYo?|2&GFkF=nSFtJqMHI2OK;NHClnWOrBwB)! z({d)G^D_FM_9ztKwjdJ_ny4#6BWPI#1vLOfg8>hzK&fM6Mi<%G05+!@=m`k+)$ zGY9z$8ieR7Nb*HQ%g)oNvvl!G$&HV$nGbw^d{)A<%>UJ^5DezS(vkxV6b;M_JSHnA zr>dzL+35b&_qgiayKisax^)o^HV(LE(^pD$tgW*_NThG+K6o&7IG*OrnXZx;1jdqG zK{6k7z$qY}oC`0ky=*`@2i)3qQh^17#~3$XOyi$>!0hkPW-Ptd>Zwd?}qMLu|5jZI91 z&vxHCo?a@aum2u^9pKQ82h~Otv8up5%(Qd5rX^+2~m4fum-z*O-;9%2=v%1p>_A0tC z=;OY9(qLS@II9%hWjv^0ATq0}gnE>FILR&Fda#6@h2^#nIpuvwmNNnal!q2X9IF++ zLI)hFytEX36&|IAv2gap+C{v3_wFbKMKBA5D;CH4zoj$Z^1XEa{LOv)_HpfV*jNPV z4CeWujZagHegBlKO@J@O-yh;{`8DYCd_K@+ zv9Sfv?*Q*&qEaWI)3)|f2(>y#rgAR)cfL3n$w|w zA|u0@|5dNGb>O5d+zh#FL;ou>^GG`LK8MurH&C`+|NV{$#cpxf|LZG%K8%V!wU;Ih ze`)>)wkqQOMy?jmbxfrX@k^T3xa;gI-^q|aJmDIME+@)P$ zCWIwLL9*CQ|GancBE26RM{xZ#I)IA_=bAhB5-JCK&k&ATvfVCm5)FK~`!4EzJumH@ zq*A%=Z062|Ml3dk=gky2W}H2aLwwef6LJK8`u_eTqo01sX}ps-X3GB@c|Mqp% z$KKqHlTxUGDs0iRkd7DRKVTBQCixzofv<>anOHBs&xfh;Shv=6DCndgNXR&pG9nJ5 zuJhSWIq7zOkL%o4nzz92K!-EeR_i@lA@PO%Pz!Cf1KUc#w3hvp(>~Oi0wi9ogj?xV zaUCgs`wYd|QGB9pfAjM#o0)^v;tCJlPB3v!N&%T}_Z0ZECWH1dnC6%sbPamp%B{==c$_2xMl}*G z&b}V{{P=>D8H<|Fbh*}}q9yMYajrNd0R)9Q8${e@W5A7^__G}N!oq;_D<{vRP+Cs? zCFhn)^XX~;73lV2MTU><;8WiQ?n{rg2MhpCFpFJU(Jo;?PW!yxN?eKdrWwy2Bi!H* z|EcQi4gU3YBw&m-7?^8~ztuV8YTWexjK(W*=IQ|Kb%x*3>Nm}vmM>404Ram9WxNpW z<@ab@xCQXD_n2I}x*Ay|G3eZlV@_&2@6C6(P^nBCrghk&0#^sIqUxm=v4vzDNivrY zr+@}kWtg-$pl(&!*&@q3$m!}QGu3c;WN8)erFZe->xwZ&aK}F`X3(eTSiWFw_O9S_ zx-(nd;vdxTS*?kB52cc%uQ~vNdu*0EuaAWUFRSJeeM(fmgIxFgTbA|0xy#@1Y~&1|SHKaV|^_Q|=?!*!;1ADDoij1Aj5E9u*k1ftdaXZ$&`n#T!l zi*A5Q@${^KddBhw17koB#JSk$VfceJ^;McNW8m>eiwSgxoJ@b`8?;VEM?Hah=cOm* zbI#|gzxbl)i<5W|234uwA8h2l)W$aL#)4K~u6$5oRnC62^-HhF6`N)Q2Zr|*(K2)& z^~N4&_mUA>bXbucs)VU%Twy5fdvW^^`o3^-X=6y6Plls{Ub!njIE;)SJjGQ+_WCJl zG?-k=K_Po)uy>qqSJvDx{J7|RwtwT%xAAzY1J;r}<%hauR^J)TMp{#Xg{K({>0GIa znc6T0$N3NsD4Z_yqSI+a_Qb(`GwaT3xo^Z%oNf z3)EbAD;-*j+`kl^qtbP7aiU^e?b3a%vmu+Z(Mltz3TJ{8nc-4|5vX7#<9Cp*CczP^!2l-ds$wddC8ZWtos;mabsPLu;vn zt4}VKveLonxlUj7$K8MfB>lcbNm9Rq7=+#^j_1win9SK~|Fb(F@6yb{5*f&zlJ<$> z&1E|Hv>(>3Ce=WhU^STqd4mcYvzmY(A0*&JuB`EOE_iLs7cB>RZ9)Qe+rnTeVgrN(e_rrHay#8pL~lP; zv|EU*aGGV@64_CQk-=qq45r{9=T{2pvCqR(%-@zc&D}6S-7}=@4h;^OEuiGRr*dCW+54*QAfXQZdQ_6m~n-X=yn&YRqKMP>Q~GtQ*aH!@lt=6_GL)b;0C6|C~jWl{~K z3p(B#hwOK&-CptRMb3tQeT1HOtvpE4EjvJ%v!?enqel1 zzr0!F7AKIMKtefxv9~Qwb27)bN7v< zl(V;ej(FrSwPcgo6cRP=T;}lS+xco3NSIt&V-dr#RjzQy;=tgJv0hsV+(>5i+V&6H z@R0tne|+hdxl&O1&JXVG^LnKAu%UY;$#oJtM2Qrr=)zsG_JgZYDMplEUDrOw+bO~I ziN^LSKhqsdSy{Z8fcr)r;)EFX-by$2s3@Fz$5P*f3&6&;Y;fNkd8;bF=qESPa_8$( zP|%XRV&%-lMtl3r(gMn-rd^E_TH|hzSd;WNpE?__XrvrH)RVz}I)l$kSE+3!-q<1p zXTUbk5L4_pg5B^eY>88kJ6(5=ei=I*813bbNt{kI-SA|F!$js)4yP-NQl^=UA(Pvj z=b|AE6&1_iV8gWE_mFPwFiMZL1RKrm!9`DjI8sLnVF{;nZ2CA-Ryz)gfs9Q=*?8iN zQxsz(bMPxM_qt!7>|l%*&gR-7RtiA3f(N)CTL{XQd`z8l)_%}R%(Rq|sHL`EiY?Q- zM1RJAdh4#TZls*J;02nd*w{qV%M)xnGaE2w!{ih)3VqJ3`Ql#z7mEoKOv&X5eAMGf z>q~y7rnS>HG$&fQCz~=Gh4^MMOY~Je8?O6rX}HOlW|yp2Trt-SVOjsaUI!m6Ap23F zXS`r8#ZI-!Fg3#th^~1>Q#s9>w6tBiRvtunNvSyRR_O{iTJ=PV>UmnY&h%bhExRku;XK$j|!X|!=114d%IMwv5hJ!FNTM;9rkU{kp zb?9wq*UCW2&rj}aB{s_;6Sc3;Mkooiw0!$jcjRynH*xaKJja2}iN9&}Q#A$$A}RG& z=PM?wWLhM|X`;oyd;T)L#9ppQNvknBK7IcDx`y^fiog*-A^w=AQFF6mbm|PqmS`He+MLaJAh>e7`0?IIuDK+WB>3 z;*kVYF-CSOT50Q0*p9sg=wP=@ysU~4V_w>v33j1xZnVDH(Z#8yJ#3xxev%e0Y zSB~g4jWLlGw!J%nrHeXZ=sOu&8r%41=SKANTzxaC_(|{k+t#7B2rZiJvPJKl2LB&T zaq1HKtVxUWLR%T3%j--#Pn0I)&J{N3wX;>cv%O*8CPgzI6t`&v zjTy)t&mdbsVtZ6#0)nM2(3b%3;NsZ)LffU;u{7oywnE3FO@wd4N^PC!WjzCIV(`^y zakt$~5JJXM1&)nFjM3LCxbT|;F04uRJ?zO$-u{GkZ5}t*A+fEofl4Fe$k1(GwCmA8 zAWf}EsF8z?T0lld!&J%4J+(EdlT}*rNd;m+S&(JMMLFYqie7F*UR`EsmsW+3)0f$s zbQ#~%F|*#(vmmu(=cSrCo`r&vwf4z}Ur46GUOKk0=#se_D>c(olB>N%e%kIwxW6PZ zdZ?oH3IXjGHczv95(Sy=AKk4T#W`ou)tKKTRH=U3fXn-By|_+`}YPY}qo_Esei1 z*7Z7rR!Mt%Uo7mkD+;gPqXPcAAaieGNwwCbDfL~1lfQ%~%5Nz6W#{?^R;lF+xn2vI zoF+c}{MLgr1C{4-Y;T;L7!EyO31|_`x3u!yeie%R#uFO+KSYZWtq_4j*)X~EggTw@@*R$;n5T9|!Itiv z7d+P;@RK<)n*o+tj3ZCU{CY~%1tvNRyEnw+1h+pk$JK``BSp>_owYCfh9HZP<1$qm$odS6Wnw&W@iu7dVeY@=8qCC$t@{fRtVDpF@HfN zR7f)x7j@lvydo(hD5<{tj2Oo3v}-J^USSS|bas}v-+f$lXb=&Zd~=iZ$x&vZY69F* zKyuUBuB_gHPeNL`LOL=1c~)A*ZwlhXmqr3728b=#ZkzQ|_l*{tg~Ioq-8#?`Xj;%N`;|SRaN2t#n>z2;yZlFiA;y6jirj+7t$g&T22!x7rZXx z-Nt%j$#j4n6_mtgk>j!Il}{belAMn<;W51hF&>I#l^NSwBg{Ox)qOXogk|e1L|PkGjqYHK?%QzYF;8;knXlN}S8XPQ?2$HrQju!p0lJCW|LyXS*G# z+bJs{BtPDRCuIq6=KQT2>arLWjQmtKZsd*C(;z=VEK1o{)bzk-=lCXy(pC7%t}Iuo z#lUgRo?zc`7fMEYUw}q)msDBrQ+`%i?DyJPxwo}JU_oy*rL6~YO!S0rj1;=*Hi2YQ z#K_aCzT?*ZKqR^&mZ_9Y}GiIH1k^fjM~mR1xC zJEAJ-6t)F=E+yPr@rZUCS{KR~5fg$ZTJ>Bon(fLC4h}tx7-oXz?0>pWf5aa>b~Fzb z0hs^DC@Nam#a!{Xy04@A$dhYzXLtj7-uVYq& zCHxm_c86ZoCU^C>AJlv6zP3tqc0ltp!2^n^Oi>ciI}w{Bo7l1E6O)9FphhB0#Km=- zAi6w8u(WiWe}PZQGpS%(3>W1$gj+MDEC)}ySXd4Ag&3%HK7;Y10yOuiGgpN9fpKtl zKK$dPNW7;d+`hE&9^s8u&UhMI*koI>AMqwJueYZwR3>b5?Cro%T2M-IiRETa90*1&w)yXmDE&cfL2_R^!qybFW7Z8t&YK5 zd*{bR!aA6&T%Q!pB1B5JFn1Lfw}Ri&hn-Np(C|uDR`wv`!=dj)_AGJoP$n(6}>Aj%9`>ni0Oq<1KC(Z3+%5};j`)JfZLWZtgIuCcw}xnZ8^ zCtJ%DkOzUdud9@m_Lhh2x@FHtOISIP66eEYCq89ox6Ji?y6~0bGSb=yMZf&-4D^w$ z&&k;w+8hNBz3aRhP*!24nx3A%`$3Asd#gep46z*tM<){?oIw?HE|?#|lpIQE^e2EQ zqrCS??mgNE*>aJQk@-bMrZTH1o>ocrl@xG5Q=Y%Y-9P{S?5%%4i*V5hHFa;t5Eq5u z;lV)>0%Duz;+5V?+Ulf_|9(nw3*ZlOSI&&s5Vbsx}YF}TOi#?1;<-X=+1UadH zL-|i>+2OZo+3771+s!j>JY!Jh*;i<#C0t}#5116BiaLry@ZTx%!rapsuAYyH(EFEs#*e0Bi+T8S_?-cu$OD7R$JJ0Z?KRe0x&T=TO6c@9y@}{>9>SlbTDNkC0nFdqQ z979%__U*q^9XopT7~oZcK79F-Z)2&d=qENcGjne@I&kRVzv~#4K9dfMcf|^136S+^ zm7=h)u98gMtn4oHydN&2gWJMIe;;C1av(JN1PW79KMPV*e|`StZP#G=h57k;C`tJJ zY8`zLkSregFj?%sB-1f7Gn4LmBVRYmV21Arofj!Q_MF)a#Dt}}jS>W1d?|B&&+!qJ zKk`*r$O}mipGXA=O@t?wP7>MFMY*Va|3S9W)Dy9&zJ5?1vHyoA%T1Unghh&sh!X+9p}`a3hUTjG?y*q8J@s2v5qcgvv;UwRCw^b?KUJH~+E z3zym<_zbMP(Q0pNdzUA{Bfzvayg2a>>66X6hr2_)65$c<>v}IH&IngqShl*gh^5)t z+(8p|#=abr2;T4{JOI(t6V8Gzw4Rp*rT~VNS8!C2mEF`p;wH44n}^0wj+WC6TM8U` zPwE?VLe|K7) zV2#@X!;BZ)u-{+f@LX4hUpxWD%VlCcKomFdu3MyVJYrJhP%T4_xWszZdgb^3qtXbN~ zB_L2$YkasT>Wuj3YYKAeDTZ?Dm{?xYfbYu)evh)hgsYT|NQrG|jE3oJXjTNY0TOL) z(r{{YgDDF)nDWO0W49$@lc*7;v7ND^@FQ9-#;X)Y3%eRZ*Ij7LHWLjG{b7aM64D?0R$Z6Vx ziSIt<9DoI`dIoHC;#FT?pSF9ORPow}SENv}wPBz2)jGyTT;Prt;He_PzPO^d{lwf{ zI?;3Pvx766h?7G~Nir*2N1z-=wA{`GiuC2$t)E6?*j1I3Bqi-gf14(nJkd}THM^-O zKAq^k&Mh8y=X$V1?IVRy?@ z>4j0(8+>cuLiga}GJ{B=DS-2l(_d23prNq=k!+x9S%N1ADxIsyFQ!a{bxj6H1tzX1 zEu%5T$AbuI$6D^)A*X#W-K{o0BWE&Ej;ovOdLC%(Xm7#jzLb_-qvl9{n~LGp2@`-drDchUntGPN z^z)qNBi(;oU}}il8Gl3O`PW+fPedD?@t0_lqR|Pa+nLDO2vrK_Vea-^urFS*k81=x zq1~j8O>hV7X(3=PVBD2`3e^(PAh2el0){|&fr^?P0krQxhf%r%WbwX~yedbOo3$re zt)>{-t7FE13MSTHS*lSK`@sZmk?>q_wi{)T%S|;?Lj;sYrGcvWprDozLyt|-Ao1ZD z@t*{)oU3sq!!fK0d{aOQ*-;_Y_9rdDS9CftA`5!4Ng0~C50`7TS8CY!z?6*U!;LaR z3el{5IFCUkTP)LMf$e6!$(Y5>``M&~z{y)gaSWooGM6$`cuWcq-)L=f>1`9jaBCwj zZiBjBPVn@?YWt`DaE13eZk-eT6huKS!B~6nx$1_QWwC`3wn-7 z;o_ag=*NINQ3aI;^U%u#iS(=~cpBzXiiEXiTy7wQNW>;QIKXol(h!#RM9 z^>Xpp_N?}4n7&bI1@>S6q6_n@uzXfDYghNUDovSv*byAh1BJM2!U&a+EoZyqpPyg2 z>v`mu6(PPO2GW2I$it!o`^9B4!gS&pzMMxXOFNcZdnY8poUr=t=W~mkh8bwGEhFK| zV%BBQojsl*v#hEQp zGREe?_y-3~2`aTCatF9@6tn0n|YolT?-z8XA=Ek@Op*xQ|;WAYxA!}tdFX>SZQl&{~H5&P;Fb3%JcR*d*NoiPQ*rdlbrnns$A3Il4ZDBWI8Tc1pOpGetZuAOK!p3>^SZ9C%n`eq`nd{A?oSBu6 z6Bk4Cx<8Rhw@4RzfGET#RN@ai<(N%#=b0*z?J@zfwwU?8=(q&f|nViK&U|2ND68T|!ez=PqAM??9*p@zi3&f76*=gx5 zp7!M)2fOf4&1xa|1`(&L-LJ*yn8*=hjY7+515W5r3xUKX6?y!d08Sl^wP9=!OI{0Y z97xQ6_VawxM)nD8bj$#8)Oi2CA){ZIt}D9jk%^`%B_7f}ohe*TO!35rBV^o@@9G2& z!+xV}H@C1LhS2Q@D~VQIQKL>Op4#kP|5BiSyyqDSRE_aux{BaeEfON&cqe=tZ6qKc zg?bntKOyw+y;QR___@-|Sh&#P;>)x!)UA84BxkYn5lf_R+~DXh;68G2iYRMgYF(T$ z8CVNLwTU~mGOS7y-Rr!PrnTV86(wAF3>gOj8Ap-cdQ_%PDXXD0Q`9TZl$7_|AXmwL zY*)5!Y9ogj#yj5B z`fFkZ?_i+kO7IPDaYQI$5Z61bMe+@O%5)Gg&y~u!)u@eoJ3fgWV{+F(bRnCmnD-S< z&5`m^qU^ipn9!n&DWXNWfF2r+tZ2mGz_9R$#%Pvbvb z8E-Z{<6ybaXRN}7x~0BIHP&gN*FfaXp*j4PIzwOrNY8>sbb@q$-uNnASg;1rwa|Ne z7SZ=V1|jG9Mlp8$WnI{KJk!pl(Yn_SV)%*+e97fvdY@O)2X=hihAOm(*Br->v)a=et4Mj<-g-#Y3c z;6cyS-GJU;XW6M}e{3(3<**>4)EJH$u=1|Oid=jZc^?``@d1H^AbLd&LGmhVM3x{D zAH#x3g&1diOwFssW+c+`I*lo8R4EmEWO>wXW-Lv}ps5FZ1T)OVgDLm9us9_yED_j> zMu`)v$`NMTm(OQ65rHF;S9+m6*SPU{k72N=9=4jL7(}lEYXXgVX*hde{|$^0$hTdQ z@axqi??$HT!Tq;-_^{4KpkSjtJ){rn^@qMrz0w$M zk41ahShLE9zXfIOFoZHu-nV40dazYKG1M%aX&XKBZh$`k#&OG?!nsDRKH}y{{%i~|>GNU$fw+j?*dNZ5j zCg4yF3TYqlRs%b3*Elha6ghx6uaL{<#Y2+y(wU2>_ubz<`KR)9EQdal=~g>JcH-%f z4;+QNmv=Sdhatto`FZ#TcDC9!huoHjwc>HtzFlt<@)>eE3i02iO;qd#;t;cZc8a`9pSJ+TPuBdhEUwytL;R*nLS)wdd^EeR;zFp)kdM z$mg|zfMikK4gzK$a9b>QE8B)vHoS;uIYyYjxw(0xtQ?&0CV=8aI>S4ypM|oqyRFKT zlatGJD~pSTkY3S{{1pZM`X2AyoA3TZ7L7bXNql`wms{_nz9d)WCP5pr>CG%G+;HO% zNp=U;Z|~~r%6UkFCiBkg0%%sH*ys=r_2jfP_9Cc_qnqQ^$XS#KuOLT2-ovB(IN}BR zeeqPWCx1O>4=|a@UemZ{!g%BE|4FksiyU5fn8?PJH%zJZL2L-L0^Q!xkzbcK4JL#K zuAlDg+4j~}eMrdOyC`h^r+Mylc621h$1_7KB#rz>%I4G!=>*J97o;qKvraJ?HzIVnhTWSl$SI z#XmN7hl@B{b3tOD7~{R}jQ;#Y93xq)UB_7pn33 z7P7^;+vS9DKlpeK5~N%Z!dCe7IjumIij=G@PMGD^<>VagV!JS}pjf_&OzmP`5HuU2 z8BLr;0~lC0_)G4h<+Z)(Z$`pOol1#u(!|$6tXkBvD33_B1c+w)uts?(Qsy*?L>?el zDGCWEApeJk*?4uRK|bWRs&Q80ZV;Q&(5$2*qRx>{%-P!_CjxR+Ex;n3R902Bzin+g znKlidU*tM1uK@R4DX4@+cw1Xrdqp!p)n;d$X?ui;#816-W6u5KK|9pAM@8PMc zR%j8w`F?Q}*kRGJ{GwbaeTUWZ8RRCd>I*ZRsT|NzcdLL{?eKf{d|um|6@>K|=b_@p z3jbaA@$Nvj62edTXlrR{A)BS*C>t8)7;v+1#oV zl8-Di&P@*gafGA1JyhlWB$J^ifz1yWM@L84p_`%9X@G0MwYCEBRHpW$ND07n(1pbc zzt8z!l87)JcII)VOt<)-H2FQwxfo>TlQGV*`vp-v?*|~~+XGi0w8YR6x+E`)@7B-H@~;~G<{X>9aKEcg!97U3(T^u`%Zk!?4Pb$@babm4(4^WTyVxXd{1e z+N2>lh5H~JwtMM&bL>I8cVCn5InQ@rdHbkb*-yJx`}*%7UteDqw1>x*r(R`ANy*|U zY-W#aJ@7$8lzpoti>z4h_YIMMDJVen9KLq_I?(u+caB%DaoBinBiHOIsWFUuakWHm zqp!PtU?3V;w;y!+z02ob{9*5}Y01gb?0cIH&Xc!%$l)RQ<9|1ZTOo*-+V&ez=Knv4 zxlHc8=WoRCMpG*9tEwjKdZCdwKF0ko51_rf!EbUY7&@(ruBGmUKVcd~w~*ic<8^0C zSM_r%{`}VVeCxEPxg{Vu;%4Oo#qv5V<_! zL)Mj>t#jD+q$}Pg=7Apb?-CPWm)xepIombRoyIX~7T%{tEg_h#Pyzqx({)U2Z}-h~ zcB!|wm$5?m(bkW3%SgVAipqJOp~Rxwv*)A*1zYww7UctGt|F_#6gwUCeKc{j&$xlQ zgAvWopY%?;njmd5_Coe4#a$&Xw`*u#^N!SLhjz3ZUh;DOt8cMe?Vji9$Lt?@V8*^( zW&IOifi~1191DU<`qDd?1bFLnOT}N zvw>bsqm1}-`U!v;a(Ao3&`R)y?6dooCh;#WDuvM zhymA&Y4sMz0WePoAMX%Y03dRK&!pqd-gH$oG$LR_mS<~0Mpk>fO8h4+4^>>81@$3% z?;#&y*EqR9JXJLuAHGdDW1az#|9UhA&~^$6P|y(U(CQ!59w|}e`ct0)Nrx~M zi_1=_BK3DvLGkFaXxGvWOsoniRXJg$#1s1MLHO=KovsdmJ$5H9ui)p|w|<4C(rx9_ zeB5NJQ z{idmTS#V`0I>J$?FnjLJ);Cr#{FcPk5vM%3NB`#oE;q;#>!7^$AM7K|_Ou>usEwW0 zThba_v({xmF9e8-0CEo-d%G4ahlrM~xuG#o)FLrA*DkL6@9UNie2>$yimpsQ>lMST zhQay)g7UzAx5u+z>PRhI`u~b~3SIwcw>B+BB@7s;2-cSskfaa6934-OT9m`Q{+pkd zsdTvLIj=Y8_7DTQ9XvB=#M1=M?CQ2%Oew?^f|i1<;Tfln&W)H_ELPJ2%CaH6^J?%uSFvsO1Jm`1J>BR;IN4w#BB?h`a!-MVqHu6 zvDzz-Fk^;H8xJZ|lEOm!CYJDm z2K|!=6xer~ZPGq2ItoH{5Kx(Di1G?Y9=H;qID(?E1+47)ro@&7{#rN4hKUj-y|?iD zsHwNBNvFTNS9O+{#8pU|$+u zwp(U;y~vTG2aC5t`8NTWu^~iYhX(`@5)A9~;$a4$+_Qi8VD^IpTk7gs(C~1oxETCO zXSg*YVC@H<)M2iC_L7>Ya8ogfxhkG8n||P+EtM8*8^oXgA-U7Tv?BEqck>2Tm@^M6 ztagK}2jqZ#cehOg{8j}K!;$^@Jal8)C>w%Wc`EAa-8qg1&IpH3<~(t$SnJe7P{{&A zpIE^0hB5b*5scmg@9Uo`jF(A4o^Iomof=*4lssc zCJ>rUhA=}Bm-`ju=T9UDF?V6I&EH7E@%zf2gSSdEK|-tz}vc~Ev9 z32#8~$p}0*`>sw60t8v-1St}NjexziP}w_)D3}3NnF^@NxV6?yBxaSQBoSq-Bo>7@ z6oH^{I%|A<^876-KxGe7Sv$>UI(Aq!m%L;MJ&nzrS?}HW6zFjUm#i?mx}1@o&g;Hr zD{0qynZuv3&Y`#qw*-LE(Df97+l%aZy-u2>Mg8`rQW6EN-{`OUP7O=ZyH8 z-5GAPd5%;(Fct)U8#AXz`94)}v2_RDyJva>0d;dnb(jI z`j0a2%`AI$>*Ne)+N!zBdPvz?TuzdE4`cF2CpLCL|H}ATMGc-ZHg1P4kt-75NtO4}C#tmOJ|&YAw+R0;5F^l z^AJ}(eOaangf;?MtiZ;(R9wh$wmeNiR{PWcN3>w_&69hFsWp3Yo=v3&91RN#4m3;J zsqarzjTFMsx#{q0mGJY&;xYnG(L}aTGDOz!dZti$8Ss2qfPWZj3fl-B{8z_6bh^fY zlyZ*!(vyVfp?;;sg>^mWr>?>%KkSdi!FP3$jNd_o1hD`ot@qT4hr&TN*WImA>FEK7 zXz;%l59$P2jl+tZBzA4d!L<9Ct8>Ze(;fQ+Z-aV!5mDx=;Q!2(PM+Kd4?JXVJue$ z*Is54);Q4=5ftb#XGnhUjvfpMaCd+@2?CpjikkY!A3zM^##5Cy-6>aATwJ#mIJj&i zaB(@Ni`<)~+2VeRed9#g=9j$nz?85Q$HB%@ZQbAM7&5-U`OQ1_4b~#^Qd6@}U6z}j z{gmk50ILk%hqpYPo)6oRmMk}ITacX*(K%FQ(7jdLIA55hg)1%|RS0u-v_?-(K&*$c zczQ&_V>otm^PN|-SK&3}xfSD(Vcwe{ELy*Z1pwd}#t4e)fVuY_@RErB>QhnPpxe?;H z#p0j{kxnR-lS{0q5Qpf+cW|NFwWHY>F#Vc9H();mGdMFdBQVIdH$jwN=tE(08-ej9 zJ-ww_j4QV)ZeKvFg+1oWmmdHfEO#M)pLi_^B6=Jg5)YlHo1o8i|IkX|Yv}q5Wf+9U zgH0R zjZm&#J2*GDT|lRzAdkh^c$}SE!meh?xpHIBrA}n%@q>yLsD2E|MEYPWE2^offl@WG zr)+|`_|K(e`>CbEbH{I!4g<`@LfqDESN?zeEKj-0ym9`hrY= zyrW~m&Ak%?Ri$<3YRp#|Ne1s*NGB9A5pKYQa&R<4K~&_9un!P^+td9~!<>oXEh8zg zBlpd4CP1B0ik-L@Xp-UF-k4xAM)aF&9$wQvyRe_659#-MrY-{AwWpR+6C? zDmk1gpcE@wjr_NWDzoR%*ZJDfH<(2TNIM_3zT({LWw(vA%Vc zg|$hZxA?6*D|8zk`D$xz-!d7^>}NkTX>W8r>f(Cozpkj?jB=i?ddXmz=xY4F)B;Zt z47Jj~>*X9WY&AIK!#wr**hOY$$rFATej0rR8`{zG9Ae119QI#TyLUhPfuVZo*mooU zc~WtC`I~1bRBbTf0(ocq01Mi#SR0zd>|SEm1Pb;*rsw=m%2!rFX)Knsgan_5zrW$f zf(96%hm*Vj)a|ACnw{`f?$qu#X(dC(>!38i?sZZMrmr8PgX`}{YM9e%HTdI$SfG}~ zim;BQWhRt&VyE>zPI+_p!#o6NG&C1Fq^`Or+Y`uOteJU+C1V$&;oE$$5K|rXr!g#H zjnsC+fpw!2%vbGXpN$yuMzEk6=F8f4N#gyEfUXG}Y~L$fj%s^K)pO8RP~-OhQYfR)2&bE(G(oKavs&49al zUO2FH#YyzjveWyZ_^${oxJF@*ux5qs#-!D$7k$GYim!0lMQb>NG$aA_y6hL z`!zLBtE6!p(`=G(?)Tkp1fL5Rf1PGi6|q~QBedBI@NJ-(f&gf zMz3O}qtp7BIB9&M-gIt2jmqIOZse}71u0dxvZCt~_lRfhBhlLeI?;TuB_J4!dZwU>onSO>-Nl+kfEdxfy75PIaII#U$RR%18ffI zGaT`v2b?{_wF%B*O#b81f}U5#mdMs$6GOa~*qS#dI_GZdQ(Wp=mhifR9*c#mCB=z1npvQV25QlNiA0zFmj8Dd{iv3z5y&X-Fk4;>z^mMP<_p=Y@Si)?Y=8rwb=Io3gY+Rn2*^n70J zq0i=Bhu_uRQ`YF5%%=`f6DzdYE|V84ByGQ!{6%MdVt}0T4$1zp@`L!FG}o=$32yff z>eO!7*iec@i*NKjPZt{`N^+XiBXhBex#hdo=nOEZjLK>xg{UR*C z{sI-;_m)ld&#%Vgn#&1nrA*-iM;~ z?k=3auWI;;W!Z%R`ffXJl_FdI>*Dh_QLYSn${I-*i?}H{4$w7W`omVwl0p-|=(RQ9xFwZ5^{*R@z`Tc(lRH(Fj-6@>7@ zslToqIBOY6BT&)4XiO7Ef0U!6PwSFUd$$rM`ozsVOeGoVhDaUF3B#(=$~tu$;*c#- zMeOHyLmGFnS8^wgo1NT#e*7su?5+*N6sPUb;8WcSHu5j-KZkF;Aiu_|&A0Y!-;D#j z%Fo`NrlHAMSvle8kUu*Yapv#QH@s&JAK_lU2(fQuFi;4?2rHk4`h?0^NyTVxF(MX| zm}X|CSzxaAfaoI1C`5lk=<{Kp!ts!9R%bI$D-C4Osc(Bxrz z*lja^YnFd@CIVzqj|Rw~csLuHO@jL87aTPM>n@ZIW`us7T$~im z$@MfS*~~>Jkk(RDGiUhU&&%6gGMsSm*hF`FmwL#gxA1s+1yv!)p6^oSnUh0|H?XpMqk0jJ>KBgbwEj5%_(2pLKVU+J;35=ZKj__K$Vpfqs5^5PAg#-l?$udR0*}m4g zQJDFKMhn+ygzW2ZFjC?3J9Y2gej=%`L?%o*vJZF_5s{J9Lp4G|LQY}{rh(s|{k&ii zq9vpMyoTPWw5+V%c2@8b!cUB7u2}54j@9o{8L)??fi#+5sD=-5q&19vp z2KC#cj&}MxTiE^G-oYK4U5VUH>9+;H(3`(nbOXGTq~IhnH~l6kyn{lrcdpf$Qh@stM47|TY2isEn};a4JV2T!#)@EMdie+*L-dE z<=G!UB8?mZ^}5Tx&TV|N{iu0aHlO}*%PV4KGB=Ge0{dm{kwnYz5{2ObW;oV)`I!I0 z?GqmEt-{OSx8EFkSr=OYlly@512i(bcKv!Emh_#6=4BfwsCm!ECbuh5lrx-NjyUbv zXE=S*79vmD7=JOm`SCQhiMl7I1~x5SQa8qMXF@o2bnizjmEOB*F_S-;I!QZT5B9d- zE3OAlfaE6IUghc+cUX>MsT^OCjH3p-0&J-V`D0hXx_l)Ib9Ve#1t@qMm<&oAJlCkv znW~PDpM2jXZ@VNUKK1m$B)PAwQ;zQU;g}Ee)J^B=tVb@XhfUip+7qU4p$k=aTxRpO z%uZ|oX(La&A?^0Z3E1^WPv^x9qw2UoPu{dbb&s2)6BxmiAsbMTyJVLTS1vSeo;r8_ z5usfPEiLUpZ*M`_Q1QBF?Wg-wk9p6&k=|rG%u-%Ve0qO|G2&%>#>W&@as1-W$eMAz zZWovPJV6vVHk{%FTVnenl_I*Yudl>{aF$f0FxoqDbheHdB%dPLT@+D{RDaUWQ|Ov z`!u;1W^<#QE82009koFL@5pH~lRv%?IbXzX(>MqcG%#5Vta+VCMoh~bDa&plyP1W> zj%Zk~r8ZRIB)D8mP_67lEUI(NPu+GID^^?dgs{_=T_-@%jc680m{ja#+%MHwKQ|lzo6A}qKwn9|9L=GkW!#cTrSUem`vcj>Wa49INacE;cgCPLV48NG9Rl zVbgMLKwmc|$%=@)c1njzZ|9F%wKO&+CPoiZVe6%_ghPMxGMsyUTG6fBCz5DdX{eIU z@*vmUp1N);bAkf7jW3wtbkeoCyJ9`#FmX=sJ@@YOMH@!FOsdM<>ZMl~`4l0%dbmDhv)~JTp@{dUTk8QB6h?sw}hqIosY7p$hP#O=3jl5X+ zA@RQPkGkRTHSEX19pkq}^%ulWOz8ivshC#(K02X)Q{w)ggjE)VtZ<*{IW~YK?%Bk% zv@I_8#6(_Cu(FEmUi@&AX3)s!5SSh(q_FXhZL%sAkFVT4cI6BBY1&0t(R{D{Ofe%J z=C;F}8J*mFTf0>=E4LWJpw9HP!kpY)D2Ab-5mf>tFbfher5S@)htn7! z(OoC;;W$O++>J`+`QK-{X9CFsDFf9)@gwEd^H1|-AN3-NV zD88O&qX^3Z7R%dl`%FKuxz2UeJ~eG9GD%tSvns2l9r~2&bI^iTzk?-V@VLRzguSSj z6>B(8!WNIDAm|G6LJ7mnUuO;b$)3OHl&LLEE+>)qe>qf0{)rpm_tiA@#5;DVNecB* z#rpeFDI5Y}pA3vmT-VBbU>>AH{QTJ!)9?BCz#600(ItwRu_|S)dSNaT1K37x`pptI21 zt*5s>jV@Qsrv`xoq4tE&`u6r!#~3$31U4BxC%k&R<2=3a%*4C%E{PUN z-lC7k#i~DtJ?>#Z_>tL7IgoAsymKg{3*10$Jw3go4M0A>f^lbFyfy@Wzu&3y8#~l+ zOtl(*bDbQOAy$)d^>pJg5}X}!xbcL?h{nZu;7Bb;**sX$9QWEGRf)M}HQ-=#*G#A9 zr%a_?%CWJgHN@SanvP`V&Ep>e{R4);>LV_gQwb_@*44P3FFnYu&FWegg*ZE`@LiU- zc=$$m+cf3f(!>bNA~?3WBcmf1Y=k+5hi)9dXu%h(DD{1GPVhW;42@v45xzIcU-fWY ze|7$xVpMv}WR0Fcy+^5&y`Sbs{&eiU=T1w90EMOu*bU|%+c=*65v2}{j z6(wGkmA-(Nqq(^iinJKgFVl4l=;%Di@bR(h}#2C?G~#&=kgEG`wl-AyGyTu z#rfjJi8p}koc+mf&@W`Rp6ab->NI6vD^f+`@6ah2@bl`N^hNHnv%GpUj4rLj8Kg{8F5814y5u9h5d$RRE-U z?~WG_zfVZuDj%gE;*9JD-weQ>i1+W)zkHD;4bf;b;r(h~p1b0b;4PU1lJ9Yd0O!zU zB_N$YlFo8;1!;TypU);;lzj*U_DQoCNk6Je55r?lho2`Q;f2f@Vt?UzW`I ze#NO0N|an2@@5E=hcdu$K9Bm$(p&?-b^+Yo9h!RvP6Vs-j<~D?`*()Nmx5ZRaW6@K zx{1IFWu2PrN{Y%R$807ilvOX1XH{S18312_(UpDx{5aA}4U|;#3=3i;T3%JEl(*LJ ze+``;H^jykFiubW^JzOp^6K|B18^fjDb5X=;wsg5$+0zhgNX%NPmm^aTPCK5>Wf5( zSI~t|o+z!CsSpE*+zn^jJiXD8s$&aB7MPm?nw8p$(m)lhAiKe>Cp z=JmYe&G+%~9U-#8)(Jm1GiEcK6Z-XMws4O>#Txk)Nsq2spFUaSd_%SMhnRMKOg&O$`o^+AJohf++3%V~hG7MD#yjJ+w|N22YoOo&;p55k_dyAo-Sd zQH`Unh6%64S6_zEWGUdDpUMa$CB76wyz7nDm4wRf5AyGU%bicH(XOnrH2uK(+2axkgdL1NRHtGkk^Somf?&hgzXQ z&iN#tkw;IlBwns_lUeUfvU8V*8X_KG4p4Vftbc_I|UxL`!Q6 zu38d$;eDNPYMXIl7jSk|qyCE(LP72JpFiwKUQzI6(15)Q9L1d4e8YT;(djKuvykH7 zXPFR8IVTr!3G+o;w5KSARvaIA)IXmVRVu&)%;C=peow65?Iar#lDJHl*e+FGyX)!L z`Nq$VjEdKIuSZOx!u+KstLhKLafECHppSYxxt&J{q*L{{sk>s-KIVPAYUYxgcr!r! zG6r4S>JTKtcqw#U$l z4h=}0ynGg9l;s4ce%Of0{)Fmh64afHrcsF^)`$=1ZLW)45$aMMSz^NhsdM-QlPW(6s$ zvEuFp2Hcpp-bN}aAuv&(k`nUIzMM0e6U!74%HFaC9Vj-iB$4*#X)d|kXMm&UFWiVu z6ni3lTYhtec7aZY+lGn03*|Cthr=4G5tFY@2uXbRq_7A9RPbKoX#MgzIkhBVo$T|h zCtfV+Knp^eWGXk#! zBBE?;KTo#oD8;ETp%8&@?;t>_0lqM za#W|EhNZKEQUe6E1YoY0RMEbmi$udO-w_`R8z|eFD;6;5KR#5uL1W8bl8+oIiiHjiYUn9W%G#x+m4RnT7imt1RPqRb!I__f|Z}AJGn2$}*h@ia?I=!8z-T;fmLUDavuo<|k zm-vx=*;<)`rk{U^3whpRfL473cp5l>W4C3s!QFbx-jY5$YwjUlV{L1BFK?J7Xi#~_ z1@!xA>OU*w4|jC8K6aCoP{8C{ZpYK#Y5EQ43d56FEAp7emx(DqZ)@GBE&whjn_?PY z#LMsDYAap)X(Y|5ztuiXG5TJCB2cmdx16!aVO^G2rUjckP&0KixaF{4zsm!>JRDOLO~y<=rI z{XPEb(Zh$*+?gAHD$gcWFRhRWK3TtDx4Sd9wY&C+In%~E4^xQpO&TkoNU5RP`PBc+ z_f3e961omISjfT3YVkE{6>JY^jaWVk-J_T?`?DcjLK>E3@lg++9UK^ANy2274Y`$; zmx2YtS$r+h4;)Etc>M-sZz)G){w!lwauopp&I*DaL2;pS+Yb{Se5o$Mv@CByaQAz}Z z95B54Na)-+<02LjAFpf*7=;{I6)s?7vopQGeQr@POh_%a^%63X-1+rVLOSP>>j8JV z$*2Sk1TkzCFb-go6U@GZ>Nh3(i8{3fivTNapOTedFN0ekcP473+nu5U;%6b8Vaiij zq5q>=gc0@6EofS@&f>x0&(rk&meuXio1h2_$2)_RC{HG2mP@&FjOh$eDf5v3Gr_nN z2O_=c`M`RX+1p;rx80awiE&0vDXC-%LE(YBV`64JMyX59O4^&-iyXuCx(*j?DGn%u zCnX9?I5XHcMoum%Gf4vm)7;wHZeI=$PD#ncR1@XbLapCSow6!FJh02RTi^AzmKe<_ z8xnqyXWks^p>Q1Gw_p0h!QYhL|sq`;qtT_wXZGP8ZR&fM2U0#t7!@&Ww7h9>+RREiWnC-eG8;I z#%w9lyW*3>61Ijjg)S!#CtTdbdALPscvtps@4jyf_qSKt@p%4nU0#3A8$pu`Hir{_ z13#JTSEdxdjw9m*m6t+2?xGlOs=7l>WxI9j2tfP zOU`do*B*#9x-cCh_<7J+B{hh9Vc~t(DqZlfGjG}*fQUXta~-*!`uZ~)NDDnZ*KON4 z-HxvUQ;bxNl7yEMgZ;y z{jBqmNW$d)-jWz8&lI$5-BKm&dt6Djiz*31HaK!t05?S}GP~=4ZpZo-P%k z`8Kn}2db`a;*>+!TlWvnCw5gEhwlQN60`(*z$5JGK- z0x6BXoXcE8@Z~p*=@t}*Jd`~Sv|IZgou}0v&07$28YY|{mb&D#H zSa5aUX7(sV^|Sd}AUOEFMYjxiK{Lc7L;XyAp0wQoCx+}#0YU%Q+W=_S=doAqj89ly zqQF%m{Cc06cxv;-lV!P6X6&8H4tr>297iqq-VmgR6Y7v+c&RqYMMQW28{$7nLO)l< zv2O2@X~3@$gW>LpoRnZJf~>y4)~Rf;h)rmm7!@jAH&$)`?Smj%4 zl9^esT&*xk!Y=;~Fu?B|PR98Y_dj>lj2c+<#1)2bIwY#PmY!+Ej4zVe;9tDBnO`wS z&E;lcHFLP3aC>J9a8@465F*5>efrr5mI!K8dRW-KT-^7IMExDHLQ2r)6$18`wVB5M zc6%YjZww4BH-nOXb!DYF=-B5hw7;9%k-VY2vo&-^Tu&PNy!3{9cA~eZVb7x-ygWmH z+-_XJhkF3#6Q7tSi0fq+1`c%w>!&{puF#)a_vv)(`~jGbhQEpD`*ruJTTI@cP8HBNeZe?>paYF0$X-Rp4js@WZkJ8#mN;JXQ^`Xo_jxlGjrQW|4j-Aqud zt}ZTLAM>|a3VwsfPe*{6I00>gcInVuJTTU;uB$qj_)@K$$4o@`+#+d~SFI7~-M_As z9lDBS;#53D#YT<2mp}QLc*^*s8F7C9VDrh`_-*$suMC||6$}4R=j-B|BBGdu`i)5n zn+GY8SCRDe6TaP3llbdYb?5d&jI{c$Z;Kx8jtV&7Z`h6eo+J`l>2?CICS|`lM-Qbtcga9ya2$yg`kRJoUtCN5yRXh zbd@RENCVuOevhmpSuaRHc-|6@3RM&XY1KHK3g!iWY<6}wIvwDw?G@2+nFWdGSjk;) zV$utZ+?AXBl?7E|mYB^x%I$^F`cBPl6{Ytc%f~*z$w0eoD#R#Ce$N#tvm1itI%#OX z{p(sSvC0`{ilD&NN{PHJ)xD7tzt9!0Ne`_Lj7vJ;Z$`K^3z`{K-!5=4$_F*=n!iJL zvR)TU@@#aW%9^6_esYqe`1VJZHtSLjQBl!(!M3(GLTjR6ximodp%Lo^Iy%mvW@(~l z_(X?GXZUgZ*I4n-7a zv?WIO%<)q!arW!>^HAE1IPUvQOunF3X0%30?tk>H+@2gzXWaMfhnKn@c-P>_4y>2! zt*lli=f4g2OLK3eH8GNq)8*(9Alyv|T#0Ps9uW?*1? zJJw(8Uf2VH%Is|yleBMO_?Av@&v-&)v(_z{F)z;}#*^ubB&Dz&8yv};)K7D_AU1l^ zRzJW-jFJruiho=iHv#ejUm`rI*!?-b3mH9~H1XSWqIK@0l+TI#uc0okpIJ;C2yj&k zfNs(QuW_SejN1&#y1$QK9q>F6w?bDeuoaR!>s{GlPcqtj)l7^wUBHu#%pUJ$e;;u$ z(D#e7Lpg^3E|fN<6zhC(`n+_&&@(bCC;&xhpoQ1=6s+p{L{5Aum>AsNF05oy;o?qI zqsd$LAr`G0JU5OZf+=);+CM0^T!@!0AKQF1Gmaf{6)|7vd(Cb*1qfzu zW~(ITr;Pm8(Bj>kLYslGmG=H+_o^mb#|eG^%e7+$jx3@sdkOZnn`4oZQG=sS${9cE z!$c(Oh30=#wuf3zCZgZAS0AXBb0@eUF-aS!!$`vNKl3qDOp44{wC@-&?tH@TqZiA9 zbsW|>_$f8f^UUYjAvZp^!(p>(1xQb&k0S7sTS3%ZeVBUu7PEcKyAmQ5SmB`e=VgdDoOf-D?owsQyv6#x`W5M9g>~qP zUg^DVN&JuGDByx^HjGSe&OeqkAjZW^?%@+8j;$a*J43)9{T_{$<~#dDjFBZ+k+_Y< zxxl%~+wgFXh!fFZxtX@N?lNf@2C)uU2>~_R9{4lweCdp9h)k8LhbeJC$wQ`g6_{7X z@u-VV`#(RWi5a+QcfY8tS>YnQhUcwcTbft~LohPoO}gDGXeDyyRBRf*nBmV_z|l+3TfN-^-^T z;O{Gl&ae=^z_$Fx%13pyM_pukl-C{aUnE%_-nr7Vd^jgLjz_IbK}vJ>-fBZhi6E)} ztNw$CAH73Dwc(AH;F`RLN8=C598fB5k_Z!R03ekmO5Dt3^RX{;+-lIe}F!?+N;gJN?m1Vw^HA*sK~H^>Pc6fMz1sikEsAa zOsVwtrS7InKVLK#E8Nm^UmHe8wYL01zERSyol0qf2?p^h(FU6h`s03)fuUb zR~6r-e-5_ig(-oriyMlP$LXOcWSXi4$*M)-_hg)}o0OW%_xBq+GLuC6DMFm34r<7+ zTbC?(Zy7|XDr-zojx$%s8J9Cb8`&@smx?9J@2=mf`}0RvU7Qg0SUeVe!%mf0$P#S3ZMwVm0P*_xk2B3wq}P^ zF769J@OUs>tx#(jizg^kLx))hv_RXrccawoE7e|=89-^9*~z0-Pw0*s3`0B}0@7Je zt02TYM(3Pn3AX-BhEZKP8Ho#|rxRz^^`aQb z-8RDS)%N(c;aG{*59LOjefot|TeKD6-wJw#wlhxD_0#jSBuaASw>tepUsiN{<~2o} z5&Kg`8;1Q5kjJNKc6wqbs%wnhA7xNP(Vr2wL}9;N_@JuT`{BHn%XmnPkDCxIT}k#2 zb_n99f@Qji+IfE>e|SlhyEAdB??1BrvL(XLbWW77$i&lvW*mZoSQkReM(UuKx5eZ> zblGSRCi$rHL1Ka$2)Em>_JHBDB^KtjCS6;xMx~>D?k(w)p1Ta!Qfj2OK9s%X7P>!FfF00 zEdLfL;m-vdyRdTaA-DxXx5OAF57KA=L@;yICDlyl9f&Ie>!rt}R-la;{__X;6>_(? zEbuK^$J>%FK|qOTgmk?>39k*g6|q7)p5xw&l+^)y-cZuj<*Ny=;{Z6CLrUHI1~c*$ z9OB~ooVvu6GvF-Gqm{TdoSgU}xb+n3gO{2%5vwG|=AiI1QLWi(l7RGSmLwIp1`N!E zAKKPfs2g6%qd>ee0Nn1*^C4`1-)D*_3`Qsi_k9jDr1lX9_PAHpdjF%Ouvqn-I*Drs zIp?7B-AGPEedL^MKA|!j4HRfg z0sJGdWEMhTVm?&`t#rq5)g2J8!c~0AY32VDO4RUG&tuZM*4Tifd^8`phROXUWn~=D zHJLi-L+kG>@{GB;IU6WA{wAm#`_s67OlWLw0|*G}o2&^C=hK03?GXM8ioXbmEN14! zha|>Oeh_+DJoLxX@C8yb4&|3ma3FCr4y%LB=l5HGMW4=acjr!@s5}_|gasNH;00h7 zM5u9uF3#m9hEF?e3s`A(#~lEJ7@eMxah)KV16pk_Eeb zh@-qVQt$oh?SDA*G(o`15jr$SWk3maA*V|JdX<~nyyF)_?zVmV);CgW11StyG9=s9 zxCmY6bVyQo@#)tN3sN|a>oFVss}ls^7z)%wvd+Y$vqF&5ED}x5uRwelQqSicKAK!0 zf};^TzgyRJ_@73KDVsG+GJRfb6uXnx3AXnC?|Z zHjN=61FgS_g^xz}nm-syWq#N?%x~4Wq^zc_tPO2dDHtX5Kz&sEV-wDtY0>UEjo{6A z&nU`U3@P1uuucS{Q0HqG!i)2P`ZeNnVEUo z1&ZQaAk*ODt8v}bJivP)V@Z&2Kh)#@&VUOz^THQ?(PDqG|xP}ySF>xqQ zA%5*hiC}v3l1^D9M)?BSReR{gj82z|V9?Qe)E;GFTf=ba=;O#*Amf0eJxpm~k5&`< zwRV^b+?CN@tdY~H$jxeXr2U(A;`cG@w;^gpEWRbHQPz(4plY!ooFzfbLwYdjz55x~ z`4fm&_sp7Cvw;YTK73s|@#V{xv#PDH+MzeIMDHQT@0}fn1-?)^6yYNg1~e$K`Fe|o z#lyIo$}gi9eAF(){fl(8Tli=HKvOls)snXpq%_#m!cy~8CWUz489r%2VQP3i1gal0WH;$<@7b=uI!89;(ZZ3-lBESI5D@aLCOB;rWLo1 zMyvESCqvG7R#%>o4TnbP;F>6*x9QmqoK8e#9lfZ5X2bX6;fMlscRga=3TtZ(WT~bD zb7YsS)GH9GLNaFyyzeq&LELs>mvT}Ek#$7O+=~Z(uCvy;bIh!)@@VY`M)Wj*w-GLx zg@p3$c9`Y#x7U)-bkQ{laU8vn*KKL6R9oTA z4SMD7wl?fSY~7aoV)q%LuO@G6jCkbF0vcXZxlDz`>t=0kk(xvQXduYG33$cpwY^k8 zhZ@~*-|ZeE$Gd6ALpKn(cwGoorm7DX78aabT=^JmWx$J%kGE|P^$&8S_6&9l>zJ|a zHrn(CX@4jGQNz%(xb{Iz{pqL1yTu>?FNHK-oo}(^(YC;BrUgR52tyb}5NHFkU z1M8c>NkT&4(MQ#RKL#>1*e_pcf%XDdk$o3|x;nV>6X;WfaXdB}EvwGe_cX@51=5E5wuDVCNOVpnDcy#U@>8K)nGR`-YL$s1hEwS2T8Kzt|L z<)AW2pN1?0U{*l-%xL+_FKhLL&B+!+ya0~@#=`}QM~XYMr|Ug@ z(-!Dx&3OM*XSh3tkP_a2kj)MVkUN-dh87e+rSTCio$p9${_^DnqZIWUVZyo>VD(Wu z`oJSY&o`V#(996B*j$w;=hAPZp>ynb-??{COMVMFk?5i~t?}GCk-B^0nn&Bi@6PUT zlS-peTmj3W5DSQsxmyIrNpZ|C(+;dHUSqN+E97vEBthwKZV^H@Kcv1}S4Jj{<>lbO z6=C5rj0jg~j9a$*xNFqXwk*)17bX)u({ssKA$>^$luDVMrz%&cim7|mI?%4}-(WUQ zI~H65v-lw+13H|psT~5fLEzubdMfdJX32^!r1?O`nW?c1e_Utngu$^?9jI%jd(&qz z*CDGeMMG}oZ_=3`8%T+){84v>^}xP8>);WO<)ZSItVh?Q6T#$z_801C?E_>b@QPWV z-&tQ@kN^mvWVadByOu+W?1SpVpBEx0c1dT|3pI%3^uTfTT?;b)nrNvDB*4U{(}!Bl z{g=8hM@vBC2ZRX%H4ehHU(JiHX1+z3x+;Mk4Qc|E#f5W^G@MjH?Mw61 zJbruU|DGz1S$vWdtYS+MT^enO+%*;!Heq4mX+gfjO*MEt`rxOPp{xO{TRjTDO+zvJiHz9+a27zX5a&PEpYZ0LWjt z^2-$!UG!KMHRj=vG^5j0RFrrcGh3aNcf>Q6V}!oa*95`Ez_3 zAi5W!5SEztpCZL}$${o6^j2x1>J09}-|>>_m#_BJ*ZujF{#(E@L4^yxoR?j&*etM> zq~h`Ty;Z`Saq~Sy9}M{nUnAQtTY>pcprGT6)O&I`d3BJG>7h28XW#9E=A*_?kw6`zkB<(XVHZ? zse6tt=w*IE0m1aj!QniSeeQVQ81v5B#H$pDv+pLxKj!CZL5kWNLQDH$+p?nB{K7(A z`2S@Jl9ykyG>wf5sW|V=L!LD{{iI0e;H2*%G3k*MynTuerJwBH<*KNrq|~paCP6ji z4Lr|Jdik-urpFw{j#oj2I1J%qVa(S?>~Kx(i)LyH;MS)@1`1pz1CWhApi+LIe&$Tb z!M9{W#z%sxp;Oy6A7MHAaQgmh>|nD%(cqzE5W_T9f^r0-Z2u0rCK}*SYvaT4?h_4JaZMdRa6T#y~Hj`2n&gHlqak z9t*c>G93+~%L-Dg`oj)X_a-^Rr&nDze>YJ=l1!iwN=Yf`GDRTpI>!5+*~8{G;EsYS z0B|&u4^X$Va_jiCLS-3#9Nh$wrnF_jx;d4UKe*Pd3P&6JGm!Bf9K-t?ZZ0l_cq9n( zMduMdI)DY%rdl~UIhDX1z6aK&B)e29kK~@VR$+9?_xl3!%m@>L0K|T3)-4nI9O^h#GmPrFrbO)(z!&FOmo%LTZ(qz=}R28b;*8ck4PY>tUAz{Nf# z9vxHD6xE@Dg{{wqxLJ{m#a}@!8sKol#mjMd*SRus+_^p!0?t+7c;8bKjSt%nbgTAHhcgL(#^W6L2!5TdLgEGeq_ zavJA0cG;>Yq0{|luJJ+6Vz;iDxz);+2>Wj8=?f$X-Wy=!rHqT0S)nvi{+qt4rwUvl zIMA6;LH4Vqpyqwq5cf$RU8%ic8EacxG>eZmYO;t@*&$;BdEEWb0?6 z6B2Ku0AgDM=)T|Ev$C__^;!-s}i#us@w%PH;AY1J|WZd zqQ+dqv*Wl<2j8^kB$RGvs%NWmU8XvnPeZ@}uGHAMFYL8tuH_RRHYf})NJ%h`z{C7t z+@6!4zg!gn93Yt|&v*whm_=5p-PaVCZ!#fcr5r-<;eQB!@O>$#OSlVyiC-JG9zmll zgT;$Jr2Unnll!=M__L85%rVG#A>aK!zGgkAGLl*sw-%r*DGq}=&|My@)KXEw+sDIq zs={aJyXu%z-#vyPkLkLN!>5)H^er7Ggrm_{%16gnxv>eXCny4C2zv*TJ5S0Di22}3 zgdHaGpyqtr)S3eNAKNFf?&CUDYZ;Y_Ma>#4gn`{2umpi(GwQYo30H1sl#oabBcnv1 zW$xA1blE6?wJ0czAf5;LFa#Zzs`1{V=*u&B!_Xx+y5=Ke3Qj~yiUu7jX>#zIAt7O_ zl(1f0tzenjm)m@Par&Su`J6IkYFe6%vG>|b$%9R;gB{eNdsvVne5u&TH7=FfhXEO8 z-a!wE5I90&9k^B4r#h98O20^&K58or=^gFMZaa(Ek`1*}+*R{e04634$r{?_{R#A_ z_en{G7-N(nl(RIPDy;I1t&@C|Q-B*1ls393EgC<2o|{Dj*UP zdTVKmAg3zCD`2oaZliQD_nZZ>C;gM6 zOM?Db=91DPBx*`>SBn<#Hr{4F9iv1$!DL55dLDW>n|YhRud!$2d6KO zNzLdogCmpS`lNcv=rTxKbkon|A2jEy0{cM_Z9;#?dAP&;IrXUY!tUst`glGaT|)_# zDOMIj3M4Gm7vMX7ATa0-YxyDlWtGpqNaajAj|>(lVX#U8w;|LHMJu*e5Amx280cbL zvj+;5d+e0za^o%Reyd30XteSd5bxE zA}BPJVsL1Pun)zYXM@GW#I&JeN}7CFPF5D132r**`d5$M6CYG#uOLA-x&U+hkviDD zV1g^4b8jA0#*vkV>e!X88w+Qerh%A^u^`k;< zZ?rWv2~yqfE$+{02=+B*2eGnnPEcpIX>q5d9Tgfdkp)L4>(j4_SUUa9=GR)dboeK& zzNhjdU>C&1WJ4PF9YYx?s0z|%sVYD=)5T;So|`9FO`e-spbotRt3Hj|eZy@J#zydI z74w^av!BCp9Zd{PJUAQxCFOu4uJdPQqJRR6t~y5Wmkx~VE!ZT$e1jk)*uBT~r2Mfy z^W@@Cg?RsPY23p_f5&I;fD+-)bmuIK!n^mf56H57if^djt7%4(<5;@lSyZLX`B@YG zuy74;wynFEYdW=9i1{X3jGP-)?Y=cN^!hvUyjo=DHJew)aQWDDE@XVa`fNcTUTJPiHI6-`MD1R=!-zMdmV<|I0Q71|7*i#IvN^vUK(w8_i|v9Y^5{txh)-+gYxP)#a%dn>_$f8oOwGh|4>M z?VDF8)I?~07_(LPk8;xXon^>DjjF1ymVcQ*4)@enQd0V*W^6oJ!FZDh5h(?>duN75iHT|C1!;9qsCvNv21ZA7-@QBcpN)}sN>1Z>M~5=pkP|>3h~zvY zqE?3&tEq+gHzwou_FB2(O>Q-JKgF%X&}jbJ&Ae~c9yi0XUrVgGsT=&68shm-iN!fq z1_;qgO-)UN?F*X;-c1!Ecls6)V)ibKou8i{V94_keMHJ!y8)jY8}A(ZE6~k4|B$!+ z*?*Nv+>kH`!%IwLAk+nZ`ZT)x17Y3}4XHi7y(utEFsum`53EbOtoBayYYE=EmAA5D ze};krWR3!SF#1cN62k92&0s!!7|0KH*yee8HyA3(JEYkzXgW9)dU|;Y!Mk7v>^Y9q z!40xDs=j5nYVbCan2Ca3tyNxlS@8E$6QJsMMsP4Wd@5nWN9SIh=%4%A(BLO0CpR!T znRF^Eu*nqp0-{^}hpm%fD+2EWI9iYc_}Z95?*=vTDTUtOzl)#%svs|KGNHP8aIm8m zGvVeYZAd)fJAZvT!tl(+VJpMKQjp{I@AHVfP1MpEK#KWel%e{P(msE07Fv~tK3eMe^XH_2O@xj5<43Y| z%2}zuI2v`ts1yN?0QK;?`)zO`VGq(DKYko)N^7A|Qg=brz|~O0_eP&av;?LOzBtcU zi`VeQW6pV!zLb6=mj*v+FI_S+YvnRx9Ng&q!uj{tre-G``Q2WeEhH9q`&y@(f<7f)3p;& zkl}w_?9Bh&d^ckqijjO1*!BIw@FLv#c{m+AD*_$}m*sB}MhUahz9x zkcxTu>pTAzjD(LdVSrpaiNpO3fR$N^vR1l4h9&*1s%HEYSERtgHxeGT*`Z!Tr4 zBNTcaSyJ6csy2Z_vx6FBhgNF_slXLM3~o635PXb2)!$G zfm8{N3y>QSzs1s?Uq<$6sfv?TA3fdGt<%O4#h*8(|Nk5`M1#RR7TXJ54053jH;Gae zBj`WEC^o;GS94T{O-W4yTdtToq}ipaR;j*f;0jXAH%;Y|c~IF*^YQ6wGJ}x?C+k`P zCG>mICMFLSTAjUyWEQNads2amn-ZFvq*~}Qsg;&*0gILXPYyfw4qeaKmxLaS|6UC@ zys=8ggkGd9+3D%BVN&>t?UixPz^0G$JGG^yIzTw=dv{fSU}OZsgV6Lk7ur0akCQ=N zb-xbs|8Z!FoFoo5`(LZ$p#5=y)ZvB{=3r;Co<$mqCRo(+j6Q-NC()aLH?+@fJaHs^ zwX;&rjw1b?wqb$fnNBkRm3JUDRl_-|BYTr_~i__oCVo>&fi>LQC2ej0%K*)!T za~xI;#gWH5#x8omvD|IUW2I>hfqsU*F5 z^QOdo)d;!v<~RKQK8?0A32$~Jp7~%9OC~na$Bgv!cK%pb;rg6~z17_C!k%U6{SqJ7 zlrm~+1@wf2UHIWI9i-+)r?5m(bN*oEtw>m|e=omL!)iAb&6mOJB-Hv;q4vy&?Sv_W{~hw*zZ)*6*z*3*rvPlY22;a? zT)0g8j^&{DqW~#I$b3wgCks;FiC(GB!Nx!o_or?go&HE=HFquF-Q}<=AD!-hnU&

hxsnh9RTqxb? z%FRT*g~~_&<6gtZQ`#y0hJTcH6HJ(GcHk@Y;+igc)%!!%^@$5;r9hci}Px zb}wuxip4CG=g_K=#VW~5#{2ST)7tHc2R=_%xsjR~TnXX-C2kNmte@S!-DslD5N3hg zNdxRmGD!^{04ZF)Z}M!Gk`U@6Z}}&tIGXe0dv!kg`zdvMD|dZ%#)CX-g|afGYII-5 z2veDl+*3YOxgM^3J$&2YN&CBZ%!k7}Gg5nXSKggs{R?~l{UQnvzycIQm+iwi-`oaLEuolfbQRyyVZELJLRkwbIlHW5wSNd7qGjZY}* z;s+l_g%{_s?$?kOQWdF&*XTt5d!-xlpwLZLPLB0hQRX>*5st|!g979z0AvY*H?2!p zkw%5OV56svZ0;R|ml25C&_xx#`Xa#ekG5F{w}{3>ed~>(DCl{kR`>@z2*`k~t$~Z0 zDer6@)VscR_~O*8X5IzZ+5f#8{6w|kZYI1yoK9;Bq|E*JQ3DzwH0Puda6H3#NvElRS z6UP8aQ96-YYg9-C=o_=mG_JM6UlObQ_MB0>`SGr^1Oz;yG5Q1Kfe&a;2)k47(<&?c~eXwq;j>RfOLPkeiq-$5$zv(KjZCGjD&>Bnvv->(_ zbqbT~ORpR-@7ROd1UnBxte7rnCQIO(H2Op0#GJQa)7hBTQP}DgUiNAkJGi>q5qd~c z^fZ5h%;3#xeSda|AQ|g_sS`x>yVsv*HE+eQY|Qu^0v;_dD8qBJtH=C(D#0Mz7<@E<>l~Ib5;3sfY*5D z0o*6p&pP++h3a*KY|O|oAFydDeW>7jrCGVKRvRZcsTreWA!eN66r3@FcbQYUp>_iH z>aV22l7+b_Jr*SDaGvOceur}(#Etrc2xbS$b-|yMKOZ-Q2i35L$&1}`1F`n0ufNp7 z?j4KOPONn4_GUBcPsP)_hx1Zg-2o4gecQi;6ywtH@5f5-iHM6`LtZR2!bFC+KUx2; z1M4SBb?OAmf$*uAj#E2GS`k4BM$I$iUGhJQ%F5i7Zwh%V!Ln!@8%vpc2U|CRNQO`m zL-{g*9yvK2$h6}Hnzt_K>*xq^oUrj;-PrwSv{qtsWoHle00fI5FwVfI+a`?ia!d+e(<@jO{?PIssl}7-;R5%gQTCEBP8{F8|j^k|@S*EkmoAGLO_d>Sp zjfX0>9g^rQoR&X~WHyUk>~^b*U*@YCxBYk4lBF*9Ce`}fNg6J>hc4ml7G+%yl}*K= z)C_wL@jt3qusd#*Ta{dk@9l-VJs4rq?#(@hAau1?;4wRTG2fr5ELdxKb;{+j)EjYJ zGt2io%Uv}DBnP|vCTq(me!U2GpRMoy* z09#G_L19*wy0h~}#ol;NPx5Uhrl|G^%h4*-#Re#Q)AS)~ScL3?t@3sc#<;+$<2!08<+2U%yRQ#m&Jy5a=`lsuH zFP0@OjKsA|a+Os+72Yu8Xtk`_V2SWJ-%i%(Vsi3n!EO~nN<1Hrn@z7xQ4qvaj(ijl zn;gu|WSrnZjzp{)yv0W=Uyry@pm<_%@+M(9?JD^zvZOT;+z&s zww6Jph>*Qfm~7d1Lqzs{XVf81){Jb~l6}vfJ%l7C#*)3V8%&rXGlu_nI`8lIcFy~s zkIE;5=eeKz{;t<`eFK}Xmav+=O}u;D2FtCNx=5bND=yaY_TEa^2seEIofxQM`N>S? zzRe%Pt1PL>$+f=u8ekqi?y#A=afy%b#Mciec~ryCbjgJr&#SLD0zYr)-QL>Um^=vS6 zC58RHj{n^!v`-Su0eGsuES5OB46RyHVXODaO52BacF96-tp)Sv&)ihW@Y!_Bs@<^w zmv-%|@4&#oQ~G9fQ-Ibds1&+r9a`UTK28_-^t;uXPy1R7sTF!S@IlyAWA=&v_IN1o zR@TV|S>35>=7Amij7H7fB(BM*CiL17^0ZuC9BDh&F9j4Q4r58QVTU)dlQtYlCsFHP2%4)n!505)gYF!6h_J>N&? z#d%2;39@PoU2yPRCRN3=NZZyhBsfF?ihnJKf5~%5iuI4vFhyZ3GL7UmN zUNnYF*Qm)Db^=J5p9p}!en4t>|Tw{zM#iT|@> zy;yJQx|dW8oqojB+$QCuS#Rup@t{7ggZ@VA*-6t`XHEpwL$YoB&+^=iI#AxJ#stOYcS zK{`hh45UYHZ|?U?ZI?K7b#x3l{J?*(0Cf$97~+uCl|}5z zC@*s41wO%9GFnd=(|=VkGl?2_=CA?+$zsh|BV@<-KJ?%?j$io5b3=Yh_Oa4C7~+Rc z;aaHgZx-Q)x@)mOnzf~0ALyI7^7J2tumtJqQ4kRN>0Y(9VNYLCmu`RxdTDaU6q4qE z+K=7qLA*~bEGrW#Erwo3$5f)wOYwL-RtvTexUzOF>9o*4Bp80%N2@vih6`*qeZ{wG zaq~NvOmBQl*Ng@n{8#rICkeWD?mU5r4UCC`wlm6MhnSSsXU?!}(C7c&+2RTS0bTy` zc_nU9wX8CuN{5TrNSif>o#Q92JL@{}uJ7N)KgLgBW=@=La4Zo_VpHZU$#>wRF`nsV zvuk&hnZNp*D}yON|CZPK1N|z*eGq`eP7>69Q;N7(ySj55X7uHZH4RU&nG$nqYQ)vA zj^{cVfz7&cRG*63RL_&GRIySwC^5$6 zr7PZUs&~=E5Oo=rRZ5F;cW_B6m`pWCz>n3@TUDSbUtS{?th$HXwtf84Y7Yi$C75X! zck>~I?qq}pw|=N<&&gsxaAmp4HezsEBBvom*{~L2J*iWzn&OYbR7eP@sfPFu`U@Du zmUIn$8yKRH4^F>-@up}~qITePXm>8P-Y|Bldd@=CH)W#PEM=MHIpPVI{f8>sO6ims zm~Q`{*CVc$85b@-pGlMP!DWvwaHRXXe%eGgE+`f&2JthnOFYl@k~v9>An6P*G^-7y1+FG75?Tu@MjLaGY{6R ziz}h=Ir$pX`iv2^uBvaRsO1NQ&t3fmViK_qSCufw8M8fd)TvKw>5qf{{O;Vu!ek|L zWSdsNPAIyc_!z2H#d2w*wKp*pO&8T_SQdoF4Me$lPd#0<(TzeZ*eNCLEKK{382vuE zNvW=lHLFy$t-Difbb6+3sLp92bb~M=if^>Cw0Lh871CQ$U1d|?i@UDW);h1&xE*P- z!jY&>;ha3d8I>k=ef3Rniy3vh#hn`Ey838)^~=ka(n-26m$_p^Ejl(=!wkbnvG%sp zcdMO#4OU(&LiP$D$SK`tmq7z9C>NZj+qZX5PitF?)_hpElZ)%zy9*`<{4zIRb`%p? zm1FY8+1D@kDnS<>a;(_r@76EKq(SXmL&L)GdhQ8Il zSmOOHtl4D=XVe{E?#=_znTcia9=%kPn%;EZBd+d_X2oTN6n4J`>x}Sf(ef6CleiI* z$bp7I@s~pq2T#RlSwJzx0e8l?mLIcEno3V3;?-1>hZNAWLr;5drp&WV-}=w?g?~*S z(~1WD{mQlBe?&fSXOPi><-HXH=>_=PjFyl~<8B=-%!W;qvWp4I*JkN1Jgj>b2UlA)yBQznonzKOQ1ulbmJCDrd(_l*117+bVZ zSe9Ctdt-8hq_pFG=kx#S2Dl=AKa>l#8EhaRh_-@m4q6)O z0g?B~0V~LepacTmS0uXu25+iA?wetB5N-eP1-z4vj%bm4S6A1`DYFWgEF!+bTw_#x z`#sJ5ww!f@9M#x(ys$MD0DMnvesscbIe*kP$m;PhRBAHvGl%;7b1N#`#ocjt&hMm% z;SXIf@{MowuHfBiy}kLmn7FY}Akf5v^jXGn4A&eu{J(qT(E)R&!k8@}CKfZDPh6xzKH_oQqz#+?*BVf6a zp&`#>9Piioue@oH@LD57t*eFSCLmp-=$o-w)A*tJkW&l^Sng|$|MLJ0{(=WU%M@77 z913x7EI@4*en@m@E!Eq`M@=^6N0kUX7xwqTwc!ZAL4Z{JqxL~LLlzG=uacCu|Kvuu z4~bTkT-e+%@!B;>nH%>U&%|_k@ng+;=KisD4 zb1H~XLJsogrplE66lIvm6HCfjM6C@?+XG%Y|JAGeT5tNi1jG-C$4;B#wbC8U>tWK` ziRGy3h*gI@3AqB*>pl%9tDq~bjY2go_qAr!WH=+X9=;-tL-FCR z_u97bKrOC@JKLcBzYv_K__nFlaC$Md%@M;~2+NHmhCMVB1?IjnXVKy?p|<<-+o#^T z^fJ-oQ-k9NzCX+ZKg_>xvHj!sc`OR&UtmmbVz5ga^aoo*;BH7Hd8J7 z;k7@Mv9A+y*p&%Oi@k}ibEF#!(ilr7Wrh#{=nkpY7qJ_P+G_922UxVW?#E=ZlN@s| z*eU06i=bD|c_)|G?dIgvDRE(&P7^3a8#^ndzEd5U50?^5Z1B&ni6)@u9~=LpUUO2Y z#a~UD^c=c1b#`QTpj%6m`ZXoIzQ0WMo=tq<{t*(qeUIOU=1M@>2C4?~2Q(r~Ga&jB zWPU!noO*4VJF6~vYM>VDPFmcRcx`WhH=17=V!#^r25fy& zMZPG%SBud9Xz5+mzN_v>nr5kV_sA0rSd_%NBp=u3w*)7mh*`68u72@{CHDPmYg4Bi zeeuigx_4n;8t@@m&CnrSwR@53OfM^#Ku?0MuZf8vB*u*1=# zwkkTo4l{XHS-hX2>x7wlCT+i#ci!!iAGNDXjMV?wUP#Tn^(vBQ)YrZ2f=OrnJL@6; zJ2ho5a!fpp)zc%>d=y$QT)-dL6y>iD4*|(!D{v!Xct;(I7$iD7ovvI@u7dn&x-;Mlylx)dEjZ%Wb z&yvxow3prE=0g|X;Ls=x1(-JQJ=t%}s(XN<9q%bG5-wx$nhF*jkL zMVuF^LHbcZA;5c52iezf;P{;je>C`rn4F_dHmx@HFa)_z>2Nlpm;9-VCw;%2TzB&j zVB~z$)eu-K#Kyk9(YfK(Mv*=sUMn`#4uaMH`_f^9>O272YmBbcj62Z%Mtg#Sa9`wB zGx0ut-pXEawkUnVB`4LIrGpJ%1h$VRx!A`X{ANh^ZFy%ksXGI@rNowj<099p6)`(A zvmz&}%tVu7t;?Zc|Iom{)BtztaEK;{ZdhC4L;n2FMfcwP;Utzg#gO(nCM~6+0vW&EK0-L3rlP*y$(OE)_yxA|Xwn7(5 zWnK2ExZbEzz?(lcB-#IYg58ZHeIQ$4}Q_~y050ym?Ycqdb2y$_CsaA zAIkM-c%5t_#zlFSQS*^$fhARL5fpUsWpuJkW$C?a`S@Kq1~DM@TB#;+_4|)Bk@0&dM0R{h2bOorR>;bywy~z< zHilS~V%uK78^Srli!2+xGA}Sumu`A}q9exMSYmjv&EjuT;Lqo*m^g$7-EPot!oi}_ zP{R$rn^%T+*u-5B>X)fqsGTyPuZX{gHy?Qiz0HfSC9$u1bBj$H@`0R##K0%7CMIN5 zM2QOvtIzDr%pQ-eoUos4RKWn?(5hlwY*MPYdJ=7jftq3RNauZ_&aV(_i`spDnIh?_ zhyh`n3%H}Wdce+NGMP|*>P!OYmk+N=2$(yHb_9}|D0L`y&m}UMj6e$1fB&=Cs77Kj zL9Yn*_~ZQt-M-vd2q$}O|2T~7gF%K8E0j8qWeiLd^=9h!CPy(%i5=WtT|M&jUTw2k z<@}}5AtYvpDxG9e=ib_4w>?c|1)(8M`!k!=xR<=spS+<>nG{q3} ze39Q$t^A>(!}j(MCRTdV6U+c6vr@mDVG4y`8Hnnc{M2i>cRPE+3>f~)H3Ll{q3fhA z%=x179JPXm!Bn*L5L-#(P66x9l!Z`TBL*cG$>ouxlaoVf#)tW~Y{<?oOG{%iJ2(T3qGZUq0N039=6sQqL~7;Sxd%re?o`QdyD%Kn>Ax_S z|NR+z9-aQU;I^1(mD-!O-I)f25u`#S8&XRRfQ<%3%H+sM{@~!G%)kVYBRYA~rr(0w zn<3{hnIUL$w#+)>EOMq{*iaiuYOs& zRI<&z`tW7V`<;Y_s0%`yzf+CQRm3QHjBie{Lj>gGC&m6oq#@wkp zJ#`3VlIzkD-}>NhL(P7{eO%UO*_tBpFNznf;vE(x8J3?Tr0YGr+5cw@-p{*n*o<)W zlbig}E=C0Xi1}`@Nuv{#

m;LvcFU4r+#5k8cSEzMAvI$frgA|WzUChsK)U}i8y zXPB9vAxN8>YG*770Q1748B2)9>gwm>yF^x8G!J}ZKi=^?%1~(EYC}Tud_)wz0`t1rO~vBkRL3BxcD&D)z$cShno<2H8tL2`4fSGa$rMDylw(btUUiq zgB5m#mtZGSH9k36;yTxZfA{ocb(QS(uM#lVbfm)C{8d2t>Syz`XT;GD3t`Pqj&xT? zu5-a`T<78BYT4_aDmZ?&wC|ow4sZ|M@-z=8O&r1fu0R8EEy#Z2P46r4FxD_2cD;}1!aUyT`t<73 z&}=ssCNtni$Q*#mC08U$^^^fdr^=hq$js8Q5vyyW?!0OMv8uqrj@!{E2&BT5svfWL z0%|LKQ{z}M){f5zL#-aC?7BzW$#dBQz5R34qkX%DmomeKBnFj@~R4*LiDoCWk z!+w2X5?KDM`GfumbR|R=grFt{;09K)=V-~FLn$-s2#toIbrN&Mmr9N}fVWarjdXEw z(K1*}bgPMsjC|l*2vUuaoU*0Ul-^HcuYzY84}`RqJ52dnm8dd*Gr6mbX{@&|qW#&J zwNk6K(|jFu_*bj~T*?>Ge`KkDUmRd*Wfbn0=C*w8yrecaeLXg2Dp|b_S`h~h6mT0` z<}dez5Q#+OB+yk22RkUs)ss5DzIC9b89%)f^6ILz?@n#1bbx=$gX5>B=WpEX$y~0V z7%B3U@Qv@Vcqr6qC)8<{vOQL*&#&zD>uSK~)#nl-Sq?wB1=wuhh@~Lo4Xca2^rPgi zvkfWx`Ob`43oH`bx%>L?xlvXJwA4e?z3-YQus+9hg6>$Sk1v)5-a4jf;wkd=|3e5lAtI3gtJ+12(Z8Q~DcI z&ZI>E>p^+SV`Z!+bA#%LHNjatncy@;y^I)6#AN2PVoBk>s{4QEHO;90Dm9Js;HNfbH&UwOvnu`0pPt2RT9ZsnDMhQy)_LokPL8V>$d9Yhxi%vEM5a$a<-Z*D0c~D*vKmtAxli6Ote)5XB zXd*Fox$S9FfP068|6Ic*8y033&#jf{*JoZBav@Qp?n9XC*>cgjX#dMHbd%njp^;T? zDz$!QmQqf;OC1~UZA7o${KwVp*)tYwN~RYDCO}ubfD#5sG0?5e0-zJJ*1KE3$^6FatHO=A#uxNDlfq-qcIU3TK$aZoFtN7my^v9ftNZNWEk-d6?{! z2!cBHV{f4O@t`a2j(2@v>p80bdIWF0?|sA7g#0ZEy%`FuIlPp|6;qO z1k}K;1gH~-a_M&i%ZG@QSfjy##&bwbUB!6BdeM$-6*|^NwnE!>NtF9vJLD1acjb-> zkV5(?ssUm$Mbf?-ikLneF5Z9AbLn$>^`s0h63U&d>u8Yic0{{sVJgg8gYOK75Yig5 ztC~Lr5hQU_xaOwM_XKAfVB7kbx)&olJuA&WQsh5Vc$ggcUx37@YXKsU9I+nSp50{P ztP`9%MuLdwA3D zlj$u%TBLfE3uw@qTU*}1E{jK;W@NM;$oJDP8k8(^JjlTD93jr8k6Y}xb@7S`4K3^& zubPIoYMB8SbJ>2l?14Hv9%a0I@1>Pf%ccqj?diLkY42BfT@47~Bd6zCm^~BI6}4og z0^}gZT8-SS5j&Miq^i)&0?My1_4?)Y zk+GQ=>-Qbk$7p=kpZE2sFzM}nhWYrW?U|siclS&0l$KZpu72MxxZI44uj>=b6d`6WPkF?T-{(^38%l>V3fUoE*t?~S&vPF z)Ag1wmxaKwac;c_Zw~SRJP_A~IdJ;Qw~#5bagt@rH?WTo3%WxRq|an+PdBzDYes2G z={Wh;lr^%?w#azu%4Wv;>hDb#x?k=35iF6I;oCRZFO?^4{Ra#1pBw%AUsH*H5oDON zAfa%qUkwIA7ZbISk%y=0&H!)}x>h7IzC@swTHxrQj(z_wb_~~TiR@F=jl0(M;mZ&u z#Ld;o;v>G)5Y^Cs;p+E=ESicku7*qiUL^O^*OBCo2vM@xJ4xt8ME*4o|CjJ z?ytqGm{DW!WOb7Q`@(}pmj|;|2z_!4()`G~h!eVg+f{6`1w-eVT%*D= zW%aMFp-}FWdTRqct(S64l4Trf2c~x&TKk;Kt1MO4=D$ihej?C$Dq*Tpu8-z~CyuRA z1w7d9rH|&R2_$vx|7F8C4M+s+)T4Jd112Z9sM4C;_&Cgc6<4+7hrQ9oxg6GE4^avs z9A01c!WhxT317kk7ufaf&jQc=cgxW}DK@6%b8b7^-lwm#kpuOGiI1%(4xfghXWrf% z{ther4OSm4kbPD5qi&F6U!}Da%>QD?31ol*Ps3&dltwtbr`7Ld^d>(T9T}-`#}AsJ zfYpM;IMiBGwZ-FrMf2`K9#5qbnR9p5O2oP^Q{9&E=Yb;?E;FD^lqy|fvbsuXdu&eS zK*?m?6YEKk`i4Jsot^yY8w+{mQiyAu_xJ9TWCQO+1n;D{Oyd#FZ_W!LNjgZ(3V9$* z!tER-lHiQf8n5yI)aS0mKJo4pFf4FBJ=*G1a#tMz1KI6F!Fy=kR_{wD4$ZfWp`~M2@uBPe(T+! z2)BtZuA30Z!HIuuf4|^15>U*|D(27+iW%A(8bb3|-;70?EcW#(8Iwt0anv|U;Ed~x z2eXT0_#deClS;Eh!=cW|Tn=fsyHOkxBE_?|4rZydjI-9RZ3f+m&*RIDtoYMq{cNIk zzUN8%tat^5{Hir8{#j3vq@H(Fkd%dB|}@ zt@6prqA+fADTINan^)hn+p})GcBK|CpLJ{({pAf};g%;qe)ZdQ$uRi`Mm&D`g;LHb zn<+b6p4FVl)J}t01;+|dy0TjR=q%=_#G}^NbYO7a{4$gpawNz-!->TXwqt+Rxd)gQ ziT0$P|9MM)|5Z$v_hq9DxuvU;M$dM<=n`N5`dpDIdE9fd`!<9_;d?#)NdPETFDe?e zbX{MQ($#L#pw>8j-4_FaoS^*YtNzyx4m~(VfWf+z_uJ@cx-*!chgaH1Ir^{4Kp!9( zpLiN1#etXoD=aKb#JnAP^DR$~TnpIo^A%f3cltSxlgiPg0mh39iOW_Q=n^3G0iYc5 zVA9MFLAPjb<40!YX%!51>xPhFq;AG>xJ&{L6|fxpXzG*nCOHn7x9A_c6ONaC(oxk$NI_TsR~S(fLA zY9i0|Xn$C=ZX<6k+ai!@+uaT+QI?a=GI4_1)Q<(^&9`SLQok&p;EuBENm@6W**4hv z1$V2{gUnzVk|W<9`=i1}Nkuz5*+YWiT^>bU(v0zj#gBZ>M>GH6X8C%Z>%`M8nd+K% zC#X>_7?x-f4#c1`4ykg_&`nP>CYEVq@` z)G(-*%$FXQJwZAPYkg36N{p~7p~I$Q3;*N%?x%O4z=d>OVW%r;cdmM z<~70%UCs|?N15A6#;pmq=10j3*TPee{42aPy~p-XW*zOWO%d>zfBRN?B{7>9DWsyA zO*-%0UlElhqZIc{nG$QPlRfNeL$1kF6Pie}cE20kwo{5q&h-**(C`#hhR1$F?JnwLpwmQGO zj70v=>II$zy#s)MJ6->1x@XMQbouNt$?W~+g-&Zn>Hcx6n8HuV*twV?`~yMmzy5|~ z0V)f+F@k6JY_jP|Dgp{9yz~`jAw$D4v%oM%qHcN9mD^iusi(e8%~PHWxf*oM7Q}M-I`D~sn+dk>(gk+BT?vzy<;wiFX_swdE&i6DK{S6;)$_ez*b0AXV278{Loj< zl#j-&-Vlb9Io2XIBT3nP@_V*5l``0N+@0qmx=SL46c>BSLYhMknobidy)O2Z+ zli7KL({DW6PrgVc#ED_0b6v4+?s&J6u}v%ZwVDU@1%6o>=6c90Ma0CEFo1dlL;#&s z&Z}3q05T5*FvwLbet%q`?CM&cpP%o-vAN|(L-YaUySTW~vLn5=)&N>jfSBQbadW3W z4-|?Jpx9H6#j>`u>Yjkf>ffiCMi+E6vkP~*_7_{KeHyr?!ty~XjwMh;SXOws$!A9t zryP{nuVIMaj>|xLbUh(X|Am?%E?(Q$_0_V5)q3t?{8f{(!#?sD;*&X(p;aYg zajfCJ=Ovpx)s1_;cU+paUYJI*bYwgY+8Hg^k>v1M&-`Y&>-vH|iLm=alEQ}ntBth4 zv#GZ%Ig&kmK-*C9DkXz>f?o3w} z59pga=l=khnUG9^)2;MRkFXJ-lK|7yU@H_fHlq6nw_@w#>CS}Ec87>aURjw2&;hsU zp5EN9e|r18c)*0<#P(7x=3j}%+tc?94GZpFgfV_f^AaKb#cwgp7nC1fzI+*W4JH!= z89?j+KH#TP!Y%{ymSv{6-IsTush>Hh)eP`JpZEHwVRJzEj`8SJH@5h2s44l-^%MuX zuY9Wp)30_GzeMldxFzO8l~h(Z&VavG-FgoOpqimJm<~oR*y(c8u5t4l^L$z})mb-4KR+b>0;LKow|p4^}y zuUN@T`mX!9$npg=?k1pdBbH6FadxB9qZ{~6h9a!@#3+*_>FF1ThBGw}19UL;kz&}Q z!3|aFoFNYv5`v$s-A14El~oG4@GUA>&0;A|rr>RcU%c>~JCCo|(l1pIL6hI9VW@+ z^8@ei)I|lTn`Fxxi=d$BalL z>G{e0mli2hoIe1_4=`ZbfWbT;{TK9wflBSwO`HVO7nm&?oQ5_#5K7`@g500IK$>LV z3N0bXgjx*erhUD*!dvgm)a!lOyHaj0pJpOV0)l<~UarZBi|MixcvJFOv*YK37oeaY zsdsDc)m6!G*?x~{8*JRv9}OJV)st9(57>*8Rgo>7=>gCXO!29s zbX>^vdx~%}p_UK$&_sB{5_?=Z*kDa)a}CyN0-#h&M<*MIag=g6cA&FJ3-1BVj`v=8 zps~za2%IwbPXK$3Qgh+E5GP8zK!=C+rdO|CVfC_hhz^D}bCb}<46g-!u2aWD4%+E1 zZUYaEat0K19YSh*O5QbGGXk_ఝLNIPN zTE?o}H~`eNfIeBBwpVVsOOIv6D+gVbIj90R2YKWJ=3pS4STF~}&5?^-&r6qt2vxV% zOcu*8{R?8Ndjq6t0RIXf0B#rr%8%MtCp}mQmX6l1uL0h6EB)SJN~~P^vs>xU*xkCh z*^X}>-s{s~Qnvzk92duUVBh0#A$a~CdgY#V6kLCQzoRUOBngoxP=iYMjMXpZUkE>4yAvt<{jas0+9fVY1mTdfhGLB$u<)ab+4Y@2xc z)_rnaCHpDMHg^QsPns0gDM96Oc_`SpgDz#@)q(L0&y1Qv<6*@ z_H%oYeG}!&KE&_V?AJY!m89fsTxI&QdKUbz{1O|y@yNUto%hM+?CoPtODIOJAS2X|m*R zA3^g(;C6sP^R^MRB|oRXYj1B4zjsxT`SFdnjZHoQ))v?Ce*A>2=(_=QN4ehli;qZ+ z&DkMNbb6uT+JJongGz@{Uk-<~!j|fT=4Ho#0V`~}%=SURJOAX*znw6yhi3rW2ilAN zx4xa6@s>`mVPB+rRGv?WJWTjjqlwA9@HHNu!}fGq@3$1YfkwaHkIuploa^0j2oX-H z;tR{hHeL%V$iC$)TzlcMfVGbWA3Vi{WGFd?P!heIWORMrXCt{L*B2#S*l|294v`Yo zzGTj7sXEBuV91q`ww@-<*h}F!LfYCcJ|Ikdf@dObZ5JJ3A7p496h-!hPRG+t7)xj$ z#A2fn7+ko(qmeSoh$crP<{=pzj$+@t9SORj1^#cm%gm^q(};< zp8T6%uI24r!`{cChJEri(i6MPwjgYoH|GodAogn|MMd4r@lV(4IeNy9lhAbre<*hZ zd9H5fIZw9VCoDM+WeafaAF3O@LaU(p?~*PI1`1-OE$u%Kc%&2jJUR~g@2vCm!19&Z zr%6m5o)L%kH$Xq;HM?f-VpdF~l&*yII!fCckJ~5>#yUKRG+qp-CFCOVgyWte{5NVf zkeE@kdCz#gW@1yo*5#D2c4C@i3g}l1ptAK3q^fh`hAu4o%P3X;tqk?|QBsxyf1M=e zxKi#~2uNEHk!`TW&*-2~j)e1LKkbPP1YK53f|AMXF|G&BDwKuUfobb8r!9Me%qjW@ zzp;a98&5NmT+044o@xzd_K^6-#5rc9wzh^#Jx_&`UhO_tsWEq%iQ-;En~)`~-(^Xo zr`pT9TfKX-TX59MVZvq?VRN+3J1WGKtk@w*O&pheo~og*Zyluq^7`#;DnWCk+bN@~ zfBp*Kg3Axr1T${+Q1JAjrH1mg8JfIsXehnp`vm$$h%k}+Ib z<=YHrtptHc3!H}teO3 z1qk^|@ax`>yLvqv;4D?|?^xbE-ul|pBH(*>45rZ8NTTMRq*@B@$@KB>v_el~g->&C z)Pg^u(S+4frSpfKPh---UwM?wWjD^65*WwE#`rtwt&j8g85Jv zWy`h6Cx9mpKJ@e{WdY%2_CRn@?50P5+ZWV#Py;0}Fo2AH|86-D%QG+-X+R1zj*-)! zGj|p^MrvH>{u#3Pyh|sRGRNCd577m(n9bVF6l-~TU+a*JC%*LwKqa3k!Q!6^RZpF6 zc2o9R|4@kP6!h#JIhQudR<*C)FfxsOK$Nl31vG`7l3CVjI7#~H8=gHZDUNULUr1_$ zIqPfUtZ4ssUr14!F?+5~q~NXa(mGZ6E&@4O>Y|OUN3zUPiI0mup#^oX0;GD zqkc59ggGzJc+J-vm#^%4F$81hx@uBs4p<7i>;>NU7w@-c&ogbGi_)Ya%w1PrJ`Ts38nRyoM(Aygcy!5wYQ#c1RMY=_wGFi|&c@!6^*tg-{cVPgX6niaf9_b|S(c?o z9jGs*1CVM}sl6%dFeJlr+P7kNjLZGq34rLRr42>kl$Knfv>@PENiN@dS&2R~S=mR9 zdQvt#_T!gTGwp}sh;Q|0Ai`4IRaClPw)oWagP;pMyk^r+$Fs!XQ2c)AsQ8WHu`#<4 zHas4$ZD=T2DEj19y4e#kf0;BWL%@>7{^9Xka0Ym1%xO0jR8+ieN>p3JwZSP7j*(=J z!eAkfTWSpUYVYPmTqWIp!#Q_{CS{w1RYc)M8EaAuWU`$4ON7hMs-bGp>4=4rTL(J| z1DdWoDGRSji$}#{FZPlXV-9K$b;S4driZa(G94SY<0fiN8;a4h+9H#sI&CY_vMU=Y z_PX=^-W2KxlphBrD)L$P3+cIIF2Tg!BpFolozePks-foESO&UiQF~px!KQH= z##y@_S-&zWGJD!`#b{@FJj4yVK^5QK&L(|)i5Eo-6dM+fxQCHyV%HxaWJl3!$&d*a zEQa&+v#1>{7`I%*dTy}kv|L-p%GTXCX`1tQ`g*kc^2hRy??aAheZ3o3*zE~@A&lMq z*okt3g8DlKGnX}dJ&iUS$yF=luP0p0amv=9qKC-M(IewNG1;4}xwP*B~mu_MogQjX}oNqwq{qs^K0v%(KM0C>o zf7eeQoT7gM*QK(xExDLsn6$XfeEq z+=%>fu*VpKFqW-UoRHFO*Snl3l{e|}?!@4gg@PQ$1-PL1Gp~!+o1X}irAyvT^=(d6 zYG8PI1u;|miF)t;Q5q8z!U?FBf#9Z0bBETKddOz5H4Ep4 zCnUu{)CuGRXdy;A?;#Hu+i`Xe^7c)w^qY_(9sfe&(Vie|T0K{La?*9V&=6w1cqBm% zWVgVQ0Ly;)lPTB-$dQ39z|O23ai`eW7L4(7*;l9Qwl^v~lU!F}B)pwnh36l|kU&9v zUUN?Hi|fs@KMNNm#Wx#K3S~VV-%M&x6uTwSzHjm_fcJA?KZRS}xz1MAWMd z|1Hz=iVP-J6meRTFgMq6+s7oz!r`E6lX3T?n~bbLOrTrKHN;k*sYM(yvlXU zivmp#`xU03z*1}GgY22oeo%f;I|{01Y65AJZ+2MvIE{5B=0#`4*~xGBn62z&-ddwR znc?buz)bEh8}q;DTt`c#j*@FvEPijWoY_8C?LB4Z*xuCO%{Iui&mr056)PpN$!IO* zxW7}cGRLovz{qUagVMuo$b5CQCeMZXgy|q34n+8%C+tTKNd%bk(5S_V2wA=^i3u|8VW0n)YsxEin&$=GTw!!rL>%UoI6GAdgq zN%#R`N?H$2HC)X5En&-RgR6SdB?=PN`^O!1goOeEddK)Uw zp|{V2z7y1bsdSoiUBbX zaWa>F^K8H4pYIvv9c*mMJo_B1trG=Nrg^!!ulJ9^4Gg_I!@4+Tf`={C@=q4Fpb!mf z%Iph;3P9O_vI9+zCdhho=1}(3;;iW*L3QI=CrhJ{KCV2k56ZU|ez__5^aiHV(C0cE zID({m>29WiMo0H@=bs?h75R2_1iP<9Z>Wx!ufNntbe6-&N$+*RyI%1A_}q+HNP}=p zPRJtd5>BEynk!(%p)1~(@;LRyF}a?KT6W9{p;*P8iG3l@r6x3U{Ed;2ag^ZiVXubB z2`Tdq{M9d}n!GR+D@3uq-bYUL=5N@IoIaQ*!M^bazH*?wzeb0$G!<;|{+wL4veRTWHC&){NPOWF*RRk#LwNXW#6gJLc<#z#2%&|PV%Y6A8D z^m`9)g)CmJg^l@w=rVeMZtsv(bs)9xAKk}2fm1&zlPrg(ry)SQJTmSPeeDiOke)gBIKe9Ekw$20H zefP{u`G1?936O&UW$i=@0Nh^vX8I3a!XsPUPv(aJ%C5UYgB@8A0{LTcG7;w zzhs|b_8P5Ab-`F&x{tAjkKFHuJO2SHPLsaMuCR1`iV)os*JnF@++-(&zBJz+z4t?X+!vu zrYlGToqI10?}k>;&^Z-N7otCPF^!U@p@)x;1ei}F#bMkPE3FJAS{h{Q7XTFG4^us9 zvL!U+7sQGu8wJv~K3Wk0;}wmBVg(fSv6i`W(m4uOB0!8}+8;|L*KP^6#2yOvrz}1^s%=PPyOo>+5(s$6q51Xibh^x2YWxqQ!25pEB9?(bjL5w5f=g-(-QA( zck333HkQdfjp4DFW>Uf=hv~d;a0p~;yHlek>)Rr+Im2`+K$5?_9A|^e8M52XFNG{ad>W}@g8ZB&;~hyv z=mx8PQb+DZ&T427yl~#@Qm_vmBrZtc!EN?@YjIBWAku0#Xg_&e3tq(`UCT_TcHGy%oUVT*;#-}^Dhx8H=Xy_@ zZZK!Kqr)#+uyA#t<*|t$p|N)Q%oGiCU9iw+M&sMI5$GJHSF_)yoZ$+O#gyk?E$jxa z!G`<;@U|F|YA?xEuTHvl0$doYs#t@{;%?tHmhEnj2E|@KLFTq~eF^!#PZeP)PT$bK z*~xIWpkj6GksNpyY-AJs>tz8-cysY7l#x?n`RrOqkzSO#La5Ew`u>5Ht3+}1?ct&S zSaz+F_HI{VV4|Vx#Z1H$Hab_a>b0U4s_x7~71`1-8pr?cc1*t_ul4goB(yPPC$S6b zOjWhVzCEj~UUGv6M|P<*^Cw!N{WiLg**hdPRSvzCESjLr6OIwV*pVt{8$-_-EESM2i z!QSFur5tOnyEohN4Rum>$~LET>i69S>S3RHXZ&!!K)lu3(T_> zqxaLW705U%%O=KZ_%Ynnu`C(Jo6tbYZ}4JqD}5Cw3T|5z{K`|0asEXQ0hS3Uw5L(8 zA1q&8@%itsILlSgW$*|E8loEO&$r@QMmEd>@@cPT;szrL>_`J7nG^vg)x6%9nRptq zQ=6Krv4w!lsd|l?JM7QrEN*lJK!y5vOb6$4s|Kh+J0HyFbE%p6Hw?QJ-K4jzA+|9w7E@>b800>n?RTn_u}x$1$`?PNtn^~WHsRqDLgy{ip4`MJ_u z<>EMljtlmd+9*s}pF@}U^$N>3jMD5HuCAODzDDiWzaFZh!j7V5FO+Q6)%W%HMw!d^ zzKuQwIo;-1FQgd2vW?RGu9M;OAH3Q+NoGK8y{;qmPOr|VEg_0^(gZ0(Y=en@;~BS? zj@9mPq9f{fie*0CO3cA~%q@_6X(1@l$!e2=a;@4~ z^Lme2v?H-<@rM7?vF$?U?(%}8@YTV(tH3O(-Gsr{d`#@8fzPIV_G8fXv0XyJ8Z@{T zzBCg6n?BpV0PS>t3n(5$6XNA$!nx$#^VTZyDvCPVRckw{6^7pW=VF*!g!l~2-wmD9 z{7ab|kW_AAJehwLSl};8d~cO5ttfEDG4U-U`@;Q^@O2f;*n6tU!d$GmVx70LaMmzp zWs6xcQR>uUXuSOX79h$EL#`p6f~ze*ZD9OM`|r);OE2 zM1=$N5(;QzXBx;#PAK?#d*b7v#y-rJ>Eo8keGRWR{E6Jv+mey4lQKU{U3EWy7pr|Q z_()eVAz(Z!%b6Q3eft?DHGhoT01xic5|^d8UWKjaNI&QvY`TO; zY&_5?&3saIVUs@cf}g)bCvvhfs^gT?QH>~YHY5L)0&Rc{9Yku8Uw(2##{{E_BuWz! zt=}tcA{Bo!)FO2(eRVrj?cNuCF6?TYIhKamuNTFUQ2UUs^<$6b!@eiS7#48(k&;(*ADOf+&a&s zSSusH=bkkAtj{uPf61mp{r==nZ9RrHJ8>o|kLuRE!{!{xuiK8UY-eY<&?2QiTIZLV3TmiKR=+Xjpo5Os(cSQ(_AtV=9UCmtkOie z=%k9a&%YewW+o_)QwBHX%vEj^bTzRdgi>sHm7?a7D6>f=VwqGh7 zTxQbQ2j-?&xTzQ&D-kH2Ds$Y>5*35n;7x*7KYguc&{^Is3_X-tL_c|TdiD0*iC4KJ zLF$H7ahuE%k86Bya-+*bM>{{*gRYoB=ocP_C2T5xFYPnaOgs@8uI^gmdGts`@ zby!1NljGQwyAP5%ZeMrLt=!rGBHeVW*P=XcBLH{(>FU$;RlLbyfP87m)l_a(Wy9GY zB1RuDnvu}~@&OZ#Ho2*Vc@Z9x3UNvJdYBOw`309B|KE8(}NtFTST22hFj~I#x?}JtL z;WtrFwzzFtK0Slty-R93K;Owk%w38{xdiAf;q@di)gvmz7_bx|DJ(zovZzh>C=Z^P z|J}-5_;KW^js~A&E;zH?mAV zd*5@EzuZ2zt3Xx;6zdi*JhR&P=|L)BSSa>2$_1aO#;R3Ue?T2;WP0Vt$76(`m-cJl zLXQY>1S5WmI=;3VMps4nEEi{na>pqGBkod zVQqiczkA+&@hqM=uFKeUYmyIvPsLwB*S8eCHSG3d!$<%w)_KbX>U#98fB$*c^WM4J z3!md<3_eKGIa%E#s_dkj!5C=^l8NL0syEljKlH%Xz%l;^|0q54)YZu0xhdiUR4E}! z3WcB3^smb4?bL5CFpk}mNiiqWHC1!30k=AGQhurBEe0} z1)D3#Q10bY!(wX+vQ<`(pG5Ccy3r@sL>tED?Pjh%my8{y&k_TMK`dVsF-0sQ;d7Hf z;@P9xKdC0LeXyMFET5(o*soNwcpeU zHZ7QqVmaAI*TIRc!7=f1kY@uGSA55OusF{dTKd+1qsr(bfGYjpJ_1PiyVa+n;Q)s6HnH$A9 zX{VRUcxuHG>;%3FoiO5D&bnBA*HT1Yass{<@r1QsA46tydSl&3h$0Nj*A38#2QwacHX98$NEje zvpyb{t#$nw6VqKa9_KSZWsMx0V3D^=ISb{0rhtB9bDt?|IvLL`Ur8Y|WO?4g?{ASa zwagAO5-(;Iv-BW;xD~&r(aiuh%_%(b8~lxv@PB{abN2r~=)VE{Ef8`;;UFbz`_qt9 z*OaHzIG-Yf70x_$v!>@aER_=IItaSq@-{rVeikrr8vin?nEf^shz~;UB@__AuL6dW z)*>!gl%0}1XG|2e_I|mSBEr^KE9u5fJv$7MF$}Yb%U0!kjOLByBMrm5iGU+EPUY6i zegSgar<)|H3?N%*GLD?8nv*T`7)y_LDl@LK;Up73ub778wvjEEbMU*&+n5qeEKuot zIo51BSD4aW1h>IAy$-J{3rxg|jKzPo>A8Hi+qv5^Os9@55Lx6TeQC<1@vLhbou|H1f`st$mnsTxgEQK| zS4()t8)kg2I{h4tKE+SA<`Wa`1`Qkg{dW#9$`nr`mNnM2BA7}80-{GDy2EZ%`seqf zeb}gX4TIx$PBzkbB{3bo2T5!45QA!HXW;?toa3-xH?%dzZc-j--*Hs!TNq>S4E8yw zL%QgB!5n8|nM+ST$hD--81HiqL!Bl+YVS(98RXDhOT75k{N(p$ATRlU8T}u>J@1a& zu`0OqxQxqqKMT8j7)I(PGX%UOcA9NLWpHkp-?J^yqHU&r1<8 z+}IlmX2l%wvUS6j`Q;X|bM(p3O)B0{3^2ATs9vr=rs239;az^O(6jLTli2OafL==& zQ!hKLHFIBkNf>ZYFx#O~xp5_!om@juA2-J#-C@#m_;bamt`7Zd;@k2k6x?$+oR@

HJPT{ur#pD0oL+Wu4To}$U@r3n!*)bPD?Qw);{arO5liNwHq?=_=Gy+{ zGM!+^hiC(cdHfu!M~sBruLZN)wxWkvGNN39ZGVXu(cIHczQsZeE_T%qk+-V>lbDU` z>E5VZr~0Y|bktaI<$Oj0Vdgp;x7ON^%$dtWU$y?P#vXfVE@haH14$w;3-zsH*1`V8 zS=!3JIRB|B9iaGoP1%>=hv{4D$_ZZ=no5zV+;gtCA^;sP0?X9xXX=L@6lJE0O{3iE zN8{=f3aTP9r_S6C9H|po2!C;Kw!b4)(b{X^it1=&mgg;&XaZ~bmHYSf$aU)|YOUr5 z$x?J-U`kn%KpYcvEaWown=J^L`8T4%0GQJ3&C(F`dnA(LXVl#!Oc@eapty% zq3Oc<_nNB4KwIpsH>Ei(FEThU>guxgeMU`KU?HMI?vh2bId)`SZ^7}5FiM+;Ta{f_ zOPSsBWa8c&&W~;4(lu9fEq>~Ip>l8Msmlfp)8qA!i{`gqq2OJ!<_ah{lh#@`cRmY4 zlpB!055{|Gl{Mz9f@6fS; zTZW;IbJJb_u?N_GqV}T8TD`V3t9cXAP3{z?7Jb*x1HsC-u}U+>m&L*5RmBXN7t4}> zmK{PQ*d>@m>luKS&_NqZE6~wi7Eua#NkTPP-BkT170CR?E=4hbjg<^69DBv(s|p>H zE~?rpWSi_Q;9`M#8cX%q&+FU?y~YyjC=hyPs2*FABs}LYUFi1R^Y{RbiquJUU#7s;+(t#yPKPHlJ z^V41*^x2f6-%oKo6W<$kga(|6lS!v9ib@a6V8_Tx z-?u!2avi2>ezRM_n+y4vQ2tkrai!@sNilS&MW~^zi`{BI&~I4S@QkNTHZCOS?j}*{ zvGm)e@^NP#1tQ4QQa1GqKbN4~wE?IBjLUf9A`sHxO(1=-wR?Fcqt(4@r z4J%!Dgx7B#4Mj}VdpN58vlrlIS2>~J5~Vi;z}Ye)2{?fC5+@X$1J_$I+D)~)!3GWR zf_S$o3?%~pO{tf7zWlc!8j$k%m;a@L@mt-0cdNDfPfr^EZ2{iC`R|GZ|5kAM{nr1l zzj5W(?ywz!U>lRd0@HjG)J*G`TNK|abHA-oVI`%}QrITC^E$fp+2^|-M3@R5D`frk zTG&cTS=cnN~b%a9qN9tZRI*}RoB^(qW+b~%7`N_Spy(L94LCjT<6#ns! zSCcqqRKh05k3Qt-pa13h^!Qce&L6KH{m<8rPhWm`{g==F`)ZbNG%Usbx268zWn|;c z{%`K&Ust1ioRp^azueUyuVVgGQepkq5B@hR%l*MzMDjm>LEyj7L!M0H|8L*%|39vO z()a(3<9e7WXP$Qd!`~$PA2}>s-p8Ojs+FAjpTz#3XhliSDZJkuK88d1Pon=<7LQjP zGoDrm{p%kr_T$bgU<2GUI{VX)4ln<)$$#aoPbw%KE8(1Xd;MkP421Xpc@`K+U_)Sm zynlR^r#Sx{hdi3Ff4t-+ZA{C>mQ3-Cj8nau-fRCG`Mz>B$qZ;$K_Mp zCgS}4R-Csocn!6``C6g+H{W8qh)@3l%df$`{!0D(tZF77J^F)poEAoyebWQi^)oFQ z28};`{Ku<;zp6(sbgY{4UiXEM1(m#e#-w-`$37$FG8>z5W%p0+?vIl*7twSMkSXRZ z^)qJ+4=k=7`_pk@!AU3dN0c?H=x!=qL!TiPrm7q!#C%;NC;j)`ba2lgO}p71ES-nZ z3nRTxpudkdo`^;acbjM+tgD=BOzwm7*rktF!#{LI&%@t>$6FPL3Xj8~zOiuH{`0Mj zU9eJd!*}NVMiH6@W8oD~s+yJ?gd1*=JlN~n17}cClPue1q9#q$qLG6df ze24pg5)`jc$R|N|Zj9p9_{5a+d1BN9WJ*rONUC?Bammbz2`pX>eYh6RzGnn@Ry*It zB$BSG>htP@wRV{FD1P(Tv6!ZDLiR6NL?uK)ivM|Tekr8FYyCq7L~p90Kp}iG?ba@5 zBZ#Fs*xbmbggdJY{d6ujy;k}{A1tukYR`wxw32mpC!fhSur)d= zID7mxfM!@?i2-2#$XeRcN((a2*0LhXd)!nBO!(lE%M6O|(~g-c$hY5*+9zstSr+C+ z=S_6AW29-NZ{DYR9(%F~A;+q^zcLcD=Ie=l+7y+B-d?6tCAPlvWjSqC2yzly2y3|| z%)V3MTg_YuaX9C{XiD}s)V)(x!L1|;XB}=WHF5Xt_uBSdBmrO$1=SnR>KjD}u5gFO z8v0P75P!ZS-)i>)NKByXD(UswU=)5igc^*(ZEl6~B|O;pdUFntsBpt9OKY{SZul-~ z>wZcnade51Siq-`bkL!%u)mGUr+As)S|}#H{`&ijnuG>C9;Ig%i~ZBZ5Effx)C1mrX&Cva$!cefCFxfm!vY z1c@CbD;JRRA4f8qDb6#_kc|ubkpWqQ_`4YXvLfpB(e~v7SI6pC6x{}M!J4&r4SjO} zqtsULG3c5VThJ;n#0TE}K7G6NF;&`J7X4>vreu-`shw#XgYrlRNxwHE#`6{?Z!I26 z4CsZ+0#>$|d!J6Hd`IR=d7PES9b#>CqZy<{zbT}#JsYW86+DMyIML6Ryoh&+@PszM z6-eL}>-cK!fGjmN^%ylf#u>Up2~962XVg|f?X7Kiz#b|1R3z*>Zj8rMaW2;f2Azvv zf7&X~z9zYG6LiO!RmnZ*wYXB$IL9XxF%2DW8e9jLu1LAt9> zK9Po8bl9!o%wkugaZ{n(3hd=1Ea6sBa1|jsj#li@cKLRNtysn`UjCV6vrY09=?SeX zczHH97p9i&#`_r%T!5c!3|ehV#P)aSBz^tmi95|NbGN{7kY|@0rO3q_&E41p-Sk5bG zbecpvoazTA`xVZ2E~HUyi3oxIG%0ggd(`I6<&wxUaB*F%jp$w# zKv)vm57KClTg&={_rgMmTSK-Z*#Lndwu-k0TI_t zG-9Cz(QT80zz)Phd%dBAn3|H=P@DSW+KMt9 z-BF99X|A9^o1a9=U9o?gKarZeZ2pj^asw8GoCcaO2^Rbv##53d<>5M1DoJtvul<)g zHTg=oz4_w|{erIh{THx?wWwW26GPK5r6R4Ty4kd*%ZCrYT9`|7c+!T~+Hw}e$@euR zXP&R|_i?M;AN5qdU9wIkl+}C``KB3@U}I=-W+5;G^Ac(w%TA7vh#(|(Jrrv1Y@LRX zP0wXr57q(C2y`z|@JjvoS{s&C>lsm*(9ktnnpgetj>(B04y?U_Mqh`*($GdKB_)6m z@fUjgdy@KueB+Oss>6b?JK1M+HvkAa$*^~Z)45%M`J*ef^!{IAK~GuCWM43haGW$p z4eC4tIr&xgMYv9{6WAmtLs2QyUQSm^)g*up?UPw(9Vg+XR{*z^(%9)d^sbyZtM28c zyr@}-<$_(LicAix2C&%3f9_v?L@LXxbN#JO(Z2H0$%T4b&C{l-mvT-p9>bIi@pM)e z3i0d5?M(v_y#!0I0Z`*ZQddPOs4P~3#xv7i$WCl1B-xA=$P`CMG)AAIrLqimd4b0( z+aw?7*DvgoY%Z4?p`Y#r3NNH@y4WIO>4j@1@<^8KED-dVwzxwg&dcedj^8f>opma< z@48`(5SiJfB&VF(NqH+eTq;QB;c!aI=a9UjNS!8#{< z2d)R-WAD}1?Wd*hQ(o%tKDAMQ(^r%;80Oo*WO1(xTSNEz_4_E3r)3Saa&UEZKXT3X zTlQ|$+@(0qYW$F=BAFwOv9jNV#9qy28|tb&bxdY3^pf4M}15C0P z_Ps-$h>Jl1os;1ouee8eNrzUE&Nq>&q@G_JgPe&Xczwm_Ulo14QmdM{b=%Z^K@ALP zUGImlx=|j0zukQ|6cWERHrzX;UGFwFYLax@apy2sC|g+tK1(O(sLpUqoA64_gge#3 zbgJ4|cN+KIq!*hfDbBJJL-wv-o*U(d_dl48w`mfeXCoKE>ZpQ_Afrlk#0Rqm8%0B* zARm=`WgZ9*r|BnNb$HFhOjn}?Qgwj#ZxEaGwEMdKe5SKuVSo15xVqX94ujYI#}Dtz z_j!wH>_J(Zd{!qos-N+GN)`r7@Vmcs<=f5oC9CC@nElna^L(a=+7T>}e*H6Vx5?W7 zOG6X!NA5PaPNa1G`M&S${ql^y^T0w_q^I5HY6X?32o^5x29wVg@iY=Lvlpt`L5ibm znbcKHx~hT=gR_!5P!m4s)-rZDTb1v!zUf}f_}qU)6hRodBb3R7auQHgzLwB|JN~kL zZFB-|-$ai(iQC#NL`Zh!&do(1>TenJ(+a5aU#moRA)+<8CntCEH`=VVgtX_L-d+|E z2u6@TK*;*PP6_&C$#zwCrA9+e-aOG5&w`P#BS9NxCQkd1utz#4%QkV`e4cCJ_jKP= zj%`LF)UpI6@t}tXh`o^c7kyuF0T{p|w=;Y49tCi2QqtJ5SthX{Jy&V4KvHCo!3W1L z&*Ox?f)s%9x+~U^(|O))OHZxRr}9`+{F?))cc}{pBxghZlsSo}O-pxH4{%}~mRiJ^ zzG{b){iv358h}!$b|(wUF7opYNXx?qyx!Wz-MpWY*K;oz|0S| zcz3InhgMdAT6Nn+=)4HBid`vx^0%Ft`HvWc3b41tz(Kz85%H_L`nvW4huZs6PMWQ@ zUOI~3%(WXVui7Wd@5wr9u)hac9d(#%E`A20*={4^>2YQNsSny=of3(mLRUviGD>cf zd4-Wo?`s*LY(d7_A=MrA!W#iyqO3lPLhZ{=#H*Q}9`0ZeJ%DlJGmLEa$>iO>g`Yp| z)Xf%t2ZNDl*4BKF4B%S#!0b%A4`&E*m+mg#hyV4(Z*5|Vp_e)NUNb7R>e9cV;9+VP zjCW_oa6B&;aH}L*tjU#fW@GHU&(~Ug7SDMF{rm$>a~V6Eg>e$yaS}zIIX6{f z=}oCNLbznXAHQF+E;K`1OsP<>)A7eVO>UVriLwmf`c}5QP&pZfN{4-f8K&>?hDgQJ z&hzq&aDx|BBf7F5%1QyHuo~O(%4s+9p{So2+@kkv+Rq^EPzBvN;C+d*962g$;TiR@ zwD>>*kpI5WUf+v=5qpC3H;4-%&H>)4^DX9N(Zn8XdjTIFWPh9g2K*>h&rgv-l@B~c zqU&z^!Bgup)3q_eO-`1ayY$qfD!TuHCjeUf6Eq)T0 z-u<4<0HU0c^0Y*6E>jXQ0Uo-_Fvrddnv2+FqiGUNUe19y1}?TAuXu!*!G~qcHU^E} zhs`msw1XdB5z)AqYJB#{slGM2N8UBjb8}OaqtKJ`jHQ!{7)RPj<8z7{15eA84FS$r z#h}uN-b4%N)tzE-b9?+1dECgIbb4s-1CwSuNA=;01L6~t>erG~Kt%m9qR8y3=hfw6 zuvDKZ18A)ZazBxPg1ou;$LY_`p*)x@{$+Gjz1zTADb9NXryBlGU)g?ryMzMbCZiqf zWZ;d7EOarEX7!^D)K>rFLJ%n4)x7KM4gYvgElXopad)J1b^>~(pju?$$PzdLf5Fjz z?6WYLu_fFI7ku_WuE5irm`*q0la-{G4!%oZm*Z&lYK((n3W_RMt9~4AaaohH6hyO^C^1cP2*3Y7QK0XMC;Hqn+!2S3@_#ZZjSIZgDDb`uyoD9Hu($6>YAd)AF1DuXz1yB1g6VZ~7?@?4c zcb^~NxR_`-mAuWOZ|Y zY4!BP%b6Pw#Xw5GC)7DrId9lQoB>M)Tb_#!rZaxea|0DCT?=vG=AH|vXz|G;h8!Fr zGL(q1&AnpZJ;PE{H-r~t?03%dzxU}swB$4cFnmj1zbrsHZa1_y&fPA?if`H=Qn+|0 zLHAI9f$=)Uo{wle9^RpSxQncY=r8=tDT$(y-tLK(-+Bgpwi?qA@Qa4dUwK+VAPS4U z%u2Qqbq691mY~Ktr~DZ?6CDe82R|Y}c3%YEy2}Pyq5%z;wI0iyljxU2U52533rNh{ zEAb)W4^kqfICfog;Sf3Zlb56q^1949_+(qZY;lgE_v57GrB*sYhbCbrn74h3{Ixc9>-KMld@anuVAM;As#@taQ||Lb zs1ABNpuWDwBjEj{eDG}nL2+upLs*e{?&OY&$%3zLCNi?D`MQIs-PbEH^k(rPU=8U@ z4kLbzVX?NzwWWGWA(mD1IV%VO2Wi4A<4yTte%Z%n>$+=UCOW}G-KcR=W4`j@jZR282lPk4l*whEpeu2)w53CwPJ;vE;{n!rRQ7PfujR_FcK zyVH;EXY;1)oZs~Pv$yd%^XFq-TNlFbweS@MI9<+GTl#49ReeEW$T!8^Edl>iWu(8Z z>D&X)$joK8A0=h%mui(hyN!k5G)x_MWJmO36!qU2^O%%GtxMD<``+4M;t2d1Qz}wZ4D$ zZ#_iTdCQh(24OiBqsg}tf4_sA_wDC>gMX|9H&^b6R6&~(&!@Grf zCb|H9e1yDKx>!k9!fw4;8vnoWw;xIUZ6 zEtcIhfegpK4__f>3ro>+V+NLS_3pAW;ZRZ_5EnTsbY_q4jAiN26nqvjKt5mlofENf z&gOkDBKS`h(g)0eT6&Ort7d5sn(^;kRg8wZG7w^^0BKRba-dpU2=`LJUzP+533;6( z#vo#HHoa~>8nPb=49uQAhcQas)I(ZPu|7tR9(??L5k)+X?O%vwS86XC&>+#0Q>w!m zGnN-Y-9QF}BW;}R{vhLC8QxI~%oFfiag{eGH4k)V1>)xr1tvyXV{o9nW6U9dgcP(z zi%DbBDUxy3>1FWwgZC%b>HuEkz4JA~pu88-3+poG<_rMK{({3@KW`bl0Bo|*nmZN| z_Y~`s)cjGEut8DC3ZRuPTOrPaoCf01gqT}TLbYUQ*uo{V*}b$%=?qc9=&XR={s!}AIgRg> z+eNM$?Bv6P=X0mvCM_MouXkFS+P*g1hZ3K76cnI|aNgBlHurR0$o-l}Pz-Z8BI6!{Wf*Q6%M_3d2)4Xt2%frQnwowS)8Y&1@0et zRDuLiKs)|`py;3kRNZ7D)JEIM7o&g@%uRrrBfI8bn~Z))4)!)vw+#pmwyfs~XJA;T z)Q8)MG)~|ww7S4gGENb9;7~3)c%9l}(>}y4PPi8CW}~W5u^9oqzQ%Jzhn#BuvL& zrgdm??JW0q5&JwG@wU4W5eol4{|tSLV{NkReUEIht&#$MJ1bq$Wp~y|A4;8LPNB3* zapSQtdnMa;_kmvE`oK?y^PWPvnnwN@Sln<=GJjUufnrW8DihM?_S3kne|jK225s;6 zu|Y~qOXKNou5`Y%gI1i?p)h}YuZ|;vC#xn zub*GfLHJ?g8Ovt%ps<})J>HrW=|2K?B3+q>vGw&Cmc*!$xUsv}R&2&wnG`0&JL^yQL*?8)Rqq8VF5O?UJy+Wd+4$%*D>f;|! zmyLX0k8oF#ZQqM5g7yCTY;WAcL)t6%DnQCyrPp+tXmR$t{$u|JWm!*!y%^|7N*K*l zsc)0d_NxS+Ros^L=F;I?QI>YC1d8bDrs&DKCE}2b!t+K+G*8>`6){kU!eD z8jZ0(Yp=W)?;-9hfpHS4!OovX>bY@4U%jPK;(7niUI5ekr?4}S4C%t+MD>HSVR6YB zk7KuJKBp^1JjJ`ma`uH3&3h@x;-b>aFPuzHSD1JD2^be$zPfNCUE&)n^@lt@9G7#n z6rCN+F7i$yyu|8_Z;t*-^v$nl{kk^Mv~bj;I9by?rFJa(YTdILy`8KET0=g+>AZiy z90WiG>ULMX=TLd8ECiqMGt=vW&p`=(P8`#=!v#e;VbGyIS!4je6umK8fPe<<^`zHq zUkl~p`iDCG?)NJOIXow88XUn&RWKXz}@vgxTD5LveoR;N{szedB&Y zzxe|JljU;>Hrjn|E1|2~*AFg$gd<$3&jLJx>qQGz)lcY}j}avrQkB=pRdnXi5xdd+ ziMw)cc+)62_n2?{H1&OU#PcDp_Tsoao{FS8Ce_ueV}mg+3?QMp&ZM`EVH0Y#a> zQ}$K#Vf&Ucz3bign=jqEHz`x}2UCP7aA*@82aHYoMJd!fK}7ER>stXnZ~E{|$)(yq zjzta(TIRodPCcMlA7hhlB~b1C5tYv&ZU+T74u-e+urK=0&`!MMj99Bh97JSV=9HBI zf#@BA098ds+%@>dJSda9x3TPFaNkb3!D6+4vuyYA11bPIX!9N8O#D3nlqlHd{jU+twn=gVCiZblh0eog%-^LLO|(E~#yh5QuyrTCqN*ReDloJT2i_T~?$Ua#xBtY!iJQSN)0?5!h;QOcQ?;uB%Jfp-FajgJLy? z6Hno3VWc`K-7dKA4Xh7b)G)k@yX}5XQ2(}Rh>Cf|q5S zrZDvD-_ar-UxM5KF@6Z;9UwdNLpyeDCL}sa()W1Xa1f+`DmVqt#P?Vo+bkM6^a?cn z(6#%O7{H_$Qshu_qU_sl`Z^mf_SDV0HXK>3c-b$6{9_amo#l(ZoOmsWL11tm3dk+1#k2rb zo<&^ouAbGGuk(EQel@`wJd;_W?00hZ6@ogribPyK68P@aTwb)Aa9i8-<(nHC8b&&L zie*P4sT2dG8lzq_J$WTUOYFY`bY^{MEF+9hdL>l-aFJKL`>_h>;kjsi-7t2~ON`_K z0JTnTHZPt`r@U2Zd}^Wz>j4!ve{KDfSjeleUAl|C(eI*yE$;N4TZ>5~5;_!lc(k>? z{(aw@b#w2HJ(UwPZmWbmWBeOOg^ptgfaqdif>TkJx(Ms3?r!l2%wAtME?hy&Vbg>1 zRr;8bTG)?PAMrD+(9 z{D<4F{PiX<>5GG#U6+tXz-h#R{KS#VVntHAra`(>3O(_uE7yo^HKN`L@U|~A;bJ|J z0p8`l!M}5Q_~rnF&c6~FP*Mm{&zBc-&MCn@b2=+f7UQ?>jZtlOvTvIf2(e#)Y4zJS zV5#9c35WTw#Y#%%KnV~7VIRoO6nER&j4Q|mIemz!P970qlvf?40CQQw@Xxm@@8FjQ zAW%h>>_jK@JJU7CZ)uv;?mVKupT3!JRNZ^unYF&FVnM9}Y$*s|2)wyO^%GScZ)vuy z&5i-AL+{#z?;Q8s^Qxgwg7q|*xR8bjKmZbB-=WR@x?0OnZdx&CG`bb6;E zws_>);O8MOzFx6>zGkRemsPp6LvfrJI5k>XHnO&gii`}X;he}MfYa>CT?V8Zo; zqIwmJ&3K%zcbpdhzg%A}Ly>B=TR#8lN$O|Bye!6XpsM*{1J_rbwmhWj; z`1WnBjZBTuj?AHC=wYf@?C zWyE0D+pXp$sphJ>07C9mP88N&AWDNRtO!f#;@cIiyw^A%L2^ZkK1+9IE>B}c3fBg> zqJy>LIdQu(oO=b0@wUbRSN6J*-8S79j10NEDAL7NEA{C-G`v-hEh@nstg|{*W0^6$ zldrPh9s5yg0&vvhh~*hT5oENd>zfv=g$xOH1GQIt@9N$|$wnf%X^8f z1O&YWL6Z2eDZp;kDQ@HB$ZuZ(-^Di|mzNy%>lrs~A`h$e6m4-fo7g`(_9*E}ez*Ab z+RB$i8NlA*FiQWObsXN%#Gn(M)yQV>+Qg_p)f^Kb+Ja ze{cK379ze7Lk2hM`JTx2I7_#HdNb~7B|^%3?+kK(V12>uU0#^od}3~|c>dGy-bKwH zmI)U8IfNngd@s%L=f4VG9KF^b?lR7*Tmj{}*L!6%l>DTAC{X`FS;#@goFQCXofQ|R zf0X$|N;d1dk+bCPXH`V`+I7gw9t%`IG3QoUS<&JO6{i}{#mbhkf33KE)r$&`)~)AV zJuO5VYJ~b^5qHQIJCJoh?kD}cFk8Jl=6;9mey6mI3>e3^Q@h7;sb-NW&^b4JshiTw z_>sEGWciGwUgcV=x|0c?g{w}V&Fw;HF@#4pr}sV}QlFi{s(j{KA6RmoLdF#m9`e5` zIva-@KNl%i;NSK-S^dL1(O2N`DlL#kjs5eHllE`*Em& z!H^Ajs<>d*UaUo&v23ioOp7+6KY|XLFH8lySKhKfqIrjMYgRwns=1Y^2P`E{;VeYc zcppJyZ5+BH6g78v(^qu~k4~7lv(mfF_D;gx?-%iIvkCWVkttu>4p8wAESilBZlJo! z^Z~aojm>+BnHegNV69<=dGopQn~b%7Im6gR>dyelpU_LOg>2*!&F3%l~A2CfBQLqkANks?eBg9OLHJXjibaWn>AyfiMxO(FbF0h<_ z#-TR%g0*ZzS}%XKbw5FaA^QfdCjnmkA~kXIydEz41T64exgV%(0Tq&zPakie8JJgI ztDYDMm|O{rloUDmR+0F6RVN92SgG~KKfJQJZW9Zeq`tq<&u|d8=0~}|s=M@;-P4%Y zn}+q+KOJ#nm;pdlz`ImToVfE=Q}1E0(3}MlP3Hs-&8*7G@|V_7sG>%CVIr)-hZ!u;ULoW z^scTh32etrWPl`aCBH&VoP@A+r3d_1k?I*Ie=LHA4jkK$xj! zh#`#CLKPC0^2ypEcvotPHZ=qkB;FJ!%gEbn5+|4cnnAljMx70WxMT$8KoyEs7@|9D zgZQ7vc-Tp3E*8x{(!FY?4KQ$gvA%WvfEC-!pH>%j2FQ=dV*XQd{$U~GmAB3AQ|WWw zK>1+h$zMfu~|k40~ny>+{&6x(7z5u(mn9;n8**Zs;!&+n%t<{GtXbe^4gN;Uvxrp1ln_Q5;AT&o%FS^mQ9z8?HT zuMsmsAJ(%|rpftV)h=7(-->TPKL_^!IHT^ge!2m%)(>=|My0DdZ{O4D^aSZ$ zk@UmP7v~3E_D23P&rdp0RvX_qec!(Yb3e2)WyJeQ7u^Uw)p2xFK_a+0Dkap5h8d#u zS0ANV9Eao#FSAbvq05ws-hIH>H2fDRt(cdOgstk-ScDH|8qcon&LbDNw)rOFGK1gy zgQt%w>?kzWQ2cmwx{l4?)sAx@G`<_u%%5habo4I|H2D5wp=V$Y^2`A5h-M1F(=^jY z4B)`)wbIBScC_$%XtXRZPCu+rnHAk9&3bZnq^{1@6;>bpxQNN(R~s< zZ=|b7*fY=|Lrw>7E;_a3h0(V1-7oyaXJ*D7x@Z(8I?BLZ*_?_a!SH5DYQQW_*4h=4 zYg<*Jfj%}=PX9>U&My~v%&n8=UE+AS<=4KWg(y~Y(K<;#B-%!jE#lVPFE0vk-|hSs z)E6#knJwnSIyVNdj$9QZwwBjv|uLs`LT6!qq_};4!$9)s}B@DOIZ%xMz!79 zsNw`PSgOb+9-e&>!hnbg(gFZZ^r%6S zTW>ct<`W=4yl%KWVJP8Opab{9scWQDEYss(>W9?3f3{}Ezo7;PIlP*zTjZ;~+qnx9 z6<7(Q;Wu5>6}B8oqtuKh{K-Ak#ogV#I)~EqcP6Q@HN5mXGqqs-V10wTrwmS9Uo>p# z5Wbc~jJWJOGLjv4Y#8Kd03nY^ zM`_^jjw-zCmUsxi6}p~kG8qUS_y`Xw_JU5rWqC1EhWD8$^bqn z9)vJTZXM;JbR<}0Oc}#{vx=m>A#a^)eOt%Z@=dpd8>1qvQyx{ppXdn-pgUBG#`zBi zzQRuTNQAz*8kBqHsIO%n5FzP}K;F2Vt9|qMRwd*i8<(aw`v10zAo_ph;-&zG^UrT;%k9JT!mS?y-ftUZ->QdgU4sK+G#75@yJHbd$=EUJgOI#NM{Ox4PQ6;Hu)B z+oU~O?h)7jF!q2;Mx`BJ10mQ8~=(1C{#PHU8@wDbGgg zU^AUV&p%A9Mm~MaNCEr%dh|&l?lk?QHK_95?3j9z6nE*?DUJ}fR_${sl7qpD9{5J( zN^0n-92H)s)AK%DD1dPFv^0r_s&e}lSUJY!aLaatFG)aJN)=^vn?OA_dhR0-aWM#% zUCtnm%AQkmIqM*m*bT%JcIzM?O$q%F+_ly{cHkLR{RTycF9586=Rp^Sl1lvIx4vUS zx{mE77l6nVGUrA!!S#MX*2W8uK0~|JcHP#K{K3|qOtZ`#cpRl9;g!Z|^L4ET!TDC9 zKHM6bI5iEKmPxbPF&O3h5tfl;@z=C8$CXQ?WnDi{l|WoBcF>ynm!>t$1s|cWM73pkqK=jMjFDUdiiK|yoaH@!M zpq)`2+HF{vh3(AA4l(X5c#tg0%hy6A0rIaAK&D!MnsbD;_S^KO30(*)#q?-A+>+&T(UgHDmuroR+4zJoUWLa#CU;mH=6U_Pd zW9sx$F}PEo!-i=8PD-s}?}VIZ`S=Z>K4}V^o=V&(y0H@XY)?=MgnS%52Q!etVZ z4*kbHDk|SR3rY!g7<(qHfuRe}ath^ZvyP1RsFCcs^UGzNMgPvSNrwjRTTs}tseo!a z*!d5l@Il0)ld44Kq16X1;q-7!Nd+!>*)C+f70L5CNIo zP zb|x#3q9x#*`BS)-x<-0G$!|bHq)DA;prslpVt3e?Rv0X(>;R7KY34jJbJnmzPZUQm~Vhs3EXup#{p*U*fkEq~aF&hj-;<~+cS z09R|oVfpmYWKpn9#xcbgNYIowo|ntF?hS95T!%ay*GPQCpoZTO0Nz?# zCVwz^)GHtTtw-IOZRGT=;YHI*z&w3l8-Pyak+T<`8zNQE=N83RyC=oKoO{o_br}W` zs*2?N_!K!U3c|t^8F-nXQRw*xRCD0^ho)d3GWl3`Teh%EW=n(Q`*m(#!eXQgFp zYFWBoc(ApD&WKA)YZc*`t8rCPZzVqP)ew#{s5+gy@dFi3sr|naGJr?%s~)kOnlh)Gd;eSBor;ym zN6BBSXD4_v+mcfA(;)3w$G;`@Hy&Zbir1zmxm%46Nx3wqLTyRoX+Jwl05{*`_V67A zIp9uqAk#o4)+t=ON++BZG6MTQJaer{P28OM1x(&yUsK7eIkYkpOA1H!v<4>X)Ku<7 z&D^KinfvbWa(KD#Iqn%Jrc;ZI&tl`3kr8~KSk46I@Uh@AppEEq6Nch$ro3akP+KaO z9#;l%cT~35@nJPxJDv=e;8f1)IJa==n#Q``uzm(n@Af`Ac4wxQhLd`B*!DGnSw0VR z{pimA!Fz4hb8mms(IkUnQnKipbAI3G@#6Haq_+kt1Nb6?ENP2$O42+te7b5kY8v_} zv-~7=nQCw0hmbo*-L$8pUqgf=@2`J&8Hsh27Xu#Wp(cNj1XWev(a+T$a+!jCQb9+* z@A*YBOj#4M+I6w31aioUqX@1fsfU)a|JUO=|Hp6hWqju?Vk)uwkhZLtPJuG->H3_* zsdH$3<5I`m@Yiq_z;Au2r}i z1eOSC;K^UR8+p7rHzLf}^jh<o@7&fI$go=dHnHkXIA*VhcXp73G0ho&osb2EM%j??djMN`# zbe>4vLhAlFYu2^t{Q8|arH-T+5q&Xnev?(a?IY^5rs1X+?&xj7VP@_1wV_+${MYvS z6mIk9h4e^YfC%-FbehF#Wn9N5VgKLwO}f$Gs^iACJW@!tJfdNAklo=2T`y@=st%@51L zx0Sl`s>pQ6@Nn=reeDy1*LZq5kB+EMyb1jA2G3DdOO4iF9o<%wZ=fcGmuQPDq``5y zw|rB(yK~`L&OH}R+up2JYTjDdKd5c)Yze$a&NlIm-Mhza1)obV(zvB0dk!!URqRRqUiq zm9ehz-M%nEt0o4P=mZq>bJlX9SzTI>y!PUBtbCz|Cg0)hd=`}L+ZlFKt9-CL(sb#j zv@nV$??roVA7l;Sfdh|q)UCTlHcy>?iA7wGE|_eY7OREI7t5K$=>5EY{p`{vzgbgn zwLSo5fYNm6>a`DArgF00^Up5cGOp!V8oxjqo2K@1l%vX|U4Lh`J0KBW!k4^of}9|B9<4q@|g2_d`;*6TfIFl_&IW z(j`Q-zd~qi;in_3Zp-H#-%6FcWH02dUkSd%Q_wg)WctDx;;D7#mil6aDSUO5n}+#@ z^R3I`o7$jZ^gCP4-vXYFzvL~kcR#DYt3ZxR{pHl`eZe7=aj=kQMQGlHE9hMxY~WAW zDY9^5@sv)j(doxer_o{1WV_ht?Nn6ptj}}LNmv4}yx82vyei9WgqY{Ji968tFQ;&W zS2OmF82bJvTrbv57BYkl`gS(WAe?DdA=0Rp0}T}PWyTufXd6+}`%LVm4@bq95u2+f z%@&8Kl}elTkt$H}-WqtZ&7DtaJ5lLqs(x=k=SBOt!nD%Ow?C63Y_%QrX|@%3c^Cul z*!wmwD%|+f{rpPs{$C65I`sz$I!x1p-$g`A&W{x>cGQ>iuG`jEy3Jg@tz1MPUBL*2 zzsZk3@RW+rPRrP=i@wzY^s8^M&-8k!v_!?xxG0Rw?ybv}zl~U@0srlO8>hV~>nhVY5dcTan=ugB95n-;Z9E8Q87o-B(ABia60-JGs??=#OeKCH6B2 z*R1&eSciNIYyMWB_4gZ1%-TKKj(;=$P| ze6nu=F|;&W(EV@MdSP=jSxPHp_;zc1?xes=VR&dO0A>Hqw!Tn|4V7w?aig!E2f7w5 z@QpKx`je-bpl>0s)eQg_=&BO-SYg_yZEOaZ6G=3<-Ir#CG2{!BH-GH~==em1m--n) zG^)Bv{cT$sl!D8mE%)r9mK6PA9zM5xnyGoOOn=FV8m|Lo7~RkJ_l@A;pt_&S1~C5J zSUbt_vLGiF8vWQ~|4MFhGqTjJP0+P7oReGaQ!HUEuIz?F=cc-%hX%~%>-Te+FT^~T zP67xhY!rn=LdbLsY;BLO&#c_#u&dGibC!awMN=<>-|q^}ARi8O3r;*(Sg#5SA(xi$ zOzdPLdXk${(WvUn@scJIG?CD0$)|mFsrQqlE)|%6-&e2oF*)%erC~bt2_?Jfyk~c6 z6#kBu06uW+@v>od<^1$oC6y^D`p19}nMTbGW7DY~&`P2ctxNCPZO^Xi?02)}o8@sY zY6FHiN53HKF~-5KrT;LJ9sdT#4$55)4w?@n{TmBZ54KT607Q;@MRWrDB%q&y-7Srx zH}$@zSj8II+nx%gXZ2Mhp(3DOL>kTJ30ir>`S1_^F@Jt|kQd*&SL=Tu zhTsZb*4_MEQv^st7kf!aX_I!X&tA(~bKFO}0-v5*chR)OdVKu6LGxJCu5Bago#^Vk77;1Th; zlg=u{$t3T_$A88A0{mY+=Bux${|czc?Ev@rCx`q`7Hb1>7TFu2BhS7QZQ-u*=rq<} zGnM^z^7i9Y=9n}2gy0zqnH^8RW zPE{9jO=MBPTj~cZ57a)Ki?ulvlTA67X`#o)IFON1nS7i1h zZb^&VKg=XAKJ7ADl5edqg18aw- zWpsEYb8{Pk?^i#xGo!2Y9+>&r3-q+PmOhM1EGS!99G0okqFx%(2+DvE=tH?mq7rT8RtQvB4 z@XhLjTi1+BM+TMD%X+`#%u7$lkO>Pb|7BrSQ3tinSg8K>P`$LYoqr{0bJ(WXOAt|Z zZi1Vb=eMRSyX9X2nhA!6tM29wVTEOn9%Jw2!Y$};MB`3{N5|eFg21E-WJ`@)Nhbm$ zer)%}svvpuW1rl>x@(@Ovkl7ykWT;I_0KcDGob zVE-##IT!s-K05l6D7BS>e{K4W`GUS|tGBm=qj#PsjrNO&Ys=djl(v{MyxrMUN3v=^ z;MT%XG)qQ3l`5+cuAbmdbOZk;EzkPBMHM1@`e<^TFhctGRW1RSLi0DVAcztyY`0jB zbTi6GTxxwrvF&47PO<9YR;Htk+E0V$&6TGFc?kc|t$U?MbHpM?6s`c4LIE~uG)={) z@Q3S|JqoZOndU+7OSk)z7)7>Q=tsYay-uJxYOd@p$t}CL))>|NzU z>6x!l-tl-CYy7>5$k>TTyo~mJ(A5AT&MWr}yYv-}Tj7URJ)6O2#q;%PeF%aR*iG0} z&fZjV*Z|ztnQ+$XfU|!v*l)yE?wd-~$G1`1U$#VNdW0=Hdioda^reK!=#1 z>TxG~{ZmgFOr3;%bitPw|f7mkC7B6k?iSzZ#6`SoMRbP9WHT%)Ae@f9)jt zi)=XF(MR>+Si!~-F%S???;Mi)cKyLf@;zWBz`Qo>rN4#yvbL`|zS2R3zkIHjDwy=0 zq0!=zBZNPr2*pIb1LyqtcLp2XIqW#6WA4`VQI=FYPgksGahmtIuWh{TZgfvq&nsmx zKH8ZRVP{Wpyw=~TG#W8#kB#h|En|L-faWtE-H}?UIvq}VmNOGap--hNSde@63h%Gk z7M6#8KcEgl5(A#yrHsaLwJ}oL_ z{=zf1vfJW=JOPd2eVS);W*ulrmYDJ}uPlXWd#Io7N;7S}FfVd_-=xrM%=S<_^W&*x zAzWWIbqCMqX8&>GigA&bDx&F%kVi44ix4pRtWJFmmAx>!6c#9>f%@{3H2ccrxHq8O zn)00V$_kI5KLJ{#jN@29{@YE>{tmik^^)7MDsblla>ef3SPjLBIaJa16u)Ebw!R~C?z3GJn0zGc-&p+zwm-1(F zJC7Sz&5EvF3CI45C+_1$tC)}MTibv9|GMVtl zSjjJ5C%$A~$9g+q`$AL52R7G_JFU5X4ifAIP8(Ld2vdV0Ws zZ)Wz4Bao!^4DyzIN?p`DSbpkWuzOHY39mUcRm zke>T}IlqDAOmDWnJVPDLt&4u*#NJ(!aifKbUt@rp$mk=om>7Mg`V?K4B{?U1IQz>- zw%%`Z_{vaC*kp%BK&=3=)b{T>J}inew)tbTOF|e+s}N5x(K62`eSpF4dLR}U4iVx( zHI<4buO^t=Hf!w_tE~CFOmV>!)2e7EoJ1odXJI0?)m4%FYhcLPI-MxGtMF(2ZwjZ8 z15p%i`>y3OuP4j$`UtStz2jYd`ROr$fQE&p&~GKbhrs2Vtv}4iVuEm}X-?(*OIc=WT5NR6p=rYF2}q2 zH1~7&2e}Tgigdq}0zFTf9%C)ve3$v1rq*sQupHvmJGP|?Px^eM+gtjU=9X&PFia{H z)NCc*)0SPFJ|pbO5vSnn-i>3v&LAeRPd#%aaCVS$M{?aQ0ItBWYf)u`5W52XZyO9o zFP7D-S3jjffCvAAhlB9e3i0Zwkl?Wy{k0W<#Y8*C?+FGhvW`}eM4!hRFd>p(r1e0n z2IN0hu$JuZ{4>tUy8*oq@AP@Bg+K(t9Z5r)ru^An@5z**#uM8KP>Sht#=TpVLc z3JDvhqV1TECUEAdf@jw}=Vb=d@j;X4w~+w=LupTufzO{)+aR5(is5-wb=*=5)ybs~bp>fr=Zt`d@N88~hiqdA2v4${x#fL`zpAy0|C2njiT@$PDORbQUtX zNc~29yF3i*U}R8X@2oEAJK7hzoE&dGhQ~f2k4~dJ#m&lwqjyu5PcyFpA6o)Qtz?eA zzXj@kp293p(h?=?v`IuH!(#rBgEh57TrI2i#`AJ>L=Xq!gR~ngkD@-NgzXM4X>+{seOWmeG z*@6SIt3xV?{_t?^TVG1~ax^KNdusO1ciWpr5}(Q}GIm!tk1iA|oj`1Ded;S^9eBAF zaz)YBZv)$WT+0HT`*wD6B@FNxc+P$d=i%!6A~z)#{ayLoZ*DE_=5s=`@iO>Z)pqU$ z;n{1uDH~sB38{R3{Ri7v|L4E_sclFDu)nD7&e1W>5rJp1UY?jzf1R#ZyyobEI$l^I zgR1lLM@fGY1Y%Y=N((g|U^0Jktc>&0y@`Z}g#RTA=e5gWM&>bLaSB+vC=5U$nH_JW zQo~pjF<-+zSJ4bj77;T-U(rI#X`$4dCwM={IMtDcFs^bC6&k}gO$}6>n%HW70-%iE zEp&K!!iMIYONF03_(cWU)M5Har z0+&J!6lAMN;Uz=piwuD1nPy{@gM8;saYhQ{zQ`>8RZ%n4+ukk{RWoza%fxg+)6Ob@ zmh+B7^HOI~VKqD?V*4jbFgq;|%5wd0!R-0!`_qoS^x5G-{L-}#I_KR+vusY6HYTa& z%3RdviysCu^nYwY8?@@5;)F~2&w#0K7zF$7d3hjkjStIjTgY4Y!DX}mcVPx7S#p8U zr+AYieQ@h;WpB((aMR__-A)76>h2zG0vEp97>Mda^V&8n|EW~Iw*(SEBB*&w9O}oj z5?A<@==+y_3RuF7dP(GL^`#RT&B7GQ_n~|lrCfR%0oxjS7d(pb>xIB{8{(hv*g$n= zfv5Rf+C~Exh&s5W-a7;P+V0xOBJ=d08THn3GQzLiYYWD;BXbQ7e)+MK9n`-+jB9oa z+|$x+%ktMs<{v87ew_wOLX577n7-b-She<2^|u~XA&54|yYctZ9p_Ft?{Ua=rg*VX zw4DDmkxCJa_YBY%gk6juUJ8${5QhnS*GU3-q4Ln^IqT3O`oH@K#)(69$kwFRm{yzS z9{~yLu`2ic!cI1uTz##>e=_OUqP$ymy3*|wh<9JAr;e@{?^mrwp!9r(6|ZbK@-mun zsTNy*qHzP4vzXrUxcv;*{ovI5>_;Ny^quD)~iwdBSMYZ zxzmN8w4^qGDaN9xFKbwjQ8O8@WG&}bI50GQf|SE!Ryr?y^3hNErC61mM6NRN;pr+* zIL_ipYsF+Z%cp1`PqRqbSK5;{UF>z81A+n>*wfKVWQKjyv_!k}A-nzbHo4{t{%reM zY88K-LteZip+ZzS)VhGwXRqO`EFn)v0LORt%<$XLg2xI5;^Q@lJTtpt!iXo z;Q&Z1w-0{d5yZK8^P}QpjbbR?az6wiLUgE1G|DJfw)dd9%NwIFA}FoVRWHDhd{DXq!MV=kQt4c`z3; z(+2WdMqG~qA=S{c+5NcCv#F4OR-h**jQ8{{z&vG}uE*oH<$!3uXJ&)#YfmC)lUqGw ztx9cD0sN2}LFvw>=v5kjKTO3jblSpQbu*jW7wfqWP};3lwM9pQ>!h{O!?Q?uuCneL zXI;sG$(9O}(p8M)5>NH8O^W+zW~g=m#jRy6wnt#xO()FSY-dIkeLzy@PNh>h`9|sj z6S{OXFRH=uP{%>U_LK-eJs}0D8OsMnAEAv-ZfI0e{+i=q|(H$2o4pBaM(8LUXTO{2@=eGY)(Vw15sn)-&v8 z@t6)n)1JdJvV4-QDnj|ECm?w-ZrctTm5(PC^sUrNyYV1>Xj4XD%y?X>S*(Fg8BM9V z`)9Hzi$1yMxUOEX&2|wzW19$RpDau@>ekCa;50GN+S>>J#>)p4SXl)8WGlUjkwOKs zrAaJ*^&x;5Nu6Xir#5m;3G~ea6yxN!$vge(fJJp@BCY7~pjRIr@{r662Js87O-nc7 zsy3_za(Zgs`Ln(b+s9`{s*x%0-B{zhpNK>Mz%{BXq~7=EfqNd6M75eG5*k)b7dYUu z_7)9?n-xmi*Xuvtapp|qp=I&F*!*3^xDN2ACI$|3FiXH7(g0_o{D7ETj1!^1MQH9k zhxwq%%pGULCna*Q9`I?$Epf&zp%;z5cFycQg^`524N1MaQDb_jI~!vQLb45q8-eb8 z^#c0kAmc&uuhk~MG%v{2J_UIf?|hp{^yEHUw-xR@njaXWpS<})tsCH-K)@eA>~wa# z<&EhMj_^*mT`#^NVPDcMzaYi3R@fl@r3u`=mYMJbi+hre*R z`m;seartwbB1Wol1rE_2O+*$E<)+$fAgyL43!wf{kZ5m2`(s~(@=44O@QVsg^Z{R- zNQu74XjA>)@B`BuTDXh%)_XlI#4Z+>)*}K_A>PUqy*^x>F;6_PF2V2Sy9Sa&RcH40^+a-n0W(wuj(Uv#2MO&zKpA6E7qYsT}&y#J( zG_lhQ_*=zpx$Dw}NnoTlvQJM-Z_U?Qh3G?=PNaF9^0yu{4Qjq)xaZbRmvr>#c4SiP1NJnd#VVOD@Za`((Pz!cBgpEgzO=sT z5s&$i$>e&^ViUp1Mf!#FUhzrCQ@I-U&Y>1*l{{zo_Y8X;zE9+R1cgrRN%$gy*afPo zcL&BE^R|=%t$fKyDDmL zY45FRZGl_HpNF?~@JOOhGwZQhe#U7q>F@v0XQzgF4Vr)}D;ioHrZRVbS$gioccgjh zy=v}H6Hayy-_;MLe9++EMSXznb5*Xq_ECtS=ooTt`wf=UBWrp0&!txrz9)4??BQSF zxv{5SGLhbWza@lOU}e&J(Gt|B)-+sXL$zP?@uLLarD4zt(Dyx)nz2d9gj}ZCo)bxQ z330dP+1i+&g?D=wlrvTJ2yR}p&n~)4kkISxotKBPyh_t6b?;{aOZ7DemhsIbZEN0G zaz46|`wq+bQkF@s)H@RXd;3`mFH98B)#h=b#SU!!2@EN+-$R^n4S=YFN~HUd=y$xwsTIm}ITvO@ziN{Q!MEetpZ5 zXo5O&S6N+kFc^?t2XOoEsl(5ry6jcvBUQee{9!Fv3~dvxA>TgFJWBWF_kRd1rIdL_ zH|_f79kE%QNpaSv9|^PG8~~=I6i@doD~~Z_(hEaE7_rqey+J~vbJdQ5Wm{r1-Z+Kc|o+KJ6*qGifyW@P?KlZ{~@B5PQ5wpk4_G&!4ElY|t0(Cc2 z-4`W~i)1c6vk3}BK}&pB?skX7-ABvi&JQz_`7fR|jB-rou1zdF*i@x{Qj4*3KQ8~> zn3+{x`yT%FzoiU6@6DA0K8A$ET#**oXn=F_$-mN^zcEz2OP)(ve7p;4&+J|}B+y6) zaTR}=JO^SqzQ|DD>d32_US0bnyF9uw1?xz?Vm*1N_|W63r3_KI1Qzt$pZl~Z$d$Q3oCD0j}K(>jZfA^oM zFBuKKk%+uspX<&o9qg;ePE7~Xw@|Dm<)Rp@8je za`bYW_gNW6ObW6u)9>aIJj8n|)ym*BjAmQWP=@%_!Q$CVh6BvFmWv;l%cGQvmS)Nr z_C(zw#Jx>p(Ru!{%@SmSyIw$$$F^qcRyLwEP1F=_{Qp{j+nrNv{wvG~wUhTO^GI4T z;Y!t#s`Y>xw4Vx9Z(_BpV_kxN}fc!g*veXpTC(fgm*-ngA9%KB?NCl7iIC&5ZC=#})hO@}@uB zp{i*gDjS1-sq&^P#1XV<<5WjE-L7G0{DrDra(XhLks&x`&Y6{Th%XKO<|x0 zXhEjhZ&Qrgkl_(*wq8AEy!=F;lgLdsJ|I9$h{7(}E~4sg{g2lM!gvEdA3`(4)o`Kc zWgo*wTVm;R=b9$8lsXA^72`a>pRhg58wjh@guCP{u;~nQaE-Rqn>pFfyMvuD$1VtK zK}cuiA`-

b&if#f7il_RXa1?CMl0{hs0q*D|XM$yl3wN>{1VeSfBW`_>hsxV9Wf zj@73(Su&I}bEAt=;}?qFaMzB>PWGA+j!c(v_RvzZQwt23BEHTx~ zCAJw>tu;wk09JLt=vAH?LVys6_;Coi!Cn~rE=dit^tu)${#1%?T(OrhjSG#vtr3HV zrIdh+O!+XmNaY1OVO0fQ{_i%tlpcdG!%YM z$FNaym=ZHm-Kv<`mWVTuM}_0M{|1XXx%((5FeoDU4*^<1IQ&E?EhaCjzK9 z5kVMR!I%f|?S%2lg>$-Z?)GuCpNrK6sL8jra$~fWB1h}43qGxHm@4tH(i?1hqKQd1 zbp%+`G_4{{4U1*uo|SXha$hogk10ak-b}w~dMW(FSK2xme}h+Ykh1+-O>R8rAAP(P!t_zQ1TE+KZeV$7fws*>*--9Lv`j8QCTKt8_53@j%F!GJt zYf?1hilor!4PjPg=`id8$&&OJeBk3vH*fDBx_(HtQ2kq~L1i5SSN7BH3sr_E?YIzo z0g5_GZoVI?wc9Q-g!r2;NM%1>n$DBDzpY-;9{*kS=tT=n1;`H~IZ0J=U-p|F)2+tw zlW~C;7uTh<;qbGVB>#h0GzD+wiQWP|nn~_jhJ9w=ymNE)t>UvMxw0S2nz4)BJ`*M) zZx3SM>kDOozkSF{S~vie$Cs5lTrj}M z^Y5P<%EbOg$hvo;tEu!3jAmkmyx1No{>-Bw?93V3V2CWn};&ojpVIlvrzAo#z%*#6h2@`Y_0L*ffjgQaX38 zR>#Md{xLQwqE)75O{}g!F9&XCF%?7fzOlY9JhBlOph{03#F+`^cw`!$=BR8*tg;YV2CS@T9~9aN!2Z4q03{T&Rn za{kj}$T7+QH)nnVoqdbWSYOqSOn#a$ZCKKn^lqKtQd1+7i0pOt3orZpz~N$FvD?7J zF@j_r_v<3jL-S}pcbYngVA*e}ysvbK)UvworN6Fqkmrr(TQnDV_{>Z?;f5%aB+)4bld{ls{Y#D zJ<(WOT{d35O4Jw)#KaWS>JYwcD3F1%7%umIvTbzeUt+^u+l^TsxnJr5j0A#0JHUwfYAR-a)^D<7u+ei%9SbG_dW89>b3 ze0;Xprm7uNU_6z?X7dM@Qw^xg7c1aH@s#F1_E0(%W?vDPkVsNYskVLEnohT z2vGQV@{)w7W&Cb~N6zK58sgD?a(GFLPY`6+J81{hsV_}Dc0Fau`DfJVchQfSqqROD ztis`+NRl*!2Bgd^@0$&Qj}`=^&O_$F90z&jps6W4n$Ci)m&Noad238=51Pk%Rm3J- zHW;FlFtydauXvp_9aMt5F_&)?X4l~9pV+iuIj${~vU91C* z?y6H*7=~}5d~W0nBm;teh@4$Za_-QlV<*TYXOfAHyDm2YgzEn*e4MS13pOi0 z#+$aqB}kk$|1&{UD-iZ;KI^+&gJeAAikZ4eDnJWdolgz*HP3$>mO0_{Bt zkDFyN5OYA(@mOrmT)hpu5L0j zc7V?b+t3PFMSNJ)TIYH1SlD+gm{VGiMGIN zH*#ZIRN{6nQLfi56i~!=K}y`5Mgq*hkrs+DN&+HG*BL#7YPUqRFo`1>}Vp%B8n~|)>d?XP0 z(m6v^rFg_rvoSSZ-6SO=>|p+~G~EDl>7sbOvlE%O@OvSG`@;aNfztIg;{{cPj9Xa+ zL$P}bu33B|)V$G8z{iiimm)7gf0Mi4wEO-V+KDcz@o}g{+1UiL%HZV!;Tq)}*QLH5 z0DzxV6)X&@R|0ArRCrFYzZWu6^4DZ#iKKdzrb}goEao#eBZVSDqh>>Iw^JGRTo8e! zAK-E8*($ra&d#Y_Ywd{%T!voqfE}B1USX?YpgN9Lzs#9v2Mfk_EN(`qejCSk>Mff* zh;8>}DPfkTOL%y?@4+#B($wUa1?7D_`4_#LlruqtSFe9HmLh5=3oNc9ziOw17xF?M z(vsrv=ePRl>j*FS@$*HnT|czS#zuK*BlPkPEVTI^ucjj#PLs^~IXV_I%EbBqJ6%W|nC(xtKqANHn zQ+M@K(i)mDyzmQa2SoLS0%oE-h1vre#v-38=%iLv{zE>nMfeu3ZP$cJGJx%x+~SB0+I%ddtdu>%|!%f9_v%Y>(e8qQa@u7o$| z?t+~w@5cAO2a5;p9MwLDqI}FQ=HKZbvY5n;LL@dd^*3m%zefFjNCqtsN2ND;If>Wi zxKN$;QT|y?ELlKrojRxK!#x#{%~O-s-B#XRK|mi>z2WayfJ5&_Y$k5AaYEc_F{}BcQH!Gr)Xc^yf4 zXy*_)PM4-VO~(Pz-xSU?0M399zYrx^x}w_Y9Pq^GzT90IUUsqp8I{|I2aoGum-Vpd znI_yzY9kI!27-aBhGI)i+N<45KFa($%sgAhdFD#hDu$Ymos}pvA|)x=50BVY;Ccru z0>9byUd*bc!Yf|+*3`v}vpKpM=i!umWpO@7R#OfOB^POSpJ_t%kGWu~Q|M)b(_!#B+8giO>@IW43B$W0^b^QS{-H+ zsRe4qPNx894Pw&9|2H}#$s4?_AtnztxaoI(?V}Yrz3ZBC*C#e6;*0_7MRc3VL-@d@ zOn*|hygblXLW*B=dc$A8oWTJojr2HE1oUmQI$4n z*l@wESCjd)R=r z2)kD5O_790*eqSE{oCD}M{<|q>KJ zEc?0#n!ysEC@H9kf#uKU{%yfGC>U#36~Jy;7*Rs8odE5_v4HB&UIF)Fpm zBIiMd!D$l!J>dPoPV-kqTDJ0BS0*bKDOvTRRR{ylUK^(u%SHC(ryvlc;|O-)N_k-R z1<$)4v|3^vX@f#AMMVTj-wBdNTe0cu|4MAzHib_(P)b7<>|XF6rNHbD>I)_#vs6hm zR)n+iczpUzWR@?!pr6Tni2pcwM#xfB?r9IQKC-&{xEK1k*DUjzum+3QHZJENmJ&ar zD2-?vZ7OO};EkyKJ~?xuHZ!B?dhRh-5y=`f1^=hQB?0n6%6eS0_EapVv0VBrIhwY# z+&E#Z{oXn)e?+{oG<6U*RNIiwq)hAbt)}nCKAx$9!pcO5>pHkLuttU1N{DB*x1>P+ z8*uXgs8I0r|Iu`nQBg+g8bv^)l#mYT?yf;Vy1P4v?ixx2B!}*h?v_sJPU&vxk{sfG zo_o$(ti}8wX7;!De&dOkIV0+v6aza*4&&E(AifEHCpU;jPZ`WRYtCav+4ti!`CI9i-M5Yh7W zXWRl$tF{nFh2!g??gowQ08NOO*tMPeEX=4&3PAL{nUiKBY<;xd}Z5#6%tq z#6n1zmZ&laf}>7>%wxh&li^MTTp z1wn@dMZ@bkOUEny?`+>b)Ma&Y*v8CTXX1KAn*pgIu-R$Zb<@)Wei>;QH##nyPrC2& zCa%a+Nhoj??;QBTgQusHFEqGl{Bd%L(B$PL zuTXGE^G=iJ&pDQl)G0{Dfw8$(2QAHAoKw*6tE`O0>w;=2<3dSAnzSlP?)jgR0Rzb? z(8UtAn?5f=cD%^$Kw?rMN4ecWpsQY85>mRAvsr@`Y_o5du{i)dzU`3U`UTz~gSY&h zzf_%lgH+_J9KpP0{b4qQ#7$4wd#%dL*%5_v&t|N(Im6}~=?nyLaF&XO49kS{}qD5bDfyM4@$?&CGcu$ZPfKF%!_^F8V6?Qh)^} z3cS?4BzAeSU-n6;F^y@a)#SX_=XKo`eKfLre{|@(LKfN93v7MKf)SAd*#Y3uUlgIa z{k!HX-?lV4ITP(mR_T0go#))h;CEQlC#^S7*<~M;p)G^gks!(2^QX61;|^|nRxBg9 z=qtEh;H3}=f33#r1~JjF9vcAuE&KiD&j5JRDvymi4z~>5v6XQ=nstCQL9IF@DOsr# z**gEm=?42!S-046i={D3m}z?*_W_PO^uKA93>LcmYs4U9gnGxOPg>ETx2_BWFP@_E zyqWvqsqTv-tv|k`vcXvwpu%BQCVfUw$`&9XpU}sZ+6ZHI*{}pGSW)P)tlcc(tovNa z)X^1-+i_LshA%{9D=-wbfAimBM44PH$orwG zScz;+b=#@@EpI@C4QA6zF&}S3y5TGb4gr(e z+^D&&Xk}f?H#)Y;WmhYD1kC6RvP2&~v((@GxlKU~N=fcrKV=8i37{91db)~_?XUZ* z4HVQXf9u)gL_!wEq@TQBLfS)IxhqoVnD)hmTRTEFwwx!+;^Pb$&v{#!c0g{2oXp^+ zN4ps2lWZ3vdP2xFGwi7Ef<{k7kTmOAy-;OJpu+vQu|X!9qvRbqA`?NeN5{Y!#{J<5 zm>-m~H{_}$T`PNXJfV^yW|uf+7d_M_ws^ln${|MEx7uVyFgFXE{3BieGC3JDRFxn* zH{t>l|EnmYUSG2EMFXURgLgoL(k3lve-CT$(?1aU_u3kH%9fZlMy?+xdkH)d!8kFLE8oY5IL~g;P+b^T@H}qP zs|hWuYC9>_QjeiW;n-PJpkB90vy302^lPj_@p&NkZ1j0QWfl3Ct#5?^mZFi}67%#G z=%$DA?J98IXYw*_bd_!jUIzvS{)FN~j}F{7cri`c&(rV4?*1rn1?n`=(D}#1XvZW? z6lAI654;#Pg)y_oN`Kg=w&23h+U)4W+Bxz~I|LLeGe=ww)cW;%&oY;_0p(p@?|Kvf5SmySC&V8GXkIg+g! zKdTFIqN--5;T#M*P$Tmrul`C~g$~#G(&Y*{zt1Z)ErVBj-47%MQq&ZM2>LcAEpPt} zA`=zBF%6jZM8#jU?(|)%7<{jneM}58A>W{Cgl6F7AGKKj@@tDb?A-@xC-<5Ts74&H zp9+*RSHg7_F43Oynk9Yt1K`X%R+yTjc+zsXzdEcq(>g5l=Vh7kmlVQE(o?c=6H~Ez zH4XBVTV&rt@{TAj88w^6OJ4V5y*> zXwC=it>@@ zY9! zh<)!{1APIOYE-~E{rd$2O(9`OY=euLU-E<{D|Pp?9$&j4Q^$sLvz)IEks@`xSzG0A zI|VQJu(m)Ml6mK2{k0Uz0YMsYWPF=KFWSdMoAV=N%J`Cdh)SAY`rK6~)*#dr`!_LUgub|4Ktg4yqNc81HeX!$wh;Xo}I5Bc&iFfZJzUg>RrUtAJ zPMB2!schCED}ztx6qfQh3r7X>nb5pL+n7Of zTJf6{G%z@o-de}~bN3s)4*X0Us%Pa$?KqgL0uw0;WUz1~Ro>qc-qniF*3i;Z&4E{O z;eo|_02y5PM@C3+$?~UU0=qj7dJ3}G*hX8)LTv!yZ}&*njb!locl=5f38`q0d@ZiYt3Y3- zayQB8VxISdAq=1S$0}y2=a9*S;Z-G;pIE)qk|;syiZG7L`&qVO#5{(tY?9K#=dk0!C77w{3W~PghiaDleJ*gmmz= zl5%L?|B!n?9@MNFx-ON=V&8z=h=!*%rb-#4?ENgbIg%~38nGXZzWdj!(;)3D;r*Z_ z(+os=BK1IddvO_&xan2wS8Lc&noV_Ee<;-}igs&D)_&7efNut519`uHg&hE`>^Cw~ z;B8b8$yy$LUguN=bs@`bpM0rzfc9rSjhfn0OogAdk|UhiaVZ`Cw4bwDncoj^wC`

U;VjjKT4T=nly9hAsi&Hx)BXo_uBS~3 zCq2D*abPyvRqV_GN#gH}5nd z?-$m78npYtAgT_UmYWCc2{bg}pd=jGjX{nWKtIm2R9AKDBU49{^q1MvpY*35L4EvK*?|HlRBL;*Nd6chd>vST`0`_O{K-d!*W_5dFdy2@uqdf0Yz)GNW-Mx+sN zTa#4?2JQsofU8iN1{!K`+`(O(ttqxH(ZS04@vyf7;E$j^Q2&?}9yQ2DWwR?$`L{2H z5xw>@;?ZN6y3tuFXB?h}W4z+grXHUzUDe*wD^gLdRk>|#$76GL`_t~7C@Hp2(AE*L z*kOGoqvF;9iL8ltXUJ?|ES^5&M+#HdTFevAhM+rUn*zG2?A>kWbzr)l^-EcbTF>rL zvhS$4N&agUL17j7Car#63PXM}-;~nfU7oo76SZS?@_`_z*$W#XsrI%4JE=LrzDB2` ze1U?XCb6QsfRnTxyD5asFsrE0+A4KVjPWB!AK~shpG%+87G*m6+yC+^u?2Y9GJhH6 z16(XzePg$rztf92cfUz7Xb090RdLaSD)Z?kKM~3DX$h+TYHIf5(vFg;L<&gUMW$kV zS`>yildK>ICcA5X&*ywMa}Oac9m8`{<)dPWv+Uih6Iwdh#F01mZKx`k z%z49rIY{f>?nrC*MaFL-I3v4)K(px;2Mcf4QAhZbkH(2iNmXq-#KfO9Rp?OehhyN6 z^l!o#FL^UZ<9?xr@N1|E^xFFYNGbF5o6L+2&A}KirXK}yGo8L&kB=`a@m=k*zD*BY zF5K&xk}H&?tE)NN$Cs=b+}g3P0f&duwF=qnhf&tVs^r6!I5{`?d}fdB2sM~D59N-j!U3b*B<4A z`P?cpocB~@dl=j9^KgFO2LqyTk4vJcWJdu4sQ z{3Jpa(JXD^Y9cxts#vQ_AwPeDmxa&dwep>2 zNRquM(i}~p&7p)zwGudAVhb)#SZO57@Njn^|w+5@h``FFmlA zSA`DySmocjLg9w`i?yi|aoK~M%vd2ZYjttO5SYU8egiRcP!u_fwCH*miYM@R` z)&KEagyt*}3oojB3lk(nQ*l`~uy(8-?}_Ud_thkPw4nyEB|=yfQF@ z==Vz~svuwK8y`fngiNAsUi9-G7Nd(pkf1IZasOM!CL^1qf6GWE#9Vd}Q)&R`7$YTT zcpCMK-qCKANj}jiD^h=jp)fIaz)*(=%~IG@X<9TJILToiC)Q?yYTFvx}gB!u#H_*LX}D=F)h- zqImjylPB&^L^`a0?pbX`bOrFpjG0xh0Q+xqGk@=W1fXw5&-^ICb#FsB*7f-6D7rAd z6`fd?>}IJ-m8}cU>483%SR709tlF!i2sBaUHE_`&M81S#giS)A{@P^Uxu5bv2@yRG zmM&;Wg^BFUs0-39cjx6AKPhz|bP?z~+FBn1D7_1-gw#B`%F184aQL?_iZP3H)ezqh z5qO*KDLz5uxhn6j!v4O18bb{#SC^_xD@-YwEj4EybDJYo&>J-JW1+aMP;25&XZ1>3 zVd^q?j(!uxWx7ID6CDN!+j6ODfjtGXaNH9ay>QZyB@q*;UB(9`Zoc+4yN~V9Tl$@R2op1^0hN3^Qq2h4Dy5n8@U*a?Ie`)LB6ELbyi&=VtP+j<-+s0qGe zVG&Fa-J(v6WNVEq#69}TM~0n#GD4p$1f+t$n6&7t zRet&-W8yfOA!mVyIHy4s*uE#1#N(Z71(SL|_A(PI+`td_xDgYKf`~SgYeODOw$Fc` zp|bj|Cq?E|xo&KpD`7KL41V~6IEWrPdRrV8u(-x?iFNsUdEgN3aXv@<6rx5bcI1}` zJrzP-ImVZkE4q_1fDAVZ=K|HVvP_3Cy>%B@6I(Sq87pYVCm%Ct=e8hDO@1+ZPF&;_ z-z#(alL^s{ylXUbPuFblgq!&B{dXDaT0&?+6Q9yruk5|}T-=d+SZV5B*hSg|-AmKZ zS$CFjeXd#^kM$BBd4F2vk(RFY#%<;v8oI+Rjg-H4nfZ*^(GU2tN4Di&gbSa!W~Vlh zFcP5kIuz9aSFMlsC8v*&;)IRwgSLW6wf)*S4SL+ZbS#AV^vmhYC7(094c%y&n3&i> z2Yn+_V!1=T?r|L3Vu)oVP3{zJ+))0|b5WdY1)HOQPy8iCc>6?1k1+snsRFW;tDp91 zY2ftu+UsLaU*lA;&vzT)GMxbjXxh^>F0?FtP9uRTfpVrHCVG~8>jQR?;+yiJuk8Ce zST!8?>3wjmQL*l(9a_G2{k^~J^Ns*w<#5eec3hX`8V8i6GqzXIgGj_8kk#g~PA!Ik zG-{tfPqso)TF(FETg$=0p*I&>J4@x}6-@80znpjNOkwQBoe)aL7G825xDz$$tQQSl zhWy?B@4m&`wjy=@$4m&EQ{YOq(T++M^l0@im7Xfao0MBoluQT;WpC+r^*S-{T&yC3 zjUTh}XnoiYSpP$R+M~B|MfL2|PXIcYL%6{+9)7O*GOkO#Uag$*n>H2xOb3;BCnAg4z-h8x=7@i? zwv1Oyd`g{wxQ^r9NuBy&lP0#bm@tya!Vq))-+?|6L>1bZltC#QvsWR!Yj$#UWz=Dp zk`W_r3Dy)h_18<|r5aC%xcutlI=hYQX7mHh$H(_!e++*&X@TpEO<#;Mh;X}aFeg;A z8UZT|9rd>N{o#+cU(8vPM-ZR`@Ky8aeqMqko&d2RQ$h8G5djqq&DhH7ZBS6q!Ti7e zFJj%5ScPD(3$-cv`!Mn8M~Y?XuR+Dn)&rlnUNj8o-L*`!;Njs98i1^TIy&y@Z%G3m zok3A4L1oG0bOr;N%RCZT{WEkQ8vNEkvr|_?smN2mH~h=8oZ9i%!wGUky3!P-4)vNF zha;`RC1Y}1d5Mc4%nI#wC5f!o;FR1wj54rp;`HuykcviORybEvk`8I<%HhMGAlPiU zia#Hd!aL+wUG1T93xC~TPmrP%otPO%4AP%}Whn&PC+v%CwhpndX{zwS|F?k}x%HZ+ z5Gc>!x=w|;q+Pu#=5HR8ebfhV@Eorx7Q}1sy2nJb2Q#c+#SR2Nq-4aHp&?qr zPEB4F5V*J#uR4^QO9du~lHp+2>1r|V-N^NBe-|e&?9-~@rFboODT<4Ooo=g@J=XZK z0qXd4qCKS3rBd~Z8nOV{O>*6ug zGb9^)xpW@eGVI@Dz`{&<_oqmb>zGuIswl!tO8HdNR*Er!k2U$*vC1K-`w*skx=J|y zg%)GxA6cr`!#72vFjODmQfGY67l&K=0sm>^2}yS6MMmXt2qm|&R=mb;v-VBj$-|*I zED^w>7FK1|-cf{%9d5p95GOZoA*u1~{J9kMu81E5dhFnzc>%R9e>NDo`4#I9upf_7 zNY3On+-I}rgzuTX9xMDr|8`Zc8uRA{l*%@>O?OpBIX&i# zyjVDJST{=Q6{D0=}nzVX11BxS+ZDSA0XU{$L6gJ!h{pTcVv1sTi8j|qVM5A5bLA{0Ti zz?Oegai7(+1sbj)^YV+cD^uB~xJWDKYJ!ecs6-1@JHQD{IB;e+&IAishSc%Z(X z?q?mm9HdmV;@8S>-c%{F;2=Sh7p(|1PMB zX)-juq$szT9{wn0mP$l2IG+FDX!cxrJ6~#gQD4d0;9tDvTD~Y-%!p2~l7sIRv1|w` zC(D8YEtKLji5HPuc9aeN=+1Fgu@jM$Y%#SM`D*=dgXWt1UED%8~5 zH6kS4jT`Pnkrd#+vg2W_*g4E$!%!D$Mz?-=pC=~1A}SwXOPoT0ZX;Cad=m0w{pPVF zg`fND_#2Nx@>lAqfO-@gcMwhc%jnUFO`GR+({NuILv0mqhLHZMhCtdO{ zT7;Fl_V^6V`Ps6sA|Pu`yFEn9T(kL=WA4E{lnzgccIR?|w60r^(xcBj$JblqsX38s z$A+%rHJcOgcbh)&f{y=-)m|vk7C@+m6VcSt$9ACiSjtkQvP>qlxHb^@!r*m#Wp?(> zKDCf~;70re>o7>++Cd=X=U;ml0UYCd_3~=fsQWI?dhy#4uq^`G_&2(06ZOw|?!&mH z&hYiT4qpVbq!FK_=5zcfSnKOU>ikb-hd*EggDv~Xrh zE<5_z3ya~vaWVgT!RczBDrDqBjE(FAG)y11om@;t<$VsC{cJibX&H4!-f-Z>qqQQW zjaZZ=;uj+j07*>Yp;b#8R{^A}o3}g^NakLLsFk9;Igf=EMu@ja zLH@y~Sm-O0Wyvs!d+EU~u>?OE?Z?8tT=g1iiDi1mo04Ax!NM;0&R)mgr_V!-W5Dzd zH>E?#Wsg4z;_uMBD)YEE9J>ijYef?4>@Hi+8~qPiiD6GNEF?mOHzO$YxwP|R5vy~- z_%`HZd5&ZgUo7XnYAOwO^ZfmII7{hCKtiu)Ow{SlKjdj0hacZqlBaIDd*ubYVWrtR zIL1A^E&di*=!{$GeHxJ3nB?WWm1j#>5S|JxmcP{K-Esn8XxEZ!C0a8b*W~!Oh3s@O zwfhWVrFNDY_%fIzvq-cgKBt54jYrDnr}?c?`W?ARUE2D&>**{i*AqWA8eq-+ZW@xngL!~ZRLSVdv zlFz1fH(~(=$6qAwBQ&N;J8QyxO-G@;UeH5LUCvOgaNNZ?QeiZHZfv@METP8;o8y=p zv|g(vZ}GhQ!7V6qU25x5gz`l9yO&fs&iCuDCaaGb45Z3O&GGe!9?R4GyILNcft@~i zr2YnF&b{}okUKXhmZ3GCs8~p;3Jh_(=_JaY5tjXQHzhE@%E@Ua)0FHb>NoKpzyi?8 z%W?jvp9}W`3pdG9O3nd_ZSf6?P*selE@50#bm#;7%XZ0?kBKevh~N`4_Lf z*EO%kV+ZlewLJy~_A-B*UQ*OS|{01TnYi#E$Qyv+9o-;jmV5i1xg*hMPk#i?j z5vjf17Suf!T(=z`L$dymt*Kc2ZodqEk1JY^zAvG8B!XtthMv%1-pb%?#*U$B_)!?g zh8Y!cdk2yWby$NAj8_9k+3esL?emMYz{27%mLd*q(aYkMMclq${#eitRWy-fU|L;L z5UzV*qzTF!51=jR-SZH_uJB?B%lHaBQ#u) zd_Ex@8KY9_jHi1t?atD5N}tZCa@{zy@5L@*)6;AWySKTCiON>A{5p)XSEqBp`Oppc z4IG#mPFdt8w7TUTc#gs+fW+()a6DTLkA7+Hox_U^ z+q^O5%ao*oQ@w~$Icm%!-v3&Jl2hTl$cqH`Dl{Z%S>hyUGJkiK_`tzCRrQkztExgEV!&8OC1TD(b1 zPH*d;#1@>BydkPw6)Lbgg*?iBoPz2Fm7|_4VYl)OZN3)noUER!Oz`yJu(Mm`GWVYi zX((I4-E@-s%3Zf`oCn~O@JoGySnA~^Td}G)*&}4|tl7)^Ett-3i z6w;37!hFxC(b6fW6aH=<-#mf1Qt2ZOC5%x--%ZLwc~#S2coIqud*XlL{mNEB8@MJhDp%<9=GMM=LfK@ zlB-?ko?6i`&uqn8UXmtD9~$izKYd?(;fK)nLQ~KZu7tn`p5|Kq@OMRpv;%L|MaqE4 z!O5}sBLTBEQS6^TK@`hzPjlzu7iLF&fhvL_@wi8(oF@7Qxg7fC??*2ZvhA0RSyr!s zYG=7mqoBc1v8)hf*R|P|UHx^_`>7?qA4FxY_+~MViC>JTO37$DIpry4Khts*B8ZO< zj>q_>8r?UodK$C#3sWQ3Y)zd|?!%Q(7FDs3Di=MCKEm1ikW!()cnpes>4fQUp`#b%?sA#tr|KkFf zOTl~-gd8eJ8jKP3$4+x*XA57ds4%zra|!r!(=h8&)W(O;XOTpQB3;OEu&V1O7BtfD znxq;!;t1wXw1DRitas7nEr6ie?5mqUp&^>GS2wpOuMnAQe*O*Sz^Rk*F7z4ZAJ<2$ ztXT{oH<1Zuby&XeE|86qXQ7{G*WgOv)1P;fenYkEWyB zFCFzJ38Venhp3u+J_pg1=b0V~WOotVkcYmY1uv5>4WUdsm;Yrko&n~pKvdF!P6=F| zIG#Q7R<2n;w;DFGWZTJ$;|^9i@7x3~Stt@!1nt3A@wuyoKgh2a9p~!?;cxloAO(Ht z<_ezR*4#+#p$Mxtbhz1gsV^z5XX@Y`ulg=>9DzxN@G3vZe5>6U4{OaH&|=)Ww#YxZ z+*xiqOKdvd!oy{Zvl2-h^1F$V9xzSU*Sn){B{Cu-16(@c&f<3-9lm<^>3X#-T9d%F z<2E*X2W`MA+{UPvtllkWFZZ6xh-@$64+jKE2T`Q2fkLCaLN2ikDoze`!4CY$AD~jh z%)e_S=n6f){O%p(!b!9Kq_|RLg;WEu35S|F=+FIip((;wk8ExbW=43U5)-C9VK2Xk zK9hsn+)irDFv0X0{QEcI3@7~uKwSOTEznbo*`J1ugGGA8mZu(aBvyW&&~|jz&4=`0 zEvRA1-U9wx?;|+iHUOb05oPuSEyUIq)ktg-TEzdLkOmzu52u4rVoLQ1jv7VIJrfl= z@n#w~h2Uc9kAK38%jD32xp+n4dbGI#Rt74w-Em=Wwl4CA8ff=|B^SrXEm-XB&j4F2 z;-TWC=C=L_;B9nSD<1bZV2pRkFGp{}T95Dl^dBfw#_K$!zFYes{d!BNPx9VqT}8OE z-mdP#LX$Vz@bt7BFxH}uX9YACfCtFNLA2krW;np&X&5Z(Xt_6HSp*sIRnn(Bl&hH{ z)}lGo?{mph@E!MUE6=>lx2N?27{5TssIR$hXQ0Hb6#I|1ur>Sm1J9dAxrqZK+LB(A zz1D3r#xHvD8G;m~xYC}HD;Kue@XLs(s>}SD7sluW-$oL>&m7UaCPRJg^i}VQ0o5@> zW>CIL!9TwC)cFyGdRH`vmn8>9_#cOR@CXeQLl_DwA|-k9<~F`wh_B7kMUb>;SsNl z>J2%r(fH=n zLkI1e$VP-K-`awbrb0Vy+=RG=T1nx~F;E^C?*4vSc5x^{$?Gn8H5oGB5c!iu`aZ=Z zPmZ}`x#?PPClUhiyejv zvPP=%*raQl4Nq(7H-%XjcE9jQ&e$ip6Bc<|JUm!VS63rk4%_Z_R^R|RJm-DBvwsro z9Zc_kk$)=SUp<1@@;0<_=&V+#Q*kV@7lM)eOmDIBykrcqmKC^fwAoYNjN9j*erfzS zu9%_hsw{sar#L!PVd47v&$$gm2?&52e08kbogQ0zeOy#C9`-_ZEpaJpSn?autKifn zKz-mStN+%6hIWumtIyuEEil#AT(|YtXh%^yGHd zxN3zGw(CAs`Un?2K@4_kcT`*9g@~~eU+ocdma6M5p8fI9z<%Pul_7{92(5qB4 zB1`P$ZkrP2SuO=CN`C7f*9%5-?(IJE?*YOm%V0-5%4>9{dVE*Zn>H@|(cTVBBRFcBdnl%m)un)!^N_0GqP!5{lxBBN)x|HjF|MY=X84sqk>!6PY!1*aLvngP zD2!R3O1(Cp`rWoqjQ3U5Hp3BbvacUGDl55#+zFt5T1K^(JJ7PU_&pqvwDR$CKN5iS zcsg6GmY`d1GJ@nAQgnqF=+UPzU9hi=$%Bo)ad(JZ?pWDIX>fTr`2S6X198 zw6oFcCKiyEqis37{0`({;YaYlEkcLbNM@fj8(O``X}$z0FJwXcc@SU28S(-~vzNg) zUk@loY})U(CDR;dU69VbaqWs${N)BrY4q;Etlz5KJ=y)%K_2-k{vG}@uQ7;Z``9=( z7b(O%ZwB8#UyNZj0qb={IPAIcKS-`0?LWA?mDvJQ)=y+Voy4iScHDy0t5?76T@U(y zi?N=eHkQT>4xnh;aiyzl)Dp0CczbjC)iM;=!bD`@vi&lJZy&>Hbs$bN=srEHax#JL zhXKJIDE`_}xFD^W7=?E-y|d3r-)Y`QrOB4ywy3039;FaEZnx|aJW8em&gY#NUoMVe z^iJcXt@41#dh7FKs<`Cu$I&x^gkA(3Ht{?_;ZOpXNh?YB5U1oy%ULg|8{DU$ZtSEk zqJABdsBoN+#q;LL(-YcUQ2~}CT<4rTmZt|305=(674t5lb_plhol*WTm5~g=doU01 zWILq5%D)77-!#(9DiTTHwd53iG~z;A-Q?wNyfyYPw3lZ2CxqfjQk3Mx{PiWu{H_e- zzL2$iEWI(F`YFL$I=(&Us70D>@Wh>gh>{_dEgT7mf&h>w{QlGZpDYEQA<1>XswOXD z>$^lApgC!N83cET9whxrA%M*UwQ3^G+*k^JUdRrkG^t5=ZT0C^Jr(M@8lXz4BDsAY zLM7~sb`{HkDnBy~`B}vBb?l^FJO0fZdu_c4zypAcAZ()>Ul`&(5?c;Ys|5G~8f5WL zWU0`daFI(0yY^l8=j<^<(Vi;ghgGVX^C{4A-#)H-{3f#Ti^}Z6*DRu!SAIvn%F=(8=aYBoUS)xjOvhZDUNxL3QOq#p1OzecIXDj2NKG} zhdU(Lwg^X#&ixJf;x00*IKgSHMJjyy=iMbZByHz8i+96EnRnv?G=G{T^?Eb~1htft zR1`bC{4GF79A^a`Fdum~!71~NlG9PW>PArb70+4Eq8s3AQjECIjX3>CrAc4-$o{{A zq6hsyhwZp+E8e~I$}P6qJWUaqwR6rq8ynZPBrvQY#>;8Gg*Ucj^nM2_Ody-gQJlSk>u6tqD*l|_2V~_J!4Ir(@^rcm$=E51=0^kJ0CTBK5qYETih=d^ zV)bBqDy6hmEU}2?w@;(JaPvtdKh=l#aDHtdQ9nOb`8OU!+(>gv6a;>=$dGd3ID=w9 zpJ=93KZ*IO1g?Iyyrxz#44AlQ#gKgPvmuDLs9>&$vaoaRO9>qfXvV=&#y!wmUd6w!btb_Y~JE_Gn4QfUzc@yNknP)OE7GdK!pgSni?qUi8*!f$6VHS-p?hAOPJ`#*R<~CWw)CyDD+Mjb;Q~eyJ!=U zCE}{hD7WoZuZo18vrhPGv?5{Dfi8zC+j^DxsU>K;y?-I~P7-z6PJuinwwG~ytAL=& z#P#()w?=UriS&m5L`jd=L^P#Z2~i&> zPloD#kETLZe+!6cG!fFmc_pfKs@QP;+Ve9VqU)txb z)zNo{*~{_XHyAA6Hv{wdNd#gS{k?$(ewKjqdt9!hO@<=P?ceWM4$25ZjCDLLDvbeH z?cXj}+URvf4EmhJR^jX<8YMER&5wf7OqmZ)hY$)IFCQqETxBw{XhYGD5c|M&h{Cq2z9=~#7VyvGtj z9D!oWE-}Y}3P{2lh8f$;xaAe>tSUObu2v=L@%33k>{8L1U4k!-=#ftz_>u9S6GytZ zu1Y6&JhoDMg79&sUy&KXWtT>5<{t8zuqhB2$x)Kx-$jr$(gd9-?g1wPzKIF1uSJCD zg7-?9yYmuOcIfo13PYJsYAo|})l(PNS7p1QJdEOaTv)NcY0ee`YgBjshwY3>{J}+~ zYdj{9FJ37&^U`MT4!A(il+uA-3JFJWBp?L)w{^Bs{q+8hein4`j3Eq;oqw;c^tID! zyB}|xx5z{`7?ok(V(WS~u!d&S?(M^cTIhXa7RX}ndc=d5wI@;Br&niDX`n?ULx3Vk zc|&VmDMZ#1sk)WttIM+^oDVE7b)rgYqrnKVoV$s3*iOf4(=@u9VJeo% zRi8ETYD&WZuH?T8LG`2^_(mCYrlH3#5ODTWuIE^Cy{E@gejucXzuG?rJp?IpXmk1+ zd8X1kXELTFe?u*yf|MoUNcv4?*w3^!oT={wX4v70wV3WXWo$#+s|p1-G$*d>&85_( z#lQb4bRnG443_yzEC8QIT_gkGuHZ|}Un^@Or_lfNlhVS%Q`Sm=g$Wjx&mxKo05xCC z`u(}~jMIGt1wCU~*bHz3pohf0ZD9xg`qg^|Ggd%;%?v+Mx|*WD*X4i8A6w&E(M1n( zv=MvbCV?tyrT$mUD{?UWGca^%>@#ree9_AsKGKN$y7uE+^g#4Ij zm-teEtcZ|*(Hl3gMyy_3@GF(fYo^kyt;wQc^^yvbB#w`nQYk5U&DTuoyi49MZmQ6X z^-poJpT;otcY$Q(-raI;;`?1_N||i4f4Gx@Wu$!uO1f%gZ3@&%NJ5=Ut%{3v^eF5b zfe%30(Yd$j`zN(|mS|imWO$PPNy>BE*zgH$|1O?d0ry>(i2_qX6K#-kxR%bzuW5Q7 z1A!0S>reMeb64<)=RDVJ5YG4bB-<1&B|V!`102Adl%atH(=2xvEDSy7uUN6daOMWx(0mFJRD{*pv9BkI$v}>b*w%~hTMgp%gGl!EWQH) zwEEY#99V!{iueTIweR_8mE;lZPb$2)^DjUsAGs7P$Cke9Ug`NSP8ahZWl>N+FYk7( znBn=*L0*%gP27X0spVimB^pw)8(O7RsnF^aZ(B}6ZFmueW3$RD{G;w0hD@=ARoq_; z14tJ#`%2@Tx(Dp%Lxs+estTmWu`3hRyn%#C@RvH8K!00QiVZlpRW+6Bg^@YXBHK3_ zfspD2hYdi`eRl*PvjkIC-;P0-Cbl&qf&;1yg84EhVn{s=^#6J^I!I&EI3U6N?Vx(L zH<4=OMu5ubmVrK%VjcDYP@|Vnzv`mrZ`6}E%ZW?nlW#3o<&(G}IFE_;CZvGXx7r%H=3e&swDau7`&s<+@2HWSuKz#xRRk#LKJY%29 zKTK{qV*d@H?eD$(P>|-g{sFL~A^i_2^)$4NwkO3I#vwsj7=$%7kPdw=WG+09J$E|3 z1JdH6`$2Fg4k3L8zcAZKD3rVDBG%G+*9(m0z#c0_Q@*d8O)P&+v1rjiU8zhcZ{F!? zY6{ob>DT)=bAm+q={~rFGOHR}4)7f(i~UZ^-S)UfFp$y`cQZ)qOhz-q+PFu0gVyVK z+v?lo?*Ot-+3k1ZAlACx5}BI_^RvQ3yuvgUy?EB)8OQK;{2YWL4?P*WcOfrn!P|BR zgh5r=2i^aE{z=8%NBUf@qmg*%sFx~RGmnAx!hQ6=SrZhDK9qU!FDotMDWR(W$P$O9g}D5+H^7{b@U4+8 z8L~}x+^-?C*FEgI>~e#=srL#N)Tzi=QtX|hW|q=qw$f5swu2#TZ;&jjnLgGnuxqVR zdQD9)&FZ>6JzHtsRCPb(q+{p~r5U=0?r!O>p&7bs;JrTI-@Ddbi+@;m!M*o$&e{9yea@>v8|1(N z<-6WlqCi7J-~#kafI*f0@Zh}uUT%N(6^du?!I7Ff_oA2f^FvM5pI6|(u~=!t?j9qmaH8v}7IK;Q_bsT-3yYdW;uBHA zKc?;I-FMiJ=NjPOWAjE9W6}p)p64gh69sgy|EUn5r^#!58;vc)jDgZf3aJ5WK4)}) zFztaTjxtFGl*0Xpo-mjGt!S}%Y2e-r2DN67pe?#MV&vb{{o>|w1xpm>HO^%VntwS7 zP;V5rgfLwz=$y<_1tJw;Qh)@R*sqOXn~-lfb>jtDz_J9!$^zGqqXVKgIz9{#$0%X;mSRw#qF+2K~7HP+W zpm9w_V2#Qr%rXg_>m_AT)&=s-FNUXn!|5E>hv92?N7$v*(JEu|iRl~jep1C8) zD8tj}SUI7(2G-zMIcMM@IP`}FDg7zhkqNh9Io>6rwatu?$JK3vm zPm7s&6*0;}-T;y_xg|hY z@ir563y&@9vfqavBu=e0$zqFKI5M&N{2{}x3DNeARPjAnX7yF*Qadh zZ05qgf4GBtelMykx}rpD;)F_bDfibnMS43?JX*=;`y!_1)k#~NtvOUbskf8D^g8pwMZuR&rc|Tb>|G{08)w| z3LqG;GYlQ{t=Y=I<)oNq$>87ttHNy|%sM8`%wUt@nSgJQB)IsgC~p5-SanNgA^TB?Ap~u!*8!T*cl|juE9$aOxxC6cT20upVLn?58*`1ycfX@`c!q2R zT}cn)rcj}=LSCPQt?>0~4eMO5NIt0I<_vzte0!Q8+mJ;+KC7!jXP$3!SV{4zzEn#p zUBhR(1lf0QGw4=1t&j!Zqt@9@TbJ!7R7rW=G?CeHQ6_a_FMjwy+zEPd7li4xdmvI= z{PiRs|3T?!TeJ7&x))^tA|>#6LXxT$Qe!r1P7zdzFxPl~Ebzy=iP_|_DT^#0zA!@Q zruIpSDmtx&#^`FU%tJ~nxG%zvSXLwHjj?lm-m_9QDAHFHV9KoQgn({`FMHOMkgrO=~BOnc1WW@Wrl*{tM`oKv8*S(U8 zO!fZZeZ$8ZKlp1*Z4yPqNLs*MN+b2uIonZIJhO;a{HKX1Z?wD>6mlWVMF(X84l)$@ z37@lY`eY1<_8=GatXe)rASlPRZ-muVflY}sH@jriG=iYQE5GJsvk47_HCg40NbeDA z($7JCU~+dUbK(?fYBr-ME-fQ>l&N3(C~b>5Vd(a2sgnUmijjpB7F2ti2tSJ230Ehr zzOHW57p$y`e^j|47lI}|KY(HT6~7S;C2=JynF>7RuRm*D1snew3{#*Gb)^P7ul(e* zfiU8JCw8utsxYQuDUP6`)bp9Cl!8M2%q3_E9=TLbHI=wTwxu7od*13^&b~@QXuRn57}(U zj}_jNOSvA%c=m8(vRaDVwb~VLio|3#F{*`MDHfikeor3A^wd8yx--tW~Q!(EZ{0Ggj~n;?|qM5;KCq`e8D* zV^}cjUs$zT9@jm>#m2**=7Uf8`!q=*$_ERhgZ%x=hz-zAw{cbZ-#Oy@_*%x1Ci;{-^+UZUWo$ z&t;=x_$<8X405~07$Dag&9%@rdwu0D1QYpfLHzW|YLWTw^*KZ5^>T)okmom(fa@hC z{FTsK2fO@`ns^6YrHr=uW}4C~orB9RKR)u^$zu@j0mTKa^7ZwW_;r3j?)A|9DQHD5 zSDF7njpJYT=wzSxrLG@qS$Lha=+h#MDdjTqINnmEkQf| zVj1Iiuo$i+5x@I|3ElBuLjk_aV=)0joJLQgaEbcp2%z%B2{qxx<6TL z@jOpB>hi|l=i>`327YgEiOyk{Pvt)r;34n$V~c^}!bbK<+raVlc`~<)X^iaMVEW~+ zVkWnouL$lj^4hC2AY3F~x3jN*Ho&>|P88-x%qKJYEV43H-s`1@D5{Zk^f1;^a5-G= zjG>BOpTJRUmpO!N_TR=DJea$lY0kz8zkRF{@3ec@eJq{d6LDk&d9Z0gGnk7dT_T@K zxmK0GWX~|fGf!P4jLa1z+Yd6wR~x2}|68p_!mgVwmb5rl`=h2YjS``?> zDmw-0BTk1;s+>L=*OHtkhE=e}F=|pzAJ-Q1DF*cJ?ST^Oho_k(atptM zUgz7y#OifokRN^%?Al--eIBd1syKH~T|}W>i5hCD_}H|bPcH)AunbverIXG?jVc4!&a?AG|- z^8JMcqJ{Ye$-VO-8-^254aTKyId>J+Hg3}xg?H2buU4Vz z1O`rYh9~RBK+;3&yG#4tCp5dlAO)lbpo2H#Kf(r8u1(aQ*63?>YpFg|$LcA*M`;kFR+@42y8al<8!~9 ziL#Y^JZUXqeK1c%>$Z-uVLbm_L)yJYP#79og4}&pJ+?nq85Lrq0G_mhTeiwnfk*hEF<~-`uvtnjC^s%Coti_4_ z=3-9ZZt{gip+1pkTxEr^Oq3U0D%Zn7(39xlIp%i!O~#f5v&>g1*^IlLVJ*mwBK1M^ zbK_(#j}i`t3X!oF5qZ~E9K7G)23t=O)lm`4ax&}p$+p94&5lqbG0;OroB8TARCC(3 zkycp;W`TL;O06d!C|eAS==`Q<^Yp43A&GDjC<~E!j2o3fF3O0l4xWK@wN2q+U=Uw- zbLQ^!@f{aV-8or$n(?Vec&zJEesuh662IM1sZ7RK9OBZTQWNkC&4=`Um5TKrnh zcP1fXEa1lxMdixO$DFy0_7dp(PWE0%?&-n1GrXcS>s zN6@Xa4yJqKXq!b#&PR=44n_HiKJGjn8deAIXf~%K_rvydyl02}Q(b3Ev@NjKy8Y<0 zGnGs2V&aCr^>*GtuWQGSF1KYw=jc3~inai?ZGA~!XrX9*B$>kt5p3557M+QC5JXtw zUbnv`Lw0FDG#*{74@+Z;>MH+C!4aLK>-HA7y!jvc%fkk`9PF5TgH4}Ok@Hr1omBVF z(0KB>-ec7@jJM@OW0Rj*$q&9*EcxU=gP@6h+Wjq=5UAgM80~4FJ-PfHGJ~jje!9pb z-~Ib>h8TqTK5#_dd1Z_ zeK6(8S~g>8iOlbjM1^PJz3by{`MH~4&ML|Nd3Zhblu9X+L9!uFjlM#ZtFkp!2s)PR zNMU;5dMd`HnXgZUmTX#K-e3JKX#3^a%(Jl22=dXg_R9Ep^X^PwWsDf*97gcW%lW(R zX_3`rY!r>w^k!F6NgQBgz0`_Ih11`zj!!U%7SdqGCAH)&uf?L@Dx7fb*ZFQlk?@{E z9W>7XcvZPRkWLs=T_I}-r#wu`2#0PE$(4PR2{)^nXlb0&9DI23^zdQ())tF`uB!;o z@PTz>BVJqB6xd({*Y-3PNsqhCeHU&CQ4ffj{W6>FuY~K;@kbYNC5Zc1a>0ZKcc;Nt z5F~l=(+iPll=WjaV(fxmO@4Xbf0VeSNbg8BIVj1 z>o}SSgZw+!aVy&906pYgeFL-#=c!AQD>VsqVk;4HroYBTUE0@XPxOVuLl#k zm?~SEhU~(H(*Pb}pxCYSNT(SU*+;CqkK?6wht-M6H$%2q?}sH?4IjxC&{T^H`a&gw zdD6S72)DW_R9n&=BpjM_9`0WWJ3g<<7ubJ%e7v+Wi675z#J^wP-+$C;HPDr7DB(@- zP|Uh@Z;7}Gne}gE{FX)gJ<4ZW`m*3_*QBaiP03i7zoJp`!ukp2%T*?G&l9)&p5w(e z!j=`zVE;~rnUy6w`s?Yp6z^_T>Y8aIM=40_RS$&^1P;p}YX&;a$`lFc?#PeV2JGrK@sI z%8Q@)9ZLuKd_|O#I7W33Zb@7H_#aNfCjxS;>?Ag7cE)k)f&EiPjU((g9lcg@Y4;gL zou@5`K=O3sL%JQe(&E3NJ>=>1n+<+7PDpn{Nrpqg&agqK6bye@iJPkHWVWgO?NM`X zcM#g%x+dXoWG?WYyez?N`iH>|y(a&7sz5`Oaw7pCxOSgo#Awo#Ny<*aUt7jmw4GK~ z6CYNN<0S-uWJ)-x!(egKb+TLz$BdTRFP$eEael3W`tbiW-Ns>Y`x{JFN!z z+}`-5@A9PLY&JCyUyMrT{qk$}srx0|ZCaZ~^fEqJ;5foa4- zT}a~G+%aMyDKBJn=xUuHsNqYEWc@kVOxp$I7_oce-dD3Mjj>|u+V@f3%agpk(Cv-R zhs&Eh3+YbjJ!pWs;TLNhB{KCHm&(dbO?;3j*9slvOzf&gqXo92x!;hRa9B*dleZ(P z{iyqS_Cl02UTwZm+!h#i>0iA&edncKXrA=By<{)CuBXW>&+n*u-uqMp_4-r@|FMD> zVQhfUbL>y$XxVd1jtxNd@)8agz1k9v5|0HfBFE|ho*N?wttIwr6p_ZZFj1R`@P2aq z&{3JWw}70)TCrkahXye6CZq1}M!@QR^@6+hNq&mXD>5+_m&D*sJXy_``ti6uO8c~D{RFgf<}Tz> z|3rLPd~$1Bx7AO(41K~`(d2D!b`^zkruRR94)W#tP0IA@vg$8 zoO?OHQ|uM&f{Ly*1TFR+(!P*~izx=gmEXGJ&uZ=y>{6)o z{B0ATMp(#?ESmvtt)Iy)-m}BxO9)E{T-nHTo}A&@vAi6>aug5wb%mgt%&f<>u*dp_ zk-q-NY9E6?aTVliDpA1HBihvmO}f+OfpR-8)3UQ7hJmTdem;gq4x zgP4;X)j5*CvzwKB&?%W2VtD8P?YrmS=9D6mZzhhe7U2BZ-R;F3EtSvsa&xfnUf^bn z1o81|BO%DV-B z-8{NPnDDq5{e2Qpf^l> zEk5&gL!I!$=+|?l`O4@Ftcf668y>wh4Sw1VcH@)SO2iw>CAuCVf_M-68|Kye&PzV! zTNG!&0(82zCyP4jyrB5qHrTx!#+jiqq%z~O@MPvQ|0-`Z*q(xcp`GFA90HsnIC zZ`bJIB3;&{B}tRMSJj6fRt@lfl!f)Kt6hF?gR}L{$tsfz$GuJ}c(?3AnB2?Im2^dj zTH^pApLD%IhIIGjXRlI)NljmQ37tIqUkfC!9FRf;8cKJU%rpe%tC0*bO}*OEV*3vv zza|Y1Au#&e?vqY%q0-OoBviw=3~+1%S@j?&q`X?II%Pka8HyjAgW;!HtX=U_Gf+*(JuOp z<{8}|i#aTI$!Ol@4t=eZ<6J7otozTt7{ECYT_FXex)y*$fsf($+C3xN!>lQr9CG0` znEgKR%Bzmi`kQyxvIYfW(m_o!h9oBW4cK|GgVC$=PfANYS0n}7>(wo?PJsWpc#Fk5 zlk(gYlJwz1bUO}C0dun#5B~-c(cEg+@per;%_j$+j$Jf1*VXA>1_Ap>Kt=*iM!Fme zY&3ZUPvf9_O;H48F5?byB}fYc;rIdCCwI6E*T%b}QAsv1aVuJnR>@2{Qp%OMtt02MPXV1D$;Pw@8R)?Pi$b*7&1;v3NN{BK7+ zF*`qOv9!N@nJRvd7Kbc5qo3w4l-abV-k|6oa79bgvkx0r)Df-`>+qNTS^eXqrWoBStLgeOqVNjb_xCS=RW-IyX=gM^9x!c6C0y@bQL4LRvB| zLNwxYbGptifB6C23RCl94s7RH&- zQCgob05ze4O&mrXYmvg&I1ZU<%+7|jPW8l{id7hT_vjF)t!I!)9yG-He+m^KM6^A$&W3#fFeyNjVuguTmYd=_sso87gbRd z3Rux&M@?)_lONE1$9aOV)W#GjD7U`Kejs7ijL9rqc)FwD}khn9KYo8bEH zR}PLoz^Fn>w&TCuFwGGcS#{7(3kJ%9Ket~3&ys2130+NLrm(mZ8AUWqj-08~zIU{P zd?XP4D@&K@Q>m>0Li>S+oqFxY3+@`o9HI|C%b$289TegjG&j;O6tVnVz^J;PymK*V zGDnqfBwz{wn&k5NDcAQ_uHf@9@k-%a&G-=c$mRopy*=<}RFCslC3dZn3fLe};+d2m zW+jmH-Jb99^zHN_b351@-Tc{8@^sFh{tD9mLh$;lTFvTIp8N#$%sw6QSuyL$ zrgIq(rw5d8c$OI&71X$&{a`!fKu@)OS{|chynYH2^kitXHCp)5jD1L|TuvQDT=5^5 zU>B5j_8`qMO0ty*&s-tU7l+FX2d^`iwEm zBR@&5D<4A9wiB{T4nYf%$ohS?nzmBE!xr+;RFGlY?cJo$Rw~>bW~KP#aDFbRcLBa5 zH*RyRnHU-HfOnWi)NONTfgh=Jbqn-R#EO?l;x709br@r>z$YQv{637(yfAR@|0rIN z!#_C&z`Lbh_4Qt+zf!1RPOOt=?UM9yQq{*~JI>D;<+~T=rl9hpZEc}~ig}c9D-ozseT%2b)nx0cOw%a~^X~Dvtxq?6KG7o#nj^+=> zBEWt*!k!Is-8Av&%-Db+vSj0x-ptwIZ@hmcMr!Lp!eScY$hMfFefei}>=QM~fIJ4t z_#KAZT`C&AO-qQ#LRR$Uca^e0{LMU;-F(7>=!upvk_FY|i;Bv>h~aw0Z8_y{05AI> zl;^(R zufCBN^&QF5$)qS;hDQy9ZqSaBQahm-0DUw+TJTum6E z@1FzaT`PTbFm_nVp%1k&&<|(O;`uyt0TT4xWTtpHtR{RY@<4%*`G?!~(FVr6-#b@tus@w2}XYkd4KC*9Yt&FbU`@?2t^#PUfFAs@fs{)^4;=houF#rTXi{y`Tt1{fZ%koM!1kIV>Y!P zL3t;=Z<2N1s zI;VZU$#s2Vem7V!NsEJ?_imN(?U$-G@9jZe~-+NeGtR_BENPB@Lp?U86s+WlD- z6Le8&?Pr<~1U6f{r1!}CpN6QdjcqLgPV_~;ExX?px9p!IdT~ZAildEzkzh->6C}a9JxfaR zq2TcIjO1&FBOdGxBZy5jL^1(^!$x+9ika*!VlF0RB=~kzq)ZEW*L?Ym`%$L#J^lmHT z8{N<>lzQqH_0})s(eNbOZLp?tDz_n*V;GWFMKLBFd!15h)Uh%;AAUzmJz&`H1oNiYo%=apHR^hLoOX@->BXSXN&e$ zh~vRMEuijMG%<-SLMZ!WQJKaTA&XZqtb%0mJk`oDt{bx~dNnD1s;>xO4jX7#Xf;jL z>42bqp2f2CThf>{cKkPCb-`+DGYf@L!@1)ABoexX7D(?^EP{^!`|Fk*i83%th?4xt zUo|OWxefCLA7%yf<}PZNPIl|Z9u9#(B2n;$nYpc=Dhu+y^X|p*H1XY&9mT1>^?Kpb zRSmM;x<;A?;}VXg9+!&hlGI23<;y-IREB9`z6z}FXTBUVONfh(qpQxNEAyDiN2h+! zVq-PVroa;Ga3|y8?2(JSLaUQ{c$3d#dkzbS@VhY6XL-fk3=0hZ!LuZ|e|8gQCkpUX z4UQt~mlbJNg9p?DdKL{@6!jmGMCj)vr%%%aE{55MLMm)4inE%0``R=J`WQnsnh3h^ ze_7sMis9?ro$)3~lZE%w-D2J?Dikt5)n!cLcd&iWV=-O(dTltY$acLSeRMXSMvNACQt=noTpvE3d-SZ z+4{0dV6Lyu0!~*%yyN)ogdT>rahg5Ql>tr%*V5_~Rwp~kk6TXuv8~+BL-e>;!Ia-y z?PZv288d8It7At5gYe*0=CL>hDtEDe?%{b7ObKtD6U=edMx4AuEO!7&jryg!stm#4 z$Et>@6W@G=To1tSUy%M*O#YX0Ve=!U-UIT)md(<|gS7#H!fE-TLK8DES`4O` zst61Bp2P<+C|ZT30N2>%POO^DIJvNUpDjfB#g!!O5$%5Xiatmrf58)^`l@Pqg?6kkVlX$D#0*MruYcdBeIcK{4>caV;ON!OOX@TOx=S5 z4oZUskpi>%za>w{PYRGh&5ln;NT^&_I%&ZMuDIFW|16&;;;X7hQmJA^AHVmJ<6 z&mm9B&9mp;Z*}$DXyV)FH|rfG+8jTnz|S63|6HMOJGH_0rI&rZ_BD>TQUw&0yW)@7 zQj-?FTYNjmrmrWa#;a^^&u6M*9Et#y{$Llm>?=7nuej9VAU8TV2vw^~-`lOh&vn1e z(!M_^baqMh5pVaUIEj7SQr9~rIN0TD0eDAMkXsSF`+wONul#XXzKtF86J6d__*YoW zyog9#xgAc}&uB077;Ed;*w2a#Q+h`$Je0m8+Dk1r7AdquLvIL>xI~k0cukgMC$&c@ z6N+3~zA!l;?makmdeZnXDxVC6N4r`q7_qWl`=4z|&tPLtKzC83F9HCXmhQDV?k{DJ zm?ZKLB9F49hr{1OifreD2Q&M#=ao2>#m|^Ie(;gK)?ha#*`B5yE(wF?`1&5csga?2 zWGA{D{Qp{j4Ebh8?d-g28RO=zXS9L*89uVmJnVd3wFw4rwausY(FNQ&e_V#ry3P#) z1GiFwv@)X$Q5F&SIY-l!*Uee=}wRVRdDt=o7aZ!*n``_Di=A84VW z#$KGiCwl?IxjJZmfJ-|7??bJQB$K| z-_oLddqpOUUTmOb+vw_+idG|m|Hr&xYRDaClsSU>SEv-SLcUp9%De@HvNB~ObCFE8 z*qnzYh|<{LZR8y|F5=6Gyr(K&PpBN>V8v7y1xWNkk#($Rks z7(ipoDzx|vh-06OYnp!6xlyipK6ZR!%&s&A{j{mQc1ownlTE%ui|?Z3$#AfRIHY8Y`Myt zKi`(2jgd~)QlnDp7FVmp$cJnF(G|}t;rN!l9_@-XD7vI+v|3?%SCjWXLXe4zbsgEF zrw6lQbCWn3_t>o4iC-S7DXWFPw4lAk0zZ1uX018VEJhA>*#ndk0OiX}AcumV?!p61 zAcTPxPD@P~|M0yDL|>>Dvj}Fw<*kvJe~c7|nn0$n+>h&(ZF_e=l@36eI*H$rt9+Cv zegR@~n2&Z(EYw7KZafTTe7kjox8c~ zR++>_roGlVbvP)Ko+{rJkLUe>$JuYt*pj8&y_+k$^+w2^`HT6Sv)XX*H9a&2|6Iut zGWMj+KWNixB{{Rh{K{k|=^vp!e{tYXtgv?dvU3B=YVUIa_RZgMJAzgBCbf4Pnrdc% z%mY&0(^SY4fWk`?i>CW^y_apIsQseM`8TiO3We`ZdDDyMKL9P1(1H~~0D||24JxC^ z5LxPf9K6|l+dmu(3=f+y5EAmUeCc3Rzw*@@V|PwxDSo2lD%Rz;sZd;-LEM6UUYn?&4L{jB__5AQ|=*aA-L-UFh#GU}n=} zl$K$yXV#L%@L2fxNGp76Xy6Qx64>|t4hXDPrp%_kub=RFwVdk$B3v$Sg^6mJE8Zk{ zjTBloL$M%BFnF1SI9B*p!iF?3y7P3wM9tI;=dK|u=7FxJlwq1*RS9pAy)~viXdwhrFaHwQ zsU(oAc~>M#+Qb{b2!jaaA2Q)=fReB9EpVH_r$icu?J-`Ww2l8xYl8{qJ&~UGaz`{5 ze9Dl`wRY-|258$35kQUNy>z+17i-`B3au{_{jJ=unZS?COf{mY_$o$VEurA`&!n#= z3Ac~Zlc5(sCmuj~Sd0k{tfj+}&t39I`H80ZQw4$?VF;i}YOhf5x3*>-J_7xn@?br8 zgOIr2PXDE67s*&ZcVReX)>}xJ{(XWdFxlPKrl3dE#->W|?&58I%HLinNNC=o^KDY*_Q%|9A*N!JzpA2rDy@Cq=2VWOfG zu$@KE@RpQzce7Q?%@90)GApUzKre=-x5V>0--wF=ClOaik<}p+qZX^LJ#8*SmG&CM zGI_@GQyepnOQmxrab^uMh(Mvl)sz7UhtbzHHNp->-FvoO~5tpV%|A>~0Mm2>maGM8oJK`6r3j9q2-boOsm@>V0{XK7U&neN! zC8}wL;W^EL(+PxFsLnfI_-#=|*Qbf!#XZhF9PyGI(cQ^_Ud6Tm8j9Esa=0RK)hh3O z{UsM%_8w>A4(mA}5}z5(;`e`x6GS^LCwTO#+rESh8QBSx|TD~W@Xp(Z^YWR-Elfx| zS%{WcTDmT|L^R8O;&CX)g zTk_1)JY1prk5CZjP*+c!tzAJh&IA~j!RxG;z2*1|EPU5x7(h8h?iHhlxT3g94hP{T zW_k=gLM#U9Gl}&J*=uWSAWR9}BT%m}U#*Chx0!>YR+G=1jNxJheW2Y@rAC@n*b|8B z?y11XsE(@U%hofaGOzL#ZK|*!)-KI=M|S`FI`LTd`#CUU4dwNcoo!aW#WeBei~)c| zfjVL6W|{6?S3d&C2yX8JlfOMUI7B#?@J4quqwP3&Y=iitYXAh&cyPnP79nYP68?9i z-rPKHz!$M3=HX+olUQ}2+amX19{877G5UEH>n%FjRcs*B>OC^x zb5%OKTP~1@la;?U=sWYYFjrvTUL6KP^VD0zO zr;s8b|0x*d2XZ zym(OVh__Nab~hq4JGGzx9cB*PEBT2oAJ-3THE;#zkkyD$PN5UMl#Zasim2(#V;OIJ zte#yaC7`SrI>EiPsI%1%aQ60ID0e;>z~JAS6Dl^c5`|dNwqD;!8m1{{$<0s*nZU;; z4qU@S)2r$5U>g6U!X{oOyfz`E757diD5qHMjU@L(b$I({D4O+o`WK;LYh>%iN}=js zo84H^QAsY;>&uZ~=jMp(omXC$0oCr7i=IcSUkqvJzDTIH!fwL>_k$V=3J(nmqM^WK zS9Oz(ws^EIuN0GDCc#LhQ7__>APC3Zv>togriRYre-4hHdGGH6$5hfWN=t~4>@uDs zDRnmt8a2*VKKOF)v{!0+*ME*CmfEgec*>X-RyeBD9OskYndu6wEiRim8#N>-xw@%< z6myk}d%D8m;Op`R)?Wmq#v60ur-rdp__X?tn7KeZV43V=IsLbJRr@CWGWqDqz1U*v zuJC-}dB;fX?H0>gsTBb@-NBgK0=}*wRS*vO*5utF$l*3)ggb0UBiQPl(wNq{Xqc9; zo)X>=+ga@84nF|S;gxZ!GG+@uLXqM!lOFOK+=3N2uNShJYq?d|VS$#ZDUKha+m7u8 z48>Ko@r^MXN*kefiV_Ci09c>!-d1=2Mu@&prM*%+x;+@qmO1LyF@?^`@cejMX`!Zt zy8I*!r`Ur#Rr+zvOcc-~eRm~gUIJ7iIluX#qM`{tB$oqMO=Dy(&8_e07aD)Y6@Ns) zTKcx#2YX;5*4Bt#g3+{qa!7B}HCZ7vW%se6^dH9F0=)vP`b2Cads0oMCOxs+Y@)+F znO*BAxKMVk^gDA_4n>Y-)0?b@(go-T&@|~mPDjz7UM2L+a~ztpp*#z-43)HOiMvvZ zc?Tw7VOw&W4q1%e<5DFG>q3IONwb$5N{zmX?Eb=h*($W$uqr;w+wE}bSa*OOcl6@I z@ZPaZPw#d!lAg!lYY2988jHpG4XTKvu3b1vgjgr62Skkn3&oml>RR_S0aK4GWC^E0 zh3n|FKfJvAsLakvF|W9%YGHVRHIu!;ogUseDO!8U;5;sA0z2&=&mhd!3NbaYx}A1 zz&qV{xZH~|JbZ**UxV8L(u>Quef?y%C!kJCa4z+u%904;-Dnif6F_B5E(F4!Ct))F zPF%@!4$!G(0(lQ-UopafPWb*oZRU?;lCMe#ZiiwhKWL)*;)&G+E1;6#*@d`GAjbKL zef}CLf>v;%ac>fXHZpA#>A#1e)-+hiQRDD7^Zn@C=(spz%#mojuo0iFgud8rNg`_l za->`P$;?eKvyOB!^;uG z4NPHqb{f*S!WRy9b6tf65__EtX%!rswW4x}{hfOZa~NjxVI7;k_G%fruDPX(QaE%b zStm6&rp@vV{qR=xv|?5&9gVKecc3L-XK2FGJl`A7dj!~sx419Ro%O?;&0k=H=;brc zqjaPpGtjf(TBMu1pzSDSW8yvm)grHId#hYyDtB*ueuo)`I!0(w{42twnyppZ{8~ z@VVUa`5p_WJjdmCkEJwG&by0_iymLNTP_sx50-!dNcsmEbPjqq2*ESEl&_CM{y|yFyGLx;d52uFu4DcpO6} zhVe?Sr)QVXVCe>odbO$(>E|RWk6MmuAki{M$5G4-nIYfi5IlW>6@9aFszxtO!YI_R z1vLKE;WWNlRw%6+HN(_-*x;tmwNYlMk3X+kGDEpk5YDWpzKqx$RiNP_z*8kvOF_t^ zE_>kI_sMLORz;BeVrkpyu(n%k{q!eE4S(hh~2B?1h)Y(_solS57Y7`XE)I0v!Q^mcm@OP9}9HSRXL;!SgDQ^+{ZwhZyj zJQ@y|xnJd12Fzx9h?p$)+_{`F+OL$dE?h`q52Sv~%!uxwB1_o-3oVtv&06*TsPD&4 z6vCfzaa?|1O6EHL+-ME)SHGk}&W zqK+kGNq{Ea`lRV^HeB1zNR?ZVe8u?@Z)QeaCq%X;Yal((B1ii`;yP{eiCZXOoT8D% zP8m$GS8XZv z9`?r~B?r3@(O^?T1-%dD7!9G-Xngn?6{yT@Gn1YvsXBahha|dVg&vSYY_xf(fQI}& zVua=GP1_u2R;8iSNAK^V`y6`4&Tw+9A||e(jiE5$taJ$5kyq%gh?=Z6hRL0{306+s zuzE}Ns;yB^OYIkuj7og;@-*YDDs?X9DB)loDOxc-wvFuR)lBl6;KDA_r-EYpb4mt+u7yvDfBg69 z=CQ9)g4&(+}-D@UW$jG8mTjZwUCqu$O#bS7b*)f($ZS%duGvm7!{WI`x<40LBo1;u;jt8xy#3h zCSPYJ@~Xy6A^DuNMCs;?_u1wsEtFaNtVxY_*7GRsiYO2c#P!|zhjwamJ$2hgGn;X~ zxi=?(e&3A81n1w#MLu9v8f}66&3nvPz~ZN(5eU$#QJ29`xI@!r-)VY%8Rz;^P&(Ux zNsZ@m!c)sCb=SFWXqena(}Lo0=HN8y5}+T%8RI{5CM%GZ4=C%P<;{{uw0x=5Pk2Q9 zCy0IX^4S~A7hGkZD5Fk-O2qMu;E(Q?T8s%_*WzPE)Z-Xpu$g;abvf|rm&t7pz;=f- z_?DZk^A6_emak&fj$l~y%8Ot2i;R4SYvg6d{M&yakgBG6OG;ChSKZqTzZ^a)j~i2) zt&#{v8jZ1~p6soObgcs_;EJK9wKS$shj5+scH+i_rHYS4z{VADd% z&$wuinA|9+f2ho}fN7pM+sQdJg+1g>*%}GSg?ogSh4@t>@R%4U(`*_pZi+{pns^?^ z>o>=p_IG4ffzAZA!Q^nMpiRSdWvNaO{VaiLQb@kYMyF+#Hn8<#<6>jV5YBF)+urk% z6EOg=As$D-JwI>^^<7Gz^V3;kvnI;QjMiS78O=^Nv>n`~?|JB0E2^nE957T4-`eCi z8))pPlK+%FqzG|+^=Yg$lz8z%!Xd+xB8(zV^Q71Bu z_IRJ(bQM7EQPI?99%b4~XjVBl3pkqwe9Lr%#2cnlrPo^g9ZnwrAMTmeVZTyH;ZXLs zQs2|qmOb&)C+Ufh0h>A@>d~76^ydfYBELG*_#&pnKB^DqQ)CD-YmfkJT$H!N0t%Z= zQpjd$Zj}t!`RK_!`I0)>`WNHbN9IppRf-sFD^VZzlvrWQNT@X=G(2zQedSS5NY{Db zc>h({c0f~-)b$yVvLud8b5$|T@9(UPBlahn-#XNW$c6apDm=gNOXbp$QuN#pAu$m( zTC~`OY&Nx+5eD|&Xac2$?&HRtGf?RL@~*UTFH%(arl%c~g7*)Gg*XYncRt?#L%-b8 z<->leBleQ4qT_%73^|G?oq<1uKzzC*f5kt zAIOQu>oCcw@tS5-bZc!rCOrd%xNvLYaZb7cCnfpJA>3sa;U>KXySb*9D5$_`2m86Tc5J(7g_1$|JFs0jS zePux20c8C3Fb;otjjJ7cX|Z(pu3a*_4Gp{(S2iSM-bC90#G;qR*6jn|Cs2JPLddD9 zDRUtIoephd>~Moqo|2x)j|Fp+%*?r>N@M=|bG^OXX+d=uCtvcRbl1HMp8Am#aySUsW+sVyhaa7F5cr(6JbhO1?Z^#V zi2lx#!X(?myeeU0kN-#0SNKKQeov#QSajDSAl==pAWC;jw{&+2NH<8A(v5V3O6N+) z!qVL=y)66QKHuN_7wmqn`-(YpX6D42-*)GJsw&OTj-K3axjUB%K1(V`Gdv)pH+wtl z6RZZKw9oMr?dmKq-(2g`Zrgm)^g*Jv+n#FLII~#eQbt3Ia4x;|9i1N7|NF}21BB|^ z1~)P+Nwyk)AR1b~m30nKp(8^>bfD4cBoYwlBQMzpKw-f6mZ<%_NKk3{FwtxIE(77= zZnBpwQhPC!)8c7W!q(bAa)is{&M#BBxTbMOlrqUi{&svLrm|G7uW`w44LP<<8wbaa z^;Uz!llIXJW`4eIy47yjb8wyY>fO_t8_r_aqxovUz#PYm>5cYIO|JQ{_$e?IQmqM;<;QM9}<{CdcB_E4~RuRf0+pSNdB= zY)~;661#Sj{?IQ)2XANQ!tL(*A(e=SwS>i~1CPEu(HPp$H!LqV4amrQ9n;P827Fzo z)|Opb->v#vDvZ=Vdj+OKYjC1iczRIaVtTS@1DFsZ!a{oX9(EL-5QN;Uw^*g`nZ}cB zd)+IuwC+cyMr;PM`@1j%G}NOT^t{Nbk-bF=osJ){i7zb-y2QoySr0Rh?+sBC9hdH3 zAg5!1j$RE$8fpAlkg3@?+ab4=E8JO_V1ZJ}=>rvbJ_i%S zlWdvbSDKLkdGomY?ytgJ-j8q8S)oyW>m4-XLZ(YhM*ZsQJ1R>1Q9Igu8Bf0b`$X8- zW?o+NsbADa5197fg~2m<7Utv_?e{7E9A#abJwRZ8>^V*bnhMa(M<={@gH2p6pY~qo zFXOJLW84X1iMARMIMj-^jlVG4$FVAQ0qsR+hX!HBq=c8mrMG{Y9K(D0Dexlv6 zEKMos+I-;f(0Yjne$~T?uMF6v@4V~c?@u2j_7?jrn7;CQi~E-2Z;~a;>2LFG_s$nU z;}>X~#T-k-ULr(=#GoA4SLU-%fEjNY?h?RxfTmwXE@BH%w@bqQzwhQbI6DhKDGc9C z_ograAyHXU;`+8p7fvMU=e=aYDebW&+7^iCP@Z+r$}hVdf!g%4aJ3bOz4(9l|HpP> z^XXhoLlQGMbR3WmH?vkIRiiq@f?{_DBS~zpQ&*$Td#3}9%v5yrRmI)2Bs6q~#wcCD zpLQ8Eh{8ohIWwH852u`1R9m;!I$dO^G^sZX~QyJqw0auHL&saT|bJI z-`9;&)h0){(jSmPH%Mbs&9rO~yl7=KLjN@!RfZU6at;Dh#LCT8FP9}UqZHq7APyaZ zF(3_X4Cw51Sig?r%04Vxjn|x?qmcu`nfGe?96&9zQmw=q*hV^%w-8Ibh-m#mQmiv@ z%hT>Weuq!B^UX+}tC36i_U%HJ*m>sp_O<&YwtbvSolwsvt%gPQKbNSEwUKW?!$N$; zpE~1Fp5>1IY#ZP$11=T5JatiDL9K)%DNUyTdl*P?$Cr#rKCVBb;qqTGe%#$|9Ojn8 z{IpY~d=aqUx!L&DDV?fI?08diY>S@dx*@NnOz%EWzgLs>WV!B_qaBUpPBI<)oVC=w z1Py6@l%g@})b+AoSE!hOvsexBE=$7DNRKZ}>fH}sq!;tEt^98oXcnNSuaIRii^+m3 zEh$%x$3hdg>Z%0X&YM-@t;p2yU7-~%5Wg20ZSa&^+g zX(M?Dp@vVx64@I;@dLQ=14UOR-HgrROw4nwWlYM`*?XxST5BmiW$xk$QRSwGzxE({ z*Ll0H?R27|o(@HB_9kEC(B||BHFLWBs?9RU-XB1p8Jrjqyutc~WuvAa>C^A09xz77 z)v2%Tjp(Z*wfk5v=ky|q};|4x)Vjry! zK9gv-O{!ZC9_Au{f`44%p)e#GxZZiSFt|A0QYqYfXR%_rDi(?I11`%wcK2SsZMSps zl0{JG3VzDfYPRbUQ<0An+$VamkdKI2rA0JA+wT$ulNA&{pNir0VbXZegr~&cp!EAe_j4!v- zZe>yy2lNUWLeR4ca&5AzZQT_)0~1Y4KH~^48l7* z==y*q8N1hJN!e)l$wF0u=tt5Qp#*^I!i2M^D%(wpDv|8imT$iE^VR=dY&bKEy^J^I zjh>pJ;QOuKrY+&i0O#$mWk(Qb2GwEd5IJ`3c9)mz{l+{0XaW*Z7*xSx?Ry~^|L5v6 z#g3ts+NybFt3cBbvsZzPSoo zwVCfF>L8*cp32W*NyCK>tQ^T@7mFnV7uZ#?9}V!4-ipI9;h5{@7iHu-fP(-x_9IV? zmnb`>#^ZO3=)=`UqU~QRZCW@JhUeXeJpdFxZ`2<$)BB@-jIz#OcUL*l!yx;52`erx zZS^V7BRJN#>}sx1E9FwTLSBil3qlxhH zPSWn=I_Y9-Q$y=x!lZy%B64RV4l1+f--cYrHK&*8w9fE89A_g_5uE>Hp4R@$NJvo0 zih$r0jey&wb3fi;K5Z|!CxN)IjlTM#0}Yi9 zp<#A9o&bG;8p*b+(*U7Ihrk_K2d<9yYQfETVFe_HZMqBmGqu_cAL908KW}A3g zllwOO@CRrq4Yj}WNW1u#l+1DORI6D8JI!s9LrX)7F`ij~BjwN>$tL@e-uokd=K6a@ zv~F1eUM2Aq(&Rpu!TUVbHXT^w71Q2dVuSRtWOLNYcPizEI7cricD@;un8pAXAEr8m zVUbkG6()U=tvtg}HP5Jy^&S=SJB(uG!ZuCsMPkT5b(0YDKoUE1@=h<{6ghGhFXWuL z+O3o`8V71u2X~Jmiubpg;gMbDL9y_zi4Q*vQy^cd3!Q-n;Ge!{)Geq!f+URk2S3g= zHvL(03JI^g7YNJ!#W9{#umH$sKTIW9 z`Wk4+mCh=C!RzVQ@`mXekpH2VG&#$5nJ3`*sIEh>lNPCA=98gfmajpS^{hUHd+8g| zD^<3X3^E6i&X509ZoXE-{%)EXharH6e1eS6{$=B=yao;)f~6;B1~ij)dm4&8n{c%& zAm7otP@s~;DXrV+mdlYLc?Je^_k?`rWdE%nnfOif8rL4s9s(cfxsUXMz%?F2x7meMSGUCsxp9pVUo!W?X_?sLifYut zjq=0=cYRRIG`HJ;Cto8JqIm0GK1XKl-Z!p#!UAX1!4Ip7lKe5AoIF=uP@!e0N&a); z$J(07zl8%hQ@P}&+1Kh`8~4KtK`{{PSm#>FV3PR!ey{5Aa4oIU%@f=W7t>0m%5`o- zF5%(oZXmGR(pNqjo0Ta8w!{&uVNVrIyCN5s&SNj#|iS z>*RPL>ijn2*0Ab?KhJD&`q8&~<|AJ>q*Pre<21Eagv+8D%EO$GV-EN|#5K-i z-wS8xU%EBh$jcBLX*|a70lIHKr%rMHQTx95#_=SUl1PXPCCof#>02ZJAiQ?dt@`S- zd)(D-uE!!sY^EpyqX^)O7|^$bG|oTGmr&y+BR9hE=J8sXj0_cIn(vWk*(YUhPyZpS z_6DshgnUGZe{fql{L9`MeTzykhL|%tcDDL^SfHkkA>@+$+J)pn{r zvjW;LU@+_ULK$EAyg={d)zpl@KUJ+dU0oPnA0O9pW;lEe4ZVl60g^EyXhgtUlwQI& zUiF?a)j)=$xy~#nvtY`@;GrE;V*XysR$NPSripl!pp+Ei?PIMN`LB2VSOhF8?~sP( zZfrC%?r~@Dq?!3}C3fp8{7ohFG+6eIaQ$+q&ffvyOyi1-x)^mB zD%+q$&y&;8?8AgxOyqz)`pyDv%~d(&`25vtqK-fF>n^Zu4~6G3jDxBe)jtx1Uy#N!E?Q+fLugXpdK99ha-U-hxR15K|+VKE~iRl$$L|A`INZ*1QykjiFM;ufyxo#%S5Ij^*;3dUA=&ZZM{hBX;NQ`xq?5GlCzR=37VyZGhEu-km4Kj#Qmp;tFvm(pQ+cwhFf@Zrwjt zLk&S2_-l}z{8Yp03c(sV$nAA?SqgUh38l4YxgC@&iC)@RBt$J<~0sVAJGR z#Vz^!?N23Flf#+9*G`w!hlh|z)xZIBKbU^<1Jcxx1;7ulV{KP(mu=xr^}R2WR><{geQt3+GO zeh9SYMrzOtWD17?TE%SczHLY}*Q1GWVol9H!5%LOru*(07H9!L>*Voa+7t>?X&yPS zZe;ir=N%sn0OkTkSa*YlQs&Cv4GG)P(R=^lnk*ZOL8!n9WRDZlYJypR`OV(Iq3lq^ zOdh}JkDkn?kIa75LO>Q~)W?Ft;JW$k!*DJIlUVqO)or1(!)><4=#+Iysg&+;YKk`j z>nZ7E+nBDbW_HCu`%Agmu;CdM*l{v)Y>S%aqd;jJbCHO>FblIX+w=nzp!bAOe%(K0 z{N2mV3|cApGY-^?FBik{Hs_sWh$32@l@ltNFBH;j;L$k`wSrXVB#;@9`(|NkKtPHE zG^F4#QE(tvjhUgg+v_vV9P;e>cukVPER}e9lIGkwTiD-8Vp{0IJ~5R0q*-b+9r-x$ zCH2_bIT44Hg8#9z>3>4&=}EWy(bwl=P?>7B1leIIYoxm*f$OxIXFt}C#2Qkq_O zG1H?WUF!0QGvGpoBh34%`@aYEf2X#m*UJh8gyD^T3_UT#tqy;`9WbY+6c3uGnX)Vc z@Shn8TB?)LDnpuS({N}^EfWwKeNGb~8fR+8SnrEv+bK@-f_ORlv;x^B$KUXS%FK!6 zEmX6i(u?<|=@TsuxgE0bL2=!&LkJApm{4``D&zR#W2GRKuz)pdi!%3yeZ1iwnE_u8 zf>QnU!;WO&uvT^3JQfOQAyqRRPV^uwd@mxekvgAf5Ks;&0&De!1+CQX-c5jnk^u2m z{oUf+k8=5Ncbpx$H@?{z8AT3M9UkFo3f*RTY4^AG16Y}Dk*_EqI$b}yk~$uY#@znQ zl;enDfsUqmAeLhBQ#JT=WXY`$|MVI4izkYWnf4vg2Vw?uz^IV7UpRAyE)%9ni)`p$ z%o&r{uq>J{9~}cks#x!tA_PB&W4N9L`38gMkzo!RJULG0dLPfe6Q=Up-47W6jgybOwInJ zfN*HWb1np4w0oyW{n~?dmxYpLK$SOo0t)F+vydUuG7!Y;rdWwG=Xc;mKQ0yG5aNb_af&2(`GH zS;UB-@f5`rQQQC}$5gfd!&wNAibUx&tQ{=A1^LLtI{wOg0zWOp+3MT2vPzB`?-Jmk zV@-So2R?Gx4ScN!$bE=yFD&k*VZ+jlBRObtx=`MJqjPW43 zEDV)KA2iP9#RsoS|9(%J>@mc|{gVdnd>iQJ&Flf6Of)$++{gJawR&?s^;5Zr7?Me6 z5C~8U-J*_RZpicHN5E4PUyydkmqqhgd@Q5c5tcXA$?%l7vU0WcjrMWChLciwA=+v| zeaDjVYxT{Ids?20v&IAQF}jawVE6?Y&ByET0#)L6_Q2Gm_n>3*r;k&zAJ$ETnmY7} zCZyGK{UNQ@blO@9CxR~igMd8yoFwonLA3v5z61#AF+1b9a%K%+KAdP>tBn`3$!Q9F z6WJZmNzCwc>*Op^343wl)*mONu1dcAKI6JZUn3TLIoPxZU^Eem|CI~8!3Ar8l{O-u z@#ap*{XE}$@RybH$j3j`J|k}l-KdTx?QQh()w12|pu)1^uqZ9yK+qQl9&XzG+BuT9 zaXJYQTK!AH`?KL~icqV4&ghkwC@CS!86PP#)9A&9yq?|w4$f5J*_MWs^VLKoBNdow ze1vP}Yxx%?`f7*Bx6UXGKiY9ye9W9tns$SdG-gK4BRamEms}cUtC4rd`!AlxQ+B$T z-YK4V<4kS}1p-cGxiCS9NXouWY$R!{1&>_q*XK*9y9mFV%@K?}#mvj)OxwMw2?Bc( zAf85J?|L;gH07%px6=ygolG3R0FCT5PoQIB z{=zp(Px)$bQT>8WD#eYfOJf(l6B+ZH!`^;m57rt$$fJ2ZETf@UcTUqoFe?aV`fgJE zv1V<#zvZ(lQ+vP>6QNg?yb>A^SGKrqV?{_{d2`FM}Tk zj~rYw8$RWL9fZkU>}#6iOFeSNd~(+I^U3pQ-7km9U(J&itlBEt%VA)j@@@s(63eI~AV2BMSKdU#h!5=zLKLu9&#&Iz+qZ>3noimbr!PTgAn+u~jcU zAn=5f_WMG=E`=UP)>{$3^AdDYa<`d8_oPPb(?+pJ(6)hFzdpXtjd?Y5FvL>Z8OiQZ zP5a#VWdORgG`B1F+(X*DP!!_$D~{xI>SV8@9_lw=H%&FILK>oun~f-ci7~`8taTLi zRjJL!-<%yLKvD~LXFiSVi>BG~Jj`Mu3dz5o-hrq>pLd#?^0U3awE2>$%Omp{TddDsTj&3czw%H%4m&b^Lj81c;zz*v!kgT42IpCu-ZC!m5=aq>&lWsPXKHI5R##zQm zR3}OHlfba4P{QN4#tZagZ4%&TlVQ9OCknWrx53 z2LqK)T>iTHp0{}8idQxc)gxG!NXK|)T`<|?4JMj$VAp(a>h@160d@~<#TD`F{+&4I z8ZdhRAM548u{cTZ6#7QEagK||&`nYdqWMY=pWA#iim~MKm5a;Ki*KCH-bC13Fq%(K~(gYa)kZ@S&kM`(zI zIiY3^%PIqnCAL-i@Jj^Njt!1`jCS~o?YQk1bS6L2kiTv!pR>iN^vHJD9G*1NT1#9*zSqi93Gv87@}d{srK6|+4)cs)0H&JI&%XK!1|;&`vPZ>s18>58}e^Z4$CDl;wKK{M{= zqgQ4s6|vqfTX~+FNaVrxGbVlSy1NOsNvX6HO83c=xqJ#d$+`n&4k2(!fng?VfPQCp zVK+nl0sQR;_PEG7!*%GSN3%g-Eo6D&6dxL**?3UcG00qeT}E~ct`gg!pqwT+a9We9 z>$2)~72B)3WK-aN%I#d}IpzvRw0pK+v!bkBpIFVwmlt0@6-=O;509R6U>gJt;SIti zJiNRRe_PnQy-l8ACK>tfJOcB_O~dAgu3%sxM$Xv**;n zC&uC-Ndc~yzWs&RNoHpeY2N#}IE8nchdb{2{L49|EdlfKd6a`1y9t`%$&INjgf;uG zsYIFacW(#uN;d9xu;oxkbY{_JXKwATJuEWabZEjlZ%+30XcUc(->{V8Y+ZV&$zQC7{}08l_d@O(o4fzk4fOMr$r}nOjMw z&c`gp7!_P(fBf}9`|Sc1!;Jj)i4I?}ohH#p(azACgzG$q;{BFB~7S(s5!?dPPsO3k^e%**h#&LU>Zd5(`BkLlony6`W(*$>LrZ$zN+22l& z^6Pl*;?db!IW1(HDP_W24B1@KH%7#4(IXoIhBKOdQPZJXN`NzZ1?(SpfPDBCXKO^- z7nXA6HO1ih)mgSeFYc<4;NGnpyRBND1tW6?-GcD_$cLsvInok-L~WgFa~o~MfjdtZ z!Ru#LRL)19EzZD}^Lm>QcKV|rv&i6;7VqckonuWdq*IlovJBhVUWupg@NK9oc_HfK z^bgZ;kS?LCRrnKKt7z{_Y6`hFdmwLGi(+J?J7q6fu3uYQwr#$PHz75^6A+q0WMA5XKYw&$=K!YKv#A1a*de39jDt z64j?4sk0eUpK&ni8l;3T3FWVOS~a!9()vWNOJ6=XsiYmZ`?$-zSvZ=AtWqr#vw6;_ zV^{*cT19Kwu6FI7-+`M*nDt&FdaIxB-1|SD8~1=FNnqa0r^djvH3|O<1DtHSa;~0W z9s>?^(T2yv;VAVaIGYdi`Y@H?o3)&tChCKc!6Dh!j9B`=_wuWPVS2jK^Pwy~rOeRV zBpaIRL#6fE4W3t*(CZt{5hUS~JLi|>A%$N<`kc|xR$MA-`!tIciz`v2&K<~j=p(ee z#lPW{w8xlL@}Jao$maAPIdD-gx0-x@He4*3&yk@s`li}01d-!P?hGBlIE_9+RzrwB zy4ljsN-eQEgYwhm(tnp_5w*7qA5u&>xoS@%9hn868KwYJnd9XF$#_gmv%gyt=cq@* z_oPQc)_lbQ*I~{nGiO;-OK@%2qaiDK6}X(uW0jxa zZX2x-tKel6bQ5%a-Bdh*>xO!0_j!B+6YmC`>xnWtkz}UlrmfginX-Fz-ZTYVrK@oG zeQHNE#vppo7eYPmXsYxfk{KC~Nwsq=Vi?s#YFbD&uet zkArqq5A18g`sV#OkMNmKH{#9AK2hJN?j5-&7YHO?yZB)o`Dl#1|4Lkf$sWFQ&Q8j6 zqsS*l40Y?cB4JZr+ia8$s1Bv$z|4(pQM-PrnMKLj%k2_q*y&BV64aNtN&bEg7u@s~ znH#ycjr}ExLh@8thkhe}Pu%v%th!!df!m+D1SP6zHW-y}tm~`aw&QcHbS?ge5Lz&a z&S>lVNO4MkXm4AP2g~S-*vs3qs$?tR@)^Q(S}3r?D3T(lPIg4&Hwb|9Q#x9wFqEv+ zLBroio>|$_mx#QoiD>IoJEPSt+3|L#&hB;)KwG^dUc&gZkNoBPNv(-5j)&S{smF~- z@Xi0wA+e zv5KAo#8TEUC3R1Es*+6OP}6UJQ@z*Cd5e)Eklk+&dQIII)tOzE(sku?)D=JHf#q*l z8LU{HL)bd9S`5+D^}3PGIhvoE~_V?%wXm3PE&lH&Y(~KF8$1>_x;31 z!sdt**Gv;lN}|?{cb_Gz5yRk<1P}TIE|L8nhHWP$;Y9cHfEM2;ki4T@{2l%hI$H(s zRp~|K`PMA)l{d6tiu-CeO=QXTPcpe2x!E3>{rrO{7!2W9=2#Tn@6oKeJstkr3o`6> z?-947bQ%xim%qm|TN2yysn zm4UF5%MPC@@+TG8|9!2}el%NJXL%}-PZVmsQLl(lxf)!JIRL&87OyQO1uyfzMK&89 zD&$jh8b;2G7O`o`V~6+5+FB95lZ>*kzeY<%x)ivDv$6&n-?KO7Aj&s0laz1AMDgx`17rxe#uhG~zS$%(gX<{T^V zSS3ssjua^V)QKIcSTyBhmQO4Tu?so2N&@zhV9ml2hA8Z$r&@KnUXraMG%<;IHn_TL z?Z%@_?CwwSmys}B?!<=@?ck!_z~LnCQ8|-h)Sl+0TqP0xU8(vQNUY9N<8Jx7sTElg zj&;kG5LOkObMs06Rr3DE4D$0688}TTii%mkZX{Nj>zum&ZBTty8Fy{C5+usTK;?RA{zr z>>ay^SjbXojBNR@j2A-4i_Yjd;;P_lnYvM$Ov|lG0%i(pPV-s|2qzok?OLh-uLaO^ zBuYDF=5$6n+u!UOd2IB#?yQBrKYp7|h?!YMRx0E$F8JKc^XqhVcHsVvM~BriR>$cT z?dd(WXXs*znG5?OrE1p)Z_mY*Ds)-v$IA;mrXUY7&px+|fa-=Wan+-WtlKj1>Z1I|pFQ1a9>k{h3k;-x#xCyY z8f(&(Dt4`AuBYX`7!6=r`>u>#;-?`Jkf=TN{lo*P}XEVHg0IQ?yvbfgh>qUJ8MxHms79Z_SW99LkuO zn2VPEY31Y>c-8m8MF@(P#v=8GyrOLBm=h|f5O&6^w^9{wp}F_*1sY&#VQ34eB}F@} z$T{x)9*S$whI?RVk!6ctM38O9jeA5*_~AEU^kPvJ2dW(k>a8;8l-B~nHMCCT6v(BQ z;FVg~*c|~d-0JJpxseK1agl6NGcFQlhp!Y^znymO!P&v6abJ#br53+L^W={+&I4+m z!K*@w=V%Y_I|D{goY;fjPmhJb41m4#C{Eo=ny`xi{ZS=VZDZ%*8_%w}t|ni!3M&5@o*$FZ0K|k)J~|*9?Y5vd1a_m|8hTCd zaO6ded6%D%1?r)yQ^)BTL3n{L1jAUmN&HPT@Mqd54-yH>Mi6?3}xO6m!$XiC*D=@$K7q zia)U#EYs}q(oC75tkg+f6*&0bo>F(SjZ?FLoLedzZTwd@i~D#Ab1WPJ{Rg$g5J;X) z1HqI17pqnP#{=hk#gi@`*%Gf}=jY)Md9DR+EBan|0TlCaOxWJ*8YGv3wWIZS={`E$b~%Gz1+ZSi)vcbYsT z@NUlma``t6HXS#h?Y{nAd1T-!jFfrbuWigDI&ya%8~YpHe+XJ^cLrB7YQ4Q={7+<( z$1HMhG@k^GJ&WDw5VlD9>wWleNx&%4h2ih*_VLWvylj4a0ntF2yAz1*Eb#qpgGw-# zgPMJ8j_bGtCC-3xjk12g53{yh(^;oHN`@*Q^`iXk7|>R4n<0r!M&OdjELR!<_Ec@f z?$(NPd!IQEY#D5le{=$xao=mt&;qM48`t;xF#36a$Gmxvq_m7y(blQWh;XSQtTzm1 z?xUu^bAQJKvk6}r;YW!$^8U0Cr3{_V#VtPb8FW>;jUSm z0SDWvPj@=aS9>@Zic;vJXEKOumZN}E$gG$;+II<;)FG%jBvI1R?GCi%&;s9;TMfKN z6Rc&6g06@Lc&#ZTmc>!~M0YLvW+2c5w6LLs+}CBq+m>KO$fEdiMH%F@a!|f~4!y)? zvwMWbYVBMz0y?Qt?3^UPYJowICl;J^^^?+J#J{$m%zaJ{+Wu+eLk%{py)_gim z8a030wbX><`E%2{*RdGwWp8TfRPVipnN7_Rw;RWg^lvw@fX!>MboWObVyxpj7!O@p z3aWSzhH0G!RUPwtS#G^i74O|QHq`uR4)-|tlIdD$MEdt{9(SGAW9P1FEekt%0Q-qe zGAQ%*_xKqC&V+Ye()*GkW4}Pe;3RLJsF692-N8j0;%})^``{pc*L$y2G@xD#B^<0# zB+}OxSRKg0;3mw-)+Fkai=HW+PKvh!$rTp8V2G8t7W37N6i5#2d?r5gDrf%j zI^&STdW^%_Ls>2{u3j*{(@pZnbrEBfTkVU)5~U&9{2l$UujCOb?U*-Y_uQZ{3BwuGnr$O3~^0f@z zY?`cfj7Qm9CEAKFhZoqc3)gCPcZCt&ag*xb+9N8-SR*Jknf`8BAcsCZs6T{WITo3w^Y@m#_>^xaidrIuo-$q zV}I{Au_L)uf7DAX#S#1LRO60`kdOg{zu@%;%9Z&aKdhu0kGdldu+CaX)*H4Vzb6PB zd~BLE%}f6FI8z;7=$%(uXI9zNEr|73s5>*s)YN|&U?uWlH22q4SlU~E$~LL=^ZLYf zq^I2|+SGc<-w}Lpwvi&?UF4S$Lu?ARxcb~TFU*ujO?0HnkE*BebqZZ92-hB$+<`R5 z)Cj%(pc3~o{y+h@h9rU&#!!*o^9by!y!Ny25wBdB-XMM6Zmc8*Iso;)Zx1iZ^Xz-Q z#Hk)yO+I^q{fy@k9uGC;my`qt!)WiEakQSa848bnuS`?)ha@R| z1~5@FEmmDILrkYN)p)hC)nh6f%Z@+gVLIIEWgOhkDVFn%4GsPh_2Lf9E>%`&`XpyI zye#3XZVPH$MxVs2sV^Q8uoiy*uGx$V5q8W7n@algCnD8d^!*P79J*EPcV|rAD?P3l z(r5Y*Mi4aFNT}1>UE&^6#^XFobtpRyp>)IO9lc7+*Uy9lVf+OmFAhm2a7Z<|_(RvO z8P?#DLn^{eSfw|I^}a5KdV!0-r1=lLtlES39?rO))456EWdy}y#nVvCa@DX$6l5Zs zQZLsnYrV#{{@iyqv!3+o1t2ny>T_tx9FC*b;aMNo;0QDV&>I+ksVOwU<|!##D@bOY zN7+-}eIitvceOQlv|gn8_mPJf&=p~8_tzo97>$4b0zI*Ivy$D2%)rdvtM7ZIU@mv3 zE^AwL0njA~8H)uGI&s*~ojTR5Xr|o8AthdulZo@P#6AO8#$vyLf11AC_R5qcZ#^DT zU)h)B^kscr{VvF1S9j}z7`n_R3|x4X`cSqB+GndWlPg*0YrrawJI-=3WZtqC?nji7 zwnn^;e?u`la2P=qWeO{}t{1H33)^=)uxA~$Yqk*)F+(yAXcxxUDQR7-YTf+zS z=h#+uGQ6g52*yVtDvV!?j<|Tk@2fYz`}KE!g1hcHdbYyywqP5jk+*w%^y~8^oaar_ z?H}FsTZev$KnX{mGjcX}N)}j4;cr|MzO+u)ChnbJ+sGmt-z<__EFf1-4~u`WXkG@z z+5lh+_x>QYcYdX^>Pe>Gy>8Fod{j+rqYzPs9&zs#_4V(Bt;=Vtj6WL~wt6nx^97rk zLW>iERk-2OG(!aW1!m$pUi$oLO#^?)UVMU#WDpo&`KH&PnB-lAd^4e_`;r~?((4{g z%76Q@`m_23?&KPr>3JNoEh6(HEA>sD#LW2t{U4OyI%acTCu_A{Rt9}Oim8jpzU^=! z{rpDf`ulWA8YK>V($&`IPfI@A-knH3CO6WOhxAVw{`t()lgt&?M(Mi3ppoVeqDK=J zS^b9-rBQ=_2j>^nr3Lfj_BP+7Dn{#F?cRnI%(g+NXT}wfa~MgJQ8&?aGhIOn*F^(& z1dz*OL2yACZ@w9vN4Rvglt^YSD`m23>)rPC1wG$V?HL*<`KBAbFWIsg8KcjN>H%f{ zCFzYudQe_d`34KNOT5?C2nQ#6gVqXzWVqoJD`fQu$?cnnnh`#wZNJo^sU;mWWx0nj zXtUHAtcmw{zZMagCGCIHd-bOJ_{n(G=TvORJGdoHZNpGo8<^ zzj(*rEUB7u6NJi32qi^dlSJdDm6J#njO)WM;?bW39VNpPBD7I0&i?nhHkU4N!}=nCWYse1b(>i*HN`JmyoFinEsLpK3ujG-h&%OtJ4hd*m>FoD|%#yHMt4@$=;ZUe6CVmV1OkJO3m?ZRH|dZPa+UVg6q=rqH5#&ToSmS+Qw@>Ti3`-6sr z`x-~%qU1GjqtiAYTvBJ>?asz@`MF`lIX+*dlh)nSYex#UgLDW+6pr6bzB3=)iKa{T zvSr998=Noy!}x|Z<8+ui<(J!ki7HB;9*TjPYX zz_r@eqNz(?JY78y?U&hd$jxv13=Z<72N-bJa-ByJ(5ukDRm_6)aoNrfO*$kaiyM_&#QS}8yS)1*EYYDuUT&P0tins ze{75?inH1aaL)3gg_-CCM6`JD__x}d@!!{qz4x+%7*FJUV$VDt7_f{vF-adPE9M}; z3a^^m7XLoQ!A!rskTvZz0LGFrBjPp>zd7E+G&7n0StXIfr3~-N7LWAmzJ>L)Zwsu= zVtV|37$bLCzJty3&SE1dA^N{9vIzATt2d^J2oq}|wCL~5S*!70Kbs(XwbnaZTBNP$ zYp!RO$!$zBFPz?MmFqmPzumuO=A9(P9=J>;6|(Yc@@D?`6P9OccOZRW?sRi}{Kf_c zraV$f-73;`zLhFX(P|hg`=U(PL%#)0S`-N4Bdb{5Ny9%okQDV zyYpPh@n|3^_4#-iA_q)jT;53fmN`|Fq4iQ8y zGFb{I<&1G|<*XSHEwmk%<-+*BgfRGz+%-2hCyJ}91gcRzP+ z=iiWnIP1Q&)CO9T*K+t`w*JYM_Sau{(X#&a5h1HnBA+nt_l=L9@%|%~=P0L4EB+?L zazJD^D%;M4j;|3_UzAvhdYapVPP)YPFD`jQ?|0RsUkL}ErxW>EEGR&q{baSS%yw0o zmIrtq!uS)w>;ofFIUO_w2Xtr;#9z;&Tc$OXw&WXp;3R42|5;s)b$NL?dyr*x++)u{ zHHh$0vWsm?db}-#oEOSOr3V1ZVI=M>jP`~s_S49HSt=z-ZY=e}ZtX3U{>I43Mnv6OsA_*RHC|C)5or7T#FXzuLL z$>MV71jbLb<2DV&vWVPBlJ}Usj#-^jcK4Ni1z?rQ%_%#VZpLR7KIt-@E5H6kIM^HC zAg{jPi|p{Pp-c0(JsvZ4aT0HPH|OrR8R*%{&$QEfKQFZ2waq6Tvl>NNo8OOWcFYI| zGy@;#id_TR21=&6m}Wr!?%v_{1)Y;uGE0Si2aZNP8@@+PULMoo0MiZwtN%tF^1W=5 z-bSnk4Y{c9*ZZJ?Ki)$QkdqMM_s`m9){#F~x-39iV>Su<2`+TS+Wn~Mvx<<$16QL! zee$jc7iHKAYWAKtRZ4C427wH)JtB%9sA?qx+=h|ncyGa|rGT}c(Q0*K`>(B-HAjvT zP3(;k{sG})HoX{eb`5RDL+0J7M-$M1X1tGyNr&%}c z^42WN3C`lOvere5e{bx*jmv2LG*gN_mX5hmiw05 z*f=ZP0M%b-ebZZij_9`f{k(b}blG$eusZM4p4ZX97RJG54Gdr#$w)UW#opE@?(jO+ zAH59~afX*?2s^CkbyU_ImiC;iG`(x<&;A^Eg{V0kkVe&wh_FxZ4aB$c-8-n_t@zS@ z3CG%EK*dT>5eYn9Oz65`xBm20sG>&xNLIhX%KBzq3qtf zV!93BFhE`tJ~X=-)HCNr1c@$ODi?itU?Aq($She&2)L>xwHBQvcGIlN{;V|`vG$6g zVf_$%m_+}~A3o1m?cYcFTAZgkj_{`wcw|(6Cc3Nm|F!qsK}~+$x+sc2QBbP%BGN&6 zhoBVcy-SrUO=_qCL=>b;??gHz^xhF6^ddEcsvtG=5(xFa`kiynnK}2)ow68@YY8|v;=+S*-{{P+Qe%jW|$gmo^JzCnZJ211qxvp7-} z0-?}%)Q6XsyRwX#rckfC5D}E9TG0C9#HK^M<0@B?Y*6TWcurd!xw7782f>7w$18E`2>2D9lcPnDKvaf#To7ioLf&<* zlxV)vIPkqC1HomRc|%zaseIKmYw(M2@$7a&AfBx4WBPXQb0-R%>p3Q|t2D;D^bqd% zDs$j@-)~_+vgx)Lm*;c#g+7)v^{W<}npIX_HSMHS;YipXjSWL?(N`E|pnW6;Qa$i> zwYXBE;yIgI?d|tRX8id{2dwD;h|n7JlBvBiM{>yw5A{>5<{GN69_UlhM z9fl{c0EXW257_vJY9@h0y@z0-5^HaXK!;;&DkKYO-~ZbBZhM&bj-ci{zL}bB{Pg#tb%gupZm z7UTViOhR&PFh2RSAbZ>N&KPTR`a!tessAh!$}j_?IC(D@%AV0+HtH7`Fp~rzW+GO& zNa)mOp*a#CPiTanUqY+Tzr{7yNsyhESgiF`lDLKB`>DcOXozE|9r=KYgZ=%~J0G%r{UOM|K_2 z@PBdvs3&gfN*9snCLmfX1!l=8OR15Xf(ipK{{ zn{s6JY;3T-Qcx)K7X&91+LLt@Ihh3L2I!}?zO$o1YG~*lQ%zbE=jG)IV~Khd60h9H zNC!N54wm695YY-T(`pd!x+~Bh&)!&d_WXD(;BeioH~4Y66Hn_MbN&+jfXkz7sKT^W zf1bpnNGu94pftHi(%V@6W?O6PJ4{SWdJPJ2TcMwsgbh;Xdkgkw0Xm#oTlLJ`hUXG{ zxObpSWZg|_CAmRC+Tb}Eos`e@dGn)uPwdoU*N&w-+&;c0xwg~kv%^9==EYJMZnnWL zeb1w#2g4g#h_5t`dR6H-@~`TBvgiRJ$;(TO6ets!_*|L3Z(3nZBL~x0%FE_{s_tvk z+42a_O-aQbQ=IC%0Gwh?;T0!Aya3UsYhiD!HI&V#9zxa?X~(K! zAkF2*dgHP=U%1B{BoN<{Ng^ErfHJpaev8GbDO5YYo>u5)2$Tm6y69|HW{Z9mo zrV?}@&_wVU*&}WbiGVOJlp-jk@IWxl@hI_HDVIAV4%|)ztZH(Y{8iqejC1=Zf*4;#?;?0sgM^ zYs8^=!1vW4aO4LUo*zWLXX2*wAs)MJX%{ZJJLTOux$xLS&~Mj~NYFfQUL!f(8V#{c zv7!HQIrg3DiR#oM5HIu8-#wQRDfZ|H03g;PjSuxCB9~i})AiTYd!Ha_KT4$geYUCwldjb`d*a za~)Vjemd&QAHj)&i5bDIF6J`!`6_AAH^E{3-!js>{sjG#K*KUdn-#HQ_QrgnXbH?c z)@@*QCwIh=xYgT-=am7X(H9zy4dr49&qTbgN=U~yN!yzSX`{rOWrEuZzdS;6ImvXu zRsg;|W0LyH0MqwID+TxQ;qVOg)LjQz6ja#Nyec5~h)P|gSiJWW%LT2QeKyq!i+%B@7dI8kb;ra|G) zT2(F%WNUv0P>s|FU1fRxG+(cN>)WvO>fgFZaBGn~LMluqmBXZ_@;(m+=JT`GUQ>s? z_`|gzxTMhD$F@%-XY?!=J8Zc3mgjtbm*~>T9`_YV8a7Sw*;jje$3V03+~r;N{n9^i zEegXs^7au^mO5h^h5svuaoAy!dO;3#LQtSOv;T1k$*d_^#rXu@?p&Ta<<&tu_9T`1 z!OumV*F8=jBdpz>0$KD1&EBSmzEnHduH>V<8a*9#`PLij@ZQ!-RH;NUs=rX2B_l-K z^_@<0aRe&qP&z2kLBi8?Us}h0&}D4ge!g{h$MJcz9_!d<`X{xSA1U8QHJnE`#51@@ zT7gI+DIi&e**GlMhpbWhCpCt(2w>h?dv*)m2xOq9Y82M|JY*{(F4XN$GNBnH_{fag zoVMNj;qu(Tj=F&z(Ho~kUwnk6*TTFs$o>5`=S9misq5GBH%2p>RYdspb`~cxyQSKG z-EUdsfr`@7i^C}CFC0a(ePr7$W(8qClNa#cy`~*ssVrwbQH=` z$i7GRJy7~f?(QC1LJYsjl;Zv%P$X}$fk!9mOeJXgWSP;PkuG<+6LN%{{?B9ny+=VzOVA-VAT0qo9_q1$}f0kF`Q1T*pb8pWB= zv21p;qi^;TJvM*{(TMS;E>(#qRfmu4Y2uOl?_1`)MRa=^=CK5A9CV@q;^Ui%Li*uy z#O!*A3tJp%l!)(i{|!HDDE!G}G!}fnb6wTAc~bR#*4q{{e21Y&e$&%30)@(HS0zV$ z^!b&c$VSC^D&%Wdn4{gr7v)W%s(Y+kg$OmqK?CLJGES2I`~npn`=9fLq;#7P)MvnE zf)$idU)x8130?}A7UQsku9ff8%`?ZR0Hx5N7H;Ulpj%frUuQb(<^OEAlUdJkco918 zhV1Cr8tEg^7lciG1*x#j89mcv7nG7VQfqz2YnY#-^~koUIOceJE%>Z59HGLU@8AaG zKqB-fPXaazWSN)jII_O)?^mjMedtuxG?)-{q{F)%Tsa+8&A}6)hMD-)WS`_wOPe1ntkaoCbD%-4m zHlplp<*D+E5^ET4G9zf+YY@ybVap4@6B-82Fu51f84;u5h2mMD1Egjh%abi*%Qqal z>;OI3K{Msvj?yQO5Lo4OXt><%uC8=7Z#}=uqQgtBX|rSmT>;AoU7A(p-*m0G%gR3# zW*Z9|)~F|3W;MQ7Gt)Ls63y>^A1yX8dn=N=#R-Xf8AMe_6C8sp}F&gjE5Fm><|MP46T=37*lBFI}y4~SzL)G2c~+#Jz*TtPq=)j<`4?&CaBkLwW>oRn zhqrTy?*{ zpVMN7aP1H9+7t7kx;+WE@GE}*d2U^;P{+4NOhKh=3~I&F z$S>ruDa(_*B(#f(+1Pl9`+l^r0r8R7O{bpxkzp#DiO)^Vgg(4ofl&$fkrNsoAvG@8 zR=D<&W5ZyqUEyh5ZjT2nUhx@MMyh%dcaYhn>9Xym^_XdMp>e-&8n(p9Ey>auUMz4s z80VddB&`9LLl=N_Qg_TI&4q&aC@R6fi%+Q=Jvu%B%j06c1m}InORSRp9--0srSK=> z7D0%;#fsv!sj50mWPgm(R{lko@F?Q@JzGe>lb*{KjgH;;;*;KS!&zaw?tE(=|8BSJ z^gcp`G-1U|>gIC#WXJmcq3?Y@+Ra1y5mleUE73176j{YVERi>PXmOym&-iBT@sB<0 zXsI#&Eu4kPVKh~b4HH*^_YTWPW^F0$I#ZR)1 z1vqK&w?jJg8K-N_jnmU<37vG|*F|Tl9y?4GTTXo!E<6#pz#v*&dkc?TjCCHsc!5!h zCnKqUfN?=fjXNYrxk4^LdIw$Sq1HV^`zJ2-O@0dB{P-op?H3V2ssa7?N5Zt-z+F`L z#6{%J`v-GL>2FI^6`RCbvPs0vfnd-(kOuaF>^;60@}=b29PJ6&LOx?Yv4_{{kSMTl zX{eJSA>M}X9Lmp;m8#zNOC5lE{%}oCU3L(|6~}LSU9X$pYU=E7yJCsg#bv)0*`Y=4 zxv(Ep9|DU`?*)HhCtS(?=u-o5!g#VJ9+}Vl2%+zo4Qtm8R6>jrUhJ3JiROxS0IdQc ztt5u1RP3qvQO4j3x)#CP0g5UMQ6lUityO5s-l+or$)0+Z2ww1~RTI8+RywZ&mP4xL zr3sDvywlX3_2%c50BI(&lx%@H;qUr08W1mE)?;m9YrW6O8t^WlItVPfxG(J+fFm6k zfOAzcAYV+5AT#*^TlpaT0x85v!J>cYsxK`BfB(4xLH;|T?sZ7=^cU5_Uw{MXp@!W4 z!3)t}6~=qa^5j7t2If?a|EAO8aRk3xr;6I3?kt~;g45=6{TZ@#GiHuSs?gv)D2Q5N zse=!FdIggH@DiaXh4hjl(QNGGeOL_JqT;OD0wih@v_pl|!eFzwsg~fUUA(2EguSqa z65WCEUzV%(M@^3DwwuAP>7ljBRSL^ODGssE0kmcmRMTLYA((bB8dYPcx2(1oUmSBVJW`zQH`>;I zuCMAn(7sMb^Dmy7_Fo^>?0*twM_kSM9qe%9-qmX!Kzwrk2D7y= z%A&jsw)3ykWV3c;W~tW|#*GU~yVR4Vfy_0CcU6{mw$kx^=E6&GbjvFjqoJVJI06wU_UcRsQOIcLacP?E`^dc9 z&0+H_jk*NIUH6_Xy$bc{RVqECO8yM`48Sz{qJY%wwTuQ z$NFBADB@D5m6H1_>;sKC5~0KUsj|DL60+ZmV!8>_xYi>}D&(#bd|%C;wQZ!UxP0TK znV9I4C7)l?B5jH}^xG+OAwUy*%7#6c)LCc_#0|}v;}Lm;4Kuy??c)`{#KaOu4pSig zIwE2guH}SHA3d7^7r!x0dNUkkb%~8}mNB%t+h60gng4w^K!4_)UG?xUneDOF$k|F@ z-j0yKS;(`0me_yLQ8q;t{%#kSSs8T) zx_@pNMFTVjBEGvhnhbC$_w$9-?#J(TC2j!+`q5dz>GnnAi&%tDwnAf4~EKCMFX? zRcR`FDb5(!C37hAfc)&dLiL+-r8XzNEe)y2WqdVUA8x9}#@3(48 zQ!5;D0n4wt#cDgleZCG}N?G!sO4Fkv9;{8S7~=$1wb7$7(Lcum?jIKoNH6INZ*4?S z`Y1%k_(?m7YpTWwg1=Ij6O-@&zR9Pa_{Nq#(R4N)LOox0hxpN zH2kB~w=jM^;t%I8N!Bxv=MAZ1>rrFA7p&r*T{{|UPfjtZtoT33ID@vwCS3S-5*x`~ zyOrK=2Q`?uUCV39SC$s6VvGMsbX<6R^@v>L7^&qUGn05iao3$m~)qKfqoe)P|A_S0&E zm)didE83_6y}v^IcTcW|7!%7=gIB?L&AFJ69(Cw^tMGcZf4QZrsxs?eChaU6-r#Ry z8IJdjjAiI%y*3t|18xth%O`Ue2SrzTKE5xy2Jd2M(GTs27t|dzU0-Gd3lqb&J(9}*Eygnul8KW@#CD-_7^ zqh;Aojia&F*BxTn0Ej;A18i)#lBQndtS1;rI|>nwdO(owgEvv*WYH&lf`Cz5TKfGh zaNolLv@YOOFAM$7&kD1|^ns1_Pd<%}X*oK9-yE?(3GT0F5>=>`K6^9pnv1+KyKr1WxIEO3aVhXh@fJpy#G#w(POh*I>EkhS!})ypg(7z?~bL&`@^v&h`K2_G#} zr0+d>Eu=i}31~}F(9(i8;nw{2@E0swC=>owp)iCUHw#I(C7 z-sTA$<{%a6L}p>V0_7ePPN5^J5HWsQvVAHFZp1?5DM#%fnc_bZuYjFRKyATndU|Di z#Bj)}@y44_-h1r;4#{aT38UB%i_RCYA-lFRdwQwShlyYUZe9Hmce zdUj&i44zgWwYO$(>Q*VBtUGAl0%=50(IW49jS=Ngi9pt9p(gzhXPW9Ur)nD`sMl50 zDcZPXv`X_v=Q5D}6r^=sbmZrOh4L@3ZF#sQjISS|dK7@{-O zt;I&_&Wu`jj0HM~f_Y?RWwrf(PhzX_2heshxBuPV|vl7T4@sohNIr4F)dF`04?Dlu|p^t>RT2`>+sYI^Hi}&@h{PyQ0xfLv zLT%h=2hrR88zbO%1wb>=Xde4?@9&!Bc00#MHua+Pw3&N;Dv3-7>4-W*z_{n&vA3jP zFnD^NBw#EYRw}7Sgw*GUPK&YH2=|plMwnVf98%za;%Xs@?R6IJL&X*A1696qavO-X zbvM;IP`C}~wI6)|(Bkfy0kH!`ioqcN4-QSxxPe2^U*=>X*s=@mwo!zLrF$&xmA zgvc2ROvABV)f8Di&e$kB&~^C6ikOxDr|u0HrN8IaBb~6%Zi;-ND^Y5`h{3_Ck;CRw zcdY%?zLi=Q!?}Fy4(0cR3lbk+-kLq(FVCM7d=;>^u+d>*oH~xK#(qRRD;%7DlJwcM z7{(E8N=kKfoGv|*YA3d>CF~nlc2T_$nbJCVoLbxhRB6dXyk?owAZu2!)jRgn<8+yy z8`sEo;*PLuHEX6dRrd_8eZx+cI3>3BrCqXPG{ral+Ly&A(^8*D*6mV^?YCU9U$#km zSo|uvzO?RGe8d%D(>_Obcf_8*l5Ll+!3k}`Qb_WbkU?1rG=wPm#}drx@n-8G#H96G z?1MGy4=h0QsHTv-86lXJEYx8xksogE`H}zrCaXxJ3`sps@(f6o+?q&4EvtXyQ}(;j zPmR8Nl6o%fdvyTQ?Rm!N(xEaASxCsTlz#J;ZPUIo4e6fB!&i}=2kx;&28SpN#xj%C&3#lc%2^GTsKHL~WL#I)YAd z{%qSK%!4XTCUhGpEk@&0((_=+f{H}-3okQ*;K@62#gW#|AF_68JeY6$wXHkJ4q=VX zFG~xh;x{u(tYcxnTKbzA!!w2>aupM-2E?Ro?(wvFDvAZn$y{kvJj*Cq4iaBgQtc*9 zc-W2I1V5@)bJM~g4oW{txo>&#_$O+7F9!~w^c%ndST35jZGBik={JuUIB$nzkZ;47!?*AY7lt)a^JG8}pw z=pZz1p~A4!K$2!vwV6YK@xA4;$|sOx+VjKsIhi24`XKXSGh!Qknj4ctd5(2XapXz$ z$3x{Ah9h5z)$dKysZIboZH)LWtp(K}hYBFYpF@3_dn6GjT0jJMQ$N27ELk$!XlBT8 zSu0Q(+<}T-^=n&tCPhivUR>~JJf}PK?!o2YTlYZVE1yhotTu?R@a8W1pfhpwM`)J3 z{jW7|&srHe# zq$lb~uamTVAp^1LA@#=T#3cR+cXZ_=XB>zzpwY0EZCh(SO1I&A?B*;1L}ly@Q_;h< zuFKE^@+PSG8>;qdCzkkrpyoXs{{;1m#x3BN-W_W#)vmE&s`B8gp9AKE1)s3ei>76O z85dcp6XyB&*3DAc_RQ{SS$jnNtCfoLpH?a*6xHt|4akCl3Ym@!W9IFjv?Ymk7UUX> z{(Ahb?+hbuF&x#^w569$r5ontn1pjJ%SZtT=j~UPh-%B*Tv)RZ(KSogAC#@dt8%xD zgmi(Xrk8t8N7fvJDW%l!4J?}th>O@=-g^tBTb64*^c?swW_JHx5*?=pgISTm?J5HsDn8e}x&uw1 zYcmZ!APz`LzrGi*7ZEM@bebZ9jC`;}meW4AHJ%DFJZr&g_=AQGdFBx~(5uj@Fq=2N ztyLg`IEv$`ss!;Efo~wMr#|x$N61qxo=%LFxmu-DwM5A5nmXwW7!c1_K zg=LMZdua+&JX}uXGcrWQ)niqvpX;IU#rq(C`^Rh4S>o z;Tu`mCU_gsXmEXf;V)=**F=&xS;PGtHi9P@cGc*zDp{IJnKEL0bo#lXjZiGoozp9w zSmJ(ZM4_`6uR()##Z#gYsQ{Ftn`*1&?c>q=f2OE}^nYCMU&W5U+>!r$QT*g{wa^PR zk7*?Q@YhKn^H2Q+N0)u-+`RSm1vKm<^~Mnsb0f+h&78a2I9~U2lt^gU8!YG78;&WL zLUeZVyRlInHFdd$op73+dd^RV(MnEgY%x`ae3l#r_FwwrN~t1hZdaY{bw?nUGr7DG zw03t1jhK@hbooh6LVV4a+a%xw;a2hR+wkIEnH)`d>v^=%AP314CS%K0TO($xDt;Xy znA1Ryq_L1|)u&>t3j#f=e_~hN=To(kuwxV%)H_MN3R5>#^M6(kA%hQooL{jpBQeTTB2Y9F2VR|Hh4`r5-68k%ms6xH3x=nbUF7xcl0ks+)VXFI`F5K!l$lUFD zggB%5RdQ@=^>LfDU5omJ|oP zcdfVCrl`W)V~RwBy1k~tWYI4w?9fxyI>~n!Mp~TiNprYmRsRInh3KrciQ&5P`+DM` z5T}Tx6wa}n%$2m*K+ad?LukQ@Db!l~YwCV%R1;F*ger*dz?-AbCufDpe|p(aPlB(R z7^9ddWVA13{3YwiV|k5rN6U9di#ede1hgYJ+~y#qa1LEf3eYm}$7)ScXrNxTAk(Wf zo4mHL5aEEx6D)AZ4!s?@VC5*gx?@-7Y=e5Y_)WNW0+{8sfkvV;8Ipb3vBJ%D3u+P` zFoJ%Pz}uQ_%DmU0zpPSc8|%wU zT+_DlB>4r^Wx^Qtz4pl^G}0T;fU}rcr8+JRmjvM_DWo|?9OYBp`{=;vrKRMbIGSyr zJqjt7Z#HFaN+O7Dz}M;#XP3{E~M!{1aykdEkF zCwwv~!afR{p2~eF3UvnQg~7!_tI5}<$^lovGdpB!S<~*RF(EU`L^3-T8HV!_-Lzy@ z>kZIg#_P)66=88dR<*MV)ypiwCJH9 zBE{NK*bdTW^cNH&?Ks7CBkVi!u2m$JEE84zY@ z65QnfxZr3o8zv9SELN{cI-X$BhLRpOYj*TGO25mU#vvhVNi9ybV|QOEutGRu&W)pj z6GdL7xFA26942v-$DzUX{-ex$p>Hac#sA(s<1Ug^0h>-zji||?a%Ugd-EMAtoV|gl z6!<2hr6jqwl%+~7fLe<{UeOAN&b#e>0wEoub41r2of8Zv#njWd1rKV+`QMoprB)i2 z+-Y^_*DLX8oIc*Mrl3Dai|{B(cb?{SjvWxXCn^mW0Ri-!8ik}|8&(;Y$yty58zVCm z^sT?HJrt&mQS=(Ft6VHS_EE<@$8FXQxe+=FF4~uzeQX&rDUBgWO@~;4tba zUv=lD7V^sxOGuRR#ZJO7v{b$$#&IZoj58OK*u?`AT9BBs%3hsx!S+e)Xss?EHT9s- zRLV(M87OpHv-m6>B>MO255D&Ty;J}1E~kzEXKIipXzkdt4z|qrZ~vI!biho~llC_P zb@c5}kMTUUcIbnE4%O5C;uDMo-?}~jhXen&c*Xqd|K;odIX(G5?}h#TzrX+2^zGmF z`EPFZzn%Ht{_!8<-t~g*zWpCf7Fk1j+xnlajo; KT)B+JhyMlE&rUA@ From 23e0f50af0dee33d0790d3823713b18160b1a090 Mon Sep 17 00:00:00 2001 From: calvin_peyron Date: Thu, 4 Sep 2025 11:18:05 +0200 Subject: [PATCH 890/964] Change D2D emulator documentation format --- doc/README.md | 2 +- doc/d2d_emulator_setup.md | 207 +++++++++++++++++++++++++++++++++++++ doc/d2d_emulator_setup.txt | 104 ------------------- 3 files changed, 208 insertions(+), 105 deletions(-) create mode 100644 doc/d2d_emulator_setup.md delete mode 100644 doc/d2d_emulator_setup.txt diff --git a/doc/README.md b/doc/README.md index e19c71268b..c48f2b6ee8 100644 --- a/doc/README.md +++ b/doc/README.md @@ -60,7 +60,7 @@ There is some general information in the [OpenAirInterface Gitlab Wiki](https:// - [How to run OAI-VNF and OAI-PNF](./nfapi.md): how to run the FAPI/nFAPI split, including some general remarks on FAPI/nFAPI. - [How to use the positioning reference signal (PRS)](./RUN_NR_PRS.md) -- [How to use device-to-device communication (D2D, 4G)](./d2d_emulator_setup.txt) +- [How to use device-to-device communication (D2D, 4G)](./d2d_emulator_setup.md) - [How to run with E2 agent](../openair2/E2AP/README.md) - [How to run the physical simulators](./physical-simulators.md) - [How to setup OAI with Nvidia Aerial and Foxconn](./Aerial_FAPI_Split_Tutorial.md) diff --git a/doc/d2d_emulator_setup.md b/doc/d2d_emulator_setup.md new file mode 100644 index 0000000000..8b529d97fa --- /dev/null +++ b/doc/d2d_emulator_setup.md @@ -0,0 +1,207 @@ +# How to use device-to-device communication (D2D, 4G) + +--- +>**⚠️ ATTENTION ⚠️** +> +>D2D is currently unfinished, the following documentation steps are likely not enough to make it work. +--- + +## Scenario 1 : **Off-network UE2UE link** +SynchREF UE (UE1) + +```mermaid +graph LR + UE1[UE1
eth0: 10.10.10.1] --- UE2[UE2
eno1: 10.10.10.2] +``` + +### Example of /etc/network/interfaces configuration for UE1 +```text +auto eth0 + iface eth0 inet static + address 10.10.10.1 + netmask 255.255.255.0 + gateway 10.10.10.1 +``` + +### Prepare the environment: +```bash +git clone https://gitlab.eurecom.fr/matzakos/LTE-D2D.git +cd LTE-D2D +git checkout master +``` + +This branch contains all the current development for **DDPS**, including: + - **UE MAC <-> UE MAC** for **Scenario 1** (off-network communication) + - **eNB MAC <-> UE MAC** using **NFAPI Transport** (on-network communication) + - **RRC Extensions** to support on-network cases + +### NFAPI configuration (required even for Scenario 1 target) +```bash +git clone https://github.com/cisco/open-nFAPI.git +cd open-nfapi +patch -p1 --dry-run < $OPENAIR_HOME/open-nfapi.oai.patch +``` +Validate that there are no errors: + +```patch -p1 < $OPENAIR_HOME/open-nfapi.oai.patch``` + +### OAI build/execute +```bash +export NFAPI_DIR=XXX (place where NFAPI was installed) +cd cmake_targets +./build_oai --UE --ninja #If necessary, use ./build_oai -I --UE to install required packages +cd ran_build/build/ +``` + +### UE1 +``` bash +sudo ifconfig oip0 10.0.0.1 +sudo iptables -A POSTROUTING -t mangle -o oip0 -d 224.0.0.3 -j MARK --set-mark 3 +``` +--- +>**NOTE** +> +>If necessary, add a default gateway: +> +>```sudo route add default gw 10.10.10.1 eth0``` +--- + + +### UE2 +```bash +sudo ifconfig oip0 10.0.0.2 +sudo iptables -A POSTROUTING -t mangle -o oip0 -d 224.0.0.3 -j MARK --set-mark 3 +``` +--- +>**NOTE** +> +>If necessary, add a default gateway: +> +>```sudo route add default gw 10.10.10.1 eno1``` +--- + + +### UE1 and UE2: Get and build `vencore_app` from `d2d-l3-stub` (branch: `l3_stub`) +```bash +gcc -I . vencore_app.c -o vencore_app -lpthread +``` + + +## TEST ONE-TO-MANY + +### Run UE1 then UE2, for example: +- UE1: +```bash +sudo ./lte-softmodem-stub -U --emul-iface eth0 +``` +- UE2: +```bash +sudo ./lte-softmodem-stub -U --emul-iface eno1 +``` + +### Test with Ping +- Sender - UE1: +```bash +ping -I oip0 224.0.0.3 +``` +- Receiver - UE2: *using wireshark* + +### Test with Iperf +- Sender - UE1: +```bash +iperf -c 224.0.0.3 -u -b 0.1M --bind 10.0.0.1 -t 100 +``` + +- Receiver - UE2: +```bash +sudo ./mcreceive 224.0.0.3 5001 +``` + +Filter the incoming packets according to GroupL2Id: receiver (one-to-many) can discard the packets if it doesn't belong to this group. +For the moment, both sender and receiver use the same set of Ids (hardcoded) + +- UE1 (sender): + ```bash + sudo ./lte-softmodem-stub -U --emul-iface eth0 + ./vencore_app #send the sourceL2Id, groupL2Id to OAI + ping -I oip0 224.0.0.3 + ``` + +- UE2(receiver) + ```bash + sudo ./lte-softmodem-stub -U --emul-iface eno1 + #we can see the incomming packets from OAI log, however, cannot see from Wireshark -> they are discarded at MAC layer + ./vencore_app #we can see the packets appearing in Wireshark + ``` + + +## TEST PC5-S (UE1 -sender, UE2 - receiver) and PC5-U for ONE-TO-ONE scenario +### Configure UE1/UE2 + +Configure ports and routing table for UE1 and UE2 + +**UE1:** + ```bash + sudo ifconfig oip0 10.0.0.1 + sudo iptables -A POSTROUTING -t mangle -o oip0 -d 10.0.0.2 -j MARK --set-mark 3 + sudo route add default gw 10.10.10.1 eth0 + ``` +**UE2:** + ```bash + sudo ifconfig oip0 10.0.0.2 + sudo iptables -A POSTROUTING -t mangle -o oip0 -d 10.0.0.1 -j MARK --set-mark 3 + sudo route add default gw 10.10.10.1 eno1 + ``` + +#### Step 1: +Run the traffic emulated over Ethernet on UE1 using lte-softmodem-stub to test the behaviour without RF board. + +**UE1:** +```bash +sudo ./lte-softmodem-stub -U --emul-iface eth0 +``` + +#### Step 2: +Run the traffic emulated over Ethernet on UE2 and set it as listening to incoming messages from PC5-S + +**UE2:** +```bash +sudo ./lte-softmodem-stub -U --emul-iface eno1 +./vencore_app -r #listen to incomming message from PC5-S +``` + +#### Step 3: +Send a message from UE1 to UE2 + +**UE1:** +```bash +./vencore_app -s #send a message via PC5-S (e.g., DirectCommunicationRequest) +``` + +#### Generate unicast traffic +**UE1:** +```bash +ping -I oip0 10.0.0.2 +``` + + +## TEST PC5-D + +#### Step 1: +Run the traffic emulated over Ethernet on UE1 and send a discovery message via PC5-D + +**UE1:** +```bash +sudo ./lte-softmodem-stub -U --emul-iface eth0 +./vencore_app -d #send a PC5-Discovery-Announcement via PC5D +``` + +#### Step 2: +Run the traffic emulated over Ethernet on UE2 and send a discovery message via PC5-D + +**UE2:** +```bash +sudo ./lte-softmodem-stub -U --emul-iface eno1 +./vencore_app -d #send a PC5-Discovery-Announcement via PC5D +``` + diff --git a/doc/d2d_emulator_setup.txt b/doc/d2d_emulator_setup.txt deleted file mode 100644 index fe26e3f9d1..0000000000 --- a/doc/d2d_emulator_setup.txt +++ /dev/null @@ -1,104 +0,0 @@ -Scenario 1 : Off-network UE2UE link -SynchREF UE (UE1) - -UE1(eth0 - 10.10.10.1)--------UE2(eno1 - 10.10.10.2) - -Here's an example of /etc/network/interfaces configuration for UE1 -auto eth0 - iface eth0 inet static - address 10.10.10.1 - netmask 255.255.255.0 - gateway 10.10.10.1 - -Prepare the environment: - - git clone https://gitlab.eurecom.fr/matzakos/LTE-D2D.git #branch: master -This branch contains all the current development for DDPS - - UE MAC<-> UE MAC for Scenario 1 - - eNB MAC<->UE MAC (NFAPI Transport) - - RRC Extensions for “on-network” cases - -NFAPI configuration (required even for Scenario 1 target) - - git clone https://github.com/cisco/open-nFAPI.git - - cd open-nfapi - - patch -p1 --dry-run < $OPENAIR_HOME/open-nfapi.oai.patch -Validate that there are no errors - - patch -p1 < $OPENAIR_HOME/open-nfapi.oai.patch - -OAI build/execute - - export NFAPI_DIR=XXX (place where NFAPI was installed) - - cd cmake_targets - - ./build_oai --UE --ninja - (if necessary, use ./build_oai -I --UE to install required packages) - - cd ran_build/build/ - -UE1: - - sudo ifconfig oip0 10.0.0.1 - - sudo iptables -A POSTROUTING -t mangle -o oip0 -d 224.0.0.3 -j MARK --set-mark 3 - - (if necessary) sudo route add default gw 10.10.10.1 eth0 -UE2: - - sudo ifconfig oip0 10.0.0.2 - - sudo iptables -A POSTROUTING -t mangle -o oip0 -d 224.0.0.3 -j MARK --set-mark 3 - - (if necessary) sudo route add default gw 10.10.10.1 eno1 - -UE1 and UE2: Get and build vencore_app from d2d-l3-stub (branch: l3_stub) - - gcc -I . vencore_app.c -o vencore_app -lpthread - --------------------------------- -TEST ONE-TO-MANY -Run UE1 then UE2, for example: -UE1: sudo ./lte-softmodem-stub -U --emul-iface eth0 -UE2: sudo ./lte-softmodem-stub -U --emul-iface eno1 - -Test with Ping -- Sender - UE1: ping -I oip0 224.0.0.3 -- Receiver - UE2: using wireshark - -Test with Iperf -- Sender - UE1: iperf -c 224.0.0.3 -u -b 0.1M --bind 10.0.0.1 -t 100 -- Receiver - UE2: sudo ./mcreceive 224.0.0.3 5001 - -Filter the incomming packets according to GroupL2Id: receiver (one-to-many) can discard the packets if it doesn't belong to this group. -For the moment, both sender and receiver use the same set of Ids (hardcoded) - -UE1 (sender) - - sudo ./lte-softmodem-stub -U --emul-iface eth0 - - ./vencore_app #send the sourceL2Id, groupL2Id to OAI - - ping -I oip0 224.0.0.3 - UE2(receiver) - - sudo ./lte-softmodem-stub -U --emul-iface eno1 - #we can see the incomming packets from OAI log, however, cannot see from Wireshark -> they are discarded at MAC layer - - ./vencore_app #we can see the packets appearing in Wireshark - - -------------------------------------- -TEST PC5-S (UE1 -sender, UE2 - receiver) and PC5-U for ONE-TO-ONE scenario -Configure UE1/UE2 -UE1: - - sudo ifconfig oip0 10.0.0.1 - - sudo iptables -A POSTROUTING -t mangle -o oip0 -d 10.0.0.2 -j MARK --set-mark 3 - - sudo route add default gw 10.10.10.1 eth0 -UE2: - - sudo ifconfig oip0 10.0.0.2 - - sudo iptables -A POSTROUTING -t mangle -o oip0 -d 10.0.0.1 -j MARK --set-mark 3 - - sudo route add default gw 10.10.10.1 eno1 - -step 1: -- UE1: sudo ./lte-softmodem-stub -U --emul-iface eth0 -step 2: -- UE2: sudo ./lte-softmodem-stub -U --emul-iface eno1 -- UE2: ./vencore_app -r #listen to incomming message from PC5-S -step 3: -- UE1: ./vencore_app -s #send a message via PC5-S (e.g., DirectCommunicationRequest) - -Generate unicast traffic -UE1: ping -I oip0 10.0.0.2 - - - -------------------------------------- -TEST PC5-D -step 1: -- UE1: sudo ./lte-softmodem-stub -U --emul-iface eth0 -- UE1: ./vencore_app -d #send a PC5-Discovery-Announcement via PC5D -step 2: -- UE2: sudo ./lte-softmodem-stub -U --emul-iface eno1 -- UE2: ./vencore_app -d #send a PC5-Discovery-Announcement via PC5D - From 8fcea7c314f02b517e27bfaaa2ec89bd5a3b3fc5 Mon Sep 17 00:00:00 2001 From: calvin_peyron Date: Fri, 12 Sep 2025 14:40:19 +0200 Subject: [PATCH 891/964] Update UL_MIMO documentation --- doc/UL_MIMO.md | 88 +++++++++++++++++++++++++++++++++++++++++++++++++ doc/UL_MIMO.txt | 31 ----------------- 2 files changed, 88 insertions(+), 31 deletions(-) create mode 100644 doc/UL_MIMO.md delete mode 100644 doc/UL_MIMO.txt diff --git a/doc/UL_MIMO.md b/doc/UL_MIMO.md new file mode 100644 index 0000000000..6adf5f2790 --- /dev/null +++ b/doc/UL_MIMO.md @@ -0,0 +1,88 @@ +# UpLink Multiple Input Multiple Output (UL MIMO) +## What is UL MIMO ? + +UpLink MIMO refers to the use of multiple antennas at both the UE (User Equipment) as transmitter and the base station as receiver. They are used to send multiple data streams simultaneously from the user to the network. + +## How to use it ? + +## Step 1: build phy sim + +```bash +cd cmake_targets/ +sudo ./build_oai --phy_simulators -c +cd phy_simulators/build/ +``` + +## Step 2: Use the sim + +### Option 1: launch ULSCH sim +On UpLink Shared CHannel(ULSCH), multiple users share the same radio resources (time and frequency slots), the base station schedules and assigns the resources dynamically. The goal here is to simulate the sending of data from an UE to a base station. + +Example: +| Parameter | Value | Description | +|--- |:-: |--: | +| R | 106 | R_NB_UL=106| +| m | 9 | MCS=9 | +| s | 13 | Start SNR | +| n | 100 | Will simulate 100 frames | +| y | 4 | 4 antennas used in eNB | +| z | 4 | 4 antennas used in UE | +| W | 4 | Will use 4 layers | + + +```bash +sudo ./nr_ulschsim -R 106 -m9 -s13 -n100 -y4 -z4 -W4 +``` + +### Option 2: launch UL sim +On UpLink Channel, a single user is dealing with a single base station. The goal is here to simulate the sending of the data from an UE to a base station. + +It's focusing on: +- UpLink chain validation +- PUSCH (whole chain) on UE side and gNB side +- No channel model on data domain signal, which means an ideal scenario is used +- No cross-path connection, which means no signal leakage or interference are present +- PMI = 0 is only unitary precoding matrix + +The same parameters are used. + +```bash +sudo ./nr_ulsim -n100 -m9 -r106 -s13 -W4 -y4 -z4 +``` +### Option 3: Use RFSIM + +#### Build + +RF simulator allows to test OAI without an RF board. It replaces an actual RF board driver. + +```bash +sudo ./build_oai -c --gNB --nrUE -w SIMU +``` + +#### Run +##### 4x4 RANK 4 + +Example: +| Parameter | Value | Description | +|--- |:-: |--: | +| O | [...] | Use a configuration file | +| l | 2 | Set the number of layers for downlink to 2 for PHY test mode | +| L | 4 | Set the number of layers for uplink to 4 for PHY test mode | +| ue-nb-ant-rx | 4 | Set UE number of rx antennas to 4 | +| ue-nb-ant-tx | 4 | Set UE number of tx antennas to 4 | + +```bash +sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.4layer.conf --rfsim --phy-test --l 2 --L 4 +sudo ./nr-uesoftmodem --rfsim --phy-test --ue-nb-ant-rx 4 --ue-nb-ant-tx 4 +``` + +##### 4x4 RANK 2 + +The same parameters are used excepted uplink number of layers set to 2. + +```bash +sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.4layer.conf --rfsim --phy-test --l 2 --L 2 +sudo ./nr-uesoftmodem --rfsim --phy-test --ue-nb-ant-rx 4 --ue-nb-ant-tx 4 +``` + + diff --git a/doc/UL_MIMO.txt b/doc/UL_MIMO.txt deleted file mode 100644 index c06bc78c4c..0000000000 --- a/doc/UL_MIMO.txt +++ /dev/null @@ -1,31 +0,0 @@ -# how to build phy sim -cd cmake_targets/ -sudo ./build_oai --phy_simulators -c - -cd phy_simulators/build/ -# ULSCH sim -# bit level validation -# PUSCH encoding and decoding for 4 layers 2 CMD without data -sudo ./nr_ulschsim -R 106 -m9 -s13 -n100 -y4 -z4 -W4 - -# UL sim -# Uplink chain validation -# PUSCH on UE side and gNB side,whole chain for PUSCH -# No channel model on data domain signal -# No cross-path connection -# PMI = 0 is only unitary prcoding matrix -sudo ./nr_ulsim -n100 -m9 -r106 -s13 -W4 -y4 -z4 - -# How to build rfsim -sudo ./build_oai -c --gNB --nrUE -w SIMU - -# How to run with rfsim -# 4x4 RANK 4 -sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.4layer.conf --rfsim --phy-test --l 2 --L 4 -sudo ./nr-uesoftmodem --rfsim --phy-test --ue-nb-ant-rx 4 --ue-nb-ant-tx 4 -# 4x4 RANK 2 -sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.4layer.conf --rfsim --phy-test --l 2 --L 2 -sudo ./nr-uesoftmodem --rfsim --phy-test --ue-nb-ant-rx 4 --ue-nb-ant-tx 4 - - - From 7eb33a4003c202ff410f0f80a4cd5fa4f44d778a Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 1 Oct 2025 22:13:48 +0200 Subject: [PATCH 892/964] Workaround: give pod deployment more time pods deployed through helm occasionally take more time, leading to errors such as Error from server (BadRequest): container "physim" in pod "oai-physims-4g-sczvl" is waiting to start: ContainerCreating Give a bit more time before checking the logs. We cannot wait too much, as the container will just end on FINISHED in running state, so the logs will always be there. --- ci-scripts/scripts/oc-deploy-physims.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci-scripts/scripts/oc-deploy-physims.sh b/ci-scripts/scripts/oc-deploy-physims.sh index c209be485b..19c1940ba1 100755 --- a/ci-scripts/scripts/oc-deploy-physims.sh +++ b/ci-scripts/scripts/oc-deploy-physims.sh @@ -15,7 +15,7 @@ oc project ${OC_NS} > /dev/null oc tag oaicicd-ran/oai-physim:${IMG_TAG} ${OC_NS}/oai-physim:${IMG_TAG} helm install ${OC_RELEASE} ${OAI_DIR}/charts/${OC_RELEASE} --set global.image.version=${IMG_TAG} --wait --timeout 120s POD_ID=$(oc get pods | grep oai-${OC_RELEASE} | awk '{print $1}') -sleep 10 +sleep 30 echo "Monitoring logs for 'FINISHED' in pod '$POD_ID'" oc logs -f -n ${OC_NS} "$POD_ID" | while read -r line; do if [[ "$line" == *"FINISHED"* ]]; then From 799934024e5fd406ac44d4d1d324fe3715b6ecb9 Mon Sep 17 00:00:00 2001 From: rmagueta Date: Wed, 4 Jun 2025 14:36:53 +0100 Subject: [PATCH 893/964] SRS-based noise calculation using holes --- .../NR_ESTIMATION/nr_ul_channel_estimation.c | 162 ++++++++---------- openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h | 1 + .../PHY/NR_TRANSPORT/nr_transport_proto.h | 3 +- openair1/PHY/NR_TRANSPORT/srs_rx.c | 48 +++--- openair1/PHY/TOOLS/tools_defs.h | 9 + .../PHY/nr_phy_common/src/nr_phy_common_srs.c | 7 +- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 8 +- openair1/SIMULATION/NR_PHY/ulsim.c | 12 +- 8 files changed, 124 insertions(+), 126 deletions(-) diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c index 7ec67ffbc5..77c6429b5c 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c @@ -777,6 +777,7 @@ int nr_srs_channel_estimation( const nr_srs_info_t *nr_srs_info, const c16_t **srs_generated_signal, c16_t srs_received_signal[][gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)], + c16_t srs_received_noise[][gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)], c16_t srs_estimated_channel_freq[][1 << srs_pdu->num_ant_ports] [gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)], c16_t srs_estimated_channel_time[][1 << srs_pdu->num_ant_ports][gNB->frame_parms.ofdm_symbol_size], @@ -801,16 +802,6 @@ int nr_srs_channel_estimation( } c16_t srs_ls_estimated_channel[frame_parms->ofdm_symbol_size * (1 << srs_pdu->num_symbols)]; - uint32_t noise_power_per_rb[srs_pdu->bwp_size]; - - const uint32_t arr_len = frame_parms->nb_antennas_rx * N_ap * M_sc_b_SRS; - - c16_t ch[arr_len]; - memset(ch, 0, arr_len * sizeof(c16_t)); - - c16_t noise[arr_len]; - memset(noise, 0, arr_len * sizeof(c16_t)); - uint8_t mem_offset = ((16 - ((intptr_t)&srs_estimated_channel_freq[0][0][subcarrier_offset + nr_srs_info->k_0_p[0][0]])) & 0xF) >> 2; // >> 2 <=> /sizeof(int32_t) @@ -831,7 +822,7 @@ int nr_srs_channel_estimation( #endif uint16_t subcarrier = subcarrier_offset + nr_srs_info->k_0_p[p_index][0]; - if (subcarrier > frame_parms->ofdm_symbol_size) { + if (subcarrier >= frame_parms->ofdm_symbol_size) { subcarrier -= frame_parms->ofdm_symbol_size; } @@ -843,19 +834,12 @@ int nr_srs_channel_estimation( uint16_t subcarrier_cdm = subcarrier; for (int cdm_idx = 0; cdm_idx < fd_cdm; cdm_idx++) { - int16_t generated_real = srs_generated_signal[p_index][subcarrier_cdm].r; - int16_t generated_imag = srs_generated_signal[p_index][subcarrier_cdm].i; - - int16_t received_real = srs_received_signal[ant][subcarrier_cdm].r; - int16_t received_imag = srs_received_signal[ant][subcarrier_cdm].i; - - // We know that nr_srs_info->srs_generated_signal_bits bits are enough to represent the generated_real and - // generated_imag. So we only need a nr_srs_info->srs_generated_signal_bits shift to ensure that the result fits into 16 + c16_t generated_srs = srs_generated_signal[p_index][subcarrier_cdm]; + c16_t received_srs = srs_received_signal[ant][subcarrier_cdm]; + // We know that nr_srs_info->srs_generated_signal_bits bits are enough to represent the real and imaginary parts of + // generated_srs. So we only need a nr_srs_info->srs_generated_signal_bits shift to ensure that the result fits into 16 // bits. - ls_estimated.r += (int16_t)(((int32_t)generated_real * received_real + (int32_t)generated_imag * received_imag) - >> nr_srs_info->srs_generated_signal_bits); - ls_estimated.i += (int16_t)(((int32_t)generated_real * received_imag - (int32_t)generated_imag * received_real) - >> nr_srs_info->srs_generated_signal_bits); + ls_estimated = c16maddConjShift(generated_srs, received_srs, ls_estimated, nr_srs_info->srs_generated_signal_bits); // Subcarrier increment subcarrier_cdm += K_TC; @@ -934,7 +918,7 @@ int nr_srs_channel_estimation( // Subcarrier increment subcarrier += K_TC; if (subcarrier >= frame_parms->ofdm_symbol_size) { - subcarrier = subcarrier - frame_parms->ofdm_symbol_size; + subcarrier -= frame_parms->ofdm_symbol_size; } } // for (int k = 0; k < M_sc_b_SRS; k++) @@ -943,25 +927,9 @@ int nr_srs_channel_estimation( &srs_est[mem_offset], (frame_parms->ofdm_symbol_size * (1 << srs_pdu->num_symbols)) * sizeof(c16_t)); - // Compute noise - subcarrier = subcarrier_offset + nr_srs_info->k_0_p[p_index][0]; - if (subcarrier > frame_parms->ofdm_symbol_size) { - subcarrier -= frame_parms->ofdm_symbol_size; - } - uint16_t base_idx = ant * N_ap * M_sc_b_SRS + p_index * M_sc_b_SRS; - for (int k = 0; k < M_sc_b_SRS; k++) { - ch[base_idx + k] = srs_estimated_channel_freq[ant][p_index][subcarrier]; - noise[base_idx + k].r = abs(srs_ls_estimated_channel[subcarrier].r - ch[base_idx + k].r); - noise[base_idx + k].i = abs(srs_ls_estimated_channel[subcarrier].i - ch[base_idx + k].i); - subcarrier += K_TC; - if (subcarrier >= frame_parms->ofdm_symbol_size) { - subcarrier = subcarrier - frame_parms->ofdm_symbol_size; - } - } - #ifdef SRS_DEBUG subcarrier = subcarrier_offset + nr_srs_info->k_0_p[p_index][0]; - if (subcarrier > frame_parms->ofdm_symbol_size) { + if (subcarrier >= frame_parms->ofdm_symbol_size) { subcarrier -= frame_parms->ofdm_symbol_size; } @@ -983,13 +951,13 @@ int nr_srs_channel_estimation( srs_ls_estimated_channel[subcarrier].i, srs_estimated_channel_freq[ant][p_index][subcarrier].r, srs_estimated_channel_freq[ant][p_index][subcarrier].i, - noise[base_idx + (k / K_TC)].r, - noise[base_idx + (k / K_TC)].i); + srs_received_noise[ant][subcarrier].r, + srs_received_noise[ant][subcarrier].i); // Subcarrier increment subcarrier++; if (subcarrier >= frame_parms->ofdm_symbol_size) { - subcarrier = subcarrier - frame_parms->ofdm_symbol_size; + subcarrier -= frame_parms->ofdm_symbol_size; } } #endif @@ -1010,61 +978,71 @@ int nr_srs_channel_estimation( } // for (int p_index = 0; p_index < N_ap; p_index++) } // for (int ant = 0; ant < frame_parms->nb_antennas_rx; ant++) - // Compute signal power - uint32_t signal_power = max(signal_energy_nodc(ch, arr_len), 1); - -#ifdef SRS_DEBUG - LOG_I(NR_PHY, "signal_power = %u\n", signal_power); -#endif - + // Compute wideband SNR + int tot_subcarriers = m_SRS_b * NR_NB_SC_PER_RB; + uint32_t signal_power = 0; + uint32_t noise_power = 0; + for (int ant = 0; ant < frame_parms->nb_antennas_rx; ant++) { + for (int p_index = 0; p_index < N_ap; p_index++) { + uint16_t subcarrier0 = subcarrier_offset + nr_srs_info->k_0_p[p_index][0]; + if (subcarrier0 >= frame_parms->ofdm_symbol_size) { + subcarrier0 -= frame_parms->ofdm_symbol_size; + } + if (subcarrier0 + tot_subcarriers < frame_parms->ofdm_symbol_size) { + signal_power += signal_energy_nodc(&srs_estimated_channel_freq[ant][p_index][subcarrier0], tot_subcarriers); + if (p_index == 0) + noise_power += signal_energy_nodc(&srs_received_noise[ant][subcarrier0], tot_subcarriers); + } else { + int size1 = frame_parms->ofdm_symbol_size - subcarrier0; + int size2 = tot_subcarriers - size1; + uint64_t signal_power_p1 = signal_energy_nodc(&srs_estimated_channel_freq[ant][p_index][subcarrier0], size1) * size1; + uint64_t signal_power_p2 = signal_energy_nodc(&srs_estimated_channel_freq[ant][p_index][0], size2) * size2; + signal_power += (signal_power_p1 + signal_power_p2) / tot_subcarriers; + if (p_index == 0) { + uint64_t noise_power_p1 = signal_energy_nodc(&srs_received_noise[ant][subcarrier0], size1) * size1; + uint64_t noise_power_p2 = signal_energy_nodc(&srs_received_noise[ant][0], size2) * size2; + noise_power += (noise_power_p1 + noise_power_p2) / tot_subcarriers; + } + } + } + } + signal_power = max(signal_power / (frame_parms->nb_antennas_rx * N_ap), 1); + noise_power = max(noise_power / (frame_parms->nb_antennas_rx), 1); if (signal_power == 0) { LOG_W(NR_PHY, "Received SRS signal power is 0\n"); return -1; } - - // Compute noise power - const uint8_t srs_symbols_per_rb = srs_pdu->comb_size == 0 ? 6 : 3; - const uint8_t n_noise_est = frame_parms->nb_antennas_rx * N_ap * srs_symbols_per_rb; - uint64_t sum_re = 0; - uint64_t sum_re2 = 0; - uint64_t sum_im = 0; - uint64_t sum_im2 = 0; - - for (int rb = 0; rb < m_SRS_b; rb++) { - sum_re = 0; - sum_re2 = 0; - sum_im = 0; - sum_im2 = 0; - - for (int ant = 0; ant < frame_parms->nb_antennas_rx; ant++) { - for (int p_index = 0; p_index < N_ap; p_index++) { - uint16_t base_idx = ant * N_ap * M_sc_b_SRS + p_index * M_sc_b_SRS + rb * srs_symbols_per_rb; - for (int srs_symb = 0; srs_symb < srs_symbols_per_rb; srs_symb++) { - sum_re = sum_re + noise[base_idx + srs_symb].r; - sum_re2 = sum_re2 + noise[base_idx + srs_symb].r * noise[base_idx + srs_symb].r; - sum_im = sum_im + noise[base_idx + srs_symb].i; - sum_im2 = sum_im2 + noise[base_idx + srs_symb].i * noise[base_idx + srs_symb].i; - } // for (int srs_symb = 0; srs_symb < srs_symbols_per_rb; srs_symb++) - } // for (int p_index = 0; p_index < N_ap; p_index++) - } // for (int ant = 0; ant < frame_parms->nb_antennas_rx; ant++) - - noise_power_per_rb[rb] = max(sum_re2 / n_noise_est - (sum_re / n_noise_est) * (sum_re / n_noise_est) + sum_im2 / n_noise_est - - (sum_im / n_noise_est) * (sum_im / n_noise_est), - 1); - snr_per_rb[rb] = dB_fixed(signal_power) - dB_fixed(noise_power_per_rb[rb]); - -#ifdef SRS_DEBUG - LOG_I(NR_PHY, "noise_power_per_rb[%i] = %i, snr_per_rb[%i] = %i dB\n", rb, noise_power_per_rb[rb], rb, snr_per_rb[rb]); -#endif - - } // for (int rb = 0; rb < m_SRS_b; rb++) - - const uint32_t noise_power = max(signal_energy_nodc(noise, arr_len), 1); - *snr = dB_fixed(signal_power) - dB_fixed(noise_power); + // Compute SNR per RB + uint16_t subcarrier = subcarrier_offset + nr_srs_info->k_0_p[0][0]; + for (int rb = 0; rb < m_SRS_b; rb++) { + if (subcarrier >= frame_parms->ofdm_symbol_size) { + subcarrier -= frame_parms->ofdm_symbol_size; + } + uint32_t noise_power_per_rb = 0; + for (int ant = 0; ant < frame_parms->nb_antennas_rx; ant++) { + if (subcarrier + NR_NB_SC_PER_RB < frame_parms->ofdm_symbol_size) { + noise_power_per_rb += signal_energy_nodc(&srs_received_noise[ant][subcarrier], NR_NB_SC_PER_RB); + } else { + int size1 = frame_parms->ofdm_symbol_size - subcarrier; + int size2 = NR_NB_SC_PER_RB - size1; + uint32_t noise_power_per_rb1 = signal_energy_nodc(&srs_received_noise[ant][subcarrier], size1) * size1; + uint32_t noise_power_per_rb2 = signal_energy_nodc(&srs_received_noise[ant][0], size2) * size2; + noise_power_per_rb += (noise_power_per_rb1 + noise_power_per_rb2) / NR_NB_SC_PER_RB; + } + } + noise_power_per_rb = max(noise_power_per_rb / (frame_parms->nb_antennas_rx), 1); + snr_per_rb[rb] = dB_fixed(signal_power) - dB_fixed(noise_power_per_rb); + subcarrier += NR_NB_SC_PER_RB; + #ifdef SRS_DEBUG - LOG_I(NR_PHY, "noise_power = %u, SNR = %i dB\n", noise_power, *snr); + LOG_I(NR_PHY, "[RB %3i] noise_power_per_rb = %i, snr_per_rb = %i dB\n", rb, noise_power_per_rb, snr_per_rb[rb]); +#endif + } + +#ifdef SRS_DEBUG + LOG_I(NR_PHY, "signal_power = %i dB, noise_power = %i dB, SNR = %i dB\n", dB_fixed(signal_power), dB_fixed(noise_power), *snr); #endif return 0; diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h index 203021101c..6451de12dd 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h @@ -84,6 +84,7 @@ int nr_srs_channel_estimation( const nr_srs_info_t *nr_srs_info, const c16_t **srs_generated_signal, c16_t srs_received_signal[][gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)], + c16_t srs_received_noise[][gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)], c16_t srs_estimated_channel_freq[][1 << srs_pdu->num_ant_ports] [gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)], c16_t srs_estimated_channel_time[][1 << srs_pdu->num_ant_ports][gNB->frame_parms.ofdm_symbol_size], diff --git a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h index 1aabf118ef..a7769dc84d 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h +++ b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h @@ -242,7 +242,8 @@ int nr_get_srs_signal(PHY_VARS_gNB *gNB, slot_t slot, nfapi_nr_srs_pdu_t *srs_pdu, nr_srs_info_t *nr_srs_info, - c16_t srs_received_signal[][gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)]); + c16_t srs_received_signal[][gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)], + c16_t srs_received_noise[][gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)]); void init_prach_list(PHY_VARS_gNB *gNB); void init_prach_ru_list(RU_t *ru); diff --git a/openair1/PHY/NR_TRANSPORT/srs_rx.c b/openair1/PHY/NR_TRANSPORT/srs_rx.c index bab88344de..3da018bf84 100644 --- a/openair1/PHY/NR_TRANSPORT/srs_rx.c +++ b/openair1/PHY/NR_TRANSPORT/srs_rx.c @@ -79,59 +79,67 @@ int nr_get_srs_signal(PHY_VARS_gNB *gNB, slot_t slot, nfapi_nr_srs_pdu_t *srs_pdu, nr_srs_info_t *nr_srs_info, - c16_t srs_received_signal[][gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)]) + c16_t srs_received_signal[][gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)], + c16_t srs_received_noise[][gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)]) { const NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; const uint16_t n_symbols = (slot % RU_RX_SLOT_DEPTH) * frame_parms->symbols_per_slot; // number of symbols until this slot - const uint8_t l0 = srs_pdu->time_start_position; // starting symbol in this slot + const uint8_t l0 = srs_pdu->time_start_position; // starting symbol in this slot const uint64_t symbol_offset = (n_symbols + l0) * frame_parms->ofdm_symbol_size; - const uint64_t subcarrier_offset = frame_parms->first_carrier_offset + srs_pdu->bwp_start*NR_NB_SC_PER_RB; + const uint64_t subcarrier_offset = frame_parms->first_carrier_offset + srs_pdu->bwp_start * NR_NB_SC_PER_RB; - const uint8_t N_ap = 1<num_ant_ports; + const uint8_t N_ap = 1 << srs_pdu->num_ant_ports; const uint8_t N_symb_SRS = 1 << srs_pdu->num_symbols; const uint8_t K_TC = 2 << srs_pdu->comb_size; const uint16_t M_sc_b_SRS = get_m_srs(srs_pdu->config_index, srs_pdu->bandwidth_index) * NR_NB_SC_PER_RB / K_TC; - c16_t *rx_signal; bool no_srs_signal = true; for (int ant = 0; ant < frame_parms->nb_antennas_rx; ant++) { memset(srs_received_signal[ant], 0, frame_parms->ofdm_symbol_size * sizeof(c16_t)); - rx_signal = &rxdataF[ant][symbol_offset]; + memset(srs_received_noise[ant], 0, frame_parms->ofdm_symbol_size * sizeof(c16_t)); + c16_t *rx_signal = &rxdataF[ant][symbol_offset]; for (int p_index = 0; p_index < N_ap; p_index++) { - #ifdef SRS_DEBUG - LOG_I(NR_PHY,"===== UE port %d --> gNB Rx antenna %i =====\n", p_index, ant); + LOG_I(NR_PHY, "===== UE port %d --> gNB Rx antenna %i =====\n", p_index, ant); #endif for (int l_line = 0; l_line < N_symb_SRS; l_line++) { - #ifdef SRS_DEBUG - LOG_I(NR_PHY,":::::::: OFDM symbol %d ::::::::\n", l0+l_line); + LOG_I(NR_PHY, ":::::::: OFDM symbol %d ::::::::\n", l0 + l_line); #endif uint16_t subcarrier = subcarrier_offset + nr_srs_info->k_0_p[p_index][l_line]; - if (subcarrier>frame_parms->ofdm_symbol_size) { + if (subcarrier >= frame_parms->ofdm_symbol_size) { subcarrier -= frame_parms->ofdm_symbol_size; } - uint16_t l_line_offset = l_line*frame_parms->ofdm_symbol_size; + uint16_t l_line_offset = l_line * frame_parms->ofdm_symbol_size; for (int k = 0; k < M_sc_b_SRS; k++) { - - srs_received_signal[ant][l_line_offset+subcarrier] = rx_signal[l_line_offset+subcarrier]; - + // Subcarriers with SRS symbols + srs_received_signal[ant][l_line_offset + subcarrier] = rx_signal[l_line_offset + subcarrier]; if (rx_signal[l_line_offset + subcarrier].r || rx_signal[l_line_offset + subcarrier].i) { no_srs_signal = false; } + // Subcarriers without SRS symbols and only noise + srs_received_noise[ant][l_line_offset + subcarrier] = rx_signal[l_line_offset + subcarrier + 1]; + for (int n = 1; n < K_TC; n++) { + uint16_t subcarrier_n = subcarrier + n; + if (subcarrier_n >= frame_parms->ofdm_symbol_size) { + subcarrier_n -= frame_parms->ofdm_symbol_size; + } + srs_received_noise[ant][l_line_offset + subcarrier_n] = rx_signal[l_line_offset + subcarrier_n]; + } + #ifdef SRS_DEBUG - int subcarrier_log = subcarrier-subcarrier_offset; - if(subcarrier_log < 0) { + int subcarrier_log = subcarrier - subcarrier_offset; + if (subcarrier_log < 0) { subcarrier_log = subcarrier_log + frame_parms->ofdm_symbol_size; } - if(subcarrier_log%12 == 0) { - LOG_I(NR_PHY,"------------ %d ------------\n", subcarrier_log/12); + if (subcarrier_log % 12 == 0) { + LOG_I(NR_PHY, "------------ %d ------------\n", subcarrier_log / 12); } LOG_I(NR_PHY, "(%i) \t%i\t%i\n", @@ -143,7 +151,7 @@ int nr_get_srs_signal(PHY_VARS_gNB *gNB, // Subcarrier increment subcarrier += K_TC; if (subcarrier >= frame_parms->ofdm_symbol_size) { - subcarrier=subcarrier-frame_parms->ofdm_symbol_size; + subcarrier -= frame_parms->ofdm_symbol_size; } } // for (int k = 0; k < M_sc_b_SRS; k++) diff --git a/openair1/PHY/TOOLS/tools_defs.h b/openair1/PHY/TOOLS/tools_defs.h index 9ee558c72b..281d7860e8 100644 --- a/openair1/PHY/TOOLS/tools_defs.h +++ b/openair1/PHY/TOOLS/tools_defs.h @@ -219,6 +219,7 @@ extern "C" { { return (c16_t){.r = (int16_t)((a.r * b) >> Shift), .i = (int16_t)((a.i * b) >> Shift)}; } + __attribute__((always_inline)) inline c16_t c16MulConjShift(const c16_t a, const c16_t b, const int Shift) { return (c16_t) { @@ -234,6 +235,14 @@ extern "C" { }; } + __attribute__((always_inline)) inline c16_t c16maddConjShift(const c16_t a, const c16_t b, c16_t c, const int Shift) + { + return (c16_t) { + .r = (int16_t)(((a.r * b.r + a.i * b.i ) >> Shift) + c.r), + .i = (int16_t)(((a.r * b.i - a.i * b.r ) >> Shift) + c.i) + }; + } + __attribute__((always_inline)) inline c32_t c32x16mulShift(const c16_t a, const c16_t b, const int Shift) { return (c32_t) { .r = (a.r * b.r - a.i * b.i) >> Shift, diff --git a/openair1/PHY/nr_phy_common/src/nr_phy_common_srs.c b/openair1/PHY/nr_phy_common/src/nr_phy_common_srs.c index dce62add0b..ba5d792428 100644 --- a/openair1/PHY/nr_phy_common/src/nr_phy_common_srs.c +++ b/openair1/PHY/nr_phy_common/src/nr_phy_common_srs.c @@ -304,7 +304,7 @@ bool generate_srs_nr(NR_DL_FRAME_PARMS *frame_parms, #endif uint16_t subcarrier = subcarrier_offset + k_0_p; - if (subcarrier>frame_parms->ofdm_symbol_size) + if (subcarrier >= frame_parms->ofdm_symbol_size) subcarrier -= frame_parms->ofdm_symbol_size; uint16_t l_line_offset = l_line * frame_parms->ofdm_symbol_size; // For each port, and for each OFDM symbol, here it is computed and mapped an SRS sequence with M_sc_b_SRS symbols @@ -333,9 +333,8 @@ bool generate_srs_nr(NR_DL_FRAME_PARMS *frame_parms, // Subcarrier increment subcarrier += K_TC; - if (subcarrier >= frame_parms->ofdm_symbol_size) { - subcarrier=subcarrier-frame_parms->ofdm_symbol_size; - } + if (subcarrier >= frame_parms->ofdm_symbol_size) + subcarrier -= frame_parms->ofdm_symbol_size; } // for (int k = 0; k < M_sc_b_SRS; k++) } // for (int l_line = 0; l_line < N_symb_SRS; l_line++) diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 406fcc8038..0cb9d8d4fd 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -750,7 +750,7 @@ int fill_srs_channel_matrix(uint8_t *channel_matrix, for(int gI = 0; gI < num_gnb_antenna_elements; gI++) { uint16_t subcarrier = subcarrier_offset + nr_srs_info->k_0_p[uI][0]; - if (subcarrier>frame_parms->ofdm_symbol_size) { + if (subcarrier >= frame_parms->ofdm_symbol_size) { subcarrier -= frame_parms->ofdm_symbol_size; } @@ -769,7 +769,7 @@ int fill_srs_channel_matrix(uint8_t *channel_matrix, // Subcarrier increment subcarrier += step; if (subcarrier >= frame_parms->ofdm_symbol_size) { - subcarrier=subcarrier-frame_parms->ofdm_symbol_size; + subcarrier -= frame_parms->ofdm_symbol_size; } } } @@ -1045,6 +1045,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N nfapi_nr_srs_pdu_t *srs_pdu = &srs->srs_pdu; uint8_t N_symb_SRS = 1 << srs_pdu->num_symbols; c16_t srs_received_signal[frame_parms->nb_antennas_rx][frame_parms->ofdm_symbol_size * N_symb_SRS]; + c16_t srs_received_noise[frame_parms->nb_antennas_rx][frame_parms->ofdm_symbol_size * N_symb_SRS]; c16_t srs_estimated_channel_freq[frame_parms->nb_antennas_rx][1 << srs_pdu->num_ant_ports] [frame_parms->ofdm_symbol_size * N_symb_SRS] __attribute__((aligned(32))); c16_t srs_estimated_channel_time[frame_parms->nb_antennas_rx][1 << srs_pdu->num_ant_ports][frame_parms->ofdm_symbol_size] @@ -1068,7 +1069,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N stop_meas(&gNB->generate_srs_stats); c16_t **rxdataF = gNB->common_vars.rxdataF[srs->beam_nb]; start_meas(&gNB->get_srs_signal_stats); - int srs_est = nr_get_srs_signal(gNB, rxdataF, frame_rx, slot_rx, srs_pdu, gNB->nr_srs_info[i], srs_received_signal); + int srs_est = nr_get_srs_signal(gNB, rxdataF, frame_rx, slot_rx, srs_pdu, gNB->nr_srs_info[i], srs_received_signal, srs_received_noise); stop_meas(&gNB->get_srs_signal_stats); if (srs_est >= 0) { @@ -1080,6 +1081,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N gNB->nr_srs_info[i], (const c16_t**)gNB->nr_srs_info[i]->srs_generated_signal, srs_received_signal, + srs_received_noise, srs_estimated_channel_freq, srs_estimated_channel_time, srs_estimated_channel_time_shifted, diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index edab935e15..93789ba737 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -1733,7 +1733,12 @@ int main(int argc, char *argv[]) if (print_perf==1) { - printf("gNB RX\n"); + printf("UE TX\n"); + for (int i = PHY_PROC_TX; i <= OFDM_MOD_STATS; i++) { + printStatIndent(&UE->phy_cpu_stats.cpu_time_stats[i], UE->phy_cpu_stats.cpu_time_stats[i].meas_name); + } + + printf("\ngNB RX\n"); printDistribution(&gNB->phy_proc_rx,table_rx, "Total PHY proc rx"); printStatIndent(&gNB->rx_pusch_stats, "RX PUSCH time"); printStatIndent2(&gNB->ulsch_channel_estimation_stats, "ULSCH channel estimation time"); @@ -1744,11 +1749,6 @@ int main(int argc, char *argv[]) printStatIndent2(&gNB->ts_deinterleave, "ULSCH segment deinterleaving time"); printStatIndent2(&gNB->ts_rate_unmatch, "ULSCH segment rate recovery time"); printStatIndent2(&gNB->ts_ldpc_decode, "ULSCH segments decoding time"); - - printf("\nUE TX\n"); - for (int i = PHY_PROC_TX; i <= OFDM_MOD_STATS; i++) { - printStatIndent(&UE->phy_cpu_stats.cpu_time_stats[i], UE->phy_cpu_stats.cpu_time_stats[i].meas_name); - } printStatIndent(&gNB->rx_srs_stats,"RX SRS time"); printStatIndent2(&gNB->generate_srs_stats,"Generate SRS sequence time"); printStatIndent2(&gNB->get_srs_signal_stats,"Get SRS signal time"); From 8ca05e51ac94d6aadfdf7186e5e9b7194c75bf51 Mon Sep 17 00:00:00 2001 From: rmagueta Date: Tue, 10 Jun 2025 14:44:20 +0100 Subject: [PATCH 894/964] Added graph in T_Tracer to observe UL-SNR calculated using SRS --- common/utils/T/T_messages.txt | 4 +++ common/utils/T/tracer/gnb.c | 24 +++++++++++++- common/utils/T/tracer/logger/framelog.c | 32 ++++++++++++++++--- common/utils/T/tracer/logger/logger.h | 1 + .../NR_ESTIMATION/nr_ul_channel_estimation.c | 2 +- openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h | 2 +- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 12 +++++-- 7 files changed, 67 insertions(+), 10 deletions(-) diff --git a/common/utils/T/T_messages.txt b/common/utils/T/T_messages.txt index 8dd5052714..2f17b62ea5 100644 --- a/common/utils/T/T_messages.txt +++ b/common/utils/T/T_messages.txt @@ -143,6 +143,10 @@ ID = GNB_PHY_UL_TIME_CHANNEL_ESTIMATE DESC = gNodeB channel estimation in the time domain GROUP = ALL:PHY:GRAPHIC:HEAVY:GNB FORMAT = int,gNB_ID : int,rnti : int,frame : int,subframe : int,antenna : buffer,chest_t +ID = GNB_PHY_UL_SNR_ESTIMATE + DESC = gNodeB SNR estimation based on SRS + GROUP = ALL:PHY:GRAPHIC:HEAVY:GNB + FORMAT = int,gNB_ID : int,rnti : int,frame : int,subframe : int,antenna : buffer,snr ID = GNB_PHY_PRACH_INPUT_SIGNAL DESC = gNodeB input data in the time domain for slots with PRACH detection GROUP = ALL:PHY:GRAPHIC:HEAVY:GNB diff --git a/common/utils/T/tracer/gnb.c b/common/utils/T/tracer/gnb.c index 22567492f8..d47f627341 100644 --- a/common/utils/T/tracer/gnb.c +++ b/common/utils/T/tracer/gnb.c @@ -19,6 +19,7 @@ typedef struct { widget *pucch_pusch_iq_plot; widget *ul_freq_estimate_ue_xy_plot; widget *ul_time_estimate_ue_xy_plot; + widget *ul_snr_estimate_ue_xy_plot; widget *current_ue_label; widget *current_ue_button; widget *prev_ue_button; @@ -26,6 +27,7 @@ typedef struct { logger *pucch_pusch_iq_logger; logger *ul_freq_estimate_ue_logger; logger *ul_time_estimate_ue_logger; + logger *ul_snr_ue_logger; } gnb_gui; typedef struct { @@ -98,6 +100,9 @@ static void set_current_ue(gui *g, gnb_data *e, int ue) sprintf(s, "UL channel estimation in time domain [UE %d]", ue); xy_plot_set_title(g, e->e->ul_time_estimate_ue_xy_plot, s); + + sprintf(s, "UL SNR per RB based on SRS [UE %d]", ue); + xy_plot_set_title(g, e->e->ul_snr_estimate_ue_xy_plot, s); } void reset_ue_ids(void) @@ -146,12 +151,13 @@ static void gnb_main_gui(gnb_gui *e, gui *g, event_handler *h, void *database, g logger *l; view *v; - main_window = new_toplevel_window(g, 1500, 230, "gNB tracer"); + main_window = new_toplevel_window(g, 1500, 460, "gNB tracer"); top_container = new_container(g, VERTICAL); widget_add_child(g, main_window, top_container, -1); line = new_container(g, HORIZONTAL); widget_add_child(g, top_container, line, -1); + logo = new_image(g, openair_logo_png, openair_logo_png_len); /* logo + prev/next UE buttons */ @@ -206,6 +212,21 @@ static void gnb_main_gui(gnb_gui *e, gui *g, event_handler *h, void *database, g logger_add_view(l, v); e->ul_time_estimate_ue_logger = l; + line = new_container(g, HORIZONTAL); + widget_add_child(g, top_container, line, -1); + + /* UL SNR based on SRS */ + w = new_xy_plot(g, 1280, 200, "", 190); + e->ul_snr_estimate_ue_xy_plot = w; + widget_add_child(g, line, w, -1); + xy_plot_set_range(g, w, 0, 273, -10, 65); + l = new_framelog(h, database, "GNB_PHY_UL_SNR_ESTIMATE", "subframe", "snr"); + framelog_set_update_only_at_sf9(l, 0); + framelog_set_type_buffer_db(l); + v = new_view_xy(273, 10, g, w, new_color(g, "#0c0c72"), XY_LOOP_MODE); + logger_add_view(l, v); + e->ul_snr_ue_logger = l; + set_current_ue(g, ed, ed->ue); register_notifier(g, "click", e->current_ue_button, click, ed); register_notifier(g, "click", e->prev_ue_button, click, ed); @@ -251,6 +272,7 @@ int main(int n, char **v) on_off(database, "GNB_PHY_PUCCH_PUSCH_IQ", is_on, 1); on_off(database, "GNB_PHY_UL_FREQ_CHANNEL_ESTIMATE", is_on, 1); on_off(database, "GNB_PHY_UL_TIME_CHANNEL_ESTIMATE", is_on, 1); + on_off(database, "GNB_PHY_UL_SNR_ESTIMATE", is_on, 1); gnb_data.ue = 0; gnb_data.e = ⪚ diff --git a/common/utils/T/tracer/logger/framelog.c b/common/utils/T/tracer/logger/framelog.c index 45ae3e399f..040482278f 100644 --- a/common/utils/T/tracer/logger/framelog.c +++ b/common/utils/T/tracer/logger/framelog.c @@ -8,6 +8,11 @@ #include #include +typedef enum { + FRAMELOG_BUFFER, + FRAMELOG_BUFFER_dB, +} framelog_buffer_type_t; + struct framelog { struct logger common; void *database; @@ -22,6 +27,7 @@ struct framelog { int skip_current; /* internal data for the skip mechanism */ int skip_on; /* internal data for the skip mechanism */ int update_only_at_sf9; + framelog_buffer_type_t type; }; static void _event(void *p, event e) @@ -52,7 +58,10 @@ static void _event(void *p, event e) } if (l->skip_on) return; - nsamples = bsize / (2*sizeof(int16_t)); + if (l->type == FRAMELOG_BUFFER) + nsamples = bsize / (2 * sizeof(int16_t)); + else + nsamples = bsize / sizeof(int16_t); if (l->blength != nsamples * 10) { l->blength = nsamples * 10; @@ -71,10 +80,15 @@ static void _event(void *p, event e) } /* TODO: compute the LOGs in the plotter (too much useless computations) */ - for (i = 0; i < nsamples; i++) { - int I = ((int16_t *)buffer)[i*2]; - int Q = ((int16_t *)buffer)[i*2+1]; - l->buffer[subframe * nsamples + i] = 10*log10(1.0+(float)(I*I+Q*Q)); + if (l->type == FRAMELOG_BUFFER_dB) { + for (i = 0; i < nsamples; i++) + l->buffer[subframe * nsamples + i] = ((int16_t *)buffer)[i]; + } else { + for (i = 0; i < nsamples; i++) { + int I = ((int16_t *)buffer)[i * 2]; + int Q = ((int16_t *)buffer)[i * 2 + 1]; + l->buffer[subframe * nsamples + i] = 10 * log10(1.0 + (float)(I * I + Q * Q)); + } } if (l->update_only_at_sf9 == 0 || subframe == 9) @@ -132,6 +146,8 @@ logger *new_framelog(event_handler *h, void *database, abort(); } + ret->type = FRAMELOG_BUFFER; + return ret; } @@ -153,3 +169,9 @@ void framelog_set_update_only_at_sf9(logger *_this, int update_only_at_sf9) struct framelog *l = _this; l->update_only_at_sf9 = update_only_at_sf9; } + +void framelog_set_type_buffer_db(logger *_this) +{ + struct framelog *l = _this; + l->type = FRAMELOG_BUFFER_dB; +} diff --git a/common/utils/T/tracer/logger/logger.h b/common/utils/T/tracer/logger/logger.h index b78fa1b359..d8458ef104 100644 --- a/common/utils/T/tracer/logger/logger.h +++ b/common/utils/T/tracer/logger/logger.h @@ -30,6 +30,7 @@ logger *new_iqdotlog(void *event_handler, void *database, void framelog_set_skip(logger *_this, int skip_delay); void framelog_set_update_only_at_sf9(logger *_this, int update_only_at_sf9); +void framelog_set_type_buffer_db(logger *_this); void textlog_dump_buffer(logger *_this, int dump_buffer); void textlog_raw_time(logger *_this, int raw_time); diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c index 77c6429b5c..93d7feebe0 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c @@ -782,7 +782,7 @@ int nr_srs_channel_estimation( [gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)], c16_t srs_estimated_channel_time[][1 << srs_pdu->num_ant_ports][gNB->frame_parms.ofdm_symbol_size], c16_t srs_estimated_channel_time_shifted[][1 << srs_pdu->num_ant_ports][gNB->frame_parms.ofdm_symbol_size], - int8_t *snr_per_rb, + int16_t *snr_per_rb, int8_t *snr) { #ifdef SRS_DEBUG diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h index 6451de12dd..04377db1b8 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h @@ -89,7 +89,7 @@ int nr_srs_channel_estimation( [gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)], c16_t srs_estimated_channel_time[][1 << srs_pdu->num_ant_ports][gNB->frame_parms.ofdm_symbol_size], c16_t srs_estimated_channel_time_shifted[][1 << srs_pdu->num_ant_ports][gNB->frame_parms.ofdm_symbol_size], - int8_t *snr_per_rb, + int16_t *snr_per_rb, int8_t *snr); void nr_freq_equalization(NR_DL_FRAME_PARMS *frame_parms, diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 0cb9d8d4fd..51e8c771e5 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -710,7 +710,7 @@ static void fill_ul_rb_mask(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, uint32 int fill_srs_reported_symbol(nfapi_nr_srs_reported_symbol_t *reported_symbol, const nfapi_nr_srs_pdu_t *srs_pdu, const int N_RB_UL, - const int8_t *snr_per_rb, + const int16_t *snr_per_rb, const int srs_est) { reported_symbol->num_prgs = srs_pdu->beamforming.num_prgs; for (int prg_idx = 0; prg_idx < reported_symbol->num_prgs; prg_idx++) { @@ -1052,7 +1052,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N __attribute__((aligned(32))); c16_t srs_estimated_channel_time_shifted[frame_parms->nb_antennas_rx][1 << srs_pdu->num_ant_ports] [frame_parms->ofdm_symbol_size]; - int8_t snr_per_rb[srs_pdu->bwp_size]; + int16_t snr_per_rb[srs_pdu->bwp_size]; start_meas(&gNB->generate_srs_stats); @@ -1110,6 +1110,14 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N T_INT(0), T_BUFFER(srs_estimated_channel_time_shifted[0][0], frame_parms->ofdm_symbol_size * sizeof(int32_t))); + T(T_GNB_PHY_UL_SNR_ESTIMATE, + T_INT(0), + T_INT(srs_pdu->rnti), + T_INT(frame_rx), + T_INT(0), + T_INT(0), + T_BUFFER(snr_per_rb, srs_pdu->bwp_size * sizeof(int16_t))); + UL_INFO->srs_ind.sfn = frame_rx; UL_INFO->srs_ind.slot = slot_rx; From 42b6576d81fdaa2d5b9eb7e0a9d0a6df98402d53 Mon Sep 17 00:00:00 2001 From: francescomani Date: Sat, 27 Sep 2025 09:56:03 +0200 Subject: [PATCH 895/964] fix RSRP computation at UE (let the higher layers compute the index) --- common/utils/nr/nr_common.h | 2 -- .../PHY/NR_UE_ESTIMATION/nr_ue_measurements.c | 3 +- openair1/PHY/NR_UE_TRANSPORT/csi_rx.c | 2 +- .../SIMULATION/NR_PHY/nr_unitary_common.c | 2 +- openair2/COMMON/mac_messages_types.h | 2 +- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 32 ++++++++----------- openair2/RRC/NR_UE/L2_interface_ue.c | 2 +- openair2/RRC/NR_UE/L2_interface_ue.h | 2 +- openair2/RRC/NR_UE/rrc_UE.c | 4 +-- 9 files changed, 22 insertions(+), 29 deletions(-) diff --git a/common/utils/nr/nr_common.h b/common/utils/nr/nr_common.h index 67f0913dc4..08c0110721 100644 --- a/common/utils/nr/nr_common.h +++ b/common/utils/nr/nr_common.h @@ -88,8 +88,6 @@ static inline const char *rnti_types(nr_rnti_type_t rr) #define NR_NUMBER_OF_SYMBOLS_PER_SLOT_EXTENDED_CP 12 #define NR_MAX_NB_LAYERS 4 // 8 -#define BOUNDED_EVAL(a, b, c) (min(c, max(a, b))) - // Since the IQ samples are represented by SQ15 R+I (see https://en.wikipedia.org/wiki/Q_(number_format)) we need to compensate when // calcualting signal energy. Instead of shifting each sample right by 15, we can normalize the result in dB scale once its // calcualted. Signal energy is calculated using RMS^2, where each sample is squared before taking the average of the sum, therefore diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c b/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c index ff706af688..73776ebf26 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c @@ -236,11 +236,10 @@ void nr_ue_ssb_rsrp_measurements(PHY_VARS_NR_UE *ue, .gNB_index = proc->gNB_id, .meas_type = NFAPI_NR_SS_MEAS, .Nid_cell = ue->frame_parms.Nid_cell, + .rsrp_dBm = ue->measurements.ssb_rsrp_dBm[ssb_index], .ssb_index = ssb_index, .is_neighboring_cell = false, }; - int ssb_rsrp_dBm = ue->measurements.ssb_rsrp_dBm[ssb_index]; - l1_measurements.rsrp_dBm = BOUNDED_EVAL(16, ssb_rsrp_dBm + 157, 113); // TS 38.133 - Table 10.1.6.1-1 nr_downlink_indication_t dl_indication = {0}; fapi_nr_rx_indication_t rx_ind = {0}; nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, NULL); diff --git a/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c b/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c index 4ab72a13f0..c28830e4d7 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c +++ b/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c @@ -987,7 +987,7 @@ void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue, .meas_type = NFAPI_NR_CSI_MEAS, .Nid_cell = frame_parms->Nid_cell, .is_neighboring_cell = false, - .rsrp_dBm = BOUNDED_EVAL(16, rsrp_dBm + 157, 113), // TS 38.133 - Table 10.1.6.1-1 + .rsrp_dBm = rsrp_dBm, .rank_indicator = rank_indicator, .i1 = *i1, .i2 = *i2, diff --git a/openair1/SIMULATION/NR_PHY/nr_unitary_common.c b/openair1/SIMULATION/NR_PHY/nr_unitary_common.c index 585c5388e4..604e7a8c2a 100644 --- a/openair1/SIMULATION/NR_PHY/nr_unitary_common.c +++ b/openair1/SIMULATION/NR_PHY/nr_unitary_common.c @@ -184,6 +184,6 @@ void nr_mac_rrc_meas_ind_ue(module_id_t module_id, uint16_t Nid_cell, bool csi_meas, bool is_neighboring_cell, - uint8_t rsrp_dBm) + int rsrp_dBm) { } diff --git a/openair2/COMMON/mac_messages_types.h b/openair2/COMMON/mac_messages_types.h index 677e1e90b1..c5c18a12f2 100644 --- a/openair2/COMMON/mac_messages_types.h +++ b/openair2/COMMON/mac_messages_types.h @@ -146,7 +146,7 @@ typedef struct NRRrcMacSBcchDataInd_s { typedef struct NRRrcMacMeasDataInd_s { uint8_t gnb_index; - uint8_t rsrp_dBm; + int rsrp_dBm; uint16_t Nid_cell; bool is_csi_meas; bool is_neighboring_cell; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index f2f783869c..3d9d5fba43 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -139,7 +139,6 @@ static csi_payload_t get_csirs_RSRP_payload(NR_UE_MAC_INST_t *mac, struct NR_CSI_ReportConfig *csi_reportconfig, NR_CSI_ResourceConfigId_t csi_ResourceConfigId, const NR_CSI_MeasConfig_t *csi_MeasConfig); -static uint8_t get_rsrp_index(int rsrp); static uint8_t get_rsrp_diff_index(int best_rsrp, int current_rsrp); @@ -2917,6 +2916,18 @@ static int compare_ssb_rsrp(const void *a, const void *b) return mb->ssb_rsrp_dBm - ma->ssb_rsrp_dBm; } +// returns index from RSRP +// according to Table 10.1.6.1-1 in 38.133 +static uint8_t get_rsrp_index(int rsrp) +{ + int index = rsrp + 157; + if (rsrp > -44) + index = 113; + if (rsrp < -140) + index = 16; + return index; +} + static csi_payload_t get_ssb_rsrp_payload(NR_UE_MAC_INST_t *mac, struct NR_CSI_ReportConfig *csi_reportconfig, NR_CSI_ResourceConfigId_t csi_ResourceConfigId, @@ -3126,15 +3137,14 @@ static csi_payload_t get_csirs_RSRP_payload(NR_UE_MAC_INST_t *mac, } // TODO: Improvements will be needed to cri_ssbri_bitlen>0 - temp_payload = reverse_bits(mac->l1_measurements.rsrp_dBm, n_bits); // rsrp_dBm as in TS 38.133 - Table 10.1.6.1-1 + temp_payload = get_rsrp_index(mac->l1_measurements.rsrp_dBm); + temp_payload = reverse_bits(temp_payload, n_bits); LOG_D(NR_MAC, "cri_ssbri_bitlen = %d\n", cri_ssbri_bitlen); LOG_D(NR_MAC, "rsrp_bitlen = %d\n", rsrp_bitlen); LOG_D(NR_MAC, "diff_rsrp_bitlen = %d\n", diff_rsrp_bitlen); - LOG_D(NR_MAC, "n_bits = %d\n", n_bits); LOG_D(NR_MAC, "csi_part1_payload = 0x%lx\n", temp_payload); - break; } } @@ -3145,20 +3155,6 @@ static csi_payload_t get_csirs_RSRP_payload(NR_UE_MAC_INST_t *mac, return csi; } -// returns index from RSRP -// according to Table 10.1.6.1-1 in 38.133 - -static uint8_t get_rsrp_index(int rsrp) -{ - int index = rsrp + 157; - if (rsrp>-44) - index = 113; - if (rsrp<-140) - index = 16; - - return index; -} - // returns index from differential RSRP // according to Table 10.1.6.1-2 in 38.133 static uint8_t get_rsrp_diff_index(int best_rsrp, int current_rsrp) diff --git a/openair2/RRC/NR_UE/L2_interface_ue.c b/openair2/RRC/NR_UE/L2_interface_ue.c index d6bee2ab10..d1e06753b1 100644 --- a/openair2/RRC/NR_UE/L2_interface_ue.c +++ b/openair2/RRC/NR_UE/L2_interface_ue.c @@ -37,7 +37,7 @@ typedef uint32_t channel_t; -void nr_mac_rrc_meas_ind_ue(module_id_t module_id, uint32_t gNB_index, uint16_t Nid_cell, bool csi_meas, bool is_neighboring_cell, uint8_t rsrp_dBm) +void nr_mac_rrc_meas_ind_ue(module_id_t module_id, uint32_t gNB_index, uint16_t Nid_cell, bool csi_meas, bool is_neighboring_cell, int rsrp_dBm) { MessageDef *message_p = itti_alloc_new_message(TASK_MAC_UE, 0, NR_RRC_MAC_MEAS_DATA_IND); NR_RRC_MAC_MEAS_DATA_IND(message_p).gnb_index = gNB_index; diff --git a/openair2/RRC/NR_UE/L2_interface_ue.h b/openair2/RRC/NR_UE/L2_interface_ue.h index 857c110d9e..a94c96b9c7 100644 --- a/openair2/RRC/NR_UE/L2_interface_ue.h +++ b/openair2/RRC/NR_UE/L2_interface_ue.h @@ -42,7 +42,7 @@ void nr_mac_rrc_meas_ind_ue(module_id_t module_id, uint16_t Nid_cell, bool csi_meas, bool is_neighboring_cell, - uint8_t rsrp_dBm); + int rsrp_dBm); void nr_mac_rrc_inactivity_timer_ind(const module_id_t mod_id); void nr_mac_rrc_msg3_ind(const module_id_t mod_id, const int rnti, bool prepare_payload); void nr_ue_rrc_timer_trigger(int instance, int frame, int gnb_id); diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index c167982859..1e01d471d8 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -2589,14 +2589,14 @@ void *rrc_nrue(void *notUsed) NR_RRC_MAC_MEAS_DATA_IND(msg_p).is_neighboring_cell? "Neighboring cell" : "Active cell", NR_RRC_MAC_MEAS_DATA_IND(msg_p).Nid_cell, NR_RRC_MAC_MEAS_DATA_IND(msg_p).is_csi_meas ? "CSI meas" : "SSB meas", - NR_RRC_MAC_MEAS_DATA_IND(msg_p).rsrp_dBm - 157); + NR_RRC_MAC_MEAS_DATA_IND(msg_p).rsrp_dBm); rrcPerNB_t *rrcNB = rrc->perNB + NR_RRC_MAC_MEAS_DATA_IND(msg_p).gnb_index; nr_ue_meas_filtering(rrcNB, NR_RRC_MAC_MEAS_DATA_IND(msg_p).is_neighboring_cell, NR_RRC_MAC_MEAS_DATA_IND(msg_p).Nid_cell, NR_RRC_MAC_MEAS_DATA_IND(msg_p).is_csi_meas, - NR_RRC_MAC_MEAS_DATA_IND(msg_p).rsrp_dBm - 157); + NR_RRC_MAC_MEAS_DATA_IND(msg_p).rsrp_dBm); nr_ue_check_meas_report(rrc, NR_RRC_MAC_MEAS_DATA_IND(msg_p).gnb_index); break; From 7355b55ad1cb8b3bc1830fcffd4ef6392bbadd7e Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Thu, 5 Jun 2025 16:15:17 +0200 Subject: [PATCH 896/964] this MR replaces constants INT16_MIN by -INT16_MAX (so -32767) in places where it used for mathematical operations --- openair1/PHY/CODING/3gpplte_turbo_decoder.c | 3 --- .../LTE_ESTIMATION/lte_ul_channel_estimation.c | 6 +----- openair1/PHY/LTE_TRANSPORT/pucch.c | 2 +- openair1/PHY/LTE_TRANSPORT/pucch_common.c | 6 +++--- .../PHY/LTE_UE_TRANSPORT/dlsch_demodulation.c | 16 ++++++++-------- openair1/PHY/LTE_UE_TRANSPORT/drs_modulation.c | 4 ++-- openair1/PHY/TOOLS/signal_energy.c | 2 -- openair1/SCHED/sched_common_extern.h | 11 ++++++----- 8 files changed, 21 insertions(+), 29 deletions(-) diff --git a/openair1/PHY/CODING/3gpplte_turbo_decoder.c b/openair1/PHY/CODING/3gpplte_turbo_decoder.c index 52860e096f..3cc54ab0d4 100644 --- a/openair1/PHY/CODING/3gpplte_turbo_decoder.c +++ b/openair1/PHY/CODING/3gpplte_turbo_decoder.c @@ -123,9 +123,6 @@ typedef char Binary; typedef short llr_t; // internal decoder data is 16-bit fixed typedef short channel_t; -#define LLR_MAX 32767 -#define LLR_MIN -32768 -#define LLRTOT 16 #define MAX 32767//16383 #define FRAME_LENGTH_MAX 6144 #define STATES 8 diff --git a/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c b/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c index 591c589b49..b7ad400ff1 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c @@ -526,11 +526,7 @@ int32_t lte_srs_channel_estimation(LTE_DL_FRAME_PARMS *frame_parms, //if ((1<<(sub_frame_number%T_SFC))&transmission_offset_tdd[Ssrs]) { - if (generate_srs(frame_parms, - soundingrs_ul_config_dedicated, - &srs_vars->srs[eNB_id], - 0x7FFF, - subframe)==-1) { + if (generate_srs(frame_parms, soundingrs_ul_config_dedicated, &srs_vars->srs[eNB_id], INT16_MAX, subframe) == -1) { LOG_E(PHY,"lte_srs_channel_estimation: Error in generate_srs\n"); return(-1); } diff --git a/openair1/PHY/LTE_TRANSPORT/pucch.c b/openair1/PHY/LTE_TRANSPORT/pucch.c index c8adb38f7c..c777313df0 100644 --- a/openair1/PHY/LTE_TRANSPORT/pucch.c +++ b/openair1/PHY/LTE_TRANSPORT/pucch.c @@ -764,7 +764,7 @@ uint32_t calc_pucch_1x_interference(PHY_VARS_eNB *eNB, uint8_t m,l; uint8_t n_cs,alpha_ind; int16_t tmp_re,tmp_im,W_re=0,W_im=0; - int16_t W4_nouse[4]={32767,32767,-32768,-32768}; + int16_t W4_nouse[4] = {32767, 32767, -32767, -32767}; int32_t n0_IQ[2]; double interference_power; int16_t *rxptr; diff --git a/openair1/PHY/LTE_TRANSPORT/pucch_common.c b/openair1/PHY/LTE_TRANSPORT/pucch_common.c index 932d30ed70..1722f9a22d 100644 --- a/openair1/PHY/LTE_TRANSPORT/pucch_common.c +++ b/openair1/PHY/LTE_TRANSPORT/pucch_common.c @@ -72,7 +72,7 @@ void init_ncs_cell(LTE_DL_FRAME_PARMS *frame_parms,uint8_t ncs_cell[20][7]) } } -const int16_t W4[3][4] = {{32767, 32767, 32767, 32767}, {32767, -32768, 32767, -32768}, {32767, -32768, -32768, 32767}}; +const int16_t W4[3][4] = {{32767, 32767, 32767, 32767}, {32767, -32767, 32767, -32767}, {32767, -32767, -32767, 32767}}; const int16_t W3_re[3][6] = {{32767, 32767, 32767}, {32767, -16384, -16384}, {32767, -16384, -16384}}; const int16_t W3_im[3][6] = {{0, 0, 0}, {0, 28377, -28378}, {0, -28378, 28377}}; @@ -334,8 +334,8 @@ const uint8_t chcod_tbl[128][48] = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 {0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1}}; -const int16_t alpha_re[12] = {32767, 28377, 16383, 0, -16384, -28378, -32768, -28378, -16384, -1, 16383, 28377}; -const int16_t alpha_im[12] = {0, 16383, 28377, 32767, 28377, 16383, 0, -16384, -28378, -32768, -28378, -16384}; +const int16_t alpha_re[12] = {32767, 28377, 16383, 0, -16384, -28378, -32767, -28378, -16384, -1, 16383, 28377}; +const int16_t alpha_im[12] = {0, 16383, 28377, 32767, 28377, 16383, 0, -16384, -28378, -32767, -28378, -16384}; // W5_TBL const int16_t W5_fmt3_re[5][5] = {{32767, 32767, 32767, 32767, 32767}, diff --git a/openair1/PHY/LTE_UE_TRANSPORT/dlsch_demodulation.c b/openair1/PHY/LTE_UE_TRANSPORT/dlsch_demodulation.c index ac045480da..9aa520c585 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/dlsch_demodulation.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/dlsch_demodulation.c @@ -2867,16 +2867,16 @@ void float_to_chan_est(int32_t **dl_ch_estimates_ext, for (aarx=0; aarx=1) - imag = 0x7FFF; + imag = INT16_MAX; else imag = cimag(dl_ch_estimates_ext_f[aatx*n_rx + aarx][re])*32768; if (creal(dl_ch_estimates_ext_f[aatx*n_rx + aarx][re])<-1) - real = 0x8000; + real = -INT16_MAX; else if (creal(dl_ch_estimates_ext_f[aatx*n_rx + aarx][re])>=1) - real = 0x7FFF; + real = INT16_MAX; else real = creal(dl_ch_estimates_ext_f[aatx*n_rx + aarx][re])*32768; @@ -2910,16 +2910,16 @@ void float_to_rxdataF(int32_t **rxdataF_ext, for (aarx=0; aarx=1) - imag = 0x7FFF; + imag = INT16_MAX; else imag = cimag(rxdataF_f[aarx][re])*32768; if (creal(rxdataF_f[aarx][re])<-1) - real = 0x8000; + real = -INT16_MAX; else if (creal(rxdataF_f[aarx][re])>=1) - real = 0x7FFF; + real = INT16_MAX; else real = creal(rxdataF_f[aarx][re])*32768; diff --git a/openair1/PHY/LTE_UE_TRANSPORT/drs_modulation.c b/openair1/PHY/LTE_UE_TRANSPORT/drs_modulation.c index eb029aa429..929c3ba7c0 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/drs_modulation.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/drs_modulation.c @@ -56,8 +56,8 @@ int generate_drs_pusch(PHY_VARS_UE *ue, //uint32_t phase_shift; // phase shift for cyclic delay in DM RS //uint8_t alpha_ind; - int16_t alpha_re[12] = {32767, 28377, 16383, 0,-16384, -28378,-32768,-28378,-16384, -1, 16383, 28377}; - int16_t alpha_im[12] = {0, 16383, 28377, 32767, 28377, 16383, 0,-16384,-28378,-32768,-28378,-16384}; + int16_t alpha_re[12] = {32767, 28377, 16383, 0, -16384, -28378, -32767, -28378, -16384, -1, 16383, 28377}; + int16_t alpha_im[12] = {0, 16383, 28377, 32767, 28377, 16383, 0, -16384, -28378, -32767, -28378, -16384}; uint8_t cyclic_shift,cyclic_shift0=0,cyclic_shift1=0; LTE_DL_FRAME_PARMS *fp = (ue==NULL) ? frame_parms : &ue->frame_parms; diff --git a/openair1/PHY/TOOLS/signal_energy.c b/openair1/PHY/TOOLS/signal_energy.c index 93544da758..a7c314dd44 100644 --- a/openair1/PHY/TOOLS/signal_energy.c +++ b/openair1/PHY/TOOLS/signal_energy.c @@ -27,8 +27,6 @@ // length : length of vector in complex samples #define shift 4 -//#define shift_DC 0 -//#define SHRT_MIN -32768 //----------------------------------------------------------------- // Average Power calculation with DC removing diff --git a/openair1/SCHED/sched_common_extern.h b/openair1/SCHED/sched_common_extern.h index 57d70f7d1e..f413ba683c 100644 --- a/openair1/SCHED/sched_common_extern.h +++ b/openair1/SCHED/sched_common_extern.h @@ -27,11 +27,12 @@ #include "sched_eNB.h" // This is the formula from Section 5.1.1.1 in 36.213 100*10*log10((2^(MPR*Ks)-1)), where MPR is in the range [0,6] and Ks=1.25 -static const int16_t hundred_times_delta_TF[100] = {-32768, -1268, -956, -768, -631, -523, -431, -352, -282, -219, -161, -107, -57, -9, 36, 79, 120, 159, 197, 234, - 269, 304, 337, 370, 402, 434, 465, 495, 525, 555, 583, 612, 640, 668, 696, 723, 750, 777, 803, 829, - 856, 881, 907, 933, 958, 983, 1008, 1033, 1058, 1083, 1108, 1132, 1157, 1181, 1205, 1229, 1254, 1278, 1302, 1325, - 1349, 1373, 1397, 1421, 1444, 1468, 1491, 1515, 1538, 1562, 1585, 1609, 1632, 1655, 1679, 1702, 1725, 1748, 1772, 1795, - 1818, 1841, 1864, 1887, 1910, 1933, 1956, 1980, 2003, 2026, 2049, 2072, 2095, 2118, 2141, 2164, 2186, 2209, 2232, 2255}; +static const int16_t hundred_times_delta_TF[100] = { + -32767, -1268, -956, -768, -631, -523, -431, -352, -282, -219, -161, -107, -57, -9, 36, 79, 120, 159, 197, 234, + 269, 304, 337, 370, 402, 434, 465, 495, 525, 555, 583, 612, 640, 668, 696, 723, 750, 777, 803, 829, + 856, 881, 907, 933, 958, 983, 1008, 1033, 1058, 1083, 1108, 1132, 1157, 1181, 1205, 1229, 1254, 1278, 1302, 1325, + 1349, 1373, 1397, 1421, 1444, 1468, 1491, 1515, 1538, 1562, 1585, 1609, 1632, 1655, 1679, 1702, 1725, 1748, 1772, 1795, + 1818, 1841, 1864, 1887, 1910, 1933, 1956, 1980, 2003, 2026, 2049, 2072, 2095, 2118, 2141, 2164, 2186, 2209, 2232, 2255}; static const uint16_t hundred_times_log10_NPRB[100] = {0, 301, 477, 602, 698, 778, 845, 903, 954, 1000, 1041, 1079, 1113, 1146, 1176, 1204, 1230, 1255, 1278, 1301, 1322, 1342, 1361, 1380, 1397, 1414, 1431, 1447, 1462, 1477, 1491, 1505, 1518, 1531, 1544, 1556, 1568, 1579, 1591, 1602, 1612, 1623, 1633, 1643, 1653, 1662, 1672, 1681, 1690, 1698, 1707, 1716, 1724, 1732, 1740, 1748, 1755, 1763, 1770, 1778, From 9086fb63de1e3c0fa8ae79ccab6652f2a5ee8cfd Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Fri, 3 Oct 2025 10:38:38 +0200 Subject: [PATCH 897/964] Fix memory leak in nr_rrc_ue_process_masterCellGroup - Replace asn1cFreeStruc with ASN_STRUCT_FREE in MAC layer cleanup - Fixes improper memory management of NR_CellGroupConfig structures Root cause: asn1cFreeStruc only calls ASN_STRUCT_RESET + free(), which doesn't properly free nested ASN.1 allocations. ASN_STRUCT_FREE frees all nested structures completely. AddressSanitizer leak trace: Direct leak of 288 byte(s) in 1 object(s) allocated from: /#0 0x7fb72bab4a57 in __interceptor_calloc /#1 0x593752b28d0d in SEQUENCE_decode_uper /#2 0x593752b9a546 in SET_OF_decode_uper /#3 0x593752b2863c in SEQUENCE_decode_uper /#4 0x593752b47363 in CHOICE_decode_uper /#5 0x593752b2863c in SEQUENCE_decode_uper /#6 0x593752b2863c in SEQUENCE_decode_uper /#7 0x593752b2863c in SEQUENCE_decode_uper /#8 0x593752b2863c in SEQUENCE_decode_uper /#9 0x593752b2863c in SEQUENCE_decode_uper /#10 0x593752b38551 in uper_decode /#11 0x5937527d859f in nr_rrc_ue_process_masterCellGroup /#12 0x5937527d9408 in nr_rrc_process_reconfiguration_v1530 /#13 0x5937527dd5bb in nr_rrc_ue_process_rrcReconfiguration /#14 0x5937527f5e6b in nr_rrc_ue_decode_dcch /#15 0x5937527ff003 in rrc_nrue /#16 0x59375280c6de in rrc_nrue_task --- openair2/RRC/NR_UE/L2_interface_ue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair2/RRC/NR_UE/L2_interface_ue.c b/openair2/RRC/NR_UE/L2_interface_ue.c index d6bee2ab10..501510f7d2 100644 --- a/openair2/RRC/NR_UE/L2_interface_ue.c +++ b/openair2/RRC/NR_UE/L2_interface_ue.c @@ -140,7 +140,7 @@ void process_msg_rcc_to_mac(nr_mac_rrc_message_t *msg, int instance_id) break; case NR_MAC_RRC_CONFIG_CG: nr_rrc_mac_config_req_cg(instance_id, 0, msg->payload.config_cg.cellGroupConfig, msg->payload.config_cg.UE_NR_Capability); - asn1cFreeStruc(asn_DEF_NR_CellGroupConfig, msg->payload.config_cg.cellGroupConfig); + ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, msg->payload.config_cg.cellGroupConfig); break; case NR_MAC_RRC_CONFIG_MIB: nr_rrc_mac_config_req_mib(instance_id, From 9639cbb436cbc8364917a87472eead4dde35969c Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Fri, 3 Oct 2025 12:33:03 +0200 Subject: [PATCH 898/964] Fix memory leak in nr_rrc_process_dedicatedNAS_MessageList The leak was caused by improper memory ownership handling in the dedicatedNAS_MessageList processing. The function was transferring buffer ownership to NAS messages and then preventing ASN.1 cleanup from freeing the original allocations by setting list.count = 0, causing a memory leak. Leak trace: Direct leak of 40 byte(s) in 1 object(s) allocated from: /#0 0x7f2ce3ab4a57 in __interceptor_calloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:154 /#1 0x567907083f0f in OCTET_STRING_decode_uper /cmake_targets/ran_build/build/openair2/RRC/LTE/MESSAGES/OCTET_STRING_uper.c:89 /#2 0x5679070ed5e6 in SET_OF_decode_uper /cmake_targets/ran_build/build/openair2/RRC/NR/MESSAGES/constr_SET_OF_uper.c:70 /#3 0x56790707b6dc in SEQUENCE_decode_uper /cmake_targets/ran_build/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE_uper.c:118 /#4 0x56790707b6dc in SEQUENCE_decode_uper /cmake_targets/ran_build/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE_uper.c:118 /#5 0x56790709a403 in CHOICE_decode_uper /cmake_targets/ran_build/build/openair2/RRC/LTE/MESSAGES/constr_CHOICE_uper.c:84 /#6 0x56790707b6dc in SEQUENCE_decode_uper /cmake_targets/ran_build/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE_uper.c:118 /#7 0x56790709a403 in CHOICE_decode_uper /cmake_targets/ran_build/build/openair2/RRC/LTE/MESSAGES/constr_CHOICE_uper.c:84 /#8 0x56790709a403 in CHOICE_decode_uper /cmake_targets/ran_build/build/openair2/RRC/LTE/MESSAGES/constr_CHOICE_uper.c:84 /#9 0x56790707b6dc in SEQUENCE_decode_uper /cmake_targets/ran_build/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE_uper.c:118 /#10 0x56790708b5f1 in uper_decode /cmake_targets/ran_build/build/openair2/RRC/LTE/MESSAGES/uper_decoder.c:83 /#11 0x567906d44b4b in nr_rrc_ue_decode_dcch /openair2/RRC/NR_UE/rrc_UE.c:2212 /#12 0x567906d520a3 in rrc_nrue /openair2/RRC/NR_UE/rrc_UE.c:2615 /#13 0x567906d5f77e in rrc_nrue_task /openair2/RRC/NR_UE/rrc_UE.c:2501 /#14 0x7f2ce2494ac2 in start_thread nptl/pthread_create.c:442 Fix: - Copy OCTET_STRING data instead of transferring ownership - Allow ASN.1 cleanup to properly free original allocations This fixes the leak that occurred during rrcReconfiguration message processing when dedicatedNAS_MessageList was present. Closes #828 --- openair2/RRC/NR_UE/rrc_UE.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index c167982859..217ca85be7 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -607,10 +607,10 @@ static void nr_rrc_process_dedicatedNAS_MessageList(NR_UE_RRC_INST_t *rrc, NR_RR nas_establish_cnf_t *msg = &NAS_CONN_ESTABLI_CNF(ittiMsg); msg->errCode = AS_SUCCESS; msg->nasMsg.length = tmp->list.array[i]->size; - msg->nasMsg.nas_data = tmp->list.array[i]->buf; + msg->nasMsg.nas_data = malloc_or_fail(msg->nasMsg.length); + memcpy(msg->nasMsg.nas_data, tmp->list.array[i]->buf, msg->nasMsg.length); itti_send_msg_to_task(TASK_NAS_NRUE, rrc->ue_id, ittiMsg); } - tmp->list.count = 0; // to prevent the automatic free by ASN1_FREE } } From d6047cd83dbe26997dc0a307467617b7d3bccdfc Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Fri, 3 Oct 2025 10:54:43 +0200 Subject: [PATCH 899/964] Fix memory leak in dlInformationTransfer case - Remove unnecessary NULL assignment for dedicatedNAS_Message->buf - The original buffer is copied and transfered to NAS, so it can be properly freed by ASN.1 structure cleanup Root cause: Code was nullifying dedicatedNAS_Message->buf pointer before ASN.1 cleanup could free the original allocation, causing the leak from OCTET_STRING_decode_uper. AddressSanitizer leak trace (FIXED): Direct leak of 119 byte(s) in 3 object(s) allocated from: /#0 0x7ec2a42b4c38 in __interceptor_realloc /#1 0x555fade852e0 in OCTET_STRING_decode_uper /#9 0x555fadb48b11 in nr_rrc_ue_decode_dcch. --- openair2/RRC/NR_UE/rrc_UE.c | 1 - 1 file changed, 1 deletion(-) diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 217ca85be7..2801aacce7 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -2299,7 +2299,6 @@ static int nr_rrc_ue_decode_dcch(NR_UE_RRC_INST_t *rrc, 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; From 8411a428db04995a4bce45cae9eb79218858dc5d Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 3 Oct 2025 09:20:22 +0200 Subject: [PATCH 900/964] prevent faulty behavior of nr_compute_tbs when null input is not producing TBS = 0 --- openair2/LAYER2/NR_MAC_COMMON/nr_compute_tbs_common.c | 5 +++++ openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c | 3 +-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_compute_tbs_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_compute_tbs_common.c index 96819378f0..1643d4e732 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_compute_tbs_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_compute_tbs_common.c @@ -59,6 +59,11 @@ uint32_t nr_compute_tbs(uint16_t Qm, tb_scaling, Nl); + if (Qm == 0 || R == 0 || nb_rb == 0 || Nl == 0) { + LOG_E(NR_MAC, "Error in compute TBS with a NULL input, returning NULL TBS\n"); + return 0; + } + const int nb_subcarrier_per_rb = 12; const uint32_t nbp_re = nb_subcarrier_per_rb * nb_symb_sch - nb_dmrs_prb - nb_rb_oh; const uint32_t nb_re = min(156, nbp_re) * nb_rb; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 21a032fde6..63be110ab7 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -673,8 +673,7 @@ bool nr_find_nb_rb(uint16_t Qm, uint16_t *nb_rb) { // for transform precoding only RB = 2^a_2 * 3^a_3 * 5^a_5 is allowed with a non-negative - while(transform_precoding == NR_PUSCH_Config__transformPrecoder_enabled && - !multiple_2_3_5(nb_rb_max)) + while (transform_precoding == NR_PUSCH_Config__transformPrecoder_enabled && !multiple_2_3_5(nb_rb_max)) nb_rb_max--; /* is the maximum (not even) enough? */ From 958fe1ed75fb96cc6a874a829ceb478774d71538 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 1 Oct 2025 09:54:16 +0200 Subject: [PATCH 901/964] OC PhySim deployment: always undeploy safely This fixes basically two problems. First, remove "set -e", which leads to the script exiting on error. For instance, there was the sleep which should account for the time of the pod being in "ContainerCreating", but might not be enough. In that case, the script would exit, leaving the pod deployed. Second, a fixed time is not good, as it can be too short and unduly prolong waiting time. Replace with a loop. --- ci-scripts/scripts/oc-deploy-physims.sh | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ci-scripts/scripts/oc-deploy-physims.sh b/ci-scripts/scripts/oc-deploy-physims.sh index 19c1940ba1..c0b4e388c1 100755 --- a/ci-scripts/scripts/oc-deploy-physims.sh +++ b/ci-scripts/scripts/oc-deploy-physims.sh @@ -1,7 +1,5 @@ #!/bin/bash -set -e - function die() { echo $@; exit 1; } [ $# -eq 4 ] || die "usage: $0 " @@ -15,7 +13,11 @@ oc project ${OC_NS} > /dev/null oc tag oaicicd-ran/oai-physim:${IMG_TAG} ${OC_NS}/oai-physim:${IMG_TAG} helm install ${OC_RELEASE} ${OAI_DIR}/charts/${OC_RELEASE} --set global.image.version=${IMG_TAG} --wait --timeout 120s POD_ID=$(oc get pods | grep oai-${OC_RELEASE} | awk '{print $1}') -sleep 30 +wait_creating=30 +while [[ $(oc describe pod "$POD_ID" | grep "ContainerCreating") && ${wait_creating} > 0 ]]; do + sleep 1; + let wait_creating=$wait_creating-1 +done echo "Monitoring logs for 'FINISHED' in pod '$POD_ID'" oc logs -f -n ${OC_NS} "$POD_ID" | while read -r line; do if [[ "$line" == *"FINISHED"* ]]; then From bd1dadaa79943096361b2829dfb7e482dfaa165a Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Wed, 1 Oct 2025 10:07:25 +0200 Subject: [PATCH 902/964] OC PhySim deployment: log bash script commands Also, don't use "set -x" debugging for oc login command: ci-scripts/cls_cmd.py:242 sets BASH_XTRACEFD=1, which makes that all "set -x" output is in stdout, leading to a redirect to the file into which we redirect. This would lead to the following error with unsuccessfull oc login: error: You are not a member of project "****-core-for-ci-ran". Error from server (Forbidden): imagestreams.image.openshift.io "oai-physim" is forbidden: User "system:anonymous" cannot get resource "imagestreams" in API group "image.openshift.io" in the namespace "****-ran" --- ci-scripts/scripts/oc-deploy-physims.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ci-scripts/scripts/oc-deploy-physims.sh b/ci-scripts/scripts/oc-deploy-physims.sh index c0b4e388c1..29812a8980 100755 --- a/ci-scripts/scripts/oc-deploy-physims.sh +++ b/ci-scripts/scripts/oc-deploy-physims.sh @@ -9,9 +9,11 @@ IMG_TAG=${3} OAI_DIR=${4} cat /opt/oc-password | oc login -u oaicicd --server https://api.oai.cs.eurecom.fr:6443 > /dev/null +set -x oc project ${OC_NS} > /dev/null oc tag oaicicd-ran/oai-physim:${IMG_TAG} ${OC_NS}/oai-physim:${IMG_TAG} helm install ${OC_RELEASE} ${OAI_DIR}/charts/${OC_RELEASE} --set global.image.version=${IMG_TAG} --wait --timeout 120s +set +x POD_ID=$(oc get pods | grep oai-${OC_RELEASE} | awk '{print $1}') wait_creating=30 while [[ $(oc describe pod "$POD_ID" | grep "ContainerCreating") && ${wait_creating} > 0 ]]; do @@ -29,6 +31,7 @@ oc logs -f -n ${OC_NS} "$POD_ID" | while read -r line; do break fi done +set -x oc logs -n ${OC_NS} "$POD_ID" >> ${OAI_DIR}/physim_log.txt oc describe pod $POD_ID >> ${OAI_DIR}/physim_log.txt helm uninstall ${OC_RELEASE} --wait From 9949c7e71b0a494656814dbe44c64c0bbc2b508c Mon Sep 17 00:00:00 2001 From: Nick Hedberg Date: Thu, 2 Oct 2025 11:47:53 +0000 Subject: [PATCH 903/964] Assign antenna ports correctly for 1 and 2 layers for aerial. Removes Aerial-specific changes and harmonizes with OAI full-stack. --- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 24 ++++--------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 21a032fde6..f9a851376b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -343,23 +343,13 @@ NR_pdsch_dmrs_t get_dl_dmrs_params(const NR_ServingCellConfigCommon_t *scc, switch (Layers) { case 1: -#ifdef ENABLE_AERIAL - dmrs.dmrs_ports_id = 3; - dmrs.numDmrsCdmGrpsNoData = 2; -#else dmrs.dmrs_ports_id = 0; dmrs.numDmrsCdmGrpsNoData = 1; -#endif frontloaded_symb = 1; break; case 2: -#ifdef ENABLE_AERIAL - dmrs.dmrs_ports_id = 7; - dmrs.numDmrsCdmGrpsNoData = 2; -#else dmrs.dmrs_ports_id = 2; dmrs.numDmrsCdmGrpsNoData = 1; -#endif frontloaded_symb = 1; break; case 3: @@ -738,15 +728,10 @@ NR_pusch_dmrs_t get_ul_dmrs_params(const NR_ServingCellConfigCommon_t *scc, const int Layers) { NR_pusch_dmrs_t dmrs = {0}; - // TODO setting of cdm groups with no data to be redone for MIMO - if(NFAPI_MODE == NFAPI_MODE_AERIAL) { + if (ul_bwp->transform_precoding && Layers < 3) + dmrs.num_dmrs_cdm_grps_no_data = ul_bwp->dci_format == NR_UL_DCI_FORMAT_0_1 || tda_info->nrOfSymbols <= 2 ? 1 : 2; + else dmrs.num_dmrs_cdm_grps_no_data = 2; - } else { - if (ul_bwp->transform_precoding && Layers < 3) - dmrs.num_dmrs_cdm_grps_no_data = ul_bwp->dci_format == NR_UL_DCI_FORMAT_0_1 || tda_info->nrOfSymbols <= 2 ? 1 : 2; - else - dmrs.num_dmrs_cdm_grps_no_data = 2; - } const NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig = get_DMRS_UplinkConfig(ul_bwp->pusch_Config, tda_info); dmrs.ptrsConfig = NR_DMRS_UplinkConfig @@ -1247,8 +1232,7 @@ void config_uldci(const NR_UE_ServingCell_Info_t *sc_info, // antenna_ports.val = 0 for transform precoder is disabled, dmrs-Type=1, maxLength=1, Rank=1/2/3/4 // Antenna Ports - - dci_pdu_rel15->antenna_ports.val = NFAPI_MODE == NFAPI_MODE_AERIAL ? 2 : 0; + dci_pdu_rel15->antenna_ports.val = 0; // DMRS sequence initialization dci_pdu_rel15->dmrs_sequence_initialization.val = pusch_pdu->scid; From b012700fe4e62dd5e97c10d5d763c6ed849094b5 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 24 Sep 2025 09:11:13 +0200 Subject: [PATCH 904/964] Fix analyze-timing.sh for mawk compatibility The awk script in analyze-timing.sh used syntax that works with gawk but fails on systems where mawk is the default implementation, producing errors such as: awk: /dev/fd/3: line 6: syntax error at or near , -- test command finished with SIGPIPE Concretely, the match(text, pattern, variable) function does not exist in mawk, as it cannot capture matches in variables. Work around by substituing strings, and force a numeric comparison. --- openair1/SIMULATION/tests/analyze-timing.sh | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/openair1/SIMULATION/tests/analyze-timing.sh b/openair1/SIMULATION/tests/analyze-timing.sh index 2ca45f346f..27f113ec2e 100755 --- a/openair1/SIMULATION/tests/analyze-timing.sh +++ b/openair1/SIMULATION/tests/analyze-timing.sh @@ -28,6 +28,13 @@ while [ $# -gt 0 ]; do # RC to signal error). In both cases, the result is logged in an array to # output at the end of the script. # + # To search for the number, first substr() returns what has been matched + # (PATTERN + number), and sub() deletes PATTERN and whitespace, resulting in + # the number (measurement). To force number into a numeric context, we add 0, + # as awk would otherwise compare a string to a number (example: + # gawk 'BEGIN { meas = "117"; if (meas > 96) { } else { print "fail";}}' + # printfs "fail"). + # # Example: pattern "PHY proc tx", condition "< 200" # The awk script tries to match every line for "PHY proc tx _NUMBER_" (where # number is a decimal), and compares _NUMBER_ against condition "< 200", @@ -35,14 +42,16 @@ while [ $# -gt 0 ]; do # If the condition holds, will set "CHECK PHY proc tx _NUMBER_ < 200 SUCCESS". # If the condition fails, will set "CHECK PHY proc tx _NUMBER_ < 200 FAIL". SCRIPT+=' - match($0, /'${PATTERN}' +([0-9]+(\.[0-9]+)?)/, n) { - if (n[1] '${COND}') { + match($0, /'${PATTERN}' +([0-9]+(\.[0-9]+)?)/) { + meas = substr($0, RSTART, RLENGTH); + sub(/'${PATTERN}' +/, "", meas); + if ((meas+0) '${COND}') { r = "SUCCESS"; } else { r = "FAIL"; RC = 1; } - RESULTS['${NUM}']=sprintf("CHECK %-35s %7.2f %-8s %s", "'${PATTERN}'", n[1], " '${COND}'", r); + RESULTS['${NUM}']=sprintf("CHECK %-35s %7.2f %-8s %s", "'${PATTERN}'", meas, " '${COND}'", r); } ' From a3ac1dbdfe1ba243b6c02bb73d05887a9bb1092c Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 30 Sep 2025 17:50:09 +0200 Subject: [PATCH 905/964] analyze-timing.sh: check only last measurement occurrence For some physical simulators, we have multiple SNR iterations. The previous version of the script correctly retained only the last measurement, but if a previous measurement condition set RC=1, the script would fail although the final "good" run might fulfil the measurement condition (IOW, it would show SUCCESS, but still fail on the check). Instead, check if all measurement lines finish on SUCCESS, which handles the above case. --- openair1/SIMULATION/tests/analyze-timing.sh | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/openair1/SIMULATION/tests/analyze-timing.sh b/openair1/SIMULATION/tests/analyze-timing.sh index 27f113ec2e..f88b595a97 100755 --- a/openair1/SIMULATION/tests/analyze-timing.sh +++ b/openair1/SIMULATION/tests/analyze-timing.sh @@ -6,12 +6,9 @@ function die() { echo $@ 1>&2; exit 1; } -# RC will be the return code. If any rule fails, it will set RC=1, which will -# make the script fail. Print also every line, because the logs are piped into -# this script, but a user is typically also interested into the raw logs. +# Print every line, because the logs are piped into this script, but a user is +# typically also interested into the raw logs. SCRIPT=' - BEGIN { RC = 0; } - { print $0 } ' @@ -24,9 +21,9 @@ while [ $# -gt 0 ]; do shift 2 # Add a rule that searches for a PATTERN + number, and checks against - # CONDition. If the condition does not hold, it is counted as a failure (sets - # RC to signal error). In both cases, the result is logged in an array to - # output at the end of the script. + # CONDition. If the condition does not hold, it is counted as a failure. In + # both cases, the result is logged in an array to output at the end of the + # script. # # To search for the number, first substr() returns what has been matched # (PATTERN + number), and sub() deletes PATTERN and whitespace, resulting in @@ -49,7 +46,6 @@ while [ $# -gt 0 ]; do r = "SUCCESS"; } else { r = "FAIL"; - RC = 1; } RESULTS['${NUM}']=sprintf("CHECK %-35s %7.2f %-8s %s", "'${PATTERN}'", meas, " '${COND}'", r); } @@ -63,7 +59,6 @@ while [ $# -gt 0 ]; do END { if (!RESULTS['${NUM}']) { RESULTS['${NUM}']=sprintf("CHECK %-35s %-7s NOTFOUND", "'${PATTERN}'", "'${COND}'"); - RC = 1; } } ' @@ -75,8 +70,11 @@ done # (0 on success, i.e..all conditions checked, otherwise 1 on failure). SCRIPT+=' END { + RC = 0; for (i = 0; i < '${NUM}'; ++i) { print RESULTS[i] + if (!(RESULTS[i] ~ /SUCCESS$/)) + RC = 1; } exit RC } From 78d91db964b7d80acab2b56f80ffa9e634156e93 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Mon, 6 Oct 2025 11:09:04 +0200 Subject: [PATCH 906/964] Include timing analysis file in physim.rhel9 image Add missing timinig analysis scripts to RHEL9 physim docker image. These files are now copied from the build stage to /oai-ran/openair1/SIMULATION/tests/, where they are expected by ctest. Resolves following issue when running ctest in docker container: CMake Error: Error processing file: /oai-ran/openair1/SIMULATION/tests/RunTimedTest.cmake --- docker/Dockerfile.phySim.rhel9 | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docker/Dockerfile.phySim.rhel9 b/docker/Dockerfile.phySim.rhel9 index c5faab2ec7..6a4ca5c226 100644 --- a/docker/Dockerfile.phySim.rhel9 +++ b/docker/Dockerfile.phySim.rhel9 @@ -101,4 +101,11 @@ COPY --from=phy-sim-build \ /oai-ran/cmake_targets/ran_build/build/openair1/SIMULATION/tests/CTestTestfile.cmake \ /opt/oai-physim/ +RUN mkdir -p /oai-ran/openair1/SIMULATION/tests + +COPY --from=phy-sim-build \ + /oai-ran/openair1/SIMULATION/tests/RunTimedTest.cmake \ + /oai-ran/openair1/SIMULATION/tests/analyze-timing.sh \ + /oai-ran/openair1/SIMULATION/tests/ + #CMD ["sleep", "infinity"] From f4e4ef74ff315a6bd7b8c5187c67ad905db99818 Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 2 Oct 2025 15:11:12 +0200 Subject: [PATCH 907/964] remove emulate_l1 code --- doc/L2NFAPI.md | 43 +- executables/create_tasks.c | 2 +- executables/nr-ue.c | 188 ---- executables/nr-uesoftmodem.c | 213 ++-- executables/nr-uesoftmodem.h | 2 - executables/softmodem-common.h | 5 - openair1/SCHED_NR_UE/fapi_nr_ue_l1.c | 237 ---- openair2/LAYER2/NR_MAC_COMMON/nr_mac.h | 29 - openair2/LAYER2/NR_MAC_UE/config_ue.c | 15 +- openair2/LAYER2/NR_MAC_UE/mac_defs.h | 2 - openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c | 1 - openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 32 - openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 10 - openair2/LAYER2/PDCP_v10.1.0/pdcp.c | 6 +- openair2/NR_PHY_INTERFACE/NR_IF_Module.h | 2 - openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c | 1018 +----------------- openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h | 42 - openair2/RRC/LTE/rrc_eNB.c | 2 +- openair2/RRC/NR_UE/rrc_UE.c | 2 +- openair2/RRC/NR_UE/rrc_proto.h | 2 - 20 files changed, 90 insertions(+), 1763 deletions(-) diff --git a/doc/L2NFAPI.md b/doc/L2NFAPI.md index d9f0ad0435..282e6eeedf 100644 --- a/doc/L2NFAPI.md +++ b/doc/L2NFAPI.md @@ -40,48 +40,7 @@ Normally it should be fine to run both executables on the same host using the `l **2022/03/08: Starting the `2022.w01` tag on the `develop` branch, the L2 nFAPI simulation is using a proxy.** -## 5G L2 nFAPI simulator - -**Note: L2 simulator does not work anymore.** - -### Download and Build the Proxy Server (from EpiSci) - -```bash -$ cd ~ -$ git clone https://github.com/EpiSci/oai-lte-5g-multi-ue-proxy.git -$ cd oai-lte-multi-ue-proxy -$ make -``` - -### Start Proxy Server -Set the number of UEs to connect to server as 1 and the mode is SA. -```bash -$ number_of_ues=1 -$ sudo -E ./build/proxy $number_of_ues --nr -``` - -### Start gNB -```bash -$ sudo -E ./nr-softmodem -O ../ci-scripts/conf_files/episci/proxy_rcc.band78.tm1.106PRB.nfapi.conf --nfapi VNF --noS1 --emulate-l1 -``` -### Start UE -```bash -$ sudo -E ./nr-uesoftmodem -O ../ci-scripts/conf_files/nrue.uicc.conf --nfapi STANDALONE_PNF --node-number 2 --emulate-l1 -``` ### EpiSci's Documentation A more detailed tutorial is available on the [EpiSci GitHub Repository](https://github.com/EpiSci/oai-lte-5g-multi-ue-proxy#readme). -This proxy allows to perform L2 nFAPI simulator for: - -* LTE -* 5G-NSA -* 5G-SA - -### L2 Simulator as Docker Containers - -There used to be docker deployment with L2sim that was run in the CI. Since L2 -simulator does not work anymore, it has been removed. However, you can see the -old `README.md` from tag `2024.w44` -[here](https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/2024.w44/ci-scripts/yaml_files/5g_l2sim_tdd/README.md). -In the same directory is a `docker-compose.yaml` file that can be used to run -L2sim. +Since 5G code has been removed, this proxy allows to perform L2 nFAPI simulator for LTE only. diff --git a/executables/create_tasks.c b/executables/create_tasks.c index ad81beca09..a36cf410e5 100644 --- a/executables/create_tasks.c +++ b/executables/create_tasks.c @@ -52,7 +52,7 @@ int create_tasks(uint32_t enb_nb) { rrc_enb_init(); itti_mark_task_ready(TASK_RRC_ENB); - if (get_softmodem_params()->emulate_l1 || !IS_SOFTMODEM_NOS1) { + if (!IS_SOFTMODEM_NOS1) { rc = itti_create_task(TASK_SCTP, sctp_eNB_task, NULL); AssertFatal(rc >= 0, "Create task for SCTP failed\n"); } diff --git a/executables/nr-ue.c b/executables/nr-ue.c index 588465133b..f789484465 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -31,13 +31,10 @@ #include "SCHED_NR_UE/defs.h" #include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h" #include "executables/softmodem-common.h" -#include "PHY/NR_REFSIG/refsig_defs_ue.h" #include "radio/COMMON/common_lib.h" #include "LAYER2/nr_pdcp/nr_pdcp_oai_api.h" #include "LAYER2/nr_rlc/nr_rlc_oai_api.h" -#include "RRC/NR/MESSAGES/asn1_msg.h" #include "openair1/PHY/TOOLS/phy_scope_interface.h" -#include "PHY/MODULATION/nr_modulation.h" #include "instrumentation.h" #include "common/utils/threadPool/notified_fifo.h" #include "position_interface.h" @@ -102,8 +99,6 @@ * */ -static void *NRUE_phy_stub_standalone_pnf_task(void *arg); - static void start_process_slot_tx(void* arg) { notifiedFIFO_elt_t *newTx = arg; nr_rxtx_thread_data_t *curMsgTx = NotifiedFifoData(newTx); @@ -194,189 +189,6 @@ void init_nr_ue_vars(PHY_VARS_NR_UE *ue, uint8_t UE_id) ue->ta_slot = -1; } -void init_nrUE_standalone_thread(int ue_idx) -{ - int standalone_tx_port = 3611 + ue_idx * 2; - int standalone_rx_port = 3612 + ue_idx * 2; - nrue_init_standalone_socket(standalone_tx_port, standalone_rx_port); - - NR_UE_MAC_INST_t *mac = get_mac_inst(0); - pthread_mutex_init(&mac->mutex_dl_info, NULL); - - pthread_t thread; - if (pthread_create(&thread, NULL, nrue_standalone_pnf_task, NULL) != 0) { - LOG_E(NR_MAC, "pthread_create failed for calling nrue_standalone_pnf_task"); - } - pthread_setname_np(thread, "oai:nrue-stand"); - pthread_t phy_thread; - if (pthread_create(&phy_thread, NULL, NRUE_phy_stub_standalone_pnf_task, NULL) != 0) { - LOG_E(NR_MAC, "pthread_create failed for calling NRUE_phy_stub_standalone_pnf_task"); - } - pthread_setname_np(phy_thread, "oai:nrue-stand-phy"); -} - -static void process_queued_nr_nfapi_msgs(NR_UE_MAC_INST_t *mac, int sfn, int slot) -{ - struct sfn_slot_s sfn_slot = {.sfn = sfn, .slot = slot}; - nfapi_nr_rach_indication_t *rach_ind = unqueue_matching(&nr_rach_ind_queue, MAX_QUEUE_SIZE, sfn_slot_matcher, &sfn_slot); - nfapi_nr_dl_tti_request_t *dl_tti_request = get_queue(&nr_dl_tti_req_queue); - nfapi_nr_ul_dci_request_t *ul_dci_request = get_queue(&nr_ul_dci_req_queue); - - for (int i = 0; i < NR_MAX_HARQ_PROCESSES; i++) { - LOG_D(NR_MAC, - "Try to get a ul_tti_req by matching CRC active sfn/slot %d.%d from queue with %lu items\n", - sfn, - slot, - nr_ul_tti_req_queue.num_items); - struct sfn_slot_s sfn_sf = {.sfn = mac->nr_ue_emul_l1.harq[i].active_ul_harq_sfn, .slot = mac->nr_ue_emul_l1.harq[i].active_ul_harq_slot }; - nfapi_nr_ul_tti_request_t *ul_tti_request_crc = unqueue_matching(&nr_ul_tti_req_queue, MAX_QUEUE_SIZE, sfn_slot_matcher, &sfn_sf); - if (ul_tti_request_crc && ul_tti_request_crc->n_pdus > 0) { - check_and_process_dci(NULL, NULL, NULL, ul_tti_request_crc); - free_and_zero(ul_tti_request_crc); - } - } - - if (rach_ind && rach_ind->number_of_pdus > 0) { - NR_UL_IND_t UL_INFO = { - .rach_ind = *rach_ind, - }; - send_nsa_standalone_msg(&UL_INFO, rach_ind->header.message_id); - free_and_zero(rach_ind->pdu_list); - free_and_zero(rach_ind); - } - if (dl_tti_request) { - struct sfn_slot_s sfn_slot = {.sfn = dl_tti_request->SFN, .slot = dl_tti_request->Slot}; - nfapi_nr_tx_data_request_t *tx_data_request = unqueue_matching(&nr_tx_req_queue, MAX_QUEUE_SIZE, sfn_slot_matcher, &sfn_slot); - if (!tx_data_request) { - LOG_E(NR_MAC, "[%d.%d] No corresponding tx_data_request for given dl_tti_request sfn/slot\n", - dl_tti_request->SFN, dl_tti_request->Slot); - if (get_softmodem_params()->nsa) - save_nr_measurement_info(dl_tti_request); - free_and_zero(dl_tti_request); - } - else if (dl_tti_request->dl_tti_request_body.nPDUs > 0 && tx_data_request->Number_of_PDUs > 0) { - if (get_softmodem_params()->nsa) - save_nr_measurement_info(dl_tti_request); - check_and_process_dci(dl_tti_request, tx_data_request, NULL, NULL); - free_and_zero(dl_tti_request); - free_and_zero(tx_data_request); - } - else { - AssertFatal(false, "We dont have PDUs in either dl_tti %d or tx_req %d\n", - dl_tti_request->dl_tti_request_body.nPDUs, tx_data_request->Number_of_PDUs); - } - } - if (ul_dci_request && ul_dci_request->numPdus > 0) { - check_and_process_dci(NULL, NULL, ul_dci_request, NULL); - free_and_zero(ul_dci_request); - } -} - -static void *NRUE_phy_stub_standalone_pnf_task(void *arg) -{ - LOG_I(MAC, "Clearing Queues\n"); - reset_queue(&nr_rach_ind_queue); - reset_queue(&nr_rx_ind_queue); - reset_queue(&nr_crc_ind_queue); - reset_queue(&nr_uci_ind_queue); - reset_queue(&nr_dl_tti_req_queue); - reset_queue(&nr_tx_req_queue); - reset_queue(&nr_ul_dci_req_queue); - reset_queue(&nr_ul_tti_req_queue); - - int last_sfn_slot = -1; - uint16_t sfn_slot = 0; - - module_id_t mod_id = 0; - NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); - for (int i = 0; i < NR_MAX_HARQ_PROCESSES; i++) { - mac->nr_ue_emul_l1.harq[i].active = false; - mac->nr_ue_emul_l1.harq[i].active_ul_harq_sfn = -1; - mac->nr_ue_emul_l1.harq[i].active_ul_harq_slot = -1; - } - - while (!oai_exit) { - if (sem_wait(&sfn_slot_semaphore) != 0) { - LOG_E(NR_MAC, "sem_wait() error\n"); - abort(); - } - uint16_t *slot_ind = get_queue(&nr_sfn_slot_queue); - nr_phy_channel_params_t *ch_info = get_queue(&nr_chan_param_queue); - if (!slot_ind && !ch_info) { - LOG_D(MAC, "get nr_sfn_slot_queue and nr_chan_param_queue == NULL!\n"); - continue; - } - if (slot_ind) { - sfn_slot = *slot_ind; - free_and_zero(slot_ind); - } - else if (ch_info) { - sfn_slot = ch_info->sfn_slot; - free_and_zero(ch_info); - } - - int mu = 1; // NR-UE emul-L1 is hardcoded to 30kHZ, see check_and_process_dci() - frame_t frame = NFAPI_SFNSLOTDEC2SFN(mu, sfn_slot); - int slot = NFAPI_SFNSLOTDEC2SLOT(mu, sfn_slot); - if (sfn_slot == last_sfn_slot) { - LOG_D(NR_MAC, "repeated sfn_sf = %d.%d\n", - frame, slot); - continue; - } - last_sfn_slot = sfn_slot; - - LOG_D(NR_MAC, "The received sfn/slot [%d %d] from proxy\n", - frame, slot); - - if (IS_SA_MODE(get_softmodem_params()) && mac->mib == NULL) { - LOG_D(NR_MAC, "We haven't gotten MIB. Lets see if we received it\n"); - nr_ue_dl_indication(&mac->dl_info); - process_queued_nr_nfapi_msgs(mac, frame, slot); - } - - int CC_id = 0; - uint8_t gNB_id = 0; - int slots_per_frame = 20; //30 kHZ subcarrier spacing - int slot_ahead = 2; // TODO: Make this dynamic - nr_uplink_indication_t ul_info = {.cc_id = CC_id, - .gNB_index = gNB_id, - .module_id = mod_id, - .slot = (slot + slot_ahead) % slots_per_frame, - .frame = (slot + slot_ahead >= slots_per_frame) ? (frame + 1) % 1024 : frame}; - - if (pthread_mutex_lock(&mac->mutex_dl_info)) abort(); - - if (ch_info) { - mac->nr_ue_emul_l1.pmi = ch_info->csi[0].pmi; - mac->nr_ue_emul_l1.ri = ch_info->csi[0].ri; - mac->nr_ue_emul_l1.cqi = ch_info->csi[0].cqi; - free_and_zero(ch_info); - } - - if (is_dl_slot(slot, &mac->frame_structure)) { - memset(&mac->dl_info, 0, sizeof(mac->dl_info)); - mac->dl_info.cc_id = CC_id; - mac->dl_info.gNB_index = gNB_id; - mac->dl_info.module_id = mod_id; - mac->dl_info.frame = frame; - mac->dl_info.slot = slot; - mac->dl_info.dci_ind = NULL; - mac->dl_info.rx_ind = NULL; - nr_ue_dl_indication(&mac->dl_info); - } - - if (pthread_mutex_unlock(&mac->mutex_dl_info)) abort(); - - if (is_ul_slot(ul_info.slot, &mac->frame_structure)) { - LOG_D(NR_MAC, "Slot %d. calling nr_ue_ul_ind()\n", ul_info.slot); - nr_ue_ul_scheduler(mac, &ul_info); - } - process_queued_nr_nfapi_msgs(mac, frame, slot); - } - return NULL; -} - - /*! * It performs band scanning and synchonization. * \param arg is a pointer to a \ref PHY_VARS_NR_UE structure. diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index ac7b23382f..fb740781cd 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -93,15 +93,6 @@ unsigned short config_frames[4] = {2,9,11,13}; THREAD_STRUCT thread_struct; nrUE_params_t nrUE_params = {0}; -// Thread variables -pthread_cond_t nfapi_sync_cond; -pthread_mutex_t nfapi_sync_mutex; -int nfapi_sync_var=-1; //!< protected by mutex \ref nfapi_sync_mutex -pthread_cond_t sync_cond; -pthread_mutex_t sync_mutex; -int sync_var=-1; //!< protected by mutex \ref sync_mutex. -int config_sync_var=-1; - // not used in UE instance_t CUuniqInstance=0; instance_t DUuniqInstance=0; @@ -111,7 +102,6 @@ int get_node_type() {return -1;} RAN_CONTEXT_t RC; int oai_exit = 0; - static int tx_max_power[MAX_NUM_CCs] = {0}; double rx_gain_off = 0.0; @@ -121,10 +111,7 @@ int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; uint64_t sidelink_frequency[MAX_NUM_CCs][4]; // UE and OAI config variables -int16_t node_synch_ref[MAX_NUM_CCs]; -int otg_enabled; double cpuf; -uint32_t N_RB_DL = 106; int create_tasks_nrue(uint32_t ue_nb) { LOG_D(NR_RRC, "%s(ue_nb:%d)\n", __FUNCTION__, ue_nb); @@ -342,40 +329,6 @@ static void trigger_deregistration(int sig) } } -static void get_channel_model_mode(configmodule_interface_t *cfg) -{ - paramdef_t GNBParams[] = GNBPARAMS_DESC; - config_get(cfg, GNBParams, sizeofArray(GNBParams), NULL); - int num_xp_antennas = *GNBParams[GNB_PDSCH_ANTENNAPORTS_XP_IDX].iptr; - - if (num_xp_antennas == 2) - init_nr_bler_table("NR_MIMO2x2_AWGN_RESULTS_DIR"); - else - init_nr_bler_table("NR_AWGN_RESULTS_DIR"); -} - -void start_oai_nrue_threads() -{ - init_queue(&nr_rach_ind_queue); - init_queue(&nr_rx_ind_queue); - init_queue(&nr_crc_ind_queue); - init_queue(&nr_uci_ind_queue); - init_queue(&nr_sfn_slot_queue); - init_queue(&nr_chan_param_queue); - init_queue(&nr_dl_tti_req_queue); - init_queue(&nr_tx_req_queue); - init_queue(&nr_ul_dci_req_queue); - init_queue(&nr_ul_tti_req_queue); - - if (sem_init(&sfn_slot_semaphore, 0, 0) != 0) - { - LOG_E(MAC, "sem_init() error\n"); - abort(); - } - - init_nrUE_standalone_thread(ue_id_g); -} - int NB_UE_INST = 1; configmodule_interface_t *uniqCfg = NULL; nrLDPC_coding_interface_t nrLDPC_coding_interface = {0}; @@ -455,11 +408,6 @@ int main(int argc, char **argv) init_NR_UE(NB_UE_INST, get_nrUE_params()->uecap_file, get_nrUE_params()->reconfig_file, get_nrUE_params()->rbconfig_file); - if (get_softmodem_params()->emulate_l1) { - RCconfig_nr_ue_macrlc(); - get_channel_model_mode(uniqCfg); - } - // start time manager with some reasonable default for the running mode // (may be overwritten in configuration file or command line) void nr_pdcp_ms_tick(void); @@ -475,97 +423,90 @@ int main(int argc, char **argv) IS_SOFTMODEM_RFSIM ? TIME_SOURCE_IQ_SAMPLES : TIME_SOURCE_REALTIME); - if (!get_softmodem_params()->nsa && get_softmodem_params()->emulate_l1) - start_oai_nrue_threads(); - - if (!get_softmodem_params()->emulate_l1) { - for (int inst = 0; inst < NB_UE_INST; inst++) { - PHY_VARS_NR_UE *UE[MAX_NUM_CCs]; - for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { - UE[CC_id] = PHY_vars_UE_g[inst][CC_id]; - - set_options(CC_id, UE[CC_id]); - NR_UE_MAC_INST_t *mac = get_mac_inst(inst); - init_nr_ue_phy_cpu_stats(&UE[CC_id]->phy_cpu_stats); - - if (IS_SA_MODE(get_softmodem_params()) || get_softmodem_params()->sl_mode) { // set frame config to initial values from command line - // and assume that the SSB is centered on the grid - uint16_t nr_band = get_softmodem_params()->band; - mac->nr_band = nr_band; - mac->ssb_start_subcarrier = UE[CC_id]->frame_parms.ssb_start_subcarrier; - nr_init_frame_parms_ue_sa(&UE[CC_id]->frame_parms, - downlink_frequency[CC_id][0], - uplink_frequency_offset[CC_id][0], - get_softmodem_params()->numerology, - nr_band); - } else { - do { - notifiedFIFO_elt_t *elt = pollNotifiedFIFO(&mac->input_nf); - if (!elt) { - break; - } - process_msg_rcc_to_mac(NotifiedFifoData(elt), inst); - delNotifiedFIFO_elt(elt); - } while (true); - fapi_nr_config_request_t *nrUE_config = &UE[CC_id]->nrUE_config; - nr_init_frame_parms_ue(&UE[CC_id]->frame_parms, nrUE_config, mac->nr_band); - } - - UE[CC_id]->sl_mode = get_softmodem_params()->sl_mode; - init_actor(&UE[CC_id]->sync_actor, "SYNC_", -1); - if (get_nrUE_params()->num_dl_actors > 0) { - UE[CC_id]->dl_actors = calloc_or_fail(get_nrUE_params()->num_dl_actors, sizeof(*UE[CC_id]->dl_actors)); - for (int i = 0; i < get_nrUE_params()->num_dl_actors; i++) { - init_actor(&UE[CC_id]->dl_actors[i], "DL_", -1); + for (int inst = 0; inst < NB_UE_INST; inst++) { + PHY_VARS_NR_UE *UE[MAX_NUM_CCs]; + for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { + UE[CC_id] = PHY_vars_UE_g[inst][CC_id]; + set_options(CC_id, UE[CC_id]); + NR_UE_MAC_INST_t *mac = get_mac_inst(inst); + init_nr_ue_phy_cpu_stats(&UE[CC_id]->phy_cpu_stats); + // set frame config to initial values from command line and assume that the SSB is centered on the grid + if (IS_SA_MODE(get_softmodem_params()) || get_softmodem_params()->sl_mode) { + uint16_t nr_band = get_softmodem_params()->band; + mac->nr_band = nr_band; + mac->ssb_start_subcarrier = UE[CC_id]->frame_parms.ssb_start_subcarrier; + nr_init_frame_parms_ue_sa(&UE[CC_id]->frame_parms, + downlink_frequency[CC_id][0], + uplink_frequency_offset[CC_id][0], + get_softmodem_params()->numerology, + nr_band); + } else { + do { + notifiedFIFO_elt_t *elt = pollNotifiedFIFO(&mac->input_nf); + if (!elt) { + break; } - } - if (get_nrUE_params()->num_ul_actors > 0) { - UE[CC_id]->ul_actors = calloc_or_fail(get_nrUE_params()->num_ul_actors, sizeof(*UE[CC_id]->ul_actors)); - for (int i = 0; i < get_nrUE_params()->num_ul_actors; i++) { - init_actor(&UE[CC_id]->ul_actors[i], "UL_", -1); - } - } - init_nr_ue_vars(UE[CC_id], inst); - - if (UE[CC_id]->sl_mode) { - AssertFatal(UE[CC_id]->sl_mode == 2, "Only Sidelink mode 2 supported. Mode 1 not yet supported\n"); - DevAssert(mac->if_module != NULL && mac->if_module->sl_phy_config_request != NULL); - nr_sl_phy_config_t *phycfg = &mac->SL_MAC_PARAMS->sl_phy_config; - phycfg->sl_config_req.sl_carrier_config.sl_num_rx_ant = get_nrUE_params()->nb_antennas_rx; - phycfg->sl_config_req.sl_carrier_config.sl_num_tx_ant = get_nrUE_params()->nb_antennas_tx; - mac->if_module->sl_phy_config_request(phycfg); - sl_nr_ue_phy_params_t *sl_phy = &UE[CC_id]->SL_UE_PHY_PARAMS; - nr_init_frame_parms_ue_sl(&sl_phy->sl_frame_params, - &sl_phy->sl_config, - get_softmodem_params()->threequarter_fs, - get_nrUE_params()->ofdm_offset_divisor); - sl_ue_phy_init(UE[CC_id]); - } - init_openair0(UE[CC_id]); + process_msg_rcc_to_mac(NotifiedFifoData(elt), inst); + delNotifiedFIFO_elt(elt); + } while (true); + fapi_nr_config_request_t *nrUE_config = &UE[CC_id]->nrUE_config; + nr_init_frame_parms_ue(&UE[CC_id]->frame_parms, nrUE_config, mac->nr_band); } - } - lock_memory_to_ram(); + UE[CC_id]->sl_mode = get_softmodem_params()->sl_mode; + init_actor(&UE[CC_id]->sync_actor, "SYNC_", -1); + if (get_nrUE_params()->num_dl_actors > 0) { + UE[CC_id]->dl_actors = calloc_or_fail(get_nrUE_params()->num_dl_actors, sizeof(*UE[CC_id]->dl_actors)); + for (int i = 0; i < get_nrUE_params()->num_dl_actors; i++) { + init_actor(&UE[CC_id]->dl_actors[i], "DL_", -1); + } + } + if (get_nrUE_params()->num_ul_actors > 0) { + UE[CC_id]->ul_actors = calloc_or_fail(get_nrUE_params()->num_ul_actors, sizeof(*UE[CC_id]->ul_actors)); + for (int i = 0; i < get_nrUE_params()->num_ul_actors; i++) { + init_actor(&UE[CC_id]->ul_actors[i], "UL_", -1); + } + } + init_nr_ue_vars(UE[CC_id], inst); - if (IS_SOFTMODEM_DOSCOPE) { - load_softscope("nr", PHY_vars_UE_g[0][0]); + if (UE[CC_id]->sl_mode) { + AssertFatal(UE[CC_id]->sl_mode == 2, "Only Sidelink mode 2 supported. Mode 1 not yet supported\n"); + DevAssert(mac->if_module != NULL && mac->if_module->sl_phy_config_request != NULL); + nr_sl_phy_config_t *phycfg = &mac->SL_MAC_PARAMS->sl_phy_config; + phycfg->sl_config_req.sl_carrier_config.sl_num_rx_ant = get_nrUE_params()->nb_antennas_rx; + phycfg->sl_config_req.sl_carrier_config.sl_num_tx_ant = get_nrUE_params()->nb_antennas_tx; + mac->if_module->sl_phy_config_request(phycfg); + sl_nr_ue_phy_params_t *sl_phy = &UE[CC_id]->SL_UE_PHY_PARAMS; + nr_init_frame_parms_ue_sl(&sl_phy->sl_frame_params, + &sl_phy->sl_config, + get_softmodem_params()->threequarter_fs, + get_nrUE_params()->ofdm_offset_divisor); + sl_ue_phy_init(UE[CC_id]); + } + init_openair0(UE[CC_id]); } - if (IS_SOFTMODEM_IMSCOPE_ENABLED) { - load_softscope("im", PHY_vars_UE_g[0][0]); - } - AssertFatal(!(IS_SOFTMODEM_IMSCOPE_ENABLED && IS_SOFTMODEM_IMSCOPE_RECORD_ENABLED), - "Data recoding and ImScope cannot be enabled at the same time\n"); - if (IS_SOFTMODEM_IMSCOPE_RECORD_ENABLED) { - load_module_shlib("imscope_record", NULL, 0, PHY_vars_UE_g[0][0]); - } - - for (int inst = 0; inst < NB_UE_INST; inst++) { - LOG_I(PHY,"Intializing UE Threads for instance %d ...\n", inst); - init_NR_UE_threads(PHY_vars_UE_g[inst][0]); - } - printf("UE threads created by %ld\n", gettid()); } + lock_memory_to_ram(); + + if (IS_SOFTMODEM_DOSCOPE) { + load_softscope("nr", PHY_vars_UE_g[0][0]); + } + if (IS_SOFTMODEM_IMSCOPE_ENABLED) { + load_softscope("im", PHY_vars_UE_g[0][0]); + } + AssertFatal(!(IS_SOFTMODEM_IMSCOPE_ENABLED && IS_SOFTMODEM_IMSCOPE_RECORD_ENABLED), + "Data recoding and ImScope cannot be enabled at the same time\n"); + if (IS_SOFTMODEM_IMSCOPE_RECORD_ENABLED) { + load_module_shlib("imscope_record", NULL, 0, PHY_vars_UE_g[0][0]); + } + + for (int inst = 0; inst < NB_UE_INST; inst++) { + LOG_I(PHY,"Intializing UE Threads for instance %d ...\n", inst); + init_NR_UE_threads(PHY_vars_UE_g[inst][0]); + } + printf("UE threads created by %ld\n", gettid()); + // wait for end of program printf("TYPE TO TERMINATE\n"); diff --git a/executables/nr-uesoftmodem.h b/executables/nr-uesoftmodem.h index 3ceb3e479e..df13e2e02e 100644 --- a/executables/nr-uesoftmodem.h +++ b/executables/nr-uesoftmodem.h @@ -137,8 +137,6 @@ extern int setup_nr_ue_buffers(PHY_VARS_NR_UE **phy_vars_ue, openair0_config_t * extern void fill_ue_band_info(void); extern void init_NR_UE(int, char *, char *, char *); extern void init_NR_UE_threads(PHY_VARS_NR_UE *ue); -void start_oai_nrue_threads(void); void *UE_thread(void *arg); void init_nr_ue_vars(PHY_VARS_NR_UE *ue, uint8_t UE_id); -void init_nrUE_standalone_thread(int ue_idx); #endif diff --git a/executables/softmodem-common.h b/executables/softmodem-common.h index d122b1a1d5..4dfa5eb680 100644 --- a/executables/softmodem-common.h +++ b/executables/softmodem-common.h @@ -105,7 +105,6 @@ extern "C" #define CONFIG_HLP_DISABLNBIOT "disable nb-iot, even if defined in config\n" #define CONFIG_HLP_USRP_THREAD "having extra thead for usrp tx\n" #define CONFIG_HLP_NFAPI "Change the nFAPI mode for NR 'MONOLITHIC', 'PNF', 'VNF', 'AERIAL','UE_STUB_PNF','UE_STUB_OFFNET','STANDALONE_PNF'\n" -#define CONFIG_L1_EMULATOR "Run in L1 emulated mode (disable PHY layer)\n" #define CONFIG_HLP_CONTINUOUS_TX "perform continuous transmission, even in TDD mode (to work around USRP issues)\n" #define CONFIG_HLP_STATS_DISABLE "disable globally the stats generation and persistence" #define CONFIG_HLP_NOITTI "Do not start itti threads, call queue processing in place, inside the caller thread" @@ -137,7 +136,6 @@ extern "C" #define NSA softmodem_params.nsa #define NODE_NUMBER softmodem_params.node_number #define NON_STOP softmodem_params.non_stop -#define EMULATE_L1 softmodem_params.emulate_l1 #define CONTINUOUS_TX softmodem_params.continuous_tx #define SYNC_REF softmodem_params.sync_ref #define DEFAULT_PDU_ID softmodem_params.default_pdu_session_id @@ -174,7 +172,6 @@ extern int usrp_tx_thread; {"usrp-tx-thread-config", CONFIG_HLP_USRP_THREAD, 0, .iptr=&usrp_tx_thread, .defstrval=0, TYPE_INT, 0}, \ {"nfapi", CONFIG_HLP_NFAPI, 0, .strptr=NULL, .defstrval="MONOLITHIC", TYPE_STRING, 0}, \ {"non-stop", CONFIG_HLP_NONSTOP, PARAMFLAG_BOOL, .iptr=&NON_STOP, .defintval=0, TYPE_INT, 0}, \ - {"emulate-l1", CONFIG_L1_EMULATOR, PARAMFLAG_BOOL, .iptr=&EMULATE_L1, .defintval=0, TYPE_INT, 0}, \ {"continuous-tx", CONFIG_HLP_CONTINUOUS_TX, PARAMFLAG_BOOL, .iptr=&CONTINUOUS_TX, .defintval=0, TYPE_INT, 0}, \ {"disable-stats", CONFIG_HLP_STATS_DISABLE, PARAMFLAG_BOOL, .iptr=&stats_disabled, .defintval=0, TYPE_INT, 0}, \ {"no-itti-threads", CONFIG_HLP_NOITTI, PARAMFLAG_BOOL, .iptr=&softmodem_params.no_itti, .defintval=0, TYPE_INT, 0}, \ @@ -228,7 +225,6 @@ extern int usrp_tx_thread; { .s5 = { NULL } }, \ { .s5 = { NULL } }, \ { .s5 = { NULL } }, \ - { .s5 = { NULL } }, \ } // clang-format on @@ -331,7 +327,6 @@ typedef struct { int nsa; uint16_t node_number; int non_stop; - int emulate_l1; int continuous_tx; uint32_t sync_ref; int no_itti; diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c index 52d5033457..92da66fdd6 100644 --- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c +++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c @@ -31,7 +31,6 @@ */ #include - #include "fapi_nr_ue_interface.h" #include "fapi_nr_ue_l1.h" #include "harq_nr.h" @@ -39,247 +38,11 @@ #include "PHY/defs_nr_UE.h" #include "PHY/impl_defs_nr.h" #include "utils.h" -#include "openair2/PHY_INTERFACE/queue_t.h" #include "SCHED_NR_UE/phy_sch_processing_time.h" #include "openair1/PHY/phy_extern_nr_ue.h" const char *const dl_pdu_type[] = {"DCI", "DLSCH", "RA_DLSCH", "SI_DLSCH", "P_DLSCH", "CSI_RS", "CSI_IM", "TA"}; const char *const ul_pdu_type[] = {"PRACH", "PUCCH", "PUSCH", "SRS"}; -queue_t nr_rx_ind_queue; -queue_t nr_crc_ind_queue; -queue_t nr_uci_ind_queue; -queue_t nr_rach_ind_queue; - -static void fill_uci_2_3_4(nfapi_nr_uci_pucch_pdu_format_2_3_4_t *pdu_2_3_4, - fapi_nr_ul_config_pucch_pdu *pucch_pdu) -{ - NR_UE_MAC_INST_t *mac = get_mac_inst(0); - memset(pdu_2_3_4, 0, sizeof(*pdu_2_3_4)); - pdu_2_3_4->handle = 0; - pdu_2_3_4->rnti = pucch_pdu->rnti; - pdu_2_3_4->pucch_format = 2; - pdu_2_3_4->ul_cqi = 255; - pdu_2_3_4->timing_advance = 0; - pdu_2_3_4->rssi = 0; - // TODO: Eventually check 38.212:Sect.631 to know when to use csi_part2, for now only using csi_part1 - pdu_2_3_4->pduBitmap = 4; - pdu_2_3_4->csi_part1.csi_part1_bit_len = mac->nr_ue_emul_l1.num_csi_reports; - int csi_part1_byte_len = (int)((pdu_2_3_4->csi_part1.csi_part1_bit_len / 8) + 1); - AssertFatal(!pdu_2_3_4->csi_part1.csi_part1_payload, "pdu_2_3_4->csi_part1.csi_part1_payload != NULL\n"); - pdu_2_3_4->csi_part1.csi_part1_payload = CALLOC(csi_part1_byte_len, - sizeof(pdu_2_3_4->csi_part1.csi_part1_payload)); - for (int k = 0; k < csi_part1_byte_len; k++) - { - pdu_2_3_4->csi_part1.csi_part1_payload[k] = (pucch_pdu->payload >> (k * 8)) & 0xff; - } - pdu_2_3_4->csi_part1.csi_part1_crc = 0; -} - -static void free_uci_inds(nfapi_nr_uci_indication_t *uci_ind) -{ - for (int k = 0; k < uci_ind->num_ucis; k++) - { - if (uci_ind->uci_list[k].pdu_type == NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE) - { - //nfapi_nr_uci_pucch_pdu_format_0_1_t *pdu_0_1 = &uci_ind->uci_list[k].pucch_pdu_format_0_1; - // Warning: pdu_0_1 is unused - } - if (uci_ind->uci_list[k].pdu_type == NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE) - { - nfapi_nr_uci_pucch_pdu_format_2_3_4_t *pdu_2_3_4 = &uci_ind->uci_list[k].pucch_pdu_format_2_3_4; - free(pdu_2_3_4->sr.sr_payload); - pdu_2_3_4->sr.sr_payload = NULL; - free(pdu_2_3_4->harq.harq_payload); - pdu_2_3_4->harq.harq_payload = NULL; - } - } - free(uci_ind->uci_list); - uci_ind->uci_list = NULL; - free(uci_ind); -} - -int8_t nr_ue_scheduled_response_stub(nr_scheduled_response_t *scheduled_response) { - - NR_UE_MAC_INST_t *mac = get_mac_inst(0); - - if (scheduled_response && scheduled_response->ul_config) { - int frame = scheduled_response->ul_config->frame; - int slot = scheduled_response->ul_config->slot; - fapi_nr_ul_config_request_pdu_t *it = fapiLockIterator(scheduled_response->ul_config, frame, slot); - while (it->pdu_type != FAPI_NR_END) { - switch (it->pdu_type) { - case FAPI_NR_UL_CONFIG_TYPE_PRACH: { - fapi_nr_ul_config_prach_pdu *prach_pdu = &it->prach_config_pdu; - nfapi_nr_rach_indication_t *rach_ind = CALLOC(1, sizeof(*rach_ind)); - rach_ind->sfn = frame; - rach_ind->slot = slot; - rach_ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION; - uint8_t pdu_index = 0; - rach_ind->pdu_list = CALLOC(1, sizeof(*rach_ind->pdu_list)); - rach_ind->number_of_pdus = 1; - rach_ind->pdu_list[pdu_index].phy_cell_id = prach_pdu->phys_cell_id; - rach_ind->pdu_list[pdu_index].symbol_index = prach_pdu->prach_start_symbol; - rach_ind->pdu_list[pdu_index].slot_index = prach_pdu->prach_slot; - rach_ind->pdu_list[pdu_index].freq_index = prach_pdu->num_ra; - rach_ind->pdu_list[pdu_index].avg_rssi = 128; - rach_ind->pdu_list[pdu_index].avg_snr = 0xff; // invalid for now - const int num_p = rach_ind->pdu_list[pdu_index].num_preamble; - AssertFatal(num_p == 1, "can handle only one preamble in preamble_list\n"); - rach_ind->pdu_list[pdu_index].num_preamble = 1; - rach_ind->pdu_list[pdu_index].preamble_list[0].preamble_index = prach_pdu->ra_PreambleIndex; - rach_ind->pdu_list[pdu_index].preamble_list[0].timing_advance = 0; - rach_ind->pdu_list[pdu_index].preamble_list[0].preamble_pwr = 0xffffffff; - - if (!put_queue(&nr_rach_ind_queue, rach_ind)) { - free(rach_ind->pdu_list); - free(rach_ind); - } - LOG_D(NR_MAC, "We have successfully filled the rach_ind queue with the recently filled rach ind\n"); - break; - } - case (FAPI_NR_UL_CONFIG_TYPE_PUSCH): { - nfapi_nr_rx_data_indication_t *rx_ind = CALLOC(1, sizeof(*rx_ind)); - nfapi_nr_crc_indication_t *crc_ind = CALLOC(1, sizeof(*crc_ind)); - nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu = &it->pusch_config_pdu; - if (pusch_config_pdu->tx_request_body.fapiTxPdu) { - rx_ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION; - rx_ind->sfn = frame; - rx_ind->slot = slot; - rx_ind->number_of_pdus = 1; - rx_ind->pdu_list = CALLOC(rx_ind->number_of_pdus, sizeof(*rx_ind->pdu_list)); - for (int j = 0; j < rx_ind->number_of_pdus; j++) { - fapi_nr_tx_request_body_t *tx_req_body = &pusch_config_pdu->tx_request_body; - rx_ind->pdu_list[j].handle = pusch_config_pdu->handle; - rx_ind->pdu_list[j].harq_id = pusch_config_pdu->pusch_data.harq_process_id; - rx_ind->pdu_list[j].pdu_length = tx_req_body->pdu_length; - rx_ind->pdu_list[j].pdu = CALLOC(tx_req_body->pdu_length, sizeof(*rx_ind->pdu_list[j].pdu)); - memcpy(rx_ind->pdu_list[j].pdu, tx_req_body->fapiTxPdu, tx_req_body->pdu_length * sizeof(*rx_ind->pdu_list[j].pdu)); - rx_ind->pdu_list[j].rnti = pusch_config_pdu->rnti; - /* TODO: Implement channel modeling to abstract TA and CQI. For now, - we hard code the values below since they are set in L1 and we are - abstracting L1. */ - rx_ind->pdu_list[j].timing_advance = 31; - rx_ind->pdu_list[j].ul_cqi = 255; - } - - crc_ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION; - crc_ind->number_crcs = rx_ind->number_of_pdus; - crc_ind->sfn = frame; - crc_ind->slot = slot; - crc_ind->crc_list = CALLOC(crc_ind->number_crcs, sizeof(*crc_ind->crc_list)); - for (int j = 0; j < crc_ind->number_crcs; j++) { - crc_ind->crc_list[j].handle = pusch_config_pdu->handle; - crc_ind->crc_list[j].harq_id = pusch_config_pdu->pusch_data.harq_process_id; - LOG_D(NR_MAC, "This is the harq pid %d for crc_list[%d]\n", crc_ind->crc_list[j].harq_id, j); - LOG_D(NR_MAC, "This is sched sfn/sl [%d %d] and crc sfn/sl [%d %d]\n", frame, slot, crc_ind->sfn, crc_ind->slot); - crc_ind->crc_list[j].num_cb = pusch_config_pdu->pusch_data.num_cb; - crc_ind->crc_list[j].rnti = pusch_config_pdu->rnti; - crc_ind->crc_list[j].tb_crc_status = 0; - crc_ind->crc_list[j].timing_advance = 31; - crc_ind->crc_list[j].ul_cqi = 255; - emul_l1_harq_t *harq = &mac->nr_ue_emul_l1.harq[crc_ind->crc_list[j].harq_id]; - AssertFatal(harq->active_ul_harq_sfn == -1 && harq->active_ul_harq_slot == -1, - "We did not send an active CRC when we should have!\n"); - harq->active_ul_harq_sfn = crc_ind->sfn; - harq->active_ul_harq_slot = crc_ind->slot; - LOG_D(NR_MAC, - "This is sched sfn/sl [%d %d] and crc sfn/sl [%d %d] with mcs_index in ul_cqi -> %d\n", - frame, - slot, - crc_ind->sfn, - crc_ind->slot, - pusch_config_pdu->mcs_index); - } - - if (!put_queue(&nr_rx_ind_queue, rx_ind)) { - LOG_E(NR_MAC, "Put_queue failed for rx_ind\n"); - for (int i = 0; i < rx_ind->number_of_pdus; i++) { - free(rx_ind->pdu_list[i].pdu); - rx_ind->pdu_list[i].pdu = NULL; - } - - free(rx_ind->pdu_list); - rx_ind->pdu_list = NULL; - free(rx_ind); - rx_ind = NULL; - } - if (!put_queue(&nr_crc_ind_queue, crc_ind)) { - LOG_E(NR_MAC, "Put_queue failed for crc_ind\n"); - free(crc_ind->crc_list); - crc_ind->crc_list = NULL; - free(crc_ind); - crc_ind = NULL; - } - - LOG_D(PHY, "In %s: Filled queue rx/crc_ind which was filled by ulconfig. \n", __FUNCTION__); - } - break; - } - case FAPI_NR_UL_CONFIG_TYPE_PUCCH: { - nfapi_nr_uci_indication_t *uci_ind = CALLOC(1, sizeof(*uci_ind)); - uci_ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION; - uci_ind->sfn = frame; - uci_ind->slot = slot; - uci_ind->num_ucis = 1; - uci_ind->uci_list = CALLOC(uci_ind->num_ucis, sizeof(*uci_ind->uci_list)); - for (int j = 0; j < uci_ind->num_ucis; j++) { - LOG_D(NR_MAC, "pucch_config_pdu.n_bit = %d\n", it->pucch_config_pdu.n_bit); - if (it->pucch_config_pdu.n_bit > 3 && mac->nr_ue_emul_l1.num_csi_reports > 0) { - uci_ind->uci_list[j].pdu_type = NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE; - uci_ind->uci_list[j].pdu_size = sizeof(nfapi_nr_uci_pucch_pdu_format_2_3_4_t); - nfapi_nr_uci_pucch_pdu_format_2_3_4_t *pdu_2_3_4 = &uci_ind->uci_list[j].pucch_pdu_format_2_3_4; - fill_uci_2_3_4(pdu_2_3_4, &it->pucch_config_pdu); - } else { - nfapi_nr_uci_pucch_pdu_format_0_1_t *pdu_0_1 = &uci_ind->uci_list[j].pucch_pdu_format_0_1; - uci_ind->uci_list[j].pdu_type = NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE; - uci_ind->uci_list[j].pdu_size = sizeof(nfapi_nr_uci_pucch_pdu_format_0_1_t); - memset(pdu_0_1, 0, sizeof(*pdu_0_1)); - pdu_0_1->handle = 0; - pdu_0_1->rnti = it->pucch_config_pdu.rnti; - pdu_0_1->pucch_format = 1; - pdu_0_1->ul_cqi = 255; - pdu_0_1->timing_advance = 0; - pdu_0_1->rssi = 0; - if (mac->nr_ue_emul_l1.num_harqs > 0) { - int harq_index = 0; - pdu_0_1->pduBitmap = 2; // (value->pduBitmap >> 1) & 0x01) == HARQ and (value->pduBitmap) & 0x01) == SR - pdu_0_1->harq.num_harq = mac->nr_ue_emul_l1.num_harqs; - pdu_0_1->harq.harq_confidence_level = 0; - int harq_pid = -1; - for (int k = 0; k < NR_MAX_HARQ_PROCESSES; k++) { - if (mac->nr_ue_emul_l1.harq[k].active && mac->nr_ue_emul_l1.harq[k].active_dl_harq_sfn == uci_ind->sfn - && mac->nr_ue_emul_l1.harq[k].active_dl_harq_slot == uci_ind->slot) { - mac->nr_ue_emul_l1.harq[k].active = false; - harq_pid = k; - AssertFatal(harq_index < pdu_0_1->harq.num_harq, "Invalid harq_index %d\n", harq_index); - pdu_0_1->harq.harq_list[harq_index].harq_value = !mac->dl_harq_info[k].ack; - harq_index++; - } - } - AssertFatal(harq_pid != -1, "No active harq_pid, sfn_slot = %u.%u", uci_ind->sfn, uci_ind->slot); - } - } - } - - LOG_D(NR_PHY, "Sending UCI with %d PDUs in sfn.slot %d/%d\n", uci_ind->num_ucis, uci_ind->sfn, uci_ind->slot); - NR_UL_IND_t ul_info = { - .uci_ind = *uci_ind, - }; - send_nsa_standalone_msg(&ul_info, uci_ind->header.message_id); - free_uci_inds(uci_ind); - break; - } - - default: - LOG_W(NR_MAC, "Unknown ul_config->pdu_type %d\n", it->pdu_type); - break; - } - it++; - } - release_ul_config(it, true); - } - return 0; -} static void configure_dlsch(NR_UE_DLSCH_t *dlsch0, NR_DL_UE_HARQ_t *harq_list, diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h index 68182ab9ec..6e73a0f855 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h @@ -320,35 +320,6 @@ typedef struct { uint8_t nbits; } dci_field_t; -typedef struct { - /* The active harq sfn/slot field was created to save the - scheduled SFN/Slot transmission for the ACK/NAK. If we - do not save it, then we have to calculate it again as the - NRUE MAC layer already does in get_downlink_ack(). */ - int active_dl_harq_sfn; - int active_dl_harq_slot; - int active_ul_harq_sfn; - int active_ul_harq_slot; - bool active; -} emul_l1_harq_t; - -typedef struct { - bool expected_sib; - bool index_has_sib[NR_MAX_HARQ_PROCESSES]; - bool expected_rar; - bool index_has_rar[NR_MAX_HARQ_PROCESSES]; - bool expected_dci; - bool index_has_dci[NR_MAX_HARQ_PROCESSES]; - emul_l1_harq_t harq[NR_MAX_HARQ_PROCESSES]; - int active_uci_sfn_slot; - int num_srs; - int num_harqs; - int num_csi_reports; - uint8_t pmi; - uint8_t ri; - uint8_t cqi; -} nr_emulated_l1_t; - typedef struct { uint8_t format_indicator; //1 bit diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index bb37c3d582..f592423c5a 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -1942,8 +1942,7 @@ void nr_rrc_mac_config_req_sib1(module_id_t module_id, int cc_idP, NR_SIB1_t *si if (mac->state == UE_RECEIVING_SIB && can_start_ra) mac->state = UE_PERFORMING_RA; - if (!get_softmodem_params()->emulate_l1) - mac->if_module->phy_config_request(&mac->phy_config); + mac->if_module->phy_config_request(&mac->phy_config); ret = pthread_mutex_unlock(&mac->if_mutex); AssertFatal(!ret, "mutex failed %d\n", ret); } @@ -2002,13 +2001,11 @@ static void handle_reconfiguration_with_sync(NR_UE_MAC_INST_t *mac, ra->ra_state = nrRA_UE_IDLE; nr_ue_mac_default_configs(mac); - if (!get_softmodem_params()->emulate_l1) { - mac->synch_request.Mod_id = mac->ue_id; - mac->synch_request.CC_id = cc_idP; - mac->synch_request.synch_req.target_Nid_cell = mac->physCellId; - mac->if_module->synch_request(&mac->synch_request); - mac->if_module->phy_config_request(&mac->phy_config); - } + mac->synch_request.Mod_id = mac->ue_id; + mac->synch_request.CC_id = cc_idP; + mac->synch_request.synch_req.target_Nid_cell = mac->physCellId; + mac->if_module->synch_request(&mac->synch_request); + mac->if_module->phy_config_request(&mac->phy_config); } static void configure_physicalcellgroup(NR_UE_MAC_INST_t *mac, diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index 3e41ec0980..b7ebd5a651 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -646,8 +646,6 @@ typedef struct NR_UE_MAC_INST_s { NR_TimeAlignmentTimer_t timeAlignmentTimerCommon; NR_timer_t time_alignment_timer; - nr_emulated_l1_t nr_ue_emul_l1; - pthread_mutex_t mutex_dl_info; //SIDELINK MAC PARAMETERS diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index 3f3df90cde..c6385e765c 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -1253,7 +1253,6 @@ void prepare_msg4_msgb_feedback(NR_UE_MAC_INST_t *mac, int pid, int ack_nack) NR_UE_DL_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[pid]; int sched_slot = current_harq->ul_slot; int sched_frame = current_harq->ul_frame; - mac->nr_ue_emul_l1.num_harqs = 1; PUCCH_sched_t pucch = {.n_CCE = current_harq->n_CCE, .N_CCE = current_harq->N_CCE, .ack_payload = ack_nack, diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index f2f783869c..0b1d7dfaa9 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -2420,11 +2420,6 @@ bool get_downlink_ack(NR_UE_MAC_INST_t *mac, frame_t frame, int slot, PUCCH_sche dl_harq_pid, current_harq->ul_frame, current_harq->ul_slot); /* check if current tx slot should transmit downlink acknowlegment */ if (current_harq->ul_frame == frame && current_harq->ul_slot == slot) { - if (get_softmodem_params()->emulate_l1) { - mac->nr_ue_emul_l1.harq[dl_harq_pid].active = true; - mac->nr_ue_emul_l1.harq[dl_harq_pid].active_dl_harq_sfn = frame; - mac->nr_ue_emul_l1.harq[dl_harq_pid].active_dl_harq_slot = slot; - } if (res_ind != -1 && res_ind != current_harq->pucch_resource_indicator) LOG_E(NR_MAC, "Value of pucch_resource_indicator %d not matching with what set before %d (Possibly due to a false DCI) \n", @@ -3037,18 +3032,6 @@ static csi_payload_t get_csirs_RI_PMI_CQI_payload(NR_UE_MAC_INST_t *mac, int pmi_x1_bitlen = csi_report->csi_meas_bitlen.pmi_x1_bitlen[mac->l1_measurements.rank_indicator]; int pmi_x2_bitlen = csi_report->csi_meas_bitlen.pmi_x2_bitlen[mac->l1_measurements.rank_indicator]; int cqi_bitlen = csi_report->csi_meas_bitlen.cqi_bitlen[mac->l1_measurements.rank_indicator]; - - if (get_softmodem_params()->emulate_l1) { - static const uint8_t mcs_to_cqi[] = {0, 1, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, - 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15}; - CHECK_INDEX(nr_bler_data, NR_NUM_MCS - 1); - int mcs = get_mcs_from_sinr(nr_bler_data, (mac->nr_ue_emul_l1.cqi - 640) * 0.1); - CHECK_INDEX(mcs_to_cqi, mcs); - mac->l1_measurements.rank_indicator = mac->nr_ue_emul_l1.ri; - mac->l1_measurements.i1 = mac->nr_ue_emul_l1.pmi; - mac->l1_measurements.cqi = mcs_to_cqi[mcs]; - } - int padding_bitlen = 0; // TODO: Improvements will be needed to cri_bitlen>0 and pmi_x1_bitlen>0 if (mapping_type == ON_PUSCH) { @@ -4291,21 +4274,6 @@ static void nr_ue_process_rar(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *d handle_rar_reception(mac, rar, frame, slot); if (ra->cfra) nr_ra_succeeded(mac, dl_info->gNB_index, frame, slot); - if (get_softmodem_params()->emulate_l1) { - /* When we are emulating L1 with multiple UEs, the rx_indication will have - multiple RAR PDUs. The code would previously handle each of these PDUs, - but it should only be handling the single RAR that matches the current - UE. */ - LOG_I(NR_MAC, "RAR PDU found for our UE with PDU index %d\n", pdu_id); - dl_info->rx_ind->number_pdus = 1; - if (pdu_id != 0) { - memcpy(&dl_info->rx_ind->rx_indication_body[0], - &dl_info->rx_ind->rx_indication_body[pdu_id], - sizeof(fapi_nr_rx_indication_body_t)); - } - mac->nr_ue_emul_l1.expected_rar = false; - memset(mac->nr_ue_emul_l1.index_has_rar, 0, sizeof(mac->nr_ue_emul_l1.index_has_rar)); - } break; } if (rarh->E == 0) { diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 16af9b4883..03bd8b6fd4 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -1718,10 +1718,6 @@ static bool schedule_uci_on_pusch(NR_UE_MAC_INST_t *mac, static void nr_ue_pucch_scheduler(NR_UE_MAC_INST_t *mac, frame_t frame, int slot) { PUCCH_sched_t pucch[3] = {0}; // TODO the size might change in the future in case of multiple SR or multiple CSI in a slot - - mac->nr_ue_emul_l1.num_srs = 0; - mac->nr_ue_emul_l1.num_harqs = 0; - mac->nr_ue_emul_l1.num_csi_reports = 0; int num_res = 0; if (mac->ra.ra_pucch) { @@ -1771,9 +1767,6 @@ static void nr_ue_pucch_scheduler(NR_UE_MAC_INST_t *mac, frame_t frame, int slot pucch[j].n_harq, pucch[j].n_sr, pucch[j].n_csi); - mac->nr_ue_emul_l1.num_srs = pucch[j].n_sr; - mac->nr_ue_emul_l1.num_harqs = pucch[j].n_harq; - mac->nr_ue_emul_l1.num_csi_reports = pucch[j].n_csi; // checking if we need to schedule pucch[j] on PUSCH if (schedule_uci_on_pusch(mac, frame, slot, &pucch[j], mac->current_UL_BWP)) @@ -1784,9 +1777,6 @@ static void nr_ue_pucch_scheduler(NR_UE_MAC_INST_t *mac, frame_t frame, int slot LOG_E(NR_MAC, "Error in pucch allocation\n"); return; } - DevAssert(mac->current_DL_BWP != NULL); - int mu = mac->current_DL_BWP->scs; - mac->nr_ue_emul_l1.active_uci_sfn_slot = NFAPI_SFNSLOT2DEC(mu, frame, slot); int ret = nr_ue_configure_pucch(mac, slot, frame, diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c index f93044f9cd..e0afa1ee35 100644 --- a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c +++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c @@ -1262,7 +1262,7 @@ pdcp_run ( // IP/NAS -> PDCP traffic : TX, read the pkt from the upper layer buffer // if (LINK_ENB_PDCP_TO_GTPV1U && ctxt_pP->enb_flag == ENB_FLAG_NO) { - if (!get_softmodem_params()->emulate_l1 && (IS_SOFTMODEM_NOS1 || ctxt_pP->enb_flag == ENB_FLAG_NO)) { + if (IS_SOFTMODEM_NOS1 || ctxt_pP->enb_flag == ENB_FLAG_NO) { pdcp_fifo_read_input_sdus(ctxt_pP); } @@ -1272,9 +1272,7 @@ pdcp_run ( } else { start_meas(&UE_pdcp_stats[ctxt_pP->module_id].pdcp_ip); } - if (!get_softmodem_params()->emulate_l1) { - pdcp_fifo_flush_sdus(ctxt_pP); - } + pdcp_fifo_flush_sdus(ctxt_pP); if (ctxt_pP->enb_flag) { stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].pdcp_ip); diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.h b/openair2/NR_PHY_INTERFACE/NR_IF_Module.h index ce6acffc2c..52a0f28871 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.h +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.h @@ -138,8 +138,6 @@ void NR_IF_Module_kill(int Mod_id); void NR_UL_indication(NR_UL_IND_t *UL_INFO); -void RCconfig_nr_ue_macrlc(void); - /*Interface for Downlink, transmitting the DLSCH SDU, DCI SDU*/ void NR_Schedule_Response(NR_Sched_Rsp_t *Sched_INFO); diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c index 1f86c61be5..23cd60b25f 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c @@ -30,41 +30,16 @@ * \warning */ -#include -#include -#include - #include "PHY/defs_nr_UE.h" #include "NR_IF_Module.h" #include "NR_MAC_UE/mac_proto.h" #include "assertions.h" #include "SCHED_NR_UE/fapi_nr_ue_l1.h" -#include "executables/softmodem-common.h" #include "openair2/RRC/NR_UE/L2_interface_ue.h" -#include "openair2/GNB_APP/L1_nr_paramdef.h" -#include "openair2/GNB_APP/gnb_paramdef.h" -#include "radio/ETHERNET/if_defs.h" -#include -#include "openair2/GNB_APP/MACRLC_nr_paramdef.h" #define MAX_IF_MODULES 100 -UL_IND_t *UL_INFO = NULL; - -static eth_params_t stub_eth_params; static nr_ue_if_module_t *nr_ue_if_module_inst[MAX_IF_MODULES]; -static int ue_tx_sock_descriptor = -1; -static int ue_rx_sock_descriptor = -1; -static int g_harq_pid; -sem_t sfn_slot_semaphore; - -queue_t nr_sfn_slot_queue; -queue_t nr_chan_param_queue; -queue_t nr_dl_tti_req_queue; -queue_t nr_tx_req_queue; -queue_t nr_ul_dci_req_queue; -queue_t nr_ul_tti_req_queue; -static void save_pdsch_pdu_for_crnti(nfapi_nr_dl_tti_request_t *dl_tti_request); void print_ue_mac_stats(const module_id_t mod, const int frame_rx, const int slot_rx) { @@ -126,956 +101,6 @@ void print_ue_mac_stats(const module_id_t mod, const int frame_rx, const int slo AssertFatal(!ret, "mutex failed %d\n", ret); } -void nrue_init_standalone_socket(int tx_port, int rx_port) -{ - { - struct sockaddr_in server_address; - int addr_len = sizeof(server_address); - memset(&server_address, 0, addr_len); - server_address.sin_family = AF_INET; - server_address.sin_port = htons(tx_port); - - int sd = socket(server_address.sin_family, SOCK_DGRAM, 0); - if (sd < 0) - { - LOG_E(NR_MAC, "Socket creation error standalone PNF\n"); - return; - } - - if (inet_pton(server_address.sin_family, stub_eth_params.remote_addr, &server_address.sin_addr) <= 0) - { - LOG_E(NR_MAC, "Invalid standalone PNF Address\n"); - close(sd); - return; - } - - // Using connect to use send() instead of sendto() - if (connect(sd, (struct sockaddr *)&server_address, addr_len) < 0) - { - LOG_E(NR_MAC, "Connection to standalone PNF failed: %s\n", strerror(errno)); - close(sd); - return; - } - assert(ue_tx_sock_descriptor == -1); - ue_tx_sock_descriptor = sd; - LOG_T(NR_RRC, "Successfully set up tx_socket in %s.\n", __FUNCTION__); - } - - { - struct sockaddr_in server_address; - int addr_len = sizeof(server_address); - memset(&server_address, 0, addr_len); - server_address.sin_family = AF_INET; - server_address.sin_addr.s_addr = INADDR_ANY; - server_address.sin_port = htons(rx_port); - - int sd = socket(server_address.sin_family, SOCK_DGRAM, 0); - if (sd < 0) - { - LOG_E(MAC, "Socket creation error standalone PNF\n"); - return; - } - - if (bind(sd, (struct sockaddr *)&server_address, addr_len) < 0) - { - LOG_E(NR_MAC, "Connection to standalone PNF failed: %s\n", strerror(errno)); - close(sd); - return; - } - assert(ue_rx_sock_descriptor == -1); - ue_rx_sock_descriptor = sd; - LOG_T(NR_RRC, "Successfully set up rx_socket in %s.\n", __FUNCTION__); - } - LOG_D(NR_RRC, "NRUE standalone socket info: tx_port %d rx_port %d on %s.\n", - tx_port, rx_port, stub_eth_params.remote_addr); -} - -void send_nsa_standalone_msg(NR_UL_IND_t *UL_INFO, uint16_t msg_id) -{ - switch(msg_id) - { - case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: - { - char buffer[NFAPI_MAX_PACKED_MESSAGE_SIZE]; - LOG_T(NR_MAC, "RACH header id :%d\n", UL_INFO->rach_ind.header.message_id); - int encoded_size = nfapi_nr_p7_message_pack(&UL_INFO->rach_ind, buffer, sizeof(buffer), NULL); - if (encoded_size <= 0) - { - LOG_E(NR_MAC, "nfapi_nr_p7_message_pack has failed. Encoded size = %d\n", encoded_size); - return; - } - - LOG_D(NR_MAC, "NR_RACH_IND sent to Proxy, Size: %d Frame %d Slot %d Num PDUS %d\n", encoded_size, - UL_INFO->rach_ind.sfn, UL_INFO->rach_ind.slot, UL_INFO->rach_ind.number_of_pdus); - if (send(ue_tx_sock_descriptor, buffer, encoded_size, 0) < 0) - { - LOG_E(NR_MAC, "Send Proxy NR_UE failed\n"); - return; - } - break; - } - case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION: - { - char buffer[NFAPI_MAX_PACKED_MESSAGE_SIZE]; - LOG_T(NR_MAC, "RX header id :%d\n", UL_INFO->rx_ind.header.message_id); - int encoded_size = nfapi_nr_p7_message_pack(&UL_INFO->rx_ind, buffer, sizeof(buffer), NULL); - if (encoded_size <= 0) - { - LOG_E(NR_MAC, "nfapi_nr_p7_message_pack has failed. Encoded size = %d\n", encoded_size); - return; - } - - LOG_D(NR_MAC, "NR_RX_IND sent to Proxy, Size: %d Frame %d Slot %d Num PDUS %d\n", encoded_size, - UL_INFO->rx_ind.sfn, UL_INFO->rx_ind.slot, UL_INFO->rx_ind.number_of_pdus); - if (send(ue_tx_sock_descriptor, buffer, encoded_size, 0) < 0) - { - LOG_E(NR_MAC, "Send Proxy NR_UE failed\n"); - return; - } - break; - } - case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION: - { - char buffer[NFAPI_MAX_PACKED_MESSAGE_SIZE]; - LOG_T(NR_MAC, "CRC header id :%d\n", UL_INFO->crc_ind.header.message_id); - int encoded_size = nfapi_nr_p7_message_pack(&UL_INFO->crc_ind, buffer, sizeof(buffer), NULL); - if (encoded_size <= 0) - { - LOG_E(NR_MAC, "nfapi_nr_p7_message_pack has failed. Encoded size = %d\n", encoded_size); - return; - } - - LOG_D(NR_MAC, "NR_CRC_IND sent to Proxy, Size: %d Frame %d Slot %d Num PDUS %d\n", encoded_size, - UL_INFO->crc_ind.sfn, UL_INFO->crc_ind.slot, UL_INFO->crc_ind.number_crcs); - if (send(ue_tx_sock_descriptor, buffer, encoded_size, 0) < 0) - { - LOG_E(NR_MAC, "Send Proxy NR_UE failed\n"); - return; - } - break; - } - case NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION: - { - char buffer[NFAPI_MAX_PACKED_MESSAGE_SIZE]; - LOG_D(NR_MAC, "UCI header id :%d\n", UL_INFO->uci_ind.header.message_id); - int encoded_size = nfapi_nr_p7_message_pack(&UL_INFO->uci_ind, buffer, sizeof(buffer), NULL); - if (encoded_size <= 0) - { - LOG_E(NR_MAC, "nfapi_nr_p7_message_pack has failed. Encoded size = %d\n", encoded_size); - return; - } - - LOG_D(NR_MAC, "NR_UCI_IND sent to Proxy, Size: %d Frame %d Slot %d Num PDUS %d\n", encoded_size, - UL_INFO->uci_ind.sfn, UL_INFO->uci_ind.slot, UL_INFO->uci_ind.num_ucis); - if (send(ue_tx_sock_descriptor, buffer, encoded_size, 0) < 0) - { - LOG_E(NR_MAC, "Send Proxy NR_UE failed\n"); - return; - } - break; - } - case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION: - break; - default: - break; - } -} - -bool sfn_slot_matcher(void *sfn_slot_s, void *candidate) -{ - nfapi_p7_message_header_t *msg = candidate; - const struct sfn_slot_s *sfn_sf = (const struct sfn_slot_s *)sfn_slot_s; - - switch (msg->message_id) - { - case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: - { - nfapi_nr_rach_indication_t *ind = candidate; - return sfn_sf->sfn == ind->sfn && sfn_sf->slot == ind->slot; - } - - case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION: - { - nfapi_nr_rx_data_indication_t *ind = candidate; - return sfn_sf->sfn == ind->sfn && sfn_sf->slot == ind->slot; - } - - case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION: - { - nfapi_nr_crc_indication_t *ind = candidate; - return sfn_sf->sfn == ind->sfn && sfn_sf->slot == ind->slot; - } - - case NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION: - { - nfapi_nr_uci_indication_t *ind = candidate; - return sfn_sf->sfn == ind->sfn && sfn_sf->slot == ind->slot; - } - - case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: - { - nfapi_nr_dl_tti_request_t *ind = candidate; - return sfn_sf->sfn == ind->SFN && sfn_sf->slot == ind->Slot; - } - - case NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST: - { - nfapi_nr_tx_data_request_t *ind = candidate; - return sfn_sf->sfn == ind->SFN && sfn_sf->slot == ind->Slot; - } - - case NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST: - { - nfapi_nr_ul_dci_request_t *ind = candidate; - return sfn_sf->sfn == ind->SFN && sfn_sf->slot == ind->Slot; - } - - case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: - { - nfapi_nr_ul_tti_request_t *ind = candidate; - return sfn_sf->sfn == ind->SFN && sfn_sf->slot == ind->Slot; - } - - default: - LOG_E(NR_MAC, "sfn_slot_match bad ID: %d\n", msg->message_id); - - } - - return false; -} - -static void fill_dl_info_with_pdcch(fapi_nr_dci_indication_t *dci, nfapi_nr_dl_dci_pdu_t *rx_dci, int idx) -{ - int num_bytes = (rx_dci->PayloadSizeBits + 7) / 8; - LOG_D(NR_PHY, "[%d, %d] PDCCH DCI (Payload) for rnti %x with PayloadSizeBits %d, num_bytes %d\n", - dci->SFN, dci->slot, rx_dci->RNTI, rx_dci->PayloadSizeBits, num_bytes); - for (int k = 0; k < num_bytes; k++) - { - LOG_D(NR_MAC, "PDCCH DCI PDU payload[%d] = %d\n", k, rx_dci->Payload[k]); - dci->dci_list[idx].payloadBits[k] = rx_dci->Payload[k]; - } - dci->dci_list[idx].payloadSize = rx_dci->PayloadSizeBits; - dci->dci_list[idx].rnti = rx_dci->RNTI; - dci->dci_list[idx].n_CCE = rx_dci->CceIndex; - dci->dci_list[idx].N_CCE = rx_dci->AggregationLevel; - dci->number_of_dcis = idx + 1; -} - -static void fill_mib_in_rx_ind(nfapi_nr_dl_tti_request_pdu_t *pdu_list, fapi_nr_rx_indication_t *rx_ind, int pdu_idx, int pdu_type) -{ - AssertFatal(pdu_idx < sizeof(rx_ind->rx_indication_body) / sizeof(rx_ind->rx_indication_body[0]), - "pdu_index (%d) is greater than rx_indication_body size!\n", pdu_idx); - AssertFatal(pdu_idx == rx_ind->number_pdus, "Invalid pdu_idx %d!\n", pdu_idx); - - LOG_T(NR_MAC, "Recevied an SSB and are filling rx_ind with the MIB!\n"); - - nfapi_nr_dl_tti_ssb_pdu_rel15_t *ssb_pdu = &pdu_list->ssb_pdu.ssb_pdu_rel15; - rx_ind->rx_indication_body[pdu_idx].ssb_pdu.cell_id = ssb_pdu->PhysCellId; - rx_ind->rx_indication_body[pdu_idx].ssb_pdu.pdu[0] = (ssb_pdu->bchPayload) & 0xff; - rx_ind->rx_indication_body[pdu_idx].ssb_pdu.pdu[1] = (ssb_pdu->bchPayload >> 8) & 0xff; - rx_ind->rx_indication_body[pdu_idx].ssb_pdu.pdu[2] = (ssb_pdu->bchPayload >> 16) & 0xff; - rx_ind->rx_indication_body[pdu_idx].ssb_pdu.ssb_index = ssb_pdu->SsbBlockIndex; - rx_ind->rx_indication_body[pdu_idx].ssb_pdu.ssb_length = pdu_list->PDUSize; - rx_ind->rx_indication_body[pdu_idx].ssb_pdu.ssb_start_subcarrier = ssb_pdu->SsbSubcarrierOffset; - rx_ind->rx_indication_body[pdu_idx].ssb_pdu.decoded_pdu = true; - rx_ind->rx_indication_body[pdu_idx].pdu_type = pdu_type; - rx_ind->number_pdus = pdu_idx + 1; -} - -static bool is_my_dci(NR_UE_MAC_INST_t *mac, nfapi_nr_dl_dci_pdu_t *received_pdu) -{ - /* For multiple UEs, we need to be able to filter the rx'd messages by - the RNTI. The filtering is different between NSA mode and SA mode. - NSA mode has a two step CFRA procedure and SA has a 4 step procedure. - We only need to check if the rx'd RNTI doesnt match the CRNTI if the RAR - has been processed already, in NSA mode. - In SA, depending on the RA state, we can have a SIB (0xffff), RAR (0x10b), - Msg3 (TC_RNTI) or an actual DCI message (CRNTI). When we get Msg3, the - MAC instance of the UE still has a CRNTI = 0. We should only check if the - CRNTI doesnt match the received RNTI in SA mode if Msg3 has been processed - already. Only once the RA procedure succeeds is the CRNTI value updated - to the TC_RNTI. */ - if (get_softmodem_params()->nsa) { - if (received_pdu->RNTI != mac->crnti && (received_pdu->RNTI != mac->ra.ra_rnti)) - return false; - } - if (IS_SA_MODE(get_softmodem_params())) { - if (mac->state == UE_NOT_SYNC) - return false; - if (received_pdu->RNTI == 0xFFFF) - return false; - if (received_pdu->RNTI != mac->crnti && mac->ra.ra_state == nrRA_SUCCEEDED) - return false; - if (received_pdu->RNTI != mac->ra.t_crnti && mac->ra.ra_state == nrRA_WAIT_CONTENTION_RESOLUTION) - return false; - if (received_pdu->RNTI != 0x10b && mac->ra.ra_state == nrRA_WAIT_RAR) - return false; - if (received_pdu->RNTI != 0xFFFF && mac->ra.ra_state <= nrRA_GENERATE_PREAMBLE) - return false; - } - return true; -} - -static void copy_dl_tti_req_to_dl_info(nr_downlink_indication_t *dl_info, nfapi_nr_dl_tti_request_t *dl_tti_request) -{ - NR_UE_MAC_INST_t *mac = get_mac_inst(dl_info->module_id); - mac->nr_ue_emul_l1.expected_sib = false; - memset(mac->nr_ue_emul_l1.index_has_sib, 0, sizeof(mac->nr_ue_emul_l1.index_has_sib)); - mac->nr_ue_emul_l1.expected_rar = false; - memset(mac->nr_ue_emul_l1.index_has_rar, 0, sizeof(mac->nr_ue_emul_l1.index_has_rar)); - mac->nr_ue_emul_l1.expected_dci = false; - memset(mac->nr_ue_emul_l1.index_has_dci, 0, sizeof(mac->nr_ue_emul_l1.index_has_dci)); - int pdu_idx = 0; - - int num_pdus = dl_tti_request->dl_tti_request_body.nPDUs; - AssertFatal(num_pdus >= 0, "Invalid dl_tti_request number of PDUS\n"); - - for (int i = 0; i < num_pdus; i++) - { - nfapi_nr_dl_tti_request_pdu_t *pdu_list = &dl_tti_request->dl_tti_request_body.dl_tti_pdu_list[i]; - if (pdu_list->PDUType == NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE) - { - LOG_D(NR_PHY, "[%d, %d] PDSCH PDU for rnti %x\n", - dl_tti_request->SFN, dl_tti_request->Slot, pdu_list->pdsch_pdu.pdsch_pdu_rel15.rnti); - } - - if (pdu_list->PDUType == NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE) - { - LOG_D(NR_PHY, "[%d, %d] PDCCH DCI PDU (Format for incoming PDSCH PDU)\n", - dl_tti_request->SFN, dl_tti_request->Slot); - uint16_t num_dcis = pdu_list->pdcch_pdu.pdcch_pdu_rel15.numDlDci; - if (num_dcis > 0) - { - if (!dl_info->dci_ind) - { - dl_info->dci_ind = CALLOC(1, sizeof(fapi_nr_dci_indication_t)); - } - dl_info->dci_ind->SFN = dl_tti_request->SFN; - dl_info->dci_ind->slot = dl_tti_request->Slot; - AssertFatal(num_dcis <= sizeof(dl_info->dci_ind->dci_list) / sizeof(dl_info->dci_ind->dci_list[0]), - "The number of DCIs is greater than dci_list"); - for (int j = 0; j < num_dcis; j++) - { - nfapi_nr_dl_dci_pdu_t *dci_pdu_list = &pdu_list->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[j]; - if (!is_my_dci(mac, dci_pdu_list)) - { - continue; - } - fill_dl_info_with_pdcch(dl_info->dci_ind, dci_pdu_list, pdu_idx); - if (dci_pdu_list->RNTI == 0xffff) - { - mac->nr_ue_emul_l1.expected_sib = true; - mac->nr_ue_emul_l1.index_has_sib[j] = true; - LOG_T(NR_MAC, "Setting index_has_sib[%d] = true\n", j); - } - else if (dci_pdu_list->RNTI == mac->ra.ra_rnti) - { - mac->nr_ue_emul_l1.expected_rar = true; - mac->nr_ue_emul_l1.index_has_rar[j] = true; - LOG_T(NR_MAC, "Setting index_has_rar[%d] = true\n", j); - } - else - { - mac->nr_ue_emul_l1.expected_dci = true; - mac->nr_ue_emul_l1.index_has_dci[j] = true; - LOG_T(NR_MAC, "Setting index_has_dci[%d] = true\n", j); - } - pdu_idx++; - } - } - } - if (pdu_list->PDUType == NFAPI_NR_DL_TTI_SSB_PDU_TYPE) - { - /* If we get a MIB, we want to handle it right away and then come back. - The MIB and SIB come in the same dl_tti_req but the MIB should be - processed first and then the DCI and payload of the SIB1 can be - processed. The MIB should be handled first and then the rx_ind - will be freed after handling. This is why the PDU index will - always be zero for the RX_IND becasue we should not have more than - one MIB. */ - if (!dl_info->rx_ind) - { - dl_info->rx_ind = CALLOC(1, sizeof(*dl_info->rx_ind)); - } - fapi_nr_rx_indication_t *rx_ind = dl_info->rx_ind; - rx_ind->sfn = dl_tti_request->SFN; - rx_ind->slot = dl_tti_request->Slot; - fill_mib_in_rx_ind(pdu_list, rx_ind, 0, FAPI_NR_RX_PDU_TYPE_SSB); - nr_ue_dl_indication(&mac->dl_info); - } - } - dl_info->slot = dl_tti_request->Slot; - dl_info->frame = dl_tti_request->SFN; -} - -static void fill_rx_ind(nfapi_nr_pdu_t *pdu_list, fapi_nr_rx_indication_t *rx_ind, int pdu_idx, int pdu_type) -{ - NR_UE_MAC_INST_t *mac = get_mac_inst(0); - AssertFatal(pdu_list->num_TLV < sizeof(pdu_list->TLVs) / sizeof(pdu_list->TLVs[0]), "Num TLVs exceeds TLV array size"); - int length = 0; - for (int j = 0; j < pdu_list->num_TLV; j++) - { - length += pdu_list->TLVs[j].length; - } - LOG_D(NR_PHY, "%s: num_tlv %d and length %d, pdu index %d\n", - __FUNCTION__, pdu_list->num_TLV, length, pdu_idx); - uint8_t *pdu = malloc(length); - AssertFatal(pdu != NULL, "%s: Out of memory in malloc", __FUNCTION__); - rx_ind->rx_indication_body[pdu_idx].pdsch_pdu.pdu = pdu; - for (int j = 0; j < pdu_list->num_TLV; j++) - { - const uint32_t *ptr; - if (pdu_list->TLVs[j].tag) - ptr = pdu_list->TLVs[j].value.ptr; - else - ptr = pdu_list->TLVs[j].value.direct; - memcpy(pdu, ptr, pdu_list->TLVs[j].length); - pdu += pdu_list->TLVs[j].length; - } - bool ack_nack = true; - if (mac->ra.ra_state >= nrRA_SUCCEEDED && should_drop_transport_block(rx_ind->slot, mac->crnti)) { - ack_nack = false; - } - rx_ind->rx_indication_body[pdu_idx].pdsch_pdu.ack_nack = ack_nack; - rx_ind->rx_indication_body[pdu_idx].pdsch_pdu.pdu_length = length; - rx_ind->rx_indication_body[pdu_idx].pdu_type = pdu_type; - -} - - -static void copy_tx_data_req_to_dl_info(nr_downlink_indication_t *dl_info, nfapi_nr_tx_data_request_t *tx_data_request) -{ - NR_UE_MAC_INST_t *mac = get_mac_inst(dl_info->module_id); - int num_pdus = tx_data_request->Number_of_PDUs; - AssertFatal(num_pdus >= 0, "Invalid tx_data_request number of PDUS\n"); - - if (!dl_info->rx_ind) - { - dl_info->rx_ind = CALLOC(num_pdus, sizeof(fapi_nr_rx_indication_t)); - } - AssertFatal(dl_info->rx_ind != NULL, "%s: Out of memory in calloc", __FUNCTION__); - fapi_nr_rx_indication_t *rx_ind = dl_info->rx_ind; - rx_ind->sfn = tx_data_request->SFN; - rx_ind->slot = tx_data_request->Slot; - - int pdu_idx = 0; - - for (int i = 0; i < num_pdus; i++) - { - nfapi_nr_pdu_t *pdu_list = &tx_data_request->pdu_list[i]; - if (mac->nr_ue_emul_l1.index_has_sib[i]) - { - AssertFatal(!get_softmodem_params()->nsa, - "Should not be processing SIB in NSA mode, something bad happened\n"); - fill_rx_ind(pdu_list, rx_ind, pdu_idx, FAPI_NR_RX_PDU_TYPE_SIB); - pdu_idx++; - } - else if (mac->nr_ue_emul_l1.index_has_rar[i]) - { - fill_rx_ind(pdu_list, rx_ind, pdu_idx, FAPI_NR_RX_PDU_TYPE_RAR); - pdu_idx++; - } - else if (mac->nr_ue_emul_l1.index_has_dci[i]) - { - fill_rx_ind(pdu_list, rx_ind, pdu_idx, FAPI_NR_RX_PDU_TYPE_DLSCH); - pdu_idx++; - } - else - { - LOG_T(NR_MAC, "mac->nr_ue_emul_l1.index_has_dci[%d] = 0, so this index contained a DCI for a different UE\n", i); - } - - } - dl_info->slot = tx_data_request->Slot; - dl_info->frame = tx_data_request->SFN; - dl_info->rx_ind->number_pdus = pdu_idx; -} - -static void copy_ul_dci_data_req_to_dl_info(nr_downlink_indication_t *dl_info, nfapi_nr_ul_dci_request_t *ul_dci_req) -{ - NR_UE_MAC_INST_t *mac = get_mac_inst(dl_info->module_id); - int pdu_idx = 0; - - int num_pdus = ul_dci_req->numPdus; - AssertFatal(num_pdus >= 0, "Invalid ul_dci_request number of PDUS\n"); - - for (int i = 0; i < num_pdus; i++) - { - nfapi_nr_ul_dci_request_pdus_t *pdu_list = &ul_dci_req->ul_dci_pdu_list[i]; - AssertFatal(pdu_list->PDUType == 0, "ul_dci_req pdu type != PUCCH"); - LOG_D(NR_PHY, "[%d %d] PUCCH PDU in ul_dci for rnti %x and numDLDCI = %d\n", - ul_dci_req->SFN, ul_dci_req->Slot, pdu_list->pdcch_pdu.pdcch_pdu_rel15.dci_pdu->RNTI, - pdu_list->pdcch_pdu.pdcch_pdu_rel15.numDlDci); - uint16_t num_dci = pdu_list->pdcch_pdu.pdcch_pdu_rel15.numDlDci; - if (num_dci > 0) - { - if (!dl_info->dci_ind) - { - dl_info->dci_ind = CALLOC(1, sizeof(fapi_nr_dci_indication_t)); - } - AssertFatal(dl_info->dci_ind != NULL, "%s: Out of memory in calloc", __FUNCTION__); - dl_info->dci_ind->SFN = ul_dci_req->SFN; - dl_info->dci_ind->slot = ul_dci_req->Slot; - AssertFatal(num_dci < sizeof(dl_info->dci_ind->dci_list) / sizeof(dl_info->dci_ind->dci_list[0]), "The number of DCIs is greater than dci_list"); - for (int j = 0; j < num_dci; j++) - { - nfapi_nr_dl_dci_pdu_t *dci_pdu_list = &pdu_list->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[j]; - if (dci_pdu_list->RNTI != mac->crnti) - { - LOG_T(NR_MAC, "dci_pdu_list->RNTI (%x) != mac->crnti (%x)\n", dci_pdu_list->RNTI, mac->crnti); - continue; - } - fill_dl_info_with_pdcch(dl_info->dci_ind, dci_pdu_list, pdu_idx); - pdu_idx++; - } - } - } - dl_info->frame = ul_dci_req->SFN; - dl_info->slot = ul_dci_req->Slot; -} - -static bool send_crc_ind_and_rx_ind(int sfn, int slot) -{ - bool sent_crc_rx = true; - - struct sfn_slot_s sfn_slot = {.sfn = sfn, .slot = slot}; - nfapi_nr_rx_data_indication_t *rx_ind = unqueue_matching(&nr_rx_ind_queue, MAX_QUEUE_SIZE, sfn_slot_matcher, &sfn_slot); - nfapi_nr_crc_indication_t *crc_ind = unqueue_matching(&nr_crc_ind_queue, MAX_QUEUE_SIZE, sfn_slot_matcher, &sfn_slot); - - if (crc_ind && crc_ind->number_crcs > 0) - { - NR_UE_MAC_INST_t *mac = get_mac_inst(0); - for (int i = 0; i < crc_ind->number_crcs; i++) { - int harq_pid = crc_ind->crc_list[i].harq_id; - LOG_T(NR_MAC, "Resetting harq_pid %d active_ul_harq_sfn/slot\n", harq_pid); - mac->nr_ue_emul_l1.harq[harq_pid].active_ul_harq_sfn = -1; - mac->nr_ue_emul_l1.harq[harq_pid].active_ul_harq_slot = -1; - } - NR_UL_IND_t UL_INFO = { - .crc_ind = *crc_ind, - }; - send_nsa_standalone_msg(&UL_INFO, crc_ind->header.message_id); - free(crc_ind->crc_list); - free(crc_ind); - } - if (rx_ind && rx_ind->number_of_pdus > 0) - { - NR_UL_IND_t UL_INFO = { - .rx_ind = *rx_ind, - }; - send_nsa_standalone_msg(&UL_INFO, rx_ind->header.message_id); - free(rx_ind->pdu_list); - free(rx_ind); - } - else - { - sent_crc_rx = false; - } - return sent_crc_rx; -} - -static void copy_ul_tti_data_req_to_dl_info(nr_downlink_indication_t *dl_info, nfapi_nr_ul_tti_request_t *ul_tti_req) -{ - int num_pdus = ul_tti_req->n_pdus; - AssertFatal(num_pdus >= 0, "Invalid ul_tti_request number of PDUS\n"); - AssertFatal(num_pdus <= sizeof(ul_tti_req->pdus_list) / sizeof(ul_tti_req->pdus_list[0]), - "Too many pdus %d in ul_tti_req\n", num_pdus); - - if (!send_crc_ind_and_rx_ind(ul_tti_req->SFN, ul_tti_req->Slot)) - { - LOG_T(NR_MAC, "CRC_RX ind not sent\n"); - if (!put_queue(&nr_ul_tti_req_queue, ul_tti_req)) - { - LOG_E(NR_PHY, "put_queue failed for ul_tti_req.\n"); - } - return; - } -} - -static void fill_dci_from_dl_config(nr_downlink_indication_t*dl_ind, fapi_nr_dl_config_request_t *dl_config) -{ - - if (!dl_ind->dci_ind) - return; - - AssertFatal(dl_config->number_pdus < sizeof(dl_config->dl_config_list) / sizeof(dl_config->dl_config_list[0]), - "Too many dl_config pdus %d", dl_config->number_pdus); - for (int i = 0; i < dl_config->number_pdus; i++) { - LOG_D(PHY, "Filling DCI with a total of %d total DL PDUs (dl_config %p) \n", - dl_config->number_pdus, dl_config); - fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15_dci = &dl_config->dl_config_list[i].dci_config_pdu.dci_config_rel15; - int num_dci_options = rel15_dci->num_dci_options; - if (num_dci_options <= 0) - LOG_D(NR_MAC, "num_dci_opts = %d for pdu[%d] in dl_config_list\n", rel15_dci->num_dci_options, i); - AssertFatal(num_dci_options <= sizeof(rel15_dci->dci_length_options) / sizeof(rel15_dci->dci_length_options[0]), - "num_dci_options %d > dci_length_options array\n", num_dci_options); - AssertFatal(num_dci_options <= sizeof(rel15_dci->dci_format_options) / sizeof(rel15_dci->dci_format_options[0]), - "num_dci_options %d > dci_format_options array\n", num_dci_options); - - for (int j = 0; j < num_dci_options; j++) { - int num_dcis = dl_ind->dci_ind->number_of_dcis; - AssertFatal(num_dcis <= sizeof(dl_ind->dci_ind->dci_list) / sizeof(dl_ind->dci_ind->dci_list[0]), - "dl_config->number_pdus %d > dci_ind->dci_list array\n", num_dcis); - for (int k = 0; k < num_dcis; k++) { - LOG_T(NR_PHY, "Received len %d, length options[%d] %d, format assigned %d, format options[%d] %d\n", - dl_ind->dci_ind->dci_list[k].payloadSize, j, rel15_dci->dci_length_options[j], - dl_ind->dci_ind->dci_list[k].dci_format, j, rel15_dci->dci_format_options[j]); - if (rel15_dci->dci_length_options[j] == dl_ind->dci_ind->dci_list[k].payloadSize) { - dl_ind->dci_ind->dci_list[k].dci_format = rel15_dci->dci_format_options[j]; - dl_ind->dci_ind->dci_list[k].ss_type = rel15_dci->ss_type_options[j]; - dl_ind->dci_ind->dci_list[k].coreset_type = rel15_dci->coreset.CoreSetType; - LOG_D(NR_PHY, "format assigned dl_ind->dci_ind->dci_list[k].dci_format %d\n", - dl_ind->dci_ind->dci_list[k].dci_format); - } - } - } - } -} - -// This piece of code is not used in "normal" ue, but in "fapi mode" -void check_and_process_dci(nfapi_nr_dl_tti_request_t *dl_tti_request, - nfapi_nr_tx_data_request_t *tx_data_request, - nfapi_nr_ul_dci_request_t *ul_dci_request, - nfapi_nr_ul_tti_request_t *ul_tti_request) -{ - frame_t frame = 0; - int slot = 0; - NR_UE_MAC_INST_t *mac = get_mac_inst(0); - - if (pthread_mutex_lock(&mac->mutex_dl_info)) abort(); - - if (dl_tti_request) { - frame = dl_tti_request->SFN; - slot = dl_tti_request->Slot; - LOG_D(NR_PHY, "[%d, %d] dl_tti_request\n", frame, slot); - copy_dl_tti_req_to_dl_info(&mac->dl_info, dl_tti_request); - } - /* This checks if the previously recevied DCI matches our current RNTI - value. The assumption is that if the DCI matches our RNTI, then the - incoming tx_data_request is also destined for the current UE. If the - RAR hasn't been processed yet, we do not want to be filtering the - tx_data_requests. */ - if (tx_data_request) { - if (mac->nr_ue_emul_l1.expected_sib || - mac->nr_ue_emul_l1.expected_rar || - mac->nr_ue_emul_l1.expected_dci) { - frame = tx_data_request->SFN; - slot = tx_data_request->Slot; - LOG_D(NR_PHY, "[%d, %d] PDSCH in tx_request\n", frame, slot); - copy_tx_data_req_to_dl_info(&mac->dl_info, tx_data_request); - } - else { - LOG_D(NR_MAC, "Unexpected tx_data_req\n"); - } - } - else if (ul_dci_request) { - frame = ul_dci_request->SFN; - slot = ul_dci_request->Slot; - LOG_D(NR_PHY, "[%d, %d] ul_dci_request\n", frame, slot); - copy_ul_dci_data_req_to_dl_info(&mac->dl_info, ul_dci_request); - } - else if (ul_tti_request) { - frame = ul_tti_request->SFN; - slot = ul_tti_request->Slot; - LOG_T(NR_PHY, "[%d, %d] ul_tti_request\n", frame, slot); - copy_ul_tti_data_req_to_dl_info(&mac->dl_info, ul_tti_request); - } - else { - if (pthread_mutex_unlock(&mac->mutex_dl_info)) abort(); - LOG_T(NR_MAC, "All indications were NULL in %s\n", __FUNCTION__); - return; - } - - if (dl_tti_request || tx_data_request || ul_dci_request) { - fapi_nr_dl_config_request_t *dl_config = get_dl_config_request(mac, slot); - fill_dci_from_dl_config(&mac->dl_info, dl_config); - } - nr_ue_dl_scheduler(mac, &mac->dl_info); - nr_ue_dl_indication(&mac->dl_info); - - if (pthread_mutex_unlock(&mac->mutex_dl_info)) - abort(); - int slots_per_frame = 20; //30 kHZ subcarrier spacing - int slot_ahead = 2; // TODO: Make this dynamic - - if (is_ul_slot((slot + slot_ahead) % slots_per_frame, &mac->frame_structure) - && mac->ra.ra_state != nrRA_SUCCEEDED) { - // If we filled dl_info AFTER we got the slot indication, we want to check if we should fill tx_req: - nr_uplink_indication_t ul_info = {.slot = (slot + slot_ahead) % slots_per_frame, - .frame = slot + slot_ahead >= slots_per_frame ? (frame + 1) % 1024 : frame}; - nr_ue_ul_scheduler(mac, &ul_info); - } -} - -void save_nr_measurement_info(nfapi_nr_dl_tti_request_t *dl_tti_request) -{ - int num_pdus = dl_tti_request->dl_tti_request_body.nPDUs; - char buffer[MAX_MESSAGE_SIZE]; - if (num_pdus <= 0) - { - LOG_E(NR_PHY, "%s: dl_tti_request number of PDUS <= 0\n", __FUNCTION__); - abort(); - } - LOG_T(NR_PHY, "%s: dl_tti_request number of PDUS: %d\n", __FUNCTION__, num_pdus); - for (int i = 0; i < num_pdus; i++) - { - nfapi_nr_dl_tti_request_pdu_t *pdu_list = &dl_tti_request->dl_tti_request_body.dl_tti_pdu_list[i]; - if (pdu_list->PDUType == NFAPI_NR_DL_TTI_SSB_PDU_TYPE) - { - LOG_T(NR_PHY, "Cell_id: %d, the ssb_block_idx %d, sc_offset: %d and payload %d\n", - pdu_list->ssb_pdu.ssb_pdu_rel15.PhysCellId, - pdu_list->ssb_pdu.ssb_pdu_rel15.SsbBlockIndex, - pdu_list->ssb_pdu.ssb_pdu_rel15.SsbSubcarrierOffset, - pdu_list->ssb_pdu.ssb_pdu_rel15.bchPayload); - pdu_list->ssb_pdu.ssb_pdu_rel15.ssbRsrp = 60; - LOG_T(NR_RRC, "Setting pdulist[%d].ssbRsrp to %d\n", i, pdu_list->ssb_pdu.ssb_pdu_rel15.ssbRsrp); - } - } - - size_t pack_len = nfapi_nr_p7_message_pack((void *)dl_tti_request, - buffer, - sizeof(buffer), - NULL); - if (pack_len < 0) - { - LOG_E(NR_PHY, "%s: Error packing nr p7 message.\n", __FUNCTION__); - } - nsa_sendmsg_to_lte_ue(buffer, pack_len, NR_UE_RRC_MEASUREMENT); - LOG_A(NR_RRC, "Populated NR_UE_RRC_MEASUREMENT information and sent to LTE UE\n"); -} - -static void enqueue_nr_nfapi_msg(void *buffer, ssize_t len, nfapi_p7_message_header_t header) -{ - NR_UE_MAC_INST_t *mac = get_mac_inst(0); - switch (header.message_id) - { - case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: - { - nfapi_nr_dl_tti_request_t *dl_tti_request = malloc16(sizeof(*dl_tti_request)); - const bool result = nfapi_nr_p7_message_unpack(buffer, len, dl_tti_request, sizeof(*dl_tti_request), NULL); - if (!result) { - LOG_E(NR_PHY, "Message dl_tti_request failed to unpack\n"); - break; - } - LOG_D(NR_PHY, "Received an NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST message in sfn/slot %d %d. \n", - dl_tti_request->SFN, dl_tti_request->Slot); - - if (is_channel_modeling()) - save_pdsch_pdu_for_crnti(dl_tti_request); - - if (!put_queue(&nr_dl_tti_req_queue, dl_tti_request)) - { - LOG_E(NR_PHY, "put_queue failed for dl_tti_request.\n"); - free(dl_tti_request); - dl_tti_request = NULL; - } - break; - } - - case NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST: - { - nfapi_nr_tx_data_request_t *tx_data_request = malloc16(sizeof(*tx_data_request)); - const bool result = nfapi_nr_p7_message_unpack(buffer, len, tx_data_request, sizeof(*tx_data_request), NULL); - if (!result) { - LOG_E(NR_PHY, "Message tx_data_request failed to unpack\n"); - break; - } - LOG_D(NR_PHY, "Received an NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST message in SFN/slot %d %d. \n", - tx_data_request->SFN, tx_data_request->Slot); - if (!put_queue(&nr_tx_req_queue, tx_data_request)) - { - LOG_E(NR_PHY, "put_queue failed for tx_request.\n"); - free(tx_data_request); - tx_data_request = NULL; - } - break; - } - - case NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST: - { - nfapi_nr_ul_dci_request_t *ul_dci_request = malloc16(sizeof(*ul_dci_request)); - const bool result = nfapi_nr_p7_message_unpack(buffer, len, ul_dci_request, sizeof(*ul_dci_request), NULL); - if (!result) { - LOG_E(NR_PHY, "Message ul_dci_request failed to unpack\n"); - break; - } - LOG_D(NR_PHY, "Received an NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST message in SFN/slot %d %d. \n", - ul_dci_request->SFN, ul_dci_request->Slot); - if (!put_queue(&nr_ul_dci_req_queue, ul_dci_request)) - { - LOG_E(NR_PHY, "put_queue failed for ul_dci_request.\n"); - free(ul_dci_request); - ul_dci_request = NULL; - } - break; - } - - case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: - { - nfapi_nr_ul_tti_request_t *ul_tti_request = malloc16(sizeof(*ul_tti_request)); - const bool result = nfapi_nr_p7_message_unpack(buffer, len, ul_tti_request, sizeof(*ul_tti_request), NULL); - if (!result) { - LOG_E(NR_PHY, "Message ul_tti_request failed to unpack\n"); - break; - } - /* We are filtering UL_TTI_REQs below. We only care about UL_TTI_REQs that - will trigger sending a ul_harq (CRC/RX pair). This UL_TTI_REQ will have - NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE. If we have not yet completed the CBRA/ - CFRA procedure, we need to queue all UL_TTI_REQs. */ - for (int i = 0; i < ul_tti_request->n_pdus; i++) { - if (ul_tti_request->pdus_list[i].pdu_type == NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE - && mac->ra.ra_state >= nrRA_SUCCEEDED) { - if (!put_queue(&nr_ul_tti_req_queue, ul_tti_request)) { - LOG_D(NR_PHY, "put_queue failed for ul_tti_request, calling put_queue_replace.\n"); - nfapi_nr_ul_tti_request_t *evicted_ul_tti_req = put_queue_replace(&nr_ul_tti_req_queue, ul_tti_request); - free(evicted_ul_tti_req); - } - break; - } else if (mac->ra.ra_state < nrRA_SUCCEEDED) { - if (!put_queue(&nr_ul_tti_req_queue, ul_tti_request)) { - LOG_D(NR_PHY, "put_queue failed for ul_tti_request, calling put_queue_replace.\n"); - nfapi_nr_ul_tti_request_t *evicted_ul_tti_req = put_queue_replace(&nr_ul_tti_req_queue, ul_tti_request); - free(evicted_ul_tti_req); - } - break; - } - } - break; - } - - default: - LOG_E(NR_PHY, "Invalid nFAPI message. Header ID %d\n", - header.message_id); - break; - } - return; -} - -static void save_pdsch_pdu_for_crnti(nfapi_nr_dl_tti_request_t *dl_tti_request) -{ - int count_sent = 0; - NR_UE_MAC_INST_t *mac = get_mac_inst(0); - int number_of_pdu = dl_tti_request->dl_tti_request_body.nPDUs; - if (number_of_pdu <= 0) - { - LOG_E(NR_MAC, "%s: dl_tti_request pdu size <= 0\n", __FUNCTION__); - abort(); - } - - for (int i = 0; i < number_of_pdu; i++) - { - const nfapi_nr_dl_tti_request_pdu_t *pdu_list = &dl_tti_request->dl_tti_request_body.dl_tti_pdu_list[i]; - - if (pdu_list->PDUType == NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE) - { - const nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu = &pdu_list->pdsch_pdu.pdsch_pdu_rel15; - if (pdsch_pdu->rnti == mac->crnti && mac->ra.ra_state == nrRA_SUCCEEDED) { - read_channel_param(pdsch_pdu, dl_tti_request->Slot, count_sent); - count_sent++; - LOG_T(NR_MAC, "pdsch_pdu->rnti %x mac->crnti %x mac->ra.ra_state %d count_sent %d\n", - pdsch_pdu->rnti, mac->crnti, mac->ra.ra_state, count_sent); - } - } - } -} - -static uint16_t get_message_id(const uint8_t *buffer, ssize_t len) -{ - if (len < 4) - return 0; - - // Unpack 2 bytes message_id from buffer. - uint16_t v; - memcpy(&v, buffer + 2, sizeof(v)); - return ntohs(v); -} - -void *nrue_standalone_pnf_task(void *context) -{ - struct sockaddr_in server_address; - socklen_t addr_len = sizeof(server_address); - int sd = ue_rx_sock_descriptor; - assert(sd > 0); - - char buffer[NFAPI_MAX_PACKED_MESSAGE_SIZE]; - - LOG_I(NR_RRC, "Successfully started %s.\n", __FUNCTION__); - - while (true) - { - ssize_t len = recvfrom(sd, buffer, sizeof(buffer), MSG_TRUNC, (struct sockaddr *)&server_address, &addr_len); - if (len == -1) - { - LOG_E(NR_PHY, "reading from standalone pnf sctp socket failed \n"); - continue; - } - if (len > sizeof(buffer)) - { - LOG_E(NR_PHY, "%s(%d). Message truncated. %zd\n", __FUNCTION__, __LINE__, len); - continue; - } - if (len == sizeof(uint16_t)) - { - uint16_t *sfn_slot = CALLOC(1, sizeof(*sfn_slot)); - memcpy(sfn_slot, buffer, sizeof(*sfn_slot)); - - LOG_D(NR_PHY, "Received from proxy sfn_slot %x\n", *sfn_slot); - - if (!put_queue(&nr_sfn_slot_queue, sfn_slot)) - { - LOG_E(NR_PHY, "put_queue failed for sfn slot.\n"); - } - - if (sem_post(&sfn_slot_semaphore) != 0) - { - LOG_E(NR_PHY, "sem_post() error\n"); - abort(); - } - } - else if (get_message_id((const uint8_t *)buffer, len) == 0x0FFF) // 0x0FFF : channel info identifier. - { - nr_phy_channel_params_t *ch_info = CALLOC(1, sizeof(*ch_info)); - memcpy(ch_info, buffer, sizeof(*ch_info)); - - if (ch_info->nb_of_csi > 1) - LOG_W(NR_PHY, "Expecting only one CSI report.\n"); - - // TODO: Update sinr field of slot_rnti_mcs to be array. - for (int i = 0; i < ch_info->nb_of_csi; ++i) - { - int mu = 1; // NR-UE emul-L1 is hardcoded to 30kHZ, see check_and_process_dci() - int frame = NFAPI_SFNSLOTDEC2SFN(mu, ch_info->sfn_slot); - int slot = NFAPI_SFNSLOTDEC2SLOT(mu, ch_info->sfn_slot); - slot_rnti_mcs[slot].sinr = ch_info->csi[i].sinr; - slot_rnti_mcs[slot].area_code = ch_info->csi[i].area_code; - - LOG_D(NR_PHY, "Received_SINR[%d] = %f, sfn:slot %d:%d\n", i, ch_info->csi[i].sinr, frame, slot); - } - - if (!put_queue(&nr_chan_param_queue, ch_info)) - { - LOG_E(NR_PHY, "put_queue failed for sfn slot.\n"); - } - - if (sem_post(&sfn_slot_semaphore) != 0) - { - LOG_E(NR_MAC, "sem_post() error\n"); - abort(); - } - } - else - { - nfapi_p7_message_header_t header; - if (nfapi_p7_message_header_unpack(buffer, len, &header, sizeof(header), NULL) < 0) - { - LOG_E(NR_PHY, "Header unpack failed for nrue_standalone pnf\n"); - continue; - } - enqueue_nr_nfapi_msg(buffer, len, header); - } - } //while(true) -} - // L2 Abstraction Layer static int handle_bcch_bch(NR_UE_MAC_INST_t *mac, int cc_id, @@ -1141,13 +166,6 @@ static nr_dci_format_t handle_dci(NR_UE_MAC_INST_t *mac, // Note: sdu should always be processed because data and timing advance updates are transmitted by the UE static int8_t handle_dlsch(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_info, int pdu_id) { - /* L1 assigns harq_pid, but in emulated L1 mode we need to assign - the harq_pid based on the saved global g_harq_pid. Because we are - emulating L1, no antenna measurements are conducted to calculate - a harq_pid, therefore we must set it here. */ - if (get_softmodem_params()->emulate_l1) - dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.harq_pid = g_harq_pid; - if (mac->ra.ra_state != nrRA_WAIT_RAR) // no HARQ for MSG2 update_harq_status(mac, dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.harq_pid, @@ -1232,9 +250,6 @@ static uint32_t nr_ue_dl_processing(NR_UE_MAC_INST_t *mac, nr_downlink_indicatio continue; } dci_pdu_rel15_t *def_dci_pdu_rel15 = &mac->def_dci_pdu_rel15[dl_info->slot][dci_format]; - g_harq_pid = def_dci_pdu_rel15->harq_pid.val; - LOG_T(NR_MAC, "Setting harq_pid = %d and dci_index = %d (based on format)\n", g_harq_pid, dci_format); - ret_mask |= (1 << FAPI_NR_DCI_IND); AssertFatal(nr_ue_if_module_inst[dl_info->module_id] != NULL, "IF module is NULL!\n"); fapi_nr_dl_config_request_t *dl_config = get_dl_config_request(mac, dl_info->slot); @@ -1362,45 +377,14 @@ nr_ue_if_module_t *nr_ue_if_module_init(uint32_t module_id) nr_ue_if_module_inst[module_id]->sl_phy_config_request = nr_ue_sl_phy_config_request; nr_ue_if_module_inst[module_id]->sl_indication = nr_ue_sl_indication; } - if (get_softmodem_params()->emulate_l1) - nr_ue_if_module_inst[module_id]->scheduled_response = nr_ue_scheduled_response_stub; - else - nr_ue_if_module_inst[module_id]->scheduled_response = nr_ue_scheduled_response; + nr_ue_if_module_inst[module_id]->scheduled_response = nr_ue_scheduled_response; nr_ue_if_module_inst[module_id]->dl_indication = nr_ue_dl_indication; nr_ue_if_module_inst[module_id]->ul_indication = nr_ue_ul_indication; nr_ue_if_module_inst[module_id]->slot_indication = nr_ue_slot_indication; } - return nr_ue_if_module_inst[module_id]; } -void RCconfig_nr_ue_macrlc(void) { - int j; - paramdef_t MACRLC_Params[] = MACRLCPARAMS_DESC; - paramlist_def_t MACRLC_ParamList = {CONFIG_STRING_MACRLC_LIST, NULL, 0}; - - config_getlist(config_get_if(), &MACRLC_ParamList, MACRLC_Params, sizeofArray(MACRLC_Params), NULL); - if (MACRLC_ParamList.numelt > 0) { - for (j = 0; j < MACRLC_ParamList.numelt; j++) { - if (strcmp(*(MACRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_N_PREFERENCE_IDX].strptr), "nfapi") == 0) { - stub_eth_params.my_addr = strdup( - *(MACRLC_ParamList.paramarray[j][MACRLC_LOCAL_N_ADDRESS_IDX].strptr)); - stub_eth_params.remote_addr = strdup( - *(MACRLC_ParamList.paramarray[j][MACRLC_REMOTE_N_ADDRESS_IDX].strptr)); - stub_eth_params.my_portc = - *(MACRLC_ParamList.paramarray[j][MACRLC_LOCAL_N_PORTC_IDX].iptr); - stub_eth_params.remote_portc = - *(MACRLC_ParamList.paramarray[j][MACRLC_REMOTE_N_PORTC_IDX].iptr); - stub_eth_params.my_portd = - *(MACRLC_ParamList.paramarray[j][MACRLC_LOCAL_N_PORTD_IDX].iptr); - stub_eth_params.remote_portd = - *(MACRLC_ParamList.paramarray[j][MACRLC_REMOTE_N_PORTD_IDX].iptr); - stub_eth_params.transp_preference = ETH_UDP_MODE; - } - } - } -} - static void handle_sl_bch(int ue_id, sl_nr_ue_mac_params_t *sl_mac, uint8_t *const sl_mib, diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h index 2bbd97db84..a1175282f0 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h @@ -34,11 +34,8 @@ #define __NR_IF_MODULE_H__ #include "common/platform_types.h" -#include #include "fapi_nr_ue_interface.h" -#include "openair2/PHY_INTERFACE/queue_t.h" #include "openair2/NR_PHY_INTERFACE/NR_IF_Module.h" -#include "NR_Packet_Drop.h" #include "nfapi/open-nFAPI/nfapi/public_inc/sidelink_nr_ue_interface.h" typedef enum sl_sidelink_slot_type { @@ -50,19 +47,6 @@ typedef enum sl_sidelink_slot_type { } sl_sidelink_slot_type_t; -extern queue_t nr_rach_ind_queue; -extern queue_t nr_rx_ind_queue; -extern queue_t nr_crc_ind_queue; -extern queue_t nr_uci_ind_queue; -extern queue_t nr_sfn_slot_queue; -extern queue_t nr_chan_param_queue; -extern queue_t nr_dl_tti_req_queue; -extern queue_t nr_tx_req_queue; -extern queue_t nr_ul_dci_req_queue; -extern queue_t nr_ul_tti_req_queue; - -extern slot_rnti_mcs_s slot_rnti_mcs[NUM_NFAPI_SLOT]; - typedef struct NR_UL_TIME_ALIGNMENT NR_UL_TIME_ALIGNMENT_t; typedef struct { @@ -292,32 +276,6 @@ typedef struct nr_ue_if_module_s { \param module_id module id*/ nr_ue_if_module_t *nr_ue_if_module_init(uint32_t module_id); -void nrue_init_standalone_socket(int tx_port, int rx_port); - -void *nrue_standalone_pnf_task(void *context); -extern sem_t sfn_slot_semaphore; - -typedef struct nfapi_dl_tti_config_req_tx_data_req_t -{ - nfapi_nr_dl_tti_request_pdu_t *dl_itti_config_req; - nfapi_nr_tx_data_request_t *tx_data_req_pdu_list; -} nfapi_dl_tti_config_req_tx_data_req_t; - -void send_nsa_standalone_msg(NR_UL_IND_t *UL_INFO, uint16_t msg_id); - -void save_nr_measurement_info(nfapi_nr_dl_tti_request_t *dl_tti_request); - -void check_and_process_dci(nfapi_nr_dl_tti_request_t *dl_tti_request, - nfapi_nr_tx_data_request_t *tx_data_request, - nfapi_nr_ul_dci_request_t *ul_dci_request, - nfapi_nr_ul_tti_request_t *ul_tti_request); - -struct sfn_slot_s { - int sfn; - int slot; -}; -bool sfn_slot_matcher(void *sfn_slot_s, void *candidate); - /**\brief interface between L1/L2, indicating the downlink related information, like dci_ind and rx_req \param dl_info including dci_ind and rx_request messages*/ int nr_ue_dl_indication(nr_downlink_indication_t *dl_info); diff --git a/openair2/RRC/LTE/rrc_eNB.c b/openair2/RRC/LTE/rrc_eNB.c index 90b2d3b86f..4ddd7fc625 100644 --- a/openair2/RRC/LTE/rrc_eNB.c +++ b/openair2/RRC/LTE/rrc_eNB.c @@ -6354,7 +6354,7 @@ rrc_eNB_decode_dcch( /*NN: revise the condition */ /*FK: left the condition as is for the case MME is used (S1 mode) but setting dedicated_DRB = 1 otherwise (noS1 mode) so that no second RRCReconfiguration message activationg more DRB is sent as this causes problems with the nasmesh driver.*/ - if (!IS_SOFTMODEM_NOS1 || get_softmodem_params()->emulate_l1) { + if (!IS_SOFTMODEM_NOS1) { if (ue_context_p->ue_context.StatusRrc == RRC_RECONFIGURED) { dedicated_DRB = 1; LOG_I(RRC, diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index c167982859..0544637975 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -2921,7 +2921,7 @@ static void process_lte_nsa_msg(NR_UE_RRC_INST_t *rrc, nsa_msg_t *msg, int msg_l LOG_D(NR_RRC, "NR carrierFreq_r15 (ssb): %ld and sub carrier spacing:%ld\n", nr_meas_obj->measObject.choice.measObjectNR_r15.carrierFreq_r15, nr_meas_obj->measObject.choice.measObjectNR_r15.rs_ConfigSSB_r15.subcarrierSpacingSSB_r15); - start_oai_nrue_threads(); + //start_oai_nrue_threads(); break; } diff --git a/openair2/RRC/NR_UE/rrc_proto.h b/openair2/RRC/NR_UE/rrc_proto.h index d332ca5175..cdcf1966b4 100644 --- a/openair2/RRC/NR_UE/rrc_proto.h +++ b/openair2/RRC/NR_UE/rrc_proto.h @@ -74,8 +74,6 @@ void *recv_msgs_from_lte_ue(void *args_p); void init_connections_with_lte_ue(void); -extern void start_oai_nrue_threads(void); - int get_from_lte_ue_fd(); void nr_rrc_SI_timers(NR_UE_RRC_SI_INFO *SInfo); From 6289409f15c82d6e5426ebc473fc00f2d537f2a1 Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 2 Oct 2025 17:21:27 +0200 Subject: [PATCH 908/964] remove nsa UE option code --- CMakeLists.txt | 4 - common/utils/ocp_itti/intertask_interface.h | 2 - doc/Doxyfile | 1 - executables/create_tasks_ue.c | 9 - executables/nr-uesoftmodem.c | 25 +- openair2/COMMON/as_message.h | 4 - openair2/COMMON/pdcp_messages_def.h | 1 - openair2/COMMON/pdcp_messages_types.h | 1 - openair2/COMMON/rrc_messages_def.h | 2 - openair2/COMMON/rrc_messages_types.h | 1 - openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c | 29 +- openair2/RRC/LTE/MESSAGES/asn1_msg.c | 119 +--- openair2/RRC/LTE/MESSAGES/asn1_msg.h | 4 +- openair2/RRC/LTE/rrc_UE.c | 642 +------------------ openair2/RRC/LTE/rrc_proto.h | 6 - openair2/RRC/NR_UE/L2_interface_ue.h | 1 - openair2/RRC/NR_UE/rrc_UE.c | 182 ------ openair2/RRC/NR_UE/rrc_nsa.c | 85 --- openair2/RRC/NR_UE/rrc_proto.h | 6 - openair3/NAS/NR_UE/nr_nas_msg.c | 2 +- 20 files changed, 7 insertions(+), 1119 deletions(-) delete mode 100644 openair2/RRC/NR_UE/rrc_nsa.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 5dc7ba40d5..57d165ea05 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1184,7 +1184,6 @@ set(NR_L2_SRC_UE ${NR_UE_RRC_DIR}/L2_interface_ue.c ${NR_UE_RRC_DIR}/main_ue.c ${NR_UE_RRC_DIR}/rrc_UE.c - ${NR_UE_RRC_DIR}/rrc_nsa.c ${NR_UE_RRC_DIR}/rrc_timers_and_constants.c ${NR_UE_RRC_DIR}/rrc_sl_preconfig.c ) @@ -1977,7 +1976,6 @@ target_link_libraries(nr_pbchsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) add_executable(nr_psbchsim ${OPENAIR1_DIR}/SIMULATION/NR_PHY/psbchsim.c ${OPENAIR_DIR}/executables/softmodem-common.c - ${NR_UE_RRC_DIR}/rrc_nsa.c ${NFAPI_USER_DIR}/nfapi.c ${NFAPI_USER_DIR}/gnb_ind_vars.c ${PHY_INTERFACE_DIR}/queue_t.c @@ -1998,7 +1996,6 @@ target_link_libraries(nr_pucchsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) add_executable(nr_dlsim ${OPENAIR1_DIR}/SIMULATION/NR_PHY/dlsim.c ${OPENAIR_DIR}/executables/softmodem-common.c - ${NR_UE_RRC_DIR}/rrc_nsa.c ${NFAPI_USER_DIR}/nfapi.c ${NFAPI_USER_DIR}/gnb_ind_vars.c ${PHY_INTERFACE_DIR}/queue_t.c @@ -2028,7 +2025,6 @@ target_link_libraries(nr_ulschsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) add_executable(nr_ulsim ${OPENAIR1_DIR}/SIMULATION/NR_PHY/ulsim.c ${OPENAIR_DIR}/executables/softmodem-common.c - ${NR_UE_RRC_DIR}/rrc_nsa.c ${NFAPI_USER_DIR}/nfapi.c ${NFAPI_USER_DIR}/gnb_ind_vars.c ${PHY_INTERFACE_DIR}/queue_t.c diff --git a/common/utils/ocp_itti/intertask_interface.h b/common/utils/ocp_itti/intertask_interface.h index 84dbd15365..8f4e25d8b1 100644 --- a/common/utils/ocp_itti/intertask_interface.h +++ b/common/utils/ocp_itti/intertask_interface.h @@ -321,8 +321,6 @@ typedef struct { TASK_DEF(TASK_DU_F1, 200) \ TASK_DEF(TASK_CUCP_E1, 200) \ TASK_DEF(TASK_CUUP_E1, 200) \ - TASK_DEF(TASK_RRC_NSA_UE, 200) \ - TASK_DEF(TASK_RRC_NSA_NRUE, 200) \ TASK_DEF(TASK_NAS_NRUE, 200) \ TASK_DEF(TASK_MAX, 200) diff --git a/doc/Doxyfile b/doc/Doxyfile index e91e63386f..5f96bc2e4a 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -1836,7 +1836,6 @@ INPUT = \ @CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/common.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR_UE/rrc_UE.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR_UE/rrc_sl_preconfig.c \ -@CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR_UE/rrc_nsa.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR_UE/rrc_proto.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR_UE/rrc_vars.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR_UE/sl_preconfig_paramvalues.h \ diff --git a/executables/create_tasks_ue.c b/executables/create_tasks_ue.c index 50b9221f3f..46b80a0496 100644 --- a/executables/create_tasks_ue.c +++ b/executables/create_tasks_ue.c @@ -64,15 +64,6 @@ int create_tasks_ue(uint32_t ue_nb) LOG_E(RRC, "Create task for RRC UE failed\n"); return -1; } - - if (get_softmodem_params()->nsa) { - init_connections_with_nr_ue(); - LOG_I(RRC, "Started LTE-NR link in the LTE UE\n"); - if (itti_create_task (TASK_RRC_NSA_UE, recv_msgs_from_nr_ue, NULL) < 0) { - LOG_E(RRC, "Create task for RRC NSA UE failed\n"); - return -1; - } - } } itti_wait_ready(0); diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index fb740781cd..fbac6402f5 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -124,13 +124,6 @@ int create_tasks_nrue(uint32_t ue_nb) { LOG_E(NR_RRC, "Create task for RRC UE failed\n"); return -1; } - if (get_softmodem_params()->nsa) { - init_connections_with_lte_ue(); - if (itti_create_task (TASK_RRC_NSA_NRUE, recv_msgs_from_lte_ue, NULL) < 0) { - LOG_E(NR_RRC, "Create task for RRC NSA nr-UE failed\n"); - return -1; - } - } const ittiTask_parms_t parmsNAS = {NULL, nas_nrue}; if (itti_create_task(TASK_NAS_NRUE, nas_nrue_task, &parmsNAS) < 0) { LOG_E(NR_RRC, "Create task for NAS UE failed\n"); @@ -292,14 +285,6 @@ void init_openair0(PHY_VARS_NR_UE *ue) } } -static void init_pdcp(int ue_id) -{ - if (get_softmodem_params()->nsa && nr_rlc_module_init(NR_RLC_OP_MODE_UE) != 0) { - LOG_I(RLC, "Problem at RLC initiation \n"); - } - nr_pdcp_layer_init(); -} - // Stupid function addition because UE itti messages queues definition is common with eNB void *rrc_enb_process_msg(void *notUsed) { return NULL; @@ -395,15 +380,7 @@ int main(int argc, char **argv) exit(-1); // need a softer mode } - int mode_offset = get_softmodem_params()->nsa ? NUMBER_OF_UE_MAX : 1; - uint16_t node_number = get_softmodem_params()->node_number; - ue_id_g = (node_number == 0) ? 0 : node_number - 2; - AssertFatal(ue_id_g >= 0, "UE id is expected to be nonnegative.\n"); - - if (node_number == 0) - init_pdcp(0); - else - init_pdcp(mode_offset + ue_id_g); + nr_pdcp_layer_init(); nas_init_nrue(NB_UE_INST); init_NR_UE(NB_UE_INST, get_nrUE_params()->uecap_file, get_nrUE_params()->reconfig_file, get_nrUE_params()->rbconfig_file); diff --git a/openair2/COMMON/as_message.h b/openair2/COMMON/as_message.h index 1fb59c6aa9..a134c1b47c 100644 --- a/openair2/COMMON/as_message.h +++ b/openair2/COMMON/as_message.h @@ -218,10 +218,6 @@ typedef struct kenb_refresh_req_s { uint8_t kenb[32]; } kenb_refresh_req_t; -typedef struct nsa_oai_tun_nsa_s { - uint8_t buffer[500]; -} nas_oai_tun_nsa_t; - /* * NAS->AS - Cell Information request * NAS request AS to search for a suitable cell belonging to the selected diff --git a/openair2/COMMON/pdcp_messages_def.h b/openair2/COMMON/pdcp_messages_def.h index 5392c9e04d..da7d87f142 100644 --- a/openair2/COMMON/pdcp_messages_def.h +++ b/openair2/COMMON/pdcp_messages_def.h @@ -31,7 +31,6 @@ MESSAGE_DEF(RRC_DCCH_DATA_REQ, MESSAGE_PRIORITY_MED_PLUS, RrcDcchDataReq, rrc_dcch_data_req) MESSAGE_DEF(RRC_DCCH_DATA_IND, MESSAGE_PRIORITY_MED_PLUS, RrcDcchDataInd, rrc_dcch_data_ind) MESSAGE_DEF(RRC_PCCH_DATA_REQ, MESSAGE_PRIORITY_MED_PLUS, RrcPcchDataReq, rrc_pcch_data_req) -MESSAGE_DEF(RRC_NRUE_CAP_INFO_IND, MESSAGE_PRIORITY_MED_PLUS, RrcDcchDataInd, rrc_nrue_cap_info_ind) MESSAGE_DEF(RRC_DCCH_DATA_COPY_IND, MESSAGE_PRIORITY_MED_PLUS, RrcDcchDataInd, rrc_dcch_data_copy_ind) // gNB diff --git a/openair2/COMMON/pdcp_messages_types.h b/openair2/COMMON/pdcp_messages_types.h index b97fdef986..cf7a1f8f0c 100644 --- a/openair2/COMMON/pdcp_messages_types.h +++ b/openair2/COMMON/pdcp_messages_types.h @@ -34,7 +34,6 @@ #define RRC_DCCH_DATA_REQ(mSGpTR) (mSGpTR)->ittiMsg.rrc_dcch_data_req #define RRC_DCCH_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.rrc_dcch_data_ind #define RRC_PCCH_DATA_REQ(mSGpTR) (mSGpTR)->ittiMsg.rrc_pcch_data_req -#define RRC_NRUE_CAP_INFO_IND(mSGpTR) (mSGpTR)->ittiMsg.rrc_nrue_cap_info_ind #define RRC_DCCH_DATA_COPY_IND(mSGpTR) (mSGpTR)->ittiMsg.rrc_dcch_data_copy_ind // gNB diff --git a/openair2/COMMON/rrc_messages_def.h b/openair2/COMMON/rrc_messages_def.h index 33d6b7b59e..7dda028565 100644 --- a/openair2/COMMON/rrc_messages_def.h +++ b/openair2/COMMON/rrc_messages_def.h @@ -67,8 +67,6 @@ MESSAGE_DEF(NAS_5GMM_IND, MESSAGE_PRIORITY_MED, nas_5gmm_ind_t, nas_5gmm_ind) MESSAGE_DEF(NAS_RAB_ESTABLI_RSP, MESSAGE_PRIORITY_MED, rab_establish_rsp_t, nas_rab_est_rsp) -MESSAGE_DEF(NAS_OAI_TUN_NSA, MESSAGE_PRIORITY_MED, nas_oai_tun_nsa_t, nas_oai_tun_nsa) - // UE: RRC -> NAS messages MESSAGE_DEF(NAS_CELL_SELECTION_CNF, MESSAGE_PRIORITY_MED, cell_info_cnf_t, nas_cell_selection_cnf) MESSAGE_DEF(NAS_CELL_SELECTION_IND, MESSAGE_PRIORITY_MED, cell_info_ind_t, nas_cell_selection_ind) diff --git a/openair2/COMMON/rrc_messages_types.h b/openair2/COMMON/rrc_messages_types.h index e1656a3d7f..255da9f189 100644 --- a/openair2/COMMON/rrc_messages_types.h +++ b/openair2/COMMON/rrc_messages_types.h @@ -103,7 +103,6 @@ #define RLC_SDU_INDICATION(mSGpTR) (mSGpTR)->ittiMsg.rlc_sdu_indication #define NRDuDlReq(mSGpTR) (mSGpTR)->ittiMsg.nr_du_dl_req -#define NAS_OAI_TUN_NSA(mSGpTR) (mSGpTR)->ittiMsg.nas_oai_tun_nsa #define NAS_PDU_SESSION_REQ(mSGpTR) (mSGpTR)->ittiMsg.nas_pdu_session_req #define NR_RRC_RLC_MAXRTX(mSGpTR) (mSGpTR)->ittiMsg.nr_rlc_maxrtx_indication diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index c6385e765c..0dae34eda7 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -835,34 +835,7 @@ bool init_RA(NR_UE_MAC_INST_t *mac, int frame) // TODO this piece of code is required to compute MSG3_size that is used by ra_preambles_config function // Not a good implementation, it needs improvements - int size_sdu = 0; - - // Concerning the C-RNTI MAC CE, - // it has to be included if the UL transmission (Msg3) is not being made for the CCCH logical channel. - // Therefore it has been assumed that this event only occurs only when RA is done and it is not SA mode. - if (get_softmodem_params()->nsa) { - - uint8_t mac_sdus[34 * 1056]; - uint16_t sdu_lengths[NB_RB_MAX] = {0}; - int TBS_bytes = 848; - int mac_ce_len = 0; - unsigned short post_padding = 1; - - // fill ulsch_buffer with random data - for (int i = 0; i < TBS_bytes; i++) { - mac_sdus[i] = (unsigned char)(rand()&0xff); - } - // Sending SDUs with size 1 - // Initialize elements of sdu_lengths - sdu_lengths[0] = TBS_bytes - 3 - post_padding - mac_ce_len; - size_sdu += sdu_lengths[0]; - - if (size_sdu > 0) { - memcpy(ra->cont_res_id, mac_sdus, sizeof(uint8_t) * 6); - ra->Msg3_size = size_sdu + sizeof(NR_MAC_SUBHEADER_SHORT) + sizeof(NR_MAC_SUBHEADER_SHORT); - } - - } else if (!IS_SA_MODE(get_softmodem_params())) + if (!IS_SA_MODE(get_softmodem_params())) ra->Msg3_size = sizeof(uint16_t) + sizeof(NR_MAC_SUBHEADER_FIXED); // Random acces procedure initialization diff --git a/openair2/RRC/LTE/MESSAGES/asn1_msg.c b/openair2/RRC/LTE/MESSAGES/asn1_msg.c index 9511a7494b..61a0456511 100644 --- a/openair2/RRC/LTE/MESSAGES/asn1_msg.c +++ b/openair2/RRC/LTE/MESSAGES/asn1_msg.c @@ -4521,117 +4521,8 @@ is_en_dc_supported( #undef NCE } -void allocate_en_DC_r15(LTE_UE_EUTRA_Capability_t *cap) +OAI_UECapability_t *fill_ue_capability(char *UE_EUTRA_Capability_xer_fname) { - LOG_D(RRC, "Entered %s\n", __FUNCTION__); - if (!cap->nonCriticalExtension) - cap->nonCriticalExtension = CALLOC(1, sizeof(*cap->nonCriticalExtension)); - - typeof(cap->nonCriticalExtension) nce1 = cap->nonCriticalExtension; - if (!nce1->nonCriticalExtension) - nce1->nonCriticalExtension = CALLOC(1, sizeof(*nce1->nonCriticalExtension)); - - typeof(nce1->nonCriticalExtension) nce2 = nce1->nonCriticalExtension; - if (!nce2->nonCriticalExtension) - nce2->nonCriticalExtension = CALLOC(1, sizeof(*nce2->nonCriticalExtension)); - - typeof(nce2->nonCriticalExtension) nce3 = nce2->nonCriticalExtension; - if (!nce3->nonCriticalExtension) - nce3->nonCriticalExtension = CALLOC(1, sizeof(*nce3->nonCriticalExtension)); - - typeof(nce3->nonCriticalExtension) nce4 = nce3->nonCriticalExtension; - if (!nce4->nonCriticalExtension) - nce4->nonCriticalExtension = CALLOC(1, sizeof(*nce4->nonCriticalExtension)); - - typeof(nce4->nonCriticalExtension) nce5 = nce4->nonCriticalExtension; - if (!nce5->nonCriticalExtension) - nce5->nonCriticalExtension = CALLOC(1, sizeof(*nce5->nonCriticalExtension)); - - typeof(nce5->nonCriticalExtension) nce6 = nce5->nonCriticalExtension; - if (!nce6->nonCriticalExtension) - nce6->nonCriticalExtension = CALLOC(1, sizeof(*nce6->nonCriticalExtension)); - - typeof(nce6->nonCriticalExtension) nce7 = nce6->nonCriticalExtension; - if (!nce7->nonCriticalExtension) - nce7->nonCriticalExtension = CALLOC(1, sizeof(*nce7->nonCriticalExtension)); - - typeof(nce7->nonCriticalExtension) nce8 = nce7->nonCriticalExtension; - if (!nce8->nonCriticalExtension) - nce8->nonCriticalExtension = CALLOC(1, sizeof(*nce8->nonCriticalExtension)); - - typeof(nce8->nonCriticalExtension) nce9 = nce8->nonCriticalExtension; - if (!nce9->nonCriticalExtension) - nce9->nonCriticalExtension = CALLOC(1, sizeof(*nce9->nonCriticalExtension)); - - typeof(nce9->nonCriticalExtension) nce10 = nce9->nonCriticalExtension; - if (!nce10->nonCriticalExtension) - nce10->nonCriticalExtension = CALLOC(1, sizeof(*nce10->nonCriticalExtension)); - - typeof(nce10->nonCriticalExtension) nce11 = nce10->nonCriticalExtension; - if (!nce11->nonCriticalExtension) - nce11->nonCriticalExtension = CALLOC(1, sizeof(*nce11->nonCriticalExtension)); - - typeof(nce11->nonCriticalExtension) nce12 = nce11->nonCriticalExtension; - if (!nce12->nonCriticalExtension) - nce12->nonCriticalExtension = CALLOC(1, sizeof(*nce12->nonCriticalExtension)); - - typeof(nce12->nonCriticalExtension) nce13 = nce12->nonCriticalExtension; - if (!nce13->nonCriticalExtension) - nce13->nonCriticalExtension = CALLOC(1, sizeof(*nce13->nonCriticalExtension)); - - typeof(nce13->nonCriticalExtension) nce14 = nce13->nonCriticalExtension; - if (!nce14->nonCriticalExtension) - nce14->nonCriticalExtension = CALLOC(1, sizeof(*nce14->nonCriticalExtension)); - - typeof(nce14->nonCriticalExtension) nce15 = nce14->nonCriticalExtension; - if (!nce15->nonCriticalExtension) - nce15->nonCriticalExtension = CALLOC(1, sizeof(*nce15->nonCriticalExtension)); - - typeof(nce15->nonCriticalExtension) nce16 = nce15->nonCriticalExtension; - if (!nce16->nonCriticalExtension) - nce16->nonCriticalExtension = CALLOC(1, sizeof(*nce16->nonCriticalExtension)); - - typeof(nce16->nonCriticalExtension) nce17 = nce16->nonCriticalExtension; - if (!nce17->nonCriticalExtension) - nce17->nonCriticalExtension = CALLOC(1, sizeof(*nce17->nonCriticalExtension)); - - typeof(nce17->nonCriticalExtension) nce18 = nce17->nonCriticalExtension; - if (!nce18->nonCriticalExtension) - nce18->nonCriticalExtension = CALLOC(1, sizeof(*nce18->nonCriticalExtension)); - - typeof(nce18->nonCriticalExtension) nce19 = nce18->nonCriticalExtension; - if (!nce19->nonCriticalExtension) - nce19->nonCriticalExtension = CALLOC(1, sizeof(*nce19->nonCriticalExtension)); - - typeof(nce19->nonCriticalExtension) nce20 = nce19->nonCriticalExtension; - if (!nce20->nonCriticalExtension) - nce20->nonCriticalExtension = CALLOC(1, sizeof(*nce20->nonCriticalExtension)); - - typeof(nce20->nonCriticalExtension) nce21 = nce20->nonCriticalExtension; - if (!nce21->nonCriticalExtension) - nce21->nonCriticalExtension = CALLOC(1, sizeof(*nce21->nonCriticalExtension)); - - typeof(nce21->nonCriticalExtension) nce22 = nce21->nonCriticalExtension; - if (!nce22->nonCriticalExtension) - nce22->nonCriticalExtension = CALLOC(1, sizeof(*nce22->nonCriticalExtension)); - - typeof(nce22->nonCriticalExtension) nce23 = nce22->nonCriticalExtension; - if (!nce23->nonCriticalExtension) - nce23->nonCriticalExtension = CALLOC(1, sizeof(*nce23->nonCriticalExtension)); - - typeof(nce23->nonCriticalExtension) nce24 = nce23->nonCriticalExtension; - if (!nce24->irat_ParametersNR_r15) - nce24->irat_ParametersNR_r15 = CALLOC(1, sizeof(*nce24->irat_ParametersNR_r15)); - - typeof(nce24->irat_ParametersNR_r15) irat = nce24->irat_ParametersNR_r15; - if (!irat->en_DC_r15) - irat->en_DC_r15 = CALLOC(1, sizeof(*irat->en_DC_r15)); - - *irat->en_DC_r15 = LTE_IRAT_ParametersNR_r15__en_DC_r15_supported; - -} - -OAI_UECapability_t *fill_ue_capability(char *UE_EUTRA_Capability_xer_fname, bool received_nr_msg) { static OAI_UECapability_t UECapability; /* TODO declared static to allow returning this has an address should be allocated in a cleaner way. */ static LTE_SupportedBandEUTRA_t Bandlist[4]; // the macro asn1cSeqAdd() does not copy the source, but only stores a reference to it static LTE_InterFreqBandInfo_t InterFreqBandInfo[4][4]; // the macro asn1cSeqAdd() does not copy the source, but only stores a reference to it @@ -4716,14 +4607,6 @@ OAI_UECapability_t *fill_ue_capability(char *UE_EUTRA_Capability_xer_fname, bool // UE_EUTRA_Capability->measParameters.bandListEUTRA.list.count = 0; // no measurements on other bands // UE_EUTRA_Capability->featureGroupIndicators // null - - if (get_softmodem_params()->nsa && received_nr_msg) - { - allocate_en_DC_r15(UE_EUTRA_Capability); - if (!is_en_dc_supported(UE_EUTRA_Capability)){ - LOG_E(RRC, "We did not properly allocate en_DC_r15 for UE_EUTRA_Capability\n"); - } - } } else { FILE *f = fopen(UE_EUTRA_Capability_xer_fname, "r"); assert(f); diff --git a/openair2/RRC/LTE/MESSAGES/asn1_msg.h b/openair2/RRC/LTE/MESSAGES/asn1_msg.h index 3d5a8bb68c..b7d9dc4856 100644 --- a/openair2/RRC/LTE/MESSAGES/asn1_msg.h +++ b/openair2/RRC/LTE/MESSAGES/asn1_msg.h @@ -368,12 +368,10 @@ int do_HandoverPreparation(char *ho_buf, int ho_size, LTE_UE_EUTRA_Capability_t int do_HandoverCommand(char *ho_buf, int ho_size, char *rrc_buf, int rrc_size); -OAI_UECapability_t *fill_ue_capability(char *LTE_UE_EUTRA_Capability_xer, bool received_nr_msg); +OAI_UECapability_t *fill_ue_capability(char *LTE_UE_EUTRA_Capability_xer); int is_en_dc_supported(LTE_UE_EUTRA_Capability_t *c); -void allocate_en_DC_r15(LTE_UE_EUTRA_Capability_t *cap); - uint8_t do_UECapabilityEnquiry( const protocol_ctxt_t *const ctxt_pP, diff --git a/openair2/RRC/LTE/rrc_UE.c b/openair2/RRC/LTE/rrc_UE.c index b9d2551fcb..70692bfaa9 100644 --- a/openair2/RRC/LTE/rrc_UE.c +++ b/openair2/RRC/LTE/rrc_UE.c @@ -64,9 +64,6 @@ #include "LTE_UECapabilityEnquiry.h" #include "LTE_UE-CapabilityRequest.h" -#include "NR_RAT-Type.h" -#include "NR_UE-CapabilityRAT-Container.h" - #include "common/utils/tun_if.h" #if ENABLE_RAL #include "rrc_UE_ral.h" @@ -97,9 +94,6 @@ //for D2D int ctrl_sock_fd; struct sockaddr_in prose_app_addr; -static const char nsa_ipaddr[] = "127.0.0.1"; -static int from_nr_ue_fd = -1; -static int to_nr_ue_fd = -1; int slrb_id; int send_ue_information = 0; // TimeToTrigger enum mapping table (36.331 TimeToTrigger IE) @@ -144,22 +138,10 @@ typedef struct rrc_dcch_data_copy_t LTE_DL_DCCH_Message_t *dl_dcch_msg; } rrc_dcch_data_copy_t; -typedef struct rrc_nrue_cap_info_t -{ - uint8_t mesg[RRC_BUF_SIZE]; - size_t mesg_len; - LTE_DL_DCCH_Message_t *dl_dcch_msg; -} rrc_nrue_cap_info_t; - static void rrc_ue_process_ueCapabilityEnquiry(const protocol_ctxt_t *const ctxt_pP, LTE_UECapabilityEnquiry_t *UECapabilityEnquiry, uint8_t eNB_index); -static void rrc_ue_process_nrueCapabilityEnquiry(const protocol_ctxt_t *const ctxt_pP, - LTE_UECapabilityEnquiry_t *UECapabilityEnquiry, - rrc_nrue_cap_info_t *nrue_cap_info, - uint8_t eNB_index); - /** \brief Generates/Encodes RRCConnnectionSetupComplete message at UE * \param ctxt_pP Running context * \param eNB_index Index of corresponding eNB/CH @@ -184,8 +166,6 @@ static void rrc_ue_generate_RRCConnectionReconfigurationComplete(const protocol_ static void rrc_ue_generate_MeasurementReport(protocol_ctxt_t *const ctxt_pP, uint8_t eNB_index ); -static void rrc_ue_generate_nrMeasurementReport(protocol_ctxt_t *const ctxt_pP, uint8_t eNB_index ); - static uint8_t check_trigger_meas_event( module_id_t module_idP, frame_t frameP, @@ -208,8 +188,6 @@ rrc_ue_process_MBMSCountingRequest( uint8_t eNB_index ); -static void process_nr_nsa_msg(nsa_msg_t *msg, int msg_len); -static void nsa_sendmsg_to_nrue(const void *message, size_t msg_len, Rrc_Msg_Type_t msg_type); protocol_ctxt_t ctxt_pP_local; @@ -838,25 +816,6 @@ rrc_ue_process_measConfig( measObj->measObject.choice.measObjectEUTRA.allowedMeasBandwidth, measObj->measObject.choice.measObjectEUTRA.presenceAntennaPort1, measObj->measObject.choice.measObjectEUTRA.neighCellConfig.buf[0]); - } else if (measObj->measObject.present == LTE_MeasObjectToAddMod__measObject_PR_measObjectNR_r15) { - ue->subframeCount = 0; - LOG_I(RRC, "NR_r15 Measurement: carrierFreq: %ld\n", - measObj->measObject.choice.measObjectNR_r15.carrierFreq_r15); - if (!get_softmodem_params()->nsa) { - LOG_E(RRC, "Not in NSA mode but attempting to send measurement request to NR-UE\n"); - return; - } - uint8_t buffer[RRC_BUF_SIZE]; - asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_LTE_MeasObjectToAddMod, - NULL, - measObj, - buffer, - sizeof(buffer)); - AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %zu)!\n", - enc_rval.failed_type->name, enc_rval.encoded); - nsa_sendmsg_to_nrue(buffer, (enc_rval.encoded + 7)/8, RRC_MEASUREMENT_PROCEDURE); - LOG_A(RRC, "Encoded measurement object %zu bits (%zu bytes) and sent to NR UE\n", - enc_rval.encoded, (enc_rval.encoded + 7)/8); } LOG_D(RRC, "Adding measurement object [%d][%ld]\n", eNB_index, ind); ue->MeasObj[eNB_index][ind-1]=measObj; @@ -1697,102 +1656,6 @@ rrc_ue_process_MBMSCountingRequest( } - -//----------------------------------------------------------------------------- -void -rrc_ue_process_nrueCapabilityEnquiry( - const protocol_ctxt_t *const ctxt_pP, - LTE_UECapabilityEnquiry_t *UECapabilityEnquiry, - rrc_nrue_cap_info_t *nrue_cap_info, - uint8_t eNB_index -) -//----------------------------------------------------------------------------- -{ - asn_enc_rval_t enc_rval; - uint8_t buffer[RRC_BUF_SIZE]; - LOG_I(RRC,"[UE %d] Frame %d: Receiving from SRB1 (DL-DCCH), Processing NRUECapabilityEnquiry (eNB %d)\n", - ctxt_pP->module_id, - ctxt_pP->frame, - eNB_index); - LTE_UL_DCCH_Message_t ul_dcch_msg; - memset(&ul_dcch_msg, 0, sizeof(ul_dcch_msg)); - LTE_UECapabilityInformation_t *ue_cap = &ul_dcch_msg.message.choice.c1.choice.ueCapabilityInformation; - ul_dcch_msg.message.present = LTE_UL_DCCH_MessageType_PR_c1; - ul_dcch_msg.message.choice.c1.present = LTE_UL_DCCH_MessageType__c1_PR_ueCapabilityInformation; - ue_cap->rrc_TransactionIdentifier = UECapabilityEnquiry->rrc_TransactionIdentifier; - - NR_UE_CapabilityRAT_Container_t ue_CapabilityRAT_Container; - memset(&ue_CapabilityRAT_Container, 0, sizeof(ue_CapabilityRAT_Container)); - ue_CapabilityRAT_Container.rat_Type = NR_RAT_Type_nr; - OCTET_STRING_fromBuf(&ue_CapabilityRAT_Container.ue_CapabilityRAT_Container, - (const char *)nrue_cap_info->mesg, - nrue_cap_info->mesg_len); - # if(1) // TODO: The MRDC capabilites should be filled in the NR UE - NR_UE_CapabilityRAT_Container_t ue_CapabilityRAT_Container_mrdc; - memset(&ue_CapabilityRAT_Container_mrdc, 0, sizeof(ue_CapabilityRAT_Container_mrdc)); - uint8_t buffer_mrdc[RRC_BUF_SIZE]; - NR_UE_MRDC_Capability_t *UE_Capability_MRDC = CALLOC(1, sizeof(NR_UE_MRDC_Capability_t)); - asn_enc_rval_t enc_rval_mrdc = uper_encode_to_buffer(&asn_DEF_NR_UE_MRDC_Capability, - NULL, - (void *)UE_Capability_MRDC, - &buffer_mrdc, - sizeof(buffer_mrdc)); - AssertFatal (enc_rval_mrdc.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", - enc_rval_mrdc.failed_type->name, enc_rval_mrdc.encoded); - LOG_I(RRC, "[NR_RRC] NRUE MRDC Capability encoded, %ld bytes (%ld bits)\n", - (enc_rval_mrdc.encoded + 7) / 8, enc_rval_mrdc.encoded + 7); - - ue_CapabilityRAT_Container_mrdc.rat_Type = NR_RAT_Type_eutra_nr; - OCTET_STRING_fromBuf(&ue_CapabilityRAT_Container_mrdc.ue_CapabilityRAT_Container, - (const char *)buffer_mrdc, - (enc_rval_mrdc.encoded + 7) / 8); - #endif - - ue_cap->criticalExtensions.present = LTE_UECapabilityInformation__criticalExtensions_PR_c1; - ue_cap->criticalExtensions.choice.c1.present = LTE_UECapabilityInformation__criticalExtensions__c1_PR_ueCapabilityInformation_r8; - ue_cap->criticalExtensions.choice.c1.choice.ueCapabilityInformation_r8.ue_CapabilityRAT_ContainerList.list.count = 0; - int count = UECapabilityEnquiry->criticalExtensions.choice.c1.choice.ueCapabilityEnquiry_r8.ue_CapabilityRequest.list.count; - xer_fprint(stdout, &asn_DEF_NR_UE_CapabilityRAT_Container, (void *)&ue_CapabilityRAT_Container); - LTE_UE_CapabilityRequest_t *cap_req = &UECapabilityEnquiry->criticalExtensions.choice.c1.choice.ueCapabilityEnquiry_r8.ue_CapabilityRequest; - for (int i = 0; i < count; i++) { - enc_rval.encoded = 0; - if (*cap_req->list.array[i] == LTE_RAT_Type_nr) { - asn1cSeqAdd(&ue_cap->criticalExtensions.choice.c1.choice.ueCapabilityInformation_r8.ue_CapabilityRAT_ContainerList.list, - &ue_CapabilityRAT_Container); - ue_cap->criticalExtensions.choice.c1.choice.ueCapabilityInformation_r8.ue_CapabilityRAT_ContainerList.list.array[i]->rat_Type = LTE_RAT_Type_nr; - asn_enc_rval_t enc_rval_nr = uper_encode_to_buffer(&asn_DEF_LTE_UL_DCCH_Message, NULL, (void *) &ul_dcch_msg, buffer, sizeof(buffer)); - AssertFatal (enc_rval_nr.encoded > 0, "ASN1 message encoding failed (%s, %jd)!\n", - enc_rval_nr.failed_type->name, enc_rval_nr.encoded); - enc_rval.encoded = enc_rval.encoded + enc_rval_nr.encoded; - xer_fprint(stdout, &asn_DEF_LTE_UL_DCCH_Message, (void *)&ul_dcch_msg); - LOG_A(RRC, "%s: NR_UECapInfo LTE_RAT_Type_nr Encoded %zd bits (%zd bytes)\n", - __FUNCTION__, enc_rval.encoded, (enc_rval.encoded+7)/8); - } - else if (*cap_req->list.array[i] == LTE_RAT_Type_eutra_nr) { - asn1cSeqAdd(&ue_cap->criticalExtensions.choice.c1.choice.ueCapabilityInformation_r8.ue_CapabilityRAT_ContainerList.list, - &ue_CapabilityRAT_Container_mrdc); - ue_cap->criticalExtensions.choice.c1.choice.ueCapabilityInformation_r8.ue_CapabilityRAT_ContainerList.list.array[i]->rat_Type = LTE_RAT_Type_eutra_nr; - asn_enc_rval_t enc_rval_eutra_nr = uper_encode_to_buffer(&asn_DEF_LTE_UL_DCCH_Message, NULL, (void *) &ul_dcch_msg, buffer, sizeof(buffer)); - AssertFatal (enc_rval_eutra_nr.encoded > 0, "ASN1 message encoding failed (%s, %jd)!\n", - enc_rval_eutra_nr.failed_type->name, enc_rval_eutra_nr.encoded); - enc_rval.encoded = enc_rval.encoded + enc_rval_eutra_nr.encoded; - xer_fprint(stdout, &asn_DEF_LTE_UL_DCCH_Message, (void *)&ul_dcch_msg); - LOG_A(RRC, "%s: NR_UECapInfo LTE_RAT_Type_eutra_nr Encoded %zd bits (%zd bytes)\n", - __FUNCTION__, enc_rval.encoded, (enc_rval.encoded+7)/8); - } - rrc_data_req_ue ( - ctxt_pP, - DCCH, - rrc_mui++, - SDU_CONFIRM_NO, - (enc_rval.encoded + 7) / 8, - buffer, - PDCP_TRANSMISSION_MODE_CONTROL); - } -} - - - //----------------------------------------------------------------------------- void rrc_ue_process_ueCapabilityEnquiry( @@ -1861,57 +1724,9 @@ rrc_ue_process_ueCapabilityEnquiry( buffer, PDCP_TRANSMISSION_MODE_CONTROL); } - else if (*UECapabilityEnquiry->criticalExtensions.choice.c1.choice.ueCapabilityEnquiry_r8.ue_CapabilityRequest.list.array[i] - == LTE_RAT_Type_nr) { - asn1cSeqAdd( - &ul_dcch_msg.message.choice.c1.choice.ueCapabilityInformation.criticalExtensions.choice.c1.choice.ueCapabilityInformation_r8.ue_CapabilityRAT_ContainerList.list, - &ue_CapabilityRAT_Container); - enc_rval = uper_encode_to_buffer(&asn_DEF_LTE_UL_DCCH_Message, NULL, (void *) &ul_dcch_msg, buffer, 100); - AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %jd)!\n", - enc_rval.failed_type->name, enc_rval.encoded); - - if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { - xer_fprint(stdout, &asn_DEF_LTE_UL_DCCH_Message, (void *)&ul_dcch_msg); - } - - LOG_A(RRC, "%s: NR_UECapabilityInformation Encoded %zd bits (%zd bytes)\n", - __FUNCTION__, enc_rval.encoded,(enc_rval.encoded+7)/8); - rrc_data_req_ue ( - ctxt_pP, - DCCH, - rrc_mui++, - SDU_CONFIRM_NO, - (enc_rval.encoded + 7) / 8, - buffer, - PDCP_TRANSMISSION_MODE_CONTROL); - } } } -static bool is_nr_r15_config_present(LTE_RRCConnectionReconfiguration_r8_IEs_t *c) -{ -#define NCE nonCriticalExtension -#define chk(x) do { \ - if ((x) == NULL) { \ - LOG_I(RRC, "NULL at %d\n", __LINE__); \ - return false; \ - } \ -} while(0) - chk(c); - chk(c->NCE); - chk(c->NCE->NCE); - chk(c->NCE->NCE->NCE); - chk(c->NCE->NCE->NCE->NCE); - chk(c->NCE->NCE->NCE->NCE->NCE); - chk(c->NCE->NCE->NCE->NCE->NCE->NCE); - chk(c->NCE->NCE->NCE->NCE->NCE->NCE->NCE); - chk(c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE); - return c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->nr_Config_r15->present == - LTE_RRCConnectionReconfiguration_v1510_IEs__nr_Config_r15_PR_setup; - -#undef NCE -#undef chk -} /** \brief process the received rrcConnectionReconfiguration message at UE \param ctxt_pP Running context \param *rrcConnectionReconfiguration pointer to the sturcture @@ -1932,42 +1747,6 @@ static void rrc_ue_process_rrcConnectionReconfiguration(const protocol_ctxt_t *c criticalExtensions.choice.c1. choice.rrcConnectionReconfiguration_r8; - if (is_nr_r15_config_present(r_r8)) { - OCTET_STRING_t *nr_RadioBearer = r_r8->nonCriticalExtension->nonCriticalExtension-> - nonCriticalExtension->nonCriticalExtension->nonCriticalExtension-> - nonCriticalExtension->nonCriticalExtension->nonCriticalExtension-> - nr_RadioBearerConfig1_r15; - OCTET_STRING_t *nr_SecondaryCellGroup = r_r8->nonCriticalExtension->nonCriticalExtension-> - nonCriticalExtension->nonCriticalExtension->nonCriticalExtension-> - nonCriticalExtension->nonCriticalExtension->nonCriticalExtension-> - nr_Config_r15->choice.setup.nr_SecondaryCellGroupConfig_r15; - uint32_t total_size = nr_RadioBearer->size + nr_SecondaryCellGroup->size; - struct msg { - uint32_t RadioBearer_size; - uint32_t SecondaryCellGroup_size; - uint8_t trans_id; - uint8_t padding[3]; - uint8_t *buffer; - } msg; - - msg.buffer = calloc(total_size, sizeof(*msg.buffer)); - AssertFatal(msg.buffer != NULL, "Error in memory allocation\n"); - msg.RadioBearer_size = nr_RadioBearer->size; - msg.SecondaryCellGroup_size = nr_SecondaryCellGroup->size; - msg.trans_id = rrcConnectionReconfiguration->rrc_TransactionIdentifier; - memcpy(msg.buffer, nr_RadioBearer->buf, nr_RadioBearer->size); - memcpy(msg.buffer + nr_RadioBearer->size, nr_SecondaryCellGroup->buf, nr_SecondaryCellGroup->size); - - LOG_D(RRC, "nr_RadioBearerConfig1_r15 size %ld nr_SecondaryCellGroupConfig_r15 size %ld, sizeof(msg) = %zu\n", - nr_RadioBearer->size, - nr_SecondaryCellGroup->size, - sizeof(msg)); - - nsa_sendmsg_to_nrue(&msg, sizeof(msg), RRC_CONFIG_COMPLETE_REQ); - free(msg.buffer); - LOG_A(RRC, "Sent RRC_CONFIG_COMPLETE_REQ to the NR UE\n"); - } - if (r_r8->mobilityControlInfo) { LOG_I(RRC,"Mobility Control Information is present\n"); rrc_ue_process_mobilityControlInfo( @@ -2483,52 +2262,7 @@ static void rrc_ue_decode_dcch(const protocol_ctxt_t *const ctxt_pP, ctxt_pP->module_id, eNB_indexP); - LTE_UE_CapabilityRequest_t *ue_cap = &dl_dcch_msg->message.choice.c1.choice.ueCapabilityEnquiry.criticalExtensions. - choice.c1.choice.ueCapabilityEnquiry_r8.ue_CapabilityRequest; - bool have_received_nrue_cap = false; - for (int i = 0; i < ue_cap->list.count; i++) { - if (*ue_cap->list.array[i] == LTE_RAT_Type_nr || *ue_cap->list.array[i] == LTE_RAT_Type_eutra_nr) { - have_received_nrue_cap = true; - break; - } - } - if (have_received_nrue_cap) { - LTE_UECapabilityEnquiry_t *ueCapabilityEnquiry_nsa = &dl_dcch_msg->message.choice.c1.choice.ueCapabilityEnquiry; - OCTET_STRING_t * requestedFreqBandsNR = ueCapabilityEnquiry_nsa-> - criticalExtensions.choice.c1.choice.ueCapabilityEnquiry_r8.nonCriticalExtension-> - nonCriticalExtension->nonCriticalExtension->nonCriticalExtension-> - nonCriticalExtension->requestedFreqBandsNR_MRDC_r15; - nsa_sendmsg_to_nrue(requestedFreqBandsNR->buf, requestedFreqBandsNR->size, NRUE_CAPABILITY_ENQUIRY); - LOG_A(RRC, "Second ueCapabilityEnquiry (request for NR capabilities) sent to NR UE with size %zu\n", - requestedFreqBandsNR->size); - // Save ueCapabilityEnquiry so we can use in nsa mode after nrUE response is received - UE_RRC_INFO *info = &UE_rrc_inst[ctxt_pP->module_id].Info[eNB_indexP]; - if (info->dl_dcch_msg != NULL) { - info->dl_dcch_msg = NULL; - } - info->dl_dcch_msg = dl_dcch_msg; - dl_dcch_msg = NULL; - } else if (get_softmodem_params()->nsa && !have_received_nrue_cap) { - LTE_UECapabilityEnquiry_t *ueCapabilityEnquiry_nsa = &dl_dcch_msg->message.choice.c1.choice.ueCapabilityEnquiry; - OCTET_STRING_t * requestedFreqBandsNR = ueCapabilityEnquiry_nsa-> - criticalExtensions.choice.c1.choice.ueCapabilityEnquiry_r8.nonCriticalExtension-> - nonCriticalExtension->nonCriticalExtension->nonCriticalExtension-> - nonCriticalExtension->requestedFreqBandsNR_MRDC_r15; - nsa_sendmsg_to_nrue(requestedFreqBandsNR->buf, requestedFreqBandsNR->size, UE_CAPABILITY_ENQUIRY); - LOG_A(RRC, "Initial ueCapabilityEnquiry sent to NR UE with size %zu\n", requestedFreqBandsNR->size); - // Save ueCapabilityEnquiry so we can use in nsa mode after nrUE response is received - UE_RRC_INFO *info = &UE_rrc_inst[ctxt_pP->module_id].Info[eNB_indexP]; - if (info->dl_dcch_msg != NULL) { - info->dl_dcch_msg = NULL; - } - info->dl_dcch_msg = dl_dcch_msg; - dl_dcch_msg = NULL; - } else { - rrc_ue_process_ueCapabilityEnquiry( - ctxt_pP, - &dl_dcch_msg->message.choice.c1.choice.ueCapabilityEnquiry, - eNB_indexP); - } + rrc_ue_process_ueCapabilityEnquiry(ctxt_pP, &dl_dcch_msg->message.choice.c1.choice.ueCapabilityEnquiry, eNB_indexP); break; case LTE_DL_DCCH_MessageType__c1_PR_counterCheck: @@ -4285,43 +4019,6 @@ void ue_meas_filtering( const protocol_ctxt_t *const ctxt_pP, const uint8_t eNB_ } } } -//Below routine implements Measurement Reporting procedure from 36.331 Section 5.5.5 -//----------------------------------------------------------------------------- -void rrc_ue_generate_nrMeasurementReport(protocol_ctxt_t *const ctxt_pP, uint8_t eNB_index ) { - uint8_t buffer[RRC_BUF_SIZE]; - UE_RRC_INST *ue = &UE_rrc_inst[ctxt_pP->module_id]; - uint8_t target_eNB_offset = ue->Info[0].handoverTarget; - LTE_PhysCellId_t targetCellId = ue->HandoverInfoUe.targetCellId; - - for (int i = 0; i < MAX_MEAS_ID; i++) { - if (ue->measReportList[eNB_index][i] != NULL) { - LTE_MeasId_t measId = ue->measReportList[eNB_index][i]->measId; - long rsrp_s = binary_search_float(RSRP_meas_mapping, 98, ue->rsrp_db_filtered[eNB_index]); - long rsrq_s = binary_search_float(RSRQ_meas_mapping, 35, ue->rsrq_db_filtered[eNB_index]); - long rsrp_tar = binary_search_float(RSRP_meas_mapping, 98, ue->rsrp_db_filtered[target_eNB_offset]); - long rsrq_tar = binary_search_float(RSRQ_meas_mapping, 35, ue->rsrq_db_filtered[target_eNB_offset]); - - LOG_I(RRC,"[UE %d] Frame %d: source eNB: %d target eNB: %d servingCell(%d) targetCell(%ld)\n", - ctxt_pP->module_id, - ctxt_pP->frame, - eNB_index, - target_eNB_offset, - get_adjacent_cell_id(ctxt_pP->module_id, eNB_index), - targetCellId); - - if (ctxt_pP->frame != 0) { - LOG_I(RRC, "measId %ld, targetCellId %ld, rsrp_s %ld, rsrq_s %ld, rsrp_t %ld, rsrq_t %ld\n", - measId, targetCellId, rsrp_s, rsrq_s, rsrp_tar, rsrq_tar); - ssize_t size = do_nrMeasurementReport(buffer, sizeof(buffer), measId, targetCellId, rsrp_s, rsrq_s, rsrp_tar, rsrq_tar); - AssertFatal(size >= 0, "do_nrMeasurementReport failed \n"); - LOG_I(RRC, "[UE %d] Frame %d : Generating Measurement Report for eNB %d\n", - ctxt_pP->module_id, ctxt_pP->frame, eNB_index); - const bool result = pdcp_data_req(ctxt_pP, SRB_FLAG_YES, DCCH, rrc_mui++, 0, size, buffer, PDCP_TRANSMISSION_MODE_DATA,NULL, NULL); - AssertFatal (result == true, "PDCP data request failed!\n"); - } - } - } -} //Below routine implements Measurement Reporting procedure from 36.331 Section 5.5.5 //----------------------------------------------------------------------------- @@ -4395,39 +4092,6 @@ void rrc_ue_generate_MeasurementReport(protocol_ctxt_t *const ctxt_pP, uint8_t e } } -static bool does_rrcConnReconfig_have_nr(const UE_RRC_INST *ue) { - for (int i = 0; i < NB_CNX_UE; i++) { - for (int j = 0; j < MAX_MEAS_ID; j++) { - LTE_ReportConfigId_t reportConfigId = ue->MeasId[i][j]->reportConfigId; - AssertFatal(reportConfigId >= 1 && reportConfigId <= MAX_MEAS_CONFIG, "Bad index\n"); - const LTE_ReportConfigToAddMod_t *rc = ue->ReportConfig[i][reportConfigId-1]; - if (rc == NULL) { - LOG_D(RRC, "UE_rrc_inst[ctxt_pP->module_id]->ReportConfig[%d][%ld] = NULL\n", i, reportConfigId-1); - continue; - } - if (rc->reportConfig.present != LTE_ReportConfigToAddMod__reportConfig_PR_reportConfigInterRAT) { - LOG_D(RRC, "reportConfig.present = %d, not LTE_ReportConfigToAddMod__reportConfig_PR_reportConfigInterRAT\n", - rc->reportConfig.present); - continue; - } - LTE_ReportConfigInterRAT_t irat = rc->reportConfig.choice.reportConfigInterRAT; - if (irat.triggerType.present != LTE_ReportConfigInterRAT__triggerType_PR_event) { - LOG_D(RRC, "irat.triggerType.present = %d, not LTE_ReportConfigInterRAT__triggerType_PR_event\n", - irat.triggerType.present); - continue; - } - if (irat.triggerType.choice.event.eventId.present != LTE_ReportConfigInterRAT__triggerType__event__eventId_PR_eventB1_NR_r15) { - LOG_D(RRC, "irat.triggerType.choice.event.eventId.present = %d\n", - irat.triggerType.choice.event.eventId.present); - continue; - } - return true; - } - } - return false; -} - - // Measurement report triggering, described in 36.331 Section 5.5.4.1: called periodically //----------------------------------------------------------------------------- void ue_measurement_report_triggering(protocol_ctxt_t *const ctxt_pP, const uint8_t eNB_index ) { @@ -4528,49 +4192,6 @@ void ue_measurement_report_triggering(protocol_ctxt_t *const ctxt_pP, const uint } } } - - if (ue->MeasObj[i][measObjId-1]->measObject.present == LTE_MeasObjectToAddMod__measObject_PR_measObjectNR_r15) { - if (!does_rrcConnReconfig_have_nr(ue)) - break; - LTE_ReportConfigInterRAT_t *rc = &ue->ReportConfig[i][reportConfigId-1]->reportConfig.choice.reportConfigInterRAT; - LTE_TimeToTrigger_t trig_per = rc->triggerType.choice.event.timeToTrigger; - ttt_ms = timeToTrigger_ms[trig_per]; - LOG_D(RRC, "[UE %d] Frame %d: B1_NR_r15 event. count %d, ttt %ld\n", - ctxt_pP->module_id, ctxt_pP->frame, ue->subframeCount, ttt_ms); - if (ue->subframeCount < ttt_ms) { - ++ue->subframeCount; - break; - } - ue->subframeCount = 0; - bool is_state_connected = false; - bool is_t304_inactive = false; - bool have_meas_flag = false; - if (ue->Info[0].State >= RRC_CONNECTED) - is_state_connected = true; - if (ue->Info[0].T304_active == 0) - is_t304_inactive = true; - if (ue->HandoverInfoUe.measFlag == 1) - have_meas_flag = true; - - if (is_state_connected && is_t304_inactive && have_meas_flag) { - LOG_I(RRC,"[UE %d] Frame %d: Triggering generation of Meas Report for NR_r15. count = %d\n", - ctxt_pP->module_id, ctxt_pP->frame, ue->subframeCount); - if (ue->measReportList[i][j] == NULL) { - ue->measReportList[i][j] = malloc(sizeof(MEAS_REPORT_LIST)); - } - ue->measReportList[i][j]->measId = ue->MeasId[i][j]->measId; - ue->measReportList[i][j]->numberOfReportsSent = 0; - rrc_ue_generate_nrMeasurementReport(ctxt_pP, eNB_index); - ue->HandoverInfoUe.measFlag = 1; - LOG_I(RRC,"[UE %d] Frame %d: RSRB detected, state: %d \n", - ctxt_pP->module_id, ctxt_pP->frame, ue->Info[0].State); - } else { - if(ue->measReportList[i][j] != NULL) { - free(ue->measReportList[i][j]); - } - ue->measReportList[i][j] = NULL; - } - } } } } @@ -4970,38 +4591,6 @@ void *rrc_ue_task( void *args_p ) { break; } - case RRC_NRUE_CAP_INFO_IND: - { - PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, RRC_NRUE_CAP_INFO_IND (msg_p).module_id, - ENB_FLAG_NO, RRC_NRUE_CAP_INFO_IND (msg_p).rnti, - RRC_NRUE_CAP_INFO_IND (msg_p).frame, - 0, - RRC_NRUE_CAP_INFO_IND (msg_p).eNB_index); - LOG_I(RRC, "[UE %d] Received %s. Now calling rrc_ue_process_nrueCapabilityEnquiry\n", - ue_mod_id, ITTI_MSG_NAME (msg_p)); - rrc_nrue_cap_info_t *nrue_cap_info = (void *)RRC_NRUE_CAP_INFO_IND (msg_p).sdu_p; - AssertFatal(RRC_NRUE_CAP_INFO_IND (msg_p).sdu_size == sizeof(*nrue_cap_info), "Size of nrue_cap_info incorrect\n"); - rrc_ue_process_nrueCapabilityEnquiry( - &ctxt, - &nrue_cap_info->dl_dcch_msg->message.choice.c1.choice.ueCapabilityEnquiry, - nrue_cap_info, - RRC_NRUE_CAP_INFO_IND (msg_p).eNB_index); - SEQUENCE_free(&asn_DEF_LTE_DL_DCCH_Message, nrue_cap_info->dl_dcch_msg, ASFM_FREE_EVERYTHING); - result = itti_free (ITTI_MSG_ORIGIN_ID(msg_p), RRC_NRUE_CAP_INFO_IND (msg_p).sdu_p); - AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); - break; - } - case NAS_OAI_TUN_NSA: - { - LOG_D(NAS, "Received %s: length %lu. About to send this to the NR UE\n", ITTI_MSG_NAME (msg_p), - sizeof(NAS_OAI_TUN_NSA (msg_p).buffer)); - char buffer[RRC_BUF_SIZE]; - memcpy(buffer, NAS_OAI_TUN_NSA(msg_p).buffer, sizeof(buffer)); - nsa_sendmsg_to_nrue(buffer, sizeof(buffer), OAI_TUN_IFACE_NSA); - break; - } - - case NAS_KENB_REFRESH_REQ: memcpy((void *)UE_rrc_inst[ue_mod_id].kenb, (void *)NAS_KENB_REFRESH_REQ(msg_p).kenb, sizeof(UE_rrc_inst[ue_mod_id].kenb)); LOG_D(RRC, "[UE %d] Received %s: refreshed RRC::KeNB = " @@ -5331,8 +4920,7 @@ openair_rrc_top_init_ue( memset (UE_rrc_inst, 0, NB_UE_INST * sizeof(UE_RRC_INST)); LOG_D(RRC, "ALLOCATE %d Bytes for UE_RRC_INST @ %p\n", (unsigned int)(NB_UE_INST*sizeof(UE_RRC_INST)), UE_rrc_inst); // fill UE capability - bool received_nr_msg = false; - UECap = fill_ue_capability (uecap_xer, received_nr_msg); + UECap = fill_ue_capability (uecap_xer); for (module_id = 0; module_id < NB_UE_INST; module_id++) { UE_rrc_inst[module_id].UECap = UECap; @@ -6405,229 +5993,3 @@ rrc_rx_tx_ue( VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_OUT); return (RRC_OK); } - -void *recv_msgs_from_nr_ue(void *args_p) -{ - itti_mark_task_ready (TASK_RRC_NSA_UE); - for (;;) - { - nsa_msg_t msg; - int recvLen = recvfrom(from_nr_ue_fd, &msg, sizeof(msg), - MSG_WAITALL | MSG_TRUNC, NULL, NULL); - if (recvLen == -1) - { - LOG_E(RRC, "%s: recvfrom: %s\n", __func__, strerror(errno)); - continue; - } - if (recvLen > sizeof(msg)) - { - LOG_E(NR_RRC, "%s: Received a truncated message %d\n", __func__, recvLen); - continue; - } - LOG_D(RRC, "We have received a %d msg (%d bytes). Calling process_nr_nsa_msg\n", msg.msg_type, recvLen); - process_nr_nsa_msg(&msg, recvLen); - } - -} - -void nsa_sendmsg_to_nrue(const void *message, size_t msg_len, Rrc_Msg_Type_t msg_type) -{ - LOG_I(RRC, "Entered %s \n", __FUNCTION__); - nsa_msg_t n_msg; - if (msg_len > sizeof(n_msg.msg_buffer)) - { - LOG_E(RRC, "%s: message too big: %zu\n", __func__, msg_len); - abort(); - } - n_msg.msg_type = msg_type; - memcpy(n_msg.msg_buffer, message, msg_len); - size_t to_send = sizeof(n_msg.msg_type) + msg_len; - - struct sockaddr_in sa = - { - .sin_family = AF_INET, - .sin_port = htons(6008 + ue_id_g * 2), - }; - int sent = sendto(to_nr_ue_fd, &n_msg, to_send, 0, - (struct sockaddr *)&sa, sizeof(sa)); - if (sent == -1) - { - LOG_E(RRC, "%s: sendto: %s\n", __func__, strerror(errno)); - return; - } - if (sent != to_send) - { - LOG_E(RRC, "%s: Short send %d != %zu\n", __func__, sent, to_send); - return; - } - LOG_I(RRC, "Sent a %d message to the nrUE (%d bytes) \n", msg_type, sent); -} - -void init_connections_with_nr_ue() -{ - struct sockaddr_in sa = - { - .sin_family = AF_INET, - .sin_port = htons(6007 + ue_id_g * 2), - }; - AssertFatal(from_nr_ue_fd == -1, "from_nr_ue_fd was assigned already"); - from_nr_ue_fd = socket(AF_INET, SOCK_DGRAM, 0); - if (from_nr_ue_fd == -1) - { - LOG_E(RRC, "%s: Error opening socket %d (%d:%s)\n", __FUNCTION__, from_nr_ue_fd, errno, strerror(errno)); - abort(); - } - - if (inet_aton(nsa_ipaddr, &sa.sin_addr) == 0) - { - LOG_E(RRC, "Bad nsa_ipaddr '%s'\n", nsa_ipaddr); - abort(); - } - - if (bind(from_nr_ue_fd, (struct sockaddr *) &sa, sizeof(sa)) == -1) - { - LOG_E(RRC,"%s: Failed to bind the socket\n", __FUNCTION__); - abort(); - } - - AssertFatal(to_nr_ue_fd == -1, "to_nr_ue_fd was assigned already"); - to_nr_ue_fd = socket(AF_INET, SOCK_DGRAM, 0); - if (to_nr_ue_fd == -1) - { - LOG_E(RRC, "%s: Error opening socket %d (%d:%s)\n", __FUNCTION__, to_nr_ue_fd, errno, strerror(errno)); - abort(); - } - -} - -void process_nr_nsa_msg(nsa_msg_t *msg, int msg_len) -{ - if (msg_len < sizeof(msg->msg_type)) - { - LOG_E(RRC, "Msg_len = %d\n", msg_len); - return; - } - LOG_D(RRC, "We are processing an NSA message %d \n", msg->msg_type); - Rrc_Msg_Type_t msg_type = msg->msg_type; - uint8_t *const msg_buffer = msg->msg_buffer; - msg_len -= sizeof(msg->msg_type); - bool received_nr_msg = true; - protocol_ctxt_t ctxt; - module_id_t module_id = 0; - eNB_index_t eNB_index = 0; - - switch (msg_type) - { - case NRUE_CAPABILITY_INFO: - { - LOG_I(RRC, "Create itti msg to send received NRUE_CAPABILITY_INFO to eNB\n"); - - MessageDef *message_p; - rrc_nrue_cap_info_t *nrue_cap_buf = itti_malloc (TASK_RRC_NSA_UE, - TASK_RRC_UE, - sizeof(rrc_nrue_cap_info_t)); - AssertFatal(msg_len <= sizeof(nrue_cap_buf->mesg), "msg_len = %d\n", msg_len); - memcpy(nrue_cap_buf->mesg, msg_buffer, msg_len); - nrue_cap_buf->mesg_len = msg_len; - UE_RRC_INFO *info = &UE_rrc_inst[module_id].Info[eNB_index]; - nrue_cap_buf->dl_dcch_msg = info->dl_dcch_msg; - info->dl_dcch_msg = NULL; - message_p = itti_alloc_new_message (TASK_RRC_UE, 0, RRC_NRUE_CAP_INFO_IND); - RRC_NRUE_CAP_INFO_IND (message_p).sdu_p = (void *)nrue_cap_buf; - RRC_NRUE_CAP_INFO_IND (message_p).sdu_size = sizeof(*nrue_cap_buf); - RRC_NRUE_CAP_INFO_IND (message_p).module_id = module_id; - RRC_NRUE_CAP_INFO_IND (message_p).rnti = info->rnti; - RRC_NRUE_CAP_INFO_IND (message_p).eNB_index = eNB_index; - itti_send_msg_to_task (TASK_RRC_UE, 0, message_p); - LOG_I(RRC, "Sent itti RRC_NRUE_CAP_INFO_IND\n"); - break; - } - case UE_CAPABILITY_DUMMY: - { - fill_ue_capability(NULL, received_nr_msg); - UE_rrc_inst[module_id].UECap = UE_rrc_inst->UECap; - if (!is_en_dc_supported(UE_rrc_inst->UECap->UE_EUTRA_Capability)) - { - LOG_E(RRC, "en_dc is NOT supported! Not sending RRC_DCCH_DATA_COPY_IND to update UE_Capability_INFO\n"); - break; - } - - LOG_I(RRC, "Send itti msg to trigger processing of capabilites b/c we have a UE_CAPABILITY_DUMMY\n"); - MessageDef *message_p; - rrc_dcch_data_copy_t *dl_dcch_buffer = itti_malloc (TASK_RRC_NSA_UE, - TASK_RRC_UE, - sizeof(rrc_dcch_data_copy_t)); - UE_RRC_INFO *info = &UE_rrc_inst[module_id].Info[eNB_index]; - dl_dcch_buffer->dl_dcch_msg = info->dl_dcch_msg; - info->dl_dcch_msg = NULL; - message_p = itti_alloc_new_message (TASK_RRC_UE, 0, RRC_DCCH_DATA_COPY_IND); - RRC_DCCH_DATA_COPY_IND (message_p).sdu_p = (void *)dl_dcch_buffer; - RRC_DCCH_DATA_COPY_IND (message_p).sdu_size = sizeof(rrc_dcch_data_copy_t); - RRC_DCCH_DATA_COPY_IND (message_p).module_id = module_id; - RRC_DCCH_DATA_COPY_IND (message_p).rnti = info->rnti; - RRC_DCCH_DATA_COPY_IND (message_p).eNB_index = eNB_index; - itti_send_msg_to_task (TASK_RRC_UE, 0, message_p); - LOG_I(RRC, "Sent itti RRC_DCCH_DATA_COPY_IND\n"); - break; - } - - case NR_UE_RRC_MEASUREMENT: - { - nfapi_p7_message_header_t header; - if (nfapi_p7_message_header_unpack((void *)msg_buffer, msg_len, &header, sizeof(header), NULL) < 0) - { - LOG_E(MAC, "Header unpack failed in %s \n", __FUNCTION__); - break; - } - if (header.message_id != NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST) - { - LOG_E(MAC, "%s: Unexpected nfapi message type: %d\n", __FUNCTION__, header.message_id); - break; - } - - nfapi_nr_dl_tti_request_t dl_tti_request; - const bool result = - nfapi_nr_p7_message_unpack((void *)msg_buffer, msg_len, &dl_tti_request, sizeof(nfapi_nr_dl_tti_request_t), NULL); - if (!result) { - LOG_E(RRC, "%s: SSB PDU unpack failed \n", __FUNCTION__); - break; - } - int num_pdus = dl_tti_request.dl_tti_request_body.nPDUs; - if (num_pdus <= 0) - { - LOG_E(RRC, "%s: dl_tti_request number of PDUS <= 0\n", __FUNCTION__); - abort(); - } - for (int i = 0; i < num_pdus; i++) - { - nfapi_nr_dl_tti_request_pdu_t *pdu_list = &dl_tti_request.dl_tti_request_body.dl_tti_pdu_list[i]; - if (pdu_list->PDUType == NFAPI_NR_DL_TTI_SSB_PDU_TYPE) - { - LOG_I(RRC, "Got an NR_UE_RRC_MEASUREMENT. pdulist[%d].ssbRsrp = %d\n", - i, pdu_list->ssb_pdu.ssb_pdu_rel15.ssbRsrp); - } - } - break; - } - - case NR_RRC_CONFIG_COMPLETE_REQ: - { - LOG_I(RRC, "Got an NR_RRC_CONFIG_COMPLETE_REQ. Now make octet string and call below!\n"); - OCTET_STRING_t rrcConfigurationComplete; - memset(&rrcConfigurationComplete, 0, sizeof(rrcConfigurationComplete)); - OCTET_STRING_fromBuf(&rrcConfigurationComplete, - (const char *)msg_buffer, - msg_len); - UE_RRC_INFO *info = &UE_rrc_inst[module_id].Info[eNB_index]; - uint8_t t_id = info->dl_dcch_msg->message.choice.c1.choice. - rrcConnectionReconfiguration.rrc_TransactionIdentifier; - PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_id, - ENB_FLAG_NO, info->rnti, - 0, 0, eNB_index); - rrc_ue_generate_RRCConnectionReconfigurationComplete(&ctxt, ctxt.eNB_index, t_id, &rrcConfigurationComplete); - break; - } - default: - LOG_E(RRC, "No NSA Message Found\n"); - } -} diff --git a/openair2/RRC/LTE/rrc_proto.h b/openair2/RRC/LTE/rrc_proto.h index 38ba42b251..261e6a9960 100644 --- a/openair2/RRC/LTE/rrc_proto.h +++ b/openair2/RRC/LTE/rrc_proto.h @@ -331,12 +331,6 @@ void *rrc_enb_task(void *args_p); \param args_p Pointer on arguments to start the task. */ void *rrc_ue_task(void *args_p); -/**\brief RRC NSA UE task. - \param args_p Pointer on arguments to start the task. */ -void *recv_msgs_from_nr_ue(void *args_p); - -void init_connections_with_nr_ue(void); - void rrc_eNB_process_x2_setup_request(int mod_id, x2ap_setup_req_t *m); void rrc_eNB_process_x2_setup_response(int mod_id, x2ap_setup_resp_t *m); diff --git a/openair2/RRC/NR_UE/L2_interface_ue.h b/openair2/RRC/NR_UE/L2_interface_ue.h index 857c110d9e..7ab320f709 100644 --- a/openair2/RRC/NR_UE/L2_interface_ue.h +++ b/openair2/RRC/NR_UE/L2_interface_ue.h @@ -47,7 +47,6 @@ void nr_mac_rrc_inactivity_timer_ind(const module_id_t mod_id); void nr_mac_rrc_msg3_ind(const module_id_t mod_id, const int rnti, bool prepare_payload); void nr_ue_rrc_timer_trigger(int instance, int frame, int gnb_id); void nr_mac_rrc_ra_ind(const module_id_t mod_id, bool success); -void nsa_sendmsg_to_lte_ue(const void *message, size_t msg_len, Rrc_Msg_Type_t msg_type); void process_msg_rcc_to_mac(nr_mac_rrc_message_t *msg, int instance_id); #endif diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 0544637975..d502ec45d0 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -140,7 +140,6 @@ static void nr_rrc_manage_rlc_bearers(NR_UE_RRC_INST_t *rrc, static void nr_rrc_ue_process_RadioBearerConfig(NR_UE_RRC_INST_t *ue_rrc, NR_RadioBearerConfig_t *const radioBearerConfig); static void nr_rrc_ue_generate_rrcReestablishmentComplete(const NR_UE_RRC_INST_t *rrc, const NR_RRCReestablishment_t *rrcReestablishment); -static void process_lte_nsa_msg(NR_UE_RRC_INST_t *rrc, nsa_msg_t *msg, int msg_len); 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, @@ -2713,10 +2712,6 @@ static void nr_rrc_ue_process_ueCapabilityEnquiry(NR_UE_RRC_INST_t *rrc, NR_UECa ue_CapabilityRAT_Container->rat_Type = NR_RAT_Type_nr; OCTET_STRING_fromBuf(&ue_CapabilityRAT_Container->ue_CapabilityRAT_Container, (const char *)rrc->UECap.sdu, rrc->UECap.sdu_size); NR_UECapabilityEnquiry_IEs_t *ueCapabilityEnquiry_ie = UECapabilityEnquiry->criticalExtensions.choice.ueCapabilityEnquiry; - if (get_softmodem_params()->nsa == 1) { - OCTET_STRING_t *requestedFreqBandsNR = ueCapabilityEnquiry_ie->ue_CapabilityEnquiryExt; - nsa_sendmsg_to_lte_ue(requestedFreqBandsNR->buf, requestedFreqBandsNR->size, UE_CAPABILITY_INFO); - } // ue_CapabilityRAT_Container.ueCapabilityRAT_Container.buf = UE_rrc_inst[ue_mod_idP].UECapability; // ue_CapabilityRAT_Container.ueCapabilityRAT_Container.size = UE_rrc_inst[ue_mod_idP].UECapability_size; AssertFatal(UECapabilityEnquiry->criticalExtensions.present == NR_UECapabilityEnquiry__criticalExtensions_PR_ueCapabilityEnquiry, @@ -2799,183 +2794,6 @@ static void nr_rrc_ue_generate_rrcReestablishmentComplete(const NR_UE_RRC_INST_t nr_pdcp_data_req_srb(rrc->ue_id, srb_id, 0, size, buffer, deliver_pdu_srb_rlc, NULL); } -void *recv_msgs_from_lte_ue(void *args_p) -{ - itti_mark_task_ready (TASK_RRC_NSA_NRUE); - int from_lte_ue_fd = get_from_lte_ue_fd(); - for (;;) { - nsa_msg_t msg; - int recvLen = recvfrom(from_lte_ue_fd, &msg, sizeof(msg), MSG_WAITALL | MSG_TRUNC, NULL, NULL); - if (recvLen == -1) { - LOG_E(NR_RRC, "%s: recvfrom: %s\n", __func__, strerror(errno)); - continue; - } - if (recvLen > sizeof(msg)) { - LOG_E(NR_RRC, "%s: Received truncated message %d\n", __func__, recvLen); - continue; - } - process_lte_nsa_msg(get_NR_UE_rrc_inst(0), &msg, recvLen); - } - return NULL; -} - -static void nsa_rrc_ue_process_ueCapabilityEnquiry(NR_UE_RRC_INST_t *rrc) -{ - NR_UE_NR_Capability_t *UE_Capability_nr = rrc->UECap.UE_NR_Capability = CALLOC(1, sizeof(NR_UE_NR_Capability_t)); - NR_BandNR_t *nr_bandnr = CALLOC(1, sizeof(NR_BandNR_t)); - nr_bandnr->bandNR = 78; - asn1cSeqAdd(&UE_Capability_nr->rf_Parameters.supportedBandListNR.list, nr_bandnr); - OAI_NR_UECapability_t *UECap = CALLOC(1, sizeof(OAI_NR_UECapability_t)); - UECap->UE_NR_Capability = UE_Capability_nr; - - asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_UE_NR_Capability, - NULL, - (void *)UE_Capability_nr, - &UECap->sdu[0], - MAX_UE_NR_CAPABILITY_SIZE); - AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", - enc_rval.failed_type->name, enc_rval.encoded); - UECap->sdu_size = (enc_rval.encoded + 7) / 8; - LOG_A(NR_RRC, "[NR_RRC] NRUE Capability encoded, %d bytes (%zd bits)\n", - UECap->sdu_size, enc_rval.encoded + 7); - - NR_UE_CapabilityRAT_Container_t ue_CapabilityRAT_Container; - memset(&ue_CapabilityRAT_Container, 0, sizeof(NR_UE_CapabilityRAT_Container_t)); - ue_CapabilityRAT_Container.rat_Type = NR_RAT_Type_nr; - OCTET_STRING_fromBuf(&ue_CapabilityRAT_Container.ue_CapabilityRAT_Container, - (const char *)rrc->UECap.sdu, - rrc->UECap.sdu_size); - - nsa_sendmsg_to_lte_ue(ue_CapabilityRAT_Container.ue_CapabilityRAT_Container.buf, - ue_CapabilityRAT_Container.ue_CapabilityRAT_Container.size, - NRUE_CAPABILITY_INFO); -} - -static void process_lte_nsa_msg(NR_UE_RRC_INST_t *rrc, nsa_msg_t *msg, int msg_len) -{ - if (msg_len < sizeof(msg->msg_type)) { - LOG_E(RRC, "Msg_len = %d\n", msg_len); - return; - } - LOG_D(NR_RRC, "Processing an NSA message\n"); - Rrc_Msg_Type_t msg_type = msg->msg_type; - uint8_t *const msg_buffer = msg->msg_buffer; - msg_len -= sizeof(msg->msg_type); - switch (msg_type) { - case UE_CAPABILITY_ENQUIRY: { - LOG_D(NR_RRC, "We are processing a %d message \n", msg_type); - NR_FreqBandList_t *nr_freq_band_list = NULL; - asn_dec_rval_t dec_rval = uper_decode_complete(NULL, - &asn_DEF_NR_FreqBandList, - (void **)&nr_freq_band_list, - msg_buffer, - msg_len); - if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) { - SEQUENCE_free(&asn_DEF_NR_FreqBandList, nr_freq_band_list, ASFM_FREE_EVERYTHING); - LOG_E(RRC, "Failed to decode UECapabilityInfo (%zu bits)\n", dec_rval.consumed); - break; - } - for (int i = 0; i < nr_freq_band_list->list.count; i++) { - LOG_D(NR_RRC, "Received NR band information: %ld.\n", - nr_freq_band_list->list.array[i]->choice.bandInformationNR->bandNR); - } - int dummy_msg = 0;// whatever piece of data, it will never be used by sendee - LOG_D(NR_RRC, "We are calling nsa_sendmsg_to_lte_ue to send a UE_CAPABILITY_DUMMY\n"); - nsa_sendmsg_to_lte_ue(&dummy_msg, sizeof(dummy_msg), UE_CAPABILITY_DUMMY); - LOG_A(NR_RRC, "Sent initial NRUE Capability response to LTE UE\n"); - break; - } - - case NRUE_CAPABILITY_ENQUIRY: { - LOG_I(NR_RRC, "We are processing a %d message \n", msg_type); - NR_FreqBandList_t *nr_freq_band_list = NULL; - asn_dec_rval_t dec_rval = uper_decode_complete(NULL, - &asn_DEF_NR_FreqBandList, - (void **)&nr_freq_band_list, - msg_buffer, - msg_len); - if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) { - SEQUENCE_free(&asn_DEF_NR_FreqBandList, nr_freq_band_list, ASFM_FREE_EVERYTHING); - LOG_E(NR_RRC, "Failed to decode UECapabilityInfo (%zu bits)\n", dec_rval.consumed); - break; - } - LOG_I(NR_RRC, "Calling nsa_rrc_ue_process_ueCapabilityEnquiry\n"); - nsa_rrc_ue_process_ueCapabilityEnquiry(rrc); - break; - } - - case RRC_MEASUREMENT_PROCEDURE: { - LOG_I(NR_RRC, "We are processing a %d message \n", msg_type); - - LTE_MeasObjectToAddMod_t *nr_meas_obj = NULL; - asn_dec_rval_t dec_rval = uper_decode_complete(NULL, - &asn_DEF_NR_MeasObjectToAddMod, - (void **)&nr_meas_obj, - msg_buffer, - msg_len); - if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) { - SEQUENCE_free(&asn_DEF_NR_MeasObjectToAddMod, nr_meas_obj, ASFM_FREE_EVERYTHING); - LOG_E(RRC, "Failed to decode measurement object (%zu bits) %d\n", dec_rval.consumed, dec_rval.code); - break; - } - LOG_D(NR_RRC, "NR carrierFreq_r15 (ssb): %ld and sub carrier spacing:%ld\n", - nr_meas_obj->measObject.choice.measObjectNR_r15.carrierFreq_r15, - nr_meas_obj->measObject.choice.measObjectNR_r15.rs_ConfigSSB_r15.subcarrierSpacingSSB_r15); - //start_oai_nrue_threads(); - break; - } - - case RRC_CONFIG_COMPLETE_REQ: { - struct msg { - uint32_t RadioBearer_size; - uint32_t SecondaryCellGroup_size; - uint8_t trans_id; - uint8_t padding[3]; - uint8_t buffer[]; - } hdr; - AssertFatal(msg_len >= sizeof(hdr), "Bad received msg\n"); - memcpy(&hdr, msg_buffer, sizeof(hdr)); - LOG_I(NR_RRC, "We got an RRC_CONFIG_COMPLETE_REQ\n"); - uint32_t nr_RadioBearer_size = hdr.RadioBearer_size; - uint32_t nr_SecondaryCellGroup_size = hdr.SecondaryCellGroup_size; - AssertFatal(sizeof(hdr) + nr_RadioBearer_size + nr_SecondaryCellGroup_size <= msg_len, - "nr_RadioBearerConfig1_r15 size %u nr_SecondaryCellGroupConfig_r15 size %u sizeof(hdr) %zu, msg_len = %d\n", - nr_RadioBearer_size, - nr_SecondaryCellGroup_size, - sizeof(hdr), - msg_len); - NR_RRC_TransactionIdentifier_t t_id = hdr.trans_id; - LOG_I(NR_RRC, "nr_RadioBearerConfig1_r15 size %d nr_SecondaryCellGroupConfig_r15 size %d t_id %ld\n", - nr_RadioBearer_size, - nr_SecondaryCellGroup_size, - t_id); - - uint8_t *nr_RadioBearer_buffer = msg_buffer + offsetof(struct msg, buffer); - uint8_t *nr_SecondaryCellGroup_buffer = nr_RadioBearer_buffer + nr_RadioBearer_size; - process_nsa_message(get_NR_UE_rrc_inst(0), nr_SecondaryCellGroupConfig_r15, nr_SecondaryCellGroup_buffer, nr_SecondaryCellGroup_size); - process_nsa_message(get_NR_UE_rrc_inst(0), nr_RadioBearerConfigX_r15, nr_RadioBearer_buffer, nr_RadioBearer_size); - LOG_I(NR_RRC, "Calling do_NR_RRCReconfigurationComplete. t_id %ld \n", t_id); - uint8_t buffer[NR_RRC_BUF_SIZE]; - size_t size = do_NR_RRCReconfigurationComplete_for_nsa(buffer, sizeof(buffer), t_id); - nsa_sendmsg_to_lte_ue(buffer, size, NR_RRC_CONFIG_COMPLETE_REQ); - break; - } - - case OAI_TUN_IFACE_NSA: { - LOG_I(NR_RRC, "We got an OAI_TUN_IFACE_NSA!!\n"); - char cmd_line[NR_RRC_BUF_SIZE]; - memcpy(cmd_line, msg_buffer, sizeof(cmd_line)); - LOG_D(NR_RRC, "Command line: %s\n", cmd_line); - if (background_system(cmd_line) != 0) - LOG_E(NR_RRC, "ESM-PROC - failed command '%s'", cmd_line); - break; - } - - default: - LOG_E(NR_RRC, "No NSA Message Found\n"); - } -} - void handle_RRCRelease(NR_UE_RRC_INST_t *rrc) { NR_UE_Timers_Constants_t *tac = &rrc->timers_and_constants; diff --git a/openair2/RRC/NR_UE/rrc_nsa.c b/openair2/RRC/NR_UE/rrc_nsa.c deleted file mode 100644 index 279e920779..0000000000 --- a/openair2/RRC/NR_UE/rrc_nsa.c +++ /dev/null @@ -1,85 +0,0 @@ -#include -#include -#include -#include "common/utils/LOG/log.h" -#include "openair2/RRC/NR_UE/rrc_proto.h" - -static const char nsa_ipaddr[] = "127.0.0.1"; -static int from_lte_ue_fd = -1; -static int to_lte_ue_fd = -1; -uint16_t ue_id_g; - -int get_from_lte_ue_fd() -{ - return from_lte_ue_fd; -} - -void nsa_sendmsg_to_lte_ue(const void *message, size_t msg_len, Rrc_Msg_Type_t msg_type) -{ - LOG_I(NR_RRC, "Entered %s \n", __FUNCTION__); - nsa_msg_t n_msg; - if (msg_len > sizeof(n_msg.msg_buffer)) - { - LOG_E(NR_RRC, "%s: message too big: %zu\n", __func__, msg_len); - abort(); - } - n_msg.msg_type = msg_type; - memcpy(n_msg.msg_buffer, message, msg_len); - size_t to_send = sizeof(n_msg.msg_type) + msg_len; - - struct sockaddr_in sa = - { - .sin_family = AF_INET, - .sin_port = htons(6007 + ue_id_g * 2), - }; - int sent = sendto(from_lte_ue_fd, &n_msg, to_send, 0, - (struct sockaddr *)&sa, sizeof(sa)); - if (sent == -1) - { - LOG_E(NR_RRC, "%s: sendto: %s\n", __func__, strerror(errno)); - return; - } - if (sent != to_send) - { - LOG_E(NR_RRC, "%s: Short send %d != %zu\n", __func__, sent, to_send); - return; - } - LOG_D(NR_RRC, "Sent a %d message to the LTE UE (%d bytes) \n", msg_type, sent); -} - -void init_connections_with_lte_ue(void) -{ - struct sockaddr_in sa = - { - .sin_family = AF_INET, - .sin_port = htons(6008 + ue_id_g * 2), - }; - AssertFatal(from_lte_ue_fd == -1, "from_lte_ue_fd %d was assigned already", from_lte_ue_fd); - from_lte_ue_fd = socket(AF_INET, SOCK_DGRAM, 0); - if (from_lte_ue_fd == -1) - { - LOG_E(NR_RRC, "%s: Error opening socket %d (%d:%s)\n", __FUNCTION__, from_lte_ue_fd, errno, strerror(errno)); - abort(); - } - - if (inet_aton(nsa_ipaddr, &sa.sin_addr) == 0) - { - LOG_E(NR_RRC, "Bad nsa_ipaddr '%s'\n", nsa_ipaddr); - abort(); - } - - if (bind(from_lte_ue_fd, (struct sockaddr *) &sa, sizeof(sa)) == -1) - { - LOG_E(NR_RRC,"%s: Failed to bind the socket\n", __FUNCTION__); - abort(); - } - - AssertFatal(to_lte_ue_fd == -1, "to_lte_ue_fd was assigned already"); - to_lte_ue_fd = socket(AF_INET, SOCK_DGRAM, 0); - if (to_lte_ue_fd == -1) - { - LOG_E(NR_RRC, "%s: Error opening socket %d (%d:%s)\n", __FUNCTION__, to_lte_ue_fd, errno, strerror(errno)); - abort(); - } - LOG_I(NR_RRC, "Started LTE-NR link in the nr-UE\n"); -} diff --git a/openair2/RRC/NR_UE/rrc_proto.h b/openair2/RRC/NR_UE/rrc_proto.h index cdcf1966b4..1ebb728884 100644 --- a/openair2/RRC/NR_UE/rrc_proto.h +++ b/openair2/RRC/NR_UE/rrc_proto.h @@ -68,12 +68,6 @@ void nr_rrc_handle_timers(NR_UE_RRC_INST_t *rrc); void handle_rlf_detection(NR_UE_RRC_INST_t *rrc); void handle_302_expired_stopped(NR_UE_RRC_INST_t *rrc); -/**\brief RRC NSA UE task. - \param void *args_p Pointer on arguments to start the task. */ -void *recv_msgs_from_lte_ue(void *args_p); - -void init_connections_with_lte_ue(void); - int get_from_lte_ue_fd(); void nr_rrc_SI_timers(NR_UE_RRC_SI_INFO *SInfo); diff --git a/openair3/NAS/NR_UE/nr_nas_msg.c b/openair3/NAS/NR_UE/nr_nas_msg.c index cf8b5dd0d6..d0230e0a03 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg.c +++ b/openair3/NAS/NR_UE/nr_nas_msg.c @@ -2160,7 +2160,7 @@ void *nas_nrue(void *args_p) case NAS_INIT_NOS1_IF: { const int pdu_session_id = get_softmodem_params()->default_pdu_session_id; - const char *ip = !get_softmodem_params()->nsa ? "10.0.1.2" : "10.0.1.3"; + const char *ip = "10.0.1.2"; const int qfi = 7; create_ue_ip_if(ip, NULL, nas->UE_id, pdu_session_id); set_qfi(qfi, pdu_session_id, nas->UE_id); From 8910406a9ea0cf2567686d83c3e2495b3e84193d Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Wed, 8 Oct 2025 19:44:35 +0200 Subject: [PATCH 909/964] Add support for including custom timing threshold files in physim tests Introduce a new CMake variable PHYSIM_CHECK_FILES to specify CMake files (semicolon-separated) containing timing thresholds for timed physim tests. --- ci-scripts/xml_files/gnb_usrp_build.xml | 2 +- openair1/SIMULATION/tests/CMakeLists.txt | 21 ++++++++++++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/ci-scripts/xml_files/gnb_usrp_build.xml b/ci-scripts/xml_files/gnb_usrp_build.xml index 42d567cd15..32043985f5 100644 --- a/ci-scripts/xml_files/gnb_usrp_build.xml +++ b/ci-scripts/xml_files/gnb_usrp_build.xml @@ -42,7 +42,7 @@ Build_eNB Build gNB (USRP) caracal - --gNB -w USRP --ninja -c -P --build-lib ldpc_cuda --build-lib ldpc_aal --cmake-opt -DASN1C_EXEC=/opt/asn1c/bin/asn1c + --gNB -w USRP --ninja -c -P --build-lib ldpc_cuda --build-lib ldpc_aal --cmake-opt -DASN1C_EXEC=/opt/asn1c/bin/asn1c --cmake-opt -DPHYSIM_CHECK_FILES="ThresholdsOffload.cmake" diff --git a/openair1/SIMULATION/tests/CMakeLists.txt b/openair1/SIMULATION/tests/CMakeLists.txt index 443db31c95..1a090c566a 100644 --- a/openair1/SIMULATION/tests/CMakeLists.txt +++ b/openair1/SIMULATION/tests/CMakeLists.txt @@ -1,3 +1,18 @@ +# This defines a cmake file with timing thresholds to include (empty by default) +set(PHYSIM_CHECK_FILES "" CACHE STRING "CMake files ('\;' separated) with timing thresholds to include for timed physim tests") + +if(PHYSIM_CHECK_FILES) + foreach(PHYSIM_CHECK_FILE IN LISTS PHYSIM_CHECK_FILES) + # Construct full path relative to current source dir + set(CHECK_FILE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/${PHYSIM_CHECK_FILE}") + if(EXISTS "${CHECK_FILE_PATH}") + message(STATUS "Including file for physim timing threshold check: ${PHYSIM_CHECK_FILE}") + else() + message(FATAL_ERROR "Threshold file '${PHYSIM_CHECK_FILE}' not found at ${CHECK_FILE_PATH}") + endif() + endforeach() +endif() + define_property(TEST PROPERTY TEST_DESCRIPTION BRIEF_DOCS "A human-readable description of this test" FULL_DOCS "A human-readable description of this test") @@ -398,6 +413,10 @@ add_timed_physim_test(physim.5g-offload.nr_ulsim.testT2.8 "T2 LDPC offload: SNR add_timed_physim_test(physim.5g-offload.nr_ulsim.testCPU.9 "CPU: SNR = 30, MCS = 25, 273 PRBs, 2 layers" nr_ulsim -n1000 -s30 -S30.2 -m25 -r273 -R273 -C10 -W2 -z2 -y2 -P) add_timed_physim_test(physim.5g-offload.nr_ulsim.testT2.9 "T2 LDPC offload: SNR = 30, MCS = 25, 273 PRBs, 2 layers" nr_ulsim -n1000 -s30 -S30.2 -m25 -r273 -R273 -C10 -W2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) -include(ThresholdsOffload.cmake) +endif() +if(PHYSIM_CHECK_FILES) + foreach(PHYSIM_CHECK_FILE IN LISTS PHYSIM_CHECK_FILES) + include("${CMAKE_CURRENT_SOURCE_DIR}/${PHYSIM_CHECK_FILE}") + endforeach() endif() From ec8efe1b7efe67b328d34874b9806d9d03260a08 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Wed, 8 Oct 2025 11:22:17 +0200 Subject: [PATCH 910/964] Unify physim test definition Replace the previous add_timed_physim_test() macro with add_physim_test() to use a single, unified function for defining physim tests. This simplifies the test configuration and removes redundant macro definitions while keeping all existing functionality. This change follows up on the earlier addition of support for including custom timing threshold files (PHYSIM_CHECK_FILES). Update existing tests accordingly. --- openair1/SIMULATION/tests/CMakeLists.txt | 110 +++++++++-------------- 1 file changed, 44 insertions(+), 66 deletions(-) diff --git a/openair1/SIMULATION/tests/CMakeLists.txt b/openair1/SIMULATION/tests/CMakeLists.txt index 1a090c566a..566028234d 100644 --- a/openair1/SIMULATION/tests/CMakeLists.txt +++ b/openair1/SIMULATION/tests/CMakeLists.txt @@ -17,33 +17,11 @@ define_property(TEST PROPERTY TEST_DESCRIPTION BRIEF_DOCS "A human-readable description of this test" FULL_DOCS "A human-readable description of this test") -# Define a macro to add tests for different physical simulators -macro(add_physim_test test_name test_description test_exec) - # catch all the arguments past the last expected arqument and store them in the options_list - if (NOT TARGET ${test_exec}) - message(FATAL_ERROR "test executable ${test_exec} is not an executable") - endif() - set(options_list ${ARGN}) - add_test( - NAME ${test_name} - COMMAND ${test_exec} ${options_list} - COMMAND_EXPAND_LISTS - ) - set_tests_properties(${test_name} PROPERTIES - LABELS "${test_exec}" - TEST_DESCRIPTION "${test_description}" - # pass test description also through environment variable: for cmake < 3.30, - # in JSON export, we cannot recover the description otherwise - # see also https://gitlab.kitware.com/cmake/cmake/-/issues/21490 - ENVIRONMENT "LD_LIBRARY_PATH=.;TEST_DESCRIPTION=${test_description}" - ) - add_dependencies(tests ${test_exec}) -endmacro() - define_property(TEST PROPERTY CHECK_COUNT BRIEF_DOCS "helper property to enumerate checks in environment" FULL_DOCS "the property counts the number of threshold checks, used to enumerate environment variables given to analyze-timing.sh") -function(add_timed_physim_test test_name test_description test_exec) + +function(add_physim_test test_name test_description test_exec) # catch all the arguments past the last expected arqument and store them in the options_list if (NOT TARGET ${test_exec}) message(FATAL_ERROR "test executable ${test_exec} is not an executable") @@ -369,49 +347,49 @@ add_physim_test(physim.5g.nr_psbchsim.test2 "PSBCH TxRx" nr_psbchsim -n 30) if (ENABLE_LDPC_AAL) -add_timed_physim_test(physim.5g-offload.nr_dlsim.testCPU.1 "CPU: SNR = 30, MCS = 5, 106 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e5 -b106 -R106 -X 8,9,10,11,12 -P) -add_timed_physim_test(physim.5g-offload.nr_dlsim.testT2.1 "T2 LDPC offload: SNR = 30, MCS = 5, 106 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e5 -b106 -R106 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) -add_timed_physim_test(physim.5g-offload.nr_dlsim.testCPU.2 "CPU: SNR = 30, MCS = 15, 106 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e15 -b106 -R106 -X 8,9,10,11,12 -P) -add_timed_physim_test(physim.5g-offload.nr_dlsim.testT2.2 "T2 LDPC offload: SNR = 30, MCS = 15, 106 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e15 -b106 -R106 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) -add_timed_physim_test(physim.5g-offload.nr_dlsim.testCPU.3 "CPU: SNR = 30, MCS = 25, 106 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e25 -b106 -R106 -X 8,9,10,11,12 -P) -add_timed_physim_test(physim.5g-offload.nr_dlsim.testT2.3 "T2 LDPC offload: SNR = 30, MCS = 25, 106 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e25 -b106 -R106 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) -add_timed_physim_test(physim.5g-offload.nr_dlsim.testCPU.4 "CPU: SNR = 30, MCS = 5, 273 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e5 -b273 -R273 -X 8,9,10,11,12 -P) -add_timed_physim_test(physim.5g-offload.nr_dlsim.testT2.4 "T2 LDPC offload: SNR = 30, MCS = 5, 273 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e5 -b273 -R273 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) -add_timed_physim_test(physim.5g-offload.nr_dlsim.testCPU.5 "CPU: SNR = 30, MCS = 15, 273 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e15 -b273 -R273 -X 8,9,10,11,12 -P) -add_timed_physim_test(physim.5g-offload.nr_dlsim.testT2.5 "T2 LDPC offload: SNR = 30, MCS = 15, 273 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e15 -b273 -R273 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) -add_timed_physim_test(physim.5g-offload.nr_dlsim.testCPU.6 "CPU: SNR = 30, MCS = 25, 273 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e25 -b273 -R273 -X 8,9,10,11,12 -P) -add_timed_physim_test(physim.5g-offload.nr_dlsim.testT2.6 "T2 LDPC offload: SNR = 30, MCS = 25, 273 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e25 -b273 -R273 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) -add_timed_physim_test(physim.5g-offload.nr_dlsim.testCPU.7 "CPU: SNR = 30, MCS = 5, 273 PRBs, 2 layers" nr_dlsim -n1000 -s30 -S30.2 -e5 -b273 -R273 -X 8,9,10,11,12 -x2 -z2 -y2 -P) -add_timed_physim_test(physim.5g-offload.nr_dlsim.testT2.7 "T2 LDPC offload: SNR = 30, MCS = 5, 273 PRBs, 2 layers" nr_dlsim -n1000 -s30 -S30.2 -e5 -b273 -R273 -X4,5,6,7,8,9 -x2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) -add_timed_physim_test(physim.5g-offload.nr_dlsim.testCPU.8 "CPU: SNR = 30, MCS = 15, 273 PRBs, 2 layers" nr_dlsim -n1000 -s30 -S30.2 -e15 -b273 -R273 -X 8,9,10,11,12 -x2 -z2 -y2 -P) -add_timed_physim_test(physim.5g-offload.nr_dlsim.testT2.8 "T2 LDPC offload: SNR = 30, MCS = 15, 273 PRBs, 2 layers" nr_dlsim -n1000 -s30 -S30.2 -e15 -b273 -R273 -X4,5,6,7,8,9 -x2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) -add_timed_physim_test(physim.5g-offload.nr_dlsim.testCPU.9 "CPU: SNR = 30, MCS = 25, 273 PRBs, 2 layers" nr_dlsim -n1000 -s30 -S30.2 -e25 -b273 -R273 -X 8,9,10,11,12 -x2 -z2 -y2 -P) -add_timed_physim_test(physim.5g-offload.nr_dlsim.testT2.9 "T2 LDPC offload: SNR = 30, MCS = 25, 273 PRBs, 2 layers" nr_dlsim -n1000 -s30 -S30.2 -e25 -b273 -R273 -X4,5,6,7,8,9 -x2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) -add_timed_physim_test(physim.5g-offload.nr_dlsim.testCPU.10 "CPU: SNR = 30, MCS = 5, 273 PRBs, 2 layers, 4 antennas" nr_dlsim -n1000 -s30 -S30.2 -e5 -b273 -R273 -X8,9,10,11,12 -x2 -z4 -y4 -P) -add_timed_physim_test(physim.5g-offload.nr_dlsim.testT2.10 "T2 LDPC offload: SNR = 30, MCS = 5, 273 PRBs, 2 layers, 4 antennas" nr_dlsim -n1000 -s30 -S30.2 -e5 -b273 -R273 -X4,5,6,7,8,9 -x2 -z4 -y4 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) -add_timed_physim_test(physim.5g-offload.nr_dlsim.testCPU.11 "CPU: SNR = 30, MCS = 20, 273 PRBs, 2 layers, 4 antennas" nr_dlsim -n1000 -s30 -S30.2 -e15 -b273 -R273 -X8,9,10,11,12 -x2 -z4 -y4 -P) -add_timed_physim_test(physim.5g-offload.nr_dlsim.testT2.11 "T2 LDPC offload: SNR = 30, MCS = 20, 273 PRBs, 2 layers, 4 antennas" nr_dlsim -n1000 -s30 -S30.2 -e15 -b273 -R273 -X4,5,6,7,8,9 -x2 -z4 -y4 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) -add_timed_physim_test(physim.5g-offload.nr_dlsim.testCPU.12 "CPU: SNR = 30, MCS = 27, 273 PRBs, 2 layers, 4 antennas" nr_dlsim -n1000 -s30 -S30.2 -e25 -b273 -R273 -X8,9,10,11,12 -x2 -z4 -y4 -P) -add_timed_physim_test(physim.5g-offload.nr_dlsim.testT2.12 "T2 LDPC offload: SNR = 30, MCS = 27, 273 PRBs, 2 layers, 4 antennas" nr_dlsim -n1000 -s30 -S30.2 -e25 -b273 -R273 -X4,5,6,7,8,9 -x2 -z4 -y4 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_physim_test(physim.5g-offload.nr_dlsim.testCPU.1 "CPU: SNR = 30, MCS = 5, 106 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e5 -b106 -R106 -X 8,9,10,11,12 -P) +add_physim_test(physim.5g-offload.nr_dlsim.testT2.1 "T2 LDPC offload: SNR = 30, MCS = 5, 106 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e5 -b106 -R106 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_physim_test(physim.5g-offload.nr_dlsim.testCPU.2 "CPU: SNR = 30, MCS = 15, 106 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e15 -b106 -R106 -X 8,9,10,11,12 -P) +add_physim_test(physim.5g-offload.nr_dlsim.testT2.2 "T2 LDPC offload: SNR = 30, MCS = 15, 106 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e15 -b106 -R106 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_physim_test(physim.5g-offload.nr_dlsim.testCPU.3 "CPU: SNR = 30, MCS = 25, 106 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e25 -b106 -R106 -X 8,9,10,11,12 -P) +add_physim_test(physim.5g-offload.nr_dlsim.testT2.3 "T2 LDPC offload: SNR = 30, MCS = 25, 106 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e25 -b106 -R106 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_physim_test(physim.5g-offload.nr_dlsim.testCPU.4 "CPU: SNR = 30, MCS = 5, 273 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e5 -b273 -R273 -X 8,9,10,11,12 -P) +add_physim_test(physim.5g-offload.nr_dlsim.testT2.4 "T2 LDPC offload: SNR = 30, MCS = 5, 273 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e5 -b273 -R273 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_physim_test(physim.5g-offload.nr_dlsim.testCPU.5 "CPU: SNR = 30, MCS = 15, 273 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e15 -b273 -R273 -X 8,9,10,11,12 -P) +add_physim_test(physim.5g-offload.nr_dlsim.testT2.5 "T2 LDPC offload: SNR = 30, MCS = 15, 273 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e15 -b273 -R273 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_physim_test(physim.5g-offload.nr_dlsim.testCPU.6 "CPU: SNR = 30, MCS = 25, 273 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e25 -b273 -R273 -X 8,9,10,11,12 -P) +add_physim_test(physim.5g-offload.nr_dlsim.testT2.6 "T2 LDPC offload: SNR = 30, MCS = 25, 273 PRBs, 1 layer" nr_dlsim -n1000 -s30 -S30.2 -e25 -b273 -R273 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_physim_test(physim.5g-offload.nr_dlsim.testCPU.7 "CPU: SNR = 30, MCS = 5, 273 PRBs, 2 layers" nr_dlsim -n1000 -s30 -S30.2 -e5 -b273 -R273 -X 8,9,10,11,12 -x2 -z2 -y2 -P) +add_physim_test(physim.5g-offload.nr_dlsim.testT2.7 "T2 LDPC offload: SNR = 30, MCS = 5, 273 PRBs, 2 layers" nr_dlsim -n1000 -s30 -S30.2 -e5 -b273 -R273 -X4,5,6,7,8,9 -x2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_physim_test(physim.5g-offload.nr_dlsim.testCPU.8 "CPU: SNR = 30, MCS = 15, 273 PRBs, 2 layers" nr_dlsim -n1000 -s30 -S30.2 -e15 -b273 -R273 -X 8,9,10,11,12 -x2 -z2 -y2 -P) +add_physim_test(physim.5g-offload.nr_dlsim.testT2.8 "T2 LDPC offload: SNR = 30, MCS = 15, 273 PRBs, 2 layers" nr_dlsim -n1000 -s30 -S30.2 -e15 -b273 -R273 -X4,5,6,7,8,9 -x2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_physim_test(physim.5g-offload.nr_dlsim.testCPU.9 "CPU: SNR = 30, MCS = 25, 273 PRBs, 2 layers" nr_dlsim -n1000 -s30 -S30.2 -e25 -b273 -R273 -X 8,9,10,11,12 -x2 -z2 -y2 -P) +add_physim_test(physim.5g-offload.nr_dlsim.testT2.9 "T2 LDPC offload: SNR = 30, MCS = 25, 273 PRBs, 2 layers" nr_dlsim -n1000 -s30 -S30.2 -e25 -b273 -R273 -X4,5,6,7,8,9 -x2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_physim_test(physim.5g-offload.nr_dlsim.testCPU.10 "CPU: SNR = 30, MCS = 5, 273 PRBs, 2 layers, 4 antennas" nr_dlsim -n1000 -s30 -S30.2 -e5 -b273 -R273 -X8,9,10,11,12 -x2 -z4 -y4 -P) +add_physim_test(physim.5g-offload.nr_dlsim.testT2.10 "T2 LDPC offload: SNR = 30, MCS = 5, 273 PRBs, 2 layers, 4 antennas" nr_dlsim -n1000 -s30 -S30.2 -e5 -b273 -R273 -X4,5,6,7,8,9 -x2 -z4 -y4 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_physim_test(physim.5g-offload.nr_dlsim.testCPU.11 "CPU: SNR = 30, MCS = 20, 273 PRBs, 2 layers, 4 antennas" nr_dlsim -n1000 -s30 -S30.2 -e15 -b273 -R273 -X8,9,10,11,12 -x2 -z4 -y4 -P) +add_physim_test(physim.5g-offload.nr_dlsim.testT2.11 "T2 LDPC offload: SNR = 30, MCS = 20, 273 PRBs, 2 layers, 4 antennas" nr_dlsim -n1000 -s30 -S30.2 -e15 -b273 -R273 -X4,5,6,7,8,9 -x2 -z4 -y4 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_physim_test(physim.5g-offload.nr_dlsim.testCPU.12 "CPU: SNR = 30, MCS = 27, 273 PRBs, 2 layers, 4 antennas" nr_dlsim -n1000 -s30 -S30.2 -e25 -b273 -R273 -X8,9,10,11,12 -x2 -z4 -y4 -P) +add_physim_test(physim.5g-offload.nr_dlsim.testT2.12 "T2 LDPC offload: SNR = 30, MCS = 27, 273 PRBs, 2 layers, 4 antennas" nr_dlsim -n1000 -s30 -S30.2 -e25 -b273 -R273 -X4,5,6,7,8,9 -x2 -z4 -y4 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) -add_timed_physim_test(physim.5g-offload.nr_ulsim.testCPU.1 "CPU: SNR = 30, MCS = 5, 106 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m5 -r106 -R106 -C10 -P) -add_timed_physim_test(physim.5g-offload.nr_ulsim.testT2.1 "T2 LDPC offload: SNR = 30, MCS = 5, 106 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m5 -r106 -R106 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) -add_timed_physim_test(physim.5g-offload.nr_ulsim.testCPU.2 "CPU: SNR = 30, MCS = 15, 106 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m15 -r106 -R106 -C10 -P) -add_timed_physim_test(physim.5g-offload.nr_ulsim.testT2.2 "T2 LDPC offload: SNR = 30, MCS = 15, 106 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m15 -r106 -R106 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) -add_timed_physim_test(physim.5g-offload.nr_ulsim.testCPU.3 "CPU: SNR = 30, MCS = 25, 106 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m25 -r106 -R106 -C10 -P) -add_timed_physim_test(physim.5g-offload.nr_ulsim.testT2.3 "T2 LDPC offload: SNR = 30, MCS = 25, 106 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m25 -r106 -R106 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) -add_timed_physim_test(physim.5g-offload.nr_ulsim.testCPU.4 "CPU: SNR = 30, MCS = 5, 273 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m5 -r273 -R273 -C10 -P) -add_timed_physim_test(physim.5g-offload.nr_ulsim.testT2.4 "T2 LDPC offload: SNR = 30, MCS = 5, 273 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m5 -r273 -R273 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) -add_timed_physim_test(physim.5g-offload.nr_ulsim.testCPU.5 "CPU: SNR = 30, MCS = 15, 273 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m15 -r273 -R273 -C10 -P) -add_timed_physim_test(physim.5g-offload.nr_ulsim.testT2.5 "T2 LDPC offload: SNR = 30, MCS = 15, 273 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m15 -r273 -R273 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) -add_timed_physim_test(physim.5g-offload.nr_ulsim.testCPU.6 "CPU: SNR = 30, MCS = 25, 273 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m25 -r273 -R273 -C10 -P) -add_timed_physim_test(physim.5g-offload.nr_ulsim.testT2.6 "T2 LDPC offload: SNR = 30, MCS = 25, 273 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m25 -r273 -R273 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) -add_timed_physim_test(physim.5g-offload.nr_ulsim.testCPU.7 "CPU: SNR = 30, MCS = 5, 273 PRBs, 2 layers" nr_ulsim -n1000 -s30 -S30.2 -m5 -r273 -R273 -C10 -W2 -z2 -y2 -P) -add_timed_physim_test(physim.5g-offload.nr_ulsim.testT2.7 "T2 LDPC offload: SNR = 30, MCS = 5, 273 PRBs, 2 layers" nr_ulsim -n1000 -s30 -S30.2 -m5 -r273 -R273 -C10 -W2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) -add_timed_physim_test(physim.5g-offload.nr_ulsim.testCPU.8 "CPU: SNR = 30, MCS = 15, 273 PRBs, 2 layers" nr_ulsim -n1000 -s30 -S30.2 -m15 -r273 -R273 -C10 -W2 -z2 -y2 -P) -add_timed_physim_test(physim.5g-offload.nr_ulsim.testT2.8 "T2 LDPC offload: SNR = 30, MCS = 15, 273 PRBs, 2 layers" nr_ulsim -n1000 -s30 -S30.2 -m15 -r273 -R273 -C10 -W2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) -add_timed_physim_test(physim.5g-offload.nr_ulsim.testCPU.9 "CPU: SNR = 30, MCS = 25, 273 PRBs, 2 layers" nr_ulsim -n1000 -s30 -S30.2 -m25 -r273 -R273 -C10 -W2 -z2 -y2 -P) -add_timed_physim_test(physim.5g-offload.nr_ulsim.testT2.9 "T2 LDPC offload: SNR = 30, MCS = 25, 273 PRBs, 2 layers" nr_ulsim -n1000 -s30 -S30.2 -m25 -r273 -R273 -C10 -W2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_physim_test(physim.5g-offload.nr_ulsim.testCPU.1 "CPU: SNR = 30, MCS = 5, 106 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m5 -r106 -R106 -C10 -P) +add_physim_test(physim.5g-offload.nr_ulsim.testT2.1 "T2 LDPC offload: SNR = 30, MCS = 5, 106 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m5 -r106 -R106 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_physim_test(physim.5g-offload.nr_ulsim.testCPU.2 "CPU: SNR = 30, MCS = 15, 106 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m15 -r106 -R106 -C10 -P) +add_physim_test(physim.5g-offload.nr_ulsim.testT2.2 "T2 LDPC offload: SNR = 30, MCS = 15, 106 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m15 -r106 -R106 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_physim_test(physim.5g-offload.nr_ulsim.testCPU.3 "CPU: SNR = 30, MCS = 25, 106 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m25 -r106 -R106 -C10 -P) +add_physim_test(physim.5g-offload.nr_ulsim.testT2.3 "T2 LDPC offload: SNR = 30, MCS = 25, 106 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m25 -r106 -R106 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_physim_test(physim.5g-offload.nr_ulsim.testCPU.4 "CPU: SNR = 30, MCS = 5, 273 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m5 -r273 -R273 -C10 -P) +add_physim_test(physim.5g-offload.nr_ulsim.testT2.4 "T2 LDPC offload: SNR = 30, MCS = 5, 273 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m5 -r273 -R273 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_physim_test(physim.5g-offload.nr_ulsim.testCPU.5 "CPU: SNR = 30, MCS = 15, 273 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m15 -r273 -R273 -C10 -P) +add_physim_test(physim.5g-offload.nr_ulsim.testT2.5 "T2 LDPC offload: SNR = 30, MCS = 15, 273 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m15 -r273 -R273 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_physim_test(physim.5g-offload.nr_ulsim.testCPU.6 "CPU: SNR = 30, MCS = 25, 273 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m25 -r273 -R273 -C10 -P) +add_physim_test(physim.5g-offload.nr_ulsim.testT2.6 "T2 LDPC offload: SNR = 30, MCS = 25, 273 PRBs, 1 layer" nr_ulsim -n1000 -s30 -S30.2 -m25 -r273 -R273 -C10 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_physim_test(physim.5g-offload.nr_ulsim.testCPU.7 "CPU: SNR = 30, MCS = 5, 273 PRBs, 2 layers" nr_ulsim -n1000 -s30 -S30.2 -m5 -r273 -R273 -C10 -W2 -z2 -y2 -P) +add_physim_test(physim.5g-offload.nr_ulsim.testT2.7 "T2 LDPC offload: SNR = 30, MCS = 5, 273 PRBs, 2 layers" nr_ulsim -n1000 -s30 -S30.2 -m5 -r273 -R273 -C10 -W2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_physim_test(physim.5g-offload.nr_ulsim.testCPU.8 "CPU: SNR = 30, MCS = 15, 273 PRBs, 2 layers" nr_ulsim -n1000 -s30 -S30.2 -m15 -r273 -R273 -C10 -W2 -z2 -y2 -P) +add_physim_test(physim.5g-offload.nr_ulsim.testT2.8 "T2 LDPC offload: SNR = 30, MCS = 15, 273 PRBs, 2 layers" nr_ulsim -n1000 -s30 -S30.2 -m15 -r273 -R273 -C10 -W2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) +add_physim_test(physim.5g-offload.nr_ulsim.testCPU.9 "CPU: SNR = 30, MCS = 25, 273 PRBs, 2 layers" nr_ulsim -n1000 -s30 -S30.2 -m25 -r273 -R273 -C10 -W2 -z2 -y2 -P) +add_physim_test(physim.5g-offload.nr_ulsim.testT2.9 "T2 LDPC offload: SNR = 30, MCS = 25, 273 PRBs, 2 layers" nr_ulsim -n1000 -s30 -S30.2 -m25 -r273 -R273 -C10 -W2 -z2 -y2 -P --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev af:00.0 --nrLDPC_coding_aal.dpdk_core_list 11-12 --nrLDPC_coding_aal.is_t2 1) endif() From 31af716ccb4ee9ef8257f4fbc657881fea7090c9 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Wed, 8 Oct 2025 11:31:48 +0200 Subject: [PATCH 911/964] Update timing thershold for offload tests on Caracal --- .../SIMULATION/tests/ThresholdsOffload.cmake | 84 +++++++++---------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/openair1/SIMULATION/tests/ThresholdsOffload.cmake b/openair1/SIMULATION/tests/ThresholdsOffload.cmake index 72b2ee2569..9f787f993a 100644 --- a/openair1/SIMULATION/tests/ThresholdsOffload.cmake +++ b/openair1/SIMULATION/tests/ThresholdsOffload.cmake @@ -1,43 +1,43 @@ -check_threshold(physim.5g-offload.nr_dlsim.testCPU.1 "DLSCH encoding time" "< 230") -check_threshold(physim.5g-offload.nr_dlsim.testT2.1 "DLSCH encoding time" "< 100") -check_threshold(physim.5g-offload.nr_dlsim.testCPU.2 "DLSCH encoding time" "< 300") -check_threshold(physim.5g-offload.nr_dlsim.testT2.2 "DLSCH encoding time" "< 100") -check_threshold(physim.5g-offload.nr_dlsim.testCPU.3 "DLSCH encoding time" "< 350") -check_threshold(physim.5g-offload.nr_dlsim.testT2.3 "DLSCH encoding time" "< 200") -check_threshold(physim.5g-offload.nr_dlsim.testCPU.4 "DLSCH encoding time" "< 300") -check_threshold(physim.5g-offload.nr_dlsim.testT2.4 "DLSCH encoding time" "< 150") -check_threshold(physim.5g-offload.nr_dlsim.testCPU.5 "DLSCH encoding time" "< 350") -check_threshold(physim.5g-offload.nr_dlsim.testT2.5 "DLSCH encoding time" "< 250") -check_threshold(physim.5g-offload.nr_dlsim.testCPU.6 "DLSCH encoding time" "< 400") -check_threshold(physim.5g-offload.nr_dlsim.testT2.6 "DLSCH encoding time" "< 400") -check_threshold(physim.5g-offload.nr_dlsim.testCPU.7 "DLSCH encoding time" "< 400") -check_threshold(physim.5g-offload.nr_dlsim.testT2.7 "DLSCH encoding time" "< 200") -check_threshold(physim.5g-offload.nr_dlsim.testCPU.8 "DLSCH encoding time" "< 450") -check_threshold(physim.5g-offload.nr_dlsim.testT2.8 "DLSCH encoding time" "< 500") -check_threshold(physim.5g-offload.nr_dlsim.testCPU.9 "DLSCH encoding time" "< 500") -check_threshold(physim.5g-offload.nr_dlsim.testT2.9 "DLSCH encoding time" "< 500") -check_threshold(physim.5g-offload.nr_dlsim.testCPU.10 "DLSCH encoding time" "< 400") -check_threshold(physim.5g-offload.nr_dlsim.testT2.10 "DLSCH encoding time" "< 200") -check_threshold(physim.5g-offload.nr_dlsim.testCPU.11 "DLSCH encoding time" "< 400") -check_threshold(physim.5g-offload.nr_dlsim.testT2.11 "DLSCH encoding time" "< 300") -check_threshold(physim.5g-offload.nr_dlsim.testCPU.12 "DLSCH encoding time" "< 450") -check_threshold(physim.5g-offload.nr_dlsim.testT2.12 "DLSCH encoding time" "< 450") +check_threshold_variance(physim.5g-offload.nr_dlsim.testCPU.1 "DLSCH encoding time" AVG 50 ABS_VAR 10) +check_threshold_variance(physim.5g-offload.nr_dlsim.testT2.1 "DLSCH encoding time" AVG 19 ABS_VAR 4) +check_threshold_variance(physim.5g-offload.nr_dlsim.testCPU.2 "DLSCH encoding time" AVG 65 ABS_VAR 13) +check_threshold_variance(physim.5g-offload.nr_dlsim.testT2.2 "DLSCH encoding time" AVG 27 ABS_VAR 6) +check_threshold_variance(physim.5g-offload.nr_dlsim.testCPU.3 "DLSCH encoding time" AVG 97 ABS_VAR 20) +check_threshold_variance(physim.5g-offload.nr_dlsim.testT2.3 "DLSCH encoding time" AVG 33 ABS_VAR 7) +check_threshold_variance(physim.5g-offload.nr_dlsim.testCPU.4 "DLSCH encoding time" AVG 68 ABS_VAR 14) +check_threshold_variance(physim.5g-offload.nr_dlsim.testT2.4 "DLSCH encoding time" AVG 26 ABS_VAR 6) +check_threshold_variance(physim.5g-offload.nr_dlsim.testCPU.5 "DLSCH encoding time" AVG 108 ABS_VAR 22) +check_threshold_variance(physim.5g-offload.nr_dlsim.testT2.5 "DLSCH encoding time" AVG 46 ABS_VAR 10) +check_threshold_variance(physim.5g-offload.nr_dlsim.testCPU.6 "DLSCH encoding time" AVG 131 ABS_VAR 27) +check_threshold_variance(physim.5g-offload.nr_dlsim.testT2.6 "DLSCH encoding time" AVG 80 ABS_VAR 16) +check_threshold_variance(physim.5g-offload.nr_dlsim.testCPU.7 "DLSCH encoding time" AVG 120 ABS_VAR 24) +check_threshold_variance(physim.5g-offload.nr_dlsim.testT2.7 "DLSCH encoding time" AVG 44 ABS_VAR 9) +check_threshold_variance(physim.5g-offload.nr_dlsim.testCPU.8 "DLSCH encoding time" AVG 146 ABS_VAR 30) +check_threshold_variance(physim.5g-offload.nr_dlsim.testT2.8 "DLSCH encoding time" AVG 87 ABS_VAR 18) +check_threshold_variance(physim.5g-offload.nr_dlsim.testCPU.9 "DLSCH encoding time" AVG 204 ABS_VAR 41) +check_threshold_variance(physim.5g-offload.nr_dlsim.testT2.9 "DLSCH encoding time" AVG 138 ABS_VAR 28) +check_threshold_variance(physim.5g-offload.nr_dlsim.testCPU.10 "DLSCH encoding time" AVG 149 ABS_VAR 30) +check_threshold_variance(physim.5g-offload.nr_dlsim.testT2.10 "DLSCH encoding time" AVG 49 ABS_VAR 10) +check_threshold_variance(physim.5g-offload.nr_dlsim.testCPU.11 "DLSCH encoding time" AVG 164 ABS_VAR 33) +check_threshold_variance(physim.5g-offload.nr_dlsim.testT2.11 "DLSCH encoding time" AVG 90 ABS_VAR 18) +check_threshold_variance(physim.5g-offload.nr_dlsim.testCPU.12 "DLSCH encoding time" AVG 223 ABS_VAR 45) +check_threshold_variance(physim.5g-offload.nr_dlsim.testT2.12 "DLSCH encoding time" AVG 146 ABS_VAR 30) -check_threshold(physim.5g-offload.nr_ulsim.testCPU.1 "ULSCH total decoding time" "< 300") -check_threshold(physim.5g-offload.nr_ulsim.testT2.1 "ULSCH total decoding time" "< 100") -check_threshold(physim.5g-offload.nr_ulsim.testCPU.2 "ULSCH total decoding time" "< 300") -check_threshold(physim.5g-offload.nr_ulsim.testT2.2 "ULSCH total decoding time" "< 150") -check_threshold(physim.5g-offload.nr_ulsim.testCPU.3 "ULSCH total decoding time" "< 250") -check_threshold(physim.5g-offload.nr_ulsim.testT2.3 "ULSCH total decoding time" "< 250") -check_threshold(physim.5g-offload.nr_ulsim.testCPU.4 "ULSCH total decoding time" "< 300") -check_threshold(physim.5g-offload.nr_ulsim.testT2.4 "ULSCH total decoding time" "< 150") -check_threshold(physim.5g-offload.nr_ulsim.testCPU.5 "ULSCH total decoding time" "< 400") -check_threshold(physim.5g-offload.nr_ulsim.testT2.5 "ULSCH total decoding time" "< 350") -check_threshold(physim.5g-offload.nr_ulsim.testCPU.6 "ULSCH total decoding time" "< 400") -check_threshold(physim.5g-offload.nr_ulsim.testT2.6 "ULSCH total decoding time" "< 550") -check_threshold(physim.5g-offload.nr_ulsim.testCPU.7 "ULSCH total decoding time" "< 300") -check_threshold(physim.5g-offload.nr_ulsim.testT2.7 "ULSCH total decoding time" "< 250") -check_threshold(physim.5g-offload.nr_ulsim.testCPU.8 "ULSCH total decoding time" "< 600") -check_threshold(physim.5g-offload.nr_ulsim.testT2.8 "ULSCH total decoding time" "< 650") -check_threshold(physim.5g-offload.nr_ulsim.testCPU.9 "ULSCH total decoding time" "< 650") -check_threshold(physim.5g-offload.nr_ulsim.testT2.9 "ULSCH total decoding time" "< 1100") +check_threshold_variance(physim.5g-offload.nr_ulsim.testCPU.1 "ULSCH total decoding time" AVG 141 ABS_VAR 29) +check_threshold_variance(physim.5g-offload.nr_ulsim.testT2.1 "ULSCH total decoding time" AVG 40 ABS_VAR 8) +check_threshold_variance(physim.5g-offload.nr_ulsim.testCPU.2 "ULSCH total decoding time" AVG 165 ABS_VAR 33) +check_threshold_variance(physim.5g-offload.nr_ulsim.testT2.2 "ULSCH total decoding time" AVG 63 ABS_VAR 13) +check_threshold_variance(physim.5g-offload.nr_ulsim.testCPU.3 "ULSCH total decoding time" AVG 156 ABS_VAR 32) +check_threshold_variance(physim.5g-offload.nr_ulsim.testT2.3 "ULSCH total decoding time" AVG 87 ABS_VAR 18) +check_threshold_variance(physim.5g-offload.nr_ulsim.testCPU.4 "ULSCH total decoding time" AVG 170 ABS_VAR 34) +check_threshold_variance(physim.5g-offload.nr_ulsim.testT2.4 "ULSCH total decoding time" AVG 74 ABS_VAR 15) +check_threshold_variance(physim.5g-offload.nr_ulsim.testCPU.5 "ULSCH total decoding time" AVG 299 ABS_VAR 60) +check_threshold_variance(physim.5g-offload.nr_ulsim.testT2.5 "ULSCH total decoding time" AVG 120 ABS_VAR 24) +check_threshold_variance(physim.5g-offload.nr_ulsim.testCPU.6 "ULSCH total decoding time" AVG 324 ABS_VAR 65) +check_threshold_variance(physim.5g-offload.nr_ulsim.testT2.6 "ULSCH total decoding time" AVG 180 ABS_VAR 36) +check_threshold_variance(physim.5g-offload.nr_ulsim.testCPU.7 "ULSCH total decoding time" AVG 200 ABS_VAR 40) +check_threshold_variance(physim.5g-offload.nr_ulsim.testT2.7 "ULSCH total decoding time" AVG 120 ABS_VAR 24) +check_threshold_variance(physim.5g-offload.nr_ulsim.testCPU.8 "ULSCH total decoding time" AVG 436 ABS_VAR 88) +check_threshold_variance(physim.5g-offload.nr_ulsim.testT2.8 "ULSCH total decoding time" AVG 229 ABS_VAR 46) +check_threshold_variance(physim.5g-offload.nr_ulsim.testCPU.9 "ULSCH total decoding time" AVG 530 ABS_VAR 106) +check_threshold_variance(physim.5g-offload.nr_ulsim.testT2.9 "ULSCH total decoding time" AVG 334 ABS_VAR 67) From bcc616e654bb3baedc0add57a4aa6e527d811190 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Mon, 29 Sep 2025 15:35:05 +0200 Subject: [PATCH 912/964] Increase timeout for physim deployments Extend the timeout for physim deployments on OC to allow tests to complete reliably. --- ci-scripts/cls_oaicitest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci-scripts/cls_oaicitest.py b/ci-scripts/cls_oaicitest.py index 8dc4ae3a6f..2b31f41064 100644 --- a/ci-scripts/cls_oaicitest.py +++ b/ci-scripts/cls_oaicitest.py @@ -255,7 +255,7 @@ def Deploy_Physim(ctx, HTML, node, workdir, script, options): logging.debug(f'Running physims on server {node} workdir {workdir}') with cls_cmd.getConnection(node) as c: sys_info = c.exec_script("scripts/sys-info.sh", 5) - ret = c.exec_script(script, 600, options) + ret = c.exec_script(script, 1000, options) logging.debug(f'"{script}" finished with code {ret.returncode}, output:\n{ret.stdout}') HTML.CreateHtmlTestRowQueue('Query system info', 'OK', [sys_info.stdout]) with cls_cmd.getConnection(node) as ssh: From 5ec7bcdcd28d526df7a0cf653cad81db910d1230 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Mon, 22 Sep 2025 13:49:59 +0200 Subject: [PATCH 913/964] Add timing check for physim tests on GraceHopper Update Dockerfile to pass -DPHYSIM_CHECK_FILES="ThresholdsGracehopper.cmake". --- ci-scripts/docker/Dockerfile.physim.ubuntu | 1 + .../tests/ThresholdsGracehopper.cmake | 123 ++++++++++++++++++ 2 files changed, 124 insertions(+) create mode 100644 openair1/SIMULATION/tests/ThresholdsGracehopper.cmake diff --git a/ci-scripts/docker/Dockerfile.physim.ubuntu b/ci-scripts/docker/Dockerfile.physim.ubuntu index c3adfba966..8fe6d91c4a 100644 --- a/ci-scripts/docker/Dockerfile.physim.ubuntu +++ b/ci-scripts/docker/Dockerfile.physim.ubuntu @@ -42,5 +42,6 @@ WORKDIR /oai-ran/build RUN cmake -GNinja -DENABLE_PHYSIM_TESTS=ON \ -DSANITIZE_UNDEFINED=OFF -DSANITIZE_ADDRESS=OFF \ -DCMAKE_C_FLAGS=-Werror -DCMAKE_CXX_FLAGS=-Werror \ + -DPHYSIM_CHECK_FILES="ThresholdsGracehopper.cmake" \ .. && \ ninja ldpctest polartest smallblocktest nr_pbchsim nr_dlschsim nr_ulschsim nr_dlsim nr_ulsim nr_pucchsim nr_prachsim nr_psbchsim diff --git a/openair1/SIMULATION/tests/ThresholdsGracehopper.cmake b/openair1/SIMULATION/tests/ThresholdsGracehopper.cmake new file mode 100644 index 0000000000..7041a4f91b --- /dev/null +++ b/openair1/SIMULATION/tests/ThresholdsGracehopper.cmake @@ -0,0 +1,123 @@ +check_threshold_variance(physim.5g.nr_dlsim.basic.test1 "DLSCH encoding time" AVG 31 ABS_VAR 7) +check_threshold_variance(physim.5g.nr_dlsim.basic.test2 "DLSCH encoding time" AVG 36 ABS_VAR 8) +check_threshold_variance(physim.5g.nr_dlsim.basic.test3 "DLSCH encoding time" AVG 49 ABS_VAR 10) +check_threshold_variance(physim.5g.nr_dlsim.basic.test4 "DLSCH encoding time" AVG 33 ABS_VAR 7) +check_threshold_variance(physim.5g.nr_dlsim.basic.test5 "DLSCH encoding time" AVG 33 ABS_VAR 7) +check_threshold_variance(physim.5g.nr_dlsim.basic.test6 "DLSCH encoding time" AVG 31 ABS_VAR 7) +check_threshold_variance(physim.5g.nr_dlsim.basic.test7 "DLSCH encoding time" AVG 8 ABS_VAR 2) +check_threshold_variance(physim.5g.nr_dlsim.basic.test8 "DLSCH encoding time" AVG 20 ABS_VAR 4) +check_threshold_variance(physim.5g.nr_dlsim.offset.test1 "DLSCH encoding time" AVG 32 ABS_VAR 7) +check_threshold_variance(physim.5g.nr_dlsim.offset.test2 "DLSCH encoding time" AVG 25 ABS_VAR 5) +check_threshold_variance(physim.5g.nr_dlsim.offset.test3 "DLSCH encoding time" AVG 30 ABS_VAR 6) +check_threshold_variance(physim.5g.nr_dlsim.offset.test4 "DLSCH encoding time" AVG 34 ABS_VAR 7) +check_threshold_variance(physim.5g.nr_dlsim.offset.test5 "DLSCH encoding time" AVG 30 ABS_VAR 6) +check_threshold_variance(physim.5g.nr_dlsim.mcs.mimo.test1 "DLSCH encoding time" AVG 72 ABS_VAR 15) +check_threshold_variance(physim.5g.nr_dlsim.mcs.mimo.test2 "DLSCH encoding time" AVG 36 ABS_VAR 8) +check_threshold_variance(physim.5g.nr_dlsim.mcs.mimo.test3 "DLSCH encoding time" AVG 83 ABS_VAR 17) +check_threshold_variance(physim.5g.nr_dlsim.mcs.mimo.test4 "DLSCH encoding time" AVG 79 ABS_VAR 16) +check_threshold_variance(physim.5g.nr_dlsim.mcs.mimo.test5 "DLSCH encoding time" AVG 30 ABS_VAR 6) +check_threshold_variance(physim.5g.nr_dlsim.mcs.mimo.test6 "DLSCH encoding time" AVG 39 ABS_VAR 8) +check_threshold_variance(physim.5g.nr_dlsim.mcs.mimo.test7 "DLSCH encoding time" AVG 48 ABS_VAR 10) +check_threshold_variance(physim.5g.nr_dlsim.mcs.mimo.test8 "DLSCH encoding time" AVG 141 ABS_VAR 29) +check_threshold_variance(physim.5g.nr_dlsim.mcs.mimo.test9 "DLSCH encoding time" AVG 32 ABS_VAR 7) +check_threshold_variance(physim.5g.nr_dlsim.dmrs.ptrs.test1 "DLSCH encoding time" AVG 31 ABS_VAR 7) +check_threshold_variance(physim.5g.nr_dlsim.dmrs.ptrs.test2 "DLSCH encoding time" AVG 31 ABS_VAR 7) +check_threshold_variance(physim.5g.nr_dlsim.dmrs.ptrs.test3 "DLSCH encoding time" AVG 31 ABS_VAR 7) +check_threshold_variance(physim.5g.nr_dlsim.dmrs.ptrs.test4 "DLSCH encoding time" AVG 31 ABS_VAR 7) +check_threshold_variance(physim.5g.nr_dlsim.dmrs.ptrs.test5 "DLSCH encoding time" AVG 31 ABS_VAR 7) +check_threshold_variance(physim.5g.nr_dlsim.dmrs.ptrs.test6 "DLSCH encoding time" AVG 31 ABS_VAR 7) + +check_threshold_variance(physim.5g.nr_ulsim.misc.test1 "ULSCH total decoding time" AVG 326 ABS_VAR 66) +check_threshold_variance(physim.5g.nr_ulsim.misc.test2 "ULSCH total decoding time" AVG 466 ABS_VAR 94) +check_threshold_variance(physim.5g.nr_ulsim.misc.test3 "ULSCH total decoding time" AVG 558 ABS_VAR 112) +check_threshold_variance(physim.5g.nr_ulsim.misc.test4 "ULSCH total decoding time" AVG 578 ABS_VAR 116) +check_threshold_variance(physim.5g.nr_ulsim.misc.test5 "ULSCH total decoding time" AVG 1019 ABS_VAR 204) +check_threshold_variance(physim.5g.nr_ulsim.misc.test6 "ULSCH total decoding time" AVG 1234 ABS_VAR 247) +check_threshold_variance(physim.5g.nr_ulsim.misc.test7 "ULSCH total decoding time" AVG 244 ABS_VAR 49) +check_threshold_variance(physim.5g.nr_ulsim.misc.test8 "ULSCH total decoding time" AVG 150 ABS_VAR 30) +check_threshold_variance(physim.5g.nr_ulsim.misc.test9 "ULSCH total decoding time" AVG 148 ABS_VAR 30) +check_threshold_variance(physim.5g.nr_ulsim.misc.test10 "ULSCH total decoding time" AVG 151 ABS_VAR 31) +check_threshold_variance(physim.5g.nr_ulsim.misc.test11 "ULSCH total decoding time" AVG 46 ABS_VAR 10) +check_threshold_variance(physim.5g.nr_ulsim.misc.test12 "ULSCH total decoding time" AVG 109 ABS_VAR 22) +check_threshold_variance(physim.5g.nr_ulsim.misc.test13 "ULSCH total decoding time" AVG 85 ABS_VAR 17) +check_threshold_variance(physim.5g.nr_ulsim.misc.test14 "ULSCH total decoding time" AVG 1185 ABS_VAR 237) +check_threshold_variance(physim.5g.nr_ulsim.misc.test15 "ULSCH total decoding time" AVG 114 ABS_VAR 23) +check_threshold_variance(physim.5g.nr_ulsim.sc-fdma.test1 "ULSCH total decoding time" AVG 239 ABS_VAR 48) +check_threshold_variance(physim.5g.nr_ulsim.sc-fdma.test2 "ULSCH total decoding time" AVG 229 ABS_VAR 46) +check_threshold_variance(physim.5g.nr_ulsim.sc-fdma.test3 "ULSCH total decoding time" AVG 989 ABS_VAR 198) +check_threshold_variance(physim.5g.nr_ulsim.sc-fdma.test4 "ULSCH total decoding time" AVG 797 ABS_VAR 160) +check_threshold_variance(physim.5g.nr_ulsim.sc-fdma.test5 "ULSCH total decoding time" AVG 132 ABS_VAR 27) +check_threshold_variance(physim.5g.nr_ulsim.mimo.test1 "ULSCH total decoding time" AVG 513 ABS_VAR 103) +check_threshold_variance(physim.5g.nr_ulsim.mimo.test2 "ULSCH total decoding time" AVG 435 ABS_VAR 87) +check_threshold_variance(physim.5g.nr_ulsim.mimo.test3 "ULSCH total decoding time" AVG 1082 ABS_VAR 217) +check_threshold_variance(physim.5g.nr_ulsim.mimo.test4 "ULSCH total decoding time" AVG 1561 ABS_VAR 313) +check_threshold_variance(physim.5g.nr_ulsim.mimo.test5 "ULSCH total decoding time" AVG 1162 ABS_VAR 233) +check_threshold_variance(physim.5g.nr_ulsim.3gpp.test1 "ULSCH total decoding time" AVG 993 ABS_VAR 199) +check_threshold_variance(physim.5g.nr_ulsim.3gpp.test2 "ULSCH total decoding time" AVG 1038 ABS_VAR 208) +check_threshold_variance(physim.5g.nr_ulsim.3gpp.test3 "ULSCH total decoding time" AVG 1168 ABS_VAR 234) +check_threshold_variance(physim.5g.nr_ulsim.3gpp.test4 "ULSCH total decoding time" AVG 304 ABS_VAR 61) +check_threshold_variance(physim.5g.nr_ulsim.3gpp.test5 "ULSCH total decoding time" AVG 311 ABS_VAR 63) +check_threshold_variance(physim.5g.nr_ulsim.3gpp.test6 "ULSCH total decoding time" AVG 333 ABS_VAR 67) +check_threshold_variance(physim.5g.nr_ulsim.3gpp.test7 "ULSCH total decoding time" AVG 527 ABS_VAR 106) +check_threshold_variance(physim.5g.nr_ulsim.3gpp.test8 "ULSCH total decoding time" AVG 559 ABS_VAR 112) +check_threshold_variance(physim.5g.nr_ulsim.3gpp.test9 "ULSCH total decoding time" AVG 591 ABS_VAR 119) +check_threshold_variance(physim.5g.nr_ulsim.3gpp.test10 "ULSCH total decoding time" AVG 969 ABS_VAR 194) +check_threshold_variance(physim.5g.nr_ulsim.3gpp.test11 "ULSCH total decoding time" AVG 1056 ABS_VAR 212) +check_threshold_variance(physim.5g.nr_ulsim.3gpp.test12 "ULSCH total decoding time" AVG 1202 ABS_VAR 241) +check_threshold_variance(physim.5g.nr_ulsim.3gpp.test13 "ULSCH total decoding time" AVG 303 ABS_VAR 61) +check_threshold_variance(physim.5g.nr_ulsim.3gpp.test14 "ULSCH total decoding time" AVG 320 ABS_VAR 64) +check_threshold_variance(physim.5g.nr_ulsim.3gpp.test15 "ULSCH total decoding time" AVG 332 ABS_VAR 67) +check_threshold_variance(physim.5g.nr_ulsim.3gpp.test16 "ULSCH total decoding time" AVG 536 ABS_VAR 108) +check_threshold_variance(physim.5g.nr_ulsim.3gpp.test17 "ULSCH total decoding time" AVG 560 ABS_VAR 112) +check_threshold_variance(physim.5g.nr_ulsim.3gpp.test18 "ULSCH total decoding time" AVG 606 ABS_VAR 122) +check_threshold_variance(physim.5g.nr_ulsim.3gpp.test19 "ULSCH total decoding time" AVG 1019 ABS_VAR 204) +check_threshold_variance(physim.5g.nr_ulsim.3gpp.test20 "ULSCH total decoding time" AVG 1060 ABS_VAR 212) +check_threshold_variance(physim.5g.nr_ulsim.3gpp.test21 "ULSCH total decoding time" AVG 1158 ABS_VAR 232) +check_threshold_variance(physim.5g.nr_ulsim.3gpp.test22 "ULSCH total decoding time" AVG 2466 ABS_VAR 494) +check_threshold_variance(physim.5g.nr_ulsim.3gpp.test23 "ULSCH total decoding time" AVG 2557 ABS_VAR 512) +check_threshold_variance(physim.5g.nr_ulsim.3gpp.test24 "ULSCH total decoding time" AVG 3149 ABS_VAR 630) +check_threshold_variance(physim.5g.nr_ulsim.3gpp.test25 "ULSCH total decoding time" AVG 469 ABS_VAR 94) +check_threshold_variance(physim.5g.nr_ulsim.3gpp.test26 "ULSCH total decoding time" AVG 416 ABS_VAR 84) +check_threshold_variance(physim.5g.nr_ulsim.3gpp.test27 "ULSCH total decoding time" AVG 1587 ABS_VAR 318) +check_threshold_variance(physim.5g.nr_ulsim.3gpp.test28 "ULSCH total decoding time" AVG 1792 ABS_VAR 359) + +check_threshold_variance(physim.5g.ldpctest.test1 "Encoding time mean:" AVG 6 ABS_VAR 2) +check_threshold_variance(physim.5g.ldpctest.test1 "Decoding time mean:" AVG 103 ABS_VAR 21) +check_threshold_variance(physim.5g.ldpctest.test2 "Encoding time mean:" AVG 9 ABS_VAR 2) +check_threshold_variance(physim.5g.ldpctest.test2 "Decoding time mean:" AVG 113 ABS_VAR 23) +check_threshold_variance(physim.5g.ldpctest.test3 "Encoding time mean:" AVG 8 ABS_VAR 2) +check_threshold_variance(physim.5g.ldpctest.test3 "Decoding time mean:" AVG 123 ABS_VAR 25) +check_threshold_variance(physim.5g.ldpctest.test4 "Encoding time mean:" AVG 11 ABS_VAR 3) +check_threshold_variance(physim.5g.ldpctest.test4 "Decoding time mean:" AVG 137 ABS_VAR 28) +check_threshold_variance(physim.5g.ldpctest.test5 "Encoding time mean:" AVG 10 ABS_VAR 2) +check_threshold_variance(physim.5g.ldpctest.test5 "Decoding time mean:" AVG 143 ABS_VAR 29) +check_threshold_variance(physim.5g.ldpctest.test6 "Encoding time mean:" AVG 16 ABS_VAR 4) +check_threshold_variance(physim.5g.ldpctest.test6 "Decoding time mean:" AVG 148 ABS_VAR 30) +check_threshold_variance(physim.5g.ldpctest.test7 "Encoding time mean:" AVG 14 ABS_VAR 3) +check_threshold_variance(physim.5g.ldpctest.test7 "Decoding time mean:" AVG 171 ABS_VAR 35) +check_threshold_variance(physim.5g.ldpctest.test8 "Encoding time mean:" AVG 17 ABS_VAR 4) +check_threshold_variance(physim.5g.ldpctest.test8 "Decoding time mean:" AVG 185 ABS_VAR 37) +check_threshold_variance(physim.5g.ldpctest.test9 "Encoding time mean:" AVG 19 ABS_VAR 4) +check_threshold_variance(physim.5g.ldpctest.test9 "Decoding time mean:" AVG 206 ABS_VAR 42) +check_threshold_variance(physim.5g.ldpctest.test10 "Encoding time mean:" AVG 14 ABS_VAR 3) +check_threshold_variance(physim.5g.ldpctest.test10 "Decoding time mean:" AVG 222 ABS_VAR 45) +check_threshold_variance(physim.5g.ldpctest.test11 "Encoding time mean:" AVG 2 ABS_VAR 1) +check_threshold_variance(physim.5g.ldpctest.test11 "Decoding time mean:" AVG 8 ABS_VAR 2) +check_threshold_variance(physim.5g.ldpctest.test12 "Encoding time mean:" AVG 10 ABS_VAR 2) +check_threshold_variance(physim.5g.ldpctest.test12 "Decoding time mean:" AVG 10 ABS_VAR 2) +check_threshold_variance(physim.5g.ldpctest.test13 "Encoding time mean:" AVG 18 ABS_VAR 4) +check_threshold_variance(physim.5g.ldpctest.test13 "Decoding time mean:" AVG 10 ABS_VAR 2) +check_threshold_variance(physim.5g.ldpctest.test14 "Encoding time mean:" AVG 44 ABS_VAR 9) +check_threshold_variance(physim.5g.ldpctest.test14 "Decoding time mean:" AVG 15 ABS_VAR 3) +check_threshold_variance(physim.5g.ldpctest.test15 "Encoding time mean:" AVG 49 ABS_VAR 10) +check_threshold_variance(physim.5g.ldpctest.test15 "Decoding time mean:" AVG 14 ABS_VAR 3) +check_threshold_variance(physim.5g.ldpctest.test16 "Encoding time mean:" AVG 3 ABS_VAR 1) +check_threshold_variance(physim.5g.ldpctest.test16 "Decoding time mean:" AVG 15 ABS_VAR 3) +check_threshold_variance(physim.5g.ldpctest.test17 "Encoding time mean:" AVG 3 ABS_VAR 1) +check_threshold_variance(physim.5g.ldpctest.test17 "Decoding time mean:" AVG 14 ABS_VAR 3) +check_threshold_variance(physim.5g.ldpctest.test18 "Encoding time mean:" AVG 5 ABS_VAR 1) +check_threshold_variance(physim.5g.ldpctest.test18 "Decoding time mean:" AVG 32 ABS_VAR 7) +check_threshold_variance(physim.5g.ldpctest.test19 "Encoding time mean:" AVG 8 ABS_VAR 2) +check_threshold_variance(physim.5g.ldpctest.test19 "Decoding time mean:" AVG 48 ABS_VAR 10) +check_threshold_variance(physim.5g.ldpctest.test20 "Encoding time mean:" AVG 10 ABS_VAR 2) +check_threshold_variance(physim.5g.ldpctest.test20 "Decoding time mean:" AVG 57 ABS_VAR 12) From 6843625615e605f62713767d8049754c4d9c84c0 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Mon, 29 Sep 2025 15:15:44 +0200 Subject: [PATCH 914/964] Add separate XML file for PhySim with timing check on GH --- ci-scripts/xml_files/physim_gracehopper.xml | 8 ++-- .../xml_files/physim_timed_gracehopper.xml | 46 +++++++++++++++++++ 2 files changed, 50 insertions(+), 4 deletions(-) create mode 100644 ci-scripts/xml_files/physim_timed_gracehopper.xml diff --git a/ci-scripts/xml_files/physim_gracehopper.xml b/ci-scripts/xml_files/physim_gracehopper.xml index a2abc628d0..f04ae2541f 100644 --- a/ci-scripts/xml_files/physim_gracehopper.xml +++ b/ci-scripts/xml_files/physim_gracehopper.xml @@ -21,7 +21,7 @@ --> - build-tab + physim-tab PhySim wrench @@ -38,9 +38,9 @@ Build_Deploy_Docker_PhySim - Deploy and Deploy PhySim + Build and Deploy PhySim localhost - -R 5g -E physim.5g.nr_dlsim.mcs.mimo.test9 -j16 - + -R 5g -E "nr_dlsim|nr_ulsim|ldpctest" -j32 + diff --git a/ci-scripts/xml_files/physim_timed_gracehopper.xml b/ci-scripts/xml_files/physim_timed_gracehopper.xml new file mode 100644 index 0000000000..7658279088 --- /dev/null +++ b/ci-scripts/xml_files/physim_timed_gracehopper.xml @@ -0,0 +1,46 @@ + + + physim-timed-tab + PhySim with timing check + wrench + + 800813 + 010202 + + + + + Create_Workspace + Create new Workspace + localhost + + + + Build_Deploy_Docker_PhySim + Build and Deploy PhySim with timing check + localhost + -R 5g -R "nr_dlsim|nr_ulsim|ldpctest" -E physim.5g.nr_dlsim.mcs.mimo.test9 -j1 + + + From ba8b23772e8855a1a834581e4f1d597613af2f1e Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 9 Oct 2025 08:48:24 +0200 Subject: [PATCH 915/964] CI RFsim 5G F1: reduce DL iperf throughput Reduce throughput requirement, as this fails once two DUs are connected to a UE, which creates more load on the machine and frequently fails with low throughput. --- ci-scripts/xml_files/container_5g_f1_rfsim.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ci-scripts/xml_files/container_5g_f1_rfsim.xml b/ci-scripts/xml_files/container_5g_f1_rfsim.xml index efe8fce8e2..9987aeaae0 100644 --- a/ci-scripts/xml_files/container_5g_f1_rfsim.xml +++ b/ci-scripts/xml_files/container_5g_f1_rfsim.xml @@ -134,8 +134,8 @@ Iperf - Iperf (DL/5Mbps/UDP)(30 sec) - -u -b 5M -t 20 -R + Iperf (DL/3Mbps/UDP)(30 sec) + -u -b 3M -t 20 -R rfsim5g_ue acamas rfsim5g_ext_dn From 00a7890449543c1217dd1db88a15deee782ad610 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Thu, 9 Oct 2025 14:04:14 +0200 Subject: [PATCH 916/964] asn1c doesn't follow c99 variables alias rules, it needs to be compiled this way. issue #509 reported in https://github.com/vlm/asn1c --- cmake_targets/tools/build_helper | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake_targets/tools/build_helper b/cmake_targets/tools/build_helper index 49edfa91e8..eeffc9d4f1 100755 --- a/cmake_targets/tools/build_helper +++ b/cmake_targets/tools/build_helper @@ -575,7 +575,7 @@ install_asn1c_from_source(){ # Showing which version is used git log -n1 autoreconf -iv - ./configure --prefix /opt/asn1c/ + CFLAGS="-O2 -fno-strict-aliasing" ./configure --prefix /opt/asn1c/ make -j`nproc` $SUDO make install cd - From 1a65abb56c59ce50cd13021c05c0650dff9a7874 Mon Sep 17 00:00:00 2001 From: Reem Bahsoun Date: Thu, 9 Oct 2025 15:00:47 +0200 Subject: [PATCH 917/964] Upgrade cuBB image to 25-2.1 and update doc to match --- ci-scripts/yaml_files/sa_gnb_aerial/docker-compose.yaml | 2 +- doc/Aerial_FAPI_Split_Tutorial.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ci-scripts/yaml_files/sa_gnb_aerial/docker-compose.yaml b/ci-scripts/yaml_files/sa_gnb_aerial/docker-compose.yaml index a5cf02cc40..c9f3d90131 100644 --- a/ci-scripts/yaml_files/sa_gnb_aerial/docker-compose.yaml +++ b/ci-scripts/yaml_files/sa_gnb_aerial/docker-compose.yaml @@ -23,7 +23,7 @@ services: - ../../../cmake_targets/share:/opt/cuBB/share userns_mode: host ipc: "shareable" - image: cubb-build:25-2-srs + image: cubb-build:25-2.1 environment: - cuBB_SDK=/opt/nvidia/cuBB command: bash -c "sudo rm -rf /tmp/phy.log && sudo chmod +x /opt/nvidia/cuBB/aerial_l1_entrypoint.sh && /opt/nvidia/cuBB/aerial_l1_entrypoint.sh" diff --git a/doc/Aerial_FAPI_Split_Tutorial.md b/doc/Aerial_FAPI_Split_Tutorial.md index 08e66bdbba..6eef02dc34 100644 --- a/doc/Aerial_FAPI_Split_Tutorial.md +++ b/doc/Aerial_FAPI_Split_Tutorial.md @@ -232,10 +232,10 @@ After preparing the L1 software, the container needs to be committed to create a In this file the RU MAC address needs to be specified before commiting the image. ```bash -~$ docker commit nv-cubb cubb-build:25-2 +~$ docker commit nv-cubb cubb-build:25-2.1 ~$ docker image ls .. -cubb-build 25-2 824156e0334c 2 weeks ago 23.9GB +cubb-build 25-2.1 824156e0334c 2 weeks ago 23.9GB -.. ``` From 8b9098b7ca9479a159a9f9d33a5b1597a46662b0 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Thu, 9 Oct 2025 15:53:51 +0200 Subject: [PATCH 918/964] remove unused declarations in common/platform_types.h --- common/platform_types.h | 32 ----------------------------- openair2/LAYER2/PDCP_v10.1.0/pdcp.c | 3 +-- openair2/LAYER2/RLC/rlc.h | 16 --------------- 3 files changed, 1 insertion(+), 50 deletions(-) diff --git a/common/platform_types.h b/common/platform_types.h index 9827dba974..9404f987ac 100644 --- a/common/platform_types.h +++ b/common/platform_types.h @@ -45,7 +45,6 @@ typedef uint16_t module_id_t; typedef uint8_t slice_id_t; typedef uint8_t eNB_index_t; typedef uint64_t ue_id_t; -typedef int16_t smodule_id_t; typedef long rb_id_t; typedef long srb_id_t; @@ -74,24 +73,7 @@ typedef enum { FDD = 0 } frame_type_t; -typedef enum link_direction_e { UNKNOWN_DIR = 0, DIR_UPLINK = 1, DIR_DOWNLINK = 2 } link_direction_t; - -typedef enum rb_type_e { UNKNOWN_RADIO_BEARER = 0, SIGNALLING_RADIO_BEARER = 1, RADIO_ACCESS_BEARER = 2 } rb_type_t; - -typedef enum { CR_ROUND = 0, CR_SRB12 = 1, CR_HOL = 2, CR_LC = 3, CR_CQI = 4, CR_LCP = 5, CR_NUM = 6 } sorting_criterion_t; - -typedef enum { POL_FAIR = 0, POL_GREEDY = 1, POL_NUM = 2 } accounting_policy_t; -//----------------------------------------------------------------------------- -// PHY TYPES -//----------------------------------------------------------------------------- -typedef uint8_t crc8_t; -typedef uint16_t crc16_t; -typedef uint32_t crc32_t; typedef unsigned int crc_t; - -//----------------------------------------------------------------------------- -// MAC TYPES -//----------------------------------------------------------------------------- typedef sdu_size_t tbs_size_t; typedef sdu_size_t tb_size_t; typedef unsigned int logical_chan_id_t; @@ -103,9 +85,6 @@ typedef uint8_t mac_enb_index_t; //----------------------------------------------------------------------------- typedef unsigned int mui_t; typedef unsigned int confirm_t; -typedef unsigned int rlc_tx_status_t; -typedef int16_t rlc_sn_t; -typedef uint16_t rlc_usn_t; typedef int32_t rlc_buffer_occupancy_t; typedef signed int rlc_op_status_t; @@ -130,7 +109,6 @@ typedef struct { //----------------------------------------------------------------------------- typedef uint16_t pdcp_sn_t; typedef uint32_t pdcp_hfn_t; -typedef int16_t pdcp_hfn_offset_t; typedef enum pdcp_transmission_mode_e { PDCP_TRANSMISSION_MODE_UNKNOWN = 0, @@ -177,7 +155,6 @@ typedef struct net_ip_address_s { typedef uint32_t mbms_session_id_t; typedef uint16_t mbms_service_id_t; typedef uint16_t rnti_t; -typedef uint8_t rrc_enb_index_t; typedef uint8_t mme_code_t; typedef uint32_t m_tmsi_t; @@ -188,7 +165,6 @@ typedef uint32_t m_tmsi_t; #define P_RNTI (rnti_t)0xFFFE #define SI_RNTI (rnti_t)0xFFFF #define CBA_RNTI (rnti_t)0xfff4 -#define OAI_C_RNTI (rnti_t)0x1234 typedef enum config_action_e { CONFIG_ACTION_NULL = 0, CONFIG_ACTION_ADD = 1, @@ -256,8 +232,6 @@ typedef struct protocol_ctxt_s { eNB_index_t eNB_index; /*!< \brief valid for UE indicating the index of connected eNB(s) */ bool brOption; } protocol_ctxt_t; -// warning time hardcoded -#define PROTOCOL_CTXT_TIME_MILLI_SECONDS(CtXt_h) ((CtXt_h)->frame * 10 + (CtXt_h)->subframe) #define UE_MODULE_ID_TO_INSTANCE(mODULE_iD) mODULE_iD + RC.nb_inst #define ENB_MODULE_ID_TO_INSTANCE(mODULE_iD) mODULE_iD @@ -309,12 +283,6 @@ typedef struct protocol_ctxt_s { #define PROTOCOL_CTXT_ARGS(CTXT_Pp) \ (CTXT_Pp)->frame, ((CTXT_Pp)->enb_flag == ENB_FLAG_YES) ? "eNB" : " UE", (CTXT_Pp)->module_id, (CTXT_Pp)->rntiMaybeUEid -#define PROTOCOL_NR_CTXT_ARGS(CTXT_Pp) \ - (CTXT_Pp)->frame, ((CTXT_Pp)->enb_flag == GNB_FLAG_YES) ? "gNB" : " UE", (CTXT_Pp)->module_id, (CTXT_Pp)->rntiMaybeUEid - -#define CHECK_CTXT_ARGS(CTXT_Pp) - - static inline int ceil_mod(const unsigned int v, const unsigned int mod) { return ((v + mod - 1) / mod) * mod; diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c index f93044f9cd..0b8e9e2d40 100644 --- a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c +++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c @@ -231,8 +231,7 @@ bool pdcp_data_req(protocol_ctxt_t *ctxt_pP, hashtable_rc_t h_rc; uint8_t rb_offset= (srb_flagP == 0) ? DTCH -1 : 0; uint16_t pdcp_uid=0; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_IN); - CHECK_CTXT_ARGS(ctxt_pP); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ, VCD_FUNCTION_IN); #if T_TRACER if (ctxt_pP->enb_flag != ENB_FLAG_NO) diff --git a/openair2/LAYER2/RLC/rlc.h b/openair2/LAYER2/RLC/rlc.h index 9afad74714..4559eb3273 100644 --- a/openair2/LAYER2/RLC/rlc.h +++ b/openair2/LAYER2/RLC/rlc.h @@ -262,22 +262,6 @@ void rlc_data_ind(const protocol_ctxt_t *const, const sdu_size_t, uint8_t *const); -/*! \fn void rlc_data_conf (const protocol_ctxt_t* const ctxtP, const srb_flag_t srb_flagP, const rb_id_t rb_idP, const mui_t muiP, const rlc_tx_status_t statusP) -* \brief Interface with higher layers, confirm to upper layer the transmission status for a SDU stamped with a MUI, scheduled for transmission. -* \param[in] ctxtP Running context. -* \param[in] srb_flagP Flag to indicate SRB (1) or DRB (0) -* \param[in] rb_idP Radio bearer identifier. -* \param[in] muiP Message Unit identifier. -* \param[in] statusP Status of the transmission (RLC_SDU_CONFIRM_YES, RLC_SDU_CONFIRM_NO). -*/ -void rlc_data_conf( - const protocol_ctxt_t *const, - const srb_flag_t, - const rb_id_t, - const mui_t, - const rlc_tx_status_t ); - - /*! \fn rlc_op_status_t rlc_stat_req ( const protocol_ctxt_t* const ctxtP, const srb_flag_t srb_flagP, From c537e2cabef9befdd4f3f50d3afcbd8fd69c517b Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Thu, 9 Oct 2025 15:59:32 +0200 Subject: [PATCH 919/964] move complex numbers types above phy layer, as they are used in fapi for example --- common/platform_types.h | 33 +++++++++++++++++++++++++++++++ openair1/PHY/TOOLS/tools_defs.h | 35 +-------------------------------- 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/common/platform_types.h b/common/platform_types.h index 9404f987ac..e2ffb7b304 100644 --- a/common/platform_types.h +++ b/common/platform_types.h @@ -33,6 +33,39 @@ #include #include +#define ALIGNARRAYSIZE(a, b) (((a + b - 1) / b) * b) +#define ALNARS_16_4(a) ALIGNARRAYSIZE(a, 4) + +typedef struct complexd { + double r; + double i; +} cd_t; + +typedef struct complexf { + float r; + float i; +} cf_t; + +typedef struct complex8 { + int8_t r; + int8_t i; +} c8_t; + +typedef struct complex16 { + int16_t r; + int16_t i; +} c16_t; + +typedef struct complex32 { + int32_t r; + int32_t i; +} c32_t; + +typedef struct complex64 { + int64_t r; + int64_t i; +} c64_t; + //----------------------------------------------------------------------------- // GENERIC ACCESS STRATUM TYPES //----------------------------------------------------------------------------- diff --git a/openair1/PHY/TOOLS/tools_defs.h b/openair1/PHY/TOOLS/tools_defs.h index 9ee558c72b..092beebcd7 100644 --- a/openair1/PHY/TOOLS/tools_defs.h +++ b/openair1/PHY/TOOLS/tools_defs.h @@ -32,7 +32,7 @@ #include #include #include - +#include "common/platform_types.h" #include "PHY/sse_intrin.h" #include "common/utils/assertions.h" @@ -51,39 +51,6 @@ extern "C" { #endif -#define ALIGNARRAYSIZE(a, b) (((a + b - 1) / b) * b) -#define ALNARS_16_4(a) ALIGNARRAYSIZE(a, 4) - - typedef struct complexd { - double r; - double i; - } cd_t; - - typedef struct complexf { - float r; - float i; - } cf_t; - - typedef struct complex8 { - int8_t r; - int8_t i; - } c8_t; - - typedef struct complex16 { - int16_t r; - int16_t i; - } c16_t; - - typedef struct complex32 { - int32_t r; - int32_t i; - } c32_t; - - typedef struct complex64 { - int64_t r; - int64_t i; - } c64_t; - typedef struct { int dim1; int dim2; From be236d450e77e6503d4065c823056bb3abd2bea9 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Thu, 18 Sep 2025 14:57:57 +0200 Subject: [PATCH 920/964] Add measurements for performance analysis --- openair1/PHY/NR_TRANSPORT/nr_dlsch.c | 11 +++++++---- openair1/PHY/defs_gNB.h | 2 ++ openair1/SIMULATION/NR_PHY/dlsim.c | 10 +++++++++- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c index 58d11413f4..7aec1ac5ad 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c @@ -643,6 +643,7 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC #endif } + start_meas(&gNB->dlsch_pdsch_generation_stats); /// Resource mapping // Non interleaved VRB to PRB mapping uint16_t start_sc = frame_parms->first_carrier_offset + (rel15->rbStart + rel15->BWPStart) * NR_NB_SC_PER_RB; @@ -664,6 +665,7 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC c16_t mod_dmrs[(n_dmrs+63)&~63] __attribute__((aligned(64))); unsigned int re_beginning_of_symbol = 0; + start_meas(&gNB->dlsch_layer_mapping_stats); int layerSz2 = (layerSz + 63) & ~63; c16_t tx_layers[rel15->nrOfLayers][layerSz2] __attribute__((aligned(64))); memset(tx_layers, 0, sizeof(tx_layers)); @@ -676,7 +678,6 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC // pmi = prgs_list[rbidx/prg_size].pm_idx, rbidx =0,...,rbSize-1 // The Precoding matrix: // The Codebook Type I - start_meas(&gNB->dlsch_precoding_stats); nfapi_nr_tx_precoding_and_beamforming_t *pb = &rel15->precodingAndBeamforming; // beam number in multi-beam scenario (concurrent beams) int bitmap = SL_to_bitmap(rel15->StartSymbolIndex, rel15->NrOfSymbols); @@ -689,9 +690,10 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC bitmap); c16_t **txdataF = gNB->common_vars.txdataF[beam_nb]; - + stop_meas(&gNB->dlsch_layer_mapping_stats); // Loop Over OFDM symbols: for (int l_symbol = rel15->StartSymbolIndex; l_symbol < rel15->StartSymbolIndex + rel15->NrOfSymbols; l_symbol++) { + start_meas(&gNB->dlsch_resource_mapping_stats); int l_prime = 0; // single symbol layer 0 int l_overline = get_l0(rel15->dlDmrsSymbPos); @@ -758,13 +760,14 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC re_beginning_of_symbol += layer_sz; stop_meas(&gNB->dlsch_resource_mapping_stats); + start_meas(&gNB->dlsch_precoding_stats); for (int ant = 0; ant < frame_parms->nb_antennas_tx; ant++) { const size_t txdataF_offset_per_symbol = l_symbol * symbol_sz + txdataF_offset; do_txdataF(txdataF, symbol_sz, txdataF_precoding, gNB, rel15, ant, start_sc, txdataF_offset_per_symbol); } + stop_meas(&gNB->dlsch_precoding_stats); } - - stop_meas(&gNB->dlsch_precoding_stats); + stop_meas(&gNB->dlsch_pdsch_generation_stats); /* output and its parts for each dlsch should be aligned on 64 bytes (or 8 * 64 bits) * should remain a multiple of 8 * 64 with enough offset to fit each dlsch */ diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h index 987f77d953..395fb9d822 100644 --- a/openair1/PHY/defs_gNB.h +++ b/openair1/PHY/defs_gNB.h @@ -501,6 +501,8 @@ typedef struct PHY_VARS_gNB_s { time_stats_t dlsch_encoding_stats; time_stats_t dlsch_modulation_stats; time_stats_t dlsch_scrambling_stats; + time_stats_t dlsch_pdsch_generation_stats; + time_stats_t dlsch_layer_mapping_stats; time_stats_t dlsch_resource_mapping_stats; time_stats_t dlsch_precoding_stats; time_stats_t tinput; diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index d1d046505e..82fe1f2f7b 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -1029,7 +1029,10 @@ int main(int argc, char **argv) reset_meas(&gNB->dlsch_rate_matching_stats); reset_meas(&gNB->dlsch_segmentation_stats); reset_meas(&gNB->dlsch_modulation_stats); + reset_meas(&gNB->dlsch_pdsch_generation_stats); reset_meas(&gNB->dlsch_precoding_stats); + reset_meas(&gNB->dlsch_layer_mapping_stats); + reset_meas(&gNB->dlsch_resource_mapping_stats); reset_meas(&gNB->dlsch_encoding_stats); reset_meas(&gNB->dci_generation_stats); reset_meas(&gNB->tinput); @@ -1343,7 +1346,12 @@ int main(int argc, char **argv) printStatIndent3(&gNB->dlsch_interleaving_stats, "DLSCH Interleaving time"); printStatIndent2(&gNB->dlsch_modulation_stats,"DLSCH modulation time"); printStatIndent2(&gNB->dlsch_scrambling_stats, "DLSCH scrambling time"); - printStatIndent2(&gNB->dlsch_precoding_stats,"DLSCH Mapping/Precoding time"); + printStatIndent2(&gNB->dlsch_pdsch_generation_stats,"DLSCH PDSCH Generation time"); + printStatIndent3(&gNB->dlsch_layer_mapping_stats,"DLSCH Layer Mapping time"); + gNB->dlsch_resource_mapping_stats.trials = gNB->dlsch_layer_mapping_stats.trials; + printStatIndent3(&gNB->dlsch_resource_mapping_stats,"DLSCH Resource Mapping time"); + gNB->dlsch_precoding_stats.trials = gNB->dlsch_layer_mapping_stats.trials; + printStatIndent3(&gNB->dlsch_precoding_stats,"DLSCH Precoding time"); if (gNB->phase_comp) printStatIndent2(&gNB->phase_comp_stats, "Phase Compensation"); From 8711556d9e9a41aca6f49529deab9bc699de4d1f Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Thu, 18 Sep 2025 19:03:48 +0200 Subject: [PATCH 921/964] Handle larger RB step size in precoding --- openair1/PHY/NR_TRANSPORT/nr_dlsch.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c index 7aec1ac5ad..535c68f419 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c @@ -470,12 +470,14 @@ static inline void do_txdataF(c16_t **txdataF, // get pmi info const int pmi = (pb->prg_size > 0) ? (pb->prgs_list[(int)rb / pb->prg_size].pm_idx) : 0; const int pmi2 = (rb < (rel15->rbSize - 1) && pb->prg_size > 0) ? (pb->prgs_list[(int)(rb + 1) / pb->prg_size].pm_idx) : -1; + const int pmi3 = (rb < (rel15->rbSize - 2) && pb->prg_size > 0) ? (pb->prgs_list[(int)(rb + 2) / pb->prg_size].pm_idx) : -1; + const int pmi4 = (rb < (rel15->rbSize - 3) && pb->prg_size > 0) ? (pb->prgs_list[(int)(rb + 3) / pb->prg_size].pm_idx) : -1; // If pmi of next RB and pmi of current RB are the same, we do 2 RB in a row // if pmi differs, or current rb is the end (rel15->rbSize - 1), than we do 1 RB in a row - const int rb_step = pmi == pmi2 ? 2 : 1; + int rb_step0 = pmi == pmi2 ? 2 : 1; + const int rb_step = rb_step0==2 && pmi3==pmi && pmi4==pmi ? 4 : rb_step0; const int re_cnt = NR_NB_SC_PER_RB * rb_step; - if (pmi == 0) { // unitary Precoding if (subCarrier + re_cnt <= symbol_sz) { // RB does not cross DC if (ant < rel15->nrOfLayers) From 34ba85f3b1a70817832b96264ad765f57ffcd0b3 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Fri, 29 Aug 2025 15:11:19 +0200 Subject: [PATCH 922/964] precoder optimizations for AVX512 --- openair1/PHY/MODULATION/nr_modulation.c | 154 +++++++++++++++++++++++- 1 file changed, 149 insertions(+), 5 deletions(-) diff --git a/openair1/PHY/MODULATION/nr_modulation.c b/openair1/PHY/MODULATION/nr_modulation.c index 84f7e356e7..9b6103edd8 100644 --- a/openair1/PHY/MODULATION/nr_modulation.c +++ b/openair1/PHY/MODULATION/nr_modulation.c @@ -295,7 +295,7 @@ void nr_layer_mapping(int nbCodes, c16_t *tx0 = tx_layers[0]; c16_t *tx1 = tx_layers[1]; c16_t *tx2 = tx_layers[2]; -#if defined(__AVX512BW__) +#if defined(__AVX512F) && defined(__AVX512VBMI__) simde__m512i perm3_0 = simde_mm512_set_epi32(13 + 16, 10 + 16, 7 + 16, @@ -433,7 +433,7 @@ void nr_layer_mapping(int nbCodes, c16_t *tx1 = tx_layers[1]; c16_t *tx2 = tx_layers[2]; c16_t *tx3 = tx_layers[3]; -#if defined(__AVX512BW__) +#if defined(__AVX512VBMI__) simde__m512i perm4 = simde_mm512_set_epi32(15, 11, 7, 3, 14, 10, 6, 2, 13, 9, 5, 1, 12, 8, 4, 0); for (; i < (n_symbs & ~15); i += 16) { simde__m512i e = simde_mm512_permutexvar_epi32(perm4, *(simde__m512i *)(mod + i)); @@ -717,6 +717,35 @@ c16_t nr_layer_precoder_cm(int n_layers, return precodatatx_F; } +#if defined(__AVX512F__) && defined(__AVX512BW__) + +static inline __attribute__((always_inline)) __m512i cmac0_prec512(__m512i x, __m512i w_c, __m512i w_s) { + + // Multiplication and shift + const __m512i reals = + _mm512_srai_epi32(_mm512_madd_epi16(x, w_c), 15); // (int32_t) .r = (x.r * w.r - x.i * w.i) >> 15 + const __m512i imags = + _mm512_slli_epi32(_mm512_madd_epi16(x, w_s), 1); // (int32_t) .i = (x.r * w.i + x.i * w.r) << 1, since higher 16 bit of each 32 bit is taken by blend_epi16 + + // Re-arrange to match c16_t format + return _mm512_mask_blend_epi16(0xAAAAAAAA,reals, imags); + +} +static inline __attribute__((always_inline)) __m512i cmac_prec512(__m512i y, __m512i x, __m512i w_c, __m512i w_s) { + + // Multiplication and shift + const __m512i reals = + _mm512_srai_epi32(_mm512_madd_epi16(x, w_c), 15); // (int32_t) .r = (x.r * w.r - x.i * w.i) >> 15 + const __m512i imags = + _mm512_slli_epi32(_mm512_madd_epi16(x, w_s), 1); // (int32_t) .i = (x.r * w.i + x.i * w.r) << 1, since higher 16 bit of each 32 bit is taken by blend_epi16 + + // Re-arrange to match c16_t format + const __m512i produ = _mm512_mask_blend_epi16(0xAAAAAAAA,reals, imags); + + // Accumulate the product + return _mm512_adds_epi16(y, produ); +} +#endif void nr_layer_precoder_simd(const int n_layers, const int symSz, const c16_t txdataF_res_mapped[n_layers][symSz], @@ -731,11 +760,125 @@ void nr_layer_precoder_simd(const int n_layers, // For x86, use 256 SIMD for every 8 RE and 128 SIMD for last 4 RE // For aarch64, use 128 SIMD for every 4 RE - // 256 SIMD: Do 8 RE in one iteration, 3 iterations for 2 RB + // 512/256 SIMD: Do 16/8 RE in one iteration, 3 iterations for 2 RB +#if defined(__AVX512F__) && defined(__AVX512BW__) + const uint32_t re_cnt_align16 = re_cnt & ~15; + if (n_layers==2) { + prec_weight.r = pmi_pdu->weights[0][ant].precoder_weight_Re; + prec_weight.i = pmi_pdu->weights[0][ant].precoder_weight_Im; + const __m512i w_c = _mm512_set1_epi32(c16toI32(c16conj(prec_weight))); // broadcast conjugate of w + const __m512i w_s = _mm512_set1_epi32(c16toI32(c16swap(prec_weight))); // broadcast swapped real and img of w + prec_weight.r = pmi_pdu->weights[1][ant].precoder_weight_Re; + prec_weight.i = pmi_pdu->weights[1][ant].precoder_weight_Im; + const __m512i w_c1 = _mm512_set1_epi32(c16toI32(c16conj(prec_weight))); // broadcast conjugate of w + const __m512i w_s1 = _mm512_set1_epi32(c16toI32(c16swap(prec_weight))); // broadcast swapped real and img of w + __m512i y = _mm512_set1_epi16(0); + for (; sc < sc_offset + (re_cnt_align16); sc += sizeof(__m512i) / sizeof(prec_weight)) { + + const __m512i x = _mm512_loadu_si512(&txdataF_res_mapped[0][sc]); + const __m512i x1 = _mm512_loadu_si512(&txdataF_res_mapped[1][sc]); + // Matrix multiplication for 4 elements of the result (sizeof(simde__m256i) / sizeof(*prec_matrix) = 8) + y=cmac0_prec512(x,w_c,w_s); + y=cmac_prec512(y,x1,w_c1,w_s1); + _mm512_storeu_si512(&txdataF_precoded[sc],y); + } + } + else if (n_layers==3) { + prec_weight.r = pmi_pdu->weights[0][ant].precoder_weight_Re; + prec_weight.i = pmi_pdu->weights[0][ant].precoder_weight_Im; + const __m512i w_c = _mm512_set1_epi32(c16toI32(c16conj(prec_weight))); // broadcast conjugate of w + const __m512i w_s = _mm512_set1_epi32(c16toI32(c16swap(prec_weight))); // broadcast swapped real and img of w + prec_weight.r = pmi_pdu->weights[1][ant].precoder_weight_Re; + prec_weight.i = pmi_pdu->weights[1][ant].precoder_weight_Im; + const __m512i w_c1 = _mm512_set1_epi32(c16toI32(c16conj(prec_weight))); // broadcast conjugate of w + const __m512i w_s1 = _mm512_set1_epi32(c16toI32(c16swap(prec_weight))); // broadcast swapped real and img of w + prec_weight.r = pmi_pdu->weights[2][ant].precoder_weight_Re; + prec_weight.i = pmi_pdu->weights[2][ant].precoder_weight_Im; + const __m512i w_c2 = _mm512_set1_epi32(c16toI32(c16conj(prec_weight))); // broadcast conjugate of w + const __m512i w_s2 = _mm512_set1_epi32(c16toI32(c16swap(prec_weight))); // broadcast swapped real and img of w + __m512i y = _mm512_set1_epi16(0); + for (; sc < sc_offset + (re_cnt_align16); sc += sizeof(__m512i) / sizeof(prec_weight)) { + + const __m512i x = _mm512_loadu_si512(&txdataF_res_mapped[0][sc]); + const __m512i x1 = _mm512_loadu_si512(&txdataF_res_mapped[1][sc]); + const __m512i x2 = _mm512_loadu_si512(&txdataF_res_mapped[2][sc]); + // Matrix multiplication for 4 elements of the result (sizeof(simde__m256i) / sizeof(*prec_matrix) = 8) + y=cmac0_prec512(x,w_c,w_s); + y=cmac_prec512(y,x1,w_c1,w_s1); + y=cmac_prec512(y,x2,w_c2,w_s2); + _mm512_storeu_si512(&txdataF_precoded[sc],y); + } + } + else if (n_layers==4) { + prec_weight.r = pmi_pdu->weights[0][ant].precoder_weight_Re; + prec_weight.i = pmi_pdu->weights[0][ant].precoder_weight_Im; + const __m512i w_c = _mm512_set1_epi32(c16toI32(c16conj(prec_weight))); // broadcast conjugate of w + const __m512i w_s = _mm512_set1_epi32(c16toI32(c16swap(prec_weight))); // broadcast swapped real and img of w + prec_weight.r = pmi_pdu->weights[1][ant].precoder_weight_Re; + prec_weight.i = pmi_pdu->weights[1][ant].precoder_weight_Im; + const __m512i w_c1 = _mm512_set1_epi32(c16toI32(c16conj(prec_weight))); // broadcast conjugate of w + const __m512i w_s1 = _mm512_set1_epi32(c16toI32(c16swap(prec_weight))); // broadcast swapped real and img of w + prec_weight.r = pmi_pdu->weights[2][ant].precoder_weight_Re; + prec_weight.i = pmi_pdu->weights[2][ant].precoder_weight_Im; + const __m512i w_c2 = _mm512_set1_epi32(c16toI32(c16conj(prec_weight))); // broadcast conjugate of w + const __m512i w_s2 = _mm512_set1_epi32(c16toI32(c16swap(prec_weight))); // broadcast swapped real and img of w + prec_weight.r = pmi_pdu->weights[3][ant].precoder_weight_Re; + prec_weight.i = pmi_pdu->weights[3][ant].precoder_weight_Im; + const __m512i w_c3 = _mm512_set1_epi32(c16toI32(c16conj(prec_weight))); // broadcast conjugate of w + const __m512i w_s3 = _mm512_set1_epi32(c16toI32(c16swap(prec_weight))); // broadcast swapped real and img of w + __m512i y = _mm512_set1_epi16(0); + for (; sc < sc_offset + (re_cnt_align16); sc += sizeof(__m512i) / sizeof(prec_weight)) { + + const __m512i x = _mm512_loadu_si512(&txdataF_res_mapped[0][sc]); + const __m512i x1 = _mm512_loadu_si512(&txdataF_res_mapped[1][sc]); + const __m512i x2 = _mm512_loadu_si512(&txdataF_res_mapped[2][sc]); + const __m512i x3 = _mm512_loadu_si512(&txdataF_res_mapped[3][sc]); + // Matrix multiplication for 4 elements of the result (sizeof(simde__m256i) / sizeof(*prec_matrix) = 8) + y=cmac0_prec512(x,w_c,w_s); + y=cmac_prec512(y,x1,w_c1,w_s1); + y=cmac_prec512(y,x2,w_c2,w_s2); + y=cmac_prec512(y,x3,w_c3,w_s3); + _mm512_storeu_si512(&txdataF_precoded[sc],y); + } + } + /* + const uint32_t re_cnt_align16 = re_cnt & ~15; + for (; sc < sc_offset + (re_cnt_align16); sc += sizeof(simde__m256i) / sizeof(prec_weight)) { + // Matrix multiplication for 4 elements of the result (sizeof(simde__m256i) / sizeof(*prec_matrix) = 8) + + __m512i y = _mm512_set1_epi16(0); // Y = W[0]*X[0] + W[1]*X[1] + ... + W[nrOfLayers-1]*X[nrOfLayers-1] + for (int nl = 0; nl < n_layers; nl++) { + prec_weight.r = pmi_pdu->weights[nl][ant].precoder_weight_Re; + prec_weight.i = pmi_pdu->weights[nl][ant].precoder_weight_Im; + + const __m512i x = _mm512_loadu_si512(&txdataF_res_mapped[nl][sc]); + + // Rearrange precoding matrix weight to match complex multiplication and broadcast it to match SIMD size + const __m512i w_c = _mm512_set1_epi32(c16toI32(c16conj(prec_weight))); // broadcast conjugate of w + const __m512i w_s = _mm512_set1_epi32(c16toI32(c16swap(prec_weight))); // broadcast swapped real and img of w + + // Multiplication and shift + const __m512i reals = + _mm512_srai_epi32(_mm512_madd_epi16(x, w_c), 15); // (int32_t) .r = (x.r * w.r - x.i * w.i) >> 15 + const __m512i imags = + _mm512_slli_epi32(_mm512_madd_epi16(x, w_s), 1); // (int32_t) .i = (x.r * w.i + x.i * w.r) << 1, since higher 16 bit of each 32 bit is taken by blend_epi16 + + // Re-arrange to match c16_t format + const __m512i produ = _mm512_mask_blend_epi16(0xAAAAAAAA,reals, imags); + + // Accumulate the product + y = _mm512_adds_epi16(y, produ); + } + // Store the result to txdataF + _mm512_storeu_si512(&txdataF_precoded[sc], y); + } + */ +#endif #ifdef __AVX2__ const uint32_t re_cnt_align8 = re_cnt & ~7; for (; sc < sc_offset + (re_cnt_align8); sc += sizeof(simde__m256i) / sizeof(prec_weight)) { // Matrix multiplication for 4 elements of the result (sizeof(simde__m256i) / sizeof(*prec_matrix) = 8) + simde__m256i y = simde_mm256_set1_epi16(0); // Y = W[0]*X[0] + W[1]*X[1] + ... + W[nrOfLayers-1]*X[nrOfLayers-1] for (int nl = 0; nl < n_layers; nl++) { prec_weight.r = pmi_pdu->weights[nl][ant].precoder_weight_Re; @@ -763,7 +906,6 @@ void nr_layer_precoder_simd(const int n_layers, simde_mm256_storeu_si256(&txdataF_precoded[sc], y); } #endif - // 128 SIMD: Do 4 RE in one iteration, 3 iterations for 1 RB const uint32_t re_cnt_align4 = re_cnt & ~3; for (; sc < sc_offset + re_cnt_align4; sc += sizeof(simde__m128i) / sizeof(prec_weight)) { @@ -773,7 +915,9 @@ void nr_layer_precoder_simd(const int n_layers, y_triv[i] = nr_layer_precoder_cm(n_layers, symSz, txdataF_res_mapped, ant, pmi_pdu, sc + i); memcpy(&txdataF_precoded[sc], y_triv, sizeof(y_triv)); #endif +#ifdef __aarch64__ +#else // Matrix multiplication for 4 elements of the result (sizeof(simde__m128i) / sizeof(c16_t) = 4) simde__m128i y = simde_mm_set1_epi16(0); // Y = W[0]*X[0] + W[1]*X[1] + ... + W[nrOfLayers-1]*X[nrOfLayers-1] for (int nl = 0; nl < n_layers; nl++) { @@ -808,7 +952,7 @@ void nr_layer_precoder_simd(const int n_layers, } // Store the result to txdataF simde_mm_storeu_si128(&txdataF_precoded[sc], y); - +#endif #ifdef DEBUG_DLSCH_PRECODING_PRINT_WITH_TRIVIAL // Print simd and trivial result, TODO: To be removed c16_t *y_simd = (c16_t *)&y; printf("debug_to_be_removed re_cnt=%d, sc=%u, y_simd=(%+4d,%+4d), (%+4d,%+4d), (%+4d,%+4d), (%+4d,%+4d)\n", From e44d498cbad4efd0f5edd70e167be41e13022b4d Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Fri, 29 Aug 2025 17:38:56 +0200 Subject: [PATCH 923/964] optimization of DLSCH precoding for AVX2 --- openair1/PHY/MODULATION/nr_modulation.c | 158 ++++++++++++++++-------- 1 file changed, 104 insertions(+), 54 deletions(-) diff --git a/openair1/PHY/MODULATION/nr_modulation.c b/openair1/PHY/MODULATION/nr_modulation.c index 9b6103edd8..7f230cf420 100644 --- a/openair1/PHY/MODULATION/nr_modulation.c +++ b/openair1/PHY/MODULATION/nr_modulation.c @@ -746,6 +746,34 @@ static inline __attribute__((always_inline)) __m512i cmac_prec512(__m512i y, __m return _mm512_adds_epi16(y, produ); } #endif +#ifdef __AVX2__ +static inline __attribute__((always_inline)) __m256i cmac0_prec256(__m256i x, __m256i w_c, __m256i w_s) { + + // Multiplication and shift + const __m256i reals = + _mm256_srai_epi32(_mm256_madd_epi16(x, w_c), 15); // (int32_t) .r = (x.r * w.r - x.i * w.i) >> 15 + const __m256i imags = + _mm256_slli_epi32(_mm256_madd_epi16(x, w_s), 1); // (int32_t) .i = (x.r * w.i + x.i * w.r) << 1, since higher 16 bit of each 32 bit is taken by blend_epi16 + + // Re-arrange to match c16_t format + return _mm256_blend_epi16(reals, imags,0xAA); + +} +static inline __attribute__((always_inline)) __m256i cmac_prec256(__m256i y, __m256i x, __m256i w_c, __m256i w_s) { + + // Multiplication and shift + const __m256i reals = + _mm256_srai_epi32(_mm256_madd_epi16(x, w_c), 15); // (int32_t) .r = (x.r * w.r - x.i * w.i) >> 15 + const __m256i imags = + _mm256_slli_epi32(_mm256_madd_epi16(x, w_s), 1); // (int32_t) .i = (x.r * w.i + x.i * w.r) << 1, since higher 16 bit of each 32 bit is taken by blend_epi16 + + // Re-arrange to match c16_t format + const __m256i produ = _mm256_blend_epi16(reals, imags,0xAA); + + // Accumulate the product + return _mm256_adds_epi16(y, produ); +} +#endif void nr_layer_precoder_simd(const int n_layers, const int symSz, const c16_t txdataF_res_mapped[n_layers][symSz], @@ -841,70 +869,92 @@ void nr_layer_precoder_simd(const int n_layers, _mm512_storeu_si512(&txdataF_precoded[sc],y); } } - /* - const uint32_t re_cnt_align16 = re_cnt & ~15; - for (; sc < sc_offset + (re_cnt_align16); sc += sizeof(simde__m256i) / sizeof(prec_weight)) { - // Matrix multiplication for 4 elements of the result (sizeof(simde__m256i) / sizeof(*prec_matrix) = 8) - - __m512i y = _mm512_set1_epi16(0); // Y = W[0]*X[0] + W[1]*X[1] + ... + W[nrOfLayers-1]*X[nrOfLayers-1] - for (int nl = 0; nl < n_layers; nl++) { - prec_weight.r = pmi_pdu->weights[nl][ant].precoder_weight_Re; - prec_weight.i = pmi_pdu->weights[nl][ant].precoder_weight_Im; - - const __m512i x = _mm512_loadu_si512(&txdataF_res_mapped[nl][sc]); - - // Rearrange precoding matrix weight to match complex multiplication and broadcast it to match SIMD size - const __m512i w_c = _mm512_set1_epi32(c16toI32(c16conj(prec_weight))); // broadcast conjugate of w - const __m512i w_s = _mm512_set1_epi32(c16toI32(c16swap(prec_weight))); // broadcast swapped real and img of w - - // Multiplication and shift - const __m512i reals = - _mm512_srai_epi32(_mm512_madd_epi16(x, w_c), 15); // (int32_t) .r = (x.r * w.r - x.i * w.i) >> 15 - const __m512i imags = - _mm512_slli_epi32(_mm512_madd_epi16(x, w_s), 1); // (int32_t) .i = (x.r * w.i + x.i * w.r) << 1, since higher 16 bit of each 32 bit is taken by blend_epi16 - - // Re-arrange to match c16_t format - const __m512i produ = _mm512_mask_blend_epi16(0xAAAAAAAA,reals, imags); - - // Accumulate the product - y = _mm512_adds_epi16(y, produ); - } - // Store the result to txdataF - _mm512_storeu_si512(&txdataF_precoded[sc], y); - } - */ + else AssertFatal(1==0,"Shouldn't get here, n_layers %d\n",n_layers); #endif #ifdef __AVX2__ const uint32_t re_cnt_align8 = re_cnt & ~7; - for (; sc < sc_offset + (re_cnt_align8); sc += sizeof(simde__m256i) / sizeof(prec_weight)) { - // Matrix multiplication for 4 elements of the result (sizeof(simde__m256i) / sizeof(*prec_matrix) = 8) + if (n_layers==2) { simde__m256i y = simde_mm256_set1_epi16(0); // Y = W[0]*X[0] + W[1]*X[1] + ... + W[nrOfLayers-1]*X[nrOfLayers-1] - for (int nl = 0; nl < n_layers; nl++) { - prec_weight.r = pmi_pdu->weights[nl][ant].precoder_weight_Re; - prec_weight.i = pmi_pdu->weights[nl][ant].precoder_weight_Im; + prec_weight.r = pmi_pdu->weights[0][ant].precoder_weight_Re; + prec_weight.i = pmi_pdu->weights[0][ant].precoder_weight_Im; + const simde__m256i w_c0 = simde_mm256_set1_epi32(c16toI32(c16conj(prec_weight))); // broadcast conjugate of w + const simde__m256i w_s0 = simde_mm256_set1_epi32(c16toI32(c16swap(prec_weight))); // broadcast swapped real and img of w + prec_weight.r = pmi_pdu->weights[1][ant].precoder_weight_Re; + prec_weight.i = pmi_pdu->weights[1][ant].precoder_weight_Im; + const simde__m256i w_c1 = simde_mm256_set1_epi32(c16toI32(c16conj(prec_weight))); // broadcast conjugate of w + const simde__m256i w_s1 = simde_mm256_set1_epi32(c16toI32(c16swap(prec_weight))); // broadcast swapped real and img of w - const simde__m256i x = simde_mm256_loadu_si256(&txdataF_res_mapped[nl][sc]); - - // Rearrange precoding matrix weight to match complex multiplication and broadcast it to match SIMD size - const simde__m256i w_c = simde_mm256_set1_epi32(c16toI32(c16conj(prec_weight))); // broadcast conjugate of w - const simde__m256i w_s = simde_mm256_set1_epi32(c16toI32(c16swap(prec_weight))); // broadcast swapped real and img of w - - // Multiplication and shift - const simde__m256i reals = - simde_mm256_srai_epi32(simde_mm256_madd_epi16(x, w_c), 15); // (int32_t) .r = (x.r * w.r - x.i * w.i) >> 15 - const simde__m256i imags = - simde_mm256_slli_epi32(simde_mm256_madd_epi16(x, w_s), 1); // (int32_t) .i = (x.r * w.i + x.i * w.r) << 1, since higher 16 bit of each 32 bit is taken by blend_epi16 - - // Re-arrange to match c16_t format - const simde__m256i produ = simde_mm256_blend_epi16(reals, imags, 0xAA); + for (; sc < sc_offset + (re_cnt_align8); sc += sizeof(simde__m256i) / sizeof(prec_weight)) { + const simde__m256i x0 = simde_mm256_loadu_si256(&txdataF_res_mapped[0][sc]); + const simde__m256i x1 = simde_mm256_loadu_si256(&txdataF_res_mapped[1][sc]); // Accumulate the product - y = simde_mm256_adds_epi16(y, produ); + y = cmac0_prec256(x0,w_c0,w_s0); + y = cmac_prec256(y,x1,w_c1,w_s1); + // Store the result to txdataF + simde_mm256_storeu_si256(&txdataF_precoded[sc], y); } - // Store the result to txdataF - simde_mm256_storeu_si256(&txdataF_precoded[sc], y); } + else if (n_layers==3) { + simde__m256i y = simde_mm256_set1_epi16(0); // Y = W[0]*X[0] + W[1]*X[1] + ... + W[nrOfLayers-1]*X[nrOfLayers-1] + prec_weight.r = pmi_pdu->weights[0][ant].precoder_weight_Re; + prec_weight.i = pmi_pdu->weights[0][ant].precoder_weight_Im; + const simde__m256i w_c0 = simde_mm256_set1_epi32(c16toI32(c16conj(prec_weight))); // broadcast conjugate of w + const simde__m256i w_s0 = simde_mm256_set1_epi32(c16toI32(c16swap(prec_weight))); // broadcast swapped real and img of w + prec_weight.r = pmi_pdu->weights[1][ant].precoder_weight_Re; + prec_weight.i = pmi_pdu->weights[1][ant].precoder_weight_Im; + const simde__m256i w_c1 = simde_mm256_set1_epi32(c16toI32(c16conj(prec_weight))); // broadcast conjugate of w + const simde__m256i w_s1 = simde_mm256_set1_epi32(c16toI32(c16swap(prec_weight))); // broadcast swapped real and img of w + prec_weight.r = pmi_pdu->weights[2][ant].precoder_weight_Re; + prec_weight.i = pmi_pdu->weights[2][ant].precoder_weight_Im; + const simde__m256i w_c2 = simde_mm256_set1_epi32(c16toI32(c16conj(prec_weight))); // broadcast conjugate of w + const simde__m256i w_s2 = simde_mm256_set1_epi32(c16toI32(c16swap(prec_weight))); // broadcast swapped real and img of w + + for (; sc < sc_offset + (re_cnt_align8); sc += sizeof(simde__m256i) / sizeof(prec_weight)) { + const simde__m256i x0 = simde_mm256_loadu_si256(&txdataF_res_mapped[0][sc]); + const simde__m256i x1 = simde_mm256_loadu_si256(&txdataF_res_mapped[1][sc]); + const simde__m256i x2 = simde_mm256_loadu_si256(&txdataF_res_mapped[2][sc]); + y = cmac0_prec256(x0,w_c0,w_s0); + y = cmac_prec256(y,x1,w_c1,w_s1); + y = cmac_prec256(y,x2,w_c2,w_s2); + // Store the result to txdataF + simde_mm256_storeu_si256(&txdataF_precoded[sc], y); + } + } + else if (n_layers==4) { + simde__m256i y = simde_mm256_set1_epi16(0); // Y = W[0]*X[0] + W[1]*X[1] + ... + W[nrOfLayers-1]*X[nrOfLayers-1] + prec_weight.r = pmi_pdu->weights[0][ant].precoder_weight_Re; + prec_weight.i = pmi_pdu->weights[0][ant].precoder_weight_Im; + const simde__m256i w_c0 = simde_mm256_set1_epi32(c16toI32(c16conj(prec_weight))); // broadcast conjugate of w + const simde__m256i w_s0 = simde_mm256_set1_epi32(c16toI32(c16swap(prec_weight))); // broadcast swapped real and img of w + prec_weight.r = pmi_pdu->weights[1][ant].precoder_weight_Re; + prec_weight.i = pmi_pdu->weights[1][ant].precoder_weight_Im; + const simde__m256i w_c1 = simde_mm256_set1_epi32(c16toI32(c16conj(prec_weight))); // broadcast conjugate of w + const simde__m256i w_s1 = simde_mm256_set1_epi32(c16toI32(c16swap(prec_weight))); // broadcast swapped real and img of w + prec_weight.r = pmi_pdu->weights[2][ant].precoder_weight_Re; + prec_weight.i = pmi_pdu->weights[2][ant].precoder_weight_Im; + const simde__m256i w_c2 = simde_mm256_set1_epi32(c16toI32(c16conj(prec_weight))); // broadcast conjugate of w + const simde__m256i w_s2 = simde_mm256_set1_epi32(c16toI32(c16swap(prec_weight))); // broadcast swapped real and img of w + + prec_weight.r = pmi_pdu->weights[3][ant].precoder_weight_Re; + prec_weight.i = pmi_pdu->weights[3][ant].precoder_weight_Im; + const simde__m256i w_c3 = simde_mm256_set1_epi32(c16toI32(c16conj(prec_weight))); // broadcast conjugate of w + const simde__m256i w_s3 = simde_mm256_set1_epi32(c16toI32(c16swap(prec_weight))); // broadcast swapped real and img of w + for (; sc < sc_offset + (re_cnt_align8); sc += sizeof(simde__m256i) / sizeof(prec_weight)) { + const simde__m256i x0 = simde_mm256_loadu_si256(&txdataF_res_mapped[0][sc]); + const simde__m256i x1 = simde_mm256_loadu_si256(&txdataF_res_mapped[1][sc]); + const simde__m256i x2 = simde_mm256_loadu_si256(&txdataF_res_mapped[2][sc]); + const simde__m256i x3 = simde_mm256_loadu_si256(&txdataF_res_mapped[3][sc]); + y = cmac0_prec256(x0,w_c0,w_s0); + y = cmac_prec256(y,x1,w_c1,w_s1); + y = cmac_prec256(y,x2,w_c2,w_s2); + y = cmac_prec256(y,x3,w_c3,w_s3); + // Store the result to txdataF + simde_mm256_storeu_si256(&txdataF_precoded[sc], y); + } + } + else AssertFatal(1==0,"Shouldn't get here, n_layers %d\n",n_layers); #endif // 128 SIMD: Do 4 RE in one iteration, 3 iterations for 1 RB const uint32_t re_cnt_align4 = re_cnt & ~3; From 264f7cb817e6551b5c8d5ae177a932fed4f46594 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Sat, 30 Aug 2025 11:02:59 +0000 Subject: [PATCH 924/964] aarch64 optimizations for precoding, more complete timing reporting in nr_dlsim --- openair1/PHY/MODULATION/nr_modulation.c | 121 ++++++++++++++++++++++++ 1 file changed, 121 insertions(+) diff --git a/openair1/PHY/MODULATION/nr_modulation.c b/openair1/PHY/MODULATION/nr_modulation.c index 7f230cf420..e1548787ec 100644 --- a/openair1/PHY/MODULATION/nr_modulation.c +++ b/openair1/PHY/MODULATION/nr_modulation.c @@ -774,6 +774,42 @@ static inline __attribute__((always_inline)) __m256i cmac_prec256(__m256i y, __m return _mm256_adds_epi16(y, produ); } #endif +#ifdef __aarch64__ +static inline __attribute__((always_inline)) int16x8_t cmac0_prec128(int16x8_t x, int16x8_t wr, int16x8_t wi) { + // + int16x8_t xr = vuzp1q_s16(x, x); // even lanes + int16x8_t xi = vuzp2q_s16(x, x); // odd lanes + // real = ar*br - ai*bi (Q15 scaling via high-half doubling muls) + int16x8_t real = vqdmulhq_s16(xr, wr); // ≈ round((2*xr*wr)/2^16) + real = vqrdmlshq_s16(real, xi, wi); // real -= round((2*xi*wi)/2^16) + // + // imag = ar*bi + ai*br + int16x8_t imag = vqdmulhq_s16(xr, wi); + imag = vqrdmlahq_s16(imag, xi, wr); // imag += round((2*xi*wr)/2^16) + // + // Re-interleave [real, imag] + int16x8x2_t produ = vzipq_s16(real, imag); + return produ.val[0]; +} +static inline __attribute__((always_inline)) int16x8_t cmac_prec128(int16x8_t y, int16x8_t x, int16x8_t wr, int16x8_t wi) { + // De-interleave real/imag + int16x8_t xr = vuzp1q_s16(x, x); // even lanes + int16x8_t xi = vuzp2q_s16(x, x); // odd lanes + // + // real = ar*br - ai*bi (Q15 scaling via high-half doubling muls) + int16x8_t real = vqdmulhq_s16(xr, wr); // ≈ round((2*ar*br)/2^16) + real = vqrdmlshq_s16(real, xi, wi); // real -= round((2*ai*bi)/2^16) + // + // imag = ar*bi + ai*br + int16x8_t imag = vqdmulhq_s16(xr, wi); + imag = vqrdmlahq_s16(imag, xi, wr); // imag += round((2*ai*br)/2^16) + // + // Re-interleave [real, imag] + int16x8x2_t produ = vzipq_s16(real, imag); + return vaddq_s16(y,produ.val[0]); +} +#endif + void nr_layer_precoder_simd(const int n_layers, const int symSz, const c16_t txdataF_res_mapped[n_layers][symSz], @@ -967,6 +1003,91 @@ void nr_layer_precoder_simd(const int n_layers, #endif #ifdef __aarch64__ + const uint32_t re_cnt_align8 = re_cnt & ~3; + if (n_layers==2) { + + prec_weight.r = pmi_pdu->weights[0][ant].precoder_weight_Re; + prec_weight.i = pmi_pdu->weights[0][ant].precoder_weight_Im; + const int16x8_t wr0 = vdupq_n_s16(prec_weight.r); + const int16x8_t wi0 = vdupq_n_s16(prec_weight.i); + prec_weight.r = pmi_pdu->weights[1][ant].precoder_weight_Re; + prec_weight.i = pmi_pdu->weights[1][ant].precoder_weight_Im; + const int16x8_t wr1 = vdupq_n_s16(prec_weight.r); + const int16x8_t wi1 = vdupq_n_s16(prec_weight.i); + int16x8_t y; + + for (; sc < sc_offset + (re_cnt_align8); sc += sizeof(int16x8_t) / sizeof(prec_weight)) { + const int16x8_t x0 = vld1q_s16((const int16_t*)&txdataF_res_mapped[0][sc]); + const int16x8_t x1 = vld1q_s16((const int16_t*)&txdataF_res_mapped[1][sc]); + // Accumulate the product + y = cmac0_prec128(x0,wr0,wi0); + y = cmac_prec128(y,x1,wr1,wi1); + // Store the result to txdataF + *((int16x8_t*)&txdataF_precoded[sc])= y; + } + } + if (n_layers==3) { + + prec_weight.r = pmi_pdu->weights[0][ant].precoder_weight_Re; + prec_weight.i = pmi_pdu->weights[0][ant].precoder_weight_Im; + const int16x8_t wr0 = vdupq_n_s16(prec_weight.r); + const int16x8_t wi0 = vdupq_n_s16(prec_weight.i); + prec_weight.r = pmi_pdu->weights[1][ant].precoder_weight_Re; + prec_weight.i = pmi_pdu->weights[1][ant].precoder_weight_Im; + const int16x8_t wr1 = vdupq_n_s16(prec_weight.r); + const int16x8_t wi1 = vdupq_n_s16(prec_weight.i); + prec_weight.r = pmi_pdu->weights[2][ant].precoder_weight_Re; + prec_weight.i = pmi_pdu->weights[2][ant].precoder_weight_Im; + const int16x8_t wr2 = vdupq_n_s16(prec_weight.r); + const int16x8_t wi2 = vdupq_n_s16(prec_weight.i); + int16x8_t y; + + for (; sc < sc_offset + (re_cnt_align8); sc += sizeof(int16x8_t) / sizeof(prec_weight)) { + const int16x8_t x0 = vld1q_s16((const int16_t*)&txdataF_res_mapped[0][sc]); + const int16x8_t x1 = vld1q_s16((const int16_t*)&txdataF_res_mapped[1][sc]); + const int16x8_t x2 = vld1q_s16((const int16_t*)&txdataF_res_mapped[2][sc]); + // Accumulate the product + y = cmac0_prec128(x0,wr0,wi0); + y = cmac_prec128(y,x1,wr1,wi1); + y = cmac_prec128(y,x2,wr2,wi2); + // Store the result to txdataF + *((int16x8_t*)&txdataF_precoded[sc])= y; + } + } + if (n_layers==4) { + + prec_weight.r = pmi_pdu->weights[0][ant].precoder_weight_Re; + prec_weight.i = pmi_pdu->weights[0][ant].precoder_weight_Im; + const int16x8_t wr0 = vdupq_n_s16(prec_weight.r); + const int16x8_t wi0 = vdupq_n_s16(prec_weight.i); + prec_weight.r = pmi_pdu->weights[1][ant].precoder_weight_Re; + prec_weight.i = pmi_pdu->weights[1][ant].precoder_weight_Im; + const int16x8_t wr1 = vdupq_n_s16(prec_weight.r); + const int16x8_t wi1 = vdupq_n_s16(prec_weight.i); + prec_weight.r = pmi_pdu->weights[2][ant].precoder_weight_Re; + prec_weight.i = pmi_pdu->weights[2][ant].precoder_weight_Im; + const int16x8_t wr2 = vdupq_n_s16(prec_weight.r); + const int16x8_t wi2 = vdupq_n_s16(prec_weight.i); + prec_weight.r = pmi_pdu->weights[3][ant].precoder_weight_Re; + prec_weight.i = pmi_pdu->weights[3][ant].precoder_weight_Im; + const int16x8_t wr3 = vdupq_n_s16(prec_weight.r); + const int16x8_t wi3 = vdupq_n_s16(prec_weight.i); + int16x8_t y; + + for (; sc < sc_offset + (re_cnt_align8); sc += sizeof(int16x8_t) / sizeof(prec_weight)) { + const int16x8_t x0 = vld1q_s16((const int16_t*)&txdataF_res_mapped[0][sc]); + const int16x8_t x1 = vld1q_s16((const int16_t*)&txdataF_res_mapped[1][sc]); + const int16x8_t x2 = vld1q_s16((const int16_t*)&txdataF_res_mapped[2][sc]); + const int16x8_t x3 = vld1q_s16((const int16_t*)&txdataF_res_mapped[3][sc]); + // Accumulate the product + y = cmac0_prec128(x0,wr0,wi0); + y = cmac_prec128(y,x1,wr1,wi1); + y = cmac_prec128(y,x2,wr2,wi2); + y = cmac_prec128(y,x3,wr3,wi3); + // Store the result to txdataF + *((int16x8_t*)&txdataF_precoded[sc])= y; + } + } #else // Matrix multiplication for 4 elements of the result (sizeof(simde__m128i) / sizeof(c16_t) = 4) simde__m128i y = simde_mm_set1_epi16(0); // Y = W[0]*X[0] + W[1]*X[1] + ... + W[nrOfLayers-1]*X[nrOfLayers-1] From fb47748faeee7faded53be0139ac4548dc07eb4d Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Mon, 1 Sep 2025 17:40:07 +0200 Subject: [PATCH 925/964] fixed precoder_simd after CI run (test for n_layers=1) failed --- openair1/PHY/MODULATION/nr_modulation.c | 50 ++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 2 deletions(-) diff --git a/openair1/PHY/MODULATION/nr_modulation.c b/openair1/PHY/MODULATION/nr_modulation.c index e1548787ec..b641ceaad1 100644 --- a/openair1/PHY/MODULATION/nr_modulation.c +++ b/openair1/PHY/MODULATION/nr_modulation.c @@ -827,7 +827,21 @@ void nr_layer_precoder_simd(const int n_layers, // 512/256 SIMD: Do 16/8 RE in one iteration, 3 iterations for 2 RB #if defined(__AVX512F__) && defined(__AVX512BW__) const uint32_t re_cnt_align16 = re_cnt & ~15; - if (n_layers==2) { + if (n_layers==1) { + prec_weight.r = pmi_pdu->weights[0][ant].precoder_weight_Re; + prec_weight.i = pmi_pdu->weights[0][ant].precoder_weight_Im; + const __m512i w_c = _mm512_set1_epi32(c16toI32(c16conj(prec_weight))); // broadcast conjugate of w + const __m512i w_s = _mm512_set1_epi32(c16toI32(c16swap(prec_weight))); // broadcast swapped real and img of w + __m512i y = _mm512_set1_epi16(0); + for (; sc < sc_offset + (re_cnt_align16); sc += sizeof(__m512i) / sizeof(prec_weight)) { + + const __m512i x = _mm512_loadu_si512(&txdataF_res_mapped[0][sc]); + // Matrix multiplication for 4 elements of the result (sizeof(simde__m256i) / sizeof(*prec_matrix) = 8) + y=cmac0_prec512(x,w_c,w_s); + _mm512_storeu_si512(&txdataF_precoded[sc],y); + } + } + else if (n_layers==2) { prec_weight.r = pmi_pdu->weights[0][ant].precoder_weight_Re; prec_weight.i = pmi_pdu->weights[0][ant].precoder_weight_Im; const __m512i w_c = _mm512_set1_epi32(c16toI32(c16conj(prec_weight))); // broadcast conjugate of w @@ -909,7 +923,23 @@ void nr_layer_precoder_simd(const int n_layers, #endif #ifdef __AVX2__ const uint32_t re_cnt_align8 = re_cnt & ~7; - if (n_layers==2) { + if (n_layers==1) { + + simde__m256i y = simde_mm256_set1_epi16(0); // Y = W[0]*X[0] + W[1]*X[1] + ... + W[nrOfLayers-1]*X[nrOfLayers-1] + prec_weight.r = pmi_pdu->weights[0][ant].precoder_weight_Re; + prec_weight.i = pmi_pdu->weights[0][ant].precoder_weight_Im; + const simde__m256i w_c0 = simde_mm256_set1_epi32(c16toI32(c16conj(prec_weight))); // broadcast conjugate of w + const simde__m256i w_s0 = simde_mm256_set1_epi32(c16toI32(c16swap(prec_weight))); // broadcast swapped real and img of w + + for (; sc < sc_offset + (re_cnt_align8); sc += sizeof(simde__m256i) / sizeof(prec_weight)) { + const simde__m256i x0 = simde_mm256_loadu_si256(&txdataF_res_mapped[0][sc]); + // Accumulate the product + y = cmac0_prec256(x0,w_c0,w_s0); + // Store the result to txdataF + simde_mm256_storeu_si256(&txdataF_precoded[sc], y); + } + } + else if (n_layers==2) { simde__m256i y = simde_mm256_set1_epi16(0); // Y = W[0]*X[0] + W[1]*X[1] + ... + W[nrOfLayers-1]*X[nrOfLayers-1] prec_weight.r = pmi_pdu->weights[0][ant].precoder_weight_Re; @@ -1004,6 +1034,22 @@ void nr_layer_precoder_simd(const int n_layers, #ifdef __aarch64__ const uint32_t re_cnt_align8 = re_cnt & ~3; + if (n_layers==1) { + + prec_weight.r = pmi_pdu->weights[0][ant].precoder_weight_Re; + prec_weight.i = pmi_pdu->weights[0][ant].precoder_weight_Im; + const int16x8_t wr0 = vdupq_n_s16(prec_weight.r); + const int16x8_t wi0 = vdupq_n_s16(prec_weight.i); + int16x8_t y; + + for (; sc < sc_offset + (re_cnt_align8); sc += sizeof(int16x8_t) / sizeof(prec_weight)) { + const int16x8_t x0 = vld1q_s16((const int16_t*)&txdataF_res_mapped[0][sc]); + // Accumulate the product + y = cmac0_prec128(x0,wr0,wi0); + // Store the result to txdataF + *((int16x8_t*)&txdataF_precoded[sc])= y; + } + } if (n_layers==2) { prec_weight.r = pmi_pdu->weights[0][ant].precoder_weight_Re; From e056acc896884f791679ba277eb098363d17f1c6 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Wed, 24 Sep 2025 12:30:55 +0200 Subject: [PATCH 926/964] use c16_t type for pm weights, as it is already same type simplify SIMD version of precoder --- nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c | 5 +- nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c | 13 +- .../nfapi/public_inc/nfapi_nr_interface_scf.h | 7 +- nfapi/tests/p5/nr_fapi_config_request_test.c | 4 +- openair1/PHY/MODULATION/nr_modulation.c | 641 +++++++----------- .../MODULATION/tests/test_nr_modulation.cpp | 12 +- openair2/LAYER2/NR_MAC_gNB/config.c | 14 +- 7 files changed, 282 insertions(+), 414 deletions(-) diff --git a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c index 4bcc9b2a44..c3e36d9999 100644 --- a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c +++ b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c @@ -760,7 +760,7 @@ static uint8_t pack_pm_table_tlv_value(void *tlv, uint8_t **ppWritePackedMsg, ui 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))) { + if (!(push16(pm_weight->r, ppWritePackedMsg, end) && push16(pm_weight->i, ppWritePackedMsg, end))) { return 0; } } @@ -1307,8 +1307,7 @@ static uint8_t unpack_pm_table_tlv_value(void *tlv, uint8_t **ppReadPackedMsg, u 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))) { + if (!(pulls16(ppReadPackedMsg, &pm_weight->r, end) && pulls16(ppReadPackedMsg, &pm_weight->i, end))) { return 0; } } 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 a810b199ff..5d1d0ba4e8 100644 --- a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c +++ b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c @@ -287,8 +287,8 @@ bool eq_config_request(const nfapi_nr_config_request_scf_t *unpacked_req, const 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_pm_weight->r, req_pm_weight->r); + EQ(unpacked_pm_weight->i, req_pm_weight->i); } } } @@ -848,10 +848,7 @@ void copy_config_request(const nfapi_nr_config_request_scf_t *src, nfapi_nr_conf 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; + dst_pmi_pdu->weights[j][k] = src_pmi_pdu->weights[j][k]; } } } @@ -1313,8 +1310,8 @@ void dump_config_request(const nfapi_nr_config_request_scf_t *msg) 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); + INDENTED_GENERIC_PRINT("Dig Beam Weight Real", "0x%02x", pm_weights->r); + INDENTED_GENERIC_PRINT("Dig Beam Weight Imaginary", "0x%02x", pm_weights->i); } } depth--; 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 a8ac3f73c1..754ef60e55 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 @@ -10,6 +10,7 @@ #define _NFAPI_NR_INTERFACE_SCF_H_ #include "stddef.h" +#include "common/platform_types.h" #include "nfapi_interface.h" #include "nfapi_nr_interface.h" @@ -488,11 +489,7 @@ typedef struct { } nfapi_nr_dbt_tlv_ve_t; // Table 3–62 Precoding matrix (PM) PDU (v.222.10.04) -typedef struct { - int16_t precoder_weight_Re; - int16_t precoder_weight_Im; -} nfapi_nr_pm_weights_t; - +typedef c16_t nfapi_nr_pm_weights_t; typedef struct { uint16_t pm_idx; diff --git a/nfapi/tests/p5/nr_fapi_config_request_test.c b/nfapi/tests/p5/nr_fapi_config_request_test.c index bfb3f7fa21..5a80a89f3d 100644 --- a/nfapi/tests/p5/nr_fapi_config_request_test.c +++ b/nfapi/tests/p5/nr_fapi_config_request_test.c @@ -239,8 +239,8 @@ static void fill_config_request_tlv_tdd_rand(nfapi_nr_config_request_scf_t *nfap 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); + pm_weight->r = (int16_t)rand16_range(1, 0xffff); + pm_weight->i = (int16_t)rand16_range(1, 0xffff); } } } diff --git a/openair1/PHY/MODULATION/nr_modulation.c b/openair1/PHY/MODULATION/nr_modulation.c index b641ceaad1..5888b17eb0 100644 --- a/openair1/PHY/MODULATION/nr_modulation.c +++ b/openair1/PHY/MODULATION/nr_modulation.c @@ -710,8 +710,7 @@ c16_t nr_layer_precoder_cm(int n_layers, { c16_t precodatatx_F = {0}; for (int al = 0; al < n_layers; al++) { - nfapi_nr_pm_weights_t *w = &pmi_pdu->weights[al][ap]; - c16_t prec_weight = {.r = w->precoder_weight_Re, .i = w->precoder_weight_Im}; + c16_t prec_weight = pmi_pdu->weights[al][ap]; precodatatx_F = c16maddShift(datatx_F_precoding[al][offset], prec_weight, precodatatx_F, 15); } return precodatatx_F; @@ -732,18 +731,9 @@ static inline __attribute__((always_inline)) __m512i cmac0_prec512(__m512i x, __ } static inline __attribute__((always_inline)) __m512i cmac_prec512(__m512i y, __m512i x, __m512i w_c, __m512i w_s) { - - // Multiplication and shift - const __m512i reals = - _mm512_srai_epi32(_mm512_madd_epi16(x, w_c), 15); // (int32_t) .r = (x.r * w.r - x.i * w.i) >> 15 - const __m512i imags = - _mm512_slli_epi32(_mm512_madd_epi16(x, w_s), 1); // (int32_t) .i = (x.r * w.i + x.i * w.r) << 1, since higher 16 bit of each 32 bit is taken by blend_epi16 - - // Re-arrange to match c16_t format - const __m512i produ = _mm512_mask_blend_epi16(0xAAAAAAAA,reals, imags); - - // Accumulate the product - return _mm512_adds_epi16(y, produ); + const __m512i produ = cmac0_prec512(x, w_c, w_s); + // Accumulate the product + return _mm512_adds_epi16(y, produ); } #endif #ifdef __AVX2__ @@ -760,18 +750,9 @@ static inline __attribute__((always_inline)) __m256i cmac0_prec256(__m256i x, __ } static inline __attribute__((always_inline)) __m256i cmac_prec256(__m256i y, __m256i x, __m256i w_c, __m256i w_s) { - - // Multiplication and shift - const __m256i reals = - _mm256_srai_epi32(_mm256_madd_epi16(x, w_c), 15); // (int32_t) .r = (x.r * w.r - x.i * w.i) >> 15 - const __m256i imags = - _mm256_slli_epi32(_mm256_madd_epi16(x, w_s), 1); // (int32_t) .i = (x.r * w.i + x.i * w.r) << 1, since higher 16 bit of each 32 bit is taken by blend_epi16 - - // Re-arrange to match c16_t format - const __m256i produ = _mm256_blend_epi16(reals, imags,0xAA); - - // Accumulate the product - return _mm256_adds_epi16(y, produ); + const __m256i produ = cmac0_prec256(x, w_c, w_s); + // Accumulate the product + return _mm256_adds_epi16(y, produ); } #endif #ifdef __aarch64__ @@ -792,24 +773,41 @@ static inline __attribute__((always_inline)) int16x8_t cmac0_prec128(int16x8_t x return produ.val[0]; } static inline __attribute__((always_inline)) int16x8_t cmac_prec128(int16x8_t y, int16x8_t x, int16x8_t wr, int16x8_t wi) { - // De-interleave real/imag - int16x8_t xr = vuzp1q_s16(x, x); // even lanes - int16x8_t xi = vuzp2q_s16(x, x); // odd lanes - // - // real = ar*br - ai*bi (Q15 scaling via high-half doubling muls) - int16x8_t real = vqdmulhq_s16(xr, wr); // ≈ round((2*ar*br)/2^16) - real = vqrdmlshq_s16(real, xi, wi); // real -= round((2*ai*bi)/2^16) - // - // imag = ar*bi + ai*br - int16x8_t imag = vqdmulhq_s16(xr, wi); - imag = vqrdmlahq_s16(imag, xi, wr); // imag += round((2*ai*br)/2^16) - // - // Re-interleave [real, imag] - int16x8x2_t produ = vzipq_s16(real, imag); - return vaddq_s16(y,produ.val[0]); + int16x8_t produ = cmac0_prec128(x, wr, wi); + return vaddq_s16(y, produ.val[0]); +} +#else +static inline __attribute__((always_inline)) simde__m128i cmac0_prec128(simde__m128i x, simde__m128i w_c, simde__m128i w_s) +{ + // Multiplication and shift + const simde__m128i reals = simde_mm_srai_epi32(simde_mm_madd_epi16(x, w_c), 15); // (int32_t) .r = (x.r * w.r - x.i * w.i) >> 15 + const simde__m128i imags = simde_mm_slli_epi32( + simde_mm_madd_epi16(x, w_s), + 1); // (int32_t) .i = (x.r * w.i + x.i * w.r) << 1, since higher 16 bit of each 32 bit is taken by blend_epi16 + + /* Re-arrange to match c16_t format + bit index: 0 | 16 | 32 | 48 | 64 | 80 | 96 | 112 + reals = {R0.r[15..30] | R0.r[31] (0)*15 | R1.r[15..30] | R1.r[31] (0)*15 | R2.r[15..30] | R2.r[31] (0)*15 | R3.r[15..30] + | R3.r[31] (0)*15} imags = {0 R0.i[0..14]| R0.i[15..30] | 0 R1.i[0..14]| R1.i[15..30] | 0 R2.i[0..14]| R2.i[15..30] + | 0 R3.i[0..14]| R3.i[15..30] } 16b from {reals | imags | reals | imags | reals | imags | reals + | imags } produ = {R0.r[15..30] | R0.i[15..30] | R1.r[15..30] | R1.i[15..30] | R2.r[15..30] | R2.i[15..30] | + R3.r[15..30] | R3.i[15..30] } + */ + return simde_mm_blend_epi16(reals, imags, 0xAA); +} +static inline __attribute__((always_inline)) __m128i cmac_prec128(__m128i y, __m128i x, __m128i w_c, __m128i w_s) +{ + const __m128i produ = cmac0_prec128(x, w_c, w_s); + // Accumulate the product + return simde_mm_adds_epi16(y, produ); } #endif +#define load_consts(Type, Instruct, Rank) \ + const Type w_c##Rank = Instruct(c16toI32(c16conj(pmi_pdu->weights[Rank][ant]))); \ + const Type w_s##Rank = Instruct(c16toI32(c16swap(pmi_pdu->weights[Rank][ant]))); \ + const Type *in##Rank = (Type *)(txdataF_res_mapped[Rank] + sc_offset + (out-beginning)); + void nr_layer_precoder_simd(const int n_layers, const int symSz, const c16_t txdataF_res_mapped[n_layers][symSz], @@ -819,381 +817,264 @@ void nr_layer_precoder_simd(const int n_layers, const int re_cnt, c16_t *txdataF_precoded) { - uint32_t sc = sc_offset; - c16_t prec_weight = {0}; // For x86, use 256 SIMD for every 8 RE and 128 SIMD for last 4 RE // For aarch64, use 128 SIMD for every 4 RE + AssertFatal(n_layers > 0 && n_layers <= 4, "Shouldn't get here, n_layers %d\n", n_layers); // 512/256 SIMD: Do 16/8 RE in one iteration, 3 iterations for 2 RB -#if defined(__AVX512F__) && defined(__AVX512BW__) - const uint32_t re_cnt_align16 = re_cnt & ~15; - if (n_layers==1) { - prec_weight.r = pmi_pdu->weights[0][ant].precoder_weight_Re; - prec_weight.i = pmi_pdu->weights[0][ant].precoder_weight_Im; - const __m512i w_c = _mm512_set1_epi32(c16toI32(c16conj(prec_weight))); // broadcast conjugate of w - const __m512i w_s = _mm512_set1_epi32(c16toI32(c16swap(prec_weight))); // broadcast swapped real and img of w - __m512i y = _mm512_set1_epi16(0); - for (; sc < sc_offset + (re_cnt_align16); sc += sizeof(__m512i) / sizeof(prec_weight)) { - - const __m512i x = _mm512_loadu_si512(&txdataF_res_mapped[0][sc]); - // Matrix multiplication for 4 elements of the result (sizeof(simde__m256i) / sizeof(*prec_matrix) = 8) - y=cmac0_prec512(x,w_c,w_s); - _mm512_storeu_si512(&txdataF_precoded[sc],y); + c16_t *beginning = txdataF_precoded + sc_offset; + c16_t *out=beginning; +#if defined(__AVX512F__) && defined(__AVX512BW__) + { + c16_t *end = out + (re_cnt & ~15); + load_consts(__m512i, _mm512_set1_epi32, 0); + if (n_layers == 1) { + for (; out < end; out += sizeof(__m512i) / sizeof(*out)) { + const __m512i x = _mm512_loadu_si512(in0++); + // Matrix multiplication for 4 elements of the result (sizeof(simde__m256i) / sizeof(*prec_matrix) = 8) + __m512i y = cmac0_prec512(x, w_c0, w_s0); + _mm512_storeu_si512(out, y); + } + } else if (n_layers == 2) { + load_consts(__m512i, _mm512_set1_epi32, 1); + for (; out < end; out += sizeof(__m512i) / sizeof(*out)) { + const __m512i x = _mm512_loadu_si512(in0++); + const __m512i x1 = _mm512_loadu_si512(in1++); + // Matrix multiplication for 4 elements of the result (sizeof(simde__m256i) / sizeof(*prec_matrix) = 8) + __m512i y = cmac0_prec512(x, w_c0, w_s0); + y = cmac_prec512(y, x1, w_c1, w_s1); + _mm512_storeu_si512(out, y); + } + } else if (n_layers == 3) { + load_consts(__m512i, _mm512_set1_epi32, 1); + load_consts(__m512i, _mm512_set1_epi32, 2); + for (; out < end; out += sizeof(__m512i) / sizeof(*out)) { + const __m512i x = _mm512_loadu_si512(in0++); + const __m512i x1 = _mm512_loadu_si512(in1++); + const __m512i x2 = _mm512_loadu_si512(in2++); + // Matrix multiplication for 4 elements of the result (sizeof(simde__m256i) / sizeof(*prec_matrix) = 8) + __m512i y = cmac0_prec512(x, w_c0, w_s0); + y = cmac_prec512(y, x1, w_c1, w_s1); + y = cmac_prec512(y, x2, w_c2, w_s2); + _mm512_storeu_si512(out, y); + } + } else if (n_layers == 4) { + load_consts(__m512i, _mm512_set1_epi32, 1); + load_consts(__m512i, _mm512_set1_epi32, 2); + load_consts(__m512i, _mm512_set1_epi32, 3); + for (; out < end; out += sizeof(__m512i) / sizeof(*out)) { + const __m512i x = _mm512_loadu_si512(in0++); + const __m512i x1 = _mm512_loadu_si512(in1++); + const __m512i x2 = _mm512_loadu_si512(in2++); + const __m512i x3 = _mm512_loadu_si512(in3++); + // Matrix multiplication for 4 elements of the result (sizeof(simde__m256i) / sizeof(*prec_matrix) = 8) + __m512i y = cmac0_prec512(x, w_c0, w_s0); + y = cmac_prec512(y, x1, w_c1, w_s1); + y = cmac_prec512(y, x2, w_c2, w_s2); + y = cmac_prec512(y, x3, w_c3, w_s3); + _mm512_storeu_si512(out, y); + } } } - else if (n_layers==2) { - prec_weight.r = pmi_pdu->weights[0][ant].precoder_weight_Re; - prec_weight.i = pmi_pdu->weights[0][ant].precoder_weight_Im; - const __m512i w_c = _mm512_set1_epi32(c16toI32(c16conj(prec_weight))); // broadcast conjugate of w - const __m512i w_s = _mm512_set1_epi32(c16toI32(c16swap(prec_weight))); // broadcast swapped real and img of w - prec_weight.r = pmi_pdu->weights[1][ant].precoder_weight_Re; - prec_weight.i = pmi_pdu->weights[1][ant].precoder_weight_Im; - const __m512i w_c1 = _mm512_set1_epi32(c16toI32(c16conj(prec_weight))); // broadcast conjugate of w - const __m512i w_s1 = _mm512_set1_epi32(c16toI32(c16swap(prec_weight))); // broadcast swapped real and img of w - __m512i y = _mm512_set1_epi16(0); - for (; sc < sc_offset + (re_cnt_align16); sc += sizeof(__m512i) / sizeof(prec_weight)) { - - const __m512i x = _mm512_loadu_si512(&txdataF_res_mapped[0][sc]); - const __m512i x1 = _mm512_loadu_si512(&txdataF_res_mapped[1][sc]); - // Matrix multiplication for 4 elements of the result (sizeof(simde__m256i) / sizeof(*prec_matrix) = 8) - y=cmac0_prec512(x,w_c,w_s); - y=cmac_prec512(y,x1,w_c1,w_s1); - _mm512_storeu_si512(&txdataF_precoded[sc],y); - } - } - else if (n_layers==3) { - prec_weight.r = pmi_pdu->weights[0][ant].precoder_weight_Re; - prec_weight.i = pmi_pdu->weights[0][ant].precoder_weight_Im; - const __m512i w_c = _mm512_set1_epi32(c16toI32(c16conj(prec_weight))); // broadcast conjugate of w - const __m512i w_s = _mm512_set1_epi32(c16toI32(c16swap(prec_weight))); // broadcast swapped real and img of w - prec_weight.r = pmi_pdu->weights[1][ant].precoder_weight_Re; - prec_weight.i = pmi_pdu->weights[1][ant].precoder_weight_Im; - const __m512i w_c1 = _mm512_set1_epi32(c16toI32(c16conj(prec_weight))); // broadcast conjugate of w - const __m512i w_s1 = _mm512_set1_epi32(c16toI32(c16swap(prec_weight))); // broadcast swapped real and img of w - prec_weight.r = pmi_pdu->weights[2][ant].precoder_weight_Re; - prec_weight.i = pmi_pdu->weights[2][ant].precoder_weight_Im; - const __m512i w_c2 = _mm512_set1_epi32(c16toI32(c16conj(prec_weight))); // broadcast conjugate of w - const __m512i w_s2 = _mm512_set1_epi32(c16toI32(c16swap(prec_weight))); // broadcast swapped real and img of w - __m512i y = _mm512_set1_epi16(0); - for (; sc < sc_offset + (re_cnt_align16); sc += sizeof(__m512i) / sizeof(prec_weight)) { - - const __m512i x = _mm512_loadu_si512(&txdataF_res_mapped[0][sc]); - const __m512i x1 = _mm512_loadu_si512(&txdataF_res_mapped[1][sc]); - const __m512i x2 = _mm512_loadu_si512(&txdataF_res_mapped[2][sc]); - // Matrix multiplication for 4 elements of the result (sizeof(simde__m256i) / sizeof(*prec_matrix) = 8) - y=cmac0_prec512(x,w_c,w_s); - y=cmac_prec512(y,x1,w_c1,w_s1); - y=cmac_prec512(y,x2,w_c2,w_s2); - _mm512_storeu_si512(&txdataF_precoded[sc],y); - } - } - else if (n_layers==4) { - prec_weight.r = pmi_pdu->weights[0][ant].precoder_weight_Re; - prec_weight.i = pmi_pdu->weights[0][ant].precoder_weight_Im; - const __m512i w_c = _mm512_set1_epi32(c16toI32(c16conj(prec_weight))); // broadcast conjugate of w - const __m512i w_s = _mm512_set1_epi32(c16toI32(c16swap(prec_weight))); // broadcast swapped real and img of w - prec_weight.r = pmi_pdu->weights[1][ant].precoder_weight_Re; - prec_weight.i = pmi_pdu->weights[1][ant].precoder_weight_Im; - const __m512i w_c1 = _mm512_set1_epi32(c16toI32(c16conj(prec_weight))); // broadcast conjugate of w - const __m512i w_s1 = _mm512_set1_epi32(c16toI32(c16swap(prec_weight))); // broadcast swapped real and img of w - prec_weight.r = pmi_pdu->weights[2][ant].precoder_weight_Re; - prec_weight.i = pmi_pdu->weights[2][ant].precoder_weight_Im; - const __m512i w_c2 = _mm512_set1_epi32(c16toI32(c16conj(prec_weight))); // broadcast conjugate of w - const __m512i w_s2 = _mm512_set1_epi32(c16toI32(c16swap(prec_weight))); // broadcast swapped real and img of w - prec_weight.r = pmi_pdu->weights[3][ant].precoder_weight_Re; - prec_weight.i = pmi_pdu->weights[3][ant].precoder_weight_Im; - const __m512i w_c3 = _mm512_set1_epi32(c16toI32(c16conj(prec_weight))); // broadcast conjugate of w - const __m512i w_s3 = _mm512_set1_epi32(c16toI32(c16swap(prec_weight))); // broadcast swapped real and img of w - __m512i y = _mm512_set1_epi16(0); - for (; sc < sc_offset + (re_cnt_align16); sc += sizeof(__m512i) / sizeof(prec_weight)) { - - const __m512i x = _mm512_loadu_si512(&txdataF_res_mapped[0][sc]); - const __m512i x1 = _mm512_loadu_si512(&txdataF_res_mapped[1][sc]); - const __m512i x2 = _mm512_loadu_si512(&txdataF_res_mapped[2][sc]); - const __m512i x3 = _mm512_loadu_si512(&txdataF_res_mapped[3][sc]); - // Matrix multiplication for 4 elements of the result (sizeof(simde__m256i) / sizeof(*prec_matrix) = 8) - y=cmac0_prec512(x,w_c,w_s); - y=cmac_prec512(y,x1,w_c1,w_s1); - y=cmac_prec512(y,x2,w_c2,w_s2); - y=cmac_prec512(y,x3,w_c3,w_s3); - _mm512_storeu_si512(&txdataF_precoded[sc],y); - } - } - else AssertFatal(1==0,"Shouldn't get here, n_layers %d\n",n_layers); #endif #ifdef __AVX2__ - const uint32_t re_cnt_align8 = re_cnt & ~7; - if (n_layers==1) { - - simde__m256i y = simde_mm256_set1_epi16(0); // Y = W[0]*X[0] + W[1]*X[1] + ... + W[nrOfLayers-1]*X[nrOfLayers-1] - prec_weight.r = pmi_pdu->weights[0][ant].precoder_weight_Re; - prec_weight.i = pmi_pdu->weights[0][ant].precoder_weight_Im; - const simde__m256i w_c0 = simde_mm256_set1_epi32(c16toI32(c16conj(prec_weight))); // broadcast conjugate of w - const simde__m256i w_s0 = simde_mm256_set1_epi32(c16toI32(c16swap(prec_weight))); // broadcast swapped real and img of w - - for (; sc < sc_offset + (re_cnt_align8); sc += sizeof(simde__m256i) / sizeof(prec_weight)) { - const simde__m256i x0 = simde_mm256_loadu_si256(&txdataF_res_mapped[0][sc]); - // Accumulate the product - y = cmac0_prec256(x0,w_c0,w_s0); - // Store the result to txdataF - simde_mm256_storeu_si256(&txdataF_precoded[sc], y); + { + c16_t *end = beginning + (re_cnt & ~7); + load_consts(simde__m256i, simde_mm256_set1_epi32, 0); + if (n_layers == 1) { + for (; out < end; out += sizeof(simde__m256i) / sizeof(*out)) { + const simde__m256i x0 = simde_mm256_loadu_si256(in0++); + // Accumulate the product + simde__m256i y = cmac0_prec256(x0, w_c0, w_s0); + // Store the result to txdataF + simde_mm256_storeu_si256(out, y); + } + } else if (n_layers == 2) { + load_consts(simde__m256i, simde_mm256_set1_epi32, 1); + for (; out < end; out += sizeof(simde__m256i) / sizeof(*out)) { + const simde__m256i x0 = simde_mm256_loadu_si256(in0++); + const simde__m256i x1 = simde_mm256_loadu_si256(in1++); + // Accumulate the product + simde__m256i y = cmac0_prec256(x0, w_c0, w_s0); + y = cmac_prec256(y, x1, w_c1, w_s1); + // Store the result to txdataF + simde_mm256_storeu_si256(out, y); + } + } else if (n_layers == 3) { + load_consts(simde__m256i, simde_mm256_set1_epi32, 1); + load_consts(simde__m256i, simde_mm256_set1_epi32, 2); + for (; out < end; out += sizeof(simde__m256i) / sizeof(*out)) { + const simde__m256i x0 = simde_mm256_loadu_si256(in0++); + const simde__m256i x1 = simde_mm256_loadu_si256(in1++); + const simde__m256i x2 = simde_mm256_loadu_si256(in2++); + simde__m256i y = cmac0_prec256(x0, w_c0, w_s0); + y = cmac_prec256(y, x1, w_c1, w_s1); + y = cmac_prec256(y, x2, w_c2, w_s2); + // Store the result to txdataF + simde_mm256_storeu_si256(out, y); + } + } else if (n_layers == 4) { + load_consts(simde__m256i, simde_mm256_set1_epi32, 1); + load_consts(simde__m256i, simde_mm256_set1_epi32, 2); + load_consts(simde__m256i, simde_mm256_set1_epi32, 3); + for (; out < end; out += sizeof(simde__m256i) / sizeof(*out)) { + const simde__m256i x0 = simde_mm256_loadu_si256(in0++); + const simde__m256i x1 = simde_mm256_loadu_si256(in1++); + const simde__m256i x2 = simde_mm256_loadu_si256(in2++); + const simde__m256i x3 = simde_mm256_loadu_si256(in3++); + simde__m256i y = cmac0_prec256(x0, w_c0, w_s0); + y = cmac_prec256(y, x1, w_c1, w_s1); + y = cmac_prec256(y, x2, w_c2, w_s2); + y = cmac_prec256(y, x3, w_c3, w_s3); + // Store the result to txdataF + simde_mm256_storeu_si256(out, y); + } } } - else if (n_layers==2) { - - simde__m256i y = simde_mm256_set1_epi16(0); // Y = W[0]*X[0] + W[1]*X[1] + ... + W[nrOfLayers-1]*X[nrOfLayers-1] - prec_weight.r = pmi_pdu->weights[0][ant].precoder_weight_Re; - prec_weight.i = pmi_pdu->weights[0][ant].precoder_weight_Im; - const simde__m256i w_c0 = simde_mm256_set1_epi32(c16toI32(c16conj(prec_weight))); // broadcast conjugate of w - const simde__m256i w_s0 = simde_mm256_set1_epi32(c16toI32(c16swap(prec_weight))); // broadcast swapped real and img of w - prec_weight.r = pmi_pdu->weights[1][ant].precoder_weight_Re; - prec_weight.i = pmi_pdu->weights[1][ant].precoder_weight_Im; - const simde__m256i w_c1 = simde_mm256_set1_epi32(c16toI32(c16conj(prec_weight))); // broadcast conjugate of w - const simde__m256i w_s1 = simde_mm256_set1_epi32(c16toI32(c16swap(prec_weight))); // broadcast swapped real and img of w - - for (; sc < sc_offset + (re_cnt_align8); sc += sizeof(simde__m256i) / sizeof(prec_weight)) { - const simde__m256i x0 = simde_mm256_loadu_si256(&txdataF_res_mapped[0][sc]); - - const simde__m256i x1 = simde_mm256_loadu_si256(&txdataF_res_mapped[1][sc]); - // Accumulate the product - y = cmac0_prec256(x0,w_c0,w_s0); - y = cmac_prec256(y,x1,w_c1,w_s1); - // Store the result to txdataF - simde_mm256_storeu_si256(&txdataF_precoded[sc], y); - } - } - else if (n_layers==3) { - simde__m256i y = simde_mm256_set1_epi16(0); // Y = W[0]*X[0] + W[1]*X[1] + ... + W[nrOfLayers-1]*X[nrOfLayers-1] - prec_weight.r = pmi_pdu->weights[0][ant].precoder_weight_Re; - prec_weight.i = pmi_pdu->weights[0][ant].precoder_weight_Im; - const simde__m256i w_c0 = simde_mm256_set1_epi32(c16toI32(c16conj(prec_weight))); // broadcast conjugate of w - const simde__m256i w_s0 = simde_mm256_set1_epi32(c16toI32(c16swap(prec_weight))); // broadcast swapped real and img of w - prec_weight.r = pmi_pdu->weights[1][ant].precoder_weight_Re; - prec_weight.i = pmi_pdu->weights[1][ant].precoder_weight_Im; - const simde__m256i w_c1 = simde_mm256_set1_epi32(c16toI32(c16conj(prec_weight))); // broadcast conjugate of w - const simde__m256i w_s1 = simde_mm256_set1_epi32(c16toI32(c16swap(prec_weight))); // broadcast swapped real and img of w - prec_weight.r = pmi_pdu->weights[2][ant].precoder_weight_Re; - prec_weight.i = pmi_pdu->weights[2][ant].precoder_weight_Im; - const simde__m256i w_c2 = simde_mm256_set1_epi32(c16toI32(c16conj(prec_weight))); // broadcast conjugate of w - const simde__m256i w_s2 = simde_mm256_set1_epi32(c16toI32(c16swap(prec_weight))); // broadcast swapped real and img of w - - for (; sc < sc_offset + (re_cnt_align8); sc += sizeof(simde__m256i) / sizeof(prec_weight)) { - const simde__m256i x0 = simde_mm256_loadu_si256(&txdataF_res_mapped[0][sc]); - const simde__m256i x1 = simde_mm256_loadu_si256(&txdataF_res_mapped[1][sc]); - const simde__m256i x2 = simde_mm256_loadu_si256(&txdataF_res_mapped[2][sc]); - y = cmac0_prec256(x0,w_c0,w_s0); - y = cmac_prec256(y,x1,w_c1,w_s1); - y = cmac_prec256(y,x2,w_c2,w_s2); - // Store the result to txdataF - simde_mm256_storeu_si256(&txdataF_precoded[sc], y); - } - } - else if (n_layers==4) { - simde__m256i y = simde_mm256_set1_epi16(0); // Y = W[0]*X[0] + W[1]*X[1] + ... + W[nrOfLayers-1]*X[nrOfLayers-1] - prec_weight.r = pmi_pdu->weights[0][ant].precoder_weight_Re; - prec_weight.i = pmi_pdu->weights[0][ant].precoder_weight_Im; - const simde__m256i w_c0 = simde_mm256_set1_epi32(c16toI32(c16conj(prec_weight))); // broadcast conjugate of w - const simde__m256i w_s0 = simde_mm256_set1_epi32(c16toI32(c16swap(prec_weight))); // broadcast swapped real and img of w - prec_weight.r = pmi_pdu->weights[1][ant].precoder_weight_Re; - prec_weight.i = pmi_pdu->weights[1][ant].precoder_weight_Im; - const simde__m256i w_c1 = simde_mm256_set1_epi32(c16toI32(c16conj(prec_weight))); // broadcast conjugate of w - const simde__m256i w_s1 = simde_mm256_set1_epi32(c16toI32(c16swap(prec_weight))); // broadcast swapped real and img of w - prec_weight.r = pmi_pdu->weights[2][ant].precoder_weight_Re; - prec_weight.i = pmi_pdu->weights[2][ant].precoder_weight_Im; - const simde__m256i w_c2 = simde_mm256_set1_epi32(c16toI32(c16conj(prec_weight))); // broadcast conjugate of w - const simde__m256i w_s2 = simde_mm256_set1_epi32(c16toI32(c16swap(prec_weight))); // broadcast swapped real and img of w - - prec_weight.r = pmi_pdu->weights[3][ant].precoder_weight_Re; - prec_weight.i = pmi_pdu->weights[3][ant].precoder_weight_Im; - const simde__m256i w_c3 = simde_mm256_set1_epi32(c16toI32(c16conj(prec_weight))); // broadcast conjugate of w - const simde__m256i w_s3 = simde_mm256_set1_epi32(c16toI32(c16swap(prec_weight))); // broadcast swapped real and img of w - for (; sc < sc_offset + (re_cnt_align8); sc += sizeof(simde__m256i) / sizeof(prec_weight)) { - const simde__m256i x0 = simde_mm256_loadu_si256(&txdataF_res_mapped[0][sc]); - const simde__m256i x1 = simde_mm256_loadu_si256(&txdataF_res_mapped[1][sc]); - const simde__m256i x2 = simde_mm256_loadu_si256(&txdataF_res_mapped[2][sc]); - const simde__m256i x3 = simde_mm256_loadu_si256(&txdataF_res_mapped[3][sc]); - y = cmac0_prec256(x0,w_c0,w_s0); - y = cmac_prec256(y,x1,w_c1,w_s1); - y = cmac_prec256(y,x2,w_c2,w_s2); - y = cmac_prec256(y,x3,w_c3,w_s3); - // Store the result to txdataF - simde_mm256_storeu_si256(&txdataF_precoded[sc], y); - } - } - else AssertFatal(1==0,"Shouldn't get here, n_layers %d\n",n_layers); #endif - // 128 SIMD: Do 4 RE in one iteration, 3 iterations for 1 RB - const uint32_t re_cnt_align4 = re_cnt & ~3; - for (; sc < sc_offset + re_cnt_align4; sc += sizeof(simde__m128i) / sizeof(prec_weight)) { + c16_t *end = beginning + (re_cnt & ~3); #ifdef DEBUG_DLSCH_PRECODING_PRINT_WITH_TRIVIAL // Get result with trivial solution, TODO: To be removed + // 128 SIMD: Do 4 RE in one iteration, 3 iterations for 1 RB + for (; out < end; out += sizeof(simde__m128i) / sizeof(*out)) { c16_t y_triv[4]; for (int i = 0; i < 4; i++) y_triv[i] = nr_layer_precoder_cm(n_layers, symSz, txdataF_res_mapped, ant, pmi_pdu, sc + i); - memcpy(&txdataF_precoded[sc], y_triv, sizeof(y_triv)); + memcpy(out, y_triv, sizeof(y_triv)); + } #endif #ifdef __aarch64__ - - const uint32_t re_cnt_align8 = re_cnt & ~3; - if (n_layers==1) { - - prec_weight.r = pmi_pdu->weights[0][ant].precoder_weight_Re; - prec_weight.i = pmi_pdu->weights[0][ant].precoder_weight_Im; - const int16x8_t wr0 = vdupq_n_s16(prec_weight.r); - const int16x8_t wi0 = vdupq_n_s16(prec_weight.i); - int16x8_t y; - - for (; sc < sc_offset + (re_cnt_align8); sc += sizeof(int16x8_t) / sizeof(prec_weight)) { - const int16x8_t x0 = vld1q_s16((const int16_t*)&txdataF_res_mapped[0][sc]); + load_consts(int16x8_t, vdupq_n_s16, 0); + if (n_layers == 1) { + for (; out < end; out += sizeof(int16x8_t) / sizeof(*out)) { + const int16x8_t x0 = vld1q_s16((const int16_t *)in0++); // Accumulate the product - y = cmac0_prec128(x0,wr0,wi0); + int16x8_t y = cmac0_prec128(x0, w_c0, w_s0); // Store the result to txdataF - *((int16x8_t*)&txdataF_precoded[sc])= y; + *(int16x8_t *)out = y; } } - if (n_layers==2) { - - prec_weight.r = pmi_pdu->weights[0][ant].precoder_weight_Re; - prec_weight.i = pmi_pdu->weights[0][ant].precoder_weight_Im; - const int16x8_t wr0 = vdupq_n_s16(prec_weight.r); - const int16x8_t wi0 = vdupq_n_s16(prec_weight.i); - prec_weight.r = pmi_pdu->weights[1][ant].precoder_weight_Re; - prec_weight.i = pmi_pdu->weights[1][ant].precoder_weight_Im; - const int16x8_t wr1 = vdupq_n_s16(prec_weight.r); - const int16x8_t wi1 = vdupq_n_s16(prec_weight.i); - int16x8_t y; - - for (; sc < sc_offset + (re_cnt_align8); sc += sizeof(int16x8_t) / sizeof(prec_weight)) { - const int16x8_t x0 = vld1q_s16((const int16_t*)&txdataF_res_mapped[0][sc]); - const int16x8_t x1 = vld1q_s16((const int16_t*)&txdataF_res_mapped[1][sc]); + if (n_layers == 2) { + load_consts(int16x8_t, vdupq_n_s16, 1); + for (; out < end; out += sizeof(int16x8_t) / sizeof(*out)) { + const int16x8_t x0 = vld1q_s16((const int16_t *)in0++); + const int16x8_t x1 = vld1q_s16((const int16_t *)in1++); // Accumulate the product - y = cmac0_prec128(x0,wr0,wi0); - y = cmac_prec128(y,x1,wr1,wi1); + int16x8_t y = cmac0_prec128(x0, w_c0, w_s0); + y = cmac_prec128(y, x1, w_cr1, w_s1); // Store the result to txdataF - *((int16x8_t*)&txdataF_precoded[sc])= y; + *(int16x8_t *)out = y; } } - if (n_layers==3) { - - prec_weight.r = pmi_pdu->weights[0][ant].precoder_weight_Re; - prec_weight.i = pmi_pdu->weights[0][ant].precoder_weight_Im; - const int16x8_t wr0 = vdupq_n_s16(prec_weight.r); - const int16x8_t wi0 = vdupq_n_s16(prec_weight.i); - prec_weight.r = pmi_pdu->weights[1][ant].precoder_weight_Re; - prec_weight.i = pmi_pdu->weights[1][ant].precoder_weight_Im; - const int16x8_t wr1 = vdupq_n_s16(prec_weight.r); - const int16x8_t wi1 = vdupq_n_s16(prec_weight.i); - prec_weight.r = pmi_pdu->weights[2][ant].precoder_weight_Re; - prec_weight.i = pmi_pdu->weights[2][ant].precoder_weight_Im; - const int16x8_t wr2 = vdupq_n_s16(prec_weight.r); - const int16x8_t wi2 = vdupq_n_s16(prec_weight.i); - int16x8_t y; - - for (; sc < sc_offset + (re_cnt_align8); sc += sizeof(int16x8_t) / sizeof(prec_weight)) { - const int16x8_t x0 = vld1q_s16((const int16_t*)&txdataF_res_mapped[0][sc]); - const int16x8_t x1 = vld1q_s16((const int16_t*)&txdataF_res_mapped[1][sc]); - const int16x8_t x2 = vld1q_s16((const int16_t*)&txdataF_res_mapped[2][sc]); + if (n_layers == 3) { + load_consts(int16x8_t, vdupq_n_s16, 1); + load_consts(int16x8_t, vdupq_n_s16, 2); + for (; out < end; out += sizeof(int16x8_t) / sizeof(*out)) { + const int16x8_t x0 = vld1q_s16((const int16_t *)in0++); + const int16x8_t x1 = vld1q_s16((const int16_t *)in1++); + const int16x8_t x2 = vld1q_s16((const int16_t *)in2++); // Accumulate the product - y = cmac0_prec128(x0,wr0,wi0); - y = cmac_prec128(y,x1,wr1,wi1); - y = cmac_prec128(y,x2,wr2,wi2); + int16x8_t y = cmac0_prec128(x0, w_c0, w_s0); + ; + y = cmac_prec128(y, x1, w_cr1, w_s1); + y = cmac_prec128(y, x2, w_cr2, w_s2); // Store the result to txdataF - *((int16x8_t*)&txdataF_precoded[sc])= y; + *(int16x8_t *)out = y; } } - if (n_layers==4) { - - prec_weight.r = pmi_pdu->weights[0][ant].precoder_weight_Re; - prec_weight.i = pmi_pdu->weights[0][ant].precoder_weight_Im; - const int16x8_t wr0 = vdupq_n_s16(prec_weight.r); - const int16x8_t wi0 = vdupq_n_s16(prec_weight.i); - prec_weight.r = pmi_pdu->weights[1][ant].precoder_weight_Re; - prec_weight.i = pmi_pdu->weights[1][ant].precoder_weight_Im; - const int16x8_t wr1 = vdupq_n_s16(prec_weight.r); - const int16x8_t wi1 = vdupq_n_s16(prec_weight.i); - prec_weight.r = pmi_pdu->weights[2][ant].precoder_weight_Re; - prec_weight.i = pmi_pdu->weights[2][ant].precoder_weight_Im; - const int16x8_t wr2 = vdupq_n_s16(prec_weight.r); - const int16x8_t wi2 = vdupq_n_s16(prec_weight.i); - prec_weight.r = pmi_pdu->weights[3][ant].precoder_weight_Re; - prec_weight.i = pmi_pdu->weights[3][ant].precoder_weight_Im; - const int16x8_t wr3 = vdupq_n_s16(prec_weight.r); - const int16x8_t wi3 = vdupq_n_s16(prec_weight.i); - int16x8_t y; - - for (; sc < sc_offset + (re_cnt_align8); sc += sizeof(int16x8_t) / sizeof(prec_weight)) { - const int16x8_t x0 = vld1q_s16((const int16_t*)&txdataF_res_mapped[0][sc]); - const int16x8_t x1 = vld1q_s16((const int16_t*)&txdataF_res_mapped[1][sc]); - const int16x8_t x2 = vld1q_s16((const int16_t*)&txdataF_res_mapped[2][sc]); - const int16x8_t x3 = vld1q_s16((const int16_t*)&txdataF_res_mapped[3][sc]); + if (n_layers == 4) { + load_consts(int16x8_t, vdupq_n_s16, 1); + load_consts(int16x8_t, vdupq_n_s16, 2); + load_consts(int16x8_t, vdupq_n_s16, 3); + for (; out < end; out += sizeof(int16x8_t) / sizeof(*out)) { + const int16x8_t x0 = vld1q_s16((const int16_t *)in0++); + const int16x8_t x1 = vld1q_s16((const int16_t *)in1++); + const int16x8_t x2 = vld1q_s16((const int16_t *)in2++); + const int16x8_t x3 = vld1q_s16((const int16_t *)in3++); // Accumulate the product - y = cmac0_prec128(x0,wr0,wi0); - y = cmac_prec128(y,x1,wr1,wi1); - y = cmac_prec128(y,x2,wr2,wi2); - y = cmac_prec128(y,x3,wr3,wi3); + int16x8_t y = cmac0_prec128(x0, w_c0, w_s0); + ; + y = cmac_prec128(y, x1, w_cr1, w_s1); + y = cmac_prec128(y, x2, w_cr2, w_s2); + y = cmac_prec128(y, x3, w_cr3, w_s3); // Store the result to txdataF - *((int16x8_t*)&txdataF_precoded[sc])= y; + *(int16x8_t *)out = y; } } -#else - // Matrix multiplication for 4 elements of the result (sizeof(simde__m128i) / sizeof(c16_t) = 4) - simde__m128i y = simde_mm_set1_epi16(0); // Y = W[0]*X[0] + W[1]*X[1] + ... + W[nrOfLayers-1]*X[nrOfLayers-1] - for (int nl = 0; nl < n_layers; nl++) { - prec_weight.r = pmi_pdu->weights[nl][ant].precoder_weight_Re; - prec_weight.i = pmi_pdu->weights[nl][ant].precoder_weight_Im; - - const simde__m128i x = simde_mm_loadu_si128(&txdataF_res_mapped[nl][sc]); - - // Rearrange precoding matrix weight to match complex multiplication and broadcast it to match SIMD size - const simde__m128i w_c = simde_mm_set1_epi32(c16toI32(c16conj(prec_weight))); // broadcast conjugate of w - const simde__m128i w_s = simde_mm_set1_epi32(c16toI32(c16swap(prec_weight))); // broadcast swapped real and img of w - - // Multiplication and shift - const simde__m128i reals = - simde_mm_srai_epi32(simde_mm_madd_epi16(x, w_c), 15); // (int32_t) .r = (x.r * w.r - x.i * w.i) >> 15 - const simde__m128i imags = simde_mm_slli_epi32( - simde_mm_madd_epi16(x, w_s), - 1); // (int32_t) .i = (x.r * w.i + x.i * w.r) << 1, since higher 16 bit of each 32 bit is taken by blend_epi16 - - /* Re-arrange to match c16_t format - bit index: 0 | 16 | 32 | 48 | 64 | 80 | 96 | 112 - reals = {R0.r[15..30] | R0.r[31] (0)*15 | R1.r[15..30] | R1.r[31] (0)*15 | R2.r[15..30] | R2.r[31] (0)*15 | R3.r[15..30] - | R3.r[31] (0)*15} imags = {0 R0.i[0..14]| R0.i[15..30] | 0 R1.i[0..14]| R1.i[15..30] | 0 R2.i[0..14]| R2.i[15..30] - | 0 R3.i[0..14]| R3.i[15..30] } 16b from {reals | imags | reals | imags | reals | imags | reals - | imags } produ = {R0.r[15..30] | R0.i[15..30] | R1.r[15..30] | R1.i[15..30] | R2.r[15..30] | R2.i[15..30] | - R3.r[15..30] | R3.i[15..30] } - */ - const simde__m128i produ = simde_mm_blend_epi16(reals, imags, 0xAA); - +#else + load_consts(simde__m128i, simde_mm_set1_epi32, 0); + if (n_layers == 1) { + for (; out < end; out += sizeof(simde__m128i) / sizeof(*out)) { + const simde__m128i x0 = simde_mm_loadu_si128(in0++); // Accumulate the product - y = simde_mm_adds_epi16(y, produ); + simde__m128i y = cmac0_prec128(x0, w_c0, w_s0); + // Store the result to txdataF + simde_mm_storeu_si128(out, y); } - // Store the result to txdataF - simde_mm_storeu_si128(&txdataF_precoded[sc], y); + } else if (n_layers == 2) { + load_consts(simde__m128i, simde_mm_set1_epi32, 1); + for (; out < end; out += sizeof(simde__m128i) / sizeof(*out)) { + const simde__m128i x0 = simde_mm_loadu_si128(in0++); + const simde__m128i x1 = simde_mm_loadu_si128(in1++); + // Accumulate the product + simde__m128i y = cmac0_prec128(x0, w_c0, w_s0); + y = cmac_prec128(y, x1, w_c1, w_s1); + // Store the result to txdataF + simde_mm_storeu_si128(out, y); + } + } else if (n_layers == 3) { + load_consts(simde__m128i, simde_mm_set1_epi32, 1); + load_consts(simde__m128i, simde_mm_set1_epi32, 2); + for (; out < end; out += sizeof(simde__m128i) / sizeof(*out)) { + const simde__m128i x0 = simde_mm_loadu_si128(in0++); + const simde__m128i x1 = simde_mm_loadu_si128(in1++); + const simde__m128i x2 = simde_mm_loadu_si128(in2++); + simde__m128i y = cmac0_prec128(x0, w_c0, w_s0); + y = cmac_prec128(y, x1, w_c1, w_s1); + y = cmac_prec128(y, x2, w_c2, w_s2); + // Store the result to txdataF + simde_mm_storeu_si128(out, y); + } + } else if (n_layers == 4) { + load_consts(simde__m128i, simde_mm_set1_epi32, 1); + load_consts(simde__m128i, simde_mm_set1_epi32, 2); + load_consts(simde__m128i, simde_mm_set1_epi32, 3); + for (; out < end; out += sizeof(simde__m128i) / sizeof(*out)) { + const simde__m128i x0 = simde_mm_loadu_si128(in0++); + const simde__m128i x1 = simde_mm_loadu_si128(in1++); + const simde__m128i x2 = simde_mm_loadu_si128(in2++); + const simde__m128i x3 = simde_mm_loadu_si128(in3++); + simde__m128i y = cmac0_prec128(x0, w_c0, w_s0); + y = cmac_prec128(y, x1, w_c1, w_s1); + y = cmac_prec128(y, x2, w_c2, w_s2); + y = cmac_prec128(y, x3, w_c3, w_s3); + // Store the result to txdataF + simde_mm_storeu_si128(out, y); + } + } #endif #ifdef DEBUG_DLSCH_PRECODING_PRINT_WITH_TRIVIAL // Print simd and trivial result, TODO: To be removed - c16_t *y_simd = (c16_t *)&y; - printf("debug_to_be_removed re_cnt=%d, sc=%u, y_simd=(%+4d,%+4d), (%+4d,%+4d), (%+4d,%+4d), (%+4d,%+4d)\n", - re_cnt, - sc, - y_simd[0].r, - y_simd[0].i, - y_simd[1].r, - y_simd[1].i, - y_simd[2].r, - y_simd[2].i, - y_simd[3].r, - y_simd[3].i); - printf("debug_to_be_removed re_cnt=%d, sc=%u, y_triv=(%+4d,%+4d), (%+4d,%+4d), (%+4d,%+4d), (%+4d,%+4d)\n", - re_cnt, - sc, - y_triv[0].r, - y_triv[0].i, - y_triv[1].r, - y_triv[1].i, - y_triv[2].r, - y_triv[2].i, - y_triv[3].r, - y_triv[3].i); + c16_t *y_simd = (c16_t *)&y; + printf("debug_to_be_removed re_cnt=%d, sc=%u, y_simd=(%+4d,%+4d), (%+4d,%+4d), (%+4d,%+4d), (%+4d,%+4d)\n", + re_cnt, + sc, + y_simd[0].r, + y_simd[0].i, + y_simd[1].r, + y_simd[1].i, + y_simd[2].r, + y_simd[2].i, + y_simd[3].r, + y_simd[3].i); + printf("debug_to_be_removed re_cnt=%d, sc=%u, y_triv=(%+4d,%+4d), (%+4d,%+4d), (%+4d,%+4d), (%+4d,%+4d)\n", + re_cnt, + sc, + y_triv[0].r, + y_triv[0].i, + y_triv[1].r, + y_triv[1].i, + y_triv[2].r, + y_triv[2].i, + y_triv[3].r, + y_triv[3].i); #endif - } } diff --git a/openair1/PHY/MODULATION/tests/test_nr_modulation.cpp b/openair1/PHY/MODULATION/tests/test_nr_modulation.cpp index ca8b61acd7..04d32514a0 100644 --- a/openair1/PHY/MODULATION/tests/test_nr_modulation.cpp +++ b/openair1/PHY/MODULATION/tests/test_nr_modulation.cpp @@ -85,8 +85,7 @@ TEST(NrLayerPrecoderTest, Basic) // Create and populate the pmi_pdu structure nfapi_nr_pm_pdu_t pmi_pdu = {0}; for (int layer = 0; layer < n_layers; ++layer) { - pmi_pdu.weights[layer][ant].precoder_weight_Re = -SHRT_MAX; // Q15 representation of (~-1.0) -0.999969482421875 (-1+2^-15) - pmi_pdu.weights[layer][ant].precoder_weight_Im = 0; + pmi_pdu.weights[layer][ant] = (c16_t){-SHRT_MAX, 0}; } // Call the C function @@ -131,8 +130,7 @@ TEST(NrLayerPrecoderTest, SIMD) // Create and populate the pmi_pdu structure nfapi_nr_pm_pdu_t pmi_pdu = {0}; for (int layer = 0; layer < n_layers; ++layer) { - pmi_pdu.weights[layer][ant].precoder_weight_Re = -SHRT_MAX; // Q15 representation of (~-1.0) -0.999969482421875 (-1+2^-15) - pmi_pdu.weights[layer][ant].precoder_weight_Im = 0; + pmi_pdu.weights[layer][ant] = (c16_t){-SHRT_MAX, 0}; } // Call the C function @@ -182,10 +180,8 @@ TEST(NrLayerPrecoderTest, Compare_CM_SIMD) // Could not use convert_precoder_weight() as complex.h could not be used in googletest // Use the logic in convert_precoder_weight() // precoder [−1,−j] - pmi_pdu.weights[layer][0].precoder_weight_Re = -SHRT_MAX; // Q15 representation of (~-1.0) -0.999969482421875 (-1+2^-15) - pmi_pdu.weights[layer][0].precoder_weight_Im = 0x0000; // Q15 representation of 0 - pmi_pdu.weights[layer][1].precoder_weight_Re = 0x0000; // Q15 representation of 0 - pmi_pdu.weights[layer][1].precoder_weight_Im = -SHRT_MAX; // Q15 representation of (~-1.0) -0.999969482421875 (-1+2^-15) + pmi_pdu.weights[layer][0] = (c16_t){-SHRT_MAX, 0}; + pmi_pdu.weights[layer][1] = (c16_t){0, -SHRT_MAX}; } // Get the results for all the antenna diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c index 9a5197181f..a0637ac107 100644 --- a/openair2/LAYER2/NR_MAC_gNB/config.c +++ b/openair2/LAYER2/NR_MAC_gNB/config.c @@ -136,8 +136,7 @@ int precoding_weigths_generation(nfapi_nr_pm_list_t *mat, nfapi_nr_pm_weights_t *weights = &mat->pmi_pdu[pmiq].weights[j_col][i_rows]; res_code = sqrt(1 / (double)L) * v_lm[llc][mmc][i_rows]; c16_t precoder_weight = convert_precoder_weight(res_code); - weights->precoder_weight_Re = precoder_weight.r; - weights->precoder_weight_Im = precoder_weight.i; + *weights = precoder_weight; LOG_D(PHY, "%d Layer Precoding Matrix[pmi %d][antPort %d][layerIdx %d]= %f+j %f -> Fixed Point %d+j %d \n", L, @@ -146,15 +145,14 @@ int precoding_weigths_generation(nfapi_nr_pm_list_t *mat, j_col, creal(res_code), cimag(res_code), - weights->precoder_weight_Re, - weights->precoder_weight_Im); + weights->r, + weights->i); } for (int i_rows = N1 * N2; i_rows < 2 * N1 * N2; i_rows++) { nfapi_nr_pm_weights_t *weights = &mat->pmi_pdu[pmiq].weights[j_col][i_rows]; res_code = sqrt(1 / (double)L) * (phase_sign)*theta_n[nn] * v_lm[llc][mmc][i_rows - N1 * N2]; c16_t precoder_weight = convert_precoder_weight(res_code); - weights->precoder_weight_Re = precoder_weight.r; - weights->precoder_weight_Im = precoder_weight.i; + *weights = precoder_weight; LOG_D(PHY, "%d Layer Precoding Matrix[pmi %d][antPort %d][layerIdx %d]= %f+j %f -> Fixed Point %d+j %d \n", L, @@ -163,8 +161,8 @@ int precoding_weigths_generation(nfapi_nr_pm_list_t *mat, j_col, creal(res_code), cimag(res_code), - weights->precoder_weight_Re, - weights->precoder_weight_Im); + weights->r, + weights->i); } } pmiq++; From 0dcea09e8737037c9c389ddd26376062c938b453 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Fri, 3 Oct 2025 13:47:33 +0000 Subject: [PATCH 927/964] bugfix for arm-v8x/v9 --- openair1/PHY/MODULATION/nr_modulation.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/openair1/PHY/MODULATION/nr_modulation.c b/openair1/PHY/MODULATION/nr_modulation.c index 5888b17eb0..eb4dc50bc9 100644 --- a/openair1/PHY/MODULATION/nr_modulation.c +++ b/openair1/PHY/MODULATION/nr_modulation.c @@ -774,7 +774,7 @@ static inline __attribute__((always_inline)) int16x8_t cmac0_prec128(int16x8_t x } static inline __attribute__((always_inline)) int16x8_t cmac_prec128(int16x8_t y, int16x8_t x, int16x8_t wr, int16x8_t wi) { int16x8_t produ = cmac0_prec128(x, wr, wi); - return vaddq_s16(y, produ.val[0]); + return vaddq_s16(y, produ); } #else static inline __attribute__((always_inline)) simde__m128i cmac0_prec128(simde__m128i x, simde__m128i w_c, simde__m128i w_s) @@ -960,7 +960,7 @@ void nr_layer_precoder_simd(const int n_layers, const int16x8_t x1 = vld1q_s16((const int16_t *)in1++); // Accumulate the product int16x8_t y = cmac0_prec128(x0, w_c0, w_s0); - y = cmac_prec128(y, x1, w_cr1, w_s1); + y = cmac_prec128(y, x1, w_c1, w_s1); // Store the result to txdataF *(int16x8_t *)out = y; } @@ -975,8 +975,8 @@ void nr_layer_precoder_simd(const int n_layers, // Accumulate the product int16x8_t y = cmac0_prec128(x0, w_c0, w_s0); ; - y = cmac_prec128(y, x1, w_cr1, w_s1); - y = cmac_prec128(y, x2, w_cr2, w_s2); + y = cmac_prec128(y, x1, w_c1, w_s1); + y = cmac_prec128(y, x2, w_c2, w_s2); // Store the result to txdataF *(int16x8_t *)out = y; } @@ -993,9 +993,9 @@ void nr_layer_precoder_simd(const int n_layers, // Accumulate the product int16x8_t y = cmac0_prec128(x0, w_c0, w_s0); ; - y = cmac_prec128(y, x1, w_cr1, w_s1); - y = cmac_prec128(y, x2, w_cr2, w_s2); - y = cmac_prec128(y, x3, w_cr3, w_s3); + y = cmac_prec128(y, x1, w_c1, w_s1); + y = cmac_prec128(y, x2, w_c2, w_s2); + y = cmac_prec128(y, x3, w_c3, w_s3); // Store the result to txdataF *(int16x8_t *)out = y; } From dab8db76d7da22e094845125f69cbcdb3af03257 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 24 Sep 2025 16:18:53 +0200 Subject: [PATCH 928/964] CI: Aerial: Split out CN start/stop from main XML The next commit introduces an "UL-heavy" configuration to be tested with Aerial. To avoid waiting for the CN, start&stop it once at the beginning of the CI run. --- .../container_sa_aerial_cn_start.xml | 37 ++++++++++++++++++ .../xml_files/container_sa_aerial_cn_stop.xml | 38 +++++++++++++++++++ .../xml_files/container_sa_aerial_quectel.xml | 15 -------- 3 files changed, 75 insertions(+), 15 deletions(-) create mode 100644 ci-scripts/xml_files/container_sa_aerial_cn_start.xml create mode 100644 ci-scripts/xml_files/container_sa_aerial_cn_stop.xml diff --git a/ci-scripts/xml_files/container_sa_aerial_cn_start.xml b/ci-scripts/xml_files/container_sa_aerial_cn_start.xml new file mode 100644 index 0000000000..db622423ae --- /dev/null +++ b/ci-scripts/xml_files/container_sa_aerial_cn_start.xml @@ -0,0 +1,37 @@ + + + TEST-AERIAL-SA-CN-START + Deploy 5GC + tasks + + 555000 + + + + DeployCoreNetwork + Initialize 5G Core + oc-cn5g-20897-aerial + + + diff --git a/ci-scripts/xml_files/container_sa_aerial_cn_stop.xml b/ci-scripts/xml_files/container_sa_aerial_cn_stop.xml new file mode 100644 index 0000000000..bf0bd9fb9c --- /dev/null +++ b/ci-scripts/xml_files/container_sa_aerial_cn_stop.xml @@ -0,0 +1,38 @@ + + + TEST-AERIAL-SA-CN-STOP + Undeploy 5GC + tasks + + 000555 + + + + UndeployCoreNetwork + true + Terminate 5G Core + oc-cn5g-20897-aerial + + + diff --git a/ci-scripts/xml_files/container_sa_aerial_quectel.xml b/ci-scripts/xml_files/container_sa_aerial_quectel.xml index 45401ac77b..05d35d0171 100644 --- a/ci-scripts/xml_files/container_sa_aerial_quectel.xml +++ b/ci-scripts/xml_files/container_sa_aerial_quectel.xml @@ -25,7 +25,6 @@ AERIAL 100 MHz TDD SA tasks - 555000 111111 000222 800813 @@ -40,15 +39,8 @@ 000222 222222 333333 - 000555 - - DeployCoreNetwork - Initialize 5G Core - oc-cn5g-20897-aerial - - Pull_Local_Registry Pull Images from Local Registry @@ -160,12 +152,5 @@ gracehopper1-oai oai-gnb-aerial - - - UndeployCoreNetwork - true - Terminate 5G Core - oc-cn5g-20897-aerial - From ce4e647fd858cc5dd4860781c24a90c72d97bb66 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 9 Oct 2025 16:38:38 +0200 Subject: [PATCH 929/964] USRP: move time/clock source setting to later Doing this before using set_master_clock_rate() on the B200 seems to invalidate clock settings: [HW] USRP clock set to 1759836386.000000 sec [...] [HW] current pps at 3.286750, starting streaming at 4.286750 In other words, the current time setting was reset. With this change now, we see [HW] USRP clock set to 1759929873.000000 sec [...] [HW] current pps at 1759929873.000000, starting streaming at 1759929874.000000 This is because changing clock sources (I assume setting the master clock rate impacts the clock) can result in changing the time. From the documentation of set_time_next_pps() [1]: > Note: When changing clock sources, a previously set time will most > likely be lost. It is recommended to set the time after changing the > clock source. Otherwise, an unexpected time may line up with future PPS > edges. [1] https://files.ettus.com/manual/classuhd_1_1usrp_1_1multi__usrp.html#a75b1c5375549e6a446d686ee7d9b4e14 --- radio/USRP/usrp_lib.cpp | 139 ++++++++++++++++++---------------------- 1 file changed, 64 insertions(+), 75 deletions(-) diff --git a/radio/USRP/usrp_lib.cpp b/radio/USRP/usrp_lib.cpp index 6dde70b2eb..79c58b59f4 100644 --- a/radio/USRP/usrp_lib.cpp +++ b/radio/USRP/usrp_lib.cpp @@ -1161,79 +1161,6 @@ extern "C" { s->usrp = uhd::usrp::multi_usrp::make(args); - if (args.find("clock_source")==std::string::npos) { - if (openair0_cfg[0].clock_source == internal) { - s->usrp->set_clock_source("internal"); - LOG_I(HW,"Setting clock source to internal\n"); - } - else if (openair0_cfg[0].clock_source == external ) { - s->usrp->set_clock_source("external"); - LOG_I(HW,"Setting clock source to external\n"); - } - else if (openair0_cfg[0].clock_source==gpsdo) { - s->usrp->set_clock_source("gpsdo"); - LOG_I(HW,"Setting clock source to gpsdo\n"); - } - else { - LOG_W(HW,"Clock source set neither in usrp_args nor on command line, using default!\n"); - } - } - else { - if (openair0_cfg[0].clock_source != unset) { - LOG_W(HW,"Clock source set in both usrp_args and in clock_source, ingnoring the latter!\n"); - } - } - - if (args.find("time_source")==std::string::npos) { - if (openair0_cfg[0].time_source == internal) { - s->usrp->set_time_source("internal"); - LOG_I(HW,"Setting time source to internal\n"); - } - else if (openair0_cfg[0].time_source == external ) { - s->usrp->set_time_source("external"); - LOG_I(HW,"Setting time source to external\n"); - } - else if (openair0_cfg[0].time_source==gpsdo) { - s->usrp->set_time_source("gpsdo"); - LOG_I(HW,"Setting time source to gpsdo\n"); - } - else { - LOG_W(HW,"Time source set neither in usrp_args nor on command line, using default!\n"); - } - } - else { - 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"); - } - } - - - if (s->usrp->get_clock_source(0) == "gpsdo") { - s->use_gps = 1; - - if (sync_to_gps(device)==EXIT_SUCCESS) { - LOG_I(HW,"USRP synced with GPS!\n"); - } else { - LOG_I(HW,"USRP fails to sync with GPS. Exiting.\n"); - exit(EXIT_FAILURE); - } - } else { - if (s->usrp->get_time_source(0) == "external") { - usrp_sync_pps(s); - } else { - s->usrp->set_time_next_pps(uhd::time_spec_t(0.0)); - } - - if (s->usrp->get_clock_source(0) == "external") { - if (check_ref_locked(s,0)) { - LOG_I(HW,"USRP locked to external reference!\n"); - } else { - LOG_I(HW,"Failed to lock to external reference. Exiting.\n"); - exit(EXIT_FAILURE); - } - } - } - if (device->type==USRP_X300_DEV) { openair0_cfg[0].rx_gain_calib_table = calib_table_x310; std::cerr << "-- Using calibration table: calib_table_x310" << std::endl; @@ -1470,8 +1397,70 @@ extern "C" { } } - //s->usrp->set_clock_source("external"); - //s->usrp->set_time_source("external"); + if (args.find("clock_source") == std::string::npos) { + if (openair0_cfg[0].clock_source == internal) { + s->usrp->set_clock_source("internal"); + LOG_I(HW, "Setting clock source to internal\n"); + } else if (openair0_cfg[0].clock_source == external) { + s->usrp->set_clock_source("external"); + LOG_I(HW, "Setting clock source to external\n"); + } else if (openair0_cfg[0].clock_source == gpsdo) { + s->usrp->set_clock_source("gpsdo"); + LOG_I(HW, "Setting clock source to gpsdo\n"); + } else { + LOG_W(HW, "Clock source set neither in usrp_args nor on command line, using default!\n"); + } + } else { + if (openair0_cfg[0].clock_source != unset) { + LOG_W(HW, "Clock source set in both usrp_args and in clock_source, ingnoring the latter!\n"); + } + } + + if (args.find("time_source") == std::string::npos) { + if (openair0_cfg[0].time_source == internal) { + s->usrp->set_time_source("internal"); + LOG_I(HW, "Setting time source to internal\n"); + } else if (openair0_cfg[0].time_source == external) { + s->usrp->set_time_source("external"); + LOG_I(HW, "Setting time source to external\n"); + } else if (openair0_cfg[0].time_source == gpsdo) { + s->usrp->set_time_source("gpsdo"); + LOG_I(HW, "Setting time source to gpsdo\n"); + } else { + LOG_W(HW, "Time source set neither in usrp_args nor on command line, using default!\n"); + } + } else { + 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"); + } + } + + if (s->usrp->get_clock_source(0) == "gpsdo") { + s->use_gps = 1; + + if (sync_to_gps(device) == EXIT_SUCCESS) { + LOG_I(HW, "USRP synced with GPS!\n"); + } else { + LOG_I(HW, "USRP fails to sync with GPS. Exiting.\n"); + exit(EXIT_FAILURE); + } + } else { + if (s->usrp->get_time_source(0) == "external") { + usrp_sync_pps(s); + } else { + s->usrp->set_time_next_pps(uhd::time_spec_t(0.0)); + } + + if (s->usrp->get_clock_source(0) == "external") { + if (check_ref_locked(s, 0)) { + LOG_I(HW, "USRP locked to external reference!\n"); + } else { + LOG_I(HW, "Failed to lock to external reference. Exiting.\n"); + exit(EXIT_FAILURE); + } + } + } + // display USRP settings LOG_I(HW,"Actual master clock: %fMHz...\n",s->usrp->get_master_clock_rate()/1e6); LOG_I(HW,"Actual clock source %s...\n",s->usrp->get_clock_source(0).c_str()); From 677a16a4a9dcc5728949d787b011c345b07ffc59 Mon Sep 17 00:00:00 2001 From: Shubhika Garg Date: Mon, 6 Oct 2025 15:44:00 +0200 Subject: [PATCH 930/964] ci(docker): push ARM64 and AMD64 images to DockerHub - On PUSH events, if image build stages succeed, trigger DockerHub push stage - Build the images, then trigger the Push to DockerHub stage - Publish Jetson (ARM64/v8) and AMD64 images under the same tag on DockerHub --- ci-scripts/Jenkinsfile-GitLab-Container | 34 ++++++++++++------------- ci-scripts/Jenkinsfile-push-registry | 9 +++---- 2 files changed, 20 insertions(+), 23 deletions(-) diff --git a/ci-scripts/Jenkinsfile-GitLab-Container b/ci-scripts/Jenkinsfile-GitLab-Container index 44d857f1dc..3301c133ec 100644 --- a/ci-scripts/Jenkinsfile-GitLab-Container +++ b/ci-scripts/Jenkinsfile-GitLab-Container @@ -267,6 +267,23 @@ pipeline { } } } + stage ("DockerHub-Push") { + when { expression {doBuild && "PUSH".equals(env.gitlabActionType)} } + steps { + script { + triggerSlaveJob ('RAN-DockerHub-Push', 'DockerHub-Push') + } + } + post { + failure { + script { + echo "Push to Docker-Hub KO" + currentBuild.result = 'FAILURE' + failingStages += '\n * RAN-DockerHub-Push' + } + } + } + } stage ("Image Test Processes") { when { expression {doBuild} } parallel { @@ -756,23 +773,6 @@ pipeline { } } } - stage ("DockerHub-Push") { - when { expression {doBuild && "PUSH".equals(env.gitlabActionType)} } - steps { - script { - triggerSlaveJob ('RAN-DockerHub-Push', 'DockerHub-Push') - } - } - post { - failure { - script { - echo "Push to Docker-Hub KO" - currentBuild.result = 'FAILURE' - failingStages += '\n * RAN-DockerHub-Push' - } - } - } - } } post { success { diff --git a/ci-scripts/Jenkinsfile-push-registry b/ci-scripts/Jenkinsfile-push-registry index 8f54d352b1..ccd91e28ff 100644 --- a/ci-scripts/Jenkinsfile-push-registry +++ b/ci-scripts/Jenkinsfile-push-registry @@ -84,12 +84,9 @@ pipeline { sh "docker login -u ${DH_Username} -p ${DH_Password} > /dev/null 2>&1" sh "docker login -u oaicicd -p oaicicd ${OAI_Registry} > /dev/null 2>&1" listOfImages.eachWithIndex { item, iindex -> - sh "docker pull --quiet ${OAI_Registry}/${item}:develop-${WEEK_SHA}" - sh "docker image tag ${OAI_Registry}/${item}:develop-${WEEK_SHA} ${DH_Account}/${item}:develop" - sh "docker image tag ${OAI_Registry}/${item}:develop-${WEEK_SHA} ${DH_Account}/${item}:${WEEK_TAG}" - sh "docker push --quiet ${DH_Account}/${item}:${WEEK_TAG}" - sh "docker push --quiet ${DH_Account}/${item}:develop" - sh "docker rmi ${DH_Account}/${item}:${WEEK_TAG} ${DH_Account}/${item}:develop ${OAI_Registry}/${item}:develop-${WEEK_SHA}" + sh "docker rmi ${DH_Account}/${item}:${WEEK_TAG} ${DH_Account}/${item}:develop || true" + sh "docker buildx imagetools create --tag ${DH_Account}/${item}:${WEEK_TAG} ${OAI_Registry}/${item}:armv8_develop-${WEEK_SHA} ${OAI_Registry}/${item}:develop-${WEEK_SHA}" + sh "docker buildx imagetools create --tag ${DH_Account}/${item}:develop ${OAI_Registry}/${item}:armv8_develop-${WEEK_SHA} ${OAI_Registry}/${item}:develop-${WEEK_SHA}" } // Proxy is not following the same pattern. sh "docker image tag proxy:develop ${DH_Account}/proxy:develop" From 121937ad4c86d1a19c40eb6cde9deb7ff54c13d3 Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 23 Jun 2025 10:38:05 +0200 Subject: [PATCH 931/964] input simplification in nr_pdsch_channel_estimation --- .../nr_dl_channel_estimation.c | 39 ++++++++----------- openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h | 29 ++++++-------- openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 9 +---- 3 files changed, 29 insertions(+), 48 deletions(-) diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c index 8703c1c774..515e0f5ff5 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c @@ -1253,30 +1253,24 @@ void NFAPI_NR_DMRS_TYPE2_average_prb(NR_DL_FRAME_PARMS *frame_parms, #endif } -int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, - const UE_nr_rxtx_proc_t *proc, - int nl, - unsigned short p, - unsigned char symbol, - unsigned char nscid, - unsigned short scrambling_id, - unsigned short BWPStart, - uint8_t config_type, - int n_dmrs_cdm_groups, - uint16_t rb_offset, - unsigned short bwp_start_subcarrier, - unsigned short nb_rb_pdsch, - uint32_t pdsch_est_size, - int32_t dl_ch_estimates[][pdsch_est_size], - int rxdataFsize, - c16_t rxdataF[][rxdataFsize], - uint32_t *nvar) +void nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, + const UE_nr_rxtx_proc_t *proc, + const fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch, + int nl, + unsigned short p, + unsigned char symbol, + uint32_t pdsch_est_size, + int32_t dl_ch_estimates[][pdsch_est_size], + int rxdataFsize, + c16_t rxdataF[][rxdataFsize], + uint32_t *nvar) { // int gNB_id = proc->gNB_id; int slot = proc->nr_slot_rx; NR_DL_FRAME_PARMS *fp = &ue->frame_parms; const int ch_offset = fp->ofdm_symbol_size * symbol; const int symbol_offset = fp->ofdm_symbol_size * symbol; + int bwp_start_subcarrier = ue->frame_parms.first_carrier_offset + (dlsch->BWPStart + dlsch->start_rb) * 12; #ifdef DEBUG_PDSCH printf( @@ -1292,13 +1286,15 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, #endif // generate pilot for gNB port number 1000+p + int config_type = dlsch->dmrsConfigType; + int rb_offset = dlsch->rb_offset; + int nb_rb_pdsch = dlsch->number_rbs; int8_t delta = get_delta(p, config_type); - c16_t pilot[3280] __attribute__((aligned(16))); // Note: pilot returned by the following function is already the complex conjugate of the transmitted DMRS - float beta_dmrs_pdsch = get_beta_dmrs(n_dmrs_cdm_groups, config_type == NFAPI_NR_DMRS_TYPE2); + float beta_dmrs_pdsch = get_beta_dmrs(dlsch->n_dmrs_cdm_groups, config_type == NFAPI_NR_DMRS_TYPE2); int16_t dmrs_scaling = (int16_t)((1 / beta_dmrs_pdsch) * (1 << 14)); - const uint32_t *gold = nr_gold_pdsch(fp->N_RB_DL, fp->symbols_per_slot, scrambling_id, nscid, slot, symbol); + const uint32_t *gold = nr_gold_pdsch(fp->N_RB_DL, fp->symbols_per_slot, dlsch->dlDmrsScramblingId, dlsch->nscid, slot, symbol); nr_pdsch_dmrs_rx(ue, slot, gold, pilot, 1000 + p, 0, nb_rb_pdsch + rb_offset, config_type, dmrs_scaling); delay_t delay = {0}; @@ -1351,7 +1347,6 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, } #endif } - return 0; } /******************************************************************* diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h index b1bc3ca8e1..09ed452830 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h @@ -78,24 +78,17 @@ int nr_pbch_channel_estimation(const NR_DL_FRAME_PARMS *fp, bool sidelink, uint Nid); -int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, - const UE_nr_rxtx_proc_t *proc, - int nl, - unsigned short p, - unsigned char symbol, - unsigned char nscid, - unsigned short scrambling_id, - unsigned short BWPStart, - uint8_t config_type, - int n_dmrs_cdm_groups, - uint16_t rb_offset, - unsigned short bwp_start_subcarrier, - unsigned short nb_rb_pdsch, - uint32_t pdsch_est_size, - int32_t dl_ch_estimates[][pdsch_est_size], - int rxdataFsize, - c16_t rxdataF[][rxdataFsize], - uint32_t *nvar); +void nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, + const UE_nr_rxtx_proc_t *proc, + const fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch, + int nl, + unsigned short p, + unsigned char symbol, + uint32_t pdsch_est_size, + int32_t dl_ch_estimates[][pdsch_est_size], + int rxdataFsize, + c16_t rxdataF[][rxdataFsize], + uint32_t *nvar); int nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms, PHY_VARS_NR_UE *ue, diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index 89b8ed91a7..8d56cf65ff 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -641,17 +641,10 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, uint32_t nvar_tmp = 0; nr_pdsch_channel_estimation(ue, proc, + dlschCfg, nl, get_dmrs_port(nl, dlschCfg->dmrs_ports), m, - dlschCfg->nscid, - dlschCfg->dlDmrsScramblingId, - dlschCfg->BWPStart, - dlschCfg->dmrsConfigType, - dlschCfg->n_dmrs_cdm_groups, - dlschCfg->rb_offset, - ue->frame_parms.first_carrier_offset + (dlschCfg->BWPStart + dlschCfg->start_rb) * 12, - dlschCfg->number_rbs, pdsch_est_size, pdsch_dl_ch_estimates, ue->frame_parms.samples_per_slot_wCP, From e70a2b3cc10e9027ceaaa645425fd58a77eee33d Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 23 Jun 2025 12:35:11 +0200 Subject: [PATCH 932/964] use ad hoc UE FAPI information for PDSCH DMRS reference point --- nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h | 4 +--- openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c | 2 +- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 7 ++----- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h index 6bea8f55cc..dc52f1de2a 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h @@ -476,9 +476,7 @@ typedef struct { uint16_t start_rb; uint16_t number_symbols; uint16_t start_symbol; - // TODO this is a workaround to make it work - // implementation is also a bunch of workarounds - uint16_t rb_offset; + uint8_t refPoint; uint16_t dlDmrsSymbPos; uint8_t dmrsConfigType; uint8_t prb_bundling_size_ind; diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c index 515e0f5ff5..4c59da3cb0 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c @@ -1287,7 +1287,7 @@ void nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, // generate pilot for gNB port number 1000+p int config_type = dlsch->dmrsConfigType; - int rb_offset = dlsch->rb_offset; + int rb_offset = dlsch->start_rb + (dlsch->refPoint ? 0 : dlsch->BWPStart); int nb_rb_pdsch = dlsch->number_rbs; int8_t delta = get_delta(p, config_type); c16_t pilot[3280] __attribute__((aligned(16))); diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 3d9d5fba43..7f8db35d9f 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -818,10 +818,7 @@ static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac, return -1; } - dlsch_pdu->rb_offset = dlsch_pdu->start_rb + dlsch_pdu->BWPStart; - - if (mac->get_sib1) - dlsch_pdu->rb_offset -= dlsch_pdu->BWPStart; + dlsch_pdu->refPoint = mac->get_sib1 ? 1 : 0; /* TIME_DOM_RESOURCE_ASSIGNMENT */ int dmrs_typeA_pos = mac->dmrs_TypeA_Position; @@ -1163,7 +1160,7 @@ static int nr_ue_process_dci_dl_11(NR_UE_MAC_INST_t *mac, LOG_W(MAC, "[%d.%d] Invalid frequency_domain_assignment. Possibly due to false DCI. Ignoring DCI!\n", frame, slot); return -1; } - dlsch_pdu->rb_offset = dlsch_pdu->start_rb + dlsch_pdu->BWPStart; + dlsch_pdu->refPoint = 0; /* TIME_DOM_RESOURCE_ASSIGNMENT */ int dmrs_typeA_pos = mac->dmrs_TypeA_Position; int mux_pattern = 1; From 99e4f54d61c7fe2bf354a3e021cad445d16c3a20 Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 24 Jun 2025 13:54:35 +0200 Subject: [PATCH 933/964] type0 DLSCH frequency allocation for channel estimation --- .../nr_dl_channel_estimation.c | 114 ++++++++++-------- openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h | 1 + .../NR_UE_TRANSPORT/nr_transport_proto_ue.h | 1 - .../PHY/NR_UE_TRANSPORT/nr_transport_ue.h | 6 + openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 51 +++++++- 5 files changed, 122 insertions(+), 51 deletions(-) diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c index 4c59da3cb0..9e76b2f85f 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c @@ -938,6 +938,7 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, } void NFAPI_NR_DMRS_TYPE1_linear_interp(NR_DL_FRAME_PARMS *frame_parms, + const freq_alloc_bitmap_t *freq_alloc, c16_t *rxF, c16_t *pil, c16_t *dl_ch, @@ -948,45 +949,49 @@ void NFAPI_NR_DMRS_TYPE1_linear_interp(NR_DL_FRAME_PARMS *frame_parms, { c16_t *dl_ch0 = dl_ch; int re_offset = bwp_start_subcarrier % frame_parms->ofdm_symbol_size; - c16_t dl_ls_est[frame_parms->ofdm_symbol_size] __attribute__((aligned(32))); memset(dl_ls_est, 0, sizeof(dl_ls_est)); - - int nest_count = 0; - uint64_t noise_amp2 = 0; - - for (int pilot_cnt = 0; pilot_cnt < 6 * nb_rb_pdsch; pilot_cnt += 2) { - c16_t ch_l = c16mulShift(*pil, rxF[re_offset], 15); + int idx = 0; + for (int rb = freq_alloc->start; rb < freq_alloc->start + nb_rb_pdsch; rb++) { + bool allocated_rb = (freq_alloc->bitmap[rb / 8] >> (rb % 8)) & 0x01; + if (allocated_rb) { + for (int pilot_cnt = 0; pilot_cnt < 6; pilot_cnt += 2) { + c16_t ch_l = c16mulShift(*pil, rxF[re_offset], 15); #ifdef DEBUG_PDSCH - printf("pilot %3d: pil -> (%6d,%6d), rxF -> (%4d,%4d), ch -> (%4d,%4d) \n", pilot_cnt, pil->r, pil->i, rxF[re_offset].r, rxF[re_offset].i, ch_l.r, ch_l.i); + printf("pilot %3d: pil -> (%6d,%6d), rxF -> (%4d,%4d), ch -> (%4d,%4d) \n", pilot_cnt, pil->r, pil->i, rxF[re_offset].r, rxF[re_offset].i, ch_l.r, ch_l.i); #endif - pil++; - re_offset = (re_offset + 2) % frame_parms->ofdm_symbol_size; - c16_t ch_r = c16mulShift(*pil, rxF[re_offset], 15); + pil++; + re_offset = (re_offset + 2) % frame_parms->ofdm_symbol_size; + c16_t ch_r = c16mulShift(*pil, rxF[re_offset], 15); #ifdef DEBUG_PDSCH - printf("pilot %3d: pil -> (%6d,%6d), rxF -> (%4d,%4d), ch -> (%4d,%4d) \n", pilot_cnt + 1, pil->r, pil->i, rxF[re_offset].r, rxF[re_offset].i, ch_r.r, ch_r.i); + printf("pilot %3d: pil -> (%6d,%6d), rxF -> (%4d,%4d), ch -> (%4d,%4d) \n", pilot_cnt + 1, pil->r, pil->i, rxF[re_offset].r, rxF[re_offset].i, ch_r.r, ch_r.i); #endif - c16_t ch = c16addShift(ch_l, ch_r, 1); - pil++; - re_offset = (re_offset + 2) % frame_parms->ofdm_symbol_size; - for (int k = pilot_cnt << 1; k < (pilot_cnt << 1) + 4; k++) { - dl_ls_est[k] = ch; + c16_t ch = c16addShift(ch_l, ch_r, 1); + pil++; + re_offset = (re_offset + 2) % frame_parms->ofdm_symbol_size; + for (int k = 0; k < 4; k++) { + dl_ls_est[idx] = ch; + idx++; + } + } + } else { + pil += 6; + re_offset = (re_offset + 12) % frame_parms->ofdm_symbol_size; } } - c16_t ch_estimates_time[frame_parms->ofdm_symbol_size] __attribute__((aligned(32))); nr_est_delay(frame_parms->ofdm_symbol_size, dl_ls_est, ch_estimates_time, delay); int delay_idx = get_delay_idx(delay->est_delay, MAX_DELAY_COMP); c16_t *dl_delay_table = frame_parms->delay_table[delay_idx]; - for (int pilot_cnt = 0; pilot_cnt < 6 * nb_rb_pdsch; pilot_cnt++) { + for (int pilot_cnt = 0; pilot_cnt < idx >> 1; pilot_cnt++) { int k = pilot_cnt << 1; c16_t ch = c16mulShift(dl_ls_est[k], dl_delay_table[k], 8); if (pilot_cnt == 0) { // Treat first pilot c16multaddVectRealComplex(filt16_ul_p0, &ch, dl_ch, 16); } else if (pilot_cnt == 1 || pilot_cnt == 2) { c16multaddVectRealComplex(filt16_ul_p1p2, &ch, dl_ch, 16); - } else if (pilot_cnt == 6 * nb_rb_pdsch - 1) { // Treat last pilot + } else if (pilot_cnt == (idx >> 1) - 1) { // Treat last pilot c16multaddVectRealComplex(filt16_ul_last, &ch, dl_ch, 16); } else { // Treat middle pilots c16multaddVectRealComplex(filt16_ul_middle, &ch, dl_ch, 16); @@ -998,9 +1003,11 @@ void NFAPI_NR_DMRS_TYPE1_linear_interp(NR_DL_FRAME_PARMS *frame_parms, // Revert delay dl_ch = dl_ch0; + int nest_count = 0; + uint64_t noise_amp2 = 0; int inv_delay_idx = get_delay_idx(-delay->est_delay, MAX_DELAY_COMP); c16_t *dl_inv_delay_table = frame_parms->delay_table[inv_delay_idx]; - for (int k = 0; k < 12 * nb_rb_pdsch; k++) { + for (int k = 0; k < idx; k++) { dl_ch[k] = c16mulShift(dl_ch[k], dl_inv_delay_table[k], 8); noise_amp2 += c16amp2(c16sub(dl_ls_est[k], dl_ch[k])); nest_count++; @@ -1096,6 +1103,7 @@ void NFAPI_NR_DMRS_TYPE1_average_prb(NR_DL_FRAME_PARMS *frame_parms, } void NFAPI_NR_DMRS_TYPE2_linear_interp(NR_DL_FRAME_PARMS *frame_parms, + const freq_alloc_bitmap_t *freq_alloc, c16_t *rxF, c16_t *pil, c16_t *dl_ch, @@ -1106,45 +1114,50 @@ void NFAPI_NR_DMRS_TYPE2_linear_interp(NR_DL_FRAME_PARMS *frame_parms, { int re_offset = bwp_start_subcarrier % frame_parms->ofdm_symbol_size; c16_t *dl_ch0 = dl_ch; - c16_t dl_ls_est[frame_parms->ofdm_symbol_size] __attribute__((aligned(32))); memset(dl_ls_est, 0, sizeof(dl_ls_est)); - - int nest_count = 0; - uint64_t noise_amp2 = 0; - - for (int pilot_cnt = 0; pilot_cnt < 4 * nb_rb_pdsch; pilot_cnt += 2) { - c16_t ch_l = c16mulShift(*pil, rxF[re_offset], 15); + int idx = 0; + for (int rb = freq_alloc->start; rb < freq_alloc->start + nb_rb_pdsch; rb++) { + bool allocated_rb = (freq_alloc->bitmap[rb / 8] >> (rb % 8)) & 0x01; + if (allocated_rb) { + for (int pilot_cnt = 0; pilot_cnt < 4; pilot_cnt += 2) { + c16_t ch_l = c16mulShift(*pil, rxF[re_offset], 15); #ifdef DEBUG_PDSCH - printf("pilot %3d: pil -> (%6d,%6d), rxF -> (%4d,%4d), ch -> (%4d,%4d) \n", pilot_cnt, pil->r, pil->i, rxF[re_offset].r, rxF[re_offset].i, ch_l.r, ch_l.i); + printf("pilot %3d: pil -> (%6d,%6d), rxF -> (%4d,%4d), ch -> (%4d,%4d) \n", pilot_cnt, pil->r, pil->i, rxF[re_offset].r, rxF[re_offset].i, ch_l.r, ch_l.i); #endif - pil++; - re_offset = (re_offset + 1) % frame_parms->ofdm_symbol_size; - c16_t ch_r = c16mulShift(*pil, rxF[re_offset], 15); + pil++; + re_offset = (re_offset + 1) % frame_parms->ofdm_symbol_size; + c16_t ch_r = c16mulShift(*pil, rxF[re_offset], 15); #ifdef DEBUG_PDSCH - printf("pilot %3d: pil -> (%6d,%6d), rxF -> (%4d,%4d), ch -> (%4d,%4d) \n", pilot_cnt + 1, pil->r, pil->i, rxF[re_offset].r, rxF[re_offset].i, ch_r.r, ch_r.i); + printf("pilot %3d: pil -> (%6d,%6d), rxF -> (%4d,%4d), ch -> (%4d,%4d) \n", pilot_cnt + 1, pil->r, pil->i, rxF[re_offset].r, rxF[re_offset].i, ch_r.r, ch_r.i); #endif - c16_t ch = c16addShift(ch_l, ch_r, 1); - for (int k = 3 * pilot_cnt; k < (3 * pilot_cnt) + 6; k++) { - dl_ls_est[k] = ch; + c16_t ch = c16addShift(ch_l, ch_r, 1); + pil++; + re_offset = (re_offset + 5) % frame_parms->ofdm_symbol_size; + for (int k = 0; k < 6; k++) { + dl_ls_est[idx] = ch; + idx++; + } + } + } else { + pil += 4; + re_offset = (re_offset + 12) % frame_parms->ofdm_symbol_size; } - pil++; - re_offset = (re_offset + 5) % frame_parms->ofdm_symbol_size; } c16_t ch_estimates_time[frame_parms->ofdm_symbol_size] __attribute__((aligned(32))); nr_est_delay(frame_parms->ofdm_symbol_size, dl_ls_est, ch_estimates_time, delay); int delay_idx = get_delay_idx(delay->est_delay, MAX_DELAY_COMP); c16_t *dl_delay_table = frame_parms->delay_table[delay_idx]; - - for (int pilot_cnt = 0; pilot_cnt < 6 * nb_rb_pdsch; pilot_cnt++) { - int k = (pilot_cnt / 3) * 6; + // kept the same as before but unclear why would it be nb_rb_pdsch / 2 and not / 3 + for (int pilot_cnt = 0; pilot_cnt < idx >> 1; pilot_cnt++) { + int k = pilot_cnt << 1; c16_t ch = c16mulShift(dl_ls_est[k], dl_delay_table[k], 8); if (pilot_cnt == 0) { // Treat first pilot c16multaddVectRealComplex(filt16_ul_p0, &ch, dl_ch, 16); } else if (pilot_cnt == 1 || pilot_cnt == 2) { c16multaddVectRealComplex(filt16_ul_p1p2, &ch, dl_ch, 16); - } else if (pilot_cnt == 6 * nb_rb_pdsch - 1) { // Treat last pilot + } else if (pilot_cnt == (idx >> 1) - 1) { // Treat last pilot c16multaddVectRealComplex(filt16_ul_last, &ch, dl_ch, 16); } else { // Treat middle pilots c16multaddVectRealComplex(filt16_ul_middle, &ch, dl_ch, 16); @@ -1156,9 +1169,11 @@ void NFAPI_NR_DMRS_TYPE2_linear_interp(NR_DL_FRAME_PARMS *frame_parms, // Revert delay dl_ch = dl_ch0; + int nest_count = 0; + uint64_t noise_amp2 = 0; int inv_delay_idx = get_delay_idx(-delay->est_delay, MAX_DELAY_COMP); c16_t *dl_inv_delay_table = frame_parms->delay_table[inv_delay_idx]; - for (int k = 0; k < 12 * nb_rb_pdsch; k++) { + for (int k = 0; k < idx; k++) { dl_ch[k] = c16mulShift(dl_ch[k], dl_inv_delay_table[k], 8); noise_amp2 += c16amp2(c16sub(dl_ls_est[k], dl_ch[k])); nest_count++; @@ -1256,6 +1271,7 @@ void NFAPI_NR_DMRS_TYPE2_average_prb(NR_DL_FRAME_PARMS *frame_parms, void nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, const fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch, + const freq_alloc_bitmap_t *freq_alloc, int nl, unsigned short p, unsigned char symbol, @@ -1270,7 +1286,7 @@ void nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, NR_DL_FRAME_PARMS *fp = &ue->frame_parms; const int ch_offset = fp->ofdm_symbol_size * symbol; const int symbol_offset = fp->ofdm_symbol_size * symbol; - int bwp_start_subcarrier = ue->frame_parms.first_carrier_offset + (dlsch->BWPStart + dlsch->start_rb) * 12; + int bwp_start_subcarrier = fp->first_carrier_offset + (dlsch->BWPStart + freq_alloc->start) * 12; #ifdef DEBUG_PDSCH printf( @@ -1287,8 +1303,8 @@ void nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, // generate pilot for gNB port number 1000+p int config_type = dlsch->dmrsConfigType; - int rb_offset = dlsch->start_rb + (dlsch->refPoint ? 0 : dlsch->BWPStart); - int nb_rb_pdsch = dlsch->number_rbs; + int rb_offset = freq_alloc->start + (dlsch->refPoint ? 0 : dlsch->BWPStart); + int nb_rb_pdsch = freq_alloc->end - freq_alloc->start + 1; int8_t delta = get_delta(p, config_type); c16_t pilot[3280] __attribute__((aligned(16))); // Note: pilot returned by the following function is already the complex conjugate of the transmitted DMRS @@ -1311,7 +1327,8 @@ void nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, memset(dl_ch, 0, sizeof(*dl_ch) * fp->ofdm_symbol_size); if (config_type == NFAPI_NR_DMRS_TYPE1 && ue->chest_freq == 0) { - NFAPI_NR_DMRS_TYPE1_linear_interp(&ue->frame_parms, + NFAPI_NR_DMRS_TYPE1_linear_interp(fp, + freq_alloc, rxF, &pilot[6 * rb_offset], dl_ch, @@ -1322,6 +1339,7 @@ void nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, } else if (config_type == NFAPI_NR_DMRS_TYPE2 && ue->chest_freq == 0) { NFAPI_NR_DMRS_TYPE2_linear_interp(fp, + freq_alloc, rxF, &pilot[4 * rb_offset], dl_ch, @@ -1331,9 +1349,11 @@ void nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, nvar); } else if (config_type == NFAPI_NR_DMRS_TYPE1) { + AssertFatal(dlsch->resource_alloc == 1, "PRB average in channel estimation not supported for type0 DLSCH\n"); NFAPI_NR_DMRS_TYPE1_average_prb(fp, rxF, &pilot[6 * rb_offset], dl_ch, bwp_start_subcarrier, nb_rb_pdsch); } else { + AssertFatal(dlsch->resource_alloc == 1, "PRB average in channel estimation not supported for type0 DLSCH\n"); NFAPI_NR_DMRS_TYPE2_average_prb(fp, rxF, &pilot[4 * rb_offset], dl_ch, bwp_start_subcarrier, nb_rb_pdsch); } diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h index 09ed452830..9f38b49903 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h @@ -81,6 +81,7 @@ int nr_pbch_channel_estimation(const NR_DL_FRAME_PARMS *fp, void nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, const fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch, + const freq_alloc_bitmap_t *freq_alloc, int nl, unsigned short p, unsigned char symbol, diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h index 0c519451a5..6eaa0ecec1 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h @@ -67,7 +67,6 @@ typedef struct pdsch_scope_req_s { /** \brief This function initialises structures for DLSCH at UE */ void nr_ue_dlsch_init(NR_UE_DLSCH_t *dlsch_list, int num_dlsch, uint8_t max_ldpc_iterations); - void nr_conjch0_mult_ch1(c16_t *ch0, c16_t *ch1, c16_t *ch0conj_ch1, unsigned short nb_rb, unsigned char output_shift0); /** \brief This is the alternative top-level entry point for DLSCH decoding in UE. diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h index 26f41b1fd3..67d5f45cef 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h @@ -38,6 +38,12 @@ #include "nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h" #include "../NR_TRANSPORT/nr_transport_common_proto.h" +typedef struct { + int start; + int end; + uint8_t bitmap[36]; +} freq_alloc_bitmap_t; + typedef struct { /// Index of current HARQ round for this ULSCH uint8_t round; diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index 8d56cf65ff..d442bc6207 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -577,6 +577,43 @@ int nr_ue_pdcch_procedures(PHY_VARS_NR_UE *ue, return (dci_ind.number_of_dcis); } +static freq_alloc_bitmap_t set_start_end_from_bitmap(int size, int alloc_size, const uint8_t bitmap[alloc_size]) +{ + freq_alloc_bitmap_t alloc = { + .start = size, + .end = 0 + }; + + for (int start = 0; start < size; start++) { + if ((bitmap[start / 8] >> start % 8) & 0x1) { + alloc.start = start; + break; + } + } + AssertFatal(alloc.start < size, "Frequency allocation bitmap empty\n"); + for (int end = size - 1; end > 0; end--) { + if ((bitmap[end / 8] >> end % 8) & 0x1) { + alloc.end = end; + break; + } + } + AssertFatal(alloc.end > 0, "Frequency allocation bitmap empty\n"); + memcpy(alloc.bitmap, bitmap, alloc_size * sizeof(uint8_t)); + return alloc; +} + +static freq_alloc_bitmap_t set_bitmap_from_start_size(int start, int size) +{ + freq_alloc_bitmap_t alloc = { + .start = start, + .end = start + size - 1 + }; + memset(alloc.bitmap, 0, 36 * sizeof(uint8_t)); + for (int i = start; i < size + start; i++) + alloc.bitmap[i / 8] += 1 << (i % 8); + return alloc; +} + static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, NR_UE_DLSCH_t dlsch[2], @@ -595,8 +632,15 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, // dlsch0_harq contains the previous transmissions data for this harq pid NR_DL_UE_HARQ_t *dlsch0_harq = &ue->dl_harq_processes[0][harq_pid]; + freq_alloc_bitmap_t freq_alloc = {0}; + if (dlschCfg->resource_alloc == 0) { + int alloc_size = (dlschCfg->BWPSize / 8) + (dlschCfg->BWPSize % 8 > 0); + freq_alloc = set_start_end_from_bitmap(dlschCfg->BWPSize, alloc_size, dlschCfg->rb_bitmap); + } else + freq_alloc = set_bitmap_from_start_size(dlschCfg->start_rb, dlschCfg->number_rbs); + LOG_D(PHY, - "[UE %d] frame_rx %d, nr_slot_rx %d, harq_pid %d (%d), BWP start %d, rb_start %d, nb_rb %d, symbol_start %d, nb_symbols %d, DMRS mask " + "[UE %d] frame_rx %d, nr_slot_rx %d, harq_pid %d (%d), BWP start %d, start RB %d, end RB %d, symbol_start %d, nb_symbols %d, DMRS mask " "%x, Nl %d\n", ue->Mod_id, frame_rx, @@ -604,8 +648,8 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, harq_pid, dlsch0_harq->status, dlschCfg->BWPStart, - dlschCfg->start_rb, - dlschCfg->number_rbs, + freq_alloc.start, + freq_alloc.end, dlschCfg->start_symbol, dlschCfg->number_symbols, dlschCfg->dlDmrsSymbPos, @@ -642,6 +686,7 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, nr_pdsch_channel_estimation(ue, proc, dlschCfg, + &freq_alloc, nl, get_dmrs_port(nl, dlschCfg->dmrs_ports), m, From 7d0bf3be51e97b49c9ed2aee2411656565d38f63 Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 24 Jun 2025 14:41:31 +0200 Subject: [PATCH 934/964] include information about number of PRBs in frequency allocation structure --- openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h | 2 +- .../PHY/NR_UE_ESTIMATION/nr_ue_measurements.c | 6 +- .../PHY/NR_UE_TRANSPORT/nr_transport_ue.h | 1 + openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 58 ++++++++----------- 4 files changed, 29 insertions(+), 38 deletions(-) diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h index 9f38b49903..30464f0c8b 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h @@ -102,7 +102,7 @@ int nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms, void nr_ue_measurements(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, - NR_UE_DLSCH_t *dlsch, + int number_rbs, uint32_t pdsch_est_size, int32_t dl_ch_estimates[][pdsch_est_size]); diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c b/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c index 73776ebf26..36b8d8a673 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c @@ -48,7 +48,7 @@ void nr_ue_measurements(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, - NR_UE_DLSCH_t *dlsch, + int number_rbs, uint32_t pdsch_est_size, int32_t dl_ch_estimates[][pdsch_est_size]) { @@ -56,8 +56,6 @@ void nr_ue_measurements(PHY_VARS_NR_UE *ue, int aarx, aatx, gNB_id = 0; NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; int ch_offset = frame_parms->ofdm_symbol_size*2; - int N_RB_DL = dlsch->dlsch_config.number_rbs; - ue->measurements.nb_antennas_rx = frame_parms->nb_antennas_rx; allocCast3D(rx_spatial_power, @@ -85,7 +83,7 @@ void nr_ue_measurements(PHY_VARS_NR_UE *ue, ue->measurements.rx_power[gNB_id][aarx] = 0; for (aatx = 0; aatx < frame_parms->nb_antenna_ports_gNB; aatx++){ - const int z=signal_energy_nodc((c16_t*)&dl_ch_estimates[gNB_id][ch_offset], N_RB_DL * NR_NB_SC_PER_RB); + const int z = signal_energy_nodc((c16_t*)&dl_ch_estimates[gNB_id][ch_offset], number_rbs * NR_NB_SC_PER_RB); rx_spatial_power[gNB_id][aatx][aarx] = z; if (rx_spatial_power[gNB_id][aatx][aarx] < 0) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h index 67d5f45cef..fd4fe3a1b7 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h @@ -41,6 +41,7 @@ typedef struct { int start; int end; + int num_rbs; uint8_t bitmap[36]; } freq_alloc_bitmap_t; diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index d442bc6207..591ea711f3 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -417,28 +417,25 @@ void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, n stop_meas_nr_ue_phy(ue, PHY_PROC_TX); } -void nr_ue_measurement_procedures(uint16_t l, - PHY_VARS_NR_UE *ue, - const UE_nr_rxtx_proc_t *proc, - NR_UE_DLSCH_t *dlsch, - uint32_t pdsch_est_size, - int32_t dl_ch_estimates[][pdsch_est_size]) +static void nr_ue_measurement_procedures(uint16_t l, + PHY_VARS_NR_UE *ue, + const UE_nr_rxtx_proc_t *proc, + int number_rbs, + uint32_t pdsch_est_size, + int32_t dl_ch_estimates[][pdsch_est_size]) { NR_DL_FRAME_PARMS *frame_parms=&ue->frame_parms; int nr_slot_rx = proc->nr_slot_rx; int gNB_id = proc->gNB_id; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_MEASUREMENT_PROCEDURES, VCD_FUNCTION_IN); - if (l==2) { - + if (l == 2) { LOG_D(PHY,"Doing UE measurement procedures in symbol l %u Ncp %d nr_slot_rx %d, rxdata %p\n", - l, - ue->frame_parms.Ncp, - nr_slot_rx, - ue->common_vars.rxdata); - - nr_ue_measurements(ue, proc, dlsch, pdsch_est_size, dl_ch_estimates); - + l, + ue->frame_parms.Ncp, + nr_slot_rx, + ue->common_vars.rxdata); + nr_ue_measurements(ue, proc, number_rbs, pdsch_est_size, dl_ch_estimates); #if T_TRACER if(nr_slot_rx == 0) T(T_UE_PHY_MEAS, @@ -580,21 +577,17 @@ int nr_ue_pdcch_procedures(PHY_VARS_NR_UE *ue, static freq_alloc_bitmap_t set_start_end_from_bitmap(int size, int alloc_size, const uint8_t bitmap[alloc_size]) { freq_alloc_bitmap_t alloc = { + .num_rbs = 0, .start = size, .end = 0 }; - for (int start = 0; start < size; start++) { - if ((bitmap[start / 8] >> start % 8) & 0x1) { - alloc.start = start; - break; - } - } - AssertFatal(alloc.start < size, "Frequency allocation bitmap empty\n"); - for (int end = size - 1; end > 0; end--) { - if ((bitmap[end / 8] >> end % 8) & 0x1) { - alloc.end = end; - break; + for (int i = 0; i < size; i++) { + if ((bitmap[i / 8] >> i % 8) & 0x1) { + if (alloc.start == size) + alloc.start = i; + alloc.end = i; + alloc.num_rbs++; } } AssertFatal(alloc.end > 0, "Frequency allocation bitmap empty\n"); @@ -605,6 +598,7 @@ static freq_alloc_bitmap_t set_start_end_from_bitmap(int size, int alloc_size, c static freq_alloc_bitmap_t set_bitmap_from_start_size(int start, int size) { freq_alloc_bitmap_t alloc = { + .num_rbs = size, .start = start, .end = start + size - 1 }; @@ -665,7 +659,7 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, int32_t ptrs_re_per_slot[ue->frame_parms.nb_antennas_rx][NR_SYMBOLS_PER_SLOT]; memset(ptrs_re_per_slot, 0, sizeof(ptrs_re_per_slot)); - const uint32_t rx_size_symbol = (dlsch[0].dlsch_config.number_rbs * NR_NB_SC_PER_RB + 15) & ~15; + const uint32_t rx_size_symbol = (freq_alloc.num_rbs * NR_NB_SC_PER_RB + 15) & ~15; fourDimArray_t *toFree2 = NULL; allocCast3D(rxdataF_comp, int32_t, @@ -709,10 +703,8 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, } } stop_meas_nr_ue_phy(ue, DLSCH_CHANNEL_ESTIMATION_STATS); - nvar /= (dlschCfg->number_symbols * dlsch0->Nl * ue->frame_parms.nb_antennas_rx); - - nr_ue_measurement_procedures(2, ue, proc, &dlsch[0], pdsch_est_size, pdsch_dl_ch_estimates); + nr_ue_measurement_procedures(2, ue, proc, freq_alloc.num_rbs, pdsch_est_size, pdsch_dl_ch_estimates); if (ue->chest_time == 1) { // averaging time domain channel estimates nr_chest_time_domain_avg(&ue->frame_parms, @@ -720,7 +712,7 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, dlschCfg->number_symbols, dlschCfg->start_symbol, dlschCfg->dlDmrsSymbPos, - dlschCfg->number_rbs); + freq_alloc.num_rbs); } uint16_t first_symbol_with_data = dlschCfg->start_symbol; @@ -758,13 +750,13 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, pdschChanEstimates, sizeof(c16_t), 1, - dlschCfg->number_rbs * NR_NB_SC_PER_RB * dlschCfg->number_symbols, + freq_alloc.num_rbs * NR_NB_SC_PER_RB * dlschCfg->number_symbols, &mt); scope_req.copy_rxdataF_to_scope = UETryLockScopeData(ue, pdschRxdataF, sizeof(c16_t), 1, - dlschCfg->number_rbs * NR_NB_SC_PER_RB * dlschCfg->number_symbols, + freq_alloc.num_rbs * NR_NB_SC_PER_RB * dlschCfg->number_symbols, &mt); } for (int m = dlschCfg->start_symbol; m < (dlschCfg->number_symbols + dlschCfg->start_symbol); m++) { From 7eb65f2adc78301f9b1e3873972e8161064ef7b0 Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 24 Jun 2025 17:04:25 +0200 Subject: [PATCH 935/964] adapt nr_dlsch_extract_rbs for type0 PDSCH freq allocation --- .../nr_dl_channel_estimation.c | 30 +++-- .../NR_UE_TRANSPORT/nr_dlsch_demodulation.c | 124 +++++++++--------- .../NR_UE_TRANSPORT/nr_transport_proto_ue.h | 1 + .../PHY/NR_UE_TRANSPORT/nr_transport_ue.h | 6 +- openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 32 +++-- 5 files changed, 105 insertions(+), 88 deletions(-) diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c index 9e76b2f85f..356e044cb4 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c @@ -938,12 +938,13 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, } void NFAPI_NR_DMRS_TYPE1_linear_interp(NR_DL_FRAME_PARMS *frame_parms, - const freq_alloc_bitmap_t *freq_alloc, c16_t *rxF, c16_t *pil, c16_t *dl_ch, unsigned short bwp_start_subcarrier, - unsigned short nb_rb_pdsch, + int rb_offset, + int nb_rb_pdsch, + const uint8_t bitmap[36], delay_t *delay, uint32_t *nvar) { @@ -952,8 +953,8 @@ void NFAPI_NR_DMRS_TYPE1_linear_interp(NR_DL_FRAME_PARMS *frame_parms, c16_t dl_ls_est[frame_parms->ofdm_symbol_size] __attribute__((aligned(32))); memset(dl_ls_est, 0, sizeof(dl_ls_est)); int idx = 0; - for (int rb = freq_alloc->start; rb < freq_alloc->start + nb_rb_pdsch; rb++) { - bool allocated_rb = (freq_alloc->bitmap[rb / 8] >> (rb % 8)) & 0x01; + for (int rb = rb_offset; rb < rb_offset + nb_rb_pdsch; rb++) { + bool allocated_rb = (bitmap[rb / 8] >> (rb % 8)) & 0x01; if (allocated_rb) { for (int pilot_cnt = 0; pilot_cnt < 6; pilot_cnt += 2) { c16_t ch_l = c16mulShift(*pil, rxF[re_offset], 15); @@ -1103,12 +1104,13 @@ void NFAPI_NR_DMRS_TYPE1_average_prb(NR_DL_FRAME_PARMS *frame_parms, } void NFAPI_NR_DMRS_TYPE2_linear_interp(NR_DL_FRAME_PARMS *frame_parms, - const freq_alloc_bitmap_t *freq_alloc, c16_t *rxF, c16_t *pil, c16_t *dl_ch, unsigned short bwp_start_subcarrier, - unsigned short nb_rb_pdsch, + int rb_offset, + int nb_rb_pdsch, + const uint8_t bitmap[36], delay_t *delay, uint32_t *nvar) { @@ -1117,8 +1119,8 @@ void NFAPI_NR_DMRS_TYPE2_linear_interp(NR_DL_FRAME_PARMS *frame_parms, c16_t dl_ls_est[frame_parms->ofdm_symbol_size] __attribute__((aligned(32))); memset(dl_ls_est, 0, sizeof(dl_ls_est)); int idx = 0; - for (int rb = freq_alloc->start; rb < freq_alloc->start + nb_rb_pdsch; rb++) { - bool allocated_rb = (freq_alloc->bitmap[rb / 8] >> (rb % 8)) & 0x01; + for (int rb = rb_offset; rb < rb_offset + nb_rb_pdsch; rb++) { + bool allocated_rb = (bitmap[rb / 8] >> (rb % 8)) & 0x01; if (allocated_rb) { for (int pilot_cnt = 0; pilot_cnt < 4; pilot_cnt += 2) { c16_t ch_l = c16mulShift(*pil, rxF[re_offset], 15); @@ -1286,7 +1288,7 @@ void nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, NR_DL_FRAME_PARMS *fp = &ue->frame_parms; const int ch_offset = fp->ofdm_symbol_size * symbol; const int symbol_offset = fp->ofdm_symbol_size * symbol; - int bwp_start_subcarrier = fp->first_carrier_offset + (dlsch->BWPStart + freq_alloc->start) * 12; + int bwp_start_subcarrier = fp->first_carrier_offset + (dlsch->BWPStart + freq_alloc->start[0]) * 12; #ifdef DEBUG_PDSCH printf( @@ -1303,8 +1305,8 @@ void nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, // generate pilot for gNB port number 1000+p int config_type = dlsch->dmrsConfigType; - int rb_offset = freq_alloc->start + (dlsch->refPoint ? 0 : dlsch->BWPStart); - int nb_rb_pdsch = freq_alloc->end - freq_alloc->start + 1; + int rb_offset = freq_alloc->start[0] + (dlsch->refPoint ? 0 : dlsch->BWPStart); + int nb_rb_pdsch = freq_alloc->end[freq_alloc->num_blocks - 1] - freq_alloc->start[0] + 1; int8_t delta = get_delta(p, config_type); c16_t pilot[3280] __attribute__((aligned(16))); // Note: pilot returned by the following function is already the complex conjugate of the transmitted DMRS @@ -1328,23 +1330,25 @@ void nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, if (config_type == NFAPI_NR_DMRS_TYPE1 && ue->chest_freq == 0) { NFAPI_NR_DMRS_TYPE1_linear_interp(fp, - freq_alloc, rxF, &pilot[6 * rb_offset], dl_ch, bwp_start_subcarrier, + freq_alloc->start[0], nb_rb_pdsch, + freq_alloc->bitmap, &delay, nvar); } else if (config_type == NFAPI_NR_DMRS_TYPE2 && ue->chest_freq == 0) { NFAPI_NR_DMRS_TYPE2_linear_interp(fp, - freq_alloc, rxF, &pilot[4 * rb_offset], dl_ch, bwp_start_subcarrier, + freq_alloc->start[0], nb_rb_pdsch, + freq_alloc->bitmap, &delay, nvar); diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c index e281e1851d..6b6d322988 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c @@ -141,8 +141,8 @@ static void nr_dlsch_extract_rbs(uint32_t rxdataF_sz, unsigned char symbol, uint8_t pilots, uint8_t config_type, - unsigned short start_rb, - unsigned short nb_rb_pdsch, + int startBWP, + const freq_alloc_bitmap_t *freq_alloc, uint8_t n_dmrs_cdm_groups, uint8_t Nl, NR_DL_FRAME_PARMS *frame_parms, @@ -293,6 +293,7 @@ static uint32_t build_csi_overlap_bitmap(fapi_nr_dl_config_dlsch_pdu_rel15_t *dl int nr_rx_pdsch(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, NR_UE_DLSCH_t dlsch[2], + const freq_alloc_bitmap_t *freq_alloc, unsigned char symbol, bool first_symbol_flag, unsigned char harq_pid, @@ -393,13 +394,10 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, DEBUG_HARQ("[DEMOD] cw for TB0 = %d, cw for TB1 = %d\n", codeword_TB0, codeword_TB1); fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config = &dlsch[0].dlsch_config; - int start_rb = dlsch_config->start_rb; - int nb_rb_pdsch = dlsch_config->number_rbs; - DevAssert(dlsch0_harq); if (gNB_id > 2) { - LOG_E(PHY, "In %s: Illegal gNB_id %d\n", __FUNCTION__, gNB_id); + LOG_E(PHY, "Illegal gNB_id %d\n", gNB_id); return(-1); } @@ -423,7 +421,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, //---------------------------------------------------------- const int n_rx = frame_parms->nb_antennas_rx; const bool meas_enabled = cpumeas(CPUMEAS_GETSTATE); - + int nb_rb_pdsch = freq_alloc->num_rbs; { start_meas_nr_ue_phy(ue, DLSCH_EXTRACT_RBS_STATS); __attribute__((aligned(32))) c16_t rxdataF_ext[nbRx][rx_size_symbol]; @@ -443,8 +441,8 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, symbol, pilots, config_type, - start_rb + dlsch_config->BWPStart, - nb_rb_pdsch, + dlsch_config->BWPStart, + freq_alloc, dlsch_config->n_dmrs_cdm_groups, nl, frame_parms, @@ -453,7 +451,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, ue->chest_time); stop_meas_nr_ue_phy(ue, DLSCH_EXTRACT_RBS_STATS); if (scope_req->copy_chanest_to_scope) { - size_t size = sizeof(c16_t) * dlsch_config->number_rbs * NR_NB_SC_PER_RB; + size_t size = sizeof(c16_t) * nb_rb_pdsch * NR_NB_SC_PER_RB; int copy_index = symbol - dlsch_config->start_symbol; int offset = copy_index * size; UEscopeCopyUnsafe(ue, pdschChanEstimates, dl_ch_estimates_ext[0], size, offset, copy_index); @@ -478,14 +476,15 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, uint32_t csi_re_count = 0; uint32_t csi_res_even = csi_res_bitmap & 0xfff; uint32_t csi_res_odd = (csi_res_bitmap >> 16) & 0xfff; - int start = start_rb + dlsch_config->BWPStart; - for (int rb = start; rb < start + nb_rb_pdsch; rb++) { - uint32_t rb_csi_pattern = (rb % 2 == 0) ? csi_res_even : csi_res_odd; - csi_re_count += __builtin_popcount(rb_csi_pattern); + int start = freq_alloc->start[0] + dlsch_config->BWPStart; + int end = freq_alloc->end[freq_alloc->num_blocks - 1] + 1; + for (int rb = start; rb < end; rb++) { + if ((freq_alloc->bitmap[rb / 8] >> (rb % 8)) & 0x01) { + uint32_t rb_csi_pattern = (rb % 2 == 0) ? csi_res_even : csi_res_odd; + csi_re_count += __builtin_popcount(rb_csi_pattern); + } } - nb_re_pdsch = (nb_re_pdsch > csi_re_count) ? (nb_re_pdsch - csi_re_count) : 0; - if (csi_re_count > 0) { LOG_D(NR_PHY, "[CSI OVERLAP] Frame/Slot %d.%d Symbol %d: CSI-RS overlapping PDSCH - %d CSI-RS REs skipped, %d data REs extracted\n", @@ -778,7 +777,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, memcpy(ue->phy_sim_pdsch_dl_ch_estimates_ext + symbol * sizeof(dl_ch_estimates_ext), dl_ch_estimates_ext, sizeof(dl_ch_estimates_ext)); - return (0); + return 0; } //============================================================================================== @@ -1019,8 +1018,8 @@ static void nr_dlsch_extract_rbs(uint32_t rxdataF_sz, unsigned char symbol, uint8_t pilots, uint8_t config_type, - unsigned short start_rb, - unsigned short nb_rb_pdsch, + int startBWP, + const freq_alloc_bitmap_t *freq_alloc, uint8_t n_dmrs_cdm_groups, uint8_t Nl, NR_DL_FRAME_PARMS *frame_parms, @@ -1029,7 +1028,7 @@ static void nr_dlsch_extract_rbs(uint32_t rxdataF_sz, int chest_time_type) { if (config_type == NFAPI_NR_DMRS_TYPE1) - AssertFatal(n_dmrs_cdm_groups == 1 || n_dmrs_cdm_groups == 2, "n_dmrs_cdm_groups %d is illegal\n",n_dmrs_cdm_groups); + AssertFatal(n_dmrs_cdm_groups == 1 || n_dmrs_cdm_groups == 2, "n_dmrs_cdm_groups %d is illegal\n", n_dmrs_cdm_groups); else AssertFatal(n_dmrs_cdm_groups == 1 || n_dmrs_cdm_groups == 2 || n_dmrs_cdm_groups == 3, "n_dmrs_cdm_groups %d is illegal\n",n_dmrs_cdm_groups); @@ -1052,61 +1051,60 @@ static void nr_dlsch_extract_rbs(uint32_t rxdataF_sz, AssertFatal((dmrs_rb_bitmap & csi_res_odd) == 0, "DMRS RE overlapping with CSI RE, it shouldn't happen\n"); uint32_t dmrs_csi_overlap_even = csi_res_even + dmrs_rb_bitmap; uint32_t dmrs_csi_overlap_odd = csi_res_odd + dmrs_rb_bitmap; - - const unsigned short start_re = (frame_parms->first_carrier_offset + start_rb * NR_NB_SC_PER_RB) % frame_parms->ofdm_symbol_size; int8_t validDmrsEst; - if (chest_time_type == 0) - validDmrsEst = get_valid_dmrs_idx_for_channel_est(dlDmrsSymbPos,symbol); + validDmrsEst = get_valid_dmrs_idx_for_channel_est(dlDmrsSymbPos, symbol); else - validDmrsEst = get_next_dmrs_symbol_in_slot(dlDmrsSymbPos,0,14); // get first dmrs symbol index + validDmrsEst = get_next_dmrs_symbol_in_slot(dlDmrsSymbPos, 0, 14); // get first dmrs symbol index - for (unsigned char aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { - c16_t *rxF_ext = rxdataF_ext[aarx]; - c16_t *rxF = &rxdataF[aarx][symbol * frame_parms->ofdm_symbol_size]; - - for (unsigned char l = 0; l < Nl; l++) { - - int32_t *dl_ch0 = &dl_ch_estimates[(l * frame_parms->nb_antennas_rx) + aarx][validDmrsEst * frame_parms->ofdm_symbol_size]; - int32_t *dl_ch0_ext = dl_ch_estimates_ext[(l * frame_parms->nb_antennas_rx) + aarx]; - - if (pilots == 0 && csi_res_bitmap == 0) { // data symbol only - if (l == 0) { - if (start_re + nb_rb_pdsch * NR_NB_SC_PER_RB <= frame_parms->ofdm_symbol_size) { - memcpy(rxF_ext, &rxF[start_re], nb_rb_pdsch * NR_NB_SC_PER_RB * sizeof(int32_t)); - } else { - int neg_length = frame_parms->ofdm_symbol_size - start_re; - int pos_length = nb_rb_pdsch * NR_NB_SC_PER_RB - neg_length; - memcpy(rxF_ext, &rxF[start_re], neg_length * sizeof(int32_t)); - memcpy(&rxF_ext[neg_length], rxF, pos_length * sizeof(int32_t)); - } - } - memcpy(dl_ch0_ext, dl_ch0, nb_rb_pdsch * NR_NB_SC_PER_RB * sizeof(int32_t)); - } - else { - int j = 0; - int k = start_re; - for (int rb = 0; rb < nb_rb_pdsch; rb++) { - uint32_t overlap_map = rb % 2 ? dmrs_csi_overlap_odd : dmrs_csi_overlap_even; - for (int re = 0; re < 12; re++) { - if (((overlap_map >> re) & 0x01) == 0) { - // DATA RE - if (l == 0) - rxF_ext[j] = rxF[k]; - dl_ch0_ext[j] = dl_ch0[re]; - j++; + for (int b = 0; b < freq_alloc->num_blocks; b++) { + int start_rb = freq_alloc->start[b] + startBWP; + int nb_rb = freq_alloc->end[b] - freq_alloc->start[b] + 1; + const int start_re = (frame_parms->first_carrier_offset + start_rb * NR_NB_SC_PER_RB) % frame_parms->ofdm_symbol_size; + for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { + c16_t *rxF_ext = rxdataF_ext[aarx]; + c16_t *rxF = &rxdataF[aarx][symbol * frame_parms->ofdm_symbol_size]; + for (int l = 0; l < Nl; l++) { + int32_t *dl_ch0 = &dl_ch_estimates[(l * frame_parms->nb_antennas_rx) + aarx][validDmrsEst * frame_parms->ofdm_symbol_size]; + int32_t *dl_ch0_ext = dl_ch_estimates_ext[(l * frame_parms->nb_antennas_rx) + aarx]; + if (pilots == 0 && csi_res_bitmap == 0) { // data symbol only + if (l == 0) { + if (start_re + nb_rb * NR_NB_SC_PER_RB <= frame_parms->ofdm_symbol_size) { + memcpy(rxF_ext, &rxF[start_re], nb_rb * NR_NB_SC_PER_RB * sizeof(int32_t)); + } else { + int neg_length = frame_parms->ofdm_symbol_size - start_re; + int pos_length = nb_rb * NR_NB_SC_PER_RB - neg_length; + memcpy(rxF_ext, &rxF[start_re], neg_length * sizeof(int32_t)); + memcpy(&rxF_ext[neg_length], rxF, pos_length * sizeof(int32_t)); } - k++; - if (k >= frame_parms->ofdm_symbol_size) - k -= frame_parms->ofdm_symbol_size; } - dl_ch0 += 12; + memcpy(dl_ch0_ext, dl_ch0, nb_rb * NR_NB_SC_PER_RB * sizeof(int32_t)); + } else { + int j = 0; + int k = start_re; + for (int rb = start_rb; rb < start_rb + nb_rb; rb++) { + uint32_t overlap_map = rb % 2 ? dmrs_csi_overlap_odd : dmrs_csi_overlap_even; + for (int re = 0; re < NR_NB_SC_PER_RB; re++) { + if (((overlap_map >> re) & 0x01) == 0) { + // DATA RE + if (l == 0) + rxF_ext[j] = rxF[k]; + dl_ch0_ext[j] = dl_ch0[re]; + j++; + } + k++; + if (k >= frame_parms->ofdm_symbol_size) + k -= frame_parms->ofdm_symbol_size; + } + dl_ch0 += 12; + } } } } } } + static void nr_dlsch_detection_mrc(uint32_t rx_size_symbol, short nl, short n_rx, diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h index 6eaa0ecec1..41747a9ef1 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h @@ -315,6 +315,7 @@ void nr_dci_decoding_procedure(PHY_VARS_NR_UE *ue, int nr_rx_pdsch(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, NR_UE_DLSCH_t dlsch[2], + const freq_alloc_bitmap_t *freq_alloc, unsigned char symbol, bool first_symbol_flag, unsigned char harq_pid, diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h index fd4fe3a1b7..596916f091 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h @@ -38,10 +38,12 @@ #include "nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h" #include "../NR_TRANSPORT/nr_transport_common_proto.h" +#define MAX_FA_BLOCKS 10 typedef struct { - int start; - int end; + int start[MAX_FA_BLOCKS]; + int end[MAX_FA_BLOCKS]; int num_rbs; + int num_blocks; uint8_t bitmap[36]; } freq_alloc_bitmap_t; diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index 591ea711f3..f22d13c5fc 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -578,19 +578,29 @@ static freq_alloc_bitmap_t set_start_end_from_bitmap(int size, int alloc_size, c { freq_alloc_bitmap_t alloc = { .num_rbs = 0, - .start = size, - .end = 0 + .num_blocks = 0 }; + bool pos_bit = false; for (int i = 0; i < size; i++) { if ((bitmap[i / 8] >> i % 8) & 0x1) { - if (alloc.start == size) - alloc.start = i; - alloc.end = i; + if (!pos_bit) { + pos_bit = true; + alloc.start[alloc.num_blocks] = i; + AssertFatal(alloc.num_blocks < MAX_FA_BLOCKS, "Number of type0 PDSCH RBG exceeting %d\n", MAX_FA_BLOCKS); + alloc.num_blocks++; + } alloc.num_rbs++; + } else { + if (pos_bit) { + pos_bit = false; + alloc.end[alloc.num_blocks - 1] = i - 1; + } } } - AssertFatal(alloc.end > 0, "Frequency allocation bitmap empty\n"); + if (pos_bit) + alloc.end[alloc.num_blocks - 1] = size - 1; + AssertFatal(alloc.num_blocks > 0, "Frequency allocation bitmap empty\n"); memcpy(alloc.bitmap, bitmap, alloc_size * sizeof(uint8_t)); return alloc; } @@ -599,8 +609,9 @@ static freq_alloc_bitmap_t set_bitmap_from_start_size(int start, int size) { freq_alloc_bitmap_t alloc = { .num_rbs = size, - .start = start, - .end = start + size - 1 + .num_blocks = 1, + .start[0] = start, + .end[0] = start + size - 1 }; memset(alloc.bitmap, 0, 36 * sizeof(uint8_t)); for (int i = start; i < size + start; i++) @@ -642,8 +653,8 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, harq_pid, dlsch0_harq->status, dlschCfg->BWPStart, - freq_alloc.start, - freq_alloc.end, + freq_alloc.start[0], + freq_alloc.end[freq_alloc.num_blocks - 1], dlschCfg->start_symbol, dlschCfg->number_symbols, dlschCfg->dlDmrsSymbPos, @@ -769,6 +780,7 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, if (nr_rx_pdsch(ue, proc, dlsch, + &freq_alloc, m, first_symbol_flag, harq_pid, From d07771c53821ac5e22fbe56ddab1c511ac1c4f20 Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 24 Jun 2025 17:21:22 +0200 Subject: [PATCH 936/964] formatting improvements --- .../NR_UE_TRANSPORT/nr_dlsch_demodulation.c | 89 +++++++++---------- 1 file changed, 44 insertions(+), 45 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c index 6b6d322988..351307ea3f 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c @@ -145,7 +145,7 @@ static void nr_dlsch_extract_rbs(uint32_t rxdataF_sz, const freq_alloc_bitmap_t *freq_alloc, uint8_t n_dmrs_cdm_groups, uint8_t Nl, - NR_DL_FRAME_PARMS *frame_parms, + NR_DL_FRAME_PARMS *fp, uint16_t dlDmrsSymbPos, uint32_t csi_res_bitmap, int chest_time_type); @@ -315,12 +315,14 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, uint32_t nvar, pdsch_scope_req_t *scope_req) { + NR_DL_FRAME_PARMS *fp = &ue->frame_parms; const int nl = dlsch[0].Nl; - const int matrixSz = ue->frame_parms.nb_antennas_rx * nl; + const int n_rx = fp->nb_antennas_rx; + const int matrixSz = n_rx * nl; __attribute__((aligned(32))) int32_t dl_ch_estimates_ext[matrixSz][rx_size_symbol]; memset(dl_ch_estimates_ext, 0, sizeof(dl_ch_estimates_ext)); - __attribute__((aligned(32))) c16_t dl_ch_mag[nl][ue->frame_parms.nb_antennas_rx][rx_size_symbol]; + __attribute__((aligned(32))) c16_t dl_ch_mag[nl][n_rx][rx_size_symbol]; memset(dl_ch_mag, 0, sizeof(dl_ch_mag)); __attribute__((aligned(32))) c16_t dl_ch_magb[nl][nbRx][rx_size_symbol]; @@ -329,7 +331,6 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, __attribute__((aligned(32))) c16_t dl_ch_magr[nl][nbRx][rx_size_symbol]; memset(dl_ch_magr, 0, sizeof(dl_ch_magr)); NR_UE_COMMON *common_vars = &ue->common_vars; - NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; PHY_NR_MEASUREMENTS *measurements = &ue->measurements; const int frame = proc->frame_rx; const int nr_slot_rx = proc->nr_slot_rx; @@ -348,7 +349,14 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, if (dlsch0_harq && dlsch1_harq){ - LOG_D(PHY,"AbsSubframe %d.%d / Sym %d harq_pid %d, harq status %d.%d \n", frame, nr_slot_rx, symbol, harq_pid, dlsch0_harq->status, dlsch1_harq->status); + LOG_D(PHY, + "AbsSubframe %d.%d / Sym %d harq_pid %d, harq status %d.%d \n", + frame, + nr_slot_rx, + symbol, + harq_pid, + dlsch0_harq->status, + dlsch1_harq->status); if ((dlsch0_harq->status == ACTIVE) && (dlsch1_harq->status == ACTIVE)){ codeword_TB0 = dlsch0_harq->codeword; // SV: where is this set? revisit for DL MIMO. @@ -406,12 +414,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, return(-1); } - if (!frame_parms) { - LOG_E(PHY, "dlsch_demodulation.c: Null frame_parms\n"); - return(-1); - } - - if(symbol > ue->frame_parms.symbols_per_slot >> 1) + if(symbol > fp->symbols_per_slot >> 1) slot = 1; uint8_t pilots = (dlsch_config->dlDmrsSymbPos >> symbol) & 1; @@ -419,7 +422,6 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, //---------------------------------------------------------- //--------------------- RBs extraction --------------------- //---------------------------------------------------------- - const int n_rx = frame_parms->nb_antennas_rx; const bool meas_enabled = cpumeas(CPUMEAS_GETSTATE); int nb_rb_pdsch = freq_alloc->num_rbs; { @@ -431,7 +433,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, LOG_D(PHY, "%d.%d symbol %d csi overlap bitmap %d\n", frame, nr_slot_rx, symbol, csi_res_bitmap); - nr_dlsch_extract_rbs(ue->frame_parms.samples_per_slot_wCP, + nr_dlsch_extract_rbs(fp->samples_per_slot_wCP, rxdataF, rx_size_symbol, pdsch_est_size, @@ -445,7 +447,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, freq_alloc, dlsch_config->n_dmrs_cdm_groups, nl, - frame_parms, + fp, dlsch_config->dlDmrsSymbPos, csi_res_bitmap, ue->chest_time); @@ -506,7 +508,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, //--------------------- Channel Scaling -------------------- //---------------------------------------------------------- start_meas_nr_ue_phy(ue, DLSCH_CHANNEL_SCALE_STATS); - nr_dlsch_scale_channel(rx_size_symbol, dl_ch_estimates_ext, frame_parms, nl, n_rx, symbol, pilots, nb_re_pdsch, nb_rb_pdsch); + nr_dlsch_scale_channel(rx_size_symbol, dl_ch_estimates_ext, fp, nl, n_rx, symbol, pilots, nb_re_pdsch, nb_rb_pdsch); stop_meas_nr_ue_phy(ue, DLSCH_CHANNEL_SCALE_STATS); if (meas_enabled) { LOG_D(PHY, @@ -577,7 +579,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, dl_ch_magr, rxdataF_comp, NULL, - frame_parms, + fp, nl, symbol, nb_re_pdsch, @@ -602,10 +604,10 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, char filename[50]; snprintf(filename, 50, "rxdataF0_symb_%d_nr_slot_rx_%d.m", symbol, nr_slot_rx); - write_output(filename, "rxdataF0", &rxdataF[0][symbol * frame_parms->ofdm_symbol_size], frame_parms->ofdm_symbol_size, 1, 1); + write_output(filename, "rxdataF0", &rxdataF[0][symbol * fp->ofdm_symbol_size], fp->ofdm_symbol_size, 1, 1); snprintf(filename, 50, "dl_ch_estimates0_symb_%d_nr_slot_rx_%d.m", symbol, nr_slot_rx); - write_output(filename, "dl_ch_estimates0", &dl_ch_estimates[0][symbol * frame_parms->ofdm_symbol_size], frame_parms->ofdm_symbol_size, 1, 1); + write_output(filename, "dl_ch_estimates0", &dl_ch_estimates[0][symbol * fp->ofdm_symbol_size], fp->ofdm_symbol_size, 1, 1); snprintf(filename, 50, "rxdataF_ext0_symb_%d_nr_slot_rx_%d.m", symbol, nr_slot_rx); write_output(filename, "rxdataF_ext0", &rxdataF_ext[0][0], rx_size_symbol, 1, 1); @@ -681,7 +683,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, ptrs_re_per_slot, rx_size_symbol, rxdataF_comp, - frame_parms, + fp, dlsch0_harq, dlsch1_harq, gNB_id, @@ -758,9 +760,9 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, T_INT(frame % 1024), T_INT(nr_slot_rx), T_INT(nb_rb_pdsch), - T_INT(frame_parms->N_RB_UL), - T_INT(frame_parms->symbols_per_slot), - T_BUFFER(&rxdataF_comp[gNB_id][0], 2 * /* ulsch[UE_id]->harq_processes[harq_pid]->nb_rb */ frame_parms->N_RB_UL * 12 * 2)); + T_INT(fp->N_RB_UL), + T_INT(fp->symbols_per_slot), + T_BUFFER(&rxdataF_comp[gNB_id][0], 2 * /* ulsch[UE_id]->harq_processes[harq_pid]->nb_rb */ fp->N_RB_UL * 12 * 2)); #endif if (ue->phy_sim_pdsch_rxdataF_comp) @@ -922,7 +924,7 @@ static void nr_dlsch_channel_compensation(uint32_t rx_size_symbol, void nr_dlsch_scale_channel(uint32_t rx_size_symbol, int32_t dl_ch_estimates_ext[][rx_size_symbol], - NR_DL_FRAME_PARMS *frame_parms, + NR_DL_FRAME_PARMS *fp, uint8_t n_tx, uint8_t n_rx, uint8_t symbol, @@ -931,30 +933,28 @@ void nr_dlsch_scale_channel(uint32_t rx_size_symbol, unsigned short nb_rb) { - - short rb, ch_amp; unsigned char aatx,aarx; simde__m128i *dl_ch128, ch_amp128; - uint32_t nb_rb_0 = len/12 + ((len%12)?1:0); // Determine scaling amplitude based the symbol - - ch_amp = 1024*8; //((pilots) ? (dlsch_ue[0]->sqrt_rho_b) : (dlsch_ue[0]->sqrt_rho_a)); - - LOG_D(PHY,"Scaling PDSCH Chest in OFDM symbol %d by %d, pilots %d nb_rb %d NCP %d symbol %d\n",symbol,ch_amp,pilots,nb_rb,frame_parms->Ncp,symbol); + ch_amp = 1024 * 8; //((pilots) ? (dlsch_ue[0]->sqrt_rho_b) : (dlsch_ue[0]->sqrt_rho_a)); + LOG_D(PHY, + "Scaling PDSCH Chest in OFDM symbol %d by %d, pilots %d nb_rb %d NCP %d symbol %d\n", + symbol, + ch_amp, + pilots, + nb_rb, + fp->Ncp, + symbol); // printf("Scaling PDSCH Chest in OFDM symbol %d by %d\n",symbol_mod,ch_amp); ch_amp128 = simde_mm_set1_epi16(ch_amp); // Q3.13 - for (aatx=0; aatxnum_blocks; b++) { int start_rb = freq_alloc->start[b] + startBWP; int nb_rb = freq_alloc->end[b] - freq_alloc->start[b] + 1; - const int start_re = (frame_parms->first_carrier_offset + start_rb * NR_NB_SC_PER_RB) % frame_parms->ofdm_symbol_size; - for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { + const int start_re = (fp->first_carrier_offset + start_rb * NR_NB_SC_PER_RB) % fp->ofdm_symbol_size; + for (int aarx = 0; aarx < fp->nb_antennas_rx; aarx++) { c16_t *rxF_ext = rxdataF_ext[aarx]; - c16_t *rxF = &rxdataF[aarx][symbol * frame_parms->ofdm_symbol_size]; + c16_t *rxF = &rxdataF[aarx][symbol * fp->ofdm_symbol_size]; for (int l = 0; l < Nl; l++) { - int32_t *dl_ch0 = &dl_ch_estimates[(l * frame_parms->nb_antennas_rx) + aarx][validDmrsEst * frame_parms->ofdm_symbol_size]; - int32_t *dl_ch0_ext = dl_ch_estimates_ext[(l * frame_parms->nb_antennas_rx) + aarx]; + int32_t *dl_ch0 = &dl_ch_estimates[(l * fp->nb_antennas_rx) + aarx][validDmrsEst * fp->ofdm_symbol_size]; + int32_t *dl_ch0_ext = dl_ch_estimates_ext[(l * fp->nb_antennas_rx) + aarx]; if (pilots == 0 && csi_res_bitmap == 0) { // data symbol only if (l == 0) { - if (start_re + nb_rb * NR_NB_SC_PER_RB <= frame_parms->ofdm_symbol_size) { + if (start_re + nb_rb * NR_NB_SC_PER_RB <= fp->ofdm_symbol_size) { memcpy(rxF_ext, &rxF[start_re], nb_rb * NR_NB_SC_PER_RB * sizeof(int32_t)); } else { - int neg_length = frame_parms->ofdm_symbol_size - start_re; + int neg_length = fp->ofdm_symbol_size - start_re; int pos_length = nb_rb * NR_NB_SC_PER_RB - neg_length; memcpy(rxF_ext, &rxF[start_re], neg_length * sizeof(int32_t)); memcpy(&rxF_ext[neg_length], rxF, pos_length * sizeof(int32_t)); @@ -1093,8 +1092,8 @@ static void nr_dlsch_extract_rbs(uint32_t rxdataF_sz, j++; } k++; - if (k >= frame_parms->ofdm_symbol_size) - k -= frame_parms->ofdm_symbol_size; + if (k >= fp->ofdm_symbol_size) + k -= fp->ofdm_symbol_size; } dl_ch0 += 12; } From 9e43f998d910a04f3adb92622db387f6220add9e Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 24 Jun 2025 17:27:46 +0200 Subject: [PATCH 937/964] further code cleanup --- .../PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c | 2 -- openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h | 1 - openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c | 10 ++-------- 3 files changed, 2 insertions(+), 11 deletions(-) diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c index 356e044cb4..296606a426 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c @@ -1388,7 +1388,6 @@ void nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, * uint8_t : gNB_id, * uint8_t : nr_slot_rx, * unsigned char : symbol, - * uint32_t : nb_re_pdsch, * uint16_t : rnti * RX_type_t : rx_type * RETURN : Nothing @@ -1411,7 +1410,6 @@ void nr_pdsch_ptrs_processing(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t nr_slot_rx, unsigned char symbol, - uint32_t nb_re_pdsch, uint16_t rnti, NR_UE_DLSCH_t dlsch[2]) { diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h index 30464f0c8b..66339e25a2 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h @@ -137,7 +137,6 @@ void nr_pdsch_ptrs_processing(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t nr_slot_rx, unsigned char symbol, - uint32_t nb_re_pdsch, uint16_t rnti, NR_UE_DLSCH_t dlsch[2]); diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c index 351307ea3f..7eff76e91f 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c @@ -689,7 +689,6 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, gNB_id, nr_slot_rx, symbol, - (nb_rb_pdsch * 12), dlsch[0].rnti, dlsch); dl_valid_re[symbol] -= ptrs_re_per_slot[0][symbol]; @@ -1182,13 +1181,8 @@ void nr_a_sum_b(c16_t *input_x, c16_t *input_y, unsigned short nb_rb) } /* Zero Forcing Rx function: nr_element_sign() - * Compute b=sign*a - * - * */ -static inline void nr_element_sign(c16_t *a, // a - c16_t *b, // b - unsigned short nb_rb, - int32_t sign) + * Compute b=sign*a */ +static inline void nr_element_sign(c16_t *a, c16_t *b, unsigned short nb_rb, int32_t sign) { const int16_t nr_sign[8] __attribute__((aligned(16))) = {-1, -1, -1, -1, -1, -1, -1, -1}; simde__m128i *a_128,*b_128; From d20b1120d4fa6dc501158fa65165424383b9b061 Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 24 Jun 2025 18:14:57 +0200 Subject: [PATCH 938/964] remove temporary code to process type0 as type1 --- openair1/SCHED_NR_UE/fapi_nr_ue_l1.c | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c index 52d5033457..a8d628f473 100644 --- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c +++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c @@ -287,26 +287,6 @@ static void configure_dlsch(NR_UE_DLSCH_t *dlsch0, NR_UE_MAC_INST_t *mac, int rnti) { - // Temporary code to process type0 as type1 when the RB allocation is contiguous - if (dlsch_config_pdu->resource_alloc == 0) { - dlsch_config_pdu->number_rbs = count_bits(dlsch_config_pdu->rb_bitmap, sizeofArray(dlsch_config_pdu->rb_bitmap)); - int state = 0; - for (int i = 0; i < sizeof(dlsch_config_pdu->rb_bitmap) * 8; i++) { - int allocated = dlsch_config_pdu->rb_bitmap[i / 8] & (1 << (i % 8)); - if (allocated) { - if (state == 0) { - dlsch_config_pdu->start_rb = i; - state = 1; - } else - AssertFatal(state == 1, "non-contiguous RB allocation in RB allocation type 0 not implemented"); - } else { - if (state == 1) { - state = 2; - } - } - } - } - const uint8_t current_harq_pid = dlsch_config_pdu->harq_process_nbr; dlsch0->active = true; dlsch0->rnti = rnti; From a20640accc6a4e679369220172b60928df057aa7 Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 13 Oct 2025 11:08:51 +0200 Subject: [PATCH 939/964] feature set update --- doc/FEATURE_SET.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/FEATURE_SET.md b/doc/FEATURE_SET.md index 4429cad56b..43b8367e3b 100644 --- a/doc/FEATURE_SET.md +++ b/doc/FEATURE_SET.md @@ -279,6 +279,7 @@ These modes of operation are supported: - DCI formats: 00, 10, 01 and 11 * Reception of NR-PDSCH (including Segmentation, LDPC decoding, rate de-matching, de-scrambling, de-modulation, RB de-mapping, etc). - PDSCH mapping type A and B + - Downlink resource allocation type 0 and 1 - DMRS configuration type 1 and 2 - Single and multiple DMRS symbols - PTRS support From edc53ac9ddc74cd01692b5fe99551af1b8c6b762 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Mon, 13 Oct 2025 12:39:33 +0200 Subject: [PATCH 940/964] OAI UE: add shared RSRP Table 10.1.6.1-1 mapping helper and adopt it RRC UE - Add to common/utils/nr/nr_common remove from NR_MAC_UE/nr_ue_procedures.c - Adopt in asn1_msg.c for MeasurementReport: this solves the following assert: Assertion (enc_rval.encoded > 0) failed! In do_nrMeasurementReport_SA() /oai-ran/openair2/RRC/NR/MESSAGES/asn1_msg.c:898 ASN1 message encoding failed (MeasResultServMOList, 18446744073709551615)! Motivation: unify RSRP-to-index mapping across layers and fix NR RRC MeasurementReport encoding failures due to out-of-range values by reusing the validated mapping. Note NR_RSRP-Range.c constraint: { APC_CONSTRAINED, 7, 7, 0, 127 } /* (0..127) */ --- common/utils/nr/nr_common.c | 11 +++++++++++ common/utils/nr/nr_common.h | 3 +++ openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 11 ----------- openair2/RRC/NR/MESSAGES/asn1_msg.c | 8 ++++---- openair2/RRC/NR/MESSAGES/asn1_msg.h | 2 +- openair2/RRC/NR_UE/rrc_UE.c | 3 ++- 6 files changed, 21 insertions(+), 17 deletions(-) diff --git a/common/utils/nr/nr_common.c b/common/utils/nr/nr_common.c index 265b680500..8e6a16c97d 100644 --- a/common/utils/nr/nr_common.c +++ b/common/utils/nr/nr_common.c @@ -152,6 +152,17 @@ void reverse_bits_u8(uint8_t const* in, size_t sz, uint8_t* out) #endif } +/** @brief 3GPP TS 38.133 Table 10.1.6.1-1 mapping from dBm to RSRP index */ +uint8_t get_rsrp_index(int rsrp_dBm) +{ + int index = rsrp_dBm + 157; + if (rsrp_dBm > -44) + index = 113; + if (rsrp_dBm < -140) + index = 16; + return (uint8_t)index; +} + // Reverse bits implementation based on http://graphics.stanford.edu/~seander/bithacks.html uint64_t reverse_bits(uint64_t in, int n_bits) { diff --git a/common/utils/nr/nr_common.h b/common/utils/nr/nr_common.h index 08c0110721..e0d68a45ad 100644 --- a/common/utils/nr/nr_common.h +++ b/common/utils/nr/nr_common.h @@ -186,6 +186,9 @@ typedef struct meas_s { val_init_t csi_rsrp_dBm; } meas_t; +/** @brief Returns NR RSRP index per 3GPP TS 38.133 Table 10.1.6.1-1 */ +uint8_t get_rsrp_index(int rsrp_dBm); + /** * @brief To start a timer * @param timer Timer to be started diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 3d9d5fba43..57c9f404d3 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -2916,17 +2916,6 @@ static int compare_ssb_rsrp(const void *a, const void *b) return mb->ssb_rsrp_dBm - ma->ssb_rsrp_dBm; } -// returns index from RSRP -// according to Table 10.1.6.1-1 in 38.133 -static uint8_t get_rsrp_index(int rsrp) -{ - int index = rsrp + 157; - if (rsrp > -44) - index = 113; - if (rsrp < -140) - index = 16; - return index; -} static csi_payload_t get_ssb_rsrp_payload(NR_UE_MAC_INST_t *mac, struct NR_CSI_ReportConfig *csi_reportconfig, diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.c b/openair2/RRC/NR/MESSAGES/asn1_msg.c index 6b65ecd263..f31464822b 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.c +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.c @@ -855,7 +855,7 @@ int do_nrMeasurementReport_SA(NR_MeasurementReport_t *measurementReport, long trigger_quantity, long rs_type, uint16_t Nid_cell, - int rsrp_dBm, + int rsrp_index, uint8_t *buffer, size_t buffer_size) { @@ -884,9 +884,9 @@ int do_nrMeasurementReport_SA(NR_MeasurementReport_t *measurementReport, struct NR_MeasQuantityResults *active_mq_res = CALLOC(1, sizeof(struct NR_MeasQuantityResults)); if (trigger_quantity == NR_MeasTriggerQuantityOffset_PR_rsrp) { - active_mq_res->rsrp = CALLOC(1, sizeof(NR_RSRP_Range_t)); - - *active_mq_res->rsrp = rsrp_dBm + 157; + asn1cCalloc(active_mq_res->rsrp, rsrp); + // Assign precomputed RSRP index + *rsrp = rsrp_index; if (rs_type == NR_NR_RS_Type_ssb) measResultServingCell->measResult.cellResults.resultsSSB_Cell = active_mq_res; else diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.h b/openair2/RRC/NR/MESSAGES/asn1_msg.h index f347f3428c..73a311084d 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.h +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.h @@ -130,7 +130,7 @@ int do_nrMeasurementReport_SA(NR_MeasurementReport_t *measurementReport, long trigger_quantity, long rs_type, uint16_t Nid_cell, - int rsrp_dBm, + int rsrp_index, uint8_t *buffer, size_t buffer_size); diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 10df2c1aec..85e9205a92 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -3242,12 +3242,13 @@ void rrc_ue_generate_measurementReport(rrcPerNB_t *rrc, instance_t ue_id) NR_MeasurementReport_t measurementReport = {0}; l3_measurements_t *l3m = &rrc->l3_measurements; int rsrp_dBm = l3m->rs_type == NR_NR_RS_Type_ssb ? l3m->serving_cell.ss_rsrp_dBm.val : l3m->serving_cell.csi_rsrp_dBm.val; + int rsrp_index = get_rsrp_index(rsrp_dBm); uint8_t size = do_nrMeasurementReport_SA(&measurementReport, l3m->trigger_to_measid, l3m->trigger_quantity, l3m->rs_type, l3m->serving_cell.Nid_cell, - rsrp_dBm, + rsrp_index, buffer, sizeof(buffer)); From d7c3968df2fa21534318edf21cb278f86ed11563 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Mon, 13 Oct 2025 16:51:34 +0200 Subject: [PATCH 941/964] RRC UE: MeasurementReport refactor - Simplify do_nrMeasurementReport_SA API (encoder allocates local report) - Adopt asn1cCalloc consistently - Minor init cleanup for UL_DCCH message struct --- openair2/RRC/NR/MESSAGES/asn1_msg.c | 29 ++++++++++++----------------- openair2/RRC/NR/MESSAGES/asn1_msg.h | 3 +-- openair2/RRC/NR_UE/rrc_UE.c | 4 +--- 3 files changed, 14 insertions(+), 22 deletions(-) diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.c b/openair2/RRC/NR/MESSAGES/asn1_msg.c index f31464822b..35b21a9722 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.c +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.c @@ -850,8 +850,7 @@ int do_RRCSetupComplete(uint8_t *buffer, } // TODO: This function is only implemented for event A2 -int do_nrMeasurementReport_SA(NR_MeasurementReport_t *measurementReport, - long trigger_to_measid, +int do_nrMeasurementReport_SA(long trigger_to_measid, long trigger_quantity, long rs_type, uint16_t Nid_cell, @@ -860,29 +859,25 @@ int do_nrMeasurementReport_SA(NR_MeasurementReport_t *measurementReport, size_t buffer_size) { asn_enc_rval_t enc_rval; - NR_UL_DCCH_Message_t ul_dcch_msg; - memset((void *)&ul_dcch_msg, 0, sizeof(NR_UL_DCCH_Message_t)); + NR_UL_DCCH_Message_t ul_dcch_msg = {0}; ul_dcch_msg.message.present = NR_UL_DCCH_MessageType_PR_c1; - ul_dcch_msg.message.choice.c1 = CALLOC(1, sizeof(struct NR_UL_DCCH_MessageType__c1)); - ul_dcch_msg.message.choice.c1->present = NR_UL_DCCH_MessageType__c1_PR_measurementReport; + asn1cCalloc(ul_dcch_msg.message.choice.c1, c1); + c1->present = NR_UL_DCCH_MessageType__c1_PR_measurementReport; - memset(measurementReport, 0, sizeof(struct NR_MeasurementReport)); - ul_dcch_msg.message.choice.c1->choice.measurementReport = measurementReport; + asn1cCalloc(c1->choice.measurementReport, measurementReport); measurementReport->criticalExtensions.present = NR_MeasurementReport__criticalExtensions_PR_measurementReport; - NR_MeasurementReport_IEs_t *measurementReport_ie = CALLOC(1, sizeof(struct NR_MeasurementReport_IEs)); - measurementReport->criticalExtensions.choice.measurementReport = measurementReport_ie; - measurementReport_ie->measResults.measId = trigger_to_measid; + asn1cCalloc(measurementReport->criticalExtensions.choice.measurementReport, mrIE); + mrIE->measResults.measId = trigger_to_measid; - NR_MeasResultServMO_t *measResultServMo = CALLOC(1, sizeof(struct NR_MeasResultServMO)); + NR_MeasResultServMO_t *measResultServMo = calloc_or_fail(1, sizeof(*measResultServMo)); NR_MeasResultNR_t *measResultServingCell = &measResultServMo->measResultServingCell; - measResultServingCell->physCellId = CALLOC(1, sizeof(NR_PhysCellId_t)); - *measResultServingCell->physCellId = Nid_cell; - - struct NR_MeasQuantityResults *active_mq_res = CALLOC(1, sizeof(struct NR_MeasQuantityResults)); + asn1cCalloc(measResultServingCell->physCellId, pci); + *pci = Nid_cell; + struct NR_MeasQuantityResults *active_mq_res = calloc_or_fail(1, sizeof(*active_mq_res)); if (trigger_quantity == NR_MeasTriggerQuantityOffset_PR_rsrp) { asn1cCalloc(active_mq_res->rsrp, rsrp); // Assign precomputed RSRP index @@ -893,7 +888,7 @@ int do_nrMeasurementReport_SA(NR_MeasurementReport_t *measurementReport, measResultServingCell->measResult.cellResults.resultsCSI_RS_Cell = active_mq_res; } - ASN_SEQUENCE_ADD(&measurementReport_ie->measResults.measResultServingMOList.list, measResultServMo); + ASN_SEQUENCE_ADD(&mrIE->measResults.measResultServingMOList.list, measResultServMo); enc_rval = uper_encode_to_buffer(&asn_DEF_NR_UL_DCCH_Message, NULL, (void *)&ul_dcch_msg, buffer, buffer_size); AssertFatal(enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", enc_rval.failed_type->name, enc_rval.encoded); diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.h b/openair2/RRC/NR/MESSAGES/asn1_msg.h index 73a311084d..48a0ea734b 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.h +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.h @@ -125,8 +125,7 @@ int do_NR_MeasurementTimingConfiguration(const NR_MeasurementTimingConfiguration int do_RRCSetupRequest(uint8_t *buffer, size_t buffer_size, uint8_t *rv, uint64_t fiveG_S_TMSI_part1); -int do_nrMeasurementReport_SA(NR_MeasurementReport_t *measurementReport, - long trigger_to_measid, +int do_nrMeasurementReport_SA(long trigger_to_measid, long trigger_quantity, long rs_type, uint16_t Nid_cell, diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 85e9205a92..1733589427 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -3239,12 +3239,10 @@ void nr_rrc_set_mac_queue(instance_t instance, notifiedFIFO_t *mac_input_nf) void rrc_ue_generate_measurementReport(rrcPerNB_t *rrc, instance_t ue_id) { uint8_t buffer[NR_RRC_BUF_SIZE]; - NR_MeasurementReport_t measurementReport = {0}; l3_measurements_t *l3m = &rrc->l3_measurements; int rsrp_dBm = l3m->rs_type == NR_NR_RS_Type_ssb ? l3m->serving_cell.ss_rsrp_dBm.val : l3m->serving_cell.csi_rsrp_dBm.val; int rsrp_index = get_rsrp_index(rsrp_dBm); - uint8_t size = do_nrMeasurementReport_SA(&measurementReport, - l3m->trigger_to_measid, + uint8_t size = do_nrMeasurementReport_SA(l3m->trigger_to_measid, l3m->trigger_quantity, l3m->rs_type, l3m->serving_cell.Nid_cell, From 520d52963e9c4a7f19b2892bf821a56775e144a6 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Mon, 13 Oct 2025 11:56:49 +0200 Subject: [PATCH 942/964] ci: container_5g_f1_rfsim - remove oai-nr-cuup-asan MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rationale: CU-UP image not required for this F1 rfsim workflow’s local pull stage. --- ci-scripts/xml_files/container_5g_f1_rfsim.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ci-scripts/xml_files/container_5g_f1_rfsim.xml b/ci-scripts/xml_files/container_5g_f1_rfsim.xml index 9987aeaae0..6408a686a0 100644 --- a/ci-scripts/xml_files/container_5g_f1_rfsim.xml +++ b/ci-scripts/xml_files/container_5g_f1_rfsim.xml @@ -64,7 +64,7 @@ Pull_Local_Registry Pull Images from Local Registry localhost - oai-gnb-asan oai-nr-cuup-asan oai-nr-ue-asan + oai-gnb-asan oai-nr-ue-asan Create_Workspace @@ -245,7 +245,7 @@ true Clean Test Images on Test Server localhost - oai-gnb-asan oai-nr-cuup-asan oai-nr-ue-asan + oai-gnb-asan oai-nr-ue-asan From 0622fb362fe2f939d230c1fcb31172660f01d2fa Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Mon, 13 Oct 2025 11:52:47 +0200 Subject: [PATCH 943/964] ci: container_5g_f1_rfsim - extend F1 handover with 1 more hop - Trigger handover - IdleSleep 2s - Ping ext-dn from NR-UE - Verify UE(1) connected to DU-PCI1 Validate absence of heap-use-after-free ASAN error found in !3600. Closes #940 --- ci-scripts/xml_files/container_5g_f1_rfsim.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ci-scripts/xml_files/container_5g_f1_rfsim.xml b/ci-scripts/xml_files/container_5g_f1_rfsim.xml index 6408a686a0..50e794e4cb 100644 --- a/ci-scripts/xml_files/container_5g_f1_rfsim.xml +++ b/ci-scripts/xml_files/container_5g_f1_rfsim.xml @@ -55,6 +55,10 @@ 000031 020022 040026 + 040025 + 000031 + 020022 + 040027 100021 222222 From 1cd39501781d7ce5773031c3ea4adc1ecf59ce74 Mon Sep 17 00:00:00 2001 From: francescomani Date: Wed, 8 Oct 2025 16:31:15 +0200 Subject: [PATCH 944/964] fix non initialized DMRS port value in case of DCI00 at UE --- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 1 + 1 file changed, 1 insertion(+) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 16af9b4883..ae52615e52 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -604,6 +604,7 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, /*DCI format-related configuration*/ if (dci_format == NR_UL_DCI_FORMAT_0_0) { + pusch_config_pdu->dmrs_ports = 1; if (!tp_enabled && pusch_config_pdu->nr_of_symbols < 3) pusch_config_pdu->num_dmrs_cdm_grps_no_data = 1; else From 2b25b32b16ab5726787a475ec801bfee8a9e3718 Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 14 Oct 2025 16:01:46 +0200 Subject: [PATCH 945/964] default dmrs port value in ulsch ue scheduler --- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index ae52615e52..d2f8b3e4c8 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -398,7 +398,7 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, pusch_config_pdu->nrOfLayers = 1; pusch_config_pdu->Tpmi = 0; pusch_config_pdu->rnti = rnti; - + pusch_config_pdu->dmrs_ports = 1; pusch_dmrs_AdditionalPosition_t add_pos = pusch_dmrs_pos2; int dmrslength = 1; NR_PUSCH_Config_t *pusch_Config = current_UL_BWP->pusch_Config; @@ -435,7 +435,6 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, pusch_config_pdu->rb_size = msgA_PUSCH_Resource->nrofPRBs_PerMsgA_PO_r16; pusch_config_pdu->mcs_table = 0; pusch_config_pdu->frequency_hopping = msgA_PUSCH_Resource->msgA_IntraSlotFrequencyHopping_r16 ? *msgA_PUSCH_Resource->msgA_IntraSlotFrequencyHopping_r16 : 0; - pusch_config_pdu->dmrs_ports = 1; // is in SIB1 nrofDMRS_Sequences_r16? pusch_config_pdu->pusch_data.new_data_indicator = 1; // new data pusch_config_pdu->num_dmrs_cdm_grps_no_data = 2; pusch_config_pdu->ul_dmrs_symb_pos = get_l_prime(3, 0, pusch_dmrs_pos2, pusch_len1, 10, mac->dmrs_TypeA_Position); @@ -529,7 +528,6 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, // DM-RS configuration according to 6.2.2 UE DM-RS transmission procedure in 38.214 pusch_config_pdu->num_dmrs_cdm_grps_no_data = 2; - pusch_config_pdu->dmrs_ports = 1; // DMRS sequence initialization [TS 38.211, sec 6.4.1.1.1]. // Should match what is sent in DCI 0_1, otherwise set to 0. @@ -604,7 +602,6 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, /*DCI format-related configuration*/ if (dci_format == NR_UL_DCI_FORMAT_0_0) { - pusch_config_pdu->dmrs_ports = 1; if (!tp_enabled && pusch_config_pdu->nr_of_symbols < 3) pusch_config_pdu->num_dmrs_cdm_grps_no_data = 1; else From 1dd0194e32ba5d2030b2ca3318bdb45777f8375e Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Tue, 14 Oct 2025 20:36:48 +0200 Subject: [PATCH 946/964] remove unused global queues, dead code --- executables/lte-softmodem.c | 2 -- executables/nr-gnb.c | 11 +---------- openair1/PHY/defs_eNB.h | 1 - openair1/PHY/defs_gNB.h | 7 ------- openair1/SIMULATION/LTE_PHY/dlsim.c | 2 -- openair1/SIMULATION/LTE_PHY/ulsim.c | 2 -- openair1/SIMULATION/NR_PHY/dlsim.c | 6 +----- openair1/SIMULATION/NR_PHY/ulschsim.c | 1 - openair1/SIMULATION/NR_PHY/ulsim.c | 10 +--------- 9 files changed, 3 insertions(+), 39 deletions(-) diff --git a/executables/lte-softmodem.c b/executables/lte-softmodem.c index 25a3c25aa9..77fdb21eb4 100644 --- a/executables/lte-softmodem.c +++ b/executables/lte-softmodem.c @@ -497,12 +497,10 @@ int main ( int argc, char **argv ) L1_rxtx_proc_t *L1proc= &RC.eNB[x][CC_id]->proc.L1_proc; L1_rxtx_proc_t *L1proctx= &RC.eNB[x][CC_id]->proc.L1_proc_tx; L1proc->threadPool = (tpool_t *)malloc(sizeof(tpool_t)); - L1proc->respDecode=(notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t)); if ( strlen(get_softmodem_params()->threadPoolConfig) > 0 ) initTpool(get_softmodem_params()->threadPoolConfig, L1proc->threadPool, true); else initTpool("n", L1proc->threadPool, true); - initNotifiedFIFO(L1proc->respDecode); L1proctx->threadPool = L1proc->threadPool; } diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index 1021aba1ce..505adf825c 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -332,15 +332,10 @@ void init_gNB_Tpool(int inst) gNB->num_pusch_symbols_per_thread = 1; // ULSCH decoding threadpool initTpool(get_softmodem_params()->threadPoolConfig, &gNB->threadPool, cpumeas(CPUMEAS_GETSTATE)); - // ULSCH decoder result FIFO - initNotifiedFIFO(&gNB->respPuschSymb); - initNotifiedFIFO(&gNB->respDecode); // L1 RX result FIFO initNotifiedFIFO(&gNB->resp_L1); - // L1 TX result FIFO - initNotifiedFIFO(&gNB->L1_tx_free); - initNotifiedFIFO(&gNB->L1_tx_filled); + // L1 TX result FIFO initNotifiedFIFO(&gNB->L1_tx_out); initNotifiedFIFO(&gNB->L1_rx_out); @@ -369,10 +364,6 @@ void term_gNB_Tpool(int inst) { pthread_join(gNB->L1_tx_thread, NULL); abortTpool(&gNB->threadPool); - abortNotifiedFIFO(&gNB->respPuschSymb); - abortNotifiedFIFO(&gNB->respDecode); - abortNotifiedFIFO(&gNB->L1_tx_free); - abortNotifiedFIFO(&gNB->L1_tx_filled); abortNotifiedFIFO(&gNB->L1_rx_out); gNB_L1_proc_t *proc = &gNB->proc; diff --git a/openair1/PHY/defs_eNB.h b/openair1/PHY/defs_eNB.h index ef1db2e05f..6ae50482cc 100644 --- a/openair1/PHY/defs_eNB.h +++ b/openair1/PHY/defs_eNB.h @@ -254,7 +254,6 @@ typedef struct { pthread_mutex_t mutex_RUs; tpool_t *threadPool; int nbDecode; - notifiedFIFO_t *respDecode; int first_rx; } L1_rxtx_proc_t; diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h index 987f77d953..29bf0ebf6b 100644 --- a/openair1/PHY/defs_gNB.h +++ b/openair1/PHY/defs_gNB.h @@ -537,17 +537,10 @@ typedef struct PHY_VARS_gNB_s { time_stats_t srs_beam_report_stats; time_stats_t srs_iq_matrix_stats; - notifiedFIFO_t respPuschSymb; - notifiedFIFO_t respDecode; notifiedFIFO_t resp_L1; - notifiedFIFO_t L1_tx_free; - notifiedFIFO_t L1_tx_filled; notifiedFIFO_t L1_tx_out; notifiedFIFO_t L1_rx_out; - notifiedFIFO_t resp_RU_tx; tpool_t threadPool; - int nbSymb; - int nbAarx; int num_pusch_symbols_per_thread; int dmrs_num_antennas_per_thread; pthread_t L1_rx_thread; diff --git a/openair1/SIMULATION/LTE_PHY/dlsim.c b/openair1/SIMULATION/LTE_PHY/dlsim.c index a593a0dfb4..d6e8482919 100644 --- a/openair1/SIMULATION/LTE_PHY/dlsim.c +++ b/openair1/SIMULATION/LTE_PHY/dlsim.c @@ -1263,9 +1263,7 @@ int main(int argc, char **argv) { L1_rxtx_proc_t *proc_eNB = &eNB->proc.L1_proc; proc_eNB->threadPool = (tpool_t *)malloc(sizeof(tpool_t)); - proc_eNB->respDecode=(notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t)); initTpool("n", proc_eNB->threadPool, true); - initNotifiedFIFO(proc_eNB->respDecode); proc_eNB->frame_tx=0; diff --git a/openair1/SIMULATION/LTE_PHY/ulsim.c b/openair1/SIMULATION/LTE_PHY/ulsim.c index d17f767a2a..76cc2e0716 100644 --- a/openair1/SIMULATION/LTE_PHY/ulsim.c +++ b/openair1/SIMULATION/LTE_PHY/ulsim.c @@ -795,9 +795,7 @@ int main(int argc, char **argv) { proc_rxtx_ue->subframe_tx = proc_rxtx->subframe_rx; proc_rxtx_ue->subframe_rx = (proc_rxtx->subframe_tx+6)%10; proc_rxtx->threadPool = (tpool_t *)malloc(sizeof(tpool_t)); - proc_rxtx->respDecode=(notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t)); initTpool("n", proc_rxtx->threadPool, true); - initNotifiedFIFO(proc_rxtx->respDecode); printf("Init UL hopping UE\n"); init_ul_hopping(&UE->frame_parms); diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index d1d046505e..c6dc39dc1d 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -965,12 +965,9 @@ int main(int argc, char **argv) //NR_COMMON_channels_t *cc = RC.nrmac[0]->common_channels; int ret = 1; initNamedTpool(gNBthreads, &gNB->threadPool, true, "gNB-tpool"); - initNotifiedFIFO(&gNB->L1_tx_free); - initNotifiedFIFO(&gNB->L1_tx_filled); initNotifiedFIFO(&gNB->L1_tx_out); // we create 2 threads for L1 tx processing - notifiedFIFO_elt_t *msgL1Tx = newNotifiedFIFO_elt(sizeof(processingData_L1tx_t),0,&gNB->L1_tx_free,processSlotTX); - processingData_L1tx_t *msgDataTx = (processingData_L1tx_t *)NotifiedFifoData(msgL1Tx); + processingData_L1tx_t *msgDataTx = malloc(sizeof(processingData_L1tx_t)); init_DLSCH_struct(gNB, msgDataTx); msgDataTx->slot = slot; msgDataTx->frame = frame; @@ -1091,7 +1088,6 @@ int main(int argc, char **argv) Sched_INFO->frame = frame; Sched_INFO->slot = slot; Sched_INFO->UL_dci_req.numPdus = 0; - pushNotifiedFIFO(&gNB->L1_tx_free,msgL1Tx); nr_schedule_response(Sched_INFO); /* PTRS values for DLSIM calculations */ diff --git a/openair1/SIMULATION/NR_PHY/ulschsim.c b/openair1/SIMULATION/NR_PHY/ulschsim.c index 64c04b900e..77a0046e1f 100644 --- a/openair1/SIMULATION/NR_PHY/ulschsim.c +++ b/openair1/SIMULATION/NR_PHY/ulschsim.c @@ -391,7 +391,6 @@ int main(int argc, char **argv) //gNB_config = &gNB->gNB_config; initTpool("n", &gNB->threadPool, true); - initNotifiedFIFO(&gNB->respDecode); frame_parms = &gNB->frame_parms; //to be initialized I suppose (maybe not necessary for PBCH) frame_parms->N_RB_DL = N_RB_DL; frame_parms->N_RB_UL = N_RB_UL; diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index 93789ba737..c4b2f854c2 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -727,14 +727,7 @@ int main(int argc, char *argv[]) else initNamedTpool(gNBthreads, &gNB->threadPool, true, "gNB-tpool"); - initNotifiedFIFO(&gNB->respDecode); - - initNotifiedFIFO(&gNB->respPuschSymb); - initNotifiedFIFO(&gNB->L1_tx_free); - initNotifiedFIFO(&gNB->L1_tx_filled); - initNotifiedFIFO(&gNB->L1_tx_out); - notifiedFIFO_elt_t *msgL1Tx = newNotifiedFIFO_elt(sizeof(processingData_L1tx_t), 0, &gNB->L1_tx_free, NULL); - processingData_L1tx_t *msgDataTx = (processingData_L1tx_t *)NotifiedFifoData(msgL1Tx); + processingData_L1tx_t *msgDataTx = malloc(sizeof(processingData_L1tx_t)); msgDataTx->slot = -1; gNB->msgDataTx = msgDataTx; //gNB_config = &gNB->gNB_config; @@ -1299,7 +1292,6 @@ int main(int argc, char *argv[]) UE_proc.gNB_id = 0; // prepare ULSCH/PUSCH reception - pushNotifiedFIFO(&gNB->L1_tx_free, msgL1Tx); // to unblock the process in the beginning nr_schedule_response(Sched_INFO); // --------- setting parameters for UE -------- From b9043d990abbfe22cf946921ae6f702b413720ce Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 15 Oct 2025 08:29:41 +0200 Subject: [PATCH 947/964] Doc: correctly link to non-indexed files in doc/README.md --- doc/README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/README.md b/doc/README.md index c48f2b6ee8..927360c887 100644 --- a/doc/README.md +++ b/doc/README.md @@ -65,13 +65,14 @@ There is some general information in the [OpenAirInterface Gitlab Wiki](https:// - [How to run the physical simulators](./physical-simulators.md) - [How to setup OAI with Nvidia Aerial and Foxconn](./Aerial_FAPI_Split_Tutorial.md) - [How to setup OAI with LDPC accelerators (Xilinx T2/Intel ACCs)](./LDPC_OFFLOAD_SETUP.md) +- [How to setup OAI with the XDMA FPGA LDPC accelerator](./LDPC_XDMA_offload_setup.md) - [How to do a handover](./handover-tutorial.md) - [How to setup gNB frequency](./gNB_frequency_setup.md) +- [How to use the RT data recording app](./data_recording.md) Legacy unmaintained files: - [`L2NFAPI_NOS1.md`](./L2NFAPI_NOS1.md), [`L2NFAPI_S1.md`](./L2NFAPI_S1.md): old L2simulator, not valid anymore -- [`UL_MIMO.txt`](./UL_MIMO.txt): UL-MIMO specific notes # Designs @@ -85,6 +86,7 @@ Legacy unmaintained files: - [Information on gNB RRC](./RRC/rrc-usage.md) - [Information on analog beamforming implementation](./analog_beamforming.md) - [Information on the UE 5G NAS implementation](./5Gnas.md) +- [Information on UL-MIMO](./UL_MIMO.md): UL-MIMO specific notes # Building and running from images From 2db630e18756d2ed2cdff0fa6538926beaafd299 Mon Sep 17 00:00:00 2001 From: Robert Date: Wed, 24 Sep 2025 16:04:50 +0000 Subject: [PATCH 948/964] Add UL-heavy Aerial config Update cuBB image to cubb-build:25-2.1_srs-ul-heavy (release 25-2.1 with changes in the L1 config to test heavy ul) Co-authored-by: Reem Bahsoun --- ...-vnf.sa.band78.273prb.aerial.ul-heavy.conf | 227 ++++++++++++++++++ .../sa_gnb_aerial_ul/aerial_l1_entrypoint.sh | 34 +++ .../sa_gnb_aerial_ul/docker-compose.yaml | 66 +++++ 3 files changed, 327 insertions(+) create mode 100644 ci-scripts/conf_files/gnb-vnf.sa.band78.273prb.aerial.ul-heavy.conf create mode 100755 ci-scripts/yaml_files/sa_gnb_aerial_ul/aerial_l1_entrypoint.sh create mode 100644 ci-scripts/yaml_files/sa_gnb_aerial_ul/docker-compose.yaml diff --git a/ci-scripts/conf_files/gnb-vnf.sa.band78.273prb.aerial.ul-heavy.conf b/ci-scripts/conf_files/gnb-vnf.sa.band78.273prb.aerial.ul-heavy.conf new file mode 100644 index 0000000000..d6bdc66ddd --- /dev/null +++ b/ci-scripts/conf_files/gnb-vnf.sa.band78.273prb.aerial.ul-heavy.conf @@ -0,0 +1,227 @@ +Active_gNBs = ( "gNB-OAI"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +nfapi = "AERIAL"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + gNB_name = "gNB-OAI"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + plmn_list = ({ mcc = 208; mnc = 97; mnc_length = 2; snssaiList = ({ sst = 1; }); }); + + nr_cellid = 12345678L; + uess_agg_levels = [0,6,0,0,0]; + + ////////// Physical parameters: + + pdsch_AntennaPorts_XP = 2; + pdsch_AntennaPorts_N1 = 2; + pusch_AntennaPorts = 2; + do_CSIRS = 1; + do_SRS = 0; + min_rxtxtime = 2; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # center frequency = 3350.01 MHz + # selected SSB frequency = 3349.92 MHz + absoluteFrequencySSB = 623328; + dl_frequencyBand = 78; + # frequency point A = 3300.87 MHz + dl_absoluteFrequencyPointA = 620058; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 273; + #initialDownlinkBWP + #genericParameters + # this is RBstart=0,L=162 (275*(275-L+1))+(274-RBstart)) + initialDLBWPlocationAndBandwidth = 1099; + # +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 12; + initialDLBWPsearchSpaceZero = 0; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 273; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 1099; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 159;# testMAC 158; OAI gNB 98 +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 12; + preambleReceivedTargetPower = -96; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#one (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant = -90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; + + ssb_PositionsInBurst_Bitmap = 1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 5; + nrofDownlinkSlots = 1; + nrofDownlinkSymbols = 10; + nrofUplinkSlots = 3; + nrofUplinkSymbols = 0; + + ssPBCH_BlockPower = -25; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// AMF parameters: + amf_ip_address = ({ ipv4 = "172.21.6.103"; }); + + + NETWORK_INTERFACES : + { + GNB_IPV4_ADDRESS_FOR_NG_AMF = "172.21.16.202"; + GNB_IPV4_ADDRESS_FOR_NGU = "172.21.16.202"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + } +); + +MACRLCs = ( +{ + num_cc = 1; + remote_s_address = "127.0.0.1"; // pnf addr [!] + local_s_address = "127.0.0.2"; // vnf addr + local_s_portc = 50001; // vnf p5 port + remote_s_portc = 50000; // pnf p5 port [!] + local_s_portd = 50011; // vnf p7 port [!] + remote_s_portd = 50010; // pnf p7 port [!] + tr_s_preference = "aerial"; + tr_n_preference = "local_RRC"; + pusch_TargetSNRx10 = 220; # 150; + pucch_TargetSNRx10 = 200; #200; + dl_max_mcs = 28; + ul_max_mcs = 28; + ul_min_mcs = 16; +} +); + + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + +log_config : +{ + global_log_level ="info"; + hw_log_level ="info"; + phy_log_level ="info"; + mac_log_level ="info"; + rlc_log_level ="info"; + pdcp_log_level ="info"; + rrc_log_level ="info"; + ngap_log_level ="debug"; + f1ap_log_level ="debug"; +}; diff --git a/ci-scripts/yaml_files/sa_gnb_aerial_ul/aerial_l1_entrypoint.sh b/ci-scripts/yaml_files/sa_gnb_aerial_ul/aerial_l1_entrypoint.sh new file mode 100755 index 0000000000..e0fea22190 --- /dev/null +++ b/ci-scripts/yaml_files/sa_gnb_aerial_ul/aerial_l1_entrypoint.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +# Check if cuBB_SDK is defined, if not, use default path +cuBB_Path="${cuBB_SDK:-/opt/nvidia/cuBB}" + +cd "$cuBB_Path" || exit 1 +# Add gdrcopy to LD_LIBRARY_PATH +export LD_LIBRARY_PATH=/usr/local/nvidia/lib:/usr/local/nvidia/lib64:/opt/mellanox/dpdk/lib/x86_64-linux-gnu:/opt/mellanox/doca/lib/x86_64-linux-gnu:/opt/nvidia/cuBB/cuPHY-CP/external/gdrcopy/build/x86_64/ + +# Restart MPS +# Export variables +export CUDA_DEVICE_MAX_CONNECTIONS=8 +export CUDA_MPS_PIPE_DIRECTORY=/var +export CUDA_MPS_LOG_DIRECTORY=/var + +# Stop existing MPS +sudo -E echo quit | sudo -E nvidia-cuda-mps-control + +# Start MPS +sudo -E nvidia-cuda-mps-control -d +sudo -E echo start_server -uid 0 | sudo -E nvidia-cuda-mps-control + +# Start cuphycontroller_scf +# Check if an argument is provided +if [ $# -eq 0 ]; then + # No argument provided, use default value + argument="P5G_FXN_GH" +else + # Argument provided, use it + argument="$1" +fi + +sudo -E "$cuBB_Path"/build/cuPHY-CP/cuphycontroller/examples/cuphycontroller_scf "$argument" +sudo -E ./build/cuPHY-CP/gt_common_libs/nvIPC/tests/pcap/pcap_collect diff --git a/ci-scripts/yaml_files/sa_gnb_aerial_ul/docker-compose.yaml b/ci-scripts/yaml_files/sa_gnb_aerial_ul/docker-compose.yaml new file mode 100644 index 0000000000..077c58c67c --- /dev/null +++ b/ci-scripts/yaml_files/sa_gnb_aerial_ul/docker-compose.yaml @@ -0,0 +1,66 @@ +services: + nv-cubb: + container_name: nv-cubb + deploy: + resources: + reservations: + devices: + - driver: nvidia + count: all + capabilities: + - gpu + network_mode: host + shm_size: 4096m + privileged: true + stdin_open: true + tty: true + volumes: + - /lib/modules:/lib/modules + - /dev/hugepages:/dev/hugepages + - /usr/src:/usr/src + - ./aerial_l1_entrypoint.sh:/opt/nvidia/cuBB/aerial_l1_entrypoint.sh + - /var/log/aerial:/var/log/aerial + - ../../../cmake_targets/share:/opt/cuBB/share + userns_mode: host + ipc: "shareable" + image: cubb-build:25-2.1_srs-ul-heavy + environment: + - cuBB_SDK=/opt/nvidia/cuBB + command: bash -c "sudo rm -rf /tmp/phy.log && sudo chmod +x /opt/nvidia/cuBB/aerial_l1_entrypoint.sh && /opt/nvidia/cuBB/aerial_l1_entrypoint.sh" + healthcheck: + test: ["CMD-SHELL",'grep -q "L1 is ready!" /tmp/phy.log && echo 0 || echo 1'] + interval: 20s + timeout: 5s + retries: 5 + oai-gnb-aerial: + cpuset: "13-16" + image: ${REGISTRY:-oaisoftwarealliance}/oai-gnb-aerial:${TAG:-develop} + depends_on: + nv-cubb: + condition: service_healthy + cap_drop: + - ALL + cap_add: + - SYS_NICE + - IPC_LOCK + ipc: "container:nv-cubb" + environment: + USE_ADDITIONAL_OPTIONS: --log_config.global_log_options level,nocolor,time + deploy: + resources: + reservations: + devices: + - driver: nvidia + count: all + capabilities: + - gpu + network_mode: host + shm_size: 4096m + volumes: + - ../../conf_files/gnb-vnf.sa.band78.273prb.aerial.ul-heavy.conf:/opt/oai-gnb/etc/gnb.conf + container_name: oai-gnb-aerial + healthcheck: + test: /bin/bash -c "ps aux | grep -v grep | grep -c softmodem" + interval: 10s + timeout: 5s + retries: 5 From 3b517dd5d20409a1185b580fab9433bebe8aac36 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 24 Sep 2025 18:35:39 +0200 Subject: [PATCH 949/964] Add CI XML fail for Aerial UL heavy pipeline --- .../container_sa_aerial_quectel_ul_heavy.xml | 144 ++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 ci-scripts/xml_files/container_sa_aerial_quectel_ul_heavy.xml diff --git a/ci-scripts/xml_files/container_sa_aerial_quectel_ul_heavy.xml b/ci-scripts/xml_files/container_sa_aerial_quectel_ul_heavy.xml new file mode 100644 index 0000000000..ab38b72295 --- /dev/null +++ b/ci-scripts/xml_files/container_sa_aerial_quectel_ul_heavy.xml @@ -0,0 +1,144 @@ + + + TEST-AERIAL-SA-UL-Heavy + AERIAL 100 MHz DSUUU SA + tasks + + 111111 + 000222 + 800813 + 002222 + 002223 + 000111 + 000011 + 000032 + 000033 + 000022 + 000222 + 222222 + 333333 + + + + Pull_Local_Registry + Pull Images from Local Registry + gracehopper1-oai + oai-gnb-aerial + arm_ + + + + Create_Workspace + Create new Workspace for server 0 + gracehopper1-oai + + + + Deploy_Object + Deploy PNF/Nvidia CUBB in a container + gracehopper1-oai + ci-scripts/yaml_files/sa_gnb_aerial_ul + nv-cubb + + + + Deploy_Object + Deploy VNF in a container + gracehopper1-oai + ci-scripts/yaml_files/sa_gnb_aerial_ul + oai-gnb-aerial + + + + Attach_UE + Attach Quectel + up2-aerial + + + + Ping + Ping: 100pings in 20sec + up2-aerial + oc-cn5g-20897-aerial + -c 100 -i 0.2 + 5 + + + + Iperf + iperf (DL/UDP/200M)(30 sec)(single-ue profile) + -u -b 200M -t 30 -R + oc-cn5g-20897-aerial + up2-aerial + 25 + 80 + + + + Iperf + iperf (UL/UDP/200M)(30 sec)(single-ue profile) + -u -b 200M -t 30 -l 1428 + oc-cn5g-20897-aerial + up2-aerial + 10 + 90 + + + + Iperf + iperf (UL/UDP/220M)(30 sec)(single-ue profile) + true + -u -b 220M -t 30 -l 1428 + oc-cn5g-20897-aerial + up2-aerial + 10 + 90 + + + + Detach_UE + true + Detach Quectel + up2-aerial + + + + Undeploy_Object + true + Undeploy gNB + gracehopper1-oai + ci-scripts/yaml_files/sa_gnb_aerial_ul + 20,100,100,100 + 20,100,100,100 + + + + Clean_Test_Server_Images + true + Clean Test Images on Test Server + gracehopper1-oai + oai-gnb-aerial + + + From ae63a51ceb649e3559907c840de5a5638fc51c49 Mon Sep 17 00:00:00 2001 From: Robert Date: Mon, 29 Sep 2025 09:07:24 +0000 Subject: [PATCH 950/964] Increase PBCH Block power: better UL --- .../conf_files/gnb-vnf.sa.band78.273prb.aerial.ul-heavy.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci-scripts/conf_files/gnb-vnf.sa.band78.273prb.aerial.ul-heavy.conf b/ci-scripts/conf_files/gnb-vnf.sa.band78.273prb.aerial.ul-heavy.conf index d6bdc66ddd..90662226ed 100644 --- a/ci-scripts/conf_files/gnb-vnf.sa.band78.273prb.aerial.ul-heavy.conf +++ b/ci-scripts/conf_files/gnb-vnf.sa.band78.273prb.aerial.ul-heavy.conf @@ -147,7 +147,7 @@ gNBs = nrofUplinkSlots = 3; nrofUplinkSymbols = 0; - ssPBCH_BlockPower = -25; + ssPBCH_BlockPower = -10; } ); From 7ff05a98c22a553455819f7ab0c43a96c7332258 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 1 Oct 2025 13:36:10 +0200 Subject: [PATCH 951/964] Print frame/slot on UL failure --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index ac4b1717a8..f923a2c9ec 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -1028,7 +1028,9 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP, if (!get_softmodem_params()->phy_test && UE->UE_sched_ctrl.pusch_consecutive_dtx_cnt >= pusch_failure_thres) { LOG_W(NR_MAC, - "UE %04x: Detected UL Failure on PUSCH after %d PUSCH DTX, stopping scheduling\n", + "%4d.%2d UE %04x: Detected UL Failure on PUSCH after %d PUSCH DTX, stopping scheduling\n", + frameP, + slotP, UE->rnti, UE->UE_sched_ctrl.pusch_consecutive_dtx_cnt); nr_mac_trigger_ul_failure(&UE->UE_sched_ctrl, UE->current_UL_BWP.scs); From 1a472e4c0b5a1bcb355be4a419659f2fb1adc48a Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 7 Oct 2025 18:04:46 +0200 Subject: [PATCH 952/964] Msg3 retx: check that current slot is DL The code only checked that Msg3 would be scheduled during UL, but in some combinations, e.g., with DSUUU, the current slot can very well be UL as well => we would schedule DCI in UL slot. --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 715feb5b33..5e9cd47a79 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -805,7 +805,7 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP, const int sched_frame = (frame + (slot + K2) / slots_frame) % MAX_FRAME_NUMBER; const int sched_slot = (slot + K2) % slots_frame; - if (is_ul_slot(sched_slot, &nr_mac->frame_structure)) { + if (is_dl_slot(slot, &nr_mac->frame_structure) && is_ul_slot(sched_slot, &nr_mac->frame_structure)) { NR_beam_alloc_t beam_ul = beam_allocation_procedure(&nr_mac->beam_info, sched_frame, sched_slot, UE->UE_beam_index, slots_frame); if (beam_ul.idx < 0) return; From 8c85acbba66e3023a416dd82f1a6d0c82e6c1925 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 23 Sep 2025 11:59:48 +0200 Subject: [PATCH 953/964] Add script to control attenuation of Mini-Circuits RC*DAT --- ci-scripts/attenuatorctl.py | 175 ++++++++++++++++++++++++++++++++++++ 1 file changed, 175 insertions(+) create mode 100644 ci-scripts/attenuatorctl.py diff --git a/ci-scripts/attenuatorctl.py b/ci-scripts/attenuatorctl.py new file mode 100644 index 0000000000..e6f8c01837 --- /dev/null +++ b/ci-scripts/attenuatorctl.py @@ -0,0 +1,175 @@ +#!/usr/bin/env python3 + +import argparse +import logging +import itertools +import usb.core +import usb.util +import sys +import time + +logging.basicConfig( + level=logging.DEBUG, + stream=sys.stdout, + format="%(message)s" +) + +# helper class parsing command line options for channels and attenuators +class ValidateChAtt(argparse.Action): + def _parse_channels(s): + if len(s.split("-")) == 2: + s, e = [int(x) for x in s.split("-")] + chs = [x for x in range(s, e+1)] + if len(chs) == 0: + raise Exception(f"empty range") + elif len(s.split(",")) > 1: + chs = [int(x) for x in s.split(",")] + elif s.isdigit(): + chs = [int(s)] + else: + raise Exception(f"could not parse channel expression") + for c in chs: + if not 1 <= c <= 4: + raise Exception(f"channel number must be within [1,4], but have {c}") + return chs + + def __call__(self, parse, args, values, option_string=None): + ch, att = values + try: + chs = ValidateChAtt._parse_channels(ch) + except Exception as e: + parse.exit(1, f"while parsing channel expression {ch}: {e}\n") + if not att.isdigit(): + parse.exit(1, f'expected number for attenuation, but got {att}\n') + if not 0 <= int(att) <= 63: + parse.exit(1, f'attenuation must be within [0,63], but is {att}\n') + opts = getattr(args, self.dest) or {} + for c in chs: + opts[c] = int(att) + setattr(args, self.dest, opts) + +def _parse_args() -> argparse.Namespace: + epilog = ''' +[CHs] can have the following forms: + (1) single channel number w (within [1-4]) + (2) a range of channels in the form x-y (x <= y) + (3) a list of channels in the form a,b,c +[ATT] must be within [0,63] (dB) + +--set and --reach are mutually exclusive + +Examples: +- reset all channels to 0: -s 1-4 0 +- set channels 3 and 4 to attenuation 60: -s 3,4 60 +- perform attenuation sweep during 10s, reaching ch. 1+2 to 60: -r 1,2 60 -d 10 +''' + parser = argparse.ArgumentParser(description='Mini-Circuit RC*DAT attenuator controller', + epilog=epilog, + formatter_class=argparse.RawDescriptionHelpFormatter) + + parser.add_argument('--info', '-i', action='store_true', default=False, + help='Get Infos for all connected Mini-Circuits RC*DAT',) + parser.add_argument('--set', '-s', nargs=2, metavar=("[CHs]","[ATT]"), + action=ValidateChAtt, help="Set a fixed attenuation ATT on channels CHs") + parser.add_argument('--reach', '-r', nargs=2, metavar=("[CHs]","[ATT]"), + action=ValidateChAtt, help="Perform an \"attenuation sweep\": reach attenuation ATT on channels CHs") + parser.add_argument('--duration', '-d', action='store', type=float, default=5.0, + help='DURATION for attenuation sweep to --reach given attenuation (Default: 5)',) + parser.add_argument('--progress', '-p', action='store_true', default=False, + help='If provided, will show progress during attenuation sweep',) + return parser.parse_args() + +def _exec(dev, cmd): + dev.write(1, cmd) + ans = dev.read(0x81,64) + # take from ans(wer) while valid bytes + sn = itertools.takewhile(lambda x: x < 255 and x > 0, ans) + # turn bytes into characters and accumulate into string + return "".join(map(chr, sn)) + +def devId(dev): + return f"{dev.idVendor:04x}:{dev.idProduct:04x}" + +def _info(dev): + ident = devId(dev) + SerialN = _exec(dev, "*:SN?") + ModelN = _exec(dev, "*:MN?") + Fw = _exec(dev, "*:FIRMWARE?") + + logging.info(f'{ident}: model is {ModelN}') + logging.info(f'{ident}: serial number is {SerialN}') + logging.info(f'{ident}: FW version is {Fw}') + +def _get_attenuation(dev): + ident = devId(dev) + att = _exec(dev, "*:ATT?") + # remove leading "*" and split by channels + return [float(n) for n in att[1:].split(" ")] + +def _set_attenuation(dev, ch_att): + ident = devId(dev) + for ch, att in ch_att: + #logging.debug(f"{ident}: Set attenuation channel {ch}: {att} dB") + att = round(4 * att) / 4 # round to closest 0.25dB + resp = _exec(dev, f"*:CHAN:{ch}:SETATT:{att};" ) + +def _continuous_set_attenuation(dev, ch_att_end, duration, show_progress=False, step_duration=0.25): + ident = devId(dev) + + current = _get_attenuation(dev) + steps = duration / step_duration + ch_att_step = [(ch, (att_end - current[ch - 1]) / steps) for ch, att_end in ch_att_end] + logging.info(f"{ident}: sweep attenuation during {duration} s in {steps} steps: increments {ch_att_step}") + for i in range(1, int(steps)+1): + next_att = [(ch, current[ch - 1] + i * att_step) for ch, att_step in ch_att_step] + _set_attenuation(dev, next_att) + if show_progress: + logging.debug(f"{ident}: attenuation for channel(s): {next_att}") + time.sleep(step_duration) + _set_attenuation(dev, ch_att_end) + +def _get_usb_devs(idVendor, idProduct): + devs = [] + for dev in usb.core.find(idVendor=idVendor, idProduct=idProduct, find_all=True): + for configuration in dev: + for interface in configuration: + ifnum = interface.bInterfaceNumber + if not dev.is_kernel_driver_active(ifnum): + continue + try: + dev.detach_kernel_driver(ifnum) + except e: + pass + devs.append(dev) + return devs + +if __name__ == '__main__': + # Parse the arguments + args = _parse_args() + if args.set and args.reach: + logging.error("--set and --reach are mutually exclusive") + sys.exit(1) + + # 20ce:0023 is Mini-Circuit RC*DAT device + devs = _get_usb_devs(idVendor=0x20ce, idProduct=0x0023) + if len(devs) == 0: + logging.error('no Mini-Circuits RC*DAT device detected') + sys.exit(-1) + if len(devs) > 1: + logging.error('more than one Mini-Circuits RC*DAT device detected') + sys.exit(-1) + dev = devs[0] + + if args.info: + _info(dev) + + if args.set: + _set_attenuation(dev, [(k,v) for k,v in args.set.items()]) + + if args.reach: + _continuous_set_attenuation(dev, [(k,v) for k,v in args.reach.items()], args.duration, args.progress) + + ident = devId(dev) + for i, a in enumerate(_get_attenuation(dev)): + logging.info(f"{ident}: Attenuation channel {i+1}: {a} dB") + sys.exit(0) From f93a71977fccf561a9a6d8143190d1c5c141faa8 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Fri, 10 Oct 2025 17:46:14 +0200 Subject: [PATCH 954/964] Add band validation in neighbor cell configuration - Add band mismatch check in valid_du_in_neighbour_configs function - Ensures neighbor cell band matches serving cell band - Prevents invalid neighbor configurations for handover --- openair2/RRC/NR/rrc_gNB_du.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/openair2/RRC/NR/rrc_gNB_du.c b/openair2/RRC/NR/rrc_gNB_du.c index edf6f19164..246df60626 100644 --- a/openair2/RRC/NR/rrc_gNB_du.c +++ b/openair2/RRC/NR/rrc_gNB_du.c @@ -257,6 +257,11 @@ static bool valid_du_in_neighbour_configs(const seq_arr_t *neighbour_cell_config nc->absoluteFrequencySSB); return false; } + // Check neighbour band + if (get_dl_band(cell) != nc->band) { + LOG_W(NR_RRC, "Cell %ld in neighbour config: Band mismatch (%d vs %d)\n", cell->nr_cellid, get_dl_band(cell), nc->band); + return false; + } if (get_ssb_scs(cell) != nc->subcarrierSpacing) { LOG_W(NR_RRC, "Cell %ld in neighbour config: SCS mismatch (%d vs %d)\n", From 0ba9a9758b302816cd35a9ce62d7839351d86055 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 13 Oct 2025 09:43:44 +0200 Subject: [PATCH 955/964] CI: expand %%workspace%% token - main.py: replace %%workspace%% with CONTAINERS.eNBSourceCodePath in Custom_Command and Custom_Script Co-authored-by: Guido Casati --- ci-scripts/main.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 3e7be396cc..ac4ac2c3be 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -321,11 +321,15 @@ def ExecuteActionWithParam(action, ctx): # Change all execution targets to localhost node = 'localhost' command = test.findtext('command') + # Allow referencing repository workspace path in XML via %%workspace%% + command = command.replace("%%workspace%%", CONTAINERS.eNBSourceCodePath) success = cls_oaicitest.Custom_Command(HTML, node, command) elif action == 'Custom_Script': node = test.findtext('node') script = test.findtext('script') + # Allow referencing repository workspace path in XML via %%workspace%% + script = script.replace("%%workspace%%", CONTAINERS.eNBSourceCodePath) success = cls_oaicitest.Custom_Script(HTML, node, script) elif action == 'Pull_Cluster_Image': From 42a54a01a037451c5a32f9b02a8c7519d466a09c Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 9 Oct 2025 16:38:38 +0200 Subject: [PATCH 956/964] USRP: move time/clock source setting to later Doing this before using set_master_clock_rate() on the B200 seems to invalidate synchronization setting. [HW] USRP clock set to 1759836386.000000 sec [...] [HW] current pps at 3.286750, starting streaming at 4.286750 In other words, the current time setting was reset. With this change now, we see [HW] USRP clock set to 1759929873.000000 sec [...] [HW] current pps at 1759929873.000000, starting streaming at 1759929874.000000 This is because changing clock sources (I assume setting the master clock rate impacts the clock) can result in changing the time. From the documentation of [1]: > Note: When changing clock sources, a previously set time will most > likely be lost. It is recommended to set the time after changing the > clock source. Otherwise, an unexpected time may line up with future PPS > edges. [1] https://files.ettus.com/manual/classuhd_1_1usrp_1_1multi__usrp.html#a99254abfa5259b70a020e667eee619b9 --- radio/USRP/usrp_lib.cpp | 139 ++++++++++++++++++---------------------- 1 file changed, 64 insertions(+), 75 deletions(-) diff --git a/radio/USRP/usrp_lib.cpp b/radio/USRP/usrp_lib.cpp index 6dde70b2eb..79c58b59f4 100644 --- a/radio/USRP/usrp_lib.cpp +++ b/radio/USRP/usrp_lib.cpp @@ -1161,79 +1161,6 @@ extern "C" { s->usrp = uhd::usrp::multi_usrp::make(args); - if (args.find("clock_source")==std::string::npos) { - if (openair0_cfg[0].clock_source == internal) { - s->usrp->set_clock_source("internal"); - LOG_I(HW,"Setting clock source to internal\n"); - } - else if (openair0_cfg[0].clock_source == external ) { - s->usrp->set_clock_source("external"); - LOG_I(HW,"Setting clock source to external\n"); - } - else if (openair0_cfg[0].clock_source==gpsdo) { - s->usrp->set_clock_source("gpsdo"); - LOG_I(HW,"Setting clock source to gpsdo\n"); - } - else { - LOG_W(HW,"Clock source set neither in usrp_args nor on command line, using default!\n"); - } - } - else { - if (openair0_cfg[0].clock_source != unset) { - LOG_W(HW,"Clock source set in both usrp_args and in clock_source, ingnoring the latter!\n"); - } - } - - if (args.find("time_source")==std::string::npos) { - if (openair0_cfg[0].time_source == internal) { - s->usrp->set_time_source("internal"); - LOG_I(HW,"Setting time source to internal\n"); - } - else if (openair0_cfg[0].time_source == external ) { - s->usrp->set_time_source("external"); - LOG_I(HW,"Setting time source to external\n"); - } - else if (openair0_cfg[0].time_source==gpsdo) { - s->usrp->set_time_source("gpsdo"); - LOG_I(HW,"Setting time source to gpsdo\n"); - } - else { - LOG_W(HW,"Time source set neither in usrp_args nor on command line, using default!\n"); - } - } - else { - 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"); - } - } - - - if (s->usrp->get_clock_source(0) == "gpsdo") { - s->use_gps = 1; - - if (sync_to_gps(device)==EXIT_SUCCESS) { - LOG_I(HW,"USRP synced with GPS!\n"); - } else { - LOG_I(HW,"USRP fails to sync with GPS. Exiting.\n"); - exit(EXIT_FAILURE); - } - } else { - if (s->usrp->get_time_source(0) == "external") { - usrp_sync_pps(s); - } else { - s->usrp->set_time_next_pps(uhd::time_spec_t(0.0)); - } - - if (s->usrp->get_clock_source(0) == "external") { - if (check_ref_locked(s,0)) { - LOG_I(HW,"USRP locked to external reference!\n"); - } else { - LOG_I(HW,"Failed to lock to external reference. Exiting.\n"); - exit(EXIT_FAILURE); - } - } - } - if (device->type==USRP_X300_DEV) { openair0_cfg[0].rx_gain_calib_table = calib_table_x310; std::cerr << "-- Using calibration table: calib_table_x310" << std::endl; @@ -1470,8 +1397,70 @@ extern "C" { } } - //s->usrp->set_clock_source("external"); - //s->usrp->set_time_source("external"); + if (args.find("clock_source") == std::string::npos) { + if (openair0_cfg[0].clock_source == internal) { + s->usrp->set_clock_source("internal"); + LOG_I(HW, "Setting clock source to internal\n"); + } else if (openair0_cfg[0].clock_source == external) { + s->usrp->set_clock_source("external"); + LOG_I(HW, "Setting clock source to external\n"); + } else if (openair0_cfg[0].clock_source == gpsdo) { + s->usrp->set_clock_source("gpsdo"); + LOG_I(HW, "Setting clock source to gpsdo\n"); + } else { + LOG_W(HW, "Clock source set neither in usrp_args nor on command line, using default!\n"); + } + } else { + if (openair0_cfg[0].clock_source != unset) { + LOG_W(HW, "Clock source set in both usrp_args and in clock_source, ingnoring the latter!\n"); + } + } + + if (args.find("time_source") == std::string::npos) { + if (openair0_cfg[0].time_source == internal) { + s->usrp->set_time_source("internal"); + LOG_I(HW, "Setting time source to internal\n"); + } else if (openair0_cfg[0].time_source == external) { + s->usrp->set_time_source("external"); + LOG_I(HW, "Setting time source to external\n"); + } else if (openair0_cfg[0].time_source == gpsdo) { + s->usrp->set_time_source("gpsdo"); + LOG_I(HW, "Setting time source to gpsdo\n"); + } else { + LOG_W(HW, "Time source set neither in usrp_args nor on command line, using default!\n"); + } + } else { + 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"); + } + } + + if (s->usrp->get_clock_source(0) == "gpsdo") { + s->use_gps = 1; + + if (sync_to_gps(device) == EXIT_SUCCESS) { + LOG_I(HW, "USRP synced with GPS!\n"); + } else { + LOG_I(HW, "USRP fails to sync with GPS. Exiting.\n"); + exit(EXIT_FAILURE); + } + } else { + if (s->usrp->get_time_source(0) == "external") { + usrp_sync_pps(s); + } else { + s->usrp->set_time_next_pps(uhd::time_spec_t(0.0)); + } + + if (s->usrp->get_clock_source(0) == "external") { + if (check_ref_locked(s, 0)) { + LOG_I(HW, "USRP locked to external reference!\n"); + } else { + LOG_I(HW, "Failed to lock to external reference. Exiting.\n"); + exit(EXIT_FAILURE); + } + } + } + // display USRP settings LOG_I(HW,"Actual master clock: %fMHz...\n",s->usrp->get_master_clock_rate()/1e6); LOG_I(HW,"Actual clock source %s...\n",s->usrp->get_clock_source(0).c_str()); From e375a13aa5f2dc651b18dd03a13965db36d8a870 Mon Sep 17 00:00:00 2001 From: Reem Bahsoun Date: Wed, 15 Oct 2025 20:08:49 +0200 Subject: [PATCH 957/964] CI infra: rename UE name to reflect PLMN --- ci-scripts/ci_infra.yaml | 2 +- .../xml_files/container_sa_f1_ho_b210_quectel.xml | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/ci-scripts/ci_infra.yaml b/ci-scripts/ci_infra.yaml index 85dbd10180..837f1edb82 100644 --- a/ci-scripts/ci_infra.yaml +++ b/ci-scripts/ci_infra.yaml @@ -85,7 +85,7 @@ oc-cn5g-20897: Undeploy: "! scripts/oc-cn5g-undeploy.sh /opt/oai-cn5g-fed-develop-2025-jan oaicicd-core-for-fhi72" LogCollect: "! scripts/oc-cn5g-logcollect.sh /opt/oai-cn5g-fed-develop-2025-jan oaicicd-core-for-fhi72 %%log_dir%%" -oc-cn5g-00102-ho: +oc-cn5g-00103-ho: Host: groot NetworkScript: echo "inet 172.21.6.111" RunIperf3Server: False diff --git a/ci-scripts/xml_files/container_sa_f1_ho_b210_quectel.xml b/ci-scripts/xml_files/container_sa_f1_ho_b210_quectel.xml index 814346b5f3..81e3745167 100644 --- a/ci-scripts/xml_files/container_sa_f1_ho_b210_quectel.xml +++ b/ci-scripts/xml_files/container_sa_f1_ho_b210_quectel.xml @@ -58,7 +58,7 @@ DeployCoreNetwork Initialize 5G Core - oc-cn5g-00102-ho + oc-cn5g-00103-ho @@ -113,7 +113,7 @@ Ping Ping: 100pings in 20sec raspix - oc-cn5g-00102-ho + oc-cn5g-00103-ho -c 100 -i 0.2 5 @@ -143,7 +143,7 @@ Ping Ping: 50pings in 10sec raspix - oc-cn5g-00102-ho + oc-cn5g-00103-ho -c 50 -i 0.2 5 @@ -166,7 +166,7 @@ Ping Ping: 50pings in 10sec raspix - oc-cn5g-00102-ho + oc-cn5g-00103-ho -c 50 -i 0.2 5 @@ -189,7 +189,7 @@ Ping Ping: 50pings in 10sec raspix - oc-cn5g-00102-ho + oc-cn5g-00103-ho -c 50 -i 0.2 5 @@ -244,7 +244,7 @@ UndeployCoreNetwork true Terminate 5G Core - oc-cn5g-00102-ho + oc-cn5g-00103-ho From 464762e52be9db5809edbee693a145e126d2d555 Mon Sep 17 00:00:00 2001 From: Reem Bahsoun Date: Wed, 15 Oct 2025 20:09:38 +0200 Subject: [PATCH 958/964] Fix: PCI on different SSB position --- .../conf_files/gnb-du.sa.band78.51prb.usrpb210.ho-pci1.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci-scripts/conf_files/gnb-du.sa.band78.51prb.usrpb210.ho-pci1.conf b/ci-scripts/conf_files/gnb-du.sa.band78.51prb.usrpb210.ho-pci1.conf index 3ba7e17b46..ae94203fd0 100644 --- a/ci-scripts/conf_files/gnb-du.sa.band78.51prb.usrpb210.ho-pci1.conf +++ b/ci-scripts/conf_files/gnb-du.sa.band78.51prb.usrpb210.ho-pci1.conf @@ -108,7 +108,7 @@ gNBs = hoppingId = 40; p0_nominal = -90; # ssb_PositionsInBurs_BitmapPR - ssb_PositionsInBurst_Bitmap = 1; + ssb_PositionsInBurst_Bitmap = 2; # ssb_periodicityServingCell # 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 From c9b704ed64ca4cf0bb1b0017fad66bef22b7d5a9 Mon Sep 17 00:00:00 2001 From: Reem Bahsoun Date: Wed, 15 Oct 2025 20:10:42 +0200 Subject: [PATCH 959/964] Rename services in docker-compose for clarity Harmonize with other files and use dashes. --- ci-scripts/xml_files/container_sa_f1_ho_b210_quectel.xml | 6 +++--- ci-scripts/yaml_files/5g_sa_f1_b210_ho/docker-compose.yml | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ci-scripts/xml_files/container_sa_f1_ho_b210_quectel.xml b/ci-scripts/xml_files/container_sa_f1_ho_b210_quectel.xml index 81e3745167..f4b3dfc344 100644 --- a/ci-scripts/xml_files/container_sa_f1_ho_b210_quectel.xml +++ b/ci-scripts/xml_files/container_sa_f1_ho_b210_quectel.xml @@ -92,14 +92,14 @@ Deploy gNB-CU in a container ci-scripts/yaml_files/5g_sa_f1_b210_ho groot - oai_cu + oai-cu Deploy_Object Deploy gNB-DU0 (TDD/Band77/20MHz/B210) in a container ci-scripts/yaml_files/5g_sa_f1_b210_ho - oai_du0 + oai-du0 groot @@ -123,7 +123,7 @@ Deploy gNB-DU1 (TDD/Band77/20MHz/B210) in a container ci-scripts/yaml_files/5g_sa_f1_b210_ho rocket - oai_du1 + oai-du1 diff --git a/ci-scripts/yaml_files/5g_sa_f1_b210_ho/docker-compose.yml b/ci-scripts/yaml_files/5g_sa_f1_b210_ho/docker-compose.yml index 24a3055701..c1c3db1607 100644 --- a/ci-scripts/yaml_files/5g_sa_f1_b210_ho/docker-compose.yml +++ b/ci-scripts/yaml_files/5g_sa_f1_b210_ho/docker-compose.yml @@ -1,5 +1,5 @@ services: - oai_cu: + oai-cu: image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop} container_name: oai-cu cap_drop: @@ -25,7 +25,7 @@ services: timeout: 5s retries: 5 - oai_du0: + oai-du0: image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop} container_name: oai-du0 cap_drop: @@ -57,7 +57,7 @@ services: timeout: 5s retries: 5 - oai_du1: + oai-du1: image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop} container_name: oai-du1 cap_drop: From d8e9a30fad442c51be332bc24dcd6dc1cbc29df7 Mon Sep 17 00:00:00 2001 From: Reem Bahsoun Date: Thu, 18 Sep 2025 11:40:21 +0200 Subject: [PATCH 960/964] Add attenuator commands to the XML file --- .../container_sa_f1_ho_b210_quectel.xml | 30 ++++++++++++------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/ci-scripts/xml_files/container_sa_f1_ho_b210_quectel.xml b/ci-scripts/xml_files/container_sa_f1_ho_b210_quectel.xml index f4b3dfc344..978691e534 100644 --- a/ci-scripts/xml_files/container_sa_f1_ho_b210_quectel.xml +++ b/ci-scripts/xml_files/container_sa_f1_ho_b210_quectel.xml @@ -30,6 +30,7 @@ 000003 000004 000005 + 000027 000006 000007 000008 @@ -87,6 +88,13 @@ rocket + + Custom_Command + Set attenuator to 0 for DU0 and 17 for DU1 + rocket + python3 %%workspace%%/ci-scripts/attenuatorctl.py -r 1,2 0 -r 3,4 17 -d 5 + + Deploy_Object Deploy gNB-CU in a container @@ -134,9 +142,9 @@ Custom_Command - Trigger Handover - groot - echo ci trigger_f1_ho | ncat 127.0.0.1 9090 + Attenuate DU0 by 15 and remove the attenuation on DU1 to trigger Handover + rocket + python3 %%workspace%%/ci-scripts/attenuatorctl.py -r 1,2 15 -r 3,4 0 -d 5 @@ -156,10 +164,10 @@ - Custom_Command - Trigger Handover - groot - echo ci trigger_f1_ho | ncat 127.0.0.1 9090 + Custom_Command + Attenuate DU1 by 17dB and remove attenuation on DU0 to trigger Handover + rocket + python3 %%workspace%%/ci-scripts/attenuatorctl.py -r 1,2 0 -r 3,4 17 -d 5 @@ -179,10 +187,10 @@ - Custom_Command - Trigger Handover - groot - echo ci trigger_f1_ho | ncat 127.0.0.1 9090 + Custom_Command + Attenuate DU0 by 15 and remove the attenuation on DU1 to trigger Handover + rocket + python3 %%workspace%%/ci-scripts/attenuatorctl.py -r 1,2 15 -r 3,4 0 -d 5 From e2075b57cacb3167e87b32e62c7c852c75cddf91 Mon Sep 17 00:00:00 2001 From: Reem Bahsoun Date: Wed, 15 Oct 2025 20:12:07 +0200 Subject: [PATCH 961/964] Clean up F1 HO config files Harmonize gNB names with other files, remove control ports (not used), put sl_ahead in right place. --- ci-scripts/conf_files/gnb-cu.sa.f1.ho.conf | 4 ++-- .../gnb-du.sa.band78.51prb.usrpb210.ho-pci0.conf | 10 ++++------ .../gnb-du.sa.band78.51prb.usrpb210.ho-pci1.conf | 10 ++++------ 3 files changed, 10 insertions(+), 14 deletions(-) diff --git a/ci-scripts/conf_files/gnb-cu.sa.f1.ho.conf b/ci-scripts/conf_files/gnb-cu.sa.f1.ho.conf index 8159eff571..f16a94b472 100644 --- a/ci-scripts/conf_files/gnb-cu.sa.f1.ho.conf +++ b/ci-scripts/conf_files/gnb-cu.sa.f1.ho.conf @@ -1,4 +1,4 @@ -Active_gNBs = ( "oai-cu"); +Active_gNBs = ( "CU-OAI"); # Asn1_verbosity, choice in: none, info, annoying Asn1_verbosity = "none"; @@ -10,7 +10,7 @@ gNBs = # cell_type = "CELL_MACRO_GNB"; - gNB_name = "oai-cu"; + gNB_name = "CU-OAI"; // Tracking area code, 0x0000 and 0xfffe are reserved values tracking_area_code = 1; diff --git a/ci-scripts/conf_files/gnb-du.sa.band78.51prb.usrpb210.ho-pci0.conf b/ci-scripts/conf_files/gnb-du.sa.band78.51prb.usrpb210.ho-pci0.conf index eb52e68566..df225e84c2 100644 --- a/ci-scripts/conf_files/gnb-du.sa.band78.51prb.usrpb210.ho-pci0.conf +++ b/ci-scripts/conf_files/gnb-du.sa.band78.51prb.usrpb210.ho-pci0.conf @@ -1,4 +1,4 @@ -Active_gNBs = ( "oai-du0"); +Active_gNBs = ( "DU0-OAI"); # Asn1_verbosity, choice in: none, info, annoying Asn1_verbosity = "none"; @@ -8,7 +8,7 @@ gNBs = ////////// Identification parameters: gNB_ID = 0xe88; gNB_DU_ID = 0xe00; - gNB_name = "oai-du0"; + gNB_name = "DU0-OAI"; // Tracking area code, 0x0000 and 0xfffe are reserved values tracking_area_code = 1 ; @@ -107,7 +107,7 @@ gNBs = pucchGroupHopping = 0; hoppingId = 40; p0_nominal = -90; -# ssb_PositionsInBurs_BitmapPR + ssb_PositionsInBurst_Bitmap = 1; # ssb_periodicityServingCell @@ -159,9 +159,7 @@ MACRLCs = ( tr_n_preference = "f1"; local_n_address = "172.21.19.98"; remote_n_address = "172.21.19.98"; - local_n_portc = 500; local_n_portd = 2154; - remote_n_portc = 501; remote_n_portd = 2153; pusch_TargetSNRx10 = 200; pucch_TargetSNRx10 = 230; @@ -176,7 +174,6 @@ L1s = ( prach_dtx_threshold = 100; pucch0_dtx_threshold = 10; max_ldpc_iterations = 20; - sl_ahead = 3; ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 } ); @@ -188,6 +185,7 @@ RUs = ( nb_rx = 1 att_tx = 0; att_rx = 0; + sl_ahead = 3; bands = [77]; max_pdschReferenceSignalPower = -27; max_rxgain = 114; diff --git a/ci-scripts/conf_files/gnb-du.sa.band78.51prb.usrpb210.ho-pci1.conf b/ci-scripts/conf_files/gnb-du.sa.band78.51prb.usrpb210.ho-pci1.conf index ae94203fd0..14ec8b1e82 100644 --- a/ci-scripts/conf_files/gnb-du.sa.band78.51prb.usrpb210.ho-pci1.conf +++ b/ci-scripts/conf_files/gnb-du.sa.band78.51prb.usrpb210.ho-pci1.conf @@ -1,4 +1,4 @@ -Active_gNBs = ( "oai-du1"); +Active_gNBs = ( "DU1-OAI"); # Asn1_verbosity, choice in: none, info, annoying Asn1_verbosity = "none"; @@ -8,7 +8,7 @@ gNBs = ////////// Identification parameters: gNB_ID = 0xe88; gNB_DU_ID = 0xe01; - gNB_name = "oai-du1"; + gNB_name = "DU1-OAI"; // Tracking area code, 0x0000 and 0xfffe are reserved values tracking_area_code = 1 ; @@ -107,7 +107,7 @@ gNBs = pucchGroupHopping = 0; hoppingId = 40; p0_nominal = -90; -# ssb_PositionsInBurs_BitmapPR + ssb_PositionsInBurst_Bitmap = 2; # ssb_periodicityServingCell @@ -159,9 +159,7 @@ MACRLCs = ( tr_n_preference = "f1"; local_n_address = "172.21.19.99"; remote_n_address = "172.21.19.98"; - local_n_portc = 500; local_n_portd = 2154; - remote_n_portc = 501; remote_n_portd = 2153; pusch_TargetSNRx10 = 200; pucch_TargetSNRx10 = 230; @@ -176,7 +174,6 @@ L1s = ( prach_dtx_threshold = 100; pucch0_dtx_threshold = 10; max_ldpc_iterations = 20; - sl_ahead = 3; ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 } ); @@ -188,6 +185,7 @@ RUs = ( nb_rx = 1 att_tx = 0; att_rx = 0; + sl_ahead = 3; bands = [77]; max_pdschReferenceSignalPower = -27; max_rxgain = 114; From 9803fb29f66855fee25c0f226a53449bee6ce755 Mon Sep 17 00:00:00 2001 From: Reem Bahsoun Date: Wed, 15 Oct 2025 20:11:16 +0200 Subject: [PATCH 962/964] Reorganize XML steps for F1 HO Number linearly for easier navigation in HTML reports, and start DU1 before connecting the UE. Reset attenuation on all channels to 0. --- .../container_sa_f1_ho_b210_quectel.xml | 69 +++++++++++-------- 1 file changed, 39 insertions(+), 30 deletions(-) diff --git a/ci-scripts/xml_files/container_sa_f1_ho_b210_quectel.xml b/ci-scripts/xml_files/container_sa_f1_ho_b210_quectel.xml index 978691e534..77b2312409 100644 --- a/ci-scripts/xml_files/container_sa_f1_ho_b210_quectel.xml +++ b/ci-scripts/xml_files/container_sa_f1_ho_b210_quectel.xml @@ -30,7 +30,6 @@ 000003 000004 000005 - 000027 000006 000007 000008 @@ -52,6 +51,8 @@ 000024 000025 000026 + 000027 + 000028 @@ -88,14 +89,14 @@ rocket - + Custom_Command Set attenuator to 0 for DU0 and 17 for DU1 rocket python3 %%workspace%%/ci-scripts/attenuatorctl.py -r 1,2 0 -r 3,4 17 -d 5 - + Deploy_Object Deploy gNB-CU in a container ci-scripts/yaml_files/5g_sa_f1_b210_ho @@ -103,7 +104,7 @@ oai-cu - + Deploy_Object Deploy gNB-DU0 (TDD/Band77/20MHz/B210) in a container ci-scripts/yaml_files/5g_sa_f1_b210_ho @@ -111,13 +112,21 @@ groot - + + Deploy_Object + Deploy gNB-DU1 (TDD/Band77/20MHz/B210) in a container + ci-scripts/yaml_files/5g_sa_f1_b210_ho + rocket + oai-du1 + + + Attach_UE Attach Quectel raspix - + Ping Ping: 100pings in 20sec raspix @@ -126,28 +135,20 @@ 5 - - Deploy_Object - Deploy gNB-DU1 (TDD/Band77/20MHz/B210) in a container - ci-scripts/yaml_files/5g_sa_f1_b210_ho - rocket - oai-du1 - - - + IdleSleep Sleep 5 - + Custom_Command Attenuate DU0 by 15 and remove the attenuation on DU1 to trigger Handover rocket python3 %%workspace%%/ci-scripts/attenuatorctl.py -r 1,2 15 -r 3,4 0 -d 5 - + Ping Ping: 50pings in 10sec raspix @@ -156,21 +157,21 @@ 5 - + Custom_Command UE connected to DU1? groot echo ci fetch_du_by_ue_id 1 | ncat 127.0.0.1 9090 | grep "3585" - + Custom_Command Attenuate DU1 by 17dB and remove attenuation on DU0 to trigger Handover rocket python3 %%workspace%%/ci-scripts/attenuatorctl.py -r 1,2 0 -r 3,4 17 -d 5 - + Ping Ping: 50pings in 10sec raspix @@ -179,21 +180,21 @@ 5 - + Custom_Command UE connected to DU0? groot echo ci fetch_du_by_ue_id 1 | ncat 127.0.0.1 9090 | grep "3584" - + Custom_Command Attenuate DU0 by 15 and remove the attenuation on DU1 to trigger Handover rocket python3 %%workspace%%/ci-scripts/attenuatorctl.py -r 1,2 15 -r 3,4 0 -d 5 - + Ping Ping: 50pings in 10sec raspix @@ -202,21 +203,21 @@ 5 - + Custom_Command UE connected to DU1? groot echo ci fetch_du_by_ue_id 1 | ncat 127.0.0.1 9090 | grep "3585" - + Detach_UE true Detach Quectel raspix - + Undeploy_Object true Undeploy CU-DU0 @@ -224,7 +225,7 @@ ci-scripts/yaml_files/5g_sa_f1_b210_ho - + Undeploy_Object true Undeploy DU1 @@ -232,7 +233,15 @@ ci-scripts/yaml_files/5g_sa_f1_b210_ho - + + Custom_Command + Reset all channels on the attenuator to 0 + rocket + python3 %%workspace%%/ci-scripts/attenuatorctl.py -s 1-4 0 + true + + + Clean_Test_Server_Images true Clean Test Images on Test Server @@ -240,7 +249,7 @@ oai-gnb - + Clean_Test_Server_Images true Clean Test Images on Test Server @@ -248,7 +257,7 @@ oai-gnb - + UndeployCoreNetwork true Terminate 5G Core From 5f162c436ef23b6448dda1746229144dcd0231cc Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 16 Oct 2025 11:36:04 +0200 Subject: [PATCH 963/964] Add documentation for CI Handover Setup --- doc/TESTBenches.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/doc/TESTBenches.md b/doc/TESTBenches.md index e7564b8678..8674103a1a 100644 --- a/doc/TESTBenches.md +++ b/doc/TESTBenches.md @@ -24,6 +24,9 @@ | gracehopper1-oai | Gracehopper1 | gNB (n78, PNF/Nvidia CUBB + VNF) | Foxconn RU, _Nvidia Aerial integration_ | | gracehopper3-oai | Gracehopper3 | build | -- | | acamas | Acamas | 4G and 5G rfsimulator| -- | +| groot | Groot | gNB (n77) | B210 (30AD30F) | +| rocket | Rocket | gNB (n77) | B210 (31F8010) | +| raspix | Raspix | COTS UE | Quectel RM520N | Note: The available resources, and their current usage, is indicated here: - [Lockable resources of jenkins-oai](https://jenkins-oai.eurecom.fr/lockable-resources/): @@ -226,6 +229,11 @@ information on how the images are built. - cacofonix + FHI72 + Metanoia (gNB), up2 (Quectel RM520N UE), OAI CN5G - OpenShift cluster for CN deployment - FHI 7.2 testing with 100 MHz bandwidth, 2 layers in DL +- [RAN-SA-Handover-CN5G](https://jenkins-oai.eurecom.fr/job/RAN-SA-Handover-CN5G/) + ~5G-NR + - groot (CU+DU0) + B210, rocket (DU1) + B210, raspix (Quectel RM520N UE), OAI CN5G + - OpenShift cluster for CN deployment + - Attenuator (mini circuits RC4DAT-6G-60) - controlled from rocket ### RAN-CI-NSA-Trigger From 9620fd1a6aeb6905d2b76502c6c0f81ba1f484d4 Mon Sep 17 00:00:00 2001 From: Reem Bahsoun Date: Thu, 16 Oct 2025 12:06:15 +0200 Subject: [PATCH 964/964] Update the nvIPC library to the one packaged with the new cuBB image. --- ci-scripts/cls_containerize.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index 3fe2729c77..c97bb8d4d1 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -395,13 +395,13 @@ class Containerize(): elif image != 'ran-build': cmd.run(f'sed -i -e "s#ran-build:latest#ran-build:{imageTag}#" docker/Dockerfile.{pattern}{self.dockerfileprefix}') if image == 'oai-gnb-aerial': - cmd.run('cp -f /opt/nvidia-ipc/nvipc_src.2025.08.27.tar.gz .') + cmd.run('cp -f /opt/nvidia-ipc/nvipc_src.2025.10.09.tar.gz .') logfile = f'{lSourcePath}/cmake_targets/log/{name}.docker.log' ret = cmd.run(f'{self.cli} build {self.cliBuildOptions} --target {image} --tag {name}:{imageTag} --file docker/Dockerfile.{pattern}{self.dockerfileprefix} {option} . > {logfile} 2>&1', timeout=1200) t = (name, archiveArtifact(cmd, ctx, logfile)) log_files.append(t) if image == 'oai-gnb-aerial': - cmd.run('rm -f nvipc_src.2025.08.27.tar.gz') + cmd.run('rm -f nvipc_src.2025.10.09.tar.gz') # check the status of the build ret = cmd.run(f"{self.cli} image inspect --format=\'Size = {{{{.Size}}}} bytes\' {name}:{imageTag}") if ret.returncode != 0: